<?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/"
	xmlns:series="http://unfoldingneurons.com/"
	>

<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>A blog about web developement and usability.</description>
	<lastBuildDate>Thu, 22 Jul 2010 23:18:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<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 the MarkerManager The MarkerManager is a very useful Open Source Utility Library for Google Maps [...]]]></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>
<h3>Using the MarkerManager</h3>
<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>
<h3>Adding markers with the MarkerManager</h3>
<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>
<h3>Hiding and showing markers</h3>
<p>In the Google Maps <acronym title="Application Programming Interface">API</acronym> 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>
<h3>A bug</h3>
<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>
<h4>The solution</h4>
<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>
<h4>isHidden()</h4>
<p>The Google Maps <acronym title="Application Programming Interface">API</acronym> 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>
<h3>Live examples</h3>
<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>
<h3>Other libraries</h3>
<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 <acronym title="Application Programming Interface">API</acronym> 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>4</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 uneccesary user interaction. In this article I will describe how to create it with the [...]]]></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 <acronym title="HyperText Markup Language">HTML</acronym></h3>
<p>The <acronym title="HyperText Markup Language">HTML</acronym> is straightforward. Just insert this code somewhere in your <acronym title="HyperText Markup Language">HTML</acronym>. 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 <acronym title="Internet Explorer">IE</acronym>
         // If we have no timeout <acronym title="Internet Explorer">IE</acronym> 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 <acronym title="Internet Explorer">IE</acronym> 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 Codex and googling for a solution I couldn&#8217;t quite find an example that took all [...]]]></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>
<h3>Checking if the page has subpages</h3>
<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>
<h3>Checking if it&#8217;s a parent page or a subpage</h3>
<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>
<h3>Fetching the submenu</h3>
<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>
<h3>Outputting the <acronym title="HyperText Markup Language">HTML</acronym></h3>
<p>The last step is to output the actual <acronym title="HyperText Markup Language">HTML</acronym>. 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>
<h3>Putting it all together</h3>
<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>
<h3>Conclusion</h3>
<p>I think that WordPress is an absolutely awesome <acronym title="Content Management System">CMS</acronym>/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>38</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 different kinds of Info Windows that appear when you click on a marker. Content Basic [...]]]></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>
<h3>Content</h3>
<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>
<h3 id="basic">Basic Info Window</h3>
<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>
<h3 id="tabs">Info Window with Tabs</h3>
<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>
<h3 id="minimap">Info Window containing a Mini map</h3>
<p>The <acronym title="Application Programming Interface">API</acronym> 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>
<h3 id="maximizing">Maximizing the Info Window</h3>
<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>
<h3 id="GInfoWindowOption">Options</h3>
<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 <acronym title="HyperText Markup Language">HTML</acronym> string or an <acronym title="HyperText Markup Language">HTML</acronym> <acronym title="Document Object Model">DOM</acronym> element.</li>
<li><strong>maxTitle [string]</strong><br />
Sets the title for the window when it&#8217;s maximized. It can be either an <acronym title="HyperText Markup Language">HTML</acronym> string or an <acronym title="HyperText Markup Language">HTML</acronym> <acronym title="Document Object Model">DOM</acronym> 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>
<h4>How to use them</h4>
<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>
<h3 id="conclusion">Conclusion and further resources</h3>
<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 <acronym title="Application Programming Interface">API</acronym> Utility Library</a>. Joe Monahan has also written some about it on the Google Maps <acronym title="Application Programming Interface">API</acronym> Blog in the article <a href="http://googlemapsapi.blogspot.com/2007/12/extinfowindow-10-ajax-powered-css.html">ExtInfoWindow 1.0: Ajax powered, <acronym title="Cascading Style Sheets">CSS</acronym> customization</a>.</p>
<p>Mike William at <a href="http://econym.org.uk/gmap/index.htm">Google Maps <acronym title="Application Programming Interface">API</acronym> 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 <acronym title="Application Programming Interface">API</acronym> 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>39</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 show you a few approaches to speed up performance. I&#8217;ve also put together a test [...]]]></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>
<h3>The Marker Manager &#8211; Keeps track of them</h3>
<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>
<h4>A simple example</h4>
<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>
<h4>Bulk adding the markers</h4>
<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>
<h4>Additional methods</h4>
<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 <acronym title="Uniform Resource Locator">URL</acronym> 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 <acronym title="Subversion">SVN</acronym></a></p>
<h3>Marker Light - Markers on a diet</h3>
<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 <acronym title="Document Object Model">DOM</acronym> 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 <acronym title="Uniform Resource Locator">URL</acronym> (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>
<h3>Using Marker Light in combination with MarkerManager</h3>
<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>
<h3>Clusterer - Only show what you need</h3>
<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>
<h3 id="markerclusterer">MarkerClusterer - The new kid in town</h3>
<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>
<h3>Compare performance</h3>
<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>
<h4 id="test_result">The result</h4>
<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 <acronym title="Gigahertz">GHz</acronym> 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>
<h3>Conclusion</h3>
<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 <acronym title="Application Programming Interface">API</acronym> 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>67</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 add some interactivity to it. Adding a marker A marker is a type of overlay, [...]]]></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 <acronym title="HyperText Markup Language">HTML</acronym>-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 <acronym title="Application Programming Interface">API</acronym> and can only contain plain text. Other types can contain <acronym title="HyperText Markup Language">HTML</acronym> 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 <acronym title="Application Programming Interface">API</acronym> 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>11</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 Making Google Maps more accessible, we must prevent our applications from breaking under these circumstances [...]]]></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 <acronym title="Application Programming Interface">API</acronym></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 <acronym title="Uniform Resource Locator">URL</acronym>. A sample <acronym title="Uniform Resource Locator">URL</acronym> 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 <acronym title="Uniform Resource Locator">URL</acronym> 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 <acronym title="Application Programming Interface">API</acronym> key. Note that in the example <acronym title="Uniform Resource Locator">URL</acronym> 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 <acronym title="HyperText Markup Language">HTML</acronym> 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 <acronym title="Document Object Model">DOM</acronym>-loader that executes after the <acronym title="Document Object Model">DOM</acronym> 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 <acronym title="Application Programming Interface">API</acronym></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 <acronym title="Application Programming Interface">API</acronym> 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 map that can contain both markers and paths. A basic map The basic concept is [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/10/maps_logo_small_blue.png" alt="" class="alignright" />Google Static Maps <acronym title="Application Programming Interface">API</acronym> 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 <acronym title="Application Programming Interface">API</acronym> 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 <acronym title="Uniform Resource Locator">URL</acronym> to Google that generates a map image. In the querystring of the <acronym title="Uniform Resource Locator">URL</acronym> 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 <acronym title="Application Programming Interface">API</acronym> key. Note that in the example <acronym title="Uniform Resource Locator">URL</acronym> 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 <acronym title="Application Programming Interface">API</acronym>. 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 <acronym title="Application Programming Interface">API</acronym> 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 <acronym title="Application Programming Interface">API</acronym>, visit the <a href="http://code.google.com/apis/maps/documentation/staticmaps/"><acronym title="Application Programming Interface">API</acronym> 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 <acronym title="Uniform Resource Locator">URL</acronym> 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 <acronym title="Uniform Resource Locator">URL</acronym><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 <acronym title="Application Programming Interface">API</acronym> key at the end of the <acronym title="Uniform Resource Locator">URL</acronym>.</p>
<h3>Conclusion</h3>
<p>The Google Static Maps <acronym title="Application Programming Interface">API</acronym> is naturally not a replacement for the full Google Maps <acronym title="Application Programming Interface">API</acronym>. 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 <acronym title="Application Programming Interface">API</acronym> 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 obvious and technical one. This time around I think I&#8217;ve got all the details right. [...]]]></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"><acronym title="Cascading Style Sheets">CSS</acronym> 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 <acronym title="Cascading Style Sheets">CSS</acronym>, 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 <acronym title="Cascading Style Sheets">CSS</acronym> 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 <acronym title="Cascading Style Sheets">CSS</acronym>-sprites would be the way to go in this solution too. Thanks a lot!</p>
<h4>The (almost) complete <acronym title="Cascading Style Sheets">CSS</acronym></h4>
<p>I say almost complete because there is two additional Internet Explorer fixes, that is best put in a separate <acronym title="Cascading Style Sheets">CSS</acronym>-file only served to <acronym title="Internet Explorer">IE</acronym>.</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 <acronym title="Cascading Style Sheets">CSS</acronym> and the additional fixes needed for <acronym title="Internet Explorer">IE</acronym>, 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 <acronym title="Internet Explorer">IE</acronym> 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>
		<item>
		<title>Populating Google Maps with Microformats revisited</title>
		<link>http://www.svennerberg.com/2008/11/populating-google-maps-with-microformats-revisited/</link>
		<comments>http://www.svennerberg.com/2008/11/populating-google-maps-with-microformats-revisited/#comments</comments>
		<pubDate>Sun, 16 Nov 2008 15:51:38 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Mashups]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=446</guid>
		<description><![CDATA[A few month ago I posted about a demo where I used content marked up with Microformats to populate a Google map using Javascript. Well, now I&#8217;ve improved that demo somewhat. Please read about my first take in Using microformats to populate Google Map. The demo is still in Swedish since I originally made it [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/11/mf-logo.gif" alt="" title="mf-logo" width="100" height="98" class="alignright size-full wp-image-838" />A few month ago I posted about a demo where I used content marked up with Microformats to populate a Google map using Javascript. Well, now I&#8217;ve improved that demo somewhat. </p>
<p><span id="more-446"></span></p>
<p>Please read about my first take in <a href="http://www.svennerberg.com/2008/05/using-microformats-to-populate-google-map/">Using microformats to populate Google Map</a>.</p>
<p>The demo is still in Swedish since I originally made it for a lecture here in Sweden about using Microformats. But despite that I think it&#8217;s fairly easy for all you non-swedes to follow the code. </p>
<p><a href="http://media.svennerberg.com/2008/10/screenshot.png" rel="lightbox[imageset]" title="Screenshot of the mashup."><img src="http://media.svennerberg.com/2008/10/screenshot-410x316.png" alt="" class="alignnone" /></a></p>
<p><a href="http://www.svennerberg.com/examples/visfestivaler/">Watch the live demo</a></p>
<p>So what have I done in this new version?</p>
<h3>Updated the Google Maps code</h3>
<p>In the old demo I used some deprecated Google Maps 1.0 methods. In the new demo these are replaced with Google Maps 2 methods.</p>
<p><code>GPoint</code> is changed to <code>GLatLng</code><br />
<code>GMap.centerAndZoom()</code> is changed to <code>GMap2.setCenter()</code></p>
<h3>Switched Javascript Library</h3>
<p>I have switched Javascript library from <a href="http://www.domassistant.com/">DOMAssistant</a> to <a href="http://www.jquery.com/">jQuery</a>. Lately I&#8217;ve been working a lot with jQuery so it seemed like a natural switch. </p>
<h3>Added a slider</h3>
<p>I wanted to be able to easily filter the result by month using a slider. Since <a href="http://ui.jquery.com/">jQuery UI</a> features a nice Slider I went with that. </p>
<p><img src="http://media.svennerberg.com/2008/10/slider.png" alt="" class="alignnone" /></p>
<p>Adding the slider was fairly easy. I used the default graphics and just tweaked the slider-background a little bit in Photoshop.</p>
<p>To put the slider in place all that is needed is to add a div with <code>id="date_slider"</code> to the <acronym title="HyperText Markup Language">HTML</acronym>-document and the code below:</p>
<pre name="code" class="js">
$('#date_slider').slider({
	handle: '.handle',
	steps: 3,
	min: 5,
	max: 8,
	startValue: 8,
	slide: function(e, ui) {
		// Changing the label to the selected monthname
		$('#selected_month').html(monthName(ui.value));
	},
	change: function(e, ui) {
		// filtering event list
		filterEventList(ui.value);

		// filtering markers on map
		filterMap(ui.value);
	}
});
</pre>
<h3>Scrolling the list</h3>
<p>When you click on a marker in the map the appropriate element in the sidebar list is highlighted. When the list is long enough to be scrollable it sometimes means that the highlighted item isn&#8217;t visible. I wanted a way to make the list scroll so the item came into view.</p>
<p>The jQuery plugin <a href="http://plugins.jquery.com/project/ScrollTo">ScrollTo</a> came to the rescue. It&#8217;s a really nice plugin that makes it easy to do just this. The syntax is: <code>$(element).scrollTo(obj);</code></p>
<p>Where <code>element</code> is the list and <code>obj</code> is the selected item.</p>
<h3>The files</h3>
<p>If you want to try the demo and check out the files, please use the links below.</p>
<ul>
<li><a href="http://www.svennerberg.com/examples/visfestivaler/">View the Live Demo</a></li>
<li><a href="http://www.svennerberg.com/examples/visfestivaler/js/map.js">map.js</a></li>
<li><a href="http://www.svennerberg.com/examples/visfestivaler/css/style.css">style.css</a></li>
</ul>
<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 <acronym title="Application Programming Interface">API</acronym> 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/11/populating-google-maps-with-microformats-revisited/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Polylines in Google Maps [Part 2]</title>
		<link>http://www.svennerberg.com/2008/11/polylines-in-google-maps-part-2/</link>
		<comments>http://www.svennerberg.com/2008/11/polylines-in-google-maps-part-2/#comments</comments>
		<pubDate>Thu, 06 Nov 2008 17:05:56 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mashups]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=687</guid>
		<description><![CDATA[In part 1 I showed how to use and optimize performance on polylines in Google Maps using Javascript. In this article I will show you how to get even better performance by encoding the polylines on the server. Encoding polylines on the fly When dealing with dynamic data you may have to encode the polylines [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/10/maps_logo_small_blue.png" alt="" class="alignright" />In <a href="http://www.svennerberg.com/2008/10/polylines-in-google-maps/">part 1</a> I showed how to use and optimize performance on polylines in Google Maps using Javascript. In this article I will show you how to get even better performance by encoding the polylines on the server.</p>
<p><span id="more-687"></span></p>
<h3>Encoding polylines on the fly</h3>
<p>When dealing with dynamic data you may have to encode the polylines on the fly. In this example I will use <acronym title="Pre-Hypertext Processing">PHP</acronym> to perform the encoding. I have rewritten a <a href="http://www.jimhribar.com/cgi-bin/moin.cgi/PolylineEncoder">php script made by Jim Hribar</a> and built his functions into a class for more convenient use. I&#8217;ve also made some small changes to the code. The code itself is essentially a rip-off from <a href="http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/">Mark MacClure&#8217;s</a> Javascript class.</p>
<h3>The PolylineEncoder Class</h3>
<p>To use the class is simple. First you need to call the constructor of the class: <code>$polylineEncoder = new PolylineEncoder($point); </code></p>
<h4>The constructor</h4>
<p>PolylineEncoder optionally takes four other arguments. When they are left out these default settings are used:</p>
<ul>
<li>numLevels = 18</li>
<li>zoomFactor = 2</li>
<li>verySmall = 0.00001</li>
<li>forceEndpoints = true</li>
</ul>
<p><code><strong>numLevels</strong></code> and <code><strong>zoomFactor</strong></code> controls how many zoomlevels the encoding should take account for and in which intervals the map should change the number of displayed coordinates. </p>
<p><code><strong>verySmall</strong></code> controls what distance between coordinate the algorithm should regard a short enough distance for a coordinate to be removed. So if you want to decrease the number of coordinates used, you should set the <code><strong>verySmall</strong></code> argument to a higher number.</p>
<p><code><strong>forceEndpoints</strong></code> is a boolean and if set to true ensures that the two ending points of the polyline are displayed at all zoom-levels. I really don&#8217;t see a reason to set this to anything but true.</p>
<p>I myself tend to use the default settings since they provide a good result. </p>
<h4>Encoding the points</h4>
<p>The <code>$encoded_polyline = polylineEncoder->dpEncode()</code> method returns an associative array with the following keys. </p>
<ul>
<li><strong>Points</strong><br />
A string containing the encoded points</li>
<li><strong>Levels</strong><br />
A string containing the encoded levels</li>
<li><strong>ZoomFactor</strong><br />
The applied Zoom Factor (Same as passed to the constructor)</li>
<li><strong>NumLevels</strong><br />
The applied NumLevels (Same as passed to the constructor)</li>
</ul>
<p>A complete call to the EncodePolyline could look something like this.</p>
<pre name="code" class="php">
// Include the file containing the class
include("PolylineEncoder.php");

// Create a nested array containing the coordinates
$points = array(
	array(
		59.6919,
		17.8582
	),
	array(
		59.3030,
		18.0395
	),
	array(
		58.9789,
		17.5341
	)
);

// Create a new instance of PolylineEncoder and supply the array
// as an argument to the constructor
$polylineEncoder = new PolylineEncoder($points);

// Encode the coordinates by calling dpEncode(), it returns an array containing the
// encoded coordinates and levels.
$encoded_points = $polylineEncoder->dpEncode();

// The resulting output
$encoded_points["Points"]; // "kqikJw|~kBr}jAclb@rh~@xuaB"
$encoded_points["Levels"]; // "PMP
$encoded_points["ZoomFactor"]; // 2
$encoded_points["NumLevels"]; // 18
</pre>
<p class="note"><strong>Note:</strong> To learn more about how to use the optional settings for tweaking the encoded polyline, read <a href="http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/description.html">A description of Google&#8217;s encoded polylines</a> and <a href="http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/algorithm.html">The encoding algorithm for the levels string</a>.</p>
<h4>Download the class</h4>
<p>The PolylineEncoder class is released under <del datetime="2010-03-12T15:11:47+00:00"><acronym title="GNU General Public License">GPL</acronym></del> <ins datetime="2010-03-12T15:11:47+00:00"><acronym title="Massachusetts Institute of Technology">MIT</acronym> license</ins> and may be used and changed freely.</p>
<p><a href="http://www.svennerberg.com/examples/polylines/PolylineEncoder.php.txt">Download PolylineEncoder.php.txt</a></p>
<h3>Making use of the encoded polyline</h3>
<p>Now that we have an encoded polyline its time to make good use of it in Google Maps. To create a GPolyline from the encoded coordinates you use the method <code>GPolyline.fromEncoded()</code>. </p>
<pre name="code" class="js">
// Creating an encoded GPolyline
GPolyline.fromEncoded({
    color: string,
    weight: number,
    opacity: number,
    points: string,
    levels: string,
    numLevels: number,
    zoomFactor: number
});
</pre>
<p>As you can see it takes an object literal as an argument. The first three keys are purely for how the polyline will be styled. The keys <code>points</code> and <code>levels</code> are the ones that will be fed with the encoded polyline. The last two keys, <code>numLevels</code> and <code>zoomFactor</code> should match the settings you used when encoding the coordinates. If they don&#8217;t match, the polyline will not be rendered correctly.</p>
<div class="note">
<h4>Documentation alert</h4>
<p>The <a href="http://code.google.com/apis/maps/documentation/reference.html#GPolyline">documentation</a> doesn&#8217;t seem to be quite up to date on this, since it specifies the method to be used like this:</p>
<p><code>GPolyline.fromEncoded(color?, weight?, opacity?, latlngs, zoomFactor, levels, numLevels)</code></p>
<p class="last">Stay clear from this use since it&#8217;s deprecated and probably won&#8217;t work or eventually will stop working.</p>
</div>
<h4>Adding it to the map</h4>
<p>So adding an encoded polyline to your map is very much like adding a normal polyline to it. The only difference is that instead of creating the polyline with the constructor of GPolyline(), you call the <code>GPolyline.fromEncoded()</code> method and pass the encoded points and levels to it.</p>
<pre name="code" class="js">
// Instanciate a new map
var map = new GMap2(document.getElementById('map'));
map.setCenter(new GLatLng(59.3219, 17.6165), 8);

// Create the polyline from the encoded points
var polyline = GPolyline.fromEncoded({
    color: '#FF0000',
    weight: 6,
    opacity: 0.6,
    points: 'kqikJw|~kBr}jAclb@rh~@xuaB',
    levels: 'PMP',
    numLevels: 18,
    zoomFactor: 2
});

// Add the polyline to the map
map.addOverlay(polyline);
</pre>
<p><a href="http://www.svennerberg.com/examples/polylines/polylines_encoded_server_side.html">Watch the live example</a>.</p>
<h3>Even better performance</h3>
<p>To get even better performance you have to use a pre-encode polyline to serve directly to the Javascript. This way you save the time the <acronym title="Pre-Hypertext Processing">PHP</acronym>-script takes to execute the encoding. In many cases this might not be possible, but if it is, it delivers the best performance.</p>
<p><a href="http://www.svennerberg.com/examples/polylines/polylines_pre-encoded.html">Watch the pre-encoded example</a>.</p>
<p>The improved load-time is pretty big. When I compare this example with <a href="http://www.svennerberg.com/examples/polylines/polylines_encoded.html">the one encoding the polyline in the browser</a> using Javascript, I get load times that&#8217;s range from 2 seconds (Safari) to over 20 seconds faster (<acronym title="Internet Explorer">IE</acronym>). </p>
<h3>All test scenarios</h3>
<p>Here&#8217;s all the tested cases, from both this and <a href="http://www.svennerberg.com/2008/10/polylines-in-google-maps/" title="Polylines in Google Maps [Part 1]">the previous article</a>.</p>
<ul>
<li><a href="http://www.svennerberg.com/examples/polylines/polylines.html">Simple unencoded polyline</a></li>
<li><a href="http://www.svennerberg.com/examples/polylines/polylines_big.html">Complex unencoded polylines</a></li>
<li><a href="http://www.svennerberg.com/examples/polylines/polylines_encoded.html">Complex encoded polylines, encoding done in browser with Javascript</a></li>
<li><a href="http://www.svennerberg.com/examples/polylines/polylines_encoded_server_side.html">Complex encoded polylines, encoding done dynamically on server</a></li>
<li><a href="http://www.svennerberg.com/examples/polylines/polylines_pre-encoded.html">Complex pre-encoded polylines</a></li>
</ul>
<h3>Other resources</h3>
<p>There are several server-side classes in different languages for encoding polylines, including <acronym title="Practical Extraction and Report Language">Perl</acronym>, Java and Ruby, available at <a href="http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/">Encoding polylines for Google Maps</a>, a website by Mark McClure.</p>
<p>I have yet to find a class written in C#. If you find one or has written one yourself, I would be more than happy if you could tell me about it.</p>
<div class="note">
<h4>Update [2008-11-26]</h4>
<p>I have now written a C# class to encode polylines by porting Mark Rambows Java class. I&#8217;ve also made some other modification to it to make it easier and more natural for C# coders to use. </p>
<p><a href="http://www.svennerberg.com/examples/polylines/PolylineEncoder.cs">Download PolylineEncoder.cs</a></p>
<p>Encouraged by this article, markw has also made a C# class, which can be download from <a href="http://code.google.com/p/csharp-polyline-encoder/">Google Code</a>.
</div>
<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 <acronym title="Application Programming Interface">API</acronym> 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/11/polylines-in-google-maps-part-2/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>Bounding Box in Google Maps</title>
		<link>http://www.svennerberg.com/2008/11/bounding-box-in-google-maps/</link>
		<comments>http://www.svennerberg.com/2008/11/bounding-box-in-google-maps/#comments</comments>
		<pubDate>Sun, 02 Nov 2008 19:20:02 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mashups]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=640</guid>
		<description><![CDATA[Normally when you initialize a new Google map you set the coordinates for the center of the map and manually specifies the initial zoom level. Sometimes, however, there&#8217;s a need to dynamically calculate the center point and zoom level for certain content to fit into the viewport. Let&#8217;s say that you have a number of [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/10/maps_logo_small_blue.png" alt="" class="alignright" />Normally when you initialize a new Google map you set the coordinates for the center of the map and manually specifies the initial zoom level. Sometimes, however, there&#8217;s a need to dynamically calculate the center point and zoom level for certain content to fit into the viewport.</p>
<p><span id="more-640"></span></p>
<p>Let&#8217;s say that you have a number of markers on a map and you want the map to be displayed so that they all fit inside the viewport. You could of course experiment with center point and zoom levels to get it right. But what if the markers are put there dynamically so you don&#8217;t know beforehand where they&#8217;ll show up?</p>
<p>That&#8217;s where this trick will come in handy. </p>
<h3>Using a Bounding Box</h3>
<p>First you have to calculate the <strong>bounding box</strong>. That is, the coordinate for the <strong>south-west</strong> and <strong>north-east</strong> corners. In this case the coordinates for the marker that&#8217;s most south and the marker that&#8217;s most west provides the coordinates for the south-west corner. And vice versa for the north-east corner.</p>
<p><img src="http://media.svennerberg.com/2008/10/map_boundingbox.png" alt="" class="alignnone" /></p>
<p>Now that you know the coordinates you just have to create a <code><a href="http://code.google.com/apis/maps/documentation/reference.html#GLatLngBounds">GLatLngBounds</a></code> object, define it&#8217;s coordinates and serve it to <code>GMap2.setCenter()</code>.</p>
<p><code>GLatLngBounds</code> takes two optional arguments. A <code>GLatLng</code> for the south-west corner and a <code>GLatLng</code> for the north-east corner.</p>
<p><code>GMap2.getBoundsZoomLevel()</code> calculates the appropriate zoom level to fit the bounding box in the available viewport. It also adds some extra padding around the box.</p>
<pre name="code" class="js">
map = new GMap2(document.getElementById("map"));

// Define the two corners of the bounding box
var sw = new GLatLng(59.0, 13.12);
var ne = new GLatLng(60.35, 16.90);

// Create a bounding box
var bounds = new GLatLngBounds(sw, ne);

// Center map in the center of the bounding box
// and calculate the appropriate zoom level
map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
</pre>
<p><a href="http://www.svennerberg.com/examples/bounding_box/">Watch the live demo</a></p>
<p>I was shown this technique by my good friend Fredrik Jonsson, who writes about programming on <a href="http://www.freddes.se/">freddes.se</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 <acronym title="Application Programming Interface">API</acronym> 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/11/bounding-box-in-google-maps/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Polylines in Google Maps [Part 1]</title>
		<link>http://www.svennerberg.com/2008/10/polylines-in-google-maps/</link>
		<comments>http://www.svennerberg.com/2008/10/polylines-in-google-maps/#comments</comments>
		<pubDate>Tue, 28 Oct 2008 11:32:38 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mashups]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=546</guid>
		<description><![CDATA[Polylines are used to mark out roads, borders and other things that are made of lines in maps. The Google Maps API offers a class for drawing these lines on a Google Map called GPolyline. In this article I will show you how to use these and how to deal with potential performance issues when [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/10/maps_logo_small_blue.png" alt="" class="alignright" />Polylines are used to mark out roads, borders and other things that are made of lines in maps. The Google Maps <acronym title="Application Programming Interface">API</acronym> offers a class for drawing these lines on a Google Map called <code>GPolyline</code>. In this article I will show you how to use these and how to deal with potential performance issues when the polylines gets more complex.</p>
<p><span id="more-546"></span></p>
<h3>A basic polyline</h3>
<p>Polylines consists of several points forming a line. Like for example a road on a map.  </p>
<p>Normally you create a <a href="http://code.google.com/apis/maps/documentation/reference.html#GPolyline"><code>GPolyline</code></a> and add it to the map using <code>GMap2.addOverlay()</code>.</p>
<pre name="code" class="js">
// Create an instance of Google map
var map = new GMap2(document.getElementById("map"));

// Tell the map where to start
map.setCenter(new GLatLng(59.3324, 17.8857), 9);

// Create an array with points
var points = [
   new GLatLng(59.6919, 17.8582),
   new GLatLng(59.3030, 18.0395),
   new GLatLng(58.9789, 17.5341)
];

// Create a new polyline
var polyline = new GPolyline(points, '#ff0000', 5, 0.7);

// Add the polyline to the map using map.addOverlay()
map.addOverlay(polyline);
</pre>
<p>As you can see <code>GPolyline</code> takes four arguments. The first one is the only required one, and it&#8217;s the coordinates for the polyline. The other ones are optional and are settings for how the polyline will appear. They are, from left to right, the color, the thickness and the opacity of the polyline.</p>
<p><a href="http://svennerberg.com/examples/polylines/polylines.html">Watch the small polyline example</a>.</p>
<p>This works fine as long as the polyline doesn&#8217;t consist of too many coordinates. However when the polyline is more complex the rendering becomes really slow. </p>
<h3>More complex polylines</h3>
<p>Here&#8217;s an example of five polylines with a total of 7841 coordinates which are added to the map the same way as the previous example. You&#8217;ll notice that the performance is really starting to degrade. The load time is longer and when you zoom in or out on the map you&#8217;ll notice a significant delay. </p>
<p><a href="http://www.svennerberg.com/examples/polylines/polylines_big.html">Watch the complex polylines example</a>  (Warning: The loading time can be long)</p>
<p>The performance vary from browser to browser. So if you try the example with Internet Explorer it&#8217;s really slow, but with Safari or Google Chrome it&#8217;s still pretty fast.</p>
<h4>Data format</h4>
<p>In the example the coordinates are fetched through an <acronym title="Asynchronous JavaScript and XML">AJAX</acronym> call to a file containing the coordinates in JSON format. The data structure looks like this:</p>
<pre name="code" class="js">
[{
    "Name":"Section 1",
    "Geom":[[59.1949,17.6596],[59.1942,17.6591],[59.1941,17.659]]
},
{
    "Name":"Section 2",
    "Geom":[[59.3819,18.0088],[59.3819,18.0089],[59.3818,18.0091]]
},
</pre>
<p>I only show three points per Section here but in the used file there a total of five Sections with thousands of points each. </p>
<h3>Better performance</h3>
<h4>Decrease the number of coordinates</h4>
<p>One easy way to make it faster is to try to limit the number of coordinates that you serve to the map. You gain some performance but loose accuracy, especially when you zoom in on the page. </p>
<h4>Encoded polylines on the fly</h4>
<p>A far better solution is to encode the polylines. It provides much better performance than just decreasing the number of coordinates plus you get better accuracy. The algorithm that encodes the coordinates removes some coordinates but more importantly decreases the number of coordinates when you zoom out, and increase them when zooming in.</p>
<p>Here&#8217;s how it&#8217;s done.</p>
<p>Instead of just feeding the map with coordinates you first encode them. An excellent encoder is Mark McClure&#8217;s PolylineEncoder class. It&#8217;s available from <a href="http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/">Encoding polylines for Google Maps</a>. You can also download <a href="http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/PolylineEncoder.js">PolylineEncoder.js</a> from there.</p>
<p>The encoder doesn&#8217;t make a very big difference on the loading time of the page, but when you start zooming and panning, the difference is huge.</p>
<h4>Encoding the coordinates</h4>
<p>Put all your coordinates in an array and feed it to <code>dpEncodeToGPolyline()</code> in the <code>polylineEncoder</code> class. The coordinates should be in the <a href="http://code.google.com/apis/maps/documentation/reference.html#GLatLng">GLatLng</a> format. </p>
<p>As you may notice <code>dpEncodeToGPolyline()</code> takes exactly the same arguments as <code>GPolyline()</code> and returns a <code>GPolyline</code>. So basically you just call <code>dpEncodeToGPolyline()</code> instead of <code>GPolyline()</code> and then add it to the map with <code>addOverlay()</code>, just like you did with the regular polyline.</p>
<pre name="code" class="js">
// Create an array that will hold the coordinates
var points = [];

// Loop through the coordinates.
// In this case the coordinates are in a JSON object
for(var j = 0; j < json[i].Geom.length; j++) {
    var coords = json[i].Geom[j];
    //Convert the coordinates to GLatLng and insert into the array
    points.push(new GLatLng(parseFloat(coords[0]), parseFloat(coords[1])));
}

// Create a new instance of PolylineEncoder
var polylineEncoder = new PolylineEncoder();

// Assign the array to dpEncodeToGPolyline  to get an encoded polyline
var polyline = polylineEncoder.dpEncodeToGPolyline(points, '#ff0000', 5, 0.7);

// Add the returned polyline to the map with map.addOverlay()
map.addOverlay(polyline);
</pre>
<p>The performance boost with this technique is enormous. The loading time can still be quite long but interacting with the map is a totally different experience. <a href="http://svennerberg.com/examples/polylines/polylines_encoded.html">Watch the encoded polylines example</a> to see what I mean.</p>
<div class="note">
<h4>About the encoding algorithm</h4>
<p>The encoding algorithm is basically a reduction of unnecessary coordinates at different zoom-levels. The more you zoom-in, the more detail is revealed and the opposite around when you zoom-out.</p>
<p>For an in-depth explanation of how the algorithm works, check out Mark McClure's excellent articles on the subject: <a href="http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/description.html">Description of encoded polylines</a> and <a href="http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/algorithm.html">An explanation of the algorithm</a>. Also read <a href="http://code.google.com/apis/maps/documentation/polylinealgorithm.html">Encoded Polyline Algorithm Format</a> on Google.
</div>
<h4>Encode polylines on the server</h4>
<p>Loading time could still be too long, especially in Internet Explorer which has a a notoriously slow Javascript engine. To improve on that you should perform the encoding server side. In the <a href="http://www.svennerberg.com/2008/11/polylines-in-google-maps-part-2/" title="Polylines in Google maps [Part 2]">second part</a> of this article I describe how to do just that using <acronym title="Pre-Hypertext Processing">PHP</acronym>, to get dramatically shorter load-times.</p>
<h3>Further reading</h3>
<p>Mark MacClure, as I've already mentioned, has written a lot on the subject and also provides several examples, so don't miss checking <a href="http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/">Encoding polylines for Google Maps</a> out.</p>
<p>Peter Chng has written an article about encoded polylines, <a href="http://unitstep.net/blog/2008/05/11/playing-with-google-maps-and-encoded-polylines/">Playing with Google Maps and encoded polylines</a>,  that helped clear a lot of my confusion.</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 <acronym title="Application Programming Interface">API</acronym> 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/10/polylines-in-google-maps/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>ASP.NET MVC and JSON</title>
		<link>http://www.svennerberg.com/2008/10/aspnet-mvc-and-json/</link>
		<comments>http://www.svennerberg.com/2008/10/aspnet-mvc-and-json/#comments</comments>
		<pubDate>Wed, 22 Oct 2008 21:19:39 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=550</guid>
		<description><![CDATA[In the AJAX community, JSON have become the preferred way of sending and receiving data. That&#8217;s not surprising since it&#8217;s lightweight, fast and easy to understand. Also, since it&#8217;s a subset of Javascript, it&#8217;s familiar territory for Javascript coders. In the ASP.NET MVC Framework, passing JSON from the server to the client script is almost [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/08/aspnetlogo_200.gif" alt="" class="alignright" />In the <acronym title="Asynchronous JavaScript and XML">AJAX</acronym> community, <a href="http://json.org/" title="JavaScript Object Notation">JSON</a> have become the preferred way of sending and receiving data. That&#8217;s not surprising since it&#8217;s lightweight, fast and easy to understand. Also, since it&#8217;s a subset of Javascript, it&#8217;s familiar territory for Javascript coders.</p>
<p>In the <a href="http://www.asp.net/mvc/"><acronym title="Active Server Pages">ASP</acronym>.NET MVC Framework</a>, passing JSON from the server to the client script is almost too easy. In this article I will walk you through the code required to make it work.</p>
<p><span id="more-550"></span></p>
<h3>The back end</h3>
<p>Suppose we have a class named <code>Cars</code> like the one below. We want to feed our web page with a list of cars that we want to display <acronym title="Asynchronous JavaScript and XML">AJAX</acronym> style, preferably by sending the list as a JSON object.</p>
<pre name="code" class="c#">
public class Car {
	public string Name { get; set; }
	public string Color { get; set; }
}
</pre>
<p>With the <acronym title="Active Server Pages">ASP</acronym>.NET MVC Framework it&#8217;s a breeze. In your Controller you simply create a method of the type <code>JsonResult</code> which returns a JSON object. You then use the <code>Json()</code> method to transform the class to JSON.</p>
<pre name="code" class="c#">
public class CarsController : Controller
{
	public JsonResult GetCars()
	{
		List&lt;Car&gt; cars = Cars.GetCars();
		return this.Json(cars);
	}
}
</pre>
<p>Calling this method will return JSON that looks something like this: </p>
<pre name="code" class="js">
[{&quot;Name&quot;:&quot;Saab&quot;,&quot;Color&quot;:&quot;Red&quot;},{&quot;Name&quot;:&quot;Volvo&quot;,&quot;Color&quot;:&quot;Blue&quot;}]
</pre>
<h3>Making the <acronym title="Asynchronous JavaScript and XML">AJAX</acronym> call</h3>
<p>To get the list of cars on the client side, you want to make an <acronym title="Asynchronous JavaScript and XML">AJAX</acronym> call to the Controller method <code>GetCars()</code>. This is done by calling the <acronym title="Uniform Resource Locator">URL</acronym> <code>/Cars/GetCars/</code>. </p>
<p>First I&#8217;ll walk you through how to do it with pure Javascript. Then I&#8217;ll show you how to do it with the jQuery library.</p>
<h4>The Classic Javascript way</h4>
<p>First of all you have to create an instance of the <code>XMLHttpRequest </code>object. It&#8217;s through this object that you communicate with the back end. Since <acronym title="Internet Explorer">IE</acronym> 6 doesn&#8217;t support this object but do have support for an ActiveX object that essentially does the same thing, we initially have to do some checking to make sure that we use the correct object. I&#8217;ve created a wrapper function that with the help of object detection determines which object to use and then returns it.</p>
<pre name="code" class="js">
function getRequestObject() {
	var req = false;
	if(window.XMLHttpRequest) {
		req = new XMLHttpRequest();
	} else if(window.ActiveXObject) {
		req = new ActiveXObject(&quot;Microsoft.XMLHTTP&quot;);
	}
	return req;
}
</pre>
<p>I use the <code>getRequestObject</code> function to get the correct Request Object and then gets on with setting up the request. </p>
<pre name="code" class="js">
var request = getRequestObject();
request.onreadystatechange = handleResponse;
request.open('GET', '/Cars/GetCars', true);
request.send(null);
</pre>
<p class="note"><strong>Note:</strong> If you&#8217;re unfamiliar with <acronym title="Asynchronous JavaScript and XML">AJAX</acronym> and find this code really strange, I recommend that you read <a href="https://developer.mozilla.org/en/AJAX/Getting_Started">getting started with <acronym title="Asynchronous JavaScript and XML">AJAX</acronym></a> from Mozilla Developer Center.</p>
<p>Ok, so the <acronym title="Asynchronous JavaScript and XML">AJAX</acronym> Call is all set up. The last thing to do is to create the function <code>handleResponse</code> that takes care of the request and the received data.</p>
<pre name="code" class="js">
function handleResponse() {
	if (request.readyState == 4) {
		var cars = eval('(' + request.responseText + ')');

		for each(car in cars) {
			alert(car.Name + ', ' + car.Color);
		}
	}
}
</pre>
<p>The object is received as JSON text through the <code>responseText</code> property of the request object. To convert it to a JSON object you can use the <code>Eval()</code> function. It will parse the text and produce an object structure. This is a fast and convenient way of doing it, but be aware of that it has potential security issues. Only use it if you know that you can trust the source. Otherwise you should use a more robust JSON parser.</p>
<p>The code in this example will throw an alert for each item in the JSON object and display it&#8217;s properties. This is done by looping through the received object. Notice how we can access the properties of the object through convenient dot notation. </p>
<h4>The jQuery way</h4>
<p>The client side scripting is even easier using <a href="http://jQuery.com/">jQuery</a>. All the Javascript code above can be replaced with this.</p>
<pre name="code" class="js">
$.getJSON(&quot;/Cars/GetCars&quot;, null, function(data) {
	$.each(data, function(index, car) {
		alert(car.Name, car.Color)
	});
});
</pre>
<p>jQuery handles everything that happens in the background, like instantiating the request object and parsing the received JSON object. So it does all the heavy lifting and leaves the fun stuff to you, like doing creative things with the received data.</p>
<p class="note"><strong>Note: </strong> For brevity I have excluded all error handling in this example. This should naturally always be considered in a live application.</p>]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2008/10/aspnet-mvc-and-json/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Effective Use of Custom Icons in Google Maps</title>
		<link>http://www.svennerberg.com/2008/10/effective-use-of-custom-icons-in-google-maps/</link>
		<comments>http://www.svennerberg.com/2008/10/effective-use-of-custom-icons-in-google-maps/#comments</comments>
		<pubDate>Wed, 15 Oct 2008 08:36:58 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mashups]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=476</guid>
		<description><![CDATA[I&#8217;m currently developing a web application that uses Google Maps and have lots of markers with custom icons to mark different things on the map. To administer all these different icons is quite a chore and it took me some time to find an effective way of working with them. The problem At first I [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/10/maps_logo_small_blue.png" alt="Google Maps" class="alignright" />I&#8217;m currently developing a web application that uses Google Maps and have lots of markers with custom icons to mark different things on the map. To administer all these different icons is quite a chore and it took me some time to find an effective way of working with them. </p>
<p><span id="more-476"></span></p>
<h3>The problem</h3>
<p>At first I coded each custom icon individually, creating massive amounts of code. I then had to have a huge If-else statement to determine which icon to use on each type of marker. This didn&#8217;t feel right and also made the application unnecessarily bloated and redundant, so I started looking for a better way of doing this. Eventually I stumbled upon this solution in one of <a href="http://econym.org.uk/gmap/" title="Google Maps API Tutorial">Mike Williams excellent Google Maps tutorials</a>.</p>
<h3>The solution</h3>
<p>The solution is all about storing the icons in an associative array that you later on call to get the correct icon.</p>
<h4>Defining the icon</h4>
<p>Start of by defining a &#8220;template&#8221;-icon that you base your other icons on. </p>
<pre name="code" class="js">
var custIcon = new GIcon(G_DEFAULT_ICON);
custIcon.iconSize = new GSize(16, 16);
custIcon.shadowSize = new GSize(0, 0);
custIcon.iconAnchor = new GPoint(0, 0);
</pre>
<p>I&#8217;m using the optional copy argument in the GIcon constructor. You don&#8217;t have to do this but it&#8217;s convenient since all the properties of the icons are otherwise empty and you have to manually define them yourself.</p>
<p class="note"><strong>Note:</strong> To learn more about how markers and icons works in Google Maps read the <a href="http://code.google.com/apis/maps/documentation/overlays.html" title="Map Overlays - Google Maps API">section on overlays in the Google Maps <acronym title="Application Programming Interface">API</acronym> documentation</a>.</p>
<h4>Creating the array</h4>
<p>The next step is to define an array and start adding icons to it. Since it&#8217;s an associative array I use labels instead of numbers to identify each item.</p>
<p>Also notice that I add my template icon and a specific image for each individual icon in the GIcon constructor.</p>
<pre name="code" class="js">
var myIcons = [];
myIcons['house'] = new GIcon(custIcon, 'house.png');
myIcons['castle'] = new GIcon(custIcon, 'castle.png');
</pre>
<h4>Putting the array to use</h4>
<p>Later on when you want to place a marker in the map and assign it one of your custom icons you just write this.</p>
<pre name="code" class="js">
var marker = new GMarker(point, { icon: myIcons['house']});
</pre>
<p>In the application I&#8217;m currently building I give the array-items the same label as the <code>type</code> they represent. So instead of using a huge if-else statement to get the right icon, I just have to write one line of code where I insert my <code>type</code> as label for the array.</p>
<pre name="code" class="js">
var marker = new GMarker(point, { icon: myIcons[type]});
</pre>
<p>Simple, effective and elegant!</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 <acronym title="Application Programming Interface">API</acronym> 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/10/effective-use-of-custom-icons-in-google-maps/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>User Controls in ASP.NET MVC Preview Release 5</title>
		<link>http://www.svennerberg.com/2008/10/user-controls-in-aspnet-mvc-preview-release-5/</link>
		<comments>http://www.svennerberg.com/2008/10/user-controls-in-aspnet-mvc-preview-release-5/#comments</comments>
		<pubDate>Fri, 03 Oct 2008 15:14:42 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=479</guid>
		<description><![CDATA[I&#8217;ve had a little trouble finding out how to use User Controls in the ASP.NET MVC Framework and how to pass data to it. I haven&#8217;t been able to find a single article that clearly explains how to do this, so I thought I&#8217;ll do a little write up on the topic. Since Preview Release [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/08/aspnetlogo_200.gif" alt="" class="alignright" />I&#8217;ve had a little trouble finding out how to use User Controls in the <acronym title="Active Server Pages">ASP</acronym>.NET MVC Framework and how to pass data to it. I haven&#8217;t been able to find a single article that clearly explains how to do this, so I thought I&#8217;ll do a little write up on the topic. </p>
<p><span id="more-479"></span></p>
<p>Since Preview Release 5 of the <acronym title="Active Server Pages">ASP</acronym>.NET MVC Framework, the handling of User Controls have changed a bit. The helper method <code>RenderUserControl</code> have been replace by <code>RenderPartial</code>. A little annoying thing when a User Control is imported into a View is a tiny difference in how it&#8217;s coded that is easily overlooked. So if you get this cryptic error:</p>
<blockquote><p>CS1502: The best overloaded method match for &#8216;System.IO.TextWriter.Write(char)&#8217; has some invalid arguments</p></blockquote>
<p>It&#8217;s because you&#8217;ve been inserting the User Control with <code>&lt;%= RenderPartial("ViewName") %&gt;</code>, instead of <code>&lt;% RenderPartial("ViewName");  %&gt;</code>. (Note the equal sign before the method call and the semicolon after).</p>
<h3>Passing a Data Object from the Controller to the View</h3>
<p>Suppose you have a class called <code>Car</code> with the properties <code>Make </code>and <code>Color</code>, that you want to render using a User Control.</p>
<p>In order to pass data to the User Control, you first have to pass it from the Controller to the View. This is done by either sending the Data Object in the <code>Return</code> statement in a <code>ActionResult</code> method like this:</p>
<pre>
<code>public ActionResult List() 
{
	List&lt;Car&gt; cars = cars.GetCars();
	return View(cars);
}</code>
</pre>
<p>Or assign it explicitly to the <code>ViewData</code> object like this:</p>
<pre>
<code>public ActionResult List() 
{
	List&lt;Car&gt; cars = cars.GetCars();
	ViewData[&quot;Cars&quot;] = cars;

	return View();
}</code>
</pre>
<p>I often find it more convenient to do it the first way, but when you have several data objects that you want to pass, you&#8217;ll have to use the second way too.</p>
<h3>Passing DataObject to the User Control</h3>
<p>Like I mentioned earlier in this article, the MVC Framework has a useful helper method for inserting User Control into Views. It&#8217;s called <code>RenderPartial</code>. Before the Preview Release 5 it was called <code>RenderUserControl</code> and was used a little different. So don&#8217;t confuse the two.</p>
<p>It&#8217;s used like this:</p>
<pre>
<code>&lt;% Html.RenderPartial(&quot;~/Views/Cars/List.ascx&quot;); %&gt;</code>
</pre>
<p>To pass a list containing several instances of <code>Car</code> from the View to the User Control is easy. You just add it as the second parameter in the <code>RenderPartial</code> call like this:</p>
<pre>
<code>&lt;% Html.RenderPartial(&quot;~/Views/Cars/List.ascx&quot;, ViewDataModel); %&gt;</code>
</pre>
<p>or if you explicity assigned it to the ViewData object:</p>
<pre>
<code>&lt;% Html.RenderPartial(&quot;~/Views/Cars/List.ascx&quot;, ViewData["Cars"]); %&gt;</code>
</pre>
<h3>Displaying the data in the User Control</h3>
<p>In the User Control you have to first add a reference to the class <code>Car</code> in the CodeBehind. And since you want a list of it you have to use <code>List<></code> around it:</p>
<pre>
<code>public partial class List : System.Web.Mvc.ViewUserControl&lt;List&lt;Car&gt;&gt;
{
}</code>
</pre>
<p>In the <code>.ascx</code> you then access the data by referencing to the <code>ViewData.Model</code>, just like you would in a View. So rendering a simple list of cars would look something like this:</p>
<pre>
<code>&lt;ul&gt;
&lt;% foreach(Car car in ViewData.Model) { %&gt;
	&lt;li&gt;&lt;%= car.Make %&gt;, &lt;%= car.Color %&gt;&lt;/li&gt;
&lt;% } %&gt;
&lt;/ul&gt;</code>
</pre>
<h3>What&#8217;s up with the name?</h3>
<p>I find it a little confusing that the Helper method is called <code>RenderPartial</code> when it&#8217;s actually a User Control that you render. Wouldn&#8217;t it be more logical to call the User Control, Partial View or something instead? Or have I missed something?</p>
<p>To read more about the <acronym title="Active Server Pages">ASP</acronym>.NET MVC Framework and how to pass data objects, check out Scott Guthries excellent blog post, <a href="http://weblogs.asp.net/scottgu/archive/2007/12/06/asp-net-mvc-framework-part-3-passing-viewdata-from-controllers-to-views.aspx"><acronym title="Active Server Pages">ASP</acronym>.NET MVC Framework (Part 3): Passing ViewData from Controllers to Views</a>. It&#8217;s on an older release but most of it still applies.</p>
<p>Happy coding!</p>]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2008/10/user-controls-in-aspnet-mvc-preview-release-5/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Imagemap rollover</title>
		<link>http://www.svennerberg.com/2008/09/imagemap-rollover/</link>
		<comments>http://www.svennerberg.com/2008/09/imagemap-rollover/#comments</comments>
		<pubDate>Mon, 01 Sep 2008 19:51:05 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[XHTML]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=148</guid>
		<description><![CDATA[Imagemaps was very popular in the early days of webdesign but seem to have fallen out of grace. Probably due to accessibility problems and the rise of CSS based designs. I think that it still has it&#8217;s place when used properly and one being aware of it&#8217;s potential accessibility problems. In a recent project I [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/08/map_small.png" alt="" class="alignright" />Imagemaps was very popular in the early days of webdesign but seem to have fallen out of grace. Probably due to accessibility problems and the rise of <acronym title="Cascading Style Sheets">CSS</acronym> based designs. I think that it still has it&#8217;s place when used properly and one being aware of it&#8217;s potential accessibility problems.</p>
<p>In a recent project I was building a map where different regions of a map would highlight when you hover with the mouse over it. Using an imagemap in combination with <acronym title="Cascading Style Sheets">CSS</acronym> and Javascript seemed like the natural way to do it. </p>
<p>I thought that to actually code this solution would be pretty straightforward, but soon discovered some peculiar quirks. I also couldn&#8217;t find any information about this, so I thought that I&#8217;d share my experiences with you.</p>
<p><span id="more-148"></span></p>
<p>This is what I had in mind when I first started of.</p>
<ul>
<li>Use an image of a map.</li>
<li>Make it into an imagemap and define the clickable areas. </li>
<li>Do images of the different parts that is to be highlighted. </li>
<li>Position them with absolute positioning.</li>
<li>Use Javascript to show or hide them when the user hovers with the mouse over them.</li>
</ul>
<h3>The <acronym title="eXtensible HyperText Markup Language">XHTML</acronym></h3>
<p>I started of with a regular imagemap. (Some code is removed for brevity). I use a map over Scandinavia as the the image for the imagemap. </p>
<p><img src="http://media.svennerberg.com/2008/09/scandinavia_small.png" alt="" /></p>
<pre name="code" class="html">
&lt;div id=&quot;map&quot;&gt;
  &lt;img src=&quot;img/scandinavia.png&quot; alt=&quot;&quot; usemap=&quot;#scandinavia_map&quot; /&gt;
  &lt;map name=&quot;scandinavia_map&quot; id=&quot;scandinavia_map&quot;&gt;
    &lt;area id=&quot;area_finland&quot; shape=&quot;poly&quot; coords=&quot;193,64,207,[...]&quot; alt=&quot;Finland&quot; href=&quot;finland.html&quot; /&gt;
    &lt;area id=&quot;area_sweden&quot; shape=&quot;poly&quot; coords=&quot;192,65,206,[...]&quot; alt=&quot;Sweden&quot; href=&quot;sweden.html&quot; /&gt;
    &lt;area id=&quot;area_norway&quot; shape=&quot;poly&quot; coords=&quot;187,64,194, [...]&quot; alt=&quot;Norway&quot; href=&quot;norway.html&quot; /&gt;
  &lt;/map&gt;
  &lt;ul&gt;
    &lt;li id=&quot;finland&quot;&gt;&lt;a href=&quot;finland.html&quot;&gt;Finland&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;norway&quot;&gt;&lt;a href=&quot;norway.html&quot;&gt;Norway&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;sweden&quot;&gt;&lt;a href=&quot;sweden.html&quot;&gt;Sweden&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;
</pre>
<p>As you can see I also made a list with links. This list serves a dual purpose. First of all I&#8217;m using the list items as hooks for the &#8220;highlight images&#8221;. But they also serves as a backup, in case the user doesn&#8217;t have <acronym title="Cascading Style Sheets">CSS</acronym> and images turned on.</p>
<h3>The <acronym title="Cascading Style Sheets">CSS</acronym></h3>
<p>First of all I style the containing <code>&lt;div&gt;</code> with <code>position: relative</code>. This is necessary in order to later on position the different regions with absolute positioning. I&#8217;m also defining it&#8217;s width and height which is the same as the size of the map image. </p>
<pre name="code" class="css">
#map {
  position: relative;
  width: 340px;
  height: 438px;
}
</pre>
<p>Then I style the unordered list. The important details here is to give the <code>&lt;li&gt;</code> an absolute positioning to be able to position them on the right spots, a <code>text-indent</code> so that the text won&#8217;t show and <code>display: none</code> to hide them. (They will later be displayed with the help of Javascript.)</p>
<pre name="code" class="css">
#map ul {
  list-style: none;
}
#map li {
  position: absolute;
  z-index: 20;
  text-indent: -1000em;
  display: none;
}
</pre>
<p>Finally I style the different regions giving them the right image as a background, the right dimensions and the right position over the map. It can take some trial and error to get them in the right position. Temporarily set <code>display: block</code> while you position them.</p>
<p>Here are the images that I use as backgrounds on the elements I position over the map. (Well actually these are smaller version of the once I use)</p>
<p><img src="http://media.svennerberg.com/2008/09/sweden_small.png" class="alignleft" alt="" /><img src="http://media.svennerberg.com/2008/09/finland_small.png" class="alignleft" alt="" /><img src="http://media.svennerberg.com/2008/09/norway_small.png" class="alignleft" alt="" /></p>
<pre name="code" class="css">
#sweden {
  background: url(../img/sweden.png) no-repeat;
  width: 158px;
  height: 374px;
  top: 64px; 
  left: 80px;
}
#finland {
  background: url(../img/finland.png) no-repeat;
  width: 148px;
  height: 283px;
  top: 27px;
  right: 0;
}
#norway {
  background: url(../img/norway.png) no-repeat;
  width: 292px;
  height: 362px;
  top: 0;
  left: 0;
}
</pre>
<p>That sets the looks of the map. Now we just need some Javascript to make the rollover effects.</p>
<h3>The Javascript</h3>
<p>I use the <a href="http://www.domassistant.com/"><acronym title="Document Object Model">DOM</acronym> Assistant Javascript library</a> to help with the <acronym title="Document Object Model">DOM</acronym> manipulation. If you prefer you can just as easily use <a href="http://www.jquery.com">jQuery</a>, <a href="http://www.prototypejs.org">Prototype</a> or any other similar Javascript library to do the same thing. Still, to use this example, be sure to include a reference to <acronym title="Document Object Model">DOM</acronym> Assistant in the head of the <acronym title="HyperText Markup Language">HTML</acronym> document.</p>
<p>The script is pretty straightforward. What it basically does is that it loops through the list elements and assign mouseover, mouseout and click events to them. Review the comments in the code for a deeper explanation.</p>
<pre name="code" class="js">
// When the <acronym title="Document Object Model">DOM</acronym> is loaded, initilize initPage
DOMAssistant.DOMReady(initPage);
function initPage() {
  // Get a reference to the containing div with id='map'
  var map = $$('map');
  // Check if map exists
  if (map) {
    // Get all the areas of the imagemap
    var country_list = map.getElementsByTagName('AREA');
    // Loop through all areas
    for (var i=0; i&lt;country_list.length; i++) {
      $(country_list[i]).style.display = 'none';
      // Assign an action to the mouseover event
      $(country_list[i]).addEvent('mouseover', function(e) {
        // Get the id from the hovered area
        var country_id = this.id;
        // Extract the &quot;country&quot;-part of the id = the id of the list-item
        country_id = country_id.substring(country_id.indexOf('_')+1, country_id.length);

        // Set the &lt;li&gt; to &quot;display: inline&quot; = show it
        $$(country_id).setStyle('display', 'inline');
      });
      // Assign an action to the mouseout event
      $(country_list[i]).addEvent('mouseout', function(e)  {
        // Get the id from the hovered area
        var country_id = this.id;
        // Extract the &quot;country&quot;-part of the id = the id of the list-item
        country_id = country_id.substring(country_id.indexOf('_')+1, country_id.length);
        // Set the &lt;li&gt; to &quot;display: none&quot; = hide it
        $$(country_id).setStyle('display', 'none');
      });
      $(country_list[i]).addEvent('click', function(e) {
        var country_id = this.id;
        country_id = country_id.substring(country_id.indexOf('_')+1, country_id.length);
        alert('You clicked ' + country_id)
        DOMAssistant.preventDefault(e);
      });
    }
  }
}
</pre>
<p>This should do it one should think. But here&#8217;s where strange things starts to happen. The highlighted image flickers constantly as if the mouseOver and mouseOut events are triggered over and over again. <a href="http://www.svennerberg.com/examples/imagemap_rollover/broken.html">Watch it in action</a>. </p>
<h3>Solution to the flicker problem</h3>
<p>After some experimenting I came up with a solution where I use a transparent image as an overlay on the map image. I then assign the imagemap to the transparent image and voilà, the problem is solved.</p>
<pre name="code" class="html">
&lt;img src=&quot;img/transp.gif&quot; id=&quot;transparent_map&quot; alt=&quot;&quot; usemap=&quot;#scandinavia_map&quot; /&gt;
</pre>
<p>It&#8217;s important to give the transparent image the same dimensions as the image of the map.</p>
<pre name="code" class="js">
#transparent_map {
  position: absolute;
  z-index: 30;
  width: 340px;
  height: 438px;
  border: none;
}
</pre>
<p>With that fix the map works just fine. <a href="http://www.svennerberg.com/examples/imagemap_rollover/">View a live demo</a>.</p>
<h3>Accessibility</h3>
<p>My conclusion is that this solution, if not perfect, is still pretty accessible. With <acronym title="Cascading Style Sheets">CSS</acronym> turned off, the list is visible and even though the map isn&#8217;t clickable you can click the links in the list. With Javascript turned off, the different parts of the map doesn&#8217;t highlight but they are still clickable. </p>
<p>For those who uses the keyboard to navigate, it&#8217;s still usable, but I haven&#8217;t been able to find a way to highlight an area when it&#8217;s &#8220;active&#8221;. If anyone has an idea of how to do this, please tell me.</p>
<p>I found one other weakness and a more serious that is. If you browse with images turned off and <acronym title="Cascading Style Sheets">CSS</acronym> enabled, neither the map nor the list of links is visible thus you can&#8217;t use it. If you have a solution to this, please let me know!</p>
<h3>The files</h3>
<ul>
<li><a href="http://www.svennerberg.com/examples/imagemap_rollover/js/map.js">Download map.js</a></li>
<li><a href="http://www.svennerberg.com/examples/imagemap_rollover/css/map.css">Download map.css</a></li>
</ul>
<p class="note"><strong>Update [2009-05-04]: </strong> There&#8217;s now an <a href="http://www.svennerberg.com/examples/imagemap_rollover/index_jquery.html" title="Imagemap rollover using jQuery">example using jQuery</a> available. Also check out the Javascript file: <a href="http://www.svennerberg.com/examples/imagemap_rollover/js/map_jquery.js">map_jquery.js</a>.</p>
<p class="note"><strong>Update [2010-02-27]:</strong> I&#8217;ve made a new <a href="http://www.svennerberg.com/examples/imagemap_rollover/index_jquery_fade.html">example using jQuery and a fade effect</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2008/09/imagemap-rollover/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Looping with jQuery</title>
		<link>http://www.svennerberg.com/2008/08/looping-with-jquery/</link>
		<comments>http://www.svennerberg.com/2008/08/looping-with-jquery/#comments</comments>
		<pubDate>Thu, 21 Aug 2008 15:52:27 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=174</guid>
		<description><![CDATA[I&#8217;ve started working with the Javascript framework jQuery lately and I must say that I find it very enjoyable! I have previously mostly used Prototype and DOMAssistant, and although they excel in some areas I somehow find jQuery more fun to code with. Here&#8217;s a simple tip on how to loop through elements with jQuery [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://media.svennerberg.com/2008/08/jquery-logo.gif" alt="" class="alignright" />I&#8217;ve started working with the Javascript framework <a href="http://jquery.com/">jQuery</a> lately and I must say that I find it very enjoyable! I have previously mostly used <a href="http://www.prototypejs.org">Prototype</a> and <a href="http://www.domassistant.com/">DOMAssistant</a>, and although they excel in some areas I somehow find jQuery more fun to code with.</p>
<p>Here&#8217;s a simple tip on how to loop through elements with jQuery that I thought I&#8217;d share.</p>
<p><span id="more-174"></span></p>
<h3>An example</h3>
<p>We start with a simple unordered list.</p>
<pre>
<code>&lt;ul id=&quot;my_list&quot;&gt;
	&lt;li&gt;Item&lt;/li&gt;
	&lt;li&gt;Item&lt;/li&gt;
	&lt;li&gt;Item&lt;/li&gt;
&lt;/ul&gt;</code>
</pre>
<p>What we want to do now is to change the color of each list item to red. With regular <acronym title="Document Object Model">DOM</acronym> scripting this would probably take a few lines of code but with jQuery we need just one.</p>
<pre>
<code>$('#my_list li').css('color', 'red');</code>
</pre>
<p>This would result in:</p>
<ul>
<li style="color: red">Item</li>
<li style="color: red">Item</li>
<li style="color: red">Item</li>
</ul>
<p>If you want to do something a little more fancy, like something different with each item, you have to write a little more code, but not much. First you have to grab the the list elements like in the previous example by using selectors. By using the <code>each()</code> method, you are then able to loop through each item. By assigning an anonymous function to <code>each()</code> you get access to every individual item by using <code>$(this)</code>. </p>
<p>Notice that in the anonymous function there&#8217;s an attribute <code>i</code>. That&#8217;s the number of each item, just like in any normal array, starting from 0 and incrementing. </p>
<pre>
<code>$('#my_list li').each(function(i) {
	$(this).append(i.toString());
});</code>
</pre>
<p>The result is a list with the item number attached to the text inside the elements like this:</p>
<ul>
<li>Item0</li>
<li>Item1</li>
<li>Item2</li>
</ul>
<p>The really cool thing about this is that each iteration has it&#8217;s own function scoop. If you ever tried to do this with regular <acronym title="Document Object Model">DOM</acronym> scripting and a standard <code>for</code> loop you&#8217;ve most likely ran into some kind of scoop problem when dynamically assigning values to an object. They all end up getting the same value. jQuery elegantly solves this and makes you&#8217;re coding life a little bit easier.</p>
<p>Pretty cool don&#8217;t you think? Happy coding!</p>]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2008/08/looping-with-jquery/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Ultimate site logo</title>
		<link>http://www.svennerberg.com/2008/06/ultimate-site-logo/</link>
		<comments>http://www.svennerberg.com/2008/06/ultimate-site-logo/#comments</comments>
		<pubDate>Wed, 25 Jun 2008 12:31:56 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Accessibility]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[XHTML]]></category>

		<guid isPermaLink="false">http://www.svennerberg.com/?p=55</guid>
		<description><![CDATA[To have a good site logo is important. It&#8217;s one of the things that distinguish your web site from everybody else&#8217;s. It&#8217;s also a design element that exists on all pages within your site. Naturally you want it to be good looking, but at the same time it needs to be accessible and also search [...]]]></description>
			<content:encoded><![CDATA[<p>To have a good site logo is important. It&#8217;s one of the things that distinguish your web site from everybody else&#8217;s. It&#8217;s also a design element that exists on all pages within your site. Naturally you want it to be good looking, but at the same time it needs to be accessible and also search engine friendly. To do this properly there are some techniques worth knowing. In this article I will show you the approach I&#8217;ve taken on my own blog.</p>
<p>In my opinion a good site logo have these characteristics: </p>
<ul>
<li><strong>It&#8217;s search engine optimized</strong><br />
Score high on Google</li>
<li><strong>It&#8217;s clickable</strong><br />
Support the strong convention that a click on the site logo takes you to the homepage</li>
<li><strong>It&#8217;s accessible</strong><br />
Enable those with screenreaders or images turned off to read the &#8220;logo&#8221;</li>
<li><strong>It looks good</strong><br />
A good looking logo is important to build your brand.</li>
</ul>
<p>If you&#8217;re the impatient kind you can watch the <a href="/examples/ultimate_site_logo/" title="Ultimate site logo - Example page">example page</a> right away. For an explanation of how it&#8217;s done, read on!</p>
<p><span id="more-55"></span></p>
<h3>The <acronym title="HyperText Markup Language">HTML</acronym></h3>
<p>I&#8217;m taking a bottom-up approach to marking this up. That is, I start with some basic <acronym title="HyperText Markup Language">HTML</acronym> to render a simple text link inside a <code>&lt;h1&gt;</code>. I then build upon this with the help of <acronym title="Cascading Style Sheets">CSS</acronym>, placing the logo image on top of the text. By doing this I enable all users, even those that use screen readers or have images disabled, to view the sitename while still letting those with able browsers to see the logo image instead. </p>
<p>This approach is often referred to as <a href="http://en.wikipedia.org/wiki/Progressive_enhancement">progressive enhancement</a> and is an important concept when developing web sites according to <a href="http://en.wikipedia.org/wiki/Web_standards">web standards</a>. The beauty of this approach is that it&#8217;s also an effective way to optimize the page for search engines.</p>
<h4>To use <code>&lt;h1&gt;</code> or not</h4>
<p>In my opinion <code>&lt;h1&gt;</code> is a suitable element for the site logo since it indicates that it&#8217;s the most important heading of the page. When search engines indexes pages they give more weight to text inside a <code>&lt;h1&gt;</code> than for example text inside <code>&lt;div&gt;</code> or <code>&lt;p&gt;</code>. </p>
<p>I know that some people disagrees with this and regards the <code>&lt;h1&gt;</code> reserved for the individual documents most prominent heading and not the web sites. However in my approach <code>&lt;h1&gt;</code> is used for the site name and <code>&lt;h2&gt;</code> is used for the documents most prominent heading. If you disagree with me, you can still use this approach by exchanging the <code>&lt;h1&gt;</code> for another element.</p>
<h4>Adding a link</h4>
<p>I also want the site logo to be clickable. This is one of the most wide spread conventions in web design, and most users expect the site logo to take them to the homepage when they click it. To accommodate this I make the heading a link which points to the homepage.</p>
<p>I have wrapped the <code>&lt;h1&gt;</code> inside a <code>&lt;div&gt;</code> with the <code>id</code> &#8220;branding&#8221;. Later in the <acronym title="Cascading Style Sheets">CSS</acronym> I will use this <code>id</code> as a hook for styling what&#8217;s inside.</p>
<p>To get this solution to work properly I&#8217;m also forced to use an extra set of <code>&lt;span&gt;</code> inside the <code>&lt;a&gt;</code>. I will use this later on to insert the logo image over the text. Even though I&#8217;m not very keen on adding extraneous <acronym title="HyperText Markup Language">HTML</acronym> to the document, this seems like a small trade-off to get this to work properly.</p>
<pre>
<code>&lt;div id=&quot;branding&quot;&gt;
	&lt;h1&gt;&lt;a href=&quot;/&quot;&gt;&lt;span&gt;&lt;/span&gt;In usability we trust&lt;/a&gt;&lt;/h1&gt;
&lt;/div&gt;</code>
</pre>
<p><img src="http://media.svennerberg.com/2008/06/unstyled.png" alt=""  /></p>
<p>At this point the site logo sure is accessible and SEO friendly but it doesn&#8217;t look very appealing. Soon we&#8217;re gonna change all that with some styling.</p>
<h3>Styling it</h3>
<p>I like to keep the <acronym title="HyperText Markup Language">HTML</acronym> lean, therefor I want to have as few <acronym title="Cascading Style Sheets">CSS</acronym> selectors as possible. In this case I only have one, the <code>id="branding"</code> on the <code>&lt;div&gt;</code>. I use this hook in my <acronym title="Cascading Style Sheets">CSS</acronym> to access the header like this: <code>#branding h1</code>. What I tell the <acronym title="Cascading Style Sheets">CSS</acronym> is that I want to access the heading that&#8217;s inside the element with the id &#8220;branding&#8221;.</p>
<h4>Styling the heading</h4>
<p>I start off by giving the heading a relative position. The reason I&#8217;m doing this is that I want to position the containing elements using absolute positioning.  Elements with an absolute position is positioned in relation to the nearest containing element with a relative position. If none is available it&#8217;s positioned relative to the browsers viewport. So in order to position the site logo inside the containing <code>&lt;div&gt;</code> I have to do assign it a relative position.</p>
<p>I then remove the margin from the heading and give it the same dimensions as my logo image so that it will fit nicely inside it.</p>
<pre>
<code>#branding h1 {
	position: relative;
	margin: 0;
	width: 461px;
	height: 125px;
}</code>
</pre>
<h4>Styling the link</h4>
<p>The next step is to style the link. I want the link to be invisible yet clickable. This is done by giving it an absolute position. This is so that I can stack the link and the <code>&lt;span&gt;</code> (which will contain the logo image) on each other using <code>z-index</code>. An element with an absolute position implicitly have a z-index of 0. Therefor I don&#8217;t have to explicitly define it in the <acronym title="Cascading Style Sheets">CSS</acronym> for the link since I want it to have <code>z-index: 0;</code>.</p>
<p>I also want to ensure that the link stretches the whole area so it&#8217;s possible to click anywhere at the logo and I therefor give it a width and height of 100%.</p>
<pre>
<code>#branding h1 a {
	position: absolute;
	width: 100%;
	height: 100%;
}</code>
</pre>
<h4>Styling the <code>&lt;span&gt;</code></h4>
<p>The last step is to position the <code>&lt;span&gt;</code> on top of the link and display the logo image in it. This is done in three steps.</p>
<ol>
<li>Give it an absolute position and a z-index of 1. Thereby placing it on top of the link.</li>
<li>Ensure that it covers the whole area by giving it a width and height of 100%.</li>
<li>Assign the logo image as the background.<del datetime="2008-06-27T14:52:51+00:00"> and also add a white background color so that the text doesn&#8217;t shine through before the images has loaded.</del></li>
</ol>
<p class="note"><strong>Edit: </strong> I&#8217;ve removed the background color because it prevented the text to display if the user have images turned off. The trade-off is that there can be an occasional flicker where the text shines through when hovering the first time if the hover-image hasn&#8217;t loaded yet.</p>
<pre>
<code>#branding h1 span {
	position: absolute;
	z-index: 1;	
	width: 100%;
	height: 100%;
	background: url(img/logo.png) no-repeat;
}</code>
</pre>
<p>Now the site logo looks a lot nicer. The ugly text is gone and is replaced with the site logo graphics. Still if you turn off the stylesheet you can read the heading and click it to enter the homepage.</p>
<p><img src="http://media.svennerberg.com/2008/06/logo.png" alt="" /></p>
<h3>Adding a Hover effect</h3>
<p>To add some extra flare to the site logo and to provide the user with an additional hint that it&#8217;s clickable, you can add a hover effect. In this case it&#8217;s done by assigning the pseudo-class <code>:hover</code> to the link. When the user points at the logo the background image is altered.</p>
<pre>
<code>#branding h1 a:hover span {
	background-image: url(img/logo_hover.png);
}</code>
</pre>
<p>This is what it will look like when the user hovers with the cursor over it.</p>
<p><img src="http://media.svennerberg.com/2008/06/logo_hover.png" alt="" /></p>
<h3>Tweaks to make it work in <acronym title="Internet Explorer 6">IE6</acronym> and IE7</h3>
<p>It doesn&#8217;t come as a big suprise that Internet Explorer needs some special treatment in order for this to work properly. Frankly I wouldn&#8217;t have expected anything else! <img src='http://www.svennerberg.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  </p>
<p>A good practice is to place these &#8220;hacks&#8221; in a separate file and only feed it to <acronym title="Internet Explorer">IE</acronym> using conditional comments. Conditional comments is a proprietary feature in <acronym title="Internet Explorer">IE</acronym> that allow us to target specific versions of <acronym title="Internet Explorer">IE</acronym>. All other browsers treat it just like any other <acronym title="HyperText Markup Language">HTML</acronym> comment and ignores what&#8217;s inside it.</p>
<pre>
<code>&lt;!--[if lt <acronym title="Internet Explorer">IE</acronym> 8]&gt;
	&lt;link rel=&quot;stylesheet&quot; href=&quot;css/ie.css&quot; type=&quot;text/css&quot; media=&quot;all&quot; /&gt;
&lt;![endif]--&gt;</code>
</pre>
<p>This code snippet feeds the ie.css to versions of <acronym title="Internet Explorer">IE</acronym> that is lower than 8 (<code>lt</code> stands for <em>less than</em>). If you just want to feed the file to <acronym title="Internet Explorer 6">IE6</acronym>, just replace the 8 with a 7. <a href="http://msdn.microsoft.com/en-us/library/ms537512.aspx" title="About Conditional Comments on MSDN">More information on conditional comments</a>.</p>
<h4>Fixing the cursor</h4>
<p>A problem that occurs in both <acronym title="Internet Explorer">IE</acronym> 6 and 7 is that the cursor doesn&#8217;t change from an arrow to a hand when it hovers over the logo. That is easily fixed with this code snippet:</p>
<pre>
<code>#branding h1 span {
	cursor: hand; 
}</code>
</pre>
<h4>Fixing the hover effect</h4>
<p>If you added the hover effect you will need this tweak to get it to work properly in <acronym title="Internet Explorer 6">IE6</acronym>. Otherwise you can just discard it. </p>
<p>The problem occurs when the user have hovered with the cursor over the logo and then remove it. For some reason the image doesn&#8217;t go back to it&#8217;s original state. I found that setting <code>border: none</code> on the link, makes the browser recognize that the cursor have been removed. I&#8217;m not sure why this is, but I suspect that it has something to do with the <a href="http://www.satzansatz.de/cssd/onhavinglayout.html" title="On having layout - The concept of hasLayout in IE/Win">hasLayout</a> property in <acronym title="Internet Explorer 6">IE6</acronym>.</p>
<pre>

<code>#branding h1 a:hover {
	border: none;
}</code>
</pre>
<p>The only thing is that it now changes the height of the link to be lower than before, resulting in that only a part of the logo is visible. To fix this I had to define the height of the link in pixels instead of just as 100%.</p>
<pre>
<code>
#branding h1 a {
	height: 125px;
}</code>
</pre>
<p>With those issues taken care of, it works fine in <acronym title="Internet Explorer">IE</acronym> too.</p>
<h3>Compability</h3>
<p>I&#8217;ve tested the code in Firefox 2.5-3.0, Internet Explorer 5.5 SP2, 6.0 and 7.0, Opera 9.26 and Safari 3.1. All in Windows XP. The only weakness I&#8217;ve found so far is that &#8220;print background images&#8221; has to be turned on in the browser for the logo image to show in print-outs. Otherwise the text version is printed instead. </p>
<p>If you have a solution for this, spot other weaknesses or have other ideas of how to improve this. Please share!</p>
<ul>
<li><a href="/examples/ultimate_site_logo/" title="Ultimate site logo - Example page">The example page</a></li>
<li><a href="/examples/ultimate_site_logo/css/style.css">style.css</a></li>
<li><a href="/examples/ultimate_site_logo/css/ie.css">ie.css</a></li>
</ul>
<p class="note"><strong>Update: </strong> Since I wrote this article I have changed my mind regarding using <code>&lt;h1&gt;</code> as container for the site logo. I have also found other ways to further improve this solution. Read about it in <a href="http://www.svennerberg.com/2008/11/ultimate-site-logo-2-for-real-this-time/">Ultimate Site Logo 2 &#8211; For real this time</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2008/06/ultimate-site-logo/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Marking up contact information with microformats</title>
		<link>http://www.svennerberg.com/2008/06/marking-up-contact-information-with-microformats/</link>
		<comments>http://www.svennerberg.com/2008/06/marking-up-contact-information-with-microformats/#comments</comments>
		<pubDate>Mon, 09 Jun 2008 14:04:54 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Microformats]]></category>
		<category><![CDATA[XHTML]]></category>

		<guid isPermaLink="false">http://blog.svennerberg.com/?p=31</guid>
		<description><![CDATA[If you're building web sites you probably mark up contact information every now and then. Why not do it in a standardized ways so that you are able to quickly mark it up, style it and enhance it with microformats at the same time? The way to do this is by using hCard, a microformat for marking up contact information.

This article will not only show you why you should do this, but also exactly how!]]></description>
			<content:encoded><![CDATA[<p><img class="left" title="Microformats" src="http://media.svennerberg.com/2008/05/mf-logo.gif" alt="" /></p>
<p>If you&#8217;re building web sites you probably mark up contact information every now and then. Why not do it in a standardized ways so that you are able to quickly mark it up, style it and enhance it with microformats at the same time? The way to do this is by using hCard, a microformat for marking up contact information.</p>
<p>This article will not only show you why you should do this, but also exactly how!</p>
<p><span id="more-33"></span></p>
<h3>hCard = vCard</h3>
<p>Maybe you&#8217;ve heard of, or even used vCard before? It&#8217;s a widely adopted standard for dealing with contact info. Outlook and just about any other email application uses it, probably even your mobile phone. hCard is an <acronym title="HyperText Markup Language">HTML</acronym> adaption of the vCard format.</p>
<p>By using hCard to mark up contact info you enable it for automatic processing. You could for example import it directly to an address application by using the <a href="https://addons.mozilla.org/en-US/firefox/addon/4106">Operator extension</a> for Firefox. As of now you have to install an extension to be able to import microformat data, but as I understand it Firefox 3 will have native support for it.</p>
<p>Several search engines, including Google and Yahoo, has adopted microformats and this gives you the possibility to enable the search engines to more accurately find your content.</p>
<h3>The basic markup</h3>
<p>Let&#8217;s start by marking up a name, a phone number and an <acronym title="Uniform Resource Locator">URL</acronym> using standard <acronym title="eXtensible HyperText Markup Language">XHTML</acronym>.</p>
<pre>
<code>&lt;div&gt;
	&lt;h4&gt;Gabriel Svennerberg&lt;/h4&gt;
	&lt;div&gt;
		Tel: +46 470-76 40 50
	&lt;/div&gt;
	&lt;div&gt;
		&lt;a href=&quot;http://www.svennerberg.com/&quot;&gt;www.svennerberg.com&lt;/a&gt;
	&lt;/div&gt;
&lt;/div&gt;</code>
</pre>
<p>As you can see there&#8217;s nothing fancy here. Just some basic <acronym title="eXtensible HyperText Markup Language">XHTML</acronym>. But now comes the interesting part: how to spice it up with microformats.</p>
<p class="note"><strong>Note:</strong> In my examples I mainly use <code>div</code> and <code>span</code> to mark up the content but you could just as well use any other suitable (X)<acronym title="HyperText Markup Language">HTML</acronym> element such as list- or table elements.</p>
<h3>Enhance it with some sweet microformat magic</h3>
<p>The next step is to enhance it with microformats. For starters we want to wrap the whole thing inside a tag marked with <code>class="vcard"</code>. We do this to tell that this part of the web page is an hCard.</p>
<p>We also want to define what the name of the contact is, in this case by using <code>class="fn"</code> (formatted name). We also want to define the phone number by using <code>class="tel"</code> and the url by using <code>class="url"</code>.</p>
<p>And this is how it&#8217;s done. You just use the class-attribute with predefined class names, and voilá, you got some microformat-enhanced content.</p>
<pre>
<code>&lt;div <strong>class=&quot;vcard&quot;</strong>&gt;
	&lt;h4 <strong>class=&quot;fn&quot;</strong>&gt;Gabriel Svennerberg&lt;/h4&gt;
	&lt;div&gt;
		Tel: &lt;span <strong>class=&quot;tel&quot;</strong>&gt;+46 470-76 40 50&lt;/span&gt;
	&lt;/div&gt;
	&lt;div&gt;
		&lt;a <strong>class=&quot;url&quot;</strong> href=&quot;http://www.svennerberg.com/&quot;&gt;www.svennerberg.com&lt;/a&gt;
	&lt;/div&gt;
&lt;/div&gt;</code>
</pre>
<h3>Display it with style</h3>
<p>You can easily style the address information using the microformat classes as hooks. Here&#8217;s an example of some simple styling where I&#8217;ve used the <code>vcard</code> and the <code>fn</code> classes to style the content.</p>
<pre>
<code>.vcard {
	margin: 1em 0;
	padding: 20px;
	border: 1px solid #dde;
	width: 15em;
	background: #f4f8fd;

}
.fn {
	margin: 0 0 .1em;
}</code>
</pre>
<p>The result would look something like this.</p>
<p><img src="http://media.svennerberg.com/2008/06/hcard-address.gif" alt="" /></p>
<h3>Further enhancements</h3>
<p>You could further enhance the content by giving it even more detailed specifications. You could for example define what part of the name that&#8217;s the first name and what part that&#8217;s the family name. This is accomplished by using <code>class="given-name"</code> and <code>class="family-name"</code>.</p>
<p>You could also be more specific about the phone number by specifying what kind of phone number it is (e.g. work, home, etc.). This pattern is how you mark up several items of one particular type, like phone numbers. You then use <code>class="type"</code> to define the type of number and <code>class="value" </code>to define the actual number and wrap it all in a container with  <code>class="tel"</code>.</p>
<pre>
<code>&lt;div class=&quot;vcard&quot;&gt;
	&lt;h4 <strong>class=&quot;fn&quot;&gt;</strong>
		&lt;span <strong>class=&quot;given-name&quot;</strong>&gt;Gabriel&lt;/span&gt; 
		&lt;span <strong>class=&quot;family-name&quot;</strong>&gt;Svennerberg&lt;/span&gt;
	&lt;/h4&gt;
	&lt;div <strong>class=&quot;tel&quot;&gt;</strong>
		&lt;span <strong>class=&quot;type&quot;</strong>&gt;Home&lt;/span&gt;:
		&lt;span <strong>class=&quot;value&quot;</strong>&gt;+46 470-76 40 50&lt;/span&gt;
	&lt;/div&gt;
	&lt;div&gt;
		&lt;a class=&quot;url&quot; href=&quot;http://www.svennerberg.com/&quot;&gt;www.svennerberg.com&lt;/a&gt;
	&lt;/div&gt;
&lt;/div&gt;</code>
</pre>
<h3>Adding more content</h3>
<p>In this example I have added even more address information, like the street address, two different phone numbers and so on. By now I think you got the hang of it! You just use standard (X)<acronym title="HyperText Markup Language">HTML</acronym> elements and classes to define the content.</p>
<pre>
<code>&lt;div class=&quot;vcard&quot;&gt;
	&lt;h4 class=&quot;fn&quot;&gt;
		&lt;span class=&quot;given-name&quot;&gt;Gabriel&lt;/span&gt; 
		&lt;span class=&quot;family-name&quot;&gt;Svennerberg&lt;/span&gt;
	&lt;/h4&gt;
	&lt;div <strong>class=&quot;adr&quot;&gt;</strong>
		&lt;div <strong>class=&quot;street-address&quot;&gt;</strong>Kasernv&amp;auml;gen 9b&lt;/div&gt;
		&lt;div&gt;
			&lt;span <strong>class=&quot;postal-code&quot;&gt;</strong>352 36&lt;/span&gt; 
			&lt;span <strong>class=&quot;locality&quot;&gt;</strong>V&amp;auml;xj&amp;ouml;&lt;/span&gt;
		&lt;/div&gt;
		&lt;div <strong>class=&quot;country-name&quot;</strong>&gt;Sweden&lt;/div&gt;
		&lt;div class=&quot;tel&quot;&gt;
			&lt;span class=&quot;type&quot;&gt;Home&lt;/span&gt;:
			&lt;span class=&quot;value&quot;&gt;+46 470-76 40 50&lt;/span&gt;
		&lt;/div&gt;
		&lt;div <strong>class=&quot;tel&quot;&gt;</strong>
			&lt;span <strong>class=&quot;type&quot;</strong>&gt;Work&lt;/span&gt;:
			&lt;span <strong>class=&quot;value&quot;</strong>&gt;+46 470-427 14&lt;/span&gt;
		&lt;/div&gt;
		&lt;div&gt;
			&lt;a class=&quot;url&quot; href=&quot;http://www.svennerberg.com/&quot;&gt;www.svennerberg.com&lt;/a&gt;
		&lt;/div&gt;
	&lt;/div&gt;
&lt;/div&gt;</code>
</pre>
<p>As you can see there are quite a few class names that you can use to semantically mark up your content. In fact there&#8217;s more. Here&#8217;s the complete list:</p>
<ul>
<li>fn, n  (family-name, given-name, additional-name, honorific-prefix, honorific-suffix), nickname, sort-string</li>
<li>url, email (type, value), tel (type, value)</li>
<li>adr (post-office-box, extended-address, street-address, locality, region, postal-code, country-name, type, value), label</li>
<li>geo (latitude, longitude), tz</li>
<li>photo, logo, sound, bday</li>
<li>title, role, org (organization-name, organisation-unit)</li>
<li>category, note</li>
<li>class, key, mailer, uid, rev</li>
</ul>
<p>Class names inside parenthesis are subproperties of the preceding class name. Just like in the example with the telephone number; <code>tel</code> is the parent and <code>type</code> and <code>value</code> are the subproperties.</p>
<p>You might have noticed that there&#8217;s a class-name called geo in the list. Geo enables you to specify the geographic location of a contact by specifying coordinates. In my article, <a href="?p=20">Using microformats to populate Google Map</a>, I describe how to use microformats in combination with Javascript to populate a Google Map.</p>
<h3>More resources</h3>
<p>Sitepoint has an excellent article on microformats, <a href="http://reference.sitepoint.com/html/microformats">Microformats—Plugging the Gaps In <acronym title="HyperText Markup Language">HTML</acronym></a><br />
They&#8217;ve got separate sections about the different microformats such as <a href="http://reference.sitepoint.com/html/hcard">hCard</a>, <a href="http://reference.sitepoint.com/html/hcalendar">hCalendar</a>, <a href="http://reference.sitepoint.com/html/hreview">hReview </a>and so on, that&#8217;s really useful.</p>
<p><a href="http://www.microformats.org/">Microformats.org</a> has a <a href="http://www.microformats.org/wiki">wiki </a>with lots of information and examples of how to use microformats. They also have <a href="http://www.microformats.org/wiki/hcard">a page specifically dealing with hCard</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2008/06/marking-up-contact-information-with-microformats/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Microformats to populate Google Map</title>
		<link>http://www.svennerberg.com/2008/05/using-microformats-to-populate-google-map/</link>
		<comments>http://www.svennerberg.com/2008/05/using-microformats-to-populate-google-map/#comments</comments>
		<pubDate>Sat, 24 May 2008 17:14:48 +0000</pubDate>
		<dc:creator>Gabriel Svennerberg</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Mashups]]></category>
		<category><![CDATA[Microformats]]></category>
		<category><![CDATA[Web apps]]></category>

		<guid isPermaLink="false">http://blog.svennerberg.com/?p=20</guid>
		<description><![CDATA[Inspired by an article I&#8217;ve read on 24-ways I&#8217;ve built a demo-page for using content marked up with microformats to populate a Google Map. Unfortunately the demo is in Swedish, but I think those of you who doesn&#8217;t speak Swedish can easily understand it anyway. The main concept is to use a list of folksong [...]]]></description>
			<content:encoded><![CDATA[<p><img id="image22" class="left" src="http://media.svennerberg.com/2008/05/mf-logo.gif" alt="Microformats" />Inspired by an article I&#8217;ve read on <a title="Get To Grips with Slippy Maps" href="http://24ways.org/2007/get-to-grips-with-slippy-maps">24-ways</a> I&#8217;ve built a demo-page for using content marked up with microformats to populate a Google Map.</p>
<p>Unfortunately the demo is in Swedish, but I think those of you who doesn&#8217;t speak Swedish can easily understand it anyway.</p>
<p>The main concept is to use a list of folksong festivals in Scandinavia, carefully marked up with microformats, as a data source. I then use Javascript to loop through the content and populate the map.</p>
<p>I got the list of festivals from <a title="Föreningen NordVisa - för visan i Norden" href="http://www.nordvisa.org">www.nordvisa.org</a>. Thank you Chris!</p>
<p><span id="more-30"></span><img id="image21" src="http://media.svennerberg.com/2008/05/microformats.jpg" alt="microformats.jpg" /></p>
<p><a href="http://www.svennerberg.com/microformats/">Watch the demo in action</a></p>
<h3>So what&#8217;s the big deal?</h3>
<p>The advantage of this is that you can handle all events marked up with microformats the same way. It&#8217;s a standardized way of telling what is what. It means that you could for example build a script that automatically collects data from different sources (e.g. different web sites) and then display them all in the same place. If you find a new source to collect data from you just hook it up as well and you&#8217;re good to go.</p>
<p>On <a href="http://www.microformats.org/">microformats.org</a> they describe it like this:</p>
<blockquote><p>Designed for humans first and machines second, microformats are a set of simple, open data formats built upon existing and widely adopted standards.</p></blockquote>
<p>It&#8217;s basically a way to give more meaning to content. If for example you mark up your contact info with the microformat <a href="http://microformats.org/wiki/hcard">hCard</a>. It can easily be imported to address books and other services.</p>
<h3>Marking up the content</h3>
<p>To mark up content with microformats you use the attribute: <code>class</code> on an <acronym title="HyperText Markup Language">HTML</acronym> element. If you for example want to mark up your home phone number you can do it like this:</p>
<pre><code>&lt;div class="tel"&gt;
	&lt;span class="type"&gt;home&lt;/span&gt;:
	&lt;span class="value"&gt;+1.415.555.1212&lt;/span&gt;
&lt;/div&gt;</code></pre>
<p>This way not only humans can see that that&#8217;s your home phone number but computers can interpret it as well.</p>
<p>In this demo I&#8217;ve used the microformat <a href="http://microformats.org/wiki/hcalendar">hCalendar</a> to mark up events. To mark up a block of information as an event using the hCard standard you use the class <code>vevent</code> on the container, in this case the list element <code>&lt;li&gt;</code>.</p>
<p>This is how I marked up the title and the dates of an event:</p>
<pre><code>&lt;li class="vevent"&gt;
	&lt;h3 class="summary"&gt;Vømmelfestivalen&lt;/h3&gt;
	&lt;p&gt;
		&lt;abbr class="dtstart" title="2008-05-29"&gt;29 Maj&lt;/abbr&gt; —
		&lt;abbr class="dtend" title="2008-06-01"&gt;31 Maj&lt;/abbr&gt;
	&lt;/p&gt;
&lt;/li&gt;</code></pre>
<p>Note that in this case I use <code>class="dtstart"</code> attribute to tell what kind of information it is, in this case the start date of the event. Then I use the attribute <code>title="2008-05-29"</code> to tell the date in a standardized, machine readable way.</p>
<p>To mark up geographical data there&#8217;s a class called <code>geo</code> and there&#8217;s also classes to mark up the coordinates: <code>latitude</code> and <code>longitude</code>. I use these classes so that I later on can extract the events position using Javascript.</p>
<pre><code>&lt;p class="geo"&gt;
	GEO: &lt;span class="latitude"&gt;63.798256&lt;/span&gt;,
	&lt;span class="longitude"&gt;11.494446&lt;/span&gt;
&lt;/p&gt;</code></pre>
<p>Are you starting to get a hang of it? Microformats isn&#8217;t hard to use. It&#8217;s all about using the same <acronym title="HyperText Markup Language">HTML</acronym> that you always use with the difference that you use certain class names to describe the content.</p>
<h3>The Javascript</h3>
<p>I use the classes in the markup as hooks to extract the data and put it in the map. As an added bonus I can also use the classes to style the visual appearance of the content.</p>
<p>In map.js the script loops through the different events (<code>class="vevent"</code>) and look for information about them. It then uses this information to put a marker in the map and to create a info bubble that appears when you click the marker.</p>
<p>Here&#8217;s the code to extract the geo data:</p>
<p class="note"><strong>Note:</strong> I&#8217;ve used the <a href="http://www.domassistant.com/">Javascript library DOMAssistant</a> to ease the pain of <acronym title="Document Object Model">DOM</acronym> coding. If you don&#8217;t recognize the $() notation, you should definitively check it out.</p>
<pre><code>// Getting all elements marked up with the class="vevent"
var events = $('.vevent');

// Loop through all event elements to extract data about each event
for (var i=0; i &lt; events.length; i++) {
	// Extracting the coordinates
	events[i].latitude =  $(events[i]).elmsByClass('latitude')[0].innerHTML;
	events[i].longitude =  $(events[i]).elmsByClass('longitude')[0].innerHTML;
}</code></pre>
<p>And here&#8217;s the code for putting a marker into a Google map (some code omitted for clarity of the example):</p>
<pre><code>// Creating a point in Google map
var point = new GPoint(events[i].longitude, events[i].latitude);

// Creating and adding a marker in Google Maps
var marker = new GMarker(point);

// The variable map is the map object.
// It's been created earlier in the code and is not shown in the example
map.addOverlay(marker); </code></pre>
<p>Of course in the demo I do more than this. I extract more information about the events and then use it to create an info bubble which I attach to the click event of the marker. Please check out the entire Javascript code for this demo by downloading <a href="http://www.svennerberg.com/microformats/js/map.js">map.js</a>.</p>
<p>If you want to use the code yourself you also need <a href="http://www.svennerberg.com/microformats/js/DOMAssistantComplete-2.7.js">DOMAssistantComplete-2.7.js</a> (or newer) and an <a href="http://code.google.com/apis/maps/signup.html"><acronym title="Application Programming Interface">API</acronym>-key for Google maps</a>.</p>
<p><a href="http://www.svennerberg.com/microformats/">Watch the demo in action</a></p>
<h3>Related resources</h3>
<ul>
<li><a href="http://code.google.com/apis/maps/">Google Maps api</a></li>
<li><a href="http://www.microformats.org/">Microformats</a></li>
<li><a href="http://www.domassistant.com/">DOMAssistant</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.svennerberg.com/2008/05/using-microformats-to-populate-google-map/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
