HTML5, CSS3, jQuery, JSON, Responsive Design...

Google Maps Web App

Michael Brown   March 24 2012 11:11:00 PM
Here's a simple web app that I've put together in order to show how to pull in and display data from Google Maps.

Messing About With Google Maps App

In order to access the Google Maps API you need to get a Maps API key from Google, which means you need a Google account (e.g. Gmail) if you don't already have one.  Once you've got that, you need to load the Google Maps API JavaScript library, directly from Google's server, like so:
script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key=YourKeyGoesHere&sensor=false"


Please don't use my key if you're copying the code.  Also, don't try to copy the Google JavaScript library and load it locally in a misguided attempt to speed things up.  It won't work unless you're loading the API library directly from Google's own server.

The main code is in the code.js file.  Note: the code is namespaced - a subject that I'll be returning to in a later post - so that most of the functions are inside a global object called myGlobal.


Getting Your Position

When the page loads, the $(document).ready() function (provided by jQuery) makes a call to navigator.geolocation.getCurrentPosition() in order to get your current position.  You will see a dialog prompt at this point, asking if you if you want to share your current location with the server.  Note that the navigator.geolocation object is a native to HTML5.  It is not part of jQuery or the Google Maps API.  This call will work on any HTML5-compliant browser. I tested on Chrome, Firefox and IE 9.  The line if(navigator.geolocation) {} checks to see whether this functionality is available in your browser.  (Remember, it's good practice to test for functionality rather than for browser versions, since the latter are a moving target.)

The navigator.geolocation.getCurrentPosition() takes two function arguments.  These are callback functions: the first callback function runs if the getCurrentPosition() call successfully returns your position, and the (optional) second callback function runs if getCurrentPosition() fails for any reason.  A successful getCurrentPosition() call will automatically pass a position object as the first parameter to its defined callback function.  So, it makes sense to call that parameter "position", which I have in my code.  Here's what you get in that object, as displayed by Firebug:

The position object

We're interested in the latitude and longitude properties of the coords property.  We can pass these to the Google Maps API to plot our position on a Google map.  I do this via a call to my myGlobal.codeLatLng() in my "success" callback function.  (We're still inside $(document).ready() at this point.)


Getting the Map Object from Google Maps

myGlobal.codeLatLng() takes three parameters: the latitude, the longitude and a callback function that I've set to markupMap, which I'll get to in a moment.  myGlobal.codeLatLng() creates a simple object, called latlng, by passing to it our latitude and longitude values.  This is our first call upon the Google Maps API.  There's a further bit of prep to do, in that our next call to the Google Maps API requires the latlng object to be a property of another object. I've called this second object initObj.  Its property must be called latlng in this case.  Finally, the myObj.codeLatLng() function calls my myGlobal.getGeoCodeResultsObj, passing as parameters the new initObj object and the same callback function that we passed in, i.e. markupMap.

The myGlobal.getGeoCodeResultsObj sets up a new google.mapsGeocoder object called geocoder, if it's not been set up already.  It then makes a call to the new object's geocoder() function, passing in the initObj object that we created in myGlobal.codeLatLng(), plus two callback functions: the first for a successful call and the second for a failure, once again.  The "success" callback function calls the callback function that we've been passing through all our functions so far, i.e. markupMap.  It passes to markupMap the results of the call to the Google Maps API's geocode() function.  Those results are a JSON array of objects.  You can see the data in them on the web page itself, because I write a string version of them underneath the map itself.  (See the "Returned Geocoder JSON array" box.)


Plotting the Map

The myGlobalMap.markupMap() function plots the map on the page.  It's going to put in a div with the id of map_canvas.  The code creates a new google.maps.Map, if one doesn't already exist, passing in the map_canvas div as its first parameter.  Note that this parameter must be a DOM object for the div, not just its id as a string.  The object passed is where the API will attempt to put the map.  The second parameter passed is a config object, on which I've set a sensible zoom level and set the map to be road map (as opposed to a satellite map).

Now I've got a map on my web page, I need to tell it to show my current location.  The line myGlobal.map.setCenter(resultsArray[0].geometry.location) does this.  Note here that I'm being a tad presumptuous in assuming that the first object in the array returned by the earlier google.mapsGeocoder.geocoder() call is the right one.  In a production app, you might want to give the user the option to choose, but my way will do for this little test app.  Once I've centred the map on my current location there, I want to place a marker at that location too.  The following lines to that by creating a new google.maps.Marker object, called marker, and then placing it on my map at the desired location.  You'll note that I also push the marker object onto an array called myGlobal.markersArray.  The reason for this is that there doesn't seem to be any built-in way in the Google Maps API to clear all the existing markers.  So, I've had to write a function to clear them all, one by one - see the myGlobal.markersArray() function.


Searching and plotting your own addresses

As well as passing the google.maps.Geocoder call a set of coordinates to get some results, you can pass it an address and Google Maps will try to match it.  This is, of course, just what the Google Maps main site does, and I've tried to match that here with the Plot Address button.  Type an address in the text field and hit the button.  Google Maps will plot the first match it finds (there's my presumption again!) onto the map.  The code to retrieve and plot this map is pretty much identical to that I've already described.  In fact, you'll see that I'm reusing most of it!  The only difference is in the config object that is passed into the google.maps.Geocoder() call.  This needs to be an address object rather than a latitude/longitude object.  Check the myGlobal.codeAddress function for how I set up this address config object, using whatever has been typed into the text box.


Going Mobile

And here it is as an app on my iPhone - well, actually in the iPhone simulator to take this screen shot, but it is running on my real iPhone too!
The Maps App on the iPhone

Note this is an app, not a web page running in the Safari browser.  If I wanted to, I could put this up on the iTunes store and sell it, and then how Angry Birds would tremble!  And it's the same source code too, all written in HTML5, CSS and JavaScript.  I tweaked the formatting to better fit the smaller screen, and then add some CSS, courtesy of the jQuery Mobile library, to make it look a bit more iPhoney.  I also load the Google Maps API library with the sensor parameter set to true, i.e.
script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key=YourKeyGoesHere&sensor=true"


This lets the API take advantage of the iPhone's built-in GPS.

This magic is possible due to the wonders of PhoneGap, which lets you use web programming tools to create apps for iPhone, Android, Blackberry and numerous other mobile platforms.



 
Comments
No Comments Found

About