Friday, June 8, 2007

GMarkers are everywhere! Where do I look?

I found a common paradigm in programming GMap applications, you have a collection of markers to add to the map and you want to zoom the map and center it in such a way to show all markers at the closest zoom level possible.

GBounds over tall buildings!

All solutions to this problem involve some intense calculations, so I researched the API documentation and found that the GBounds class does this work for you. pass it a collection of points and it will tell you the four max points of a plane that will encompass all points, perfect! ... not quite.

Hobbling over the API

Unfortunately a GBounds object doesn't give us all the necessary information, but its got enough to get us there. Take the min and max coordinates to form the north east and south west GLatLng objects and create a GLatLngBounds object which will then allow you to retrieve necessary information.

GLatLngBounds on point

Now that you've got your GLatLngBounds object you can find the center by the method "getCenter()" and the zoom is found by passing the GLatLngBounds object to the method "getBoundsZoomLevel" of the map object you want to position.

An implementation, GOverlayOverseer

I've taken these ideas and created my own version of the "GMarkerManager" that is based on the ideas of hiding an overlay based on parameters of minZoom and maxZoom. I've done some things very differently though, first is the value of minZoom and maxZoom. minZoom in my class represents the min zoom value that will be considered, such that an object with a minZoom of 10 will not be seen when the viewer's zoom level is less than 10, remember 1 represents no zooming, you're looking at the entire world. maxZoom is the micro zoom, meaning that if the zoom level of the map is greater than the objects specified zoomLevel it will be hidden. This doesn't make a whole lot of sense for a GMarker, which is one point on the map but this feature becomes increasingly valuable as you begin working with polygons and polylines.

View attempts to concretely solve this problem, for good.

Static Inheritance

There have been great strides in the javascript user community of morphing the language to be more structured and accomodate for more Object oriented design patterns. One of the most widely used and well understood pattern is inheritance. The idea of a "child"(sub) inheriting properties from its "parent"(super) and in some cases over ruling some properties for its own benefit but majorily relying on what it has inherited from its parent class.

Prototype's inheritance

Prototype is a wonderful javascript library that I have based a lot of my web application development on and without a doubt has saved me an inordinate amount of time, totally recommend it to all web developers building rich applications. It handles inheritance a multitude of ways and if you would like to read more about how to build classes using it view the javascript class entry.

Back on course with the topic, Prototype uses Object.extend to allow for one object to "inherit" properties from another object. Using this we can "extend" an object from another. This is but javascript doesn't support anyform of visibility scope operator(public, protected, private) such that a subclass will override all methods from its super class such that when you call the initialize function it instantiates none of the super's properties.

Use New to Initialize

Justin Palmer writes a very interesting article about how to handle some of those issues by extending the class from a new instantiation of the super. This works great as long as you don't have to work with the DOM ...at all. He brings this point up in the blog and plays around with other examples of how and when this would fail.

A Solution to Last the Generations

I keep hearing the term "Syntactic sugar".. if you're looking for sweets im sorry to say i have no such sugar. Although I do provide a solution to maintain the super's functionality in sub classes and their sub classes. The idea is that you can statically leverage the super's respective function and apply the current object to it.





var Super = Class.create();
var Sub = Class.create();

Object.extend(Super.prototype,
{
name : "Super",
initialize : function(param){


},
inheritance : function(){

this.name += " inheritance is great";

}

}
);
Object.extend(Object.extend(Sub.prototype, Super.prototype),
{
name : "Sub",
initialize : function(obj){

this.obj = $(obj);
Event.observe(this.obj, "click", this.inheritance.bindAsEventListener(this));

},
inheritance : function(){
Super.prototype.inheritance.apply(this, arguments);

alert(this.name);

}


}
);





It isn't the prettiest way to inherit the functionality but it beats the alternative of having to re-write the code. Meaning that when the Super's inheritance function changes, the sub won't have to be updated. It doesn't get Dean his "super" operator but its not bad. Anyways have a good one!