email bluesky fediverse feed

leaflet Leaflet is "a modern, lightweight open-source JavaScript library for mobile-friendly interactive maps" and here I show how my Stacey method of linking articles to a map works with Leaflet (refer to the previous posts for the Stacey end of things).

Implementation consists of a Leaflet Template and a geo Partial file, with a link in the Article/Post code - my link looks like:

<a href="/leaflet/?@psn,14" title="view location on Leaflet OpenStreetMap"><img src="/images/opengeo.png" alt="" /></a>

Template - leaflet.html

Remember to delete [remove] from the code - it's there to stop Stacey doing it's stuff even when written as code.

<!DOCTYPE html>
    <meta charset="utf-8" />
    <meta name="keywords" content="map, cloudmade, leaflet, stamen" />
    <meta name="viewport" content="width=device-width" />
    <title>Leaflet Map</title>
    <link rel="alternate" type="application/atom+xml" href="@root_path/atom.xml">
    <link rel="stylesheet" href="/mapleaflet.css" />
    <!--[if lte IE 8]><link rel="stylesheet" href="/" /><![endif]-->
    <script src=""></script>
    <script type="text/javascript" src=""></script>

<div id="map"></div>

    var cloudmadeUrl = 'http://{s}{styleId}/256/{z}/{x}/{y}.png',
        cloudmadeAttribution = 'Map data &copy; <a href="">OpenStreetMap</a> contributors, <a href="">CC-BY-SA</a>, Imagery &copy; <a href="">CloudMade</a>',
        cloudmadeOptions = {maxZoom: 18, attribution: cloudmadeAttribution};

    var cloudmade = new L.TileLayer(cloudmadeUrl, cloudmadeOptions, {styleId: 1}),
        fineline = new L.TileLayer(cloudmadeUrl, cloudmadeOptions, {styleId: 2});

    if ( {
        var qs =;
        var url = qs.split(',',3);
        var lat = parseFloat(url[0]);
        var lng = parseFloat(url[1]);
        var zmn = parseFloat(url[2]);
    else {
        var lat = 42.94033923363181;
        var lng = -2.8125;
        var zmn = 4;

    var map = new L.Map('map', {
        center: new L.LatLng(lat,lng),
        zoom: zmn,
        layers: [cloudmade]

    var baseMaps = {
            "Cloudmade": cloudmade,
            "Fine Line": fineline,
            "Watercolour": new L.StamenTileLayer("watercolor"),
            "Terrain USA": new L.StamenTileLayer("terrain")

    layersControl = new L.Control.Layers(baseMaps);


    var dotIcon = L.Icon.extend({
                iconUrl: '/images/blue.png',
                shadowUrl: '/images/shadow.png',
                iconSize: new L.Point(12, 20),
                shadowSize: new L.Point(22, 20),
                iconAnchor: new L.Point(0, 0),
                popupAnchor: new L.Point(7, 0)

    var blueIcon = new dotIcon(),
        greenIcon = new dotIcon('/images/green.png'),
        redIcon = new dotIcon('/images/red.png'),
        yellowIcon = new dotIcon('/images/yellow.png');


            map.on('click', onMapClick);

            function onMapClick(e) {
                var latlngStr = '(' + + ', ' + e.latlng.lng.toFixed(3) + ')';
                document.getElementById('message').innerHTML = e.latlng;


    <a href="/"><img src="/images/logos.png" alt="home" title="home" style="border:0; position: absolute; top: 0; left: 45px;" /></a>
    <div id="message" style="position:absolute; top: 32px; left: 50px;">Click = point</div>


Partial - geoleaf.html

foreach $root do<br />
if $children do<br />
foreach $children do<br />
if &#64;psn do<br />
var markerLocation = new L.LatLng(&#64;psn);<br />
var marker&#64;id = new L.Marker(markerLocation, {<br />
title: "&#64;title",<br />
icon: blueIcon<br />
});<br />
map.addLayer(marker&#64;id);<br />
marker&#64;id.bindPopup("&lt;h2&gt;&lt;a href='../&#64;url'&gt;&#64;title&lt;/a&gt;&lt;br /&gt;&lt;img src='&#64;th' style='width:95px;height:95px' /&gt;&lt;/h2&gt;&lt;h3&gt;&lt;a href='/leaflet/?&#64;psn,17'&gt;zoom&lt;/a&gt;&lt;/h3&gt;");<br />
endif<br />
endforeach<br />
endif<br />

There is a zoom function in the popup window, but you can pass whatever you like through.