Google Maps API

The Motivation

OK so I was driving into work listening to the radio and I there was a story on about all of the cool uses people have been finding for the Google Maps API for.

So it looks like the first stop anyone that's interested in learning about Google Maps implementations is Google Maps Mania where you can check out the latest implementations of Google Maps.

This is kind of a downer but at the top of the list was an map of all of the murders in Rochester New York. Much like anyone else who has grown up in USA I've been subjected to reams and reams of information about violent crime in the US. Most of the information that has ever been presented to me hasn't had much impact.

My first thought upon viewing that map is that it is REALLY, REALLY dangerous to live in certain neighborhoods and REALLY REALLY save to live in other neighborhoods. I mean I can't even begin to guess how many times I've heard that some areas are very dangerous, but being able to see how the the central area of the city has murders icons layered all over eachother, but in all other areas there are almost no murders. Just seeing the map really brought the point home for me.

After pondering about how sometimes the grass is actually greener on the other side. I started clicking on some of the icons and seeing the pics and data of a 65 year old women that was strangled or the 9 year old boy that was shot the trajic nature of murder really hit home. I thought about how many times over the years I'd heard statistics about how x number of kids were killed between the years of whatever or how many women or teenagers were murdered but studying the map for a few minutes with the icons and the pictures really seemed to give me a perspective that years and years of pure data was never able to convey.

It's very clear to me that a map of data can make give perspective that no list of data could ever give. I guess that's why they always have a map with pins on it on all of the TV detective stories. The Googles Maps API could genuinely improve the internet and make the internet more useful.

The first Step - Call my big pimpin buddy Joe Reger

OK so everytime I hear about a new technology that I think will improve the web the first thing I do is call my big pimping buddy Joe Reger. The great thing about Joe is that by the time I've heard of a new technology he's usually researched it inside and out and implemented it. Sure enough Joe has implemented it and you can check it out at Reger Locations.

The second Step - Do a Google Search on "Google Maps API"

The first result was http://www.google.com/apis/maps/ and this is a very important step because this is where you can sign up for a Google Maps Key. So if you're interested in setting up your own Maps then you will need to sign up for a Google Maps API Key.

Steps to sign up for a Google Maps API key

  1. Click the link "Sign up for a Google Maps API key"
  2. Click the checkbox that reads "I have read and agree with the API terms and conditions"
  3. Enter the website your maps will be displayed on

After generating your key you will be presented with the following information

  1. Your Key
  2. Your Directory
  3. Sample Code

So here's the Google Maps API sample code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script
src="http://maps.google.com/maps?file=api&v=1&key=ABQIAAAANF1DtogJvlNoEceXGRUV3RTmXEp6K95Cy4LpKKVk_SI2sl4lHhRUKNi6Zr7xOuco3W09H-LtgGyBQw"
type="text/javascript"></script>
</head>
<body>
<div id="map" style="width: 500px; height: 400px"></div>
<script type="text/javascript">
//<![CDATA[

var map = new GMap(document.getElementById("map"));
map.addControl(new GSmallMapControl());
map.centerAndZoom(new GPoint(-122.1419, 37.4419), 4);

//]]>
</script>
</body>
</html>

Breaking the Google Maps API down:

First lets See the sample code in action. Pretty sweet huh !?
So now with just a little bit of copy and paste action we've got a fully function map of... well I don't know exactly what it's a map of, but whatever it is it's pretty cool.

First observation. The sample uses an XHTML doctype. Since I usually don't use that doctype, I usually use <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">. So let's see what happens when I change the DOCTYPE. So the good news is that the DOCTYPE doesn't effect the functionality.

Second observation. The sample uses the following line: <html xmlns="http://www.w3.org/1999/xhtml"> my suspicion is that I don't need this line. So let's see what happens when I remove that line. So far so good, after a quick look it would appear that there are no ill effects. Hmmmm I wonder if this is going to come back and bite me later.

Third lets look at the Google Maps API JavaScript include:

 
<script
src="http://maps.google.com/maps?file=api&v=1&key=ABQIAAAANF1DtogJvlNoEceXGRUV3RTmXEp6K95Cy4LpKKVk_SI2sl4lHhRUKNi6Zr7xOuco3W09H-LtgGyBQw" type="text/javascript"></script>
 
It looks like Google generates some dynamic JavaScript. It looks like the JavaScript specifies a GMAP object that has various methods including addControl and centerAndZoom.

Fourth lets look at the div spec.

<div id="map" style="width: 500px; height: 400px"></div>
 
So basically the GMap object assumes that a div with the ID set to "map". My guess is that the GMap object creates an object by using the getElementById("map") method and then examines the height and width of the the div. Once it has the height and width it adjusts the output to fit perfectly inside the div.
 
Let's experiment. First I'll set the width and height of the div the 600px by 600px.
<div id="map" style="width: 600px; height: 600px"></div>
 
Pretty cool, huh!?!
 
Now lets try a tall skinny div. <div id="map" style="width: 100px; height: 600px"></div>
 
OK even though it's a waste of time I feel compelled to make a short and fat one. I guess it's seems like setting up a short and fat div adds a nice symmetry to this exercise. <div id="map" style="width: 600px; height: 100px"></div>
 
Very slick, huh? So now we know that to change the size of the map all you need to do set the div.

SNAP. I just noticed that the GMap constructor accepts a div object. So that means that we can probably create more that one map at a time. Hmmm let's give that a try. Pretty cool huh? This is how it's done:
 
<-- THIS IS THE FIRST OBJECT -->
<div id="map" style="width: 100px; height: 600px; float:left"></div>
<script type="text/javascript">
//<![CDATA[

var map = new GMap(document.getElementById("map"));
map.addControl(new GSmallMapControl());
map.centerAndZoom(new GPoint(-122.1419, 37.4419), 4);

//]]>
</script>
<-- THIS IS THE SECOND OBJECT -->
<div id="map1" style="width: 300px; height: 300px"></div>
<script type="text/javascript">
//<![CDATA[

var map = new GMap(document.getElementById("map1"));
map.addControl(new GSmallMapControl());
map.centerAndZoom(new GPoint(-122.1419, 37.4419), 4);

//]]>
</script>
 
OK I've gotton a little ahead of myself...

Fifth lets look at the object instanciation

var map = new GMap(document.getElementById("map1"));
So three things are happenning here:
First, an object called map is being declared, since JavaScript is very loosy goosy with it's declaration we just call it a standard var. We could have accomplished the same effect with this simple line of JavaScript.
var map;
 
Second, we are instanciating a GMap object.
 
I love that word instanciation, it takes a long convoluted discussion crams it into a single word. So here's what that word means to me with respect to this situation. In the dynamic JavaScript that I wrote about in my third observation they have a bunch of code all rolled up into a template. They (Google) has generously allowed anyone access the the template and in order to access it all you need to do is create call a function they call GMap. The GMap function is called a constructor and the GMap function needs one piece of information in order to be able a create a working version of itself. That one piece of informaton is called a parameter, so if someone say's that the GMap constructor needs one paramater, all their saying is that if you want access all of the goodies in the Google Maps Template then you have to give it one piece of information.
 
It's pretty amazing that the words "instanciating a GMap object" means all the words in the previous paragraph...
 
Anyways back to business, so we can tell that we're instanciating a new object because of the keyword new in the JavaScript new GMap(document.getElementById("map1")). We could have created a new object with the following.
map = new GMap(mapLocation)
 
Third, we are passing the location and other information about where the map should be placed to the GMap constuctor. As you probably already know all web pages can be described by it's DOM (Document Object Model). Basically, any time a page is build the browser (Internet Explorer, Firefox, Opera...) keeps a map (the map is the DOM) of that page in memory. Everything in that page is described in that map. By everything I mean everything, that map has the location, the width, the height, whether it's visible or not, what it's in front of, what it's behind... Through JavaScript you can change most of the things about the stuff (objects) in that map (DOM). If you want to change something about an object on a web page (like maybe stuff a big google map into it) the first thing you need to do is find out where that object is in the map (DOM).
 
All web pages have an object call the document. The document holds the DOM and the document will gladly give you all of the information that exists about any object in the DOM. You just need to know how to ask for it. The best way I know of to get the information about an object is via it's ID.
 
Do you remember earlier when we set up this HTML?
 
<div id="map" style="width: 500px; height: 400px"></div>
 
Well at that time we assigned an ID called "map". See were id="map" is?
 
Once that is done then we can go to the document and ask for the all of the information about the Object that has the ID of "map".
 
We ask the document for that information with this javascript:
document.getElementById("map")
 
So we could get all of the information with this:
var mapLocation = document.getElementById("map")
 
So this one line:
var map = new GMap(document.getElementById("map1"));
 
Could be replaced by these four lines:
var mapLocation;
mapLocation = document.getElementById("map1");
var map;
map = new GMap(mapLocation);
 
Obviously, the second way isn't nearly as elegant as the first way, but breaking it down can be helpful sometimes.

Sixth lets look at the Google Maps API for calling some functions in the GMap object.

The first function call is:
 
map.addControl(new GSmallMapControl());
 
So it looks like the GMap template has a addControl function. If the google dudes are any good (and we all know that they are) then the addControl function is probably the way controls are added to maps. It looks we we are adding a small map control object. My guess would be that GSmallMapControl is what causes the control in the upper left hand part of the map show up. When we take a close look at the documentation I suspect we will see a listing of all the available controls and their descriptions in one convenient place. For now we will see what happens if we don't add the GSmallMapControl(). The second function call is:
 
map.centerAndZoom(new GPoint(-122.1419, 37.4419), 4);
 
The centerAndZoom function seems pretty important. Especially since this function passes in what looks like some kind of location (possibly a Latitude and Longitude) and what looks to be an integer that I would guess represents the zoom. I guess that makes sense since this function is called center (where to center of the map should be pointed at?) and Zoom (how much to zoom). So let's see what happens if we don't call this function. My guess is that if we don't call this function we will be treated to a view of the earth from outer space, but that's just a guess. It's possible that we'll see some kind of JavaScript error... no that's not possible, the Google engineers wouldn't let me down like that. So here we go. OK so we got nothing, I guess that makes sense, I'm a little disappointed, but it's cool.

So now the sample code has been disected. Let's track down some official documentation so back to the source we go http://www.google.com/apis/maps/. Well looky there in the left hand there's the documentation link.
 
So it looks like the documentation is devided into two sections the left side looks it's basically the "How to do things" sections and the right side is the "Google Specs". OK now I feel like I have a nice foundation for understanding Google Maps. So now I want to know how to do three things:

  1. Center the map where I specify.
  2. Put some of those push buttons where I want to put them.
  3. Put some pictures and text that pops when a push button is clicked.
  4. Change the picture from the push pins to my icons.

Using the Google Maps API to center the map where I specify.

So, I guess a good place to aim the google map is my wife's most awesome consignment store Melissa's Boutique. The first step is to find the latitude and longitude of her store. I know the address
 
3920 Canton Road,
Marietta, Ga
 
According to the google documentation I can use a geocoder.us a free website to find the lat. and long. So I just entered the address and here's what I got
 
Latitude 33.975884 °
Longitude -84.547325 °
 
So I should be able to change up the original code with my new lat. and long. and we should be able to Melissa's Boutique.
 
FROM: map.centerAndZoom(new GPoint(-122.1419, 37.4419), 4);
TO: map.centerAndZoom(new GPoint(-84.547325, 33.975884), 4);
 
Lets check the new code out.  
Hmmmmmm. So this is close but not correct. Back to the drawing board. OK so it looks like geocoder.us returned 915 Canton Road, not 3920 Canton Road. So let's go back to the Google List and see what else comes up. So next let's try http://www.infosports.com/m/map.htm and I found
 
Latitude 34.04642349510992 °
Longitude -84.52834725379944 °
 
Lets give it another try. So that's a lot better.

Use the Google Maps API to put some of those push buttons where I want to put them.

According to the Google Maps API Documentation it looks like we need to execute the following steps:

  1. Create a GPoint object
  2. Create a GMarker object
  3. Pass the GMarker object to the GMap addOverlay method.

Create a GPoint object
We've already created GPoint objects and passed them to the map.centerAndZoom method. Here's an example:
var overlayPoint = new GPoint(-84.52834725379944, 34.04642349510992)
Create a GMarker object
Creating a GMarker object is easy all we do is pass the GMarker constructor our new GPoint:
var overlayMarker = new GMarker(overlayPoint)
Pass the GMarker object to the GMap addOverlay method.
Now all we have to do is pass the overlayMarker to the GMap.overlay method:
map.overlay(overlayMarker)
Let's check it out.

Now lets try to put the satalite option on the map.

According to the documentation it looks like we need to add the following code map.addControl(new GMapTypeControl());
Let's check it out.

Now lets use the Google Maps API to make a pop up window..

According to the documentation it looks like we need to execute the following steps:

  1. Add a click listener event to the GMarker
  2. Pass the GMarker object to the GMap addOverlay method.

So let's start with adding an event listener to the GMarker object. According to the documentation we can add an event to the click as follows: var overlayMarker = new GMarker(overlayPoint)
...... BAM CRASH AND BURN ......

Crash and Burn Recovery

So I was working on that at around midnight and I was getting no where. After struggling and not getting anywhere for about 45 minutes I decided to go to bed. It was clear that I was having some kind of conceptual problem... Early the next morning, while showering, the conceptual breakdown became clear to me. The problem was that up until this point we've been instanciating (creating) a GMap Object and then executing methods inside of our GMap Object. Most of the time when we executed the methods inside of the GMap object we actually passed other objects to our GMap Object, I usually visualize adding the GMap Object being like a Christmas tree and the objects we pass to it being like Christmas ornaments that add value to the tree. So we have a GMap object and then we add GMarkers and GMapControls and whatever other goodies Google has provided.
 
My conceptual approach to the Events was that I was going to add an event to our GMap Object, I mean we all know that GMap is the Big Daddy... Right? Well not any more boys and girls, we've got a new Big Daddy... in order to handle events (events are things like clicking the mouse on the map) we need to create a GEvent Object and then pass our GMap Object to it... See that BAMMMMM a whole new paradigm shift... GEvent is the Christmas tree and Gmap is the shiny ornament, but it's kind of like GEvent is a 3 inch tall Christmas tree with a 2 foot tall shiny GMap ornament hanging on it. You hardly even know the tree is there and that's what makes this a little confusing.
 
OK so I am geek. We can continue now...

Let's make another attempt at using the Google Maps API to make a pop up window..

According to the documentation it looks like we need to execute the following steps:

  1. Create a GPoint object
  2. Create a GMarker object
  3. Create a GMap Object
  4. Pass the GMarker object to the GMap addOverlay method.
  5. Generate some HTML to pass to the addListener
  6. Register the GMap Object with the GEvent by calling the addListener method
  7. Pass the GMarker object to the GMap addOverlay method.

So let's start with creating a point and a marker
var overlayPoint = new GPoint(-84.52834725379944, 34.04642349510992)
var overlayMarker = new GMarker(overlayPoint)

Next we'll create a GMap object
var map = new GMap(document.getElementById("map"))

Next we'll pass the GMap object the marker object
map.addOverlay(overlayMarker)

Next we'll set up some HTML
var mapHTML = "<b>Hello World!!!!</b>"

Next we'll register our GMap Object with the GEvent object by calling the addListener method
GEvent.addListener(overlayMarker, 'click', function() {overlayMarker.openInfoWindowHtml(mapHTML);});

So let's check it out

OK We're almost there so now let's add a couple of new controls... Let's add the zoom and pan buttons and the satellite/map buttons
 
According to the documentation all we need to do is add the GMapTypeControl() and the GSmallMapControl() let's check it out.

Well the only other thing I can think of to do is to have two pop-up markers. We'll add one more marker where our store used to be.