|
<script src="http://maps.google.com/?file=api&key=[YOUR_KEY_HERE]&v=2.x" type="text/javascript"></script> |
Google provides a handy function to determine if a web browser is Google Maps compatible or not. This is handy to use when wrapping our code to degrade gracefully in the event that it won't work for a particular browser:
<script type="text/javascript"> //<![CDATA[<br> if (GBrowserIsCompatible()) { <BR> // Place all the Google Maps code in here } else { alert("Sorry, your web browser is not compatible with Google Maps"); } //]]> </script> <noscript> <p>Sorry, you do not have Javascript enabled. You will not be able to enjoy the travelogue map. </noscript> |
OK, now let's write some code. To instantiate a Google Map, we call
new GMap2: // "mapDiv" specifies the ID of the DIV tag that will contain the map var map = new GMap2(document.getElementById("mapDiv")); We can add some controls: map.addControl(new GLargeMapControl());map.addControl(new GOverviewMapControl()); map.addControl(new GMapTypeControl()); Hmm, this is is getting large enough to be encapsulated in a function. I'll let it take a parameter that specifies the : // // function setUp // Returns: the map // function setUp() { var map = new GMap2(document.getElementById("mapDiv")); map.addControl(new GLargeMapControl()); map.addControl(new GOverviewMapControl()); map.addControl(new GMapTypeControl()); return map; } |
That's better. Now what about putting some markers on the map? To do that, we need to define another function createMarker that creates a marker:
// function createMarker // point: the location of the marker // icon: the icon to use to show the marker // html: the markup for the popup info window (optional) // Returns: the marker // function createMarker(point, html) { var marker = new GMarker(point); // If there is something to show in the popup... if (html != null) { GEvent.addListener(marker, "click", &nbs p; function() { &nbs p; marker.openInfoWindowHtml(html); &nbs p; }); } return marker; } |
Now we can create some markers. Oh wait, no we can't. We don't have any data. Normally in a List Display Template, we render the data with presentation markup; however, since this time we will be using the Google Maps API for the presentation, we just need to render the data in a way that we can easily parse it in our code. We will use the built in browser DOM functions to accomplish that, but first, let's store our data in a structured way:
<div id="mapData" style="display:none"> <t:list> <div> <span>${title}</span> <span>${url}</span> <span>${firstPublicationDate}</span> <span>${location}</span> <span>${latitude}</span> <span>${longitude}</span> <span>${body}</span> </div> </t:list> </div> |
Notice the style we applied to the outer DIV tag. This causes the browser to hide the DIV so the user doesn't see our structured data in the rendered web page.
Now we have some data. We need a function to read the data, convert it into markers and add it to the map:
// Define some "constants" var TITLE = 0; var URL = TITLE + 1; var DATE = URL + 1; var LOCATION = DATE + 1; var LATITUDE = LOCATION + 1; var LONGITUDE = LATITUDE + 1; var BODY = LONGITUDE + 1; // Define a class to represent a Travelogue function Travelogue(data) { var fields = data.getElementsByTagName("SPAN"); this.title = fields[TITLE].innerHTML; this.url = fields[URL].innerHTML; this.pubDate = fields[DATE].innerHTML; this.location = fields[LOCATION].innerHTML; this.latitude = fields[LATITUDE].innerHTML; this.longitude = fields[LONGITUDE].innerHTML; this.body = fields[BODY].innerHTML; this.getTitle = function () { return this.title; } this.getURL = function () { return this.url; } this.getPubDate = function () { return this.pubDate; } this.getLocation = function () { return this.location; } this.getLatitude = function () { return this.latitude; } this.getLongitude = function () { return this.longitude; } this.getBody = function () { return this.body; } } function loadData(map) { // Find the DIV containing the data var dataDiv = document.getElementById("mapData"); if (dataDiv == null) { return; } // Get a list of all of the inner DIVs each of which contains one // data record var records = dataDiv.getElementsByTagName("DIV"); if (records.length == 0) { return; } // Iterate over each record for (var r = 0; r < records.length; r++) { // Get the fields for this record var travelogue = new Travelogue(records[r]); // we need to format some HTML for the popup var html = getInfoWindowHTML(travelogue); // Create a Google Maps point var point = new GLatLng(travelogue.getLatitude(), travelogue.getLongitude()); // create the marker var marker = createMarker(point, html); // add the new marker to the map map.addOverlay(marker); } } |
Now we are getting there! We need to get our code to run when the page is loaded. So first we'll need to update the setUp function to load the data. Then we need to get it to run when the page loads We can accomplish that (in a browser-safe manner) like so:
function setUp() { var map = new GMap2(document.getElementById('mapDiv')); map.addControl(new GLargeMapControl()); map.addControl(new GOverviewMapControl()); map.addControl(new GMapTypeControl()); loadData(map); return map; } if (window.attachEvent) { window.attachEvent("onload", setUp); window.attachEvent("onunload", GUnload); } else { window.addEventListener('load',setUp,false); window.addEventL istener('unload',GUnload,false); } |
Note the additional function registered to the unload event handlers GUnload. This is a Google Maps API call to clean up after you are done using the maps. It releases all the memory allocated to the map display code. Don't forget to include this.
Now we have a dynamic map displaying all of Marcel's travelogue posts in all of their geospatial beauty. We could call it a day and be satisfied with our accomplishments or we could make it even better. Wouldn't it be nice to use a marker icon that better reflected our website's personality? Of course it would be.
Google Map icons consist of an image and a shadow. The shadow is used to create the 3-d effect.
You can use your graphic skills to create your own images. Once you've created them and uploaded them to your website, you can tell Google to use your custom icons:
// Create a new Icon var customIcon = new GIcon(); customIcon.image = 'http://www.oursite.org/assets/maps/icons/image.png'; customIcon.shadow = 'http://www.oursite.org/assets/maps/icons/shadow.png'; // Google needs to be told the image dimensions customIcon.iconSize = new GSize(25,41); customIcon.shadowSize = new GSize(55,41); // This defines the anchor point of the info window w.r.t. the icon customIcon.infoWindowAnchor = new GSize(55,41); // create the marker using our custom marker icon var marker = createMarker(point, customIcon, html); |
If you wanted to use sequenced anchors (like this), you could create an entire set of custom icons (e.g. custom1.png, custom2.png) and then create a new GIcon for each travelogue.
![]() |
![]() |