<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>DaveOnCode &#187; google maps</title>
	<atom:link href="http://www.daveoncode.com/tag/google-maps/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.daveoncode.com</link>
	<description>Objective C, iOS and more programming stuff</description>
	<lastBuildDate>Mon, 19 Dec 2011 12:11:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Playing with Google maps API &#8211; part three: Geocoding and custom overlay</title>
		<link>http://www.daveoncode.com/2008/11/26/playing-with-google-maps-api-part-three-geocoding-and-custom-overlay/</link>
		<comments>http://www.daveoncode.com/2008/11/26/playing-with-google-maps-api-part-three-geocoding-and-custom-overlay/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 13:45:14 +0000</pubDate>
		<dc:creator>Davide Zanotti</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[custom overlay]]></category>
		<category><![CDATA[geocoding]]></category>
		<category><![CDATA[geolocation]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[GOverlay]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[prototype]]></category>

		<guid isPermaLink="false">http://daveoncode.wordpress.com/?p=65</guid>
		<description><![CDATA[The main feature provided by the Google maps API, is the ability to convert an human readable location, such &#8220;Milan, Italy&#8221; to a geographic location represented by latitude and longitude, this process is called geocoding. The GClientGeocoder is the class which provide this service, through the method getLatLng() which accepts two arguments: a string representing [...]<div class="addthis_toolbox addthis_default_style addthis_32x32_style" addthis:url='http://www.daveoncode.com/2008/11/26/playing-with-google-maps-api-part-three-geocoding-and-custom-overlay/' addthis:title='Playing with Google maps API &#8211; part three: Geocoding and custom overlay ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></description>
			<content:encoded><![CDATA[<p>The main feature provided by the Google maps API, is the ability to convert an human readable location, such &#8220;Milan, Italy&#8221; to a geographic location represented by latitude and longitude, this process is called geocoding. The <strong><em>GClientGeocoder</em></strong> is the class which provide this service, through the method <strong><em>getLatLng()</em></strong> which accepts two arguments: a string representing an address and a callback function that will be called once the coordinates are retrieved. If the address will be successful located, the callback function will be invoked by passing a <strong><em>GLatLng</em></strong> object as argument, otherwise the function will receive a <em><strong>null</strong></em>. <strong><em>GLatLng</em></strong> is an object which represents a geographic location (latitude and longitude).</p>
<p>To request a geolocation for a given address we use a similar code:</p>
<p><span id="more-65"></span></p>
<pre>
var address = "Milan, Italy";
var locator = new GClientGeocoder();

locator.getLatLng(address, function(point) {
    if (point) {
        alert(address + " is located at: " + point.lat() + " - " + point.lng());
    } else {
        alert("Unable to locate " + address);
    }
});
</pre>
<p>In the example above we simply alert the located address, after testing for a defined point and by using the two simple getters methods (that due to their type of method, Google should naming them getLat() and getLng()): <strong><strong>lat()</strong></strong> and <strong><em>lng()</em></strong>. Usually we use the callback function to add overlay to the map and to place them in the right place&#8230; and is what we are going to do!</p>
<p>There are several types of overlay (markers, polylines, tiles&#8230;), the most common is the <em><strong>GMarker</strong></em> (the red balloon that Google places over the searched address). However the most interesting part is to realize custom overlay, which will have our desired look, will display data related to our application/web site and will provide as many features as we need.</p>
<p>Create a custom overlay is like to create a custom control (as showed in the &#8220;<a href="http://daveoncode.wordpress.com/2008/11/17/playing-with-google-maps-api-part-two-create-custom-controls/">part two</a>&#8220;). Differently from a custom control however, we have to extend the <strong><em>GOverlay</em></strong> class and implement its 4 methods: <em><strong>initialize()</strong></em>, <strong><em>remove()</em></strong>, <strong><em>copy()</em></strong> and <strong><em>redraw()</em></strong>.</p>
<p>The first method has the duty to place an HTML node inside the map, the second as the opposite must remove that node, the third has simply to return an instance of our custom overlay with the same settings (in a few words it must return a copy of its self) and finally the forth method is used to adjust the position of the overlay whatever required. So the code will be something like:</p>
<pre>
// our "CustomOverlay" constructor
function CustomOverlay(settings) {
    // configures the instance with the required settings
}

// extends GOverlay class
CustomOverlay.prototype = new GOverlay();

// implements initialize()
CustomOverlay.prototype.initialize = function() {
    // creates an HTML element and appends it to the map'c container
}

// implements remove()
CustomOverlay.prototype.remove = function() {
    // removes the node from the DOM
}

// implements copy()
CustomOverlay.prototype.copy = function() {
    // returns a new instance of "CustomOverlay" with the same attributes
}

CustomOverlay.prototype.redraw = function(force) {
    if (force) {
        // adjust the position of the HTML element created by initialize()
    }
}
</pre>
<p>The <strong><em>redraw()</em></strong> deserves special attention, because it <strong>MUST</strong> handle the &#8220;force&#8221; argument, which is a boolean that indicates if we have to recalculate the position of the element or not. <strong>Without checking &#8220;force&#8221;, the code inside the method will be executed several times needless, causing possible memory leaks and browser instability!</strong>.</p>
<p>Let&#8217;s see how to use a <strong><em>CustomOverlay</em></strong>, the <strong><em>GClientGeocoder</em></strong> and a bit of jQuery, in order to realize a small Javascript application that:</p>
<ul>
<li>Read a file containing a list of addresses to locate and a value for each address which indicates an hypothetical numbers of participants to an event</li>
<li>For each address requires the geocoding service</li>
<li>For each address place a custom overlay on the map (according to its location) which will shows the numbers of participants and will looks different due to that number</li>
<li>Display a progress bar indicating the status of the &#8220;geocoded&#8221; address and disable the drag of the map while loading</li>
</ul>
<p>For convenience the file containing the address will be a text file with a json formatted array of objects:</p>
<pre>
[
	{name: "Agrigento", quantity: 6},
	{name: "Alessandria", quantity: 8},
	{name: "Ancona", quantity: 5},
...
]
</pre>
<p>In my example each object has the property &#8220;name&#8221; which indicates the name of an Italian province and &#8220;quantity&#8221; which represents the number of participants to an hypothetical event from that city.</p>
<p>This is instead the <strong><em>CustomOverlay</em></strong>&#8216;s code (comments inside the code describe all the logic behind):</p>
<pre>
// custom overlay constructor
function CustomOverlay(settings) {

	this.parentMap = settings.parentMap; // a reference to the map
	this.position = settings.position; // the geolocation of the address
	this.width = settings.width || 43; // elements's with
	this.height = settings.height || 15; // elements's height
	this.quantity = settings.quantity; // the number of partecipants to show

}

// custom overlay class extends the GOverlay class
CustomOverlay.prototype = new GOverlay();

// initialize the custom overlay object
CustomOverlay.prototype.initialize = function() {

	// the overlay element will have a shape of an arrow
	// this variable will be used in order to associate a
	// custom CSS class
	var arrowStyle;

	// determining the style of the label based on quantity value
	if (this.quantity  20 &amp;&amp; this.quantity &lt; 50) {
		arrowStyle = "yellow";
	} else {
		arrowStyle = "red";
	}

	// div that rapresents the overlay object
	this.overlayBox = document.createElement("div");

	// set overlay's size
	this.overlayBox.style.width = this.width + "px";
	this.overlayBox.style.height = this.height + "px";

	// set overlay's content
	this.overlayBox.innerHTML = this.quantity;

	// set the className to apply the stylesheet
	this.overlayBox.className = "custom_overlay_object arrow_" + arrowStyle;

	// add the html element to the dom
	this.parentMap.getPane(G_MAP_MAP_PANE).appendChild(this.overlayBox);

}

// removes the object from the dom
CustomOverlay.prototype.remove = function() {

	this.overlayBox.parentNode.removeChild(this.overlayBox);

}

// returns an object equal to the current one
CustomOverlay.prototype.copy = function() {

	return new CustomOverlay({
		parentMap: this.parentMap,
		position: this.position,
		width: this.width,
		height: this.height,
		quantity: this.quantity
	});

}

// place the object in the right position
CustomOverlay.prototype.redraw = function(force) {

	// we use redraw() only if we really need it!
	if (force) {

		// get the pixels position of the overlay based on the geographic latidute and longitude
		var elementPosition = this.parentMap.fromLatLngToDivPixel(this.position);

		// positioning the overlay
		this.overlayBox.style.left = (elementPosition.x - parseInt(this.width+4)) + "px";
		this.overlayBox.style.top = (elementPosition.y - parseInt(this.height/2)) + "px";

	}

}
</pre>
<p>To request several geocoding successfully, we have to set an interval for the use of <strong><em>GClientGeocoder</em></strong>&#8216;s method <strong><em>getLatLng()</em></strong>, that after some tests I realized that can&#8217;t never be less then 150 milliseconds, otherwise we will get errors from Google (<strong><em>we can&#8217;t simply use getLatLng() into a loop!</em></strong>). I&#8217;ve realized a js class which read the previously cited text file and manage this callings to <strong><em>getLatLng()</em></strong> at a given interval&#8230; I&#8217;ve called it DataManager, the code is the following (once again the comments inside describe the logic behind):</p>
<pre style="background-repeat:repeat;">
function DataManager(settings) {

	// Customizable parameters
	this.dataUrl = settings.dataUrl; // the url of the txt file to read
	this.gMap = settings.gMap; // a reference to the map

	// Internal parameters
	this._geoLocator = new GClientGeocoder(); // a reference to a GClientGeocoder instance
	this._processed = 0; // a counter for the processed requests
	var instance = this; // a reference to the current instance

	this._renderProgressBar = function() {

		// create a new HTML node for the progress bar
		var pb = document.createElement("div");

		// sets its ID
		pb.id = 'dm_progress_bar';

		// sets its content
		pb.innerHTML = '&lt;div id="dm_bar_container"&gt;&lt;div id="dm_bar"&gt;&lt;/div&gt;;&lt;div id="dm_info"&gt;Loading 0 of ? location(s).&lt;/div&gt;&lt;/div&gt;';

		// adds the node to the map's container
		// (returned from getPane(G_MAP_MAP_PANE))
		instance.gMap.getPane(G_MAP_MAP_PANE).appendChild(pb);

	}

	this._removeProgressBar = function() {

		// get a reference to the html element representing the progress bar
		var pb = document.getElementById("dm_progress_bar");

		// removes the node from the map's container
		// (returned from getPane(G_MAP_MAP_PANE))
		instance.gMap.getPane(G_MAP_MAP_PANE).removeChild(pb);

		// activates the drag feature
		instance.gMap.enableDragging();

	}

	this._processData = function(data) {

		// get the progress bar node
		var bar = document.getElementById("dm_bar");

		// get the node containing the "load x of y" message
		var info = document.getElementById("dm_info");

		// reference to the current width of the progress bar
		var barWidth = parseInt(bar.style.width) || 0;

		// calculates the new with based on the loaded data
		var newBarWidth = Math.round(barWidth + 200/data.length);

		// requires the geocoding for each address
		instance._geoLocator.getLatLng(

			// access to the address
			data[instance._processed].name,

			// callback funtion used by getLatLng()
			function(point) {

				// add the overlay to the dom
				instance.gMap.addOverlay(new CustomOverlay({
					parentMap: instance.gMap,
					position: point,
					quantity: data[instance._processed].quantity
				}))

				// increase the processed locations
				instance._processed++;

				// sets the new with for the progress bar
				bar.style.width = newBarWidth &gt; 200 ? 200 : newBarWidth + "px";

				if (instance._processed &lt; data.length) {

					// if the data process is not finished, display the current status
					info.innerHTML = ["Loading: ", instance._processed, " of ", data.length, " location(s)."].join("");

				} else {

					// otherwise communicates that we have finished..
					info.innerHTML = "Loaded! ;-)";

					// ...and after 1/2 second removes the progress bar
					setTimeout(instance._removeProgressBar, 500);

				}

				// if there are more locations to process call this method again every
				// 150 milliseconds. (this._processData() is a recursive function)
				if (instance._processed &lt; data.length) {
					setTimeout(function() {
						instance._processData(data);
					}, 150);
				}

			}

		)

	}

	// display the ajax error
	this._showError = function() {

		alert("error!");

	}

	// get the data
	this.getData = function() {

		// display the progress bar
		instance._renderProgressBar();

		// uses jQuery to load the txt file via Ajax
		$.ajax({
			type: "GET",
			url: instance.dataUrl,
			dataType: "json",
			cache: false,
			success: instance._processData,
			error: instance._showError
		});

	}

}</pre>
<p>In the page containing the map the necessary code to run the sample application is:</p>
<pre>function load() {

    if (GBrowserIsCompatible()) {

        var map = new GMap2(document.getElementById("map"));

        map.disableDragging();

        map.setCenter(new GLatLng(41.65, 12.5), 6);

        var manager = new DataManager({
            dataUrl: "/gmaps/assets/js/data.json",
            gMap: map
        });

        manager.getData();

    }

}
</pre>
<p>The working example is here: http://daveoncode.yourfreehosting.net/google_maps_custom_overlay/index.html (unfortunately due to the yourfreehosting service, the load of the page is slow and difficult :P).</p>
<p><em>A brief note: although the scheduled geolation requests and the progress bar are cool to see, in a real application would be a best practice to realize a static file which already contains the various geolocations, in order to realize a faster application and avoid the google&#8217;s defined limits for geocoding requests.</em></p>
<div class="addthis_toolbox addthis_default_style addthis_32x32_style" addthis:url='http://www.daveoncode.com/2008/11/26/playing-with-google-maps-api-part-three-geocoding-and-custom-overlay/' addthis:title='Playing with Google maps API &#8211; part three: Geocoding and custom overlay ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.daveoncode.com/2008/11/26/playing-with-google-maps-api-part-three-geocoding-and-custom-overlay/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Playing with Google maps API &#8211; part two: Create custom controls</title>
		<link>http://www.daveoncode.com/2008/11/17/playing-with-google-maps-api-part-two-create-custom-controls/</link>
		<comments>http://www.daveoncode.com/2008/11/17/playing-with-google-maps-api-part-two-create-custom-controls/#comments</comments>
		<pubDate>Mon, 17 Nov 2008 14:11:19 +0000</pubDate>
		<dc:creator>Davide Zanotti</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[controls]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[navigation]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://daveoncode.wordpress.com/?p=50</guid>
		<description><![CDATA[Today we are going to see how to realize custom controls to add to our Google maps powered map. The only concept that should be clear, in order to achive the goal, is what prototype is and why we must use it. Javascript is not a really object oriented language, so we can&#8217;t really talk [...]<div class="addthis_toolbox addthis_default_style addthis_32x32_style" addthis:url='http://www.daveoncode.com/2008/11/17/playing-with-google-maps-api-part-two-create-custom-controls/' addthis:title='Playing with Google maps API &#8211; part two: Create custom controls ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></description>
			<content:encoded><![CDATA[<p>Today we are going to see how to realize custom controls to add to our Google maps powered map.</p>
<p>The only concept that should be clear, in order to achive the goal, is what prototype is and why we must use it.</p>
<p>Javascript is not a really object oriented language, so we can&#8217;t really talk about classes and subclassing (using <strong><em>extends </em></strong> like in Java or Actionscript), but however we can create functions that act as constructor for new js objects, and we can inherit properties from an object to another by using the prototyping technique.</p>
<p><span id="more-50"></span></p>
<p>Let&#8217;s consider a simple Javascript constructor function, that can be used to create an Animal object:</p>
<pre>function Animal(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;

    this.getInfo = function() {
        alert("Name: " + this.name + "\nAge: " + this.age + "\nSex: " + this.sex);
    }
}</pre>
<p>To extend the Animal class with a Dog class, we have to define the Dog constructor:</p>
<pre>function Dog(name, age, sex, barkPower) {

    Animal.apply(this, arguments);

    this.barkPower = barkPower;

    this.bark = function() {

        var barkBuffer = [this.name, " says: "];

        for (var i=0; i&lt;this.barkPower; i++) {
            barkBuffer.push("bark! ");
        }

        alert(barkBuffer.join(""));

    }

}</pre>
<p>and then prototyping it in this way:</p>
<pre>Dog.prototype = new Animal();</pre>
<p>The Animal.apply() call inside Dog, is like to use super() in Java to call the SuperClass constructor.<br />
Now our Dog has the same methods and properties of Animal, for example we can use the <strong><em>getInfo() </em></strong> method, in addition to <strong><em>bark()</em></strong>:</p>
<pre>var laika = new Dog("Laika", 5, "F", 8);
laika.getInfo();
laika.bark();</pre>
<p>Now, let&#8217;s put the prototyping technique in practice, in order to create a custom control for our map.<br />
The Javascript class that represents a google map&#8217;s control is <strong><em>GControl</em></strong>, so if we want to make something of us own, we must extend that class. Furthermore we have to implements at least 2 methods: <strong><em>initialize()</em></strong> and <strong><em>getDefaultPosition()</em></strong>, in practice the GControl is to be considered an interface.<br />
The first method, must add a DOM node (a graphic button or whatelse represents our control) to the map and return it (with <strong><em>return</em></strong>), the second must return an instance of <strong><em>GControlPosition</em></strong> which is used to place the DOM node (our control) in the right position.<br />
Our goal is to create a custom map navigation (ie: move to north, move to south, move to east and move to west), so we will create 4 js classes that will extend <strong><em>GControl</em></strong> and implements the 2 methods. We call these classes respectively: <strong><em>GoUpButton</em></strong>, <strong><em>GoDownButton</em></strong>, <strong><em>GoLeftButton</em></strong> and <strong><em>GoRightButton</em></strong> .<br />
Let&#8217;s see how <strong><em>GoUpButton</em></strong> is structured and how it works (others buttons will differ only for their position and click handler):</p>
<pre>function GoUpButton(map) {

    this.map = map;
    this.button = document.createElement("a");

}</pre>
<p>The function above, is the <strong><em>GoUpButton</em></strong>&#8216;s constructor, and as you can see it takes one argument: map, that is a reference to the map&#8217;s instance, then it creates an &lt;a&gt; tag that will be our clickable button.<br />
The next step is to extend <strong><em>GControl</em></strong>:</p>
<pre>GoUpButton.prototype = new GControl();</pre>
<p>Now, let&#8217;s implement the <strong><em>initialize()</em></strong> method:</p>
<pre>GoUpButton.prototype.initialize = function() {

    var map = this.map;

    this.button.className = "custom_nav_top";
    this.button.href = "javascript:;";
    this.button.title = "Move the map to the top";
    this.button.innerHTML = "N";

    GEvent.addDomListener(this.button, "click", function() {
        map.panBy(new GSize(0, 100));
    });

    map.getContainer().appendChild(this.button);

    return this.button;

}</pre>
<p>In this method we define the CSS class for the button, set its href attribute to &#8220;javascript:;&#8221; to ensure it won&#8217;t reload the page (is not necessary, but I feel more secure by doing it), set its title attribute and its innerHTML (in this case an N, which stands for North). Then we add an (anonymous) event listener that will be triggered when the user will click the button. This listener will invoke the map&#8217;s <em><em>panBy()</em></em> method, which moves the map by a specific distance by using an animation. The distance is represented by an instance of <em><em>GSize</em></em>, which is essentially a virtual polygon, which dimension are expressed with the two parameters width and height. So with new GSize(0, 100), we will move the map 100 pixels to the top (y axis).<br />
The last two steps in the method are add the node to the DOM (by using map&#8217;s <strong><em>getContainer()</em></strong> method, which returns the node containing the map) and returns it.</p>
<p>Ok, finally there is the <strong><em>getDeafultPosition()</em></strong> implementation:</p>
<pre>GoUpButton.prototype.getDefaultPosition = function() {

    return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(240, 5));

}</pre>
<p>This is a really simple method that returns an instance of <em><strong>GControlPosition</strong></em>, which will define how to place the control. <em><strong>GControlPosition</strong></em> takes 2 arguments: anchor and offset, the first can be one of the following constants:</p>
<ul>
<li>G_ANCHOR_TOP_RIGHT</li>
<li>G_ANCHOR_TOP_LEFT</li>
<li>G_ANCHOR_BOTTOM_RIGHT</li>
<li>G_ANCHOR_BOTTOM_LEFT</li>
</ul>
<p>that will anchor the control to the 4 possible map&#8217;s corners, the second represents the offset (ie: the distance from the anchor point). In this way we can position our button where we like (GoUpButton will be placed 5 pixel to the top of the map and 240 pixels to the left&#8230; in a map of 500&#215;300 pixels it will appears centered on the top).<br />
We have finished with our custom control!<br />
Now we have to repeat the previous steps for <strong><em>GoDownButton</em></strong>, <strong><em>GoLeftButton</em></strong> and <strong><em>GoRightButton</em></strong>, by replacing the necessary values such button&#8217;s class, innerHTML, title, <em><strong>panBy()</strong></em> argument and <em><strong>GControlPosition()</strong></em> arguments.<br />
In order to add all the 4 controls to the map we will use <strong><em>addControl()</em></strong> method:</p>
<pre>    map.addControl(new GoUpButton(map));
    map.addControl(new GoDownButton(map));
    map.addControl(new GoLeftButton(map));
    map.addControl(new GoRightButton(map));</pre>
<p>The result should be this:</p>
<p><img class="alignnone size-full wp-image-52" title="Custom google map controls" src="http://www.daveoncode.com/wp-content/uploads/2008/11/cmap.jpg" alt="Custom google map controls" /></p>
<p>The full code for the map above is the following:</p>
<pre style="background-repeat:repeat;">/* go top */
function GoUpButton(map) {
    this.map = map;
    this.button = document.createElement("a");
}

GoUpButton.prototype = new GControl();

GoUpButton.prototype.initialize = function() {

    var map = this.map;

    this.button.className = "custom_nav_top";
    this.button.href = "javascript:;";
    this.button.title = "Move the map to the top";
    this.button.innerHTML = "N";

    GEvent.addDomListener(this.button, "click", function() {
        map.panBy(new GSize(0, 100));
    });

    map.getContainer().appendChild(this.button);

    return this.button;

}

GoUpButton.prototype.getDefaultPosition = function() {
    return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(240, 5));
}

/* go down */
function GoDownButton(map) {
    this.map = map;
    this.button = document.createElement("a");
}

GoDownButton.prototype = new GControl();

GoDownButton.prototype.initialize = function() {

    var map = this.map;

    this.button.className = "custom_nav_down";
    this.button.href = "javascript:;";
    this.button.title = "Move the map to the bottom";
    this.button.innerHTML = "S";

    GEvent.addDomListener(this.button, "click", function() {
         map.panBy(new GSize(0, -100));
    });

    map.getContainer().appendChild(this.button);

    return this.button;

}

GoDownButton.prototype.getDefaultPosition = function() {
    return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(240, 270));
}

/* go left */
function GoLeftButton(map) {
    this.map = map;
    this.button = document.createElement("a");
}

GoLeftButton.prototype = new GControl();

GoLeftButton.prototype.initialize = function() {

    var map = this.map;

    this.button.className = "custom_nav_left";
    this.button.href = "javascript:;";
    this.button.title = "Move the map to the left";
    this.button.innerHTML = "W";

    GEvent.addDomListener(this.button, "click", function() {
        map.panBy(new GSize(100, 0));
    });

    map.getContainer().appendChild(this.button);

    return this.button;

}

GoLeftButton.prototype.getDefaultPosition = function() {
    return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(5, 140));
}

/* go right */
function GoRightButton(map) {
    this.map = map;
    this.button = document.createElement("a");
}

GoRightButton.prototype = new GControl();

GoRightButton.prototype.initialize = function() {

    var map = this.map;

    this.button.className = "custom_nav_right";
    this.button.href = "javascript:;";
    this.button.title = "Move the map to the right";
    this.button.innerHTML = "E";

    GEvent.addDomListener(this.button, "click", function() {
         map.panBy(new GSize(-100, 0));
    });

    map.getContainer().appendChild(this.button);

    return this.button;

}

GoRightButton.prototype.getDefaultPosition = function() {
    return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(470, 140));
}

function initialize() {

    if (GBrowserIsCompatible()) {

        var map = new GMap2(document.getElementById("map_canvas"));

        map.addControl(new GoUpButton(map));
        map.addControl(new GoDownButton(map));
        map.addControl(new GoLeftButton(map));
        map.addControl(new GoRightButton(map));
        map.setCenter(new GLatLng(41.87194, 12.56738), 5);

    }

}</pre>
<div class="addthis_toolbox addthis_default_style addthis_32x32_style" addthis:url='http://www.daveoncode.com/2008/11/17/playing-with-google-maps-api-part-two-create-custom-controls/' addthis:title='Playing with Google maps API &#8211; part two: Create custom controls ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.daveoncode.com/2008/11/17/playing-with-google-maps-api-part-two-create-custom-controls/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Playing with Google maps API &#8211; Part one</title>
		<link>http://www.daveoncode.com/2008/11/14/playing-with-google-maps-api-part-one/</link>
		<comments>http://www.daveoncode.com/2008/11/14/playing-with-google-maps-api-part-one/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 12:00:31 +0000</pubDate>
		<dc:creator>Davide Zanotti</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[geolocation]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[web services]]></category>

		<guid isPermaLink="false">http://daveoncode.wordpress.com/?p=23</guid>
		<description><![CDATA[Ok, as announced in the previous post, let&#8217;s start to analyze how to work with Google maps (Javascript) API. Preface: while I was writing I have been a little too verbose, so I won&#8217;t respect the previously declared steps, but I will add/modify them while posting. 1. Getting an API key In order to use [...]<div class="addthis_toolbox addthis_default_style addthis_32x32_style" addthis:url='http://www.daveoncode.com/2008/11/14/playing-with-google-maps-api-part-one/' addthis:title='Playing with Google maps API &#8211; Part one ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></description>
			<content:encoded><![CDATA[<p>Ok, as announced in the previous post, let&#8217;s start to analyze how to work with Google maps (Javascript) API.<br />
Preface: while I was writing I have been a little too verbose, so I won&#8217;t respect the previously declared steps, but I will add/modify them while posting.</p>
<p><span id="more-23"></span></p>
<p><strong>1. Getting an API key</strong></p>
<p>In order to use the Google maps service into our website/application, we have to go at the following address:<br />
http://code.google.com/apis/maps/signup.html, accept the terms and conditions, specify our website url (an API key will works only for the specified url and its sub-directories), click on the &#8220;Generate Api Key&#8221; button and waiting for its generation. Note that in order to get the key, we have to be logged with a google account, otherwise Google will invite you to register before letting use its service.<br />
After the API key generation, we will redirected to a page showing:</p>
<p>- The Key (for example, by asking a key for the domain www.foo.com, we&#8217;ll get something like: ABQIAAAAswsigAo1t_SU1aGAbcpt8hSRoQh9m-phgHuyQptS3bFLHQ8pkBQR4s7kR1aUKqmyqavqMz-lfRX09Q)<br />
- Where this key is valid (the url that we have requested)<br />
- A basic HTML code sample to create a map with the Google service</p>
<p>The only external file that will need to use to realize our custom map is this:</p>
<pre>&lt;script type="text/javascript" src="http://maps.google.com/maps?file=api&amp;amp;v=2&amp;amp;key=GENERATED_KEY"&gt;&lt;/script&gt;</pre>
<p><strong>2. Setting up the basic map</strong></p>
<p>As we can see in the Google example, the first steps in order to display the map are: put a div in the page that will be the container (with a bit of stylesheet to set its dimension) and assign it an ID for a convenient way to retrieve it with the the Javascript DOM method document.getElementById(&#8220;DIV_ID&#8221;), waiting for the loading of the page (in the example Google uses the &lt;body&gt; onload attribute, to pass an initialization function that will be executed after the loading of the page, but we can use a custom window.onload = ourFunction, or $(document).ready() jQuery&#8217;s method, Ext.onReady() method or else according to the js library that we want to use or not) and then use the main Google maps class GMap2.</p>
<p>The very basic code, to initialize the map is:</p>
<pre>var map = new GMap2(document.getElementById("DIV_ID"));</pre>
<p>However the line above will only produce a grey box with the Google logo, and the link &#8220;Terms of use&#8221;.<br />
To display something into the map, we must tell Google what part of the world we want to see.<br />
This can be possible by using the GMap2&#8242;s method setCenter(), which requires a GLatLng as a mandatory parameter, plus an optional zoom level.<br />
As API reference says: GLatLng is a point in geographical coordinates longitude and latitude.<br />
This is the code (in the minimal possible version):</p>
<pre>map.setCenter(new GLatLng(0, 0));</pre>
<p>The previous command, will produces a very general geographic view, that according to us div dimensions will show a repeated world&#8217;s map.<br />
That&#8217;s because, we didn&#8217;t specify a zoom level, and so 0 (zero) is assumed by Google (which is the lowest possible value).<br />
Let&#8217;s try to pass a zoom value of 1 and see what happen!</p>
<pre>map.setCenter(new GLatLng(0, 0), 1);</pre>
<p>Hei! Finally we can at least read the names of the countries and pacific and Indian oceans&#8230; but is still not so funny, let&#8217;s move on!</p>
<p><strong>3. Positioning the map on a given location</strong></p>
<p>To positioning the map on a specific geographic location we have to know the latitude and longitude coordinates and passing them into the GLatLng,<br />
constructor&#8217;s arguments. The basic way to do this, is to use maps.google.com website, search for a location (for example &#8220;Italy&#8221;), click on &#8220;Link&#8221;<br />
button (the last link above the map) and extract the queryString parameter &#8220;ll&#8221;, which in my test for Italy are &#8220;41.87194,12.56738&#8243;.</p>
<p><a href="http://daveoncode.files.wordpress.com/2008/11/get_coordinate_of_italy.jpg"><img class="alignnone size-full wp-image-33" title="get_coordinate_of_italy" src="http://www.daveoncode.com/wp-content/uploads/2008/11/get_coordinate_of_italy.jpg" alt="get_coordinate_of_italy" /></a></p>
<p>By using the setCenter() method, in this way:</p>
<pre>map.setCenter(new GLatLng(41.87194, 12.56738), 5);</pre>
<p>We are able to visualize the whole Italy, plus others adjacent nations (in a 500&#215;300 pixel div). This is how the map should be:</p>
<p><a href="http://daveoncode.files.wordpress.com/2008/11/display_italy.jpg"><img class="alignnone size-full wp-image-32" title="display_italy" src="http://www.daveoncode.com/wp-content/uploads/2008/11/display_italy.jpg" alt="display_italy" /></a></p>
<p><strong>4. Add map controls</strong></p>
<p>The map we have created so far doesn&#8217;t offer many features, except the drag and drop and the doubleclick to zoom, which is enabled by default (to avoid that functionality we can use disableDoubleClickZoom() map&#8217;s method, and we can eventually toggle it alternating with enableDoubleClickZoom() and checking for its status with doubleClickZoomEnabled() which returns a boolean indicating if is active or not).<br />
To add a map control, we have to use the addControl() method and pass an instance of the desired control.<br />
The following are the basic controls that Google maps offers:</p>
<pre>map.addControl(new GMapTypeControl());</pre>
<p>That will display:</p>
<p><a href="http://daveoncode.files.wordpress.com/2008/11/gmaptypecontrol.gif"><img class="alignnone size-full wp-image-24" title="gmaptypecontrol" src="http://www.daveoncode.com/wp-content/uploads/2008/11/gmaptypecontrol.gif" alt="gmaptypecontrol" /></a></p>
<pre>map.addControl(new GHierarchicalMapTypeControl());</pre>
<p>That will display:</p>
<p><img class="alignnone size-full wp-image-25" title="ghierarchicalmaptypecontrol" src="http://www.daveoncode.com/wp-content/uploads/2008/11/ghierarchicalmaptypecontrol.gif" alt="ghierarchicalmaptypecontrol" /></p>
<pre>map.addControl(new GMenuMapTypeControl(false));
// we can pass true to display short names</pre>
<p>That will display:</p>
<p><img class="alignnone size-full wp-image-26" title="gmenumaptypecontrol" src="http://www.daveoncode.com/wp-content/uploads/2008/11/gmenumaptypecontrol.gif" alt="gmenumaptypecontrol" /></p>
<pre>map.addControl(new GSmallZoomControl());</pre>
<p>That will display:</p>
<p><img class="alignnone size-full wp-image-27" title="gsmallzoomcontrol" src="http://www.daveoncode.com/wp-content/uploads/2008/11/gsmallzoomcontrol.gif" alt="gsmallzoomcontrol" /></p>
<pre>map.addControl(new GSmallMapControl());</pre>
<p>That will display:</p>
<p><img class="alignnone size-full wp-image-28" title="gsmallmapcontrol" src="http://www.daveoncode.com/wp-content/uploads/2008/11/gsmallmapcontrol.gif" alt="gsmallmapcontrol" /></p>
<pre>map.addControl(new GLargeMapControl());</pre>
<p>That will display:</p>
<p><img class="alignnone size-full wp-image-29" title="glargemapcontrol" src="http://www.daveoncode.com/wp-content/uploads/2008/11/glargemapcontrol.gif" alt="glargemapcontrol" /></p>
<pre>map.addControl(new GScaleControl());</pre>
<p>That will display:</p>
<p><img class="alignnone size-full wp-image-30" title="gscalecontrol" src="http://www.daveoncode.com/wp-content/uploads/2008/11/gscalecontrol.gif" alt="gscalecontrol" /></p>
<pre>map.addControl(new GOverviewMapControl());</pre>
<p>That will display:</p>
<p><img class="alignnone size-full wp-image-31" title="goverviewmapcontrol" src="http://www.daveoncode.com/wp-content/uploads/2008/11/goverviewmapcontrol.gif" alt="goverviewmapcontrol" /></p>
<p>Many controls are mutually exclusive, ie if we use for example both GSmallMapControl and GLargeMapControl the result is an ugly sovrapposition of these.</p>
<div class="addthis_toolbox addthis_default_style addthis_32x32_style" addthis:url='http://www.daveoncode.com/2008/11/14/playing-with-google-maps-api-part-one/' addthis:title='Playing with Google maps API &#8211; Part one ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.daveoncode.com/2008/11/14/playing-with-google-maps-api-part-one/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Playing with Google maps API</title>
		<link>http://www.daveoncode.com/2008/11/13/playing-with-google-maps-api/</link>
		<comments>http://www.daveoncode.com/2008/11/13/playing-with-google-maps-api/#comments</comments>
		<pubDate>Thu, 13 Nov 2008 21:38:33 +0000</pubDate>
		<dc:creator>Davide Zanotti</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://daveoncode.wordpress.com/?p=19</guid>
		<description><![CDATA[In my spare time, these days I&#8217;m looking at Google maps (Javascript) API, because relatively soon, I will have to realize a web site in which include a custom and interactive map. In detail the site will be the official web page of an Italian bikers group, which will attempt to enter in the World [...]<div class="addthis_toolbox addthis_default_style addthis_32x32_style" addthis:url='http://www.daveoncode.com/2008/11/13/playing-with-google-maps-api/' addthis:title='Playing with Google maps API ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-20" title="world" src="http://www.daveoncode.com/wp-content/uploads/2008/11/wwd_world2-300x287.jpg" alt="world" />In my spare time, these days I&#8217;m looking at Google maps (Javascript) API, because relatively soon, I will have to realize a web site in which include a custom and interactive map.<br />
In detail the site will be the official web page of an Italian bikers group, which will attempt to enter in the World Records Guinness as the largest bike aggregation of the same model (and I&#8217;ll be one of those crazy men! :-)))<br />
The user will be able to subscribe to the event indicating his city and some other details.<br />
And is here that the interactive map comes into play! It will shows the Italian map sprinkled by colored labels anchored to the main cities and indicating the total of subscribers in that city.<br />
The label&#8217;s color will vary due to that number (green = few bikers, yellow = so so, red = many bikers).</p>
<p><span id="more-19"></span><br />
I&#8217;ve already developed a working map, that loads a datasource (in my test a simple .txt file which contains a JSON formatted string) with ajax and then shows the labels on the map (after a Flash like preloader), but it can be improved considerably.<br />
However in the next days I will describe all the necessary steps and know-how to achive the goal.<br />
I will split the&#8230; tutorial? description?&#8230;ah ah, I don&#8217;t know how to call it&#8230; let&#8217;s say story, into 2 parts:</p>
<p><strong>Part 1</strong></p>
<p>1. Getting a key to use the API<br />
2. Setting up the basic map<br />
3. Positioning the map on a given location<br />
4. Add custom controls for zoom, map type, and navigation<br />
5. Geolocation&#8217;s service (find latitude and longitude of a given address)</p>
<p><strong>Part 2</strong></p>
<p>6. Creating a custom overlay object by extending the GOverlay class<br />
7. Display the custom overlay on a given location<br />
8. Handle multiple geolocation requests and overlay together<br />
9. Freeze the map and display a progress bar until geolocation process has finished</p>
<p>The first is the easy part and doesn&#8217;t require a good javascript knowledge nor particular html or css skills, the second is not so hard, but requires a pretty good understanding of javascript, prototype, css and ajax.<br />
Stay tuned ;-)</p>
<div class="addthis_toolbox addthis_default_style addthis_32x32_style" addthis:url='http://www.daveoncode.com/2008/11/13/playing-with-google-maps-api/' addthis:title='Playing with Google maps API ' ><a class="addthis_button_preferred_1"></a><a class="addthis_button_preferred_2"></a><a class="addthis_button_preferred_3"></a><a class="addthis_button_preferred_4"></a><a class="addthis_button_compact"></a></div>]]></content:encoded>
			<wfw:commentRss>http://www.daveoncode.com/2008/11/13/playing-with-google-maps-api/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

