Apr 272010
 

Even the simplest data driven applications today are not only about gathering, understanding and digesting data. Its also important to decide how you display it in such a manner that the user is able to get the gist in the least amount of time. A great way to do that is display data as graphically as possible – with Charts, Graphs and maps. For displaying maps there are quite a few APIs available – Google Maps, Yahoo maps and Bing maps.

I have been playing around with the Google Maps API for the last few days and found it an amazingly simple way to display geographical data in your application. All you need to do is to reference the Google maps JavaScript file and a few lines of code would get you started with a basic map.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Google Maps API</title>
<!-- Google maps Script has to included -->
<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=false&amp;key=YOUR_API_KEY_HERE" type="text/javascript"> </script>
<script type="text/javascript">
    function initialize() {
        var map = new GMap2(document.getElementById('map_canvas'));
        map.setCenter(new GLatLng(12.98058, 77.58854), 13);
    }
</script>
</head>
<body onload="initialize()" onunload="GUnload()">
<div id="map_canvas" style="height:500px;width:500px" />
</body>
</html>

There are a few things to note here

  • GMap2 is the object which returns the map object. We need to pass the DOM element on which the map has to be drawn. This is called the canvas and can be a div HTML element.
  • map.SetCenter: This method is the first that needs to be called on a map object in order to set its coordinates. In the code we passed the latitude, longitude and the zoom level of the map.
  • GUnload: Most important part of the application. Call this function in the onUnload event handler to avoid any unpleasant memory leaks in the application. This eliminates most of the circular references.

Now only displaying a map is not of much use. We need to be programmatically able to manipulate each part of the map in order to show our data in the canvas. This can be done through the Google Maps API which is an object oriented library representing each graphical part of the map.

For a small working example, I wrote some code to display data from an xml file on the server. Suppose you want to display the hotels on a map in Bangalore, and when the user clicks on the hotel, the details of the hotel should appear in a popup window. Something like this:-

The xml file resides on the server and contains all the details of the hotel including their latitude and longitude. The JavaScript gets the xml through an AJAX call and then iterates through to get the information of the individual hotels. For each one, it creates a marker and adds it to the map. Also using the details it creates the HTML to be displayed in the popup event and hooks up the click event handler to do it.
Below is the code:-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/* ************************************************
* Developer: Ganesh Ranganathan
* Date: 26-Apr-2010
* Description: This is a Google Maps API Example.
* ***********************************************/
 
var map1;
 
$(document).ready(function() {
    //Init Method is run on load of Page DOM
    initialize();
    refreshData();
});
 
//GUnload method cleans up any google map1 objects
$(window).unload(function() {
    GUnload();
});
 
//The KeyValue pair for the location
//that we start with. Currently its bangalore
var DEF_LOC = {
'lat': 12.98058,
'lng': 77.58854,
'zoom':14
};
 
function initialize() {
    //Getting the map1 object. The [0] Index is because JQuery
    //returns an array of JavaScript elements from a DOM search
    //and we need only one
    map1 = new GMap2($('#map_canvas')[0]);
    //Setting the map1 to Bangalore and Adding standard map1 controls
    map1.setCenter(new GLatLng(DEF_LOC['lat'], DEF_LOC['lng']), DEF_LOC['zoom']);
 
    $.each([new GLargeMapControl(), new GMapTypeControl(), new GOverviewMapControl()]
    , function(index, value) {
        //Adding all the controls to the map
        map1.addControl(value);
    });
 
    //Setting the icon properties to display
    var hotelIcon = new GIcon();
    hotelIcon.image = "hotel_icon1.gif";
    hotelIcon.shadow = "http://chart.apis.google.com/chart?chst=d_map1_pin_shadow";
    hotelIcon.iconSize = new GSize(25, 34);
    hotelIcon.shadowSize = new GSize(35, 28);
    hotelIcon.iconAnchor = new GPoint(6, 20);
    hotelIcon.infoWindowAnchor = new GPoint(5, 1);
    markerOptions = { icon: hotelIcon };
}
 
function refreshData() {
    $.ajax(
{
    url: 'Hotels_data.xml', // Data Source in XML file
    //No Caching, Asynchronous call and setting the
    //Datatype to XML.
    cache: false,
    async: true,
    datatype: 'xml',
    success: function(xml) {
        //Successful ajax callback function. First clear
        //all existing markers to preserve memory
        map1.clearOverlays();
 
        $(xml).find('hotel').each(function() {
            //Iterating through each hotel tag in the xml
            //and gettiing the lattitude and longitude
            var lat = $(this).find('latitude').text();
            var lng = $(this).find('longitude').text();
            //pass node to helper function to get the markup
            //for the marker.
            var html = getMarkerHTML($(this));
            //Creating a marker object and assigning the click
            //event handler for the map to pan to the center of the
            //canvas. Also the Info window needs to open
            var marker = new GMarker(new GLatLng(lat, lng), markerOptions);
            GEvent.addListener(marker, "click", function() {
                map1.panTo(new GLatLng(lat, lng), DEF_LOC['zoom']);
                marker.openInfoWindowHtml(html);
            });
            //Add the marker to the map
            map1.addOverlay(marker);
        });
    },
    error: function() {
        //Error Callback. Just inform the user
        alert('An error has occured');
    }
});
}
 
//This is a helper function to get the markup
//for the marker's click node.
function getMarkerHTML(xmlNode) {
    //find the text in the childd nodes
    var get = function(tag) {
        return xmlNode.find(tag).text();
    };
 
    //Bolden the Key and append the value
    var decorateBold= function(key,value){
        return '<b>'+key+': </b>'+value+'<br />';
    };
 
    var singleCost = xmlNode.find('single_room').text();
    var doubleCost = xmlNode.find('double_room').text();
    var html = "<div style= 'background-color: #FFCC66;font-family: ";
    html += "Verdana;font-size: 1.0em;padding: 3px'>" + decorateBold('Name', get('name'));
    html += decorateBold('Address', get('address'));
    if(!isNaN(singleCost))
    html += '<b>Single Room: </b>'+ singleCost;
    if(!isNaN(doubleCost))
    html += '<b> Double Room: </b>'+doubleCost+'<br />';
    else
    html += '<br />';
    html += decorateBold('Phone',get('phone_no.'));
    html += decorateBold('Email',get('email'));
    html += decorateBold('Website',get('website'));
    return html+= '</div>';
}

Click here for the demo.