Geolocation + Google Closure = Confusion

In some of my spare time last weekend I was playing around with Google Closure, a JavaScript library that I think is radically different from the more traditional libraries I’m used to like jQuery or Prototype.  Google Closure isn’t really about enhancing your existing application with some snazzy JavaScript effects, I guess it can do that too, but to me it’s much more an application design framework than a quick and dirty tool to made some divs fade in and out easily.

Writing the correct JavaScript wasn’t too hard to get down, the examples provide good starting points to learn their object oriented syntax.  The trouble comes when you start pushing much beyond the simple examples.  Unlike jQuery there isn’t an example published for every function and the internet isn’t really swarming with information to help you sort things out.  I suspect the people that use closure know what they’re doing, and the people that don’t just hack in jQuery.  I almost gave up and went to jQuery a few times, but I stuck it out.

I wanted to use my browser’s HTML5 geolocation feature in my application so I could track my phone.  This was going to require a callback function, since the navigator.geolocation calls are non-blocking.  In traditional Javascript this is dead simple, you can just type the function name or just put an anonymous function like function(e){ … } right there and it works.  Not so in closure land, well at least not that simply.

Callbacks – In Google Closure, when you want a callback to reference a specific instance of an object you have to bind them together.  So if I want the GPS update to call back to the specific GPS object that’s holding it, my code might look something like this:

example.Gps.prototype.start = function() {
  navigator.geolocation.getCurrentPosition(goog.bind(this.update, this));
};

Which is english creates a function ‘start’ for an instance of a GPS object.  When the function start is called like myGps.start(); we call the standard HTML5 option for getting the current position.  When we have that position ready, we dispatch it to the instance’s update method (i.e myGps.update(position); is called).  The critical line is goog.bind(function, context), without that the update function might be called in context of the Window or Document or something weird.  Binding it forces it to stick with the currently instantiated object.

HTML5 Externs – Google Closure can also compile your code into a super minified version.  If you use the advanced optimizations flag I think the compiler will even go through and prune unused execution paths and optimize existing code around variable types.  To tell the compiler what types different variables are, you have to spruce up your code (or litter it with comments if you’re not in a good mindset) with JSDoc tags to annotate everything.  I don’t actually know how this works, but I think the more you annotate the better you can do.  This is really easy when you’re working with numbers, strings, arrays, etc.  The examples in the documentation tell you exactly what to do.

I ran intro trouble trying to figure out how to handle the custom objects associated with the navigator.geolocation calls.  The compiler would throw errors and warnings not understanding what type my var options = {enableHighAccuracy: true; } object was and the documentation how to reference the external types was weak at best.  Searching around showed me that the compiler had a definition file describing the possible types and returns and with a little luck, I was able to extrapolate that into JSDoc tags that seem to do the trick.

var options = (/** @type {GeolocationPositionOptions} */
    {enableHighAccuracy: true,
      maximumAge: 1000,
      timeout: 2000});
/**
* Write a good comment here describing what the update callback
* does when called.
* @param {GeolocationPosition} geoposition A position coming from the GPS.
*/
example.Gps.prototype.update = function(geoposition) {
  //Do Something here with the geoposition
};

As you can see, the ‘type’ tends to line up closely with what the folks over at W3C use to describe the object which makes sense… it was just quite tough to figure out without any pointers or examples.

If I remember, I’ll post what I learned about Event Triggers soon!