david hall icon

more Stacey geoblogging

A revision and slightly expanded explanation of my previous method of linking articles to a map, and back.

As I have done away with the Archives, my Stacey "content" folder now contains:

folder structure

and below is the "templates" folder showing the "navigation" Partials which are now reduced to 3:

partials structure

Therefore, the index page lists the 3 category links; other, elsewhere and britain, by calling the siblings.html partial, using :siblings. Having no archives section means there is only the need for one geotagged.html partial file for the Map to collect geo-information from the articles.

Partials

categories.html

On this site, the categories.html partial that forms the thumbnail pages, is a simplification of the standard Stacey category-lists.html partial and is called from the category.html file using :categories:

if $siblings do
<h2>@title</h2>
<div id="pix">
foreach $children do
<a href="@url"><img src="@th" alt="thumb" /></a>
endforeach
</div>
endif

geotagged.html

the geotagged.html partial, which creates a hyperlink back to the article and also a zoom button in the "info window", is called using :geotagged in the map code:

foreach $siblings do
if $children do
foreach $children do
if @psn do
var marker@id = new google.maps.Marker({
position: new google.maps.LatLng(@psn),
map: map,
title: "@title"
});
var infowindow@id = new google.maps.InfoWindow({
content: ('<h2><a href="../@url">@title</a></h2><h3><a href="/archives/map/?@psn,18">Zoom</a></h3>')
});
google.maps.event.addListener(marker@id, 'click', function() {
infowindow@id.open(map,marker@id);
});
endif
endforeach
endif
endforeach

siblings.html

and the siblings.html partial that lists the categories on the index page, is in effect a replacement for the original Stacey navigation.html partial:

if $siblings do
<ol>
foreach $children do
<li>
<a href="@year">@year</a>
</li>
endforeach
</ol>
endif

Styling is, of course, up to you!

Map Code

The complete map.html code, which includes a geocode search is:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="your name" />
    <meta name="copyright" content="Copyright (c) your name" />
    <meta name="generator" content="Stacey" />
    <meta name="viewport" content="width=device-width" />
    <title>Map</title>
    <link rel="alternate" type="application/atom+xml" title="feed title" href="http://your-site.com/feed/atom.xml" />

<style type="text/css">
    html, body, #map_canvas {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        font-family: Helvetica, Tahoma sans-serif;
        font-size: 1em;
        color: #003300;
    }
    h2 {
        font-size:1.3em;
        text-shadow: 1px 2px 5px rgba(0, 0, 0, 0.5);
        text-align: center;
    }
    h3 {
        font-size:1em;
        text-align: center;
    }
    a {
        text-decoration:none;
        color: #485c70;
    }
    a:hover, a:active {
        color:#4b8462;
    }
</style>

<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>

<script type="text/JavaScript">

    if (location.search.substring(1)) {
        var qs = location.search.substring(1);
        var url = qs.split(',',3);
        var lat = parseFloat(url[0]);
        var lng = parseFloat(url[1]);
        var zmn = parseFloat(url[2]);
        var vars = url.vars;
    }
    else {
        var lat = 42.94033923363181;
        var lng = -2.8125;
        var zmn = 3;
        var map;
    }
    var url = getAttribute("url");

    var geocoder;

    function initialize() {
    geocoder = new google.maps.Geocoder();
        map = new google.maps.Map(document.getElementById("map_canvas"), {
        center: new google.maps.LatLng(lat,lng),
        zoom: zmn,
        draggableCursor: "crosshair",
            mapTypeId: google.maps.MapTypeId.SATELLITE
        });

        google.maps.event.addListener(map, 'click', function onClickCallback(event){
            document.getElementById("message").innerHTML = event.latLng.toString();
            geocode({ 'latLng': event.latLng });
        });

        : geotagged
    }

    function codeAddress() {
    var address = document.getElementById("address").value;
    geocoder.geocode( { 'address': address}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
            map.setCenter(results[0].geometry.location);
            var image = new google.maps.MarkerImage('http://your-site.com/images/marker.png',
                new google.maps.Size(12, 20),
                new google.maps.Point(0,0),
                new google.maps.Point(7, 21));
            var shadow = new google.maps.MarkerImage('http://your-site.com/images/marker-shadow.png',
                new google.maps.Size(22, 20),
                new google.maps.Point(0, 0),
                new google.maps.Point(6, 20));
            var marker = new google.maps.Marker({
                map: map,
            shadow: shadow,
                icon: image,
                position: results[0].geometry.location,
            title: address
            });
        } else {
            alert("Geocode was not successful for the following reason: " + status);
        }
    });
    }
    </script>
  </head>

    <body onload="initialize()">
        <div id="map_canvas"></div>
        <div id="message" style="position:absolute; bottom: 60px; left: 3px;" >Click coordinates</div>
        <div id="geocode" style="position:absolute; bottom: 30px; left: 3px;" >
            <input id="address" style="color:green" type="textbox" value="" />
        <input type="button" style="color:green" value="Search" onclick="codeAddress()" />
        </div>
    </body>
</html>

Note

  • :geotagged is shown in the code with a space between the colon and text, remove the space in your code.
  • addresses may be parsed from the url, thus taking coordinates from any link, say a random location you want to mention, in the form of x,y,zoom i.e. http://www.yoursite.com/map/?54.59997042714844,-1.730046272277832,18
  • a geocode search is included on the map
  • mouse click coordinates are displayed in the "message" div, via addListener

Project file

In the templates folder, the project.html file uses the following to pick-up the position coordinates. Mine is in the date line of the article. You can of course vary the zoom level (set here to 12) or pass it using another variable in the YAML header (for the above map code it would be @zmn) and add the variable to the geotagged.html partial:

if @psn do <a href="/archives/map/?@psn,12" title="view location on Map"><img src="/images/geotag.png" alt="" /></a> endif

Article file

To provide the map coordinates, use a new line in the YAML header for that particular article, I use:

psn:

Icons

Here are some icons:   

And finally, if you use iCab or Firefox with the Minimap extension, you may use this snippet

if @psn do <meta name="ICBM" content="@psn" /> endif

in the head of you article or project page to show the browser the ICBM geodata.

2011-07-17