Blog
Books
Talks
Follow
Me
Search

Larsblog

Playing with the Google Maps API

<< 2005-12-03 13:38 >>

I sat down to try the Google Maps API yesterday, and came away very impressed by both it and the new AJAX style of web applications. Here is an introduction to the API, together with some musings on how it could be used with Topic Maps.

Using the API

The API is available for free, and you can use it to put maps onto web sites for free (provided the site is non-commercial). The way it works is that you use a script element to download the JavaScript code from Google. To do this you need to register and get a key from Google. This key is tied to your site URL, which is of course reported by the browser in the referrer header when the user's browser downloads the JavaScript.

Once this hurdle is passed, actually displaying a map with a zoom control on it is dead easy. In fact, the following would give you a nice map of London:

<!-- This loads the JavaScript code implementing the API -->
<script src="http://maps.google.com/maps?...">

<!-- This is where the map will be placed by the JavaScript -->
<div id="map" style="width: 700px; height: 650px"></div>

<script type="text/javascript">

// creating the map
var map = new GMap(document.getElementById("map"));
map.addControl(new GLargeMapControl());
map.centerAndZoom(new GPoint(-0.1, 51.5), 5);

</script>

That's it. That really is enough to give you a zoomable, draggable map of London. The GMap is a JavaScript class that basically implements all of the logic necessary. The GLargeMapControl is the overlaid zoom/navigate control on the upper left. There's also a smaller version if you prefer, and you can put in the satellite/map chooser, etc.

Of course, this isn't really that interesting. A link to Google Maps would accomplish the same thing more easily. What's more interesting is to put markers on the map. Again, this turns out to be dead easy. Just add the following to the script, below the map.centerAndZoom line:

map.addOverlay(new GMarker(new GPoint(-0.199642, 51.47405)));

The map now gets a nice red marker at the precise location of the famous White Horse pub in Parson's Green. As you scroll and move around, the marker will stay put. This is where it starts to get interesting, because once you have the coordinates of some places you can start putting them on the map. If you want, you can get even more fancy, and customize the icons (haven't gotten this to work yet), and also display information windows when the markers are clicked. (Actually, you can register events that do anything when they are clicked, but there's ready made functionality for the information windows.)

The code for registering information windows with layout etc is a bit more complex, but not much. Here is new code to replace the one-line snippet above with:

// helper function to add a pub to the map
function add_pub(x, y, popupid) {
  marker = new GMarker(new GPoint(x, y));
  marker.popupid = popupid; // register ID on object for later

  // register an event handler to open the window on click
  GEvent.addListener(map, 'click', marker_clicked);

  map.addOverlay(marker);
}

// event handler; opens info window for marker
function marker_clicked(marker) {
  // retrieve the element to show in the window
  element = document.getElementById(marker.popupid);

  // we can't pass this element in because it gets destroyed
  // once the window is closed, so we make a copy
  element = element.cloneNode(true);

  // switch display from off to on
  element.style.display = "";

  // then open the window
  map.openInfoWindow(marker.getPoint(), element);
}

// having created the helper functions we can add our pub
add_pub(-0.199642, 51.47405, "white-horse");
</script>

<!-- This element is not displayed on the page, but get passed into
        the information window -->
<div style="display: none; font-family: Arial; font-size: 8pt; width: 350px"
     id="white-horse">
<b>White Horse</b><br>
Famous pub, which is also a good restaurant. Wide beer selection,
upscale interior, good seating.
</div>

An example

Here is a working example, implemented with the code shown above. The markers show some of the most interesting places in London, but you need to click them to see what they are.

Building the data

So far we've only covered the functionality, but this only really becomes interesting once you have some data. So how to get that? How to find the coordinates of any given location? Well, to make the map center on London I started from Google's example, which focuses on Palo Alto, USA. Since the coordinates are longitude and latitude, one of them was easy. Zero longitude is Greenwich in eastern London (just visible on the far right of the map). Some quick trial and error (via southern Spain, northern Scotland, and the Channel) then led me to London.

This is a pretty cumbersome method, though. Another method is to extend the map interface a bit, so that you can go to a location and click on it to find the coordinates. This is pretty easy. Just add the following to your code, and you can cut and paste the coordinates from the popup.

// click to see where you are
GEvent.addListener(map, 'click', function(overlay, point) {
  if (point) {
    alert('You clicked at: ' + point);
   }
});

However, even this is quite awkward. The easiest is to just use Google Maps and search for the name and street address (plus city name and country name) of the place you are looking for. You don't get to see the coordinates in the Google Maps interface (unfortunately), but you can go to http://maps.google.com/local?q=your+query+here&output=js. This gives you a very hard-to-read result, but searching for "<point" will find you the coordinates.

If you find this too awkward, here is a Python script you can use to extract the coordinates. Just give it the search string and the letter of the alternative you want, and it will spit it out for you. Here is an example of use:

[larsga@localhost tmp]$ python gxy.py "The Star, 6 Belgrave Mews West, London, UK" A
Longitude: -0.155352, latitude: 51.497988

JavaScript and AJAX

Playing around with this API, plus some recent development experiences, have really given me respect for both JavaScript and the recent wave of AJAX applications. To be frank, however, I think AJAX amounts to no more than the discovery that JavaScript is a real programming language, and that XML is the best way for it to get data from the server to work with.

I guess what is the most surprising for this is that it's taken so long to happen. After all, JavaScript has been with us for 10 years now, and XML for more than 7. Probably the fact that it was almost exclusively implemented in web browsers, that implementations were incompatible (and poor), and that most of the actual JavaScript code out there was of such crappy quality contributed a lot to this. And, not only was the code crappy, but what it did was mainly to annoy users. The only thing that's really changed is that it's now possible to write code that works in most of the browsers people actually use, that the JavaScript out there is a lot less annoying than it used to be, and that the perception of the language has changed. Which was about time, anyway.

I have to admit I was no quicker in the uptake here than most other developers. For me, the big turning point was playing around with the Google Maps API, and to some extent discovering that judicious use of simple JavaScript can do wonders for web applications. Having people like Robert Cerny tell me the obvious (JavaScript is a real programming language) also helped, of course.

Having said all this, one problem does remain, however. Debugging JavaScript is still a very unpleasant job. It's become easier than it was when scripts would just silently fail, but when you do something wrong (like adding the marker before the map.centerAndZoom call) it's pretty hard to work out what, exactly, you did wrong. If I use Google's example code to add a GIcon object to a marker I get the default icon, and it shows up in the wrong place. Nothing fails, but the marker winds up in the wrong place. Why is that? What's going on? I still don't know.

Topics on maps

One thing that is interesting to me about this is that it shows that creating a Google Maps integration with a Topic Maps product is dead easy. What you need is the located-in association type (which already has an Ontopia PSI) and two latitude and longitude occurrence types to capture the coordinates of specific places. If you want to be really fancy you can attach an marker-icon occurrence to the topic types as well, so that topics of different types can get different icons on the map.

The information about the White Horse pub used as an example above would then be encoded as follows in LTM:

[white-horse : pub = "White Horse"]
{white-horse, description, [[Famous pub, which is also a good
restaurant. Wide beer selection, upscale interior, good seating.]]}

{white-horse, geo:latitude, [[51.47405]]}
{white-horse, geo:longitude, [[-0.199642]]}
geo:located-in(white-horse : geo:containee, london : geo:container)

Given this, writing JSP (or whatever) that produces a Google Map showing all topics in a particular city is dead easy. In fact, it's how the map above was produced. I've created a topic map about beer which I use, among other things, to do research on beer-related places before travelling somewhere. I extended it with the longitude and latitude occurrence types, entered them for the places in London, and two simple tolog queries (one for the add_pub function calls, another for the popup divs) did the rest.

This could easily be productized into an OKS module that would let users specify a place topic and a zoom level (plus the desired map size, I guess) and it would then produce their nice Google Map, with icons, popup windows, and links back into the Topic Maps application. All they'd need to do is use the geography PSIs in their own topic map. And, probably, buy a Google Maps key, as anyone purchasing such an OKS module would probably be a commercial site. Which, I guess, only shows the wisdom of the Google Maps creators in building such a usable and powerful API, and then making it available to non-commercial users. Hats off to them for having done a fantastic job on this.

Similar posts

The year 2005 in travelling

Norm Walsh had the excellent idea of publishing a map showing his travels (via Column Two), and I couldn't resist the temptation to do the same

Read | 2006-01-05 21:55

TMRA 2006 — day 2

Day two started right off with two parallel tracks, and I went to the track on "Portals and Information Retrieval", where the first speaker was Sam Oh

Read | 2006-10-12 09:09

tmphoto

You may have noticed that recently the photos used in this blogs have become links, which they weren't before

Read | 2007-09-15 19:08

Comments

Add a comment

Name required
Email optional, not published
URL optional, published
Comment
Spam don't check this if you want to be posted
Not spam do check this if you want to be posted