Wednesday, December 30, 2009

Google Maps API and jQuery - Tips to Avoid Using Both

I often get visits on my blog from search engines with keywords like "google maps jquery". It made me realize that jQuery is now deeply anchored in our habits.

Then I was reviewing some stuff in the Google API the other day and I saw that the API has much to offer, we just don't know it.

Table of Contents



Introduction


Hi,

If you're only using jQuery with Google Maps, then maybe you're using equivalent functions in jQuery already available in the Maps API. So I think some people out there are including an extra library for basically nothing. On the other hand, if you're using jQuery everywhere on your site, then why not use it also for some of the Google Maps stuff? Nothing prevents you from doing so.

In this blog post, I'll try to show you some things you can do with the Maps API that you usually do with jQuery. I'll try to cover up things like event binding, AJAX, DOM manipulations, etc. I would like to mention also that this article is referring to the version 2 of the Maps API. All right here we go:

Doing things on page load


You can't do without it these days. Everyone's using it! So in jQuery it is:

$(document).ready(function(){
});

Remember? Yes, good! You can do exactly the same thing with the Maps API with:

GEvent.addDomListener(window, 'load', function(){
});

It is useful to initialize your maps in this manner instead of putting a initialize function directly in the onload attribute of your body tag. It is cleaner and your JavaScript code is less widespread.

Doing things on page unload


A quick tip by the way, instead of putting your cleanup function GUnload in the body's onunload tag attribute, you can do something less obtrusive like I said with:

GEvent.addDomListener(window, 'unload', GUnload);

Cool we covered the load/unload part of the DOM events that we all use frequently.

Binding to other DOM events


As you probably guessed, the previous sections could have been merged in this one because the page load/unload are DOM events. But I decided to create separate sections to cover them up in details.

Where were we... Oh yes, binding a handler (function) to any DOM event is easy in jQuery remember?

$('#button').click(function() {
});

In Maps API, it is just as easy (only a few characters more):

GEvent.addDomListener(document.getElementById('button'), 'click', function() {
});

That's it. It supports any DOM events.

Next, I want to show you how it's easy to simulate the one function of jQuery with the Maps API. It also shows you how to deregister a event handler:

var evt = GEvent.addDomListener(document.getElementById('button'), 'click', function() {
    // do something then
    GEvent.removeListener(evt);
};

The function GEvent.addDomListener() returns an object of type GEventListener which can be used to deregister the handler with GEvent.removeListener().

Before closing in on this section, it is possible to listen to an event handler on class instances. In other words, we can decide what the this keyword will be in our event handler. This is done this time with the bindDom function (and not the addDomListener function):

var obj = {
    Message: "Hello World"
};

GEvent.bindDom(window, 'load', obj, function() {
    alert(this.Message); // prints "Hello World"
});

This sample shows an alert message on page load. A more constructive example that's really useful when you're doing object oriented JavaScript would be:

function ClickCount() {
    this.ctr = 1;
    GEvent.bindDom(document, 'click', this, this.ShowAndIncrement);
};

ClickCount.prototype.ShowAndIncrement = function() {
    alert(this.ctr++);
};

var cc = new ClickCount();

The last snippet shows the click count done by the user on the document. Using this technique is great to keep a certain level of encapsulation. It also avoids the need of an external notifier whose job is only to tell others that something has just happened. The object is then self-sufficient.

Downloading files using AJAX


These days, a great number of websites are using some sort of AJAX. jQuery provides a lot of functions that encapsulates the XMLHttpRequest object:

jQuery.ajax( options )
load( url, data, callback )
jQuery.get( url, data, callback, type )
jQuery.getJSON( url, data, callback )
jQuery.getScript( url, callback )
jQuery.post( url, data, callback, type )

The Maps API doesn't provide an equally exhaustive list but have something to get the job done.

To simply download a file (on the same domain), there is the function GDownloadUrl():

GDownloadUrl("file.txt", function(data, responseCode) {
    alert(data); // prints the content of file.txt
});

If you want total control and flexibility over your requests, the Google Maps API have a cross-browser object that simulates the original XMLHttpRequest object (snippet taken from the Maps API documentation):

var request = GXmlHttp.create();
request.open("GET", "myfile.txt", true);
request.onreadystatechange = function() {
    if (request.readyState == 4) {
        alert(request.responseText);
    }
}
request.send(null);

But let's face it, a day to day usage of AJAX involves mainly XML files and JSON data. Let's see how we manage to get both formats using the Maps API.

Downloading and parsing an XML file


This one is pretty simple. There's a function to parse the data received by the function GDownloadUrl to an XML format: GXml.parse() (another snippet taken from the Maps API Documentation):

// Download the data in data.xml and load it on the map. The format
// we expect is:
// <markers>
//   <marker lat="37.441" lng="-122.141">
//   <marker lat="37.322" lng="-121.213">
// </markers>
GDownloadUrl("data.xml", function(data, responseCode) {
    var xml = GXml.parse(data);
    var markers = xml.documentElement.getElementsByTagName("marker");
    for (var i = 0; i < markers.length; i++) {
        var point = new GLatLng(parseFloat(markers[i].getAttribute("lat")),
                                parseFloat(markers[i].getAttribute("lng")));
        map.addOverlay(new GMarker(point));
    }
});

Downloading and parsing JSON data


It's also quite easy with GDownloadUrl to download JSON data. But this time the Maps API doesn't provide a function to parse the received data into a JavaScript object like the GXml.parse() function did with XML. Instead, we rely on the native eval() function:

// The JSON data format returned by the URL is
// {"Name":"Mike","Age":30}
GDownloadUrl("getJSON.aspx", function(data, responseCode) {
    // The data is in text format, we must wrap it in parenthesis
    // before evaluating it to avoid any problems caused by ambiguities
    // of the JavaScript syntax
    var json = eval('(' + data + ')');
    alert(json.Name); // alerts "Mike"
});

Pretty simple huh!?

DOM Manipulation


This time jQuery wins all the way. I mean, you have to use the native JavaScript functions to manipulate the DOM when you work with the Maps API. But it is not that hard. You can do simple things like:

var d = document.createElement('div');
d.appendChild(document.createTextNode('Hello World'));
document.body.appendChild(d);

You have a pretty good tutorial on manipulating the DOM here.

Conclusion


So you see that sometimes we include too much libraries in our webpages for basically nothing. If you use jQuery only with your Google Maps, then maybe this article will help you to get rid your webpages a few bytes and an additional download!? Who knows.

I'm putting time and effort on this blog and having you here is my reward. Make me feel better and better everyday by spreading the love with the buttons below! Also, don't hesitate to leave a comment. Thanks for reading!

Happy mapping!

Related Articles



See ya

6 comments:

Shawn said...

This plugin does a great job of making it really simple to add a Google Map to the page through a jQuery plugin. (http://www.mayzes.org/googlemaps.jquery.html)

Sundar said...

Hi - Great post! I know this post is over 2 years old but I thought I'd post a comment anyway. I basically have a question about how to use jQuery's event model in place of GEvent used in google api. I understand the part about jQuery's events being invoked on DOM elements. For example the bindDom method of GEvent follows this syntax:

GEvent.bindDom(document.getElementById("map_canvas"), "mouseout", this, function(){
GLog.write("GEvent handler for mouseout");
});

(where "map_canvas" is the id of the div containing the gmap).

This could be written in jQuery syntax as:

$("#map_canvas").bind("mouseout", function(){
GLog.write("jQuery handler for mouseout");
});

The question I have is what about events triggered on Maps API objects themselves instead of DOM elements. For example the gmap's "load" event (not the window load event) is fired when the map setup is complete (like zoom, map type etc.). The handler is written as:

GEvent.bind(this.gmap, "load", this, function(){
GLog.write("GEvent's handler for gmap's load event");
});


What would be the equivalent jQuery syntax for the above code?

I have tried:

$(this.gmap).bind("load", function(){
GLog.write("jQuery handler for load");
});

Not surprisingly, it doesn't work because this.gmap is not a DOM element. It's a Maps API object.

I hope I am articulating my question clearly. Could you provide some help/insight into this? I would appreciate it.

Unknown said...

Hi,

Thanks for reading and posting comments :)

In your first example, both jQuery and Google Maps are listening to an event triggered by the browser (DOM). The standard is well documented and there are native JavaScript functions that provides this functionality.

In the second example, the "load" event is triggered by a 3rd party JavaScript library (The Google Maps). This is called an "event" but this is not a DOM event like in the first example. This is just some method calls when something occurs in the library. So jQuery don't have any knowledge on how to listen to those custom events.

To listen to a Google Maps Api event with jQuery, you would have to know how the Maps Api is built and hook special pieces of code into it.. which would be hard and not portable.

I'm afraid you have to stick with the methods the Google Maps Api provides to bind yourself to events specifics to the Maps Api.

You had it right :)

Thank again for reading!

Sundar said...

Thanks for the prompt reply. And for clearing up my suspicion. :)

Mike Causer said...

Nice write up.

Vijay said...

Thanks for sharing this tips. Where, I have learned about Google maps. You may also learn about some interesting things in Google Maps. How to Styled Maps or Customize colors in Maps? For More info: http://www.labstech.org/styled-maps-google-maps-2014-06-26/

©2009-2011 Mike Gleason jr Couturier All Rights Reserved