Google Maps Without JavaScript
May 26th, 2008
We recently did a small Google Maps application for ERGO insurance. It consisted of submitting all their offices to Google Maps. KML export of office data was used to create map at ERGO autoabi campaign site. First version used all JavaScript approach to create the sidebar and map on the page. I was not happy with it. Map page was empty for browsers with JavaScript disabled. Page also took too long to render. Two problems I could not ignore.
Second version was mixture of PHP, JavaScript and new static maps API. Map now works without JavaScript. It renders much faster too. Check the working demo to see yourself.
Importing KML
Google offers GGeoXML library for KML parsing. That I ditched in the beginning. It was impossible to create sidebar navigation with it. First I ended up using EGeoXML. It got the job done but as I said earlier was too slow.
To speed things up I parsed KML files and outputted sidebar HTML with PHP. Simplified HTML and PHP below. Do not mind about # hrefs. They will be replaced with something meaningfull later.
<h3><a id="cityname" class="city" href="#">ERGO cityname</a></h3>
<ul>
<li><a class="office" href="#" id="marker-1">Office 1</a></li>
<li><a class="office" href="#" id="marker-2">Office 2</a></li>
<li><a class="office" href="#" id="marker-3">Office 3</a></li>
</ul>
$kml = array("tartu.kml", "parnu.kml");
/* Used in id's so we can later bind click to correct marker. */
$counter = 0;
foreach($kml as $file) {
$city = str_replace('.kml', '', $file);
$xml = $xml = simplexml_load_file($file, null, LIBXML_NOCDATA);
/* Print cityname as headline. */
printf('<h3><a id="%s" class="city" href="#">%s</a></h3>',
$city, $xml->Document->name);
foreach ($xml->Document->Placemark as $placemark) {
$coordinates = $placemark->Point->coordinates;
list($longtitude, $latitude, $discard) = explode(',', $coordinates, 3);
/* Save parsed KML as simpler array. We output this as JSON later. */
/* Save also id so we can match clicked link ad marker. */
$markers[] = array("latitude" => $latitude,
"longtitude" => $longtitude,
"name" => (string)$placemark->name,
"description" => (string)$placemark->description,
"id" => "marker-$counter");
/* Print officename as link to single office. */
printf('<li><a class="office" href="#" id="marker-%d">%s</a></li>',
$latitude, $longtitude, $counter, $placemark->name);
print "\n";
$counter++;
}
print "</ul>\n";
}
Putting Markers on Map With JavaScript
I gave the PHP parsed KML array back to JavaScript using JSON. Array is then looped passing data to addMarker() method. This method creates new marker, puts it on map and binds event to open new infowindow when marker is clicked. Simplified code below:
$(function() {
/* Output parsed KML files as JSON */
var markers = <?php print json_encode($markers) ?>;
var marker_hash = {};
if (GBrowserIsCompatible()) {
/* Init and center at Tartu. */
var map = new GMap2(document.getElementById("map"));
map.addControl(new GSmallMapControl());
map.setCenter(new GLatLng(58.38133351447725, 24.516592025756836), 12);
for (var i=0; i<markers.length; i++) {
var current = markers[i];
var marker = addMarker(current);
marker_hash[current.id] = {marker : marker};
}
}
function addMarker(current) {
var marker = new GMarker(new GLatLng(current.latitude,
current.longtitude));
map.addOverlay(marker);
GEvent.addListener(marker, 'click', function() {
var html = '<h3>' + current.name + '</h3><p>' +
current.description + '</p>';
marker.openInfoWindowHtml(html);
});
return marker;
}
});
Make It Work With JavaScript Challenged Browsers
Inside the map <div> there is an <img> tag which points to Google Static maps api. You can pass needed parameters in URL and Google generates map as static image. For example:
http://maps.google.com/staticmap?&zoom=12&size=512x300
¢er=58.378700,26.731110&key=GOOGLE_API_KEY
Generates the following map:
What we do here is really simple. In sidebar links we pass needed parameters in querystring. PHP then writes these parameters into <img> tag pointing to static maps api. Instead of center we pass markers parameter. It contains coordinates to one or more markers. Map api then centers map automatically. This comes especially handy when there is multiple markers.
For example link:
<a href="?markers=58.384933,24.499811,red|58.384731,24.507816,red|">
becomes the following img tag:
<img src="http://maps.google.com/staticmap?size=512x300
&markers=58.384933,24.499811,red|58.384731,24.507816,red|
&key=GOOGLE_API_KEY" />
which looks like this:
What we need to do is to update the code which generates sidebar html. I cut out lots of code for sake of clarity here. Important line is one with printf().
foreach($kml as $file) {
...
foreach ($xml->Document->Placemark as $placemark) {
...
printf('<li><a class="office" href="?zoom=14&markers=%s,%s,red"
id="marker-%d">%s</a></li>', $latitude, $longtitude, $counter,
$placemark->name);
...
}
...
}
Each link now shows you map with single marker centered on map. Creating link for each city is requires one extra step. Each city contains multiple markers. Before creating the sidebar we loop through KML once to to build a querystring for marker parameter.
/* Prebuild querystring for all markers in a city. This is needed */
/* to make a link which contains all markers in query string. */
foreach($kml as $file) {
$city = str_replace('.kml', '', $file);
$temp = 'markers=';
$xml = $xml = simplexml_load_file($file, null, LIBXML_NOCDATA);
foreach ($xml->Document->Placemark as $placemark) {
$coordinates = $placemark->Point->coordinates;
list($longtitude, $latitude, $discard) = explode(',', $coordinates, 3);
$temp .= sprintf('%s,%s,red|', $latitude, $longtitude);
}
$markers_string[$city] = $temp;
}
We also need to make small change code building the sidebar.
foreach($kml as $file) {
...
/* Use prebuild querystring in city links. */
printf('<h3><a id="%s" class="city" href="?%s">%s</a></h3>',
$city, $markers_string[$city], $xml->Document->name);
...
}
Now we have working map with sidebar. Biggest difference is missing infowindows (bubbles). They would be perfectly doable but I left them out for a reason now.
You can find source code to the working demo from svn. There was couple of cosmetic things I did not describe here so check the source. ERGO Autoabi minisite still contains both original and improved versions of the map.
Static maps api is really great. I have only one complaint. Maximum size of 512×512 is a bit too limiting to my taste.
UPDATE: Google recently increased the maximum size of static map to 640×640. Thank you!
Related entries: Google Maps Without JavaScript Part 2, Clickable Markers With Google Static Maps, Infowindows With Google Static Maps.

June 5th, 2008 at 12:30 PM
Uh, oh. It seems I accidentally deleted all comments when I was supposed to delete only spam comments. Sorry. If you are missing an answer please post a comment again.
July 13th, 2008 at 09:43 PM
Nice tutorial. thanks!
September 13th, 2008 at 07:21 PM
Mika, thank you for your very useful site in relation to google static maps. We’ve been using your code on our own site.
One thing is missing though. You show us how to build a map with a set of markers from a KML file and you show us how to build a control for a map with markers, however you don’t show us how to calculate the required INITIAL ZOOM level to show the full set of markers in a KML file. You’re choosing to set the initial zoom to “14” even if some markers are outside the box OR you are choosing to let Google Static Maps decide the initial zoom level to bring all markers into the box. However the problem with this method is that we don’t know what initial zoom level Google is using for to make + and – zoom functions work.
Do you know how we can calculate the necessary zoom level and center to show all markers in a static map?
Regards,
Ronan
September 14th, 2008 at 11:21 PM
Ronan: One way to do it is to calculate the bounds of given map with given zoom. Then go through each marker to see if they are inside bounds. If not, zoom out one and go through each marker again. Do this in loop until all markers are inside bounds.
I haven’t needed this myself yet. It is great idea for next tutorial. Maybe next week already :)
September 19th, 2008 at 06:23 PM
Hi,
Where can I download this from svn ?
Could you please provide me svn link to download source.
Thanks, Venkata
September 19th, 2008 at 06:58 PM
http://svn.appelsiini.net/svn/javascript/trunk/google_maps_nojs/
November 1st, 2008 at 01:30 AM
in case you have address in my data base, how can i aplicate this method. thank you for your help Mustafa
February 10th, 2009 at 01:19 PM
This is very nice work. We’ve currently got a map page we want to make a bit more javascript friendly
http://www.aber.ac.uk/en/maps/penglais/
One thing we’re doing in the current version though is adding a custom overlay to show our road system and buildings on the map.
Anyone know if adding this overlay would be possible with the static API?
Thanks!