<?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>In usability we trust &#187; Tutorials</title>
	<atom:link href="http://www.svennerberg.com/category/tutorials/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.svennerberg.com</link>
	<description>Web Applications Designed for Humans</description>
	<lastBuildDate>Mon, 14 Nov 2011 10:29:51 +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>Calculating Distances and Areas in Google Maps API 3</title>
		<link>http://www.svennerberg.com/2011/04/calculating-distances-and-areas-in-google-maps-api-3/</link>
		<comments>http://www.svennerberg.com/2011/04/calculating-distances-and-areas-in-google-maps-api-3/#comments</comments>
		<pubDate>Thu, 07 Apr 2011 11:39:33 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Geo]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[Google Maps API 3]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=2864</guid>
		<description><![CDATA[As I mentioned in the article Extending Google Maps API 3 with libraries a couple of weeks ago, you can add functionality to the Google Maps API by using libraries. One of these libraries are the Geometry Library. In this &#8230; <a href="http://www.svennerberg.com/2011/04/calculating-distances-and-areas-in-google-maps-api-3/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2011/04/compass.png" alt="" class="alignright size-full wp-image-3079" />As I mentioned in the article <a href="/2011/03/extending-google-maps-api-3-with-libraries/">Extending Google Maps API 3 with libraries</a> a couple of weeks ago, you can add functionality to the Google Maps API by using libraries. One of these libraries are the <strong>Geometry Library</strong>. In this article I will show how you can use the function of that library to calculate distances and areas.  I will also explain some additional navigation functions that you might find useful.</p>
<p><span id="more-2864"></span></p>
<h3>Including the library</h3>
<p>First of all to be able to use the library you need to let the Google Maps API know that you want to use it. This is done by adding an extra parameter to the querystring when including the Maps API on the web page.</p>
<pre name="code" class="html">
&lt;script type="text/javascript" src="http://maps.google.com/maps/api/js?libraries=geometry&amp;sensor=true_or_false"&gt;&lt;/script&gt;
</pre>
<h3>Namespaces</h3>
<p>Once you&#8217;ve done that you have a number of extra functions that you can use. They all reside in one of two namespaces:</p>
<ul>
<li><code>google.maps.geometry.spherical</code></li>
<li><code>google.maps.geometry.encoding</code></li>
</ul>
<p>The <code>spherical </code>namespace includes functions for calculating angles, distances and areas from latitudes and longitudes. These are the functions that we will examine in this article. </p>
<p>The other namespace, <code>encoding</code>, contains functions for encoding and decoding paths for polylines and polygons. They&#8217;re useful when you have big sets of data for displaying polylines or polygons that you need to optimize. I will not describe this namespace further here, maybe it&#8217;s a subject for a future article.</p>
<p class="note"><strong>Note:</strong> The library doesn&#8217;t consist of any classes but only have static functions. </p>
<h3>The earth is round, the map is flat</h3>
<p>When calculating distances and areas you need to take the fact that the earth is round into consideration (hence the name spherical). Since a map is flat a straight line on it is in fact an arc. Take a look at the map below. The shortest route between New York and London will look like an arc on a flat map (the blue line in the image below). </p>
<div id="attachment_3051" class="wp-caption alignnone" style="width: 420px"><img src="http://media.svennerberg.com/2011/04/distances.png" alt="" class="size-full wp-image-3051" /><p class="wp-caption-text">A straight line between two point on a map is in fact an arc.</p></div>
<p>Therefor when calculating distances and areas you need to use some pretty advanced mathematics to do it. Fortunately with the <strong>Geometry Library</strong> it&#8217;s dead simple.</p>
<h3>Distances and areas</h3>
<h4>Calculating the distance</h4>
<p>Calculating the distance between two points is really easy with the help of the <strong>Geometry library</strong>. All you have to do is to call the <code>computeDistanceBetween()</code> function and pass it two <code>LatLng </code>objects.</p>
<pre name="code" class="js">
var nyc = new google.maps.LatLng(40.715, -74.002);
var london = new google.maps.LatLng(51.506, -0.119);
var distance = google.maps.geometry.spherical.computeDistanceBetween(nyc, london);
</pre>
<p>The function returns the distance in meters. In this case it says that it&#8217;s 5 576 673 meters between NYC and London. </p>
<h4>Determining the heading</h4>
<p>If you also want to know the heading between two points you can use the <code>computeHeading()</code> function. It also takes two <code>LatLng</code> objects and determines the heading from the first to the second.</p>
<pre name="code" class="js">
var nyc = new google.maps.LatLng(40.715, -74.002);
var london = new google.maps.LatLng(51.506, -0.119);
var heading = google.maps.geometry.spherical.computeHeading(nyc, london);
</pre>
<p>The heading is returned in degrees from the true north (counts clockwise from 0). The heading from NYC to London is 51.2145583127633 degrees.</p>
<h4>Calculating an area</h4>
<p>To calculate the size of an area there&#8217;s the <code>computeArea()</code> function. Unlike the two previous functions it takes an array of <code>LatLng</code> objects as a parameter. The LatLng&#8217;s in this array represents a polygon and it must be closed, meaning that it will automatically close the polygon by connection the first and the last <code>LatLng</code>.</p>
<p class="note"><strong>Note:</strong> You can also pass a <code>MVCArray</code> as a parameter. It&#8217;s basically a regular array but is API specific and has a few other advantages.</p>
<pre name="code" class="js">
var nyc = new google.maps.LatLng(40.715, -74.002);
var london = new google.maps.LatLng(51.506, -0.119);
var rio = new google.maps.LatLng(-22.916, -43.251);
var area = google.maps.geometry.spherical.computeArea([nyc, london, rio]);
</pre>
<p>The code above will calculate the area of a triangle between NYC, London and Rio de Janeiro which is 26 566 710 985 447.367 m<sup>2</sup></p>
<h3>Navigation functions</h3>
<p>There are a few additional functions apart from the ones that calculates distances and areas. </p>
<h4>Calculating an end location</h4>
<p>If for example, you know the starting point, the distance and the heading. You can get the end location by using the <code>computeOffset()</code> function. It takes the starting point, the distance and the heading as parameters and returns a <code>LatLng</code> object.</p>
<p>If we take the values from the previous examples, the location of NYC, the distance to London and the heading towards London and use them as input. </p>
<pre name="code" class="js">
 var nyc = new google.maps.LatLng(40.715, -74.002);
var distance = 5576673;
var heading = 51.2145;
var endPoint = google.maps.geometry.spherical.computeOffset(nyc, distance, heading);
var marker = new google.maps.Marker({
  position: endPoint,
  map: map
});
</pre>
<p>In this case <code>endPoint</code> will be the location of London which is <code>LatLng(51.506, -0.118)</code>. (it differs slightly because I&#8217;ve rounded the numbers)</p>
<div id="attachment_3064" class="wp-caption alignnone" style="width: 420px"><img src="http://media.svennerberg.com/2011/04/computeOffset.png" alt="" class="size-full wp-image-3064" /><p class="wp-caption-text">With the computeOffset() function we can get the end location if we know the starting point, the heading and the distance.</p></div>
<h4>Calculate a point in between</h4>
<p>Another useful function is <code>interpolate()</code> which determines a point between two locations based on a fraction between 0 and 1. The fraction represents how far between two locations a point is. So for example 0.5 is a point right in the middle between the start- and end location.</p>
<pre name="code" class="js">
var nyc = new google.maps.LatLng(40.715, -74.002);
var london = new google.maps.LatLng(51.506, -0.119);
var inBetween = google.maps.geometry.spherical.interpolate(nyc, london, 0.5);
var marker = new google.maps.Marker({
  position: inBetween,
  map: map
});
</pre>
<p>This code will return a position right between NYC and London.</p>
<div id="attachment_3062" class="wp-caption alignnone" style="width: 420px"><img src="http://media.svennerberg.com/2011/04/interpolate.png" alt="" class="size-full wp-image-3062" /><p class="wp-caption-text">By using interpolate between NYC and London  with the fraction 0.5 we get the position right in the middle of those.</p></div>
<h3>Conclusion</h3>
<p>Calculating areas and distances on geo data can be tricky, but with the help of the <strong>Geometry Library</strong> it&#8217;s really simple. I hope this article has shed some light on how you can use it in your own map solution.</p>
<h3>More resources</h4>
<p>To read more about this library, check out the article <a href="http://code.google.com/apis/maps/documentation/javascript/geometry.html">Google Maps Javascript API V3 Geometry Library</a> in the offical documentation. You&#8217;ll also find a description of all the functions in the <a href="http://code.google.com/intl/sv/apis/maps/documentation/javascript/reference.html#encoding">API documentation</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2011/04/calculating-distances-and-areas-in-google-maps-api-3/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Dynamically Toggle Markers in Google Maps</title>
		<link>http://www.svennerberg.com/2009/06/dynamically-toggle-markers-in-google-maps/</link>
		<comments>http://www.svennerberg.com/2009/06/dynamically-toggle-markers-in-google-maps/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 17:36:12 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[MarkerManager]]></category>
		<category><![CDATA[Mashups]]></category>
		<category><![CDATA[V.2]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=931</guid>
		<description><![CDATA[This article explains how to dynamically toggle the visibility of markers in Google Maps as well as how to deal with an annoying bug that occurs when trying to do this while using an utility library, like the MarkerManager. Using &#8230; <a href="http://www.svennerberg.com/2009/06/dynamically-toggle-markers-in-google-maps/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/10/maps_logo_small_blue.png" alt=""  class="alignright" />This article explains how to dynamically toggle the visibility of markers in Google Maps as well as how to deal with an annoying bug that occurs when trying to do this while using an utility library, like the MarkerManager. </p>
<p><span id="more-931"></span></p>
<h2>Using the MarkerManager</h2>
<p>The <a href="http://gmaps-utility-library-dev.googlecode.com/svn/trunk/markermanager/docs/reference.html" title="MarkerManager v1.0 Reference">MarkerManager</a> is a very useful Open Source Utility Library for Google Maps with the sole purpose to manage larger amounts of Markers. If you add markers with the MarkerManager you can control at which zoom-levels they will appear. And you can also hide and show them dynamically. </p>
<p>If you want to learn more about the MarkerManager and other libraries out there that deals with markers, read my article <a href="http://www.svennerberg.com/2009/01/handling-large-amounts-of-markers-in-google-maps/">Handling Large Amounts of Markers in Google Maps</a>.</p>
<h2>Adding markers with the MarkerManager</h2>
<p>Now the most effective way to add markers to the MarkerManager is to first add them to an array that you then add to the MarkerManager with the <code>addMarkers()</code> method. The code to do this would be something like this.</p>
<pre name="code" class="js">
// Init the MarkerManager
var mgr = new MarkerManager();
//Defining the array that will contain all markers
var markers = [];
// Creating a marker
var marker = new GMarker(new GLatLng(57.8, 14.0));
// Add marker to the array
markers.push(marker);
// Add the array to the MarkerManager
mgr.addMarkers(markers, 1);
mgr.refresh();
</pre>
<p>Obviously it&#8217;s kind of useless to add only one marker this way. It would only be useful if you had at least a few of them, but I think you get the point.</p>
<h2>Hiding and showing markers</h2>
<p>In the Google Maps API there are two handy methods to toggle the visibility of markers. These are <code>GMarker.show()</code> and <code>GMarker.hide()</code>. They both work as expected, you call <code>hide()</code> and the markers disappears and then you call <code>show()</code> and the marker is displayed again.</p>
<p>So to hide all markers in this example you simply do this:</p>
<pre name="code" class="js">
// Loop through all markers and hide each of them
for (var i = 0; i < markers.length; i++) {
  var marker = markers[i];
  marker.hide();
}
</pre>
<h2>A bug</h2>
<p>There is however one caveat and that is when you zoom the map the markers will magically appear again. This is an annoying bug that only appears when you use it on markers added with an utility library. </p>
<div class="image">
<a href="http://media.svennerberg.com/2009/06/bug_description.png" rel="lightbox[imageset]"><img src="http://media.svennerberg.com/2009/06/bug_description-410x148.png" alt="bug_description" title="bug_description" width="410" height="148" class="alignnone size-medium wp-image-1934" /></a></p>
<p>Click the image to enlarge</p>
</div>
<h3>The solution</h3>
<p>So far I've only found one solution for this and that is to extend the hide method and tweak the code to place the marker outside the map, thereby making it sort of invisible. </p>
<pre name="code" class="js">
// Saving the position of the marker and then place it outside the map
GMarker.prototype.hide = function() {
  if (this.getPoint().lat() < 90) {
    try {
        this.savePoint = this.getPoint();
        this.setPoint(new GLatLng(90, 0));
    } catch (e) { }
  }
}
</pre>
<p>Subsequently you need to prototype the show method as well so that it moves the marker into the correct position again.</p>
<pre name="code" class="js">
// Restoring the position of the marker
GMarker.prototype.show = function() {
  if (this.getPoint().lat() == 90) {
    if (this.savePoint) {
      try {
        this.setPoint(this.savePoint);
        this.savePoint = null;
      } catch (e) { }
    }
  }
}
</pre>
<p>It's a dirty solution I know, but so far it's the best solution I've found and it works really well.</p>
<p class="note"><strong>Note:</strong> I haven't come up with this solution myself but haven't been able to find where I saw it. So if you know who did come up with it, please tell me so I can give credit where credit is due.</p>
<h3>isHidden()</h3>
<p>The Google Maps API also offers a method to determain if a marker is hidden or not, <code>GMarker.isHidden()</code>. If you want to be able to use that you have to prototype it as well. </p>
<pre name="code" class="js">
GMarker.prototype.isHidden = function() {
  if (this.getPoint().lat() == 90) {
    return true;
  } else {
    return false;
  }
}
</pre>
<h2>Live examples</h2>
<div class="image">
<a href="http://www.svennerberg.com/examples/toggle_markers/" title="Dynamically Toggle Markers in Google Maps - Examples"><img src="http://media.svennerberg.com/2009/06/example-410x413.png" alt="" class="alignnone" /></a></p>
<p><a href="http://www.svennerberg.com/examples/toggle_markers/" title="Dynamically Toggle Markers in Google Maps - Examples">Live examples of the bug and the solution</a></p>
</div>
<p>I've put together a few examples of different scenarios using this, so that you will see the problem as well as the solution to it.</p>
<ul>
<li><a href="http://www.svennerberg.com/examples/toggle_markers/">Using GMarker</a></li>
<li><a href="http://www.svennerberg.com/examples/toggle_markers/markermanager.html">Using MarkerManager</a></li>
<li><a href="http://www.svennerberg.com/examples/toggle_markers/markermanager_fixed.html">Using MarkerManager - fixed</a></li>
</ul>
<h2>Other libraries</h2>
<p>There are <a href="http://www.svennerberg.com/2009/01/handling-large-amounts-of-markers-in-google-maps/" title="Handling Large Amounts of Markers in Google Maps">several other libraries for dealing with markers</a> out there, and in at least one of them, <a href="http://www.acme.com/javascript/#Clusterer" title="">Clusterer</a>, I've noticed the same bug as in MarkerManager. The fix proposed in this article will work just fine on that one as well and possibly on other libraries where you might also find this bug.</p>
<p>If you've encountered this problem in other libraries please let me know. It would also be interesting to see other, and possibly more elegant solutions to this problem.</p>
<div class="book_push">
<img src="http://media.svennerberg.com/2009/09/bgma3-70.png" alt="" /></p>
<h3>My Google Maps book</h3>
<p>If you found this article useful you might be interested in my book <a href="/bgma3/" title="Read more about my book - Beginning Google Maps API 3"><strong>Beginning Google Maps API 3</strong></a>. It covers everything you need to know to create awesome maps on your web sites. <a href="http://www.amazon.com/gp/product/1430228024?ie=UTF8&#038;tag=inusabiwetrus-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1430228024" title="Buy Beginning Google Maps Applications from Amazon.com">Buy it on Amazon.com</a><img src="http://www.assoc-amazon.com/e/ir?t=inusabiwetrus-20&#038;l=as2&#038;o=1&#038;a=1430228024" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2009/06/dynamically-toggle-markers-in-google-maps/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Non-modal alert with jQuery</title>
		<link>http://www.svennerberg.com/2009/03/non-modal-alert-with-jquery/</link>
		<comments>http://www.svennerberg.com/2009/03/non-modal-alert-with-jquery/#comments</comments>
		<pubDate>Sun, 08 Mar 2009 16:23:37 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Design patterns]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=1627</guid>
		<description><![CDATA[In circumstances where you want to notify the user of something, like for example that some information have been saved, a non-modal alert is an excellent solution. It gets your message across without being intrusive and without the need for &#8230; <a href="http://www.svennerberg.com/2009/03/non-modal-alert-with-jquery/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/08/jquery-logo.gif" alt="jquery-logo" title="jquery-logo" width="133" height="133" class="alignright size-full wp-image-176" />In circumstances where you want to notify the user of something, like for example that some information have been saved, a non-modal alert is an excellent solution. It gets your message across without being intrusive and without the need for uneccesary user interaction. </p>
<p>In this article I will describe how to create it with the help of jQuery</p>
<p><span id="more-1627"></span></p>
<h3>The basics</h3>
<p>The whole idea with this approach is to make the user aware that something has happened, or that an action has been performed. You want to make sure that the message gets across but at the same time you don&#8217;t want to annoy the user or get in his or hers way. One way to do this is to show a message across the screen that as soon as the user moves the mouse, clicks a mouse button or press a key on the keyboard fades away.</p>
<div class="image">
<a href="http://media.svennerberg.com/2009/03/screenshot.png" title="Live demo of a non-modal alert" rel="lightbox[imageset]"><img src="http://media.svennerberg.com/2009/03/screenshot-410x155.png" alt="" class="alignnone" /></a></p>
<p><a href="http://www.svennerberg.com/examples/non-modal_alert/" title="Non-modal alert with jQuery">Watch the live demo</a></p>
</div>
<h3>The HTML</h3>
<p>The HTML is straightforward. Just insert this code somewhere in your HTML. Preferably at the top or the bottom of it. Just make sure it&#8217;s not inside a container with an absolute or relative position.</p>
<pre name="code" class="html">
&lt;div class="message"&gt;
    &lt;p&gt;This is a non-modal alert&lt;/p&gt;
&lt;/div&gt;
</pre>
<h3>Give it some style</h3>
<p>We will want the message to hover over the page. Therefor we want it to have an absolute position. By setting the width of the containing <code>&lt;div&gt;</code> to 60% and it&#8217;s left position to 20% it&#8217;s going to appear centered on the screen.</p>
<p>The other declarations are just for the visual appearance of the message.</p>
<pre name="code" class="css">
.message {
    position: absolute;
    top: 145px;
    width: 60%;
    left: 20%;
    background: #ff9;
    border: 1px solid #fc0;
    font-size: 150%;
    padding: 15px 50px;
}
.message p {
    margin: 0;
    padding: 0 40px 0 20px;
    text-align: center;
}
</pre>
<h3>The Javascript</h3>
<p>The Javascript essentially checks if there&#8217;s a an element with the class message in the web page. If there is, it attaches a few events on it that when triggered, removes the message. </p>
<p>Notice that I use <code>one()</code> instead of <code>bind()</code> to attach the events. The reason being that once the event is triggered i doesn&#8217;t have to trigger again. With <code>one()</code>, jQuery automatically unbinds the event after it&#8217;s been triggered. </p>
<pre name="code" class="js">
$(document).ready(function(e) {
    // Check if there's a message
    if($('.message').length) {
         // If mouse is clicked, moved or a key is pressed
         $(document).one('click mousemove keypress', function(e) {
            // Fade the message away after 500 ms
            $('.message').animate({ opacity: 1.0 }, 500).fadeOut();
        });
    }
});
</pre>
<p>Notice in the part where the alert is faded out, there&#8217;s first <code>animate({ opacity: 1.0 }, 500)</code>. This is a hack to get a 500 ms long delay before the message starts to fade out. What it actually does is to change the opacity of the element to 1.0 over a timespan of 500 ms. But since the element already has the opacity 1.0 it just creates a 500 ms long delay before the <code>fadeOut() </code>part is executed.</p>
<p>This is all good and works well in most browsers except&#8230; you guessed it, Internet Explorer.</p>
<h3>Extra tweaks for Internet Explorer</h3>
<p>The problem in Internet Explorer is that the mousemove event triggers instantly even if you haven&#8217;t moved the mouse. Because of this we have to insert a short delay before the events are attached. In this example I&#8217;ve done it by moving the logic to remove the message to a function, <code>removeMessage()</code>,  which I call from the <code>setTimeout</code> function. The second argument of <code>setTimeout</code> determains the delay in ms before <code>removeMessage()</code> is invoked.</p>
<pre name="code" class="js">
$(document).ready(function(e) {
     // Check if there's a message
     if($('.message').length) {
         // the timeout is there to make things work properly in IE
         // If we have no timeout IE will trigger mousemove instantly
         setTimeout(removeMessage, 500);
    }
});
function removeMessage(){
    $(document).one('click mousemove keypress', function(e) {
        // Fade the message away after 500 ms
        $('.message').animate({ opacity: 1.0 }, 500).fadeOut();
    });
}
</pre>
<p>That&#8217;s it. Sadly the code is slightly less elegant, but at least i works in all browsers.</p>
<p>Check out the <a href="http://www.svennerberg.com/examples/non-modal_alert/" title="Non-modal alert with jQuery">Live demo</a></p>
<h3>Conclusion</h3>
<p>I have found this solution to be an excellent way to tell the user what&#8217;s going on in an unobtrusive, but still obvious way. I hope that you&#8217;ll find it useful too. If you have a more elegant way of overcoming the problem with IE or other ideas on how to enhance this solution, don&#8217;t hesitate to tell me.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2009/03/non-modal-alert-with-jquery/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Creating a Submenu in WordPress</title>
		<link>http://www.svennerberg.com/2009/02/creating-a-submenu-in-wordpress/</link>
		<comments>http://www.svennerberg.com/2009/02/creating-a-submenu-in-wordpress/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 21:08:59 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Templates]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=1633</guid>
		<description><![CDATA[For a project I&#8217;m currently working on I wanted to create a submenu that included the parent page as well as the supbages. I just wanted to display the submenu only if the parent page had subpages. Searching the WordPress &#8230; <a href="http://www.svennerberg.com/2009/02/creating-a-submenu-in-wordpress/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2009/02/wordpress-logo-150x150.png" alt="" class="alignright" />For a project I&#8217;m currently working on I wanted to create a submenu that included the parent page as well as the supbages. I just wanted to display the submenu only if the parent page had subpages. Searching the WordPress Codex and googling for a solution I couldn&#8217;t quite find an example that took all these factors into consideration so I had to figure it out myself. Here&#8217;s the approach I came up with.</p>
<p><span id="more-1633"></span></p>
<h2>Checking if the page has subpages</h2>
<p>I searched in vain for a method to determine if the current page has any subpages or not. I first assumed that there would be a <code>has_subpages()</code> method, but so far I haven&#8217;t found any. Lacking that, I came up with a very crude way of checking it. I explicitly had to try to fetch all the subpages with the function <code><a href="http://codex.wordpress.org/Template_Tags/wp_list_pages">wp_list_pages()</a></code> and then check if it returned anything. It&#8217;s not pretty but it works.</p>
<pre name="code" class="php">
$children = wp_list_pages('&#038;child_of='.$post->ID.'&#038;echo=0');
if($children) {
    // This page has subpages
}
</pre>
<h2>Checking if it&#8217;s a parent page or a subpage</h2>
<p>The next thing I had to figure out was how to check i the current page is a parent page or a subpage. That&#8217;s done with the following code.</p>
<pre name="code" class="php">
if(is_page() &#038;&#038; $post->post_parent) {
    // This is a subpage
} else {
    // This a parent page
}
</pre>
<h2>Fetching the submenu</h2>
<p>Now I needed a way to fetch the subpages. This is done with the <code><a href="http://codex.wordpress.org/Template_Tags/wp_list_pages">wp_list_pages()</a></code> function. The tricky part about this is that there&#8217;s no way to get both the parent page and the subpages in the same call. So therefor we have to call the function twice. The call also looks a little different depending on if we&#8217;re on the parent page or on the subpage.</p>
<pre name="code" class="php">
if(is_page() &#038;&#038; $post->post_parent) {
    // This is a subpage
    $children = wp_list_pages("title_li=&#038;include=".$post->post_parent ."&#038;echo=0");
    $children .= wp_list_pages("title_li=&#038;child_of=".$post->post_parent ."&#038;echo=0");
} else if($has_subpages) {
    // This is a parent page that have subpages
    $children = wp_list_pages("title_li=&#038;include=".$post->ID ."&#038;echo=0");
    $children .= wp_list_pages("title_li=&#038;child_of=".$post->ID ."&#038;echo=0");
}
</pre>
<p>There are other ways of doing this, but the benefit of this approach is that we automatically get <code>class="current_page_item"</code> on the list-item that represents the page that we&#8217;re currently on. That&#8217;s handy if you want to style that item in any particular way. </p>
<h2>Outputting the HTML</h2>
<p>The last step is to output the actual HTML. I&#8217;ve chosen to output it as an unordered list.</p>
<pre name="code" class="php">
&lt;?php // Check to see if we have anything to output ?&gt;
&lt;?php if ($children) { ?&gt;
&lt;ul class="submenu"&gt;
    &lt;?php echo $children; ?&gt;
&lt;/ul&gt;
&lt;?php } ?>
</pre>
<h2>Putting it all together</h2>
<p>Now it&#8217;s time to put all the pieces together. Just put this code in <del datetime="2009-03-27T17:36:31+00:00">your page template</del> <ins datetime="2009-03-27T17:40:14+00:00">one of the pages in your template, like for example page.php or sidebar.php and you&#8217;re good to go. These pages are located in /wp-content/themes/your-theme/</ins>.</p>
<pre name="code" class="php">
&lt;?php
$has_subpages = false;
// Check to see if the current page has any subpages
$children = wp_list_pages('&#038;child_of='.$post->ID.'&#038;echo=0');
if($children) {
    $has_subpages = true;
}
// Reseting $children
$children = "";

// Fetching the right thing depending on if we're on a subpage or on a parent page (that has subpages)
if(is_page() &#038;&#038; $post->post_parent) {
    // This is a subpage
    $children = wp_list_pages("title_li=&#038;include=".$post->post_parent ."&#038;echo=0");
    $children .= wp_list_pages("title_li=&#038;child_of=".$post->post_parent ."&#038;echo=0");
} else if($has_subpages) {
    // This is a parent page that have subpages
    $children = wp_list_pages("title_li=&#038;include=".$post->ID ."&#038;echo=0");
    $children .= wp_list_pages("title_li=&#038;child_of=".$post->ID ."&#038;echo=0");
}
?&gt;
&lt;?php // Check to see if we have anything to output ?&gt;
&lt;?php if ($children) { ?&gt;
&lt;ul class="submenu"&gt;
    &lt;?php echo $children; ?&gt;
&lt;/ul&gt;
&lt;?php } ?&gt;
</pre>
<h2>Conclusion</h2>
<p>I think that WordPress is an absolutely awesome CMS/Blog engine, but it do lack some handy methods. Fortunately it&#8217;s almost always possible to create workarounds. I hope that you will find this useful in your own WordPress Template. Don&#8217;t hesitate to tell me if you have a smarter way of doing this.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2009/02/creating-a-submenu-in-wordpress/feed/</wfw:commentRss>
		<slash:comments>62</slash:comments>
		</item>
		<item>
		<title>Working with Info Windows in Google Maps</title>
		<link>http://www.svennerberg.com/2009/02/working-with-info-windows-in-google-maps/</link>
		<comments>http://www.svennerberg.com/2009/02/working-with-info-windows-in-google-maps/#comments</comments>
		<pubDate>Thu, 05 Feb 2009 20:53:21 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[Info Windows]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mashups]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=1193</guid>
		<description><![CDATA[Having Info Windows in a Google Maps is a powerful way of displaying information about a specific point or object. Did you know that there are several kinds of them? In this article I will show you how to add &#8230; <a href="http://www.svennerberg.com/2009/02/working-with-info-windows-in-google-maps/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/10/maps_logo_small_blue.png" alt="Google Maps API" class="alignright" />Having Info Windows in a Google Maps is a powerful way of displaying information about a specific point or object. Did you know that there are several kinds of them? </p>
<p>In this article I will show you how to add different kinds of Info Windows that appear when you click on a marker.</p>
<p><span id="more-1193"></span></p>
<h2>Content</h2>
<ul>
<li><a href="#basic">Basic Info Window</a></li>
<li><a href="#tabs">Info window with tabs</a></li>
<li><a href="#minimap">Info Window containing a Mini map</a></li>
<li><a href="#maximizing">Maximizing the Info Window</a></li>
<li><a href="#GInfoWindowOption">Options</a></li>
<li><a href="#conclusion">Conclusion and further resources</a></li>
</ul>
<h2 id="basic">Basic Info Window</h2>
<p>The key method for opening an info window when clicking a marker is <code>GMarker.openInfoWindowHTML()</code>. It takes two arguments, first the text that will appear in the Info Window and secondly an optional object literal containing options you might want to use to configure the Info Window. To learn more about the available options, see <a href="#GInfoWindowOption">Options</a> further down the page.</p>
<p>In the examples for this article you have to click a marker to open the window. This is done by using the <code>GEvent.addListener()</code> method. I will not describe exactly how it works in this article but if you&#8217;re unfamiliar with it you can read more about it in the <a href="http://code.google.com/intl/sv-SE/apis/maps/documentation/events.html" title="Google Maps API - Events">official documentation</a>.</p>
<pre name="code" class="js">
// Init a new map
var map = new GMap2(document.getElementById('map'));
map.addControl(new GSmallMapControl());
map.setCenter(new GLatLng(56.87, 14.80), 11);
// Creating a new marker
var marker = new GMarker(new GLatLng(56.87, 14.80))
// Adding a click-event to the marker
GEvent.addListener(marker, 'click', function() {
  // When clicked, open an Info Window
  marker.openInfoWindowHtml('Some text');
});
// Add marker to map
map.addOverlay(marker);
</pre>
<p>This code will result in an ordinary map showing a marker which, when you click on it, pops up an Info Window.</p>
<p><img src="http://media.svennerberg.com/2009/01/basic.png" alt="" class="alignnone" /></p>
<p class="demo"><a href="http://www.svennerberg.com/examples/info_windows/" title="Basic Info Window">Watch live demo</a></p>
<h2 id="tabs">Info Window with Tabs</h2>
<p>If you have a lot of information about each marker, more than you can fit inside a normal Info Window, you could use an Info Window with tabs. You simply define each tab as a <code>GInfoWindowTab</code> and add them to an array that you later on add to the marker using the <code>openInfoWindowTabsHtml()</code> method.</p>
<pre name="code" class="js">
// Create an array that will hold the tabs
var tabs = [];
// Create tabs and add them to the array
tabs.push(new GInfoWindowTab('Tab 1', 'Content of tab 1'));
tabs.push(new GInfoWindowTab('Tab 2', 'Content of tab 2'));
// Add tabs to the InfowWindow
marker.openInfoWindowTabsHtml(tabs);
</pre>
<p>The result is a tabbed Info Window. </p>
<p><img src="http://media.svennerberg.com/2009/01/tabs.png" alt="" class="alignnone" /></p>
<p class="demo"><a href="http://www.svennerberg.com/examples/info_windows/tabs.html" title="Info Window with Tabs">Watch Live Demo</a></p>
<h2 id="minimap">Info Window containing a Mini map</h2>
<p>The API features an easy method to open up a mini map over the area where the marker is located, <code>showMapBlowup(opts?:GInfoWindowOptions)</code>. This method takes an object literal that have two possible parameters, <code>InfoWindowOptions.zoomLevel</code> and <code>InfoWindowOptions.mapType</code>. These lets you determine at what zoom-level the mini map should start and what map type it should show.</p>
<pre name="code" class="js">
GEvent.addListener(marker, 'click', function() {
  // When clicked, open an Info Window with a min map in it
  marker.showMapBlowup();
});
</pre>
<p>You never thought it would be this easy to do this, did you?</p>
<p><img src="http://media.svennerberg.com/2009/01/minimap.png" alt="" class="alignnone" /></p>
<p class="demo"><a href="http://www.svennerberg.com/examples/info_windows/minimap.html" title="Info Window with a Mini Map">Watch live demo</a></p>
<h2 id="maximizing">Maximizing the Info Window</h2>
<p>If you have a lot of content to show in you Info Window it could be useful to let the user maximize it. This is easily done using the options <code>maxContent</code> and <code>maxTitle</code>. If you define these you will automatically get a maximize button in your window. </p>
<p>So to make this work just do like this.</p>
<pre name="code" class="js">
marker.openInfoWindowHtml('Click the (+) to maximize me!', {
  maxTitle: 'Maximized Title',
  maxContent: 'Maximized content text.'
});
</pre>
<p>When you first click the marker an ordinary info window will pop up. When you click the plus sign (+) in it, it will maximize.</p>
<p><img src="http://media.svennerberg.com/2009/01/maximized.png" alt="" class="alignnone" /></p>
<p><a href="http://www.svennerberg.com/examples/info_windows/maximize.html" title="Maximizing an Info Window">Watch live demo</a></p>
<h2 id="GInfoWindowOption">Options</h2>
<p>As I&#8217;ve mentioned earlier each of the methods that opens an Info Window takes an optional object literal with options. The properties you can use in it are defined in the <a href="http://code.google.com/intl/sv-SE/apis/maps/documentation/reference.html#GInfoWindowOptions"><code>GInfoWindowOptions</code></a> class.</p>
<p>All properties doesn&#8217;t comply with all kinds of Info Window.</p>
<ul>
<li><strong>selectedTab [number]</strong><br />
Determines which tab should be selected when opening an Info Window. Starts with number 0.</li>
<li><strong>maxWidth [number]</strong><br />
Sets the maximum width of the info window. <strong>Note:</strong> From my observations it seems that the minimum value for this is 249 pixels.</li>
<li><strong>noCloseOnClick [bool]</strong><br />
Sets if the info window should be closed when clicking inside the map. Default value is true.</li>
<li><strong>onOpenFn [Function]</strong><br />
A function that is called after the info window is opened and the content is displayed.</li>
<li><strong>onCloseFn [Function]</strong><br />
A function that is called when the info window is closed.</li>
<li><strong>zoomLevel [number]</strong><br />
Determines what zoom level an opened Mini Map should have. Only applicable with showMapBlowUp().</li>
<li><strong>mapType [GMapType]</strong><br />
Determines what map type an opened Mini Map should have. Only applicable with showMapBlowUp().</li>
<li><strong>maxContent [string]</strong><br />
Determines what content should be showed when an info window is maximized. It can be either an HTML string or an HTML DOM element.</li>
<li><strong>maxTitle [string]</strong><br />
Sets the title for the window when it&#8217;s maximized. It can be either an HTML string or an HTML DOM element.</li>
<li><strong>pixelOffset [GSize]</strong><br />
Specifies a number of pixels to move the info window away from the current GLatLng.</li>
</ul>
<h3>How to use them</h3>
<p>The options are passed to the method in an Object Literal. Here&#8217;s an example of using the <code>maxWidth</code> property when opening a basic Info Window.</p>
<pre name="code" class="js">
marker.openInfoWindowHtml('Some text', {maxWidth: '250'});
</pre>
<h2 id="conclusion">Conclusion and further resources</h2>
<p>Info windows are a powerful way of displaying information about certain objects in a map. In this article I have showed you some of the basic ways to use the built in ones in Google Maps. I think you can go a long way with these techniques but if you have special needs there are third party extensions out there that you can use. </p>
<p>It&#8217;s beyond the scope of this article to describe how they work, but the first library to check out should be <strong>ExtInfoWindow</strong>, one of the open source utility libraries for Google Maps. You&#8217;ll find documentation and examples at <a href="http://gmaps-utility-library.googlecode.com/svn/trunk/extinfowindow/">Google Maps API Utility Library</a>. Joe Monahan has also written some about it on the Google Maps API Blog in the article <a href="http://googlemapsapi.blogspot.com/2007/12/extinfowindow-10-ajax-powered-css.html">ExtInfoWindow 1.0: Ajax powered, CSS customization</a>.</p>
<p>Mike William at <a href="http://econym.org.uk/gmap/index.htm">Google Maps API Tutorial</a> has described two other libraries in the tutorials <a href="http://econym.org.uk/gmap/ewindows.htm">Using the EWindow extension</a> and <a href="http://econym.org.uk/gmap/ebubble.htm">Using the EBubble extension</a> that also might be useful.</p>
<p>Happy coding!</p>
<div class="book_push">
<img src="http://media.svennerberg.com/2009/09/bgma3-70.png" alt="" /></p>
<h3>My Google Maps book</h3>
<p>If you found this article useful you might be interested in my book <a href="/bgma3/" title="Read more about my book - Beginning Google Maps API 3"><strong>Beginning Google Maps API 3</strong></a>. It covers everything you need to know to create awesome maps on your web sites. <a href="http://www.amazon.com/gp/product/1430228024?ie=UTF8&#038;tag=inusabiwetrus-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1430228024" title="Buy Beginning Google Maps Applications from Amazon.com">Buy it on Amazon.com</a><img src="http://www.assoc-amazon.com/e/ir?t=inusabiwetrus-20&#038;l=as2&#038;o=1&#038;a=1430228024" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2009/02/working-with-info-windows-in-google-maps/feed/</wfw:commentRss>
		<slash:comments>48</slash:comments>
		</item>
		<item>
		<title>Handling Large Amounts of Markers in Google Maps</title>
		<link>http://www.svennerberg.com/2009/01/handling-large-amounts-of-markers-in-google-maps/</link>
		<comments>http://www.svennerberg.com/2009/01/handling-large-amounts-of-markers-in-google-maps/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 19:20:45 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[Markers]]></category>
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=933</guid>
		<description><![CDATA[To use markers in Google Maps is fairly trivial, at least when you have a reasonable amount of them. But once you have more than a few hundred of them, performance quickly starts to degrade. In this article I will &#8230; <a href="http://www.svennerberg.com/2009/01/handling-large-amounts-of-markers-in-google-maps/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/10/maps_logo_small_blue.png" alt="Google Maps" class="alignright" />To use markers in Google Maps is fairly trivial, at least when you have a reasonable amount of them. But once you have more than a few hundred of them, performance quickly starts to degrade. In this article I will show you a few approaches to speed up performance. I&#8217;ve also put together a test page to compare them.</p>
<p class="note"><strong>Update [2009-05-06]:</strong>This article has been updated with the addition of the utility library <a href="#markerclusterer">MarkerClusterer</a>. The <a href="#test_result">test results</a> in the end of the article and the <a href="http://www.svennerberg.com/examples/markers/markerPerformance.html">test page</a> has also been revised.</p>
<p><span id="more-933"></span></p>
<p>If you&#8217;re new to markers in Google Maps I recommend that you first read <a href="http://www.svennerberg.com/2008/12/basic-operations-with-markers-in-google-maps/">Basic operations with markers in Google Maps</a> for an introduction on how to use them.</p>
<h2>The Marker Manager &#8211; Keeps track of them</h2>
<p>Your first option might be to use the MarkerManager since it&#8217;s an utility library provided by Google. Rather than adding each marker individually to the map using <code>GMap2.addOverlay()</code> you first add them to the MarkerManager. The MarkerManager keeps track of all your markers. By defining at which zoom-levels each marker should appear you can cluster the markers to reduce the amount being shown at a time.</p>
<p>The MarkerManager is initially a bit slower than just adding markers directly to the map but the added benefit is that you can have more control over them. </p>
<p>You add markers to the MarkerManager with <code>addMarker(GMarker, minZoom, maxZoom?)</code>. This method takes three arguments, the first one being the marker you want to add. The two second arguments are optional but define at which zoom-levels the marker will be visible. </p>
<h3>A simple example</h3>
<pre name="code" class="js">
// Create a new map
var map = new GMap2(document.getElementById('map'));
map.setCenter(new GLatLng(59.5, 14.0), 6);
// Create a new instance of the MarkerManager
var mgr = new MarkerManager(map);
// Create a new marker
var marker = new GMarker(new GLatLng(59.0, 13.80));
// Add marker to the MarkerManager
mgr.addMarker(marker);
</pre>
<p>Obviously there&#8217;s not much use adding a single marker to the MarkerManager, but if you have hundreds of them, this might be the way to go. </p>
<h3>Bulk adding the markers</h3>
<p>An even more efficient way of using the MarkerManager is to do a bulk add by first putting all your markers into an array and then add the array to the MarkerManager with the <code>addMarkers(markerArray, minZoom, maxZoom?)</code> method. </p>
<pre name="code" class="js">
// Create a new instance of the MarkerManager
var mgr = new MarkerManager(map);
// Create marker array
var markers = [];
// Loop to create markers and adding them to the MarkerManager
for(var i = 0; i < 50; i += 0.1) {
    var marker = new GMarker(new GLatLng(59.0 + i, 13.80 + i));
    markers.push(marker);
}
// Add the array to the MarkerManager
mgr.addMarkers(markers);
// Refresh the MarkerManager to make the markers appear on the map
mgr.refresh();
</pre>
<p>Notice that you have to use <code>mgr.refresh()</code> after adding the marker array to it. That's not necessary when adding the markers one by one.</p>
<h3>Additional methods</h3>
<ul>
<li><strong>removeMarker(marker)</strong><br />
Removes a marker from the MarkerManager</li>
<li><strong>clearMarkers()</strong><br />
Removes all markers.</li>
<li><strong>getMarkerCount(zoom)</strong><br />
Returns the number of markers at a given zoom-level.</li>
</ul>
<p>The MarkerManager is a utility library provided by Google. On the URL below you'll find the source code as well as the full documentation and examples.</p>
<p><a href="http://gmaps-utility-library.googlecode.com/svn/trunk/markermanager/release/">Google Maps MarkerManager SVN</a></p>
<h2>Marker Light - Markers on a diet</h2>
<p>Pamela Fox at Google has made a sample app for what she calls MarkerLight, which render less complex markers, thus increasing performance. The trade-off is that it's really just an image on the map, you can't interact with it. If you don't have the need for interaction this is a really easy way to gain performance, the only difference from the ordinary way of doing it is that you create a <code>MarkerLight</code> instead of a <code>GMarker</code>.</p>
<p>On Pamelas post about MarkerLight she explains why this approach is faster:</p>
<blockquote cite="http://groups.google.com/group/Google-Maps-API/browse_frm/thread/6ef32d27075b59b5/7e38e215a311d7eb?lnk=gst&#038;q=markerlight&#038;pli=1"><p>
The reason GMarker takes so long is that it's actually composed of many DOM elements - foreground, shadow, printable version, clickable area, etc. </p>
<p>If your purpose is visualization, then you can get away with just creating a GOverlay extension like MarkerLight that creates a div with a background URL (or background color, even better!). </p>
<p>- Pamela Fox
</p></blockquote>
<p>Here's how to use it:</p>
<pre name="code" class="js">
map.addOverlay(new MarkerLight(latlng, {image: "red_dot.png"}));
</pre>
<p>red_dot.png in is the image used for the marker. It's a very small and simple one.</p>
<p>You can try performance with different numbers of markers on <a href="http://gmaps-samples.googlecode.com/svn/trunk/manymarkers/randommarkers.html">Pamelas test page</a>.</p>
<p><a href="http://gmaps-samples.googlecode.com/svn/trunk/manymarkers/markerlight.js">Download markerlight.js</a></p>
<h2>Using Marker Light in combination with MarkerManager</h2>
<p>You can add the benefits of MarkerLight with the clustering capabilities of the MarkerManager. It's really easy, just combine the two:</p>
<pre name="code" class="js">
mgr.addMarker(new MarkerLight(latlng, {image: "red_dot.png"}));
</pre>
<p>The reason you should do this is that you can display a different number of markers at different zoom levels. This way you can ensure that not too many markers are displayed at the same time.</p>
<h2>Clusterer - Only show what you need</h2>
<p>A different approach is to use ACME labs <a href="http://www.acme.com/javascript/#Clusterer">Clusterer</a>. It's a third party library that offers a faster way of adding markers. It's released under the BSD license and is freely available.</p>
<p>It allows faster performance by doing two things.</p>
<ul>
<li>Only the markers currently visible actually get created.</li>
<li>If too many markers would be visible, then they are grouped together into cluster markers.</li>
</ul>
<p>This lets you have literally thousands of markers on a map while maintaining decent performance. My tests with this approach shows that it's significantly faster than the MarkerManager approach.</p>
<p>Here's how to use it: </p>
<pre name="code" class="js">
// Create a Clusterer object
var clusterer = new Clusterer(map);
// Create marker
var marker = new GMarker(new GLatLng(57.8, 14.0));
// Add marker to the map
clusterer.AddMarker(marker, 'text to infobox');
</pre>
<p>To remove a marker from the map call <code>clusterer.RemoveMarker(marker)</code>.</p>
<p>There's also a few methods to change the behavior of the marker.</p>
<ul>
<li><strong>clusterer.SetIcon(GIcon)</strong><br />
Changes the cluster icon</li>
<li><strong>clusterer.SetMaxVisibleMarkers(n)</strong><br />
Sets the threshold marker count where clustering kicks in. Default value is 150.</li>
<li><strong>clusterer.SetMinMarkersPerCluster(n)</strong><br />
Sets the minumum number of markers for a cluster. Default value is 5.</li>
<li><strong>clusterer.SetMaxLinesPerInfoBox(n)</strong><br />
Sets the maximum number of lines in an info box. Default value is 10.</li>
</ul>
<p><a href="http://www.acme.com/javascript/Clusterer2.js">Download Clusterer2.js</a></p>
<h3>ClusterMarker - Chunk 'em all up</h3>
<p>ClusterMarker is a free Javascript library released under the GNU General Public License, that adds clustering capabilities to markers. The unique thing with this library is that it automatically detects markers that intersect each other and cluster these into a single cluster marker. </p>
<p>The images below illustrates how this works</p>
<div class="image">
<img src="http://media.svennerberg.com/2008/12/unclustered.jpg" alt="" class="alignleft" /><img src="http://media.svennerberg.com/2008/12/clustered.jpg" alt="" class="alignleft" /></p>
<p class="clear">Images by <a href="http://googlemapsapi.martinpearman.co.uk/">Martin Pearman</a></p>
</div>
<p>The constructor takes two arguments and looks like this: </p>
<p><code>var cluster = new ClusterMarker(map, options)</code>. </p>
<p><code>map</code> is a reference to the map object and <code>options</code> is an object literal that can have these properties:</p>
<ul>
<li><strong>clusterMarkerIcon [GIcon]</strong>
<p>Changes the default cluster marker icon to an icon of your choice.</li>
<li><strong>markers [array]</strong><br />
An array with all the markers you want to pass to the ClusterMarker</li>
</ul>
<p>Apart from these properties you can also use all the other properties of the class. Se the <a href="http://googlemapsapi.martinpearman.co.uk/readarticle.php?article_id=4">documentation</a> for a complete list.</p>
<p>Here's how to add markers using the ClusterMarker with a minimum amount of code.</p>
<pre name="code" class="js">
var markerArray = [];
// Insert code to fill the markerArray with markers...
// Creating a new cluster by adding the map and the markerarray
var cluster = new ClusterMarker(map, {markers: markerArray});
// Refreshing to show the added markers
cluster.refresh();
</pre>
<p>This code will insert the markers on the map and cluster them under one icon if they're close enough to each other. For more fine grained control of how it operates there are several methods and properties. For a detailed explanation of how the library works there's excellent documentation on the <a href="http://googlemapsapi.martinpearman.co.uk/articles.php?cat_id=1">Clustermarker Project page</a>.</p>
<h2 id="markerclusterer">MarkerClusterer - The new kid in town</h2>
<p>This utility library is the newest of them all and wasn't around when I originally wrote this article. This library, which is written by Xiaoxi Wu and is part of the Google Maps Open Source Utility Library is easy to use and shows excellent performance.</p>
<p>Like some of the other libraries it reduces the number of visible markers by clustering them together making it easier to get an overview. Watch the image below to see how.</p>
<div class="image">
<img src="http://media.svennerberg.com/2009/01/screenshot_clusterereffect.jpg" alt="" class="alignnone" /></p>
<p>Image by <a href="http://googlegeodevelopers.blogspot.com/2009/04/markerclusterer-solution-to-too-many.html">Xiaoxi Wu</a></p>
</div>
<p>It's constructor takes three arguments, the first one being a reference to the map, the second one being an array of GMarkers and the third one being an object literal with options. Only the first one is required.</p>
<p><code>var markerCluster = new MarkerClusterer(map, markers, opts);</code></p>
<p>So to add a bunch of markers to the map having the default settings of the MarkerClusterer you do this:</p>
<pre name="code" class="js">
var markers = [];
// Insert code to fill the markerArray with markers...
// Creating a new cluster by adding the map and the array of markers
var markerCluster = new MarkerClusterer(map, markers);
</pre>
<p>See the <a href="http://gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/docs/reference.html">documentation</a> for a full explanation of the library and it's capabilities. Also read <a href="http://googlegeodevelopers.blogspot.com/2009/04/markerclusterer-solution-to-too-many.html">MarkerClusterer: A Solution to the Too Many Markers Problem</a> on the Google Geo Developer blog for more information.</p>
<p><a href="http://gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/src/markerclusterer.js">Download markerclusterer.js</a></p>
<h2>Compare performance</h2>
<div class="image">
<a href="http://media.svennerberg.com/2008/11/markerperformance.png" title="Measuring performance while adding markers in Google Maps" rel="lightbox[imageset]"><img src="http://media.svennerberg.com/2008/11/markerperformance-410x317.png" alt="" class="alignnone" /></a></p>
<p>Compare the different techniques on the <a href="http://www.svennerberg.com/examples/markers/markerPerformance.html">Test page</a></p>
</div>
<p>Inspired by Pamela Fox testpage for MarkerLight I've set up a <a href="http://www.svennerberg.com/examples/markers/markerPerformance.html" title="Measuring performance while adding markers in Google Maps">test page</a> of my own where you can test the performance of all the different approaches in this article.</p>
<h3 id="test_result">The result</h3>
<p>I ran a series of test with a few different browsers. In each test I added 500 markers using the different techniques. Between each test I refreshed the browsers. All tests were performed on a PC with a 3.60 GHz Pentium 4 HT processor and 2 Gb RAM running Windows XP.</p>
<table class="data">
<caption>Load times in milliseconds (ms)</caption>
<thead>
<tr>
<th></th>
<th scope="col">Google Chrome 1.0.154</th>
<th scope="col">Safari 3.2.1</th>
<th scope="col">Firefox 3.0.10</th>
<th scope="col">Internet Explorer 8.0</th>
<th scope="col">Opera 9.63</th>
<th scope="col" class="avg">Average result</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">GMarker</th>
<td>1649</td>
<td class="best">1168</td>
<td>3020</td>
<td class="worst">3329</td>
<td>1250</td>
<td class="avg">2083</td>
</tr>
<tr>
<th scope="row">MarkerManager</th>
<td>1828</td>
<td>1333</td>
<td>3232</td>
<td class="worst">5485</td>
<td class="best">1297</td>
<td class="avg">2635</td>
</tr>
<tr>
<th scope="row">MarkerLight</th>
<td>393</td>
<td  class="best" >269</td>
<td>797</td>
<td class="worst">860</td>
<td>297</td>
<td class="avg">523</td>
</tr>
<tr>
<th scope="row">MarkerManager + MarkerLight</th>
<td class="best">400</td>
<td>534</td>
<td class="worst">1134</td>
<td>906</td>
<td>469</td>
<td class="avg">689</td>
</tr>
<tr>
<th scope="row">Clusterer2</th>
<td class="best">29</td>
<td>40</td>
<td>66</td>
<td class="worst">109</td>
<td>47</td>
<td class="avg">58</td>
</tr>
<tr>
<th scope="row">ClusterMarker</th>
<td class="best">432</td>
<td>502</td>
<td>832</td>
<td class="worst">1219</td>
<td>500</td>
<td class="avg">697</td>
</tr>
<tr>
<th scope="row">MarkerClusterer</th>
<td class="best">189</td>
<td>527</td>
<td>374</td>
<td class="worst">1047</td>
<td>329</td>
<td class="avg">493</td>
</tr>
</tbody>
</table>
<p class="note"><strong>Note:</strong> Since the addition of MarkerClusterer I've ran the tests again and updated the result grid. Some of the web browsers are newer than in the lats test run. <a href="http://media.svennerberg.com/2009/01/result_table_1.png" rel="lightbox[imageset]" title="The old test result grid">See the old test results</a>.</p>
<p>In this test <strong>Clusterer2</strong> was the fastest technique of them all. Be aware however that this is not the entire truth since I've only been able to measure how long it takes before the markers are passed to the map, not the actual time until they are visible on the map. When taking this into consideration I find that <strong>MarkerClusterer</strong> is the fastest technique closely followed by <strong>ClusterMarker</strong>. </p>
<p>When it comes to browsers the fastest performance is marked with green and the worst performance is marked with red in the result grid. Not surprisingly <strong>Internet Explorer</strong> is the slowest of the lot. <strong>Google Chrome</strong> and <strong>Safari</strong> has the fastest overall performance with their blazing fast Javascript engine.</p>
<p>If you have an idea on how to improve this test to better measure the actual time until the markers are visible on the map, please share in the comments or contact me through the <a href="http://www.svennerberg.com/contact/">Contact page</a>.</p>
<h2>Conclusion</h2>
<p>The techniques showed in this article are all fairly easy to implement and works well when you don't have an incredibly large amount of markers. For those occasions where none of these techniques suffice you will have to resort to more extreme measures, like creating a big overlay with all the markers, but that's beyond the scope of this article. </p>
<p>I hope that you'll find these techniques helpful. Happy coding!</p>
<div class="book_push">
<img src="http://media.svennerberg.com/2009/09/bgma3-70.png" alt="" /></p>
<h3>My Google Maps book</h3>
<p>If you found this article useful you might be interested in my book <a href="/bgma3/" title="Read more about my book - Beginning Google Maps API 3"><strong>Beginning Google Maps API 3</strong></a>. It covers everything you need to know to create awesome maps on your web sites. <a href="http://www.amazon.com/gp/product/1430228024?ie=UTF8&#038;tag=inusabiwetrus-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1430228024" title="Buy Beginning Google Maps Applications from Amazon.com">Buy it on Amazon.com</a><img src="http://www.assoc-amazon.com/e/ir?t=inusabiwetrus-20&#038;l=as2&#038;o=1&#038;a=1430228024" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2009/01/handling-large-amounts-of-markers-in-google-maps/feed/</wfw:commentRss>
		<slash:comments>104</slash:comments>
		</item>
		<item>
		<title>Basic operations with markers in Google Maps</title>
		<link>http://www.svennerberg.com/2008/12/basic-operations-with-markers-in-google-maps/</link>
		<comments>http://www.svennerberg.com/2008/12/basic-operations-with-markers-in-google-maps/#comments</comments>
		<pubDate>Tue, 16 Dec 2008 16:46:40 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[GMarker]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mashups]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=1088</guid>
		<description><![CDATA[Markers is one of the core features in Google Maps and an effective way of displaying places on a map. In this article I will show you how to add a basic marker to a map and also how to &#8230; <a href="http://www.svennerberg.com/2008/12/basic-operations-with-markers-in-google-maps/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/10/maps_logo_small_blue.png" alt="Google Maps" class="alignright" />Markers is one of the core features in Google Maps and an effective way of displaying places on a map. In this article I will show you how to add a basic marker to a map and also how to add some interactivity to it.</p>
<p><span id="more-1088"></span></p>
<h3>Adding a marker</h3>
<p>A marker is a type of overlay, just as it&#8217;s siblings polyline and polygon. To add a basic marker to a Google Map all you have to do is to define it with a coordinate of type <code>GLatLng</code> using the <code>GMarker</code> constructor.</p>
<pre name="code" class="js">
// Init the map
var map = new GMap2(document.getElementById('map'));
map.addControl(new GSmallMapControl());
map.setCenter(new GLatLng(59.5, 14.0), 6);
// Create a marker
var marker = new GMarker(new GLatLng(59.0, 13.80))
// Add the marker to the map
map.addOverlay(marker);
</pre>
<p>This code will create a map and add a basic marker to it. </p>
<p><img src="http://media.svennerberg.com/2008/12/marker.png" alt="marker" class="alignnone" /></p>
<h3>Making it draggable</h3>
<p>To make the marker draggable is really easy. the GMarker constructor takes options in the form of an object literal as it&#8217;s second parameter. You simply add <code>{draggable: true}</code> after the coordinates. </p>
<pre name="code" class="js">
var marker = new GMarker(new GLatLng(59.0, 13.80), {draggable: true});
</pre>
<p>Voila, the marker is now draggable. This is excellent for applications where you want the user to define places on a map.</p>
<h3>Adding a Tooltip</h3>
<p>Adding a tooltip is done the same way as making the marker draggable. It&#8217;s done using another option called <code>title</code>.  It will create the same kind of tooltip that adding the attribute <code>title</code> to HTML-elements does.</p>
<pre name="code" class="js">
var marker = new GMarker(new GLatLng(59.0, 13.80), {
    draggable: true,
    title: 'Drag me'
});
</pre>
<p>This code will produce a standard tooltip when putting the cursor over the marker.</p>
<p><img src="http://media.svennerberg.com/2008/12/tooltip.png" alt="" class="alignnone" /></p>
<p>There are a lot of other options you can add to a marker. For a full list check out the <a href="http://code.google.com/intl/sv/apis/maps/documentation/reference.html#GMarkerOptions" title="Google Maps API Documentation - GMarkerOptions">documentation</a>.</p>
<h3>Adding an Info Window</h3>
<p>An InfoWindow is a great way to show more information about a location. It&#8217;s done by adding a click event to the marker with the help of the <code>GEvent</code> class. When the click event is triggered, the InfoWindow is opened using the method <code>GMarker2.openInfoWindow()</code>.</p>
<pre name="code" class="js">
// Adding a click event to the marker
GEvent.addListener(marker, "click", function() {
    marker.openInfoWindow('My InfoWindow');
});
</pre>
<p>The result is a standard GInfoWindow which open up when you click the marker. You can close it by either clicking the closing X in the upper right corner or by clicking somewhere in the map.</p>
<p><img src="http://media.svennerberg.com/2008/12/infowindow.png"  class="alignnone" /></p>
<p>GMarker.openInfoWindow is the most basic variant of InfoWindows in the API and can only contain plain text. Other types can contain HTML and have tabs. For a full description of the other options available check out the <a href="http://code.google.com/intl/sv/apis/maps/documentation/reference.html#GMarker" title="Google Maps API Documentaition - GMarker">Documentation</a>.</p>
<h4>Preventing InfoWindow offset</h4>
<p>When using a combination of drag and drop and infowindow a weird thing can happen. It&#8217;s that the InfoWindow stay in the same place while the marker is moved. </p>
<p><img src="http://media.svennerberg.com/2008/12/dragdropmarker.png" alt="" class="alignnone" /></p>
<p>To prevent this we have to make sure to close the InfoWindow when initiating the drag and drop operation. This is done by listening to the event with <code>GEvent.addListener</code> and close the window with <code>GMap2.closeInfoWindow()</code>.</p>
<pre name="code" class="js">
// Close InfoWindow at dragstart
GEvent.addListener(marker, 'dragstart', function() {
    map.closeInfoWindow();
});
</pre>
<h3>Live example</h3>
<p>I&#8217;ve put together a live example which contains all the techniques described in this article. </p>
<p><a href="http://www.svennerberg.com/examples/markers/basicOperations.html" title="Basic Marker Example">Watch the live example</a>.</p>
<h3>Conclusion</h3>
<p>Markers is an effective way of displaying places on a map. It has a simple yet powerful set of methods to create interactivity. The techniques described here are just a few of all the things you can do, but I think they&#8217;ll provide a good starting point.</p>
<div class="book_push">
<img src="http://media.svennerberg.com/2009/09/bgma3-70.png" alt="" /></p>
<h3>My Google Maps book</h3>
<p>If you found this article useful you might be interested in my book <a href="/bgma3/" title="Read more about my book - Beginning Google Maps API 3"><strong>Beginning Google Maps API 3</strong></a>. It covers everything you need to know to create awesome maps on your web sites. <a href="http://www.amazon.com/gp/product/1430228024?ie=UTF8&#038;tag=inusabiwetrus-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1430228024" title="Buy Beginning Google Maps Applications from Amazon.com">Buy it on Amazon.com</a><img src="http://www.assoc-amazon.com/e/ir?t=inusabiwetrus-20&#038;l=as2&#038;o=1&#038;a=1430228024" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2008/12/basic-operations-with-markers-in-google-maps/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Unobtrusive Google Maps</title>
		<link>http://www.svennerberg.com/2008/12/unobtrusive-google-maps/</link>
		<comments>http://www.svennerberg.com/2008/12/unobtrusive-google-maps/#comments</comments>
		<pubDate>Fri, 12 Dec 2008 06:30:20 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Accessibility]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mashups]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=1010</guid>
		<description><![CDATA[When developing web applications we can never be sure what the environment for the user is. He could for example use our application from a mobile device with a browser with limited Javascript support. Like Roger Johansson pointed out in &#8230; <a href="http://www.svennerberg.com/2008/12/unobtrusive-google-maps/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/10/maps_logo_small_blue.png" alt="" class="alignright" />When developing web applications we can never be sure what the environment for the user is. He could for example use our application from a mobile device with a browser with limited Javascript support. Like Roger Johansson pointed out in <a href="http://www.456bereastreet.com/archive/200812/making_google_maps_more_accessible/">Making Google Maps more accessible</a>, we must prevent our applications from breaking under these circumstances by making them degrade gracefully. </p>
<p>In this article I will show you how to make Google Maps degrade gracefully by providing a fallback for non-javascript users using the <a href="http://code.google.com/apis/maps/documentation/staticmaps/">Google Static Maps API</a>.</p>
<p><span id="more-1010"></span></p>
<h3>The map switch</h3>
<p>The technique is simple. First you have a Google Static Map on your web page, which in fact is a static image. If Javascript is enabled, the static image is overwritten with a dynamic map.</p>
<p>A Static Google Map is simply an ordinary image, dynamically created at Google and displayed on your webpage. You decide how it will appear by passing arguments in the querystring of the image URL. A sample URL could look like this:</p>
<pre>

http://maps.google.com/staticmap?center=59.1,14.0&#038;zoom=6&#038;size=420x300&#038;key=YOUR_KEY_HERE
</pre>
<p>This URL will generate a map that look like this:</p>
<p><img src="http://maps.google.com/staticmap?center=59.1,14.0&#038;zoom=6&#038;size=420x300&#038;key=ABQIAAAAE6Bacn8vThk2qjFRnuSSLhSTHIzSPFf37An04HmblPYaEa2AOBS_EnzjaIs3nN0IixLsMdk9mJeamA" alt="" /></p>
<p>From this example it&#8217;s quite easy to see the different arguments in the query string:</p>
<ul>
<li><strong>center</strong><br />
Defines the center of the map with a coordinate (x, y)</li>
<li><strong>zoom</strong><br />
Sets the zoom-level (1-18) </li>
<li><strong>size</strong><br />
Defines the size of the map in pixels (width x height)</li>
<li><strong>key</strong><br />
Your Google Maps API key. Note that in the example URL the key is omitted. If you don&#8217;t already have one you can <a href="http://code.google.com/apis/maps/signup.html">sign up</a> for one for free.</li>
</ul>
<h4>The switch</h4>
<p>This is easy as pie. Just do as normal. The only difference is that you put an image with the static map inside the <code>&lt;div&gt;</code> for the dynamic map. If the dynamic map is loaded it will automatically replace the content of the <code>&lt;div&gt;</code>.</p>
<p>The HTML will look like this:</p>
<pre name="code" class="html">
&lt;div id="map"&gt;
    &lt;img src="http://maps.google.com/staticmap?center=59.1,14.0&#038;zoom=6&#038;size=420x300&#038;key=YOUR_KEY_HERE" alt="" /&gt;
&lt;/div&gt;
</pre>
<p>And the Javascript will look something like this:</p>
<pre name="code" class="js">
window.onload = function(){
    if (GBrowserIsCompatible()) {
        // Init the map
        var map = new GMap2(document.getElementById('map'));
        map.setCenter(new GLatLng(59.5, 14.0), 6);
    }
}
</pre>
<p>And there you have it! A map that degrades gracefully if the user lacks Javascript support.</p>
<p class="note"><strong>Note:</strong> To avoid that the switch appears as a flicker in the browser I recommend using a DOM-loader that executes after the DOM has been loaded. All major Javascript libraries like <a href="http://www.jquery.com/">jQuery</a> and <a href="http://www.prototypejs.org/">Prototype</a> has these.</p>
<h3>Live example</h3>
<p>I&#8217;ve constructed an example page to show the concept. In the example I also add markers to the map. To learn how to do this read the article <a href="http://www.svennerberg.com/?p=1038">Simple maps with the Google Static Maps API</a>.</p>
<p><a href="http://www.svennerberg.com/examples/unobtrusive_google_maps/">Try the live example</a></p>
<div class="book_push">
<img src="http://media.svennerberg.com/2009/09/bgma3-70.png" alt="" /></p>
<h3>My Google Maps book</h3>
<p>If you found this article useful you might be interested in my book <a href="/bgma3/" title="Read more about my book - Beginning Google Maps API 3"><strong>Beginning Google Maps API 3</strong></a>. It covers everything you need to know to create awesome maps on your web sites. <a href="http://www.amazon.com/gp/product/1430228024?ie=UTF8&#038;tag=inusabiwetrus-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1430228024" title="Buy Beginning Google Maps Applications from Amazon.com">Buy it on Amazon.com</a><img src="http://www.assoc-amazon.com/e/ir?t=inusabiwetrus-20&#038;l=as2&#038;o=1&#038;a=1430228024" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2008/12/unobtrusive-google-maps/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Simple maps with the Google Static Maps API</title>
		<link>http://www.svennerberg.com/2008/12/simple-maps-with-the-google-static-maps-api/</link>
		<comments>http://www.svennerberg.com/2008/12/simple-maps-with-the-google-static-maps-api/#comments</comments>
		<pubDate>Mon, 08 Dec 2008 19:33:04 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[Mashups]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=1038</guid>
		<description><![CDATA[Google Static Maps API is an easy way to provide a map when the user doesn&#8217;t have Javascript available. Sure it&#8217;s not near as powerful as the full Google Maps API but still, it can provide you with a basic &#8230; <a href="http://www.svennerberg.com/2008/12/simple-maps-with-the-google-static-maps-api/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/10/maps_logo_small_blue.png" alt="" class="alignright" />Google Static Maps API is an easy way to provide a map when the user doesn&#8217;t have Javascript available. Sure it&#8217;s not near as powerful as the full Google Maps API but still, it can provide you with a basic map that can contain both markers and paths.</p>
<p><span id="more-1038"></span></p>
<h3>A basic map</h3>
<p>The basic concept is to generate an image by adding a regular image tag <code>&lt;img&gt;</code> to the document and in the <code>src</code> attribute add an URL to Google that generates a map image. In the querystring of the URL you define how the map will appear.</p>
<p>Here&#8217;s a basic example:</p>
<pre name="code" class="html">
&lt;img src="http://maps.google.com/staticmap?center=59.1,14.0&#038;zoom=6&#038;size=420x300&#038;key=YOUR_KEY_HERE" alt="" /&gt;
</pre>
<p>which will result in this image:</p>
<p><img src="http://maps.google.com/staticmap?center=59.1,14.0&#038;zoom=6&#038;size=420x300&#038;key=ABQIAAAAE6Bacn8vThk2qjFRnuSSLhSTHIzSPFf37An04HmblPYaEa2AOBS_EnzjaIs3nN0IixLsMdk9mJeamA" alt="" /></p>
<p>The parameters used in this example are:</p>
<ul>
<li><strong>center</strong><br />
Defines the center of the map with a coordinate (x, y)</li>
<li><strong>zoom</strong><br />
Sets the zoom-level (1-18) </li>
<li><strong>size</strong><br />
Defines the size of the map in pixels (width x height)</li>
<li><strong>key</strong><br />
Your Google Maps API key. Note that in the example URL the key is omitted. If you don&#8217;t already have a key you can <a href="http://code.google.com/apis/maps/signup.html">sign up</a> for one for free.</li>
</ul>
<h3>Adding markers</h3>
<p>The use of markers in the map is quite limited but you can put up to 50 markers on a map in 10 different colors and in 3 different sizes with an optional letter in it on the map. Naturally you can&#8217;t interact with them in any way since that requires Javascript.</p>
<p>The basic syntax is:</p>
<pre>
markers=markerDescriptor1|markerDescriptor2|markerDescriptor3|
</pre>
<p>Each marker is separated with a pipe character (|). It&#8217;s then defined with its coordinates and then with its characteristics: <code>lat, lng, size|color|letter</code>. The last parameter is the most cryptic one since the words are all crammed together. A normal sized red marker with the letter A in it will look like <code>midreda</code> (eg. mid red a).</p>
<p>This code will generate 3 markers with different characteristics. The first one will be a normal red marker with the letter A in it [midreda]. The second one will be small with the color green [smallgreen] and the last one will be really small and orange [tinyorange].</p>
<pre>
markers=59.0,13.8,midreda|59.35,15.60,smallgreen|59.73,13.12,tinyorange
</pre>
<p><img src="http://maps.google.com/staticmap?markers=59.0, 13.8,midreda|59.35, 15.60,smallgreen|59.73, 13.12,tinyorange&#038;size=420x300&#038;key=ABQIAAAAE6Bacn8vThk2qjFRnuSSLhSTHIzSPFf37An04HmblPYaEa2AOBS_EnzjaIs3nN0IixLsMdk9mJeamA" alt="" /></p>
<p>The parameters in this example are:</p>
<ul>
<li><strong>latitude</strong><br />
The latitude of the markers position.</li>
<li><strong>longitude</strong><br />
The longitude of the markers position.</li>
<li><strong>size</strong><br />
Defines the size of the marker. Valid values are <code>mid</code>, <code>small</code>, <code>tiny</code>. If none is specified it defaults to <code>mid</code>.</li>
<li><strong>color</strong><br />
The marker can have one of 10 different colors Valid colors are: black, brown, green, purple, yellow, blue, gray, orange, red, white. Default is red.</li>
<li><strong>alphanumeric-character</strong><br />
An optional character can be placed inside medium sized markers [a-z] [0-9]. Note that small and tiny markers cannot contain a character.
</ul>
<h4>No need for center or zoom</h4>
<p>One cool thing with static maps is that if you have markers on it you don&#8217;t have to define the center of the map or the zoom-level. It&#8217;s automatically calculated for you so all markers will fit. You can of course override it by explicitly defining center and zoom.</p>
<h3>Adding paths</h3>
<p>A path is a line built up of 2 or more coordinates. To add a path to a static map you use <code>path:</code> with a set of parameters.</p>
<p>There&#8217;s two kinds of parameters. The first kind defines the visual look of the path and the second kind the coordinates.</p>
<h4>The visual look of a path</h4>
<p>There are three parameters for the visual look of a path:</p>
<ul>
<li><strong>rgb</strong><br />
This is a 24-bit hex color value determining the color of the path. For example <code>rgb:0x0000ff</code>. With this parameter you can&#8217;t control the opacity of the path which defaults to 50%</li>
<li><strong>rgba</strong><br />
This is a 32-bit hex color value determining the color of the path. The last 2 characters sets the alpha channel. For example <code>rgba:0x0000ffff</code></li>
<li><strong>weight</strong><br />
Specifies the thickness of the path in pixels. For example <code>weight:5</code></li>
</ul>
<h4>The coordinates</h4>
<p>A path is made up of 2 or more coordinates. You can currently have up to 100 coordinates for each path. The coordinates are separated by a pipe character (|) like this: <code>59.0,13.8|59.2,13.9</code>.</p>
<p>A red semi transparent path made up of 5 coordinates would for example look like this</p>
<pre>
path=rgb:0x0000ff,weight:5|59.0,13.8|59.2,13.9|59.0,13.0|59.5,13.0|58.1,12.8
</pre>
<p><img src="http://maps.google.com/staticmap?path=rgb:0x0000ff,weight:5|59.9,12.8|60.0,13.5|59.0,13.7|59.0,13.0|59.3,12.0&#038;size=420x300&#038;key=ABQIAAAAE6Bacn8vThk2qjFRnuSSLhSTHIzSPFf37An04HmblPYaEa2AOBS_EnzjaIs3nN0IixLsMdk9mJeamA" alt="" /></p>
<p>Note that just like with the markers you don&#8217;t need to supply the map with center and zoom level when using a path. The map will automatically display in a way so that the entire path is visible.</p>
<h3>Optional parameters</h3>
<p>There&#8217;s some other things you can do with this API. Here&#8217;s some more optional parameters to play around with.</p>
<ul>
<li><strong>format</strong><br />
This paramater lets you determain which image format the returned map should be in. Valid values are: gif, jpg, jpg-baseline, png8, png32. Default value is gif.</li>
<li><strong>maptype</strong><br />
Defines the maptype. Possible values are roadmap, satellite, terrain, hybrid, and mobile. The default value is roadmap</li>
<li><strong>span</strong><br />
This defines the minimum size of the viewport expressed as a <code>latitude, longitude</code>. The API calculates the appropriate from the center point and the span. If zoom is defined span is ignored.</li>
<li><strong>frame</strong><br />
Defines that the image should be framed with a 5px, 55% opacity blue border. Valid values are <code>true</code> or <code>false</code>.</li>
<li><strong>hl</strong><br />
Sets the language to be used on tile labels. Not all tiles support different languages, on these the default language is used.</li>
<li><strong>sensor</strong><br />
This parameter specifies if the application is using a sensor to determine the users location. Valid values are <code>true</code> or <code>false</code>.</li>
</ul>
<p class="note">For a full description of the Google Static Maps API, visit the <a href="http://code.google.com/apis/maps/documentation/staticmaps/">API page at Google</a>.</p>
<h3>The Static Map Wizard</h3>
<p>If you&#8217;re lazy you can use the <a href="http://gmaps-samples.googlecode.com/svn/trunk/simplewizard/makestaticmap.html">Static Map Wizard</a> to create the URL for you. It&#8217;s an excellent tool making it really easy to create a map with markers and polylines.</p>
<p>It&#8217;s done in four easy steps.</p>
<ol>
<li>Find the place on the map you want to show. Draw polylines and insert markers into the map by dragging and dropping.<br />
<img src="http://media.svennerberg.com/2008/12/staticmapwizard_1.png" alt="" title="staticmapwizard_1" width="500" height="340" class="alignnone size-full wp-image-1014" /></li>
<li>Define how you want the map, markers and paths to appear<br />
<img src="http://media.svennerberg.com/2008/12/staticmapwizard_2.png" alt="" class="alignnone" /></li>
<li>Watch the generated image<br />
<img src="http://media.svennerberg.com/2008/12/staticmapwizard_3.png" alt="" class="alignnone" />
</li>
<li>Get the created URL<br/>
<pre>http://maps.google.com/staticmap?center=37.400465,-122.073003&#038;markers=37.404119,-122.061024,brown|37.391436,-122.053299,brown&#038;path=rgba:0xff000099,weight:6|37.39561,-122.08952|37.39125,-122.07064|37.40025,-122.06188|37.40998,-122.10291|37.39561,-122.08952&#038;path=rgba:0xff000099,weight:6|37.38947,-122.10686&#038;zoom=13&#038;size=300x300&#038;key=YOUR_KEY_HERE</pre>
</li>
</ol>
<p>Note that you manually have to add your API key at the end of the URL.</p>
<h3>Conclusion</h3>
<p>The Google Static Maps API is naturally not a replacement for the full Google Maps API. But it can provide basic functionality when you either just want a really simple and lightweight map or when the user doesn&#8217;t have Javascript available. </p>
<div class="book_push">
<img src="http://media.svennerberg.com/2009/09/bgma3-70.png" alt="" /></p>
<h3>My Google Maps book</h3>
<p>If you found this article useful you might be interested in my book <a href="/bgma3/" title="Read more about my book - Beginning Google Maps API 3"><strong>Beginning Google Maps API 3</strong></a>. It covers everything you need to know to create awesome maps on your web sites. <a href="http://www.amazon.com/gp/product/1430228024?ie=UTF8&#038;tag=inusabiwetrus-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1430228024" title="Buy Beginning Google Maps Applications from Amazon.com">Buy it on Amazon.com</a><img src="http://www.assoc-amazon.com/e/ir?t=inusabiwetrus-20&#038;l=as2&#038;o=1&#038;a=1430228024" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2008/12/simple-maps-with-the-google-static-maps-api/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Ultimate Site Logo 2 &#8211; For real this time</title>
		<link>http://www.svennerberg.com/2008/11/ultimate-site-logo-2-for-real-this-time/</link>
		<comments>http://www.svennerberg.com/2008/11/ultimate-site-logo-2-for-real-this-time/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 08:18:24 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[Site logo]]></category>
		<category><![CDATA[XHTML]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=792</guid>
		<description><![CDATA[After writing my first article on the subject, Ultimate Site Logo, I&#8217;ve come up with two significant enhancements.. With the original solution, there were two major flaws. The first one was a semantic one and the other one a more &#8230; <a href="http://www.svennerberg.com/2008/11/ultimate-site-logo-2-for-real-this-time/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>After writing my first article on the subject, <a href="http://www.svennerberg.com/2008/06/ultimate-site-logo/">Ultimate Site Logo</a>, I&#8217;ve come up with two significant enhancements.. With the original solution, there were two major flaws. The first one was a semantic one and the other one a more obvious and technical one.</p>
<p>This time around I think I&#8217;ve got all the details right. Well, if that&#8217;s not <a href="http://en.wikipedia.org/wiki/Kaizen">Kaizen</a>, what is?</p>
<p><span id="more-792"></span></p>
<h3>The old article</h3>
<p>In the original article, <a href="http://www.svennerberg.com/2008/06/ultimate-site-logo/">Ultimate Site Logo</a>, I described how to code a site logo to meet these needs:</p>
<ul>
<li>Search engine optimized</li>
<li>Clickable</li>
<li>Accessible</li>
<li>Looks good</li>
<li>Hover effect</li>
</ul>
<p>If you haven&#8217;t already read it, this could be a good time to do so to fully grasp the concept. But if you feel confident enough, then by all means, do read on.</p>
<h3>The semantic problem</h3>
<p>In my first solution I suggested that <code>&lt;h1&gt;</code> would be an appropriate element to host the logo. Even though I already back then felt that a different element could be used, I personally was leaning more towards <code>&lt;h1&gt;</code>.</p>
<p>After reading up a little and listening to remarks from others I have now changed my mind. Especially after reading Chris Pearsons article <a href="http://www.pearsonified.com/2007/04/definitive-guide-to-semantic-markup.php">The Definitive Guide to Semantic Web Markup for Blogs</a>. </p>
<p>I now believe that <code>&lt;h1&gt;</code> should be reserved for the most prominent heading on each individual page. So for the front page, the logo (e.g. site name) might as well be the most prominent one, while on sub pages such as an article page, the articles title should be the most prominent one. </p>
<p>Therefor I now recommend using a <code>div</code> to hold the site logo. The code for this would be:</p>
<pre name="code" class="xhtml">
&lt;div id="branding"&gt;
	&lt;div id="logo"&gt;&lt;a href="#"&gt;&lt;span>&lt;/span&gt;In usability we trust&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
</pre>
<p class="note"><strong>Note:</strong> I haven&#8217;t actually implemented this technique on this site yet, but I will do so in an upcoming redesign. Still you can watch it in action on the <a href="http://www.svennerberg.com/examples/ultimate_site_logo_2/">example page</a> for this article.</p>
<h3>The flicker problem</h3>
<p>In my last solution I changed the background-image of the <code>&lt;span&gt;</code> displaying the logo, when hovering over it. The problem with this is that if the hover-image wasn&#8217;t cashed, there would be an occasional flicker revealing the text underneath it, before the image was loaded. To solve this issue I now use <a href="http://www.alistapart.com/articles/sprites/" title="CSS Sprites: Image Slicing’s Kiss of Death - Article by Dave Shea on A List Apart">CSS sprites</a> instead. </p>
<p>A sprite is basically an image that contains several images, in this case two. The trick is to, with the help of CSS, just show a part of it at a time. By aligning the background-image to either the left or the right side of the <code>&lt;span&gt;</code>, a roll-over effect is created.</p>
<p><a href="http://media.svennerberg.com/2008/11/logo_sprite.png" title="The sprite for the two different states of the logo" rel="lightbox[imageset]"><img src="http://media.svennerberg.com/2008/11/logo_sprite-410x57.png" alt=""  class="alignnone" /></a></p>
<p>As you can see this image contains two version of the logo, one in normal state and one in hover-state. By making the container only half the width of the complete image, it&#8217;s easy to show the different versions by either aligning the background-image to the left or to the right side of the container.</p>
<p><a href="http://media.svennerberg.com/2008/11/logo_sprite_masked.png"title= "The logo in normal state - Only the normal image is visible in the containing &lt;div&gt;. " rel="lightbox[imageset]"><img src="http://media.svennerberg.com/2008/11/logo_sprite_masked-410x57.png" alt="" class="alignnone" /></a></p>
<p>The logo in it&#8217;s normal state, where only the left part of the image is visible in the containing <code>&lt;div&gt;</code> (the red area). </p>
<p><a href="http://media.svennerberg.com/2008/11/logo_sprite_masked_hover.png" title="The logo in hover state - Only the hover image is visible in the containing &lt;div&gt;. " rel="lightbox[imageset]"><img src="http://media.svennerberg.com/2008/11/logo_sprite_masked_hover-410x57.png" alt="" class="alignnone" /></a></p>
<p>The logo in it&#8217;s hover state, where only the right part of the image is visible in the containing <code>&lt;div&gt;</code> (the red area).</p>
<p>The CSS to accomplish this is:</p>
<pre name="code" class="css">
#logo span {
	background: url(../img/logo_sprite.png) left top no-repeat;
}
#logo a:hover span {
	background-position: right top;
}
</pre>
<p>It was actually a comment from <a href="http://www.dollypower.com/">r-doll</a> on a <a href="http://www.svennerberg.com/2008/09/imagemap-rollover/" title="Imagemap rollover">different article of mine</a> that made me realize that CSS-sprites would be the way to go in this solution too. Thanks a lot!</p>
<h4>The (almost) complete CSS</h4>
<p>I say almost complete because there is two additional Internet Explorer fixes, that is best put in a separate CSS-file only served to IE.</p>
<pre name="code" class="css">
#logo {
	position: relative;
	margin: 0;
	width: 442px;
	height: 125px;
}
#logo a {
	position: absolute;
	width: 100%;
	height: 100%;
}
#logo span {
	position: absolute;
	z-index: 1;
	width: 100%;
	height: 100%;
	background: url(../img/logo_sprite.png) left top no-repeat;
}
#logo a:hover span {
	background-position: right top;
}
</pre>
<p class="note"><strong>Note:</strong> For a full explanation of the CSS and the additional fixes needed for IE, read the old article, <a href="http://www.svennerberg.com/2008/06/ultimate-site-logo/">Ultimate Site Logo</a>.</p>
<h3>Further improvements</h3>
<p>If you can think of further improvements I would be more than happy if you would share it with me.</p>
<p>One issue that I&#8217;m aware of is when printing the web page. The logo just shows if you have <em>print background images</em> turned on, otherwise the text underneath the logo will show. If you have a solution for this, please let me know!</p>
<h3>The files</h3>
<ul>
<li><a href="http://www.svennerberg.com/examples/ultimate_site_logo_2/">Watch the live demo</a></li>
<li><a href="http://www.svennerberg.com/examples/ultimate_site_logo_2/css/style.css">style.css</a> [The main style sheet]</li>
<li><a href="http://www.svennerberg.com/examples/ultimate_site_logo_2/css/ie.css">ie.css</a> [Style sheet fed to IE alone]</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2008/11/ultimate-site-logo-2-for-real-this-time/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

