My next major task for the AusStage project is the development of a browse based interface for venue and event data. The basic idea is that on a single map all of the venues that we have coordinate information for would be listed. This allows a user the freedom to explore the map and visualise venue and event data in a new way.
Using the test database there are over 900 venues with coordinate information and this means that I needed to find some way to cluster markers to help speed up the performance of the map. Also a map with over 900 placemarks on it would be imposing to first time users. After some searching of the Interweb I decided on the use of the MarkerClusterer JavaScript library which is part of the GMaps Utility Library.
To help speed up the initial generation of the map I also decided to separate the venue information from the event information. This means that the InfoWindows, the little popups that are displayed when a user clicks on a placemark on the map, need to be generated dynamically using an AJAX based technique.
I also wanted to use the MapIconMaker library to style the placemarks to keep thelook and feel of the maps on the site consistent.
The code needed to achieve this is divided into two sections.
The first section builds the map and adds all of the placemarks to it. The MarkerClusterer library takes care of clustering the placemarks and the MapIconMaker library build the icon. The code looks like this:
// declare helper variables
var markerUrl = "url-to-venue-data";
var markerCluster;
// create a new map and centre it on australia
map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(-25.947028, 133.209639), 3);
map.setUIToDefault();
// get the marker data
GDownloadUrl(markerUrl, function(data) {
// get an icon - in keeping with style
var newIcon = MapIconMaker.createMarkerIcon({width: 32, height: 32, primaryColor: "#FFBC3F"});
// store the created placemarks
var markers = [];
// get the xml data
var xml = GXml.parse(data);
// extract the markers from the xml
var points = xml.documentElement.getElementsByTagName("marker");
// build a group of markers
for (var i = 0; i < points.length; i++) {
// get the coordinates
var latlng = new GLatLng(parseFloat(points[i].getAttribute("lat")), parseFloat(points[i].getAttribute("lng")));
// create the marker
var marker = new GMarker(latlng, {icon: newIcon});
// build the url for the info
var url = "url-to-event-data" + points[i].getAttribute("id");
// get a function to respond to the click
var fn = markerClick(url, latlng);
// add an event listener to listen for the click on a marker
GEvent.addListener(marker, "click", fn);
// add the marker to the list
markers.push(marker);
}
// add the markers to the map
markerCluster = new MarkerClusterer(map, markers);
});
The key lines are:
- Line 11: Where the venue data is downloaded using the GDownloadUrl function
- Line 14: Where the icon style for the placemarks is defined
- Lines 19 – 23: Where the XML data is processed
- Lines 26 – 45: Where the XML is used to create a group of markers
- Line 48: Where the MarkerClusterer library is used to manage the custering of the placemarks on the map
The key to achieving the dynamically loading InfoWindows is line 38. This line uses the markerClick function, the second part of the strategy, to construct another function which will respond to the event when a user clicks on a placemark.
The markerClick function looks like this:
// function to build a function to respond to the click on a marker
function markerClick(url, latlng) {
return function() {
// download the event information
GDownloadUrl(url, function(html) {
// open an info window with the information
map.openInfoWindowHtml(latlng, html, {maxWidth:450, maxHeight:400, autoScroll:true});
});
}
}
This function again uses the GDownloadUrl function to download data, this time a HTML snippet that lists all events associated with a venue. The data that is retrieved is then used to populate an InfoWindow that is opened using the openInfoWindowHtml function associated with the main map object. By using the same GLatLng object as that used to construct the placemark the InfoWindow appears in the right spot, over the placemark that was clicked.
Dynamically retrieving the content that is used to populate the InfoWindow introduces a slight delay to the display of the InfoWindow as the HTML content must be displayed. A planned refinement of this technique is to display some sort of loading message to the user to keep them informed of what is happening.
A pre-alpha version of the map, when it is first generated looks like this:
Clicking one of the clustered markers zoom in the map and expands the cluster of markers until such time as single makers are displayed. For example in the example below the map has been zoomed into Adelaide by clicking the clustered marker at this area.
One of the benefits of the markers created by the MarkerClusterer library is that the clusters are automatically numbered to show how many individual markers are contained in the cluster. Clicking an individual marker, there are four on this map, brings up an InfoWindow displaying information in a similar way to that which I’ve outlined before on this blog.

