Gmaps 101 - Continuing the Introduction to Google Maps & The Google Maps API V2 (Part 3)
Written by Eric Pimpler
19 June 2006
Our final article in this series will cover AJAX (Asynchronous JavaScript + XML) and how it is revolutionizing the user experience of web mapping applications. In addition, we’ll also cover various ways to geocode your data for Google Mapping applications.
In our first article in this three part series on the Google Maps API we discovered the fundamental programming constructs for developing web mapping applications with the hottest web mapping application development tool. The second articlecovered the Google Maps API Version 2 in greater detail including the most commonly used classes such as GMap2, GMarker, GLatLng and many others. We also explored the various map controls that can be placed on a Google Map including panning, zooming, and overview controls.
Geocoding
Plotting points of interest on a map is perhaps the most commonly used function in Google Maps. In Figure 1 you will see a visual example of an application that plots various address points on a map. To plot these points, you must have latitude, longitude coordinates for each point of interest or address. These coordinates are generated through a process known as geocoding which can be defined as an interpolation of the geographic location (latitude, longitude) of an address.
Let’s examine a real world geocoding example. Assume for a moment that we have a point of interest located at 150 Main St. What we need to do is determine the geographic coordinates for this address. In the real world, Main Street could be a road segment with an address range of 100 to 200. Geocoding software is used to interpolate the relative location of 150 Main St. in relation to the existing Main Street segment that runs from 100 to 200 Main St. In this simple case, the geocoding software would interpolate 150 Main St. as being exactly half way between 100 and 200 Main St. The software will then assign a latitude, longitude coordinate to this address. After an address has been geocoded it can then be plotted as a map overlay in Google Maps similar to what you see in Figure 1 where multiple addresses have been geocoded and plotted on the map.
The next logical question at this point would be “How do I obtain geocoding software so that I can geocode my addresses?” Google Maps does not currently supply a geocoding engine so you must find a third party software vendor or open source software. In this book we focus primarily on the freely available sources as well as a few hacks. We will briefly mention several of the more popular geocoding engines that can be purchased.
Let’s focus in more detail on the freely available geocoding services. We’ll also take a look at a hack or two that can be used to fill your geocoding needs. The first product we’ll look at is Yahoo’s new Maps Web Service which includes a Geocoding API. In addition, we’ll also introduce a hack that can be used to grab coordinates from Google Maps. Both of these solutions fit into the “single address match” category of geocoding. However, it would be possible to mold these services into batch geocoding services if you’re willing to invest the time into programming a solution.
Yahoo provides a Geocoding API that can be used to geocode addresses. This is a web service that you can call from your application. To obtain coordinates for an address you must supply various request parameters such as an AppID (obtained through Yahoo), Address, City, State, and Zip. The Yahoo Web Service will then perform an address match and return a response in XML format. This response will include a ResultSet, Result, Latitude, Longitude, Address, City, State, Zip, and Country. You can then plot this address on a Google Map and/or store it in a database or XML file. The Yahoo Geocoding API is a free web service provided you use it for non-commercial purposes. Commercial usage of the API is also available. Although this web service is free, Yahoo does limit you to 50,000 queries per day which shouldn’t be a problem for the vast majority of applications.
Now let’s take a look at a hack that you can use to obtain address coordinates directly from Google. As we mentioned in a previous slide, Google does not currently provide a geocoding API, although I expect they will in the not too distant future. There is however an unofficial way of obtaining the longitude, latitude coordinates from Google. This requires two separate calls to Google Maps. The first call obtains the coordinates without the map, and the second call gets the map, and plots the point coordinates obtained in the first call. In this example I’m going to use ColdFusion as the language for accomplishing this hack, but you can use whatever language you’re most comfortable with to accomplish the same thing. Let’s take a look at how this is done.
The first step in our hack is to pass an address to Google Maps and in return Google will generate a latitude, longitude coordinate for the address. However, using certain ColdFusion tags we can limit the return from Google to output only the result, not the map. Our first step is to use the ColdFusion <cfset> tag to declare a variable called “addr” which will hold an address that we’ll pass to Google Maps. This address is hard coded in our example, but you could easily set it up to hold the contents of form controls that the user has dynamically entered. We then use the ColdFusion <cfhttp> tag to query Google Maps with the “addr” variable we declared and populated. Notice that we make an http call using the “get” method with a URL that points to Google Maps and contains the “addr” variable. We then use the ColdFusion <cfhttp.filecontent> tag to output the results of the query. Here is the full code example for passing the address to Google Maps.
If you run this code from a web page it will return a seemingly empty page, but through View…Source in your web browser you can see the information that was returned. Part of the information contains the latitude and longitude of the address as you can see below:
After the initial return I can parse out the latitude, longitude coordinates and then make a second call to Google Maps to zoom to this address. This technique of dynamically obtaining address coordinates is something of a hack and since it requires two calls to Google Maps it could potentially have a negative affect on the performance of your application so you need to keep this in mind. Although the code examples you’ve just seen were written in ColdFusion, the same concept applies to whatever language you’re using.
Here’s the ColdFusion code I used to parse the latitude and longitude from the initial call:
If the Yahoo and Google solutions don’t fit your needs there are a number of other free geocoding services available for non-commercial uses. One web service that I recommend is geocoder.us which offers a Web Service that allows you to purchase 20,000 lookups for $50. The data used by geocoder.us is provided by the US Census Bureau so you will be limited to address requests within the US. A RESTful web service request to geocoder.us could take the form:
The return XML document would look something like:
You could then parse this data to plot the point on a Google Map.
In this section you will see a partial list of the most commonly used commercial geocoding software solutions available on the market. Each of these vendors provide commercial solutions that meet your batch and single address geocoding needs. Please feel free to visit the links provided in this slide.
At this point we’ve covered all the major bases related to the Google Maps API save for one all important topic; AJAX. AJAX is what makes Google Maps such an attractive platform for building interactive web mapping applications. The traditional web mapping application model works something like this: Most user actions in the interface trigger an HTTP request back to a web server. The server does some processing — retrieving data, crunching numbers, talking to various legacy systems — and then returns an HTML page to the client. It’s a model adapted from the Web’s original use as a hypertext medium, but what makes the Web good for hypertext doesn’t necessarily make it good for software. The traditional approach to web application development makes sense from a technical point of view, but from a practical standpoint it leaves much to be desired in that it forces the user to wait while the server completes its processing and refreshes the display with a new page. AJAX changes this traditional model.
AJAX (Asynchronous JavaScript + XML) isn’t a technology, but rather several technologies working in concert to produce the capability of creating highly interactive, rich, and responsive web applications. AJAX incorporates the following technologies:
standards-based presentation using XHTML and CSS
dynamic display and interaction using the Document Object Model
data interchange and manipulation using XML and XSLT
asynchronous data retrieval using XMLHttpRequest
JavaScript to bind everything together
An AJAX application eliminates the start-stop-start-stop nature of interaction on the Web by introducing an intermediary — an AJAX engine — between the user and the server. It seems like adding a layer to the application would make it less responsive, but the opposite is true. Instead of loading a webpage, at the start of the session, the browser loads an AJAX engine — written in JavaScript and usually tucked away in a hidden frame. This engine is responsible for both rendering the interface the user sees and communicating with the server on the user’s behalf. The AJAX engine allows the user’s interaction with the application to happen asynchronously — independent of communication with the server. So the user is never staring at a blank browser window and an hourglass icon, waiting around for the server to do something.
Part of the AJAX equation is the XMLHttpRequest object which is the technical component that makes asynchronous server communication possible. Basically, the XMLHttpRequest object provides a method for client side JavaScript to make HTTP requests. Even though the object is called XMLHttpRequest, this object is not limited to being used just with XML. It can request or send any type of document. So what’s the big deal you say? Well, here is a partial list of what can be accomplished through this object.
Call server-side scripts without refreshing the page
This ability alone is a huge benefit for web application interactivity.
Typically you would call server-side scripts in HTML through forms. However, forms require a page reload which is not user friendly.
Calling server-side scripts through XMLHttpRequest allows you to call the script without refreshing the page.
Load and read XML files
This is important for Google Maps applications because it allows you to read in points of interest stored in XML files and plot them to the map without refreshing the display.
Make HEAD requests
Does a URL exist?
Let’s take a closer look at the XMLHttpRequest object for more details on how it works. The GXmlHttp object in the Google Maps API is used to create a cross-browser XmlHttpRequest so you’ll be using the same methods and properties. New instances of the XMLHttpRequest class are created in slightly different ways depending upon the browser. For Safari and Mozilla browsers, the following call creates a new instance of XMLHttpRequest.
For IE, you’ll need to pass in the name of the object to the ActiveX constructor as you see below. In Google Maps the GXmlHttp class exports a factory method called GXmlHttp.create( ) that creates a cross-browser XmlHttpRequest instace so you won’t have to distinguish between the browser types when creating mapping applications built with Google. Object Methods All instances of the XMLHttpRequest object share a list of methods and properties.
Table 1. Common XMLHttpRequest Object Methods
Method
Description
abort()
Stops the current request
getAllResponseHeaders()
Returns complete set of headers (labels and values) as a string
String version of data returned from server process
responseXML
DOM-compatible document object of data returned from server process
status
Numeric code returned by server, such as 404 for "Not Found" or 200 for "OK"
statusText
String message accompanying the status code
The readyState property is used inside the onreadystatechange event handler to determine the status of the request. One of five states can be assigned to the readyState property.
0 = uninitialized
1 = loading
2 = loaded
3 = interactive
4 = complete
The state we are interested in is a value of 4 which indicates that the request is complete and we now have a response from the server. In addition to checking the readyState property we also need to check the status or statusText properties to get confirmation that the transaction completed successfully before performing an operation on the results. A value of 200 in the status property or OK in the statusText property indicate success. Assuming that we have a readyState value of 4 and a status of 200 we can proceed with processing the response. Data returned in the response can be accessed through the responseText or responseXML properties. The responseText property provides only a string representation of the data while the responseXML property gives us access to data that is returned in a well-formed XML DOM object that can then be parsed using node tree methods and properties.
Now that you understand the basic functionality provided by the XmlHttpRequest object we’ll examine the GXmlHttp class provided by the Google Maps API. Really, the GXmlHttp object is just XmlHttpRequest in disguise, but with the added benefit of being cross browser compliant. All the methods and properties are the same as what you’ll find with XmlHttpRequest. The only real difference is how you create the instance as you’ll see below. This line of code is used to create a cross browser compliant instance of XMLHttpRequest which can then access the methods and properties we detailed above. GXmlHttp is used in Google Maps applications primarily to read XML files containing points of interest that need to be plotted on a map. Let’s take a look at a code example that will show you how to take advantage of this class. For this example, assume that you have an XML file containing points of interest defined by their latitude/longitude coordinates. This example contains only a very small amount of data, but in a real application you would probably include many other data attributes beyond just the coordinates. Assume that you have an XML file called data.xml containing the following data stored on your web server: Now, let’s create an instance of GXmlHttp, download and read the XML file, and then plot these coordinates on a map. The first line of code simply creates a cross browser instance of XMLHttpRequest. We then use the open(‘Get’, ‘data.xml’, true) method to assign the parameters that will be used in the request. Note that since we are requesting data, we use the “GET” method. In the event that you need to send data to the server you’d use the “POST” method. The second parameter (data.xml) specifies the file that we are going to open, and the third parameter (true) flags this as an asynchronous request. In other words, processing of the code will continue once the send( ) method is called. A value of false in this parameter would hold up processing of the code until the request/response cycle is complete. In the third line of code we set the onreadystatechange event handler equal to a function that will be called when the readyState property changes. We’re really only interested in a readyState of 4 which indicates that the request is complete and we now have a response from the server. Once the readyState code is set to a value of 4 we then do a second test to ensure that the request was successful, and this is indicated by a value of 200 in the request.status property. At this point we know that the request has been received and a valid response has been returned. In this case since we’ve requested an XML file (data.xml) we’ll need to use the responseXML property to get an instance of the XML DOM object. Once we have this object we can use getElementsByTagName to return an array of markers which we then parse and plot on a Google Map similar to Figure 3.
The GDownloadUrl( ) function is new to Version 2 of the Google Maps API and provides a convenient way to retrieve a resource identified by a URL. Typically this function is used to fetch the contents of a non-XML formatted text file. For instance, if you frequently use ESRI’s ArcMap product you will know that it is possible to export tabular data as a comma delimited text file (.csv). You could then use GDownloadUrl to read this file. In addition to GDownloadUrl you will also need to create a separate function that processes the file that has been downloaded by GDownloadUrl. The following code shows how you would call GDownloadUrl to download a comma delimited file called test_points.txt, process the file, and plot each of the points on a map.
The file is read asynchronously and the data is passed into the specified function as one long text string. GdownloadUrl uses an XmlHttpRequest object to execute the request.
In Version 2 the Google Maps API provides a new GLog namespace that contains some static methods that allow you to write log messages to a log window similar to what you see in Figure 4. This enables basic debugging of your code through the ability to write debug messages. The first call to a GLog method opens a div (called the log window here) anchored to the lower left corner of the browser window. At the top of the log window is a title bar with two action links. The clear link will erase all messages from the log windows. The close link will close the log window. The log window will not reopen after it has been closed. The main part of the log window is a scrolling text area where messages and timestamps are displayed. The window scrolls to display the most recently written message. The text in this area is selectable, so it can be copied to save the log. The following methods are available on the GLog namespace:
write(text)
writes a text message into the log window.
writeUrl(url)
writes a hyperlink to the URL into the log window. You can click, shift-click or ctrl-click the URL to open the link in this or another window or tab.
writeHtml(html)
writes a fragment of html text into the log window.
This simple log window was created with the following line of code:
By now you should have a good understanding of the basic functionality provided by the Google Maps API and you’re probably ready to create your own Google Maps application or “Mashup” as they are called. There are many examples of Google Maps Mashups on the web so you should spend some time getting familiar with the many fun and practical applications. Mick Pegg’s Google Maps Mania blog is perhaps the most comprehensive listing of mashups and other resources related to Google Maps. Spend some time at Mike’s blog and you’ll quickly understand that you are only limited by your imagination.
Author Information Mr. Pimpler is the owner of Geospatial Training & Consulting, LLC, a provider of virtual and instructor led GIS training opportunities and the author of its popular virtual training course “Google Maps For Your Apps!” and the new PDF book “Google Maps API: The New World of Web Mapping”. For more information on the Google Maps API or any other training opportunity provided by GeoSpatial Training & Consulting, please visit our website at http://www.geospatialtraining.com
HxGN Live - The Hexagon Global Network - Learn about surveying, mapping, laser scanning and geospatial solutions from Leica Geosystems. June 3-6, 2013, Las Vegas, Nevada
Join us at GIS for Government 2013 taking place June 24-26, 2013 in the Washington, DC Metro Area to find out everything you need to know about GIS. Click here for more information