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

<channel>
	<title>David Janes&#039; Code Weblog &#187; maps</title>
	<atom:link href="http://code.davidjanes.com/blog/category/maps/feed/" rel="self" type="application/rss+xml" />
	<link>http://code.davidjanes.com/blog</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Sun, 11 Apr 2010 12:32:10 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Twitter uses WOEIDs &#8211; why you should care</title>
		<link>http://code.davidjanes.com/blog/2009/11/14/twitter-use-woeids/</link>
		<comments>http://code.davidjanes.com/blog/2009/11/14/twitter-use-woeids/#comments</comments>
		<pubDate>Sat, 14 Nov 2009 10:43:50 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[ideas]]></category>
		<category><![CDATA[maps]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=608</guid>
		<description><![CDATA[Because I don&#8217;t think this announcement got sufficient attention: Twitter is using Yahoo&#8217;s WOEIDs to identify locations in its Geolocation API.
WOEIDs are:

a numeric identifier for geographical places or regions, from a &#8220;place of interest&#8221; all the way up to continent
uniquely defined, for each place
hierarchically nested
related to each other by natural concepts, such as neighbor-of, sibling-of, [...]]]></description>
			<content:encoded><![CDATA[<p>Because I don&#8217;t think this announcement got sufficient attention: <a href="http://www.ygeoblog.com/2009/11/woeids-are-trending-on-twitter/">Twitter is using Yahoo&#8217;s WOEIDs to identify locations in its Geolocation API</a>.</p>
<p>WOEIDs are:</p>
<ul>
<li>a numeric identifier for geographical places or regions, from a &#8220;place of interest&#8221; all the way up to continent</li>
<li>uniquely defined, for each place</li>
<li>hierarchically nested</li>
<li>related to each other by natural concepts, such as neighbor-of, sibling-of, etc.</li>
<li>managed, by Yahoo</li>
<li>a language independent way of talking about place</li>
<li>not necessarily tied to political boundaries, i.e. there&#8217;s a WOEID for the Bay Area</li>
</ul>
<p>This announcement is important because:</p>
<ul>
<li>it orders tweets into &#8220;containers&#8221; that can be used to find those tweets easily. In particular, there&#8217;s now codes that a <em>machine</em> can easily work with to find <em>human</em> concepts. Previous attempts at identification depended upon things such user entered hash tags for things such as a nearby airport, postal code, zip code, etc. and other concepts that don&#8217;t necessarily reflect what&#8217;s really going on</li>
<li>it encourages others to start building on WOEIDs, a <a href="http://googleblog.blogspot.com/2009/09/place-pages-for-google-maps-there-are.html">non-Google</a> way of identifying places</li>
</ul>
<p>Read more:</p>
<ul>
<li><a href="http://www.ygeoblog.com/2009/11/woeids-are-trending-on-twitter/">Yahoo GeoPlanet Annoucement</a></li>
<li><a href="http://groups.google.com/group/twitter-api-announce/browse_thread/thread/f6608c09902976c6?hl=en">Twitter&#8217;s Annoucement</a></li>
<li><a href="http://www.techcrunch.com/2009/11/09/twitter-to-rollout-a-new-api-for-location-based-trends/">TechCrunch</a></li>
<li><a href="http://developer.yahoo.com/geo/geoplanet/guide/concepts.html">Yahoo Technical Stuff anout WOEIDs</a> (+ APIs, etc. here)</li>
</ul>
<p>Note that I have some concerns about how well WOEIDs will work when we start wanting them being dynamically/crowd defined down to the business level (e.g. sort of like what <a href="http://foursquare.com/">foursquare</a> is doing; I don&#8217;t think they use WOEIDs though.)</p>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2009/11/14/twitter-use-woeids/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How iPhone OS 3.0 delivers location services</title>
		<link>http://code.davidjanes.com/blog/2009/06/27/how-iphone-os-30-delivers-location-services/</link>
		<comments>http://code.davidjanes.com/blog/2009/06/27/how-iphone-os-30-delivers-location-services/#comments</comments>
		<pubDate>Sat, 27 Jun 2009 11:38:40 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[iphone]]></category>
		<category><![CDATA[maps]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=563</guid>
		<description><![CDATA[Alec Saunders has a seriously cool article on his blog about how your iPhone knows where it is. I got to experience how well this works yesterday when we used TimmyMe in the McCowan Road/Ellesmere Avenue neighborhood to grab a coffee pre-meeting:

Many folks assume that iPhone’s location services are GPS based.  In fact, they’re [...]]]></description>
			<content:encoded><![CDATA[<p>Alec Saunders has a <a href="http://saunderslog.com/2009/06/26/skyhook-how-iphone-os-3-0-delivers-location-services/">seriously cool article on his blog</a> about how your iPhone knows where it is. I got to experience how well this works yesterday when we used <a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=285921640&#038;mt=8">TimmyMe</a> in the <a href="http://maps.google.ca/maps?hl=en&#038;safe=off&#038;ie=UTF8&#038;cd=1&#038;geocode=FSRNnAIdH-JG-w&#038;split=0&#038;sll=49.891235,-97.15369&#038;sspn=16.71875,56.536561&#038;ll=43.772783,-79.251809&#038;spn=0.01427,0.033023&#038;z=16">McCowan Road/Ellesmere Avenue neighborhood</a> to grab a coffee pre-meeting:</p>
<blockquote><p>
Many folks assume that iPhone’s location services are GPS based.  In fact, they’re not.  [...]</p>
<p>Skyhook’s innovation is to augment that with WiFi hotspot locations.  Why WiFi? It can be wonderfully accurate, to within 30 to 60 feet, or 10 to 20m which is roughly the same as GPS.  WiFi can establish a fix within less than a second.  And, WiFi is not vulnerable to overhead obstructions, so it can be used indoors. </p>
<p>Skyhook’s technology relies on a database of WiFi access points in over 2,000 cities (and growing).  Much like Google, they use vehicles to drive cities, and using a laptop in the vehicle, they chart the location of WiFi access points.  <strong>In addition, on iPhone as users use the mapping application, new locations and newly discovered WiFi access points are automatically added to the database.  It’s a kind of automated crowdsourcing, based on usage</strong>.
</p></blockquote>
<p>My emphasis on that last sentence. Very cool.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2009/06/27/how-iphone-os-30-delivers-location-services/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pipe Cleaner (II)</title>
		<link>http://code.davidjanes.com/blog/2008/12/23/pipe-cleaner-ii/</link>
		<comments>http://code.davidjanes.com/blog/2008/12/23/pipe-cleaner-ii/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 11:37:58 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[demo]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[pipe cleaner]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=388</guid>
		<description><![CDATA[Here&#8217;s the latest evolution of Pipe Cleaner, mainly recorded here for historical interest. The big change is that there isn&#8217;t a separate outside template &#8211; everything is in the one index.jd file. The new directive is template, which can read and execute an outside module or actually produce the final output (as we see in [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s the latest evolution of <a href="http://code.davidjanes.com/blog/2008/12/18/pipe-cleaner/">Pipe Cleaner</a>, mainly recorded here for historical interest. The big change is that there isn&#8217;t a separate outside template &#8211; everything is in the one <code>index.jd</code> file. The new directive is <code>template</code>, which can read and execute an outside module or actually produce the final output (as we see in the very last directive). I have not put this up as an independent demo.</p>
<pre>
#
#	Import the Python fire module
#	- used in: map from:"fire.GetGeocodedIncidents" to:"incidents"
#
import module:"fire";

#
#	Header for Google Maps popup
#	- used in: map from:"fire.GetGeocodedIncidents" to:"incidents"
#
#
set to:"fitem.head.map" value:"""
&lt;h3&gt;
&lt;a href="#{{ IncidentNumber }}"&gt;{{ AlarmLevel}}: {{ IncidentType }} on {{ RawStreet }}&lt;/a&gt;
&lt;/h3&gt;
""";

#
#	Header for the sidebar
#	- used in: map from:"fire.GetGeocodedIncidents" to:"incidents"
#
set to:"fitem.head.sb" value:"""
&lt;h3&gt;
{% if latitude and longitude %}
&lt;a href="javascript:js_maps.map.panTo(new GLatLng({{ latitude }}, {{ longitude }}))"&gt;*&lt;/a&gt;
{% endif %}
&lt;a href="#{{ IncidentNumber }}"&gt;{{ AlarmLevel}}: {{ IncidentType }} on {{ RawStreet }}&lt;/a&gt;
&lt;/h3&gt;
""";

#
#	Body for the Google Maps pop and the sidebar
#	- used in: map from:"fire.GetGeocodedIncidents" to:"incidents"
#
set to:"fitem.body" value:"""
&lt;p&gt;
Alarm Level: {{ AlarmLevel }}
&lt;br /&gt;
Incident Type: {{ IncidentType }}
&lt;br /&gt;
City: {{ City }}
&lt;br /&gt;
Street: {{ Street }} ({{ CrossStreet }})
&lt;br /&gt;
Units: {{ Units }}
&lt;/p&gt;
""";

#
#	Convert all the incidents from the fire module
#	to the path 'incidents' using the mapping rules defined above
#
#	- incidents are used in "gmaps.js" and "gmaps.html"
#
map from:"fire.GetGeocodedIncidents" to:"incidents" map:{
	"latitude" : "{{ latitude }}",
	"longitude" : "{{ longitude }}",
	"title" : "{{ AlarmLevel}}: {{ IncidentType }} on {{ RawStreet }}",
	"uri" : "{{ HOME_URI }}#{{ IncidentNumber }}",
	"body" : "{{ *fitem.head.map|safe }}{{ *fitem.body|safe }}",
	"body_sb" : "{{ *fitem.head.sb|safe }}{{ *fitem.body|safe }}",
	"IncidentNumber" : "{{ IncidentNumber }}"
};

#
#	Load the 'gmaps' templates (for arbitrary geo-mapping),
#	using the 'incidents' for its items and the specified meta.
#
#	- used in in "gmaps.js" and "gmaps.html"
#
set to:"map_meta" value_render:true value:{
	"id" : "maps",
	"latitude" : 43.67,
	"longitude" : -79.38,
	"uzoom" : -13,
	"gzoom" : 13,
	"api_key" : "{{ cfg.gmaps.api_key|otherwise:'ABQIAAA...pIxzZQ' }}",
	"html" : {
		"width" : "1024px",
		"height" : "800px"
	}
};

#
#	Produce GMaps
#
template script:"gmaps" items:"incidents" meta:"map_meta";

#
#	Produce the final output
#
template value:"""
&lt;html&gt;
&lt;head&gt;
    &lt;link rel="stylesheet" type="text/css" href="css.css" /&gt;
	{{ gmaps.js|safe }}
&lt;/head&gt;
&lt;body&gt;
&lt;div id="content_wrapper"&gt;
	&lt;div id="map_wrapper"&gt;
		{{ gmaps.html|safe }}
	&lt;/div&gt;
	&lt;div id="text_wrapper"&gt;
{% for incident in incidents %}
	&lt;div id="{{ incident.IncidentNumber }}"&gt;
		{{ incident.body_sb|safe }}
	&lt;/div&gt;
{% endfor %}
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
""";
</pre>
<p>The gmaps.jd (imported in the second last directive) looks like as follows (there will not be a test). It&#8217;s designed to be a universal &#8220;show a map and plot points on in it&#8221; inclusion. I&#8217;ve added a few line breaks so the <code>PRE</code> box doesn&#8217;t break.</p>
<pre>
#
#
#
template to:"html" value:"""
&lt;div id="id_{{ meta.id|jslug }}"
style="{% if meta.html.width %}width: {{ meta.html.width }};{% endif %}
{% if meta.html.height %} height: {{ meta.html.height }};{% endif %}
{% if meta.html.style %} style: {{ meta.html.style }};{% endif %}"
{% if meta.html.class %} class="{{ meta.html.class }}"{% endif %}
&gt;&lt;/div&gt;
&lt;script type="text/javascript"&gt;
js_{{ meta.id|jslug }}.onload();
&lt;/script&gt;
""";

#
#
#
template to:"js" value:"""
&lt;script
 type="text/javascript"
 src="http://maps.google.com/maps?file=api&amp;v=2&amp;key={{meta.api_key}}"&gt;
&lt;/script&gt;
&lt;script type="text/javascript"&gt;
js_{{ meta.id|jslug }} = {
 onload : function() {
  js_{{ meta.id|jslug }}.map = new GMap2(document.getElementById("id_{{ meta.id|jslug }}"));
  m = js_{{ meta.id|jslug }}.map;
  m.setCenter(new GLatLng({{ meta.latitude }}, {{ meta.longitude }}), {{ meta.gzoom }});

  // {{ items|length }} items follow
{% for itemd in items %}
{% if itemd.latitude and itemd.longitude %}

  // {{ itemd.title }}
  var ll = new GLatLng({{ itemd.latitude }}, {{ itemd.longitude }});
  var marker = js_{{ meta.id|jslug }}.make_marker(m, ll, "{{ itemd.body|safe|escapejs }}");
  m.addOverlay(marker);
{% else %}
  // an item is missing latitude or longitude
{% endif %}
{% endfor %}
 },

 make_marker : function(m, ll, html) {
  var marker = new GMarker(ll);
  GEvent.addListener(marker, "click", function() {
   m.openInfoWindowHtml(ll, html);
  });

  return marker;
 },

 end : 0
}
&lt;/script&gt;
""";
</pre>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/12/23/pipe-cleaner-ii/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pipe Cleaner</title>
		<link>http://code.davidjanes.com/blog/2008/12/18/pipe-cleaner/</link>
		<comments>http://code.davidjanes.com/blog/2008/12/18/pipe-cleaner/#comments</comments>
		<pubDate>Thu, 18 Dec 2008 23:38:21 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[demo]]></category>
		<category><![CDATA[djolt]]></category>
		<category><![CDATA[dqt]]></category>
		<category><![CDATA[html / javascript]]></category>
		<category><![CDATA[ideas]]></category>
		<category><![CDATA[jd]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[pipe cleaner]]></category>
		<category><![CDATA[pybm]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=372</guid>
		<description><![CDATA[I&#8217;ve been working (in my decreasing available spare time) on a project to pull together into a project called &#8220;Pipe Cleaner&#8221; all the various concepts I&#8217;ve been mentioning on this blog: Web Object Records (WORK) for API Access and object manipulation, Djolt for generating text from templates, Data/Query/Transform/Template (DQT) for transforming data and JD for [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working (in my decreasing available spare time) on a project to pull together into a project called &#8220;Pipe Cleaner&#8221; all the various concepts I&#8217;ve been mentioning on this blog: <a href="http://code.davidjanes.com/blog/category/work/">Web Object Records (WORK</a>) for API Access and object manipulation, <a href="http://code.davidjanes.com/blog/category/djolt/">Djolt</a> for generating text from templates, <a href="http://code.davidjanes.com/blog/category/dqt/">Data/Query/Transform/Template</a> (DQT) for transforming data and <a href="http://code.davidjanes.com/blog/category/jd/">JD</a> for scripting these elements together. The pieces came together this morning enough to put a demo together and here it is &#8211; <a href="http://code.davidjanes.com/examples/2008-12-18/gmaps3/">the Toronto Fires Pt II Demo</a>.</p>
<p>How, you may ask, does this differ from <a href="http://code.davidjanes.com/blog/2008/11/22/toronto-fires/">the original Toronto Fires Demo</a>? The answer is how it is put together, which we describe here.</p>
<h4>Index.dj</h4>
<p>This is the Djolt template that generates the output. The data fed to this template is generate by the JD script, described in the next section.</p>
<pre>&lt;html&gt;
&lt;head&gt;
    &lt;link rel="stylesheet" type="text/css" href="css.css" /&gt;
    {{ gmaps.js|safe }}
&lt;/head&gt;
&lt;body&gt;
&lt;div id="content_wrapper"&gt;
    &lt;div id="map_wrapper"&gt;
        {{ gmaps.html|safe }}
    &lt;/div&gt;
    &lt;div id="text_wrapper"&gt;
{% for incident in incidents %}
    &lt;div id="{{ incident.IncidentNumber }}"&gt;
        {{ incident.body_sb|safe }}
    &lt;/div&gt;
{% endfor %}
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Quite simple &#8230; as you can see, most of the data is being pulled in from elsewhere. The elsewhere is provided by the script described in the next section.</p>
<h4>Index.jd</h4>
<p>This is the script that pull all the pieces together. Note that I&#8217;m not 100% happy with the way the data is imported, I would like the geocoding to become part of this data flow too. In the next release perhaps.</p>
<p>First we pull in the &#8220;fire&#8221; module that we wrote in the previous Map examples. This is doing exactly what you think: importing a Python module. We may have to increase the security or restrict this to working with an API for general purpose use.</p>
<pre>import module:"fire";</pre>
<p>Next we define two headers &#8211; one that is going to appear in the Google Maps popup, the next that is going to appear in the sidebar. They need to be different as they refer to themselves. Note that the sidebar header &#8220;breaks&#8221; the encapsulation of Google Maps &#8211; this seems to be unavoidable. The <code>to:"fitem.head.map"</code> and <code>to:"fitem.head.sb"</code> are manipulating a WORK dictionary to store values.</p>
<p>Note also here that we&#8217;ve extended JD to accept Python multiline strings &#8211; this was unavoidable if JD was to be useful to me.</p>
<pre>set to:"fitem.head.map" value:"""
&lt;h3&gt;
&lt;a href="#{{ IncidentNumber }}"&gt;{{ AlarmLevel}}: {{ IncidentType }} on {{ RawStreet }}
&lt;/h3&gt;
""";

set to:"fitem.head.sb" value:"""
&lt;h3&gt;
{% if latitude and longitude %}
&lt;a href="javascript:js_maps.map.panTo(new GLatLng({{ latitude }}, {{ longitude }}))"&gt;*
{% endif %}
&lt;a href="#{{ IncidentNumber }}"&gt;{{ AlarmLevel}}: {{ IncidentType }} on {{ RawStreet }}
&lt;/h3&gt;
""";</pre>
<p>The next block defines the text of the body used to describe a fire incident. It follows much the same pattern as the previous block.</p>
<pre>set to:"fitem.body" value:"""
&lt;p&gt;
Alarm Level: {{ AlarmLevel }}
&lt;br /&gt;
Incident Type: {{ IncidentType }}
&lt;br /&gt;
City: {{ City }}
&lt;br /&gt;
Street: {{ Street }} ({{ CrossStreet }})
&lt;br /&gt;
Units: {{ Units }}
&lt;/p&gt;
""";</pre>
<p>This is a map: it is translating the values in <code>fire.GetGeocodeIncidents</code> into a new format and storing that in <code>incidents</code>. The format that we were are storing it in is understood by the Google Maps generating module.</p>
<p>We may rename this translate, as the word map is somewhat overloaded.</p>
<pre>map from:"fire.GetGeocodedIncidents" to:"incidents" map:{
    "latitude" : "{{ latitude }}",
    "longitude" : "{{ longitude }}",
    "title" : "{{ AlarmLevel}}: {{ IncidentType }} on {{ RawStreet }}",
    "uri" : "{{ HOME_URI }}#{{ IncidentNumber }}",
    "body" : "{{ *fitem.head.map|safe }}{{ *fitem.body|safe }}",
    "body_sb" : "{{ *fitem.head.sb|safe }}{{ *fitem.body|safe }}",
    "IncidentNumber" : "{{ IncidentNumber }}"
};</pre>
<p>Next we set up the &#8220;meta&#8221; (see <a href="http://code.davidjanes.com/blog/2008/11/11/work-web-object-records/">WORK meta description</a> if you&#8217;re not following along) for the maps. The <code>render_value:true</code> declaration makes PC interpret the templates in strings). We then call our Google Maps generating code (which are actually more Pipe Cleaners) and that gets fed to the Djolt template we first showed you. Clear? Maybe not, we&#8217;ll have more examples coming&#8230;</p>
<pre>set to:"map_meta" render_value:true value:{
    "id" : "maps",
    "latitude" : 43.67,
    "longitude" : -79.38,
    "uzoom" : -13,
    "gzoom" : 13,
    "api_key" : "{{ cfg.gmaps.api_key|otherwise:'...mykey...' }}",
    "html" : {
        "width" : "1024px",
        "height" : "800px"
    }
};

load template:"gmaps.js" items:"incidents" meta:"map_meta";
load template:"gmaps.html" items:"incidents" meta:"map_meta";</pre>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/12/18/pipe-cleaner/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Once more with the maps</title>
		<link>http://code.davidjanes.com/blog/2008/12/07/once-more-with-the-maps/</link>
		<comments>http://code.davidjanes.com/blog/2008/12/07/once-more-with-the-maps/#comments</comments>
		<pubDate>Sun, 07 Dec 2008 12:48:39 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[maps]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=306</guid>
		<description><![CDATA[Michal Migurski added a very informative comment about tiling levels here, with a pointer to way more detailed information here.
]]></description>
			<content:encoded><![CDATA[<p><a href="http://mike.teczno.com/">Michal Migurski</a> added <a href="http://code.davidjanes.com/blog/2008/11/08/switching-between-mapping-apis-and-universal-map-levels/#comment-98">a very informative comment about tiling levels here</a>, with <a href="http://modestmaps.mapstraction.com/trac/wiki/TileCoordinateComparisons">a pointer to way more detailed information here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/12/07/once-more-with-the-maps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Toronto Fires</title>
		<link>http://code.davidjanes.com/blog/2008/11/22/toronto-fires/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/22/toronto-fires/#comments</comments>
		<pubDate>Sat, 22 Nov 2008 21:19:58 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[demo]]></category>
		<category><![CDATA[djolt]]></category>
		<category><![CDATA[ideas]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=249</guid>
		<description><![CDATA[Here&#8217;s a little mashup I&#8217;ve been putting together for the last few days: Toronto Fires.
It&#8217;s taking the data listed here on the City of Toronto&#8217;s Fire Services &#8220;Active Accidents&#8221;, scraping it (by pretending HTML is XHTML and treating it as WORK objects), geocoding it (using our WORK Google API) and mapping it (using this information).
This [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a little mashup I&#8217;ve been putting together for the last few days: <a href="http://code.davidjanes.com/examples/2008-11-22/fires/">Toronto Fires</a>.</p>
<p>It&#8217;s taking the data listed here on the <a href="http://www.toronto.ca/fire/cadinfo/livecad.htm">City of Toronto&#8217;s Fire Services &#8220;Active Accidents&#8221;</a>, scraping it (by pretending HTML is XHTML and treating it as <a href="http://code.davidjanes.com/blog/2008/11/11/work-web-object-records/">WORK</a> objects), geocoding it (using our <a href="http://code.davidjanes.com/blog/2008/11/18/work-api-teaser-iii-google-api/">WORK Google API</a>) and mapping it (using <a href="http://code.davidjanes.com/blog/category/maps/">this information</a>).</p>
<p>This is very much a work in progress, but here&#8217;s a few more things that are involved:</p>
<ul>
<li>we read <code>body.table.tr.td[1].table.tr[1].td.table.tr</code> as a list to get the rows in the table</li>
<li>we map those rows into the Geocoder use a new magic technology we&#8217;ll be explaining in the next few days: <a href="http://www.djangoproject.com/">Djolt</a> &#8211; <a href="http://www.djangoproject.com/">Django</a>-like <a href="http://docs.djangoproject.com/en/dev/ref/templates/builtins/">templates</a></li>
<li>the output program is just one big Djolt template</li>
</ul>
<p>I&#8217;m not quite satisfied with how the current page is constructed: I want the final result to be much more simple.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/22/toronto-fires/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to make your blog readable on an iPhone</title>
		<link>http://code.davidjanes.com/blog/2008/11/14/how-to-make-your-blog-readable-on-an-iphone/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/14/how-to-make-your-blog-readable-on-an-iphone/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 15:47:08 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[html / javascript]]></category>
		<category><![CDATA[ideas]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=225</guid>
		<description><![CDATA[Here&#8217;s the following changes I made to this blog to make it readable on an iPhone
Add iPhone directives to header

the META tag informas the iPhone about how wide we want the page to look &#8211; i.e. the width of the iPhone
the LINK tag loads our iPhone specific CSS (tip from here)
this should be after your [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s the following changes I made to this blog to make it readable on an iPhone</p>
<h4>Add iPhone directives to header</h4>
<ul>
<li>the META tag informas the iPhone about how wide we want the page to look &#8211; i.e. the width of the iPhone</li>
<li>the LINK tag loads our iPhone specific CSS (tip from <a href="http://iphone.wikidot.com/detection">here</a>)</li>
<li>this should be after your normal CSS LINK (or whatever) directive</li>
</ul>
<pre>&lt;meta name="viewport" content="width=320" /&gt;
&lt;link rel="stylesheet" type="text/css"
  media="only screen and (max-device-width: 480px)"
  href="/blog/wp-content/themes/davidjanes/iphone.css" /&gt;</pre>
<h4>Define iPhone specific CSS</h4>
<ul>
<li>this will obviously vary depending on what your current CSS does &#8211; that still gets loaded</li>
<li>most of this was pragmatically discovered</li>
<li>I hide several sections which I don&#8217;t think the user wants to see on an iPhone; I&#8217;ll probably play with this more</li>
<li>the PRE directive doesn&#8217;t use line breaking, so we just clip the examples, after making sure the font is small enough to get enough on a single line</li>
</ul>
<pre>body {
    padding: 5px;
    width: 480px;
}
div#content {
    float: none;
}
div#menu {
    display: none;
}
p.credit {
    display: none;
}
pre {
    overflow: hidden;
    font-size: 10px !important;
}
h1, h1 * {
    font-size: 36px;
}</pre>
<h4>What still needs to be done</h4>
<ul>
<li>we shouldn&#8217;t serve sections that users are not going to see &#8211; it&#8217;s a waste of bandwidth</li>
<li>we shouldn&#8217;t serve more than 10 articles</li>
<li>I&#8217;ll have to figure out how to do mobile browser detection on WordPress</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/14/how-to-make-your-blog-readable-on-an-iphone/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to enable/disable Mouse Wheel actions on your map</title>
		<link>http://code.davidjanes.com/blog/2008/11/14/how-to-enabledisable-mouse-wheel-actions-on-your-map/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/14/how-to-enabledisable-mouse-wheel-actions-on-your-map/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 13:44:31 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[html / javascript]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=222</guid>
		<description><![CDATA[All the major map APIs have the ability to zoom in and out if your pointer is over the map and you scroll the mouse wheel. Being able to disable this function if you&#8217;re working in a small popup form window is very important!
Google Maps
By default, this feature is disabled. To enable:
map.enableScrollWheelZoom();
To disable (again):
map.disableScrollWheelZoom();
Source
Yahoo Maps
By [...]]]></description>
			<content:encoded><![CDATA[<p>All the major map APIs have the ability to zoom in and out if your pointer is over the map and you scroll the mouse wheel. Being able to disable this function if you&#8217;re working in a small popup form window is very important!</p>
<h4>Google Maps</h4>
<p>By default, this feature is disabled. To enable:</p>
<pre>map.enableScrollWheelZoom();</pre>
<p>To disable (again):</p>
<pre>map.disableScrollWheelZoom();</pre>
<p><a href="http://googlemapsapi.blogspot.com/2007/04/v278-go-ahead-scroll-your-mouse-wheels.html">Source</a></p>
<h4>Yahoo Maps</h4>
<p>By default, this feature is enabled. To disable:</p>
<pre>map.disableKeyControls()</pre>
<p>There doesn&#8217;t appear to be a way to re-enable afterward.</p>
<p><a href="http://developer.yahoo.com/maps/ajax/V3.8/index.html#YMap">Source</a></p>
<h4>Microsoft Virtual Earth</h4>
<p>By default, this feature is enabled. To disable you have to capture the event:</p>
<pre>trap = function() { return true; }
map.AttachEvent("onmousewheel", trap);</pre>
<p>To re-enable, you have to detach the exact same event (hence the trap function)</p>
<pre>map.DetachEvent("onmousewheel", trap);</pre>
<p><a href="http://social.msdn.microsoft.com/Forums/en-US/vemapcontroldev/thread/7e67849e-c8ed-4626-94c6-1f13ad333a9e/">Source</a></p>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/14/how-to-enabledisable-mouse-wheel-actions-on-your-map/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Adding MapField to inputEx</title>
		<link>http://code.davidjanes.com/blog/2008/11/09/adding-mapfield-to-inputex/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/09/adding-mapfield-to-inputex/#comments</comments>
		<pubDate>Sun, 09 Nov 2008 11:20:40 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[demo]]></category>
		<category><![CDATA[genx]]></category>
		<category><![CDATA[html / javascript]]></category>
		<category><![CDATA[ideas]]></category>
		<category><![CDATA[inputex]]></category>
		<category><![CDATA[maps]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=161</guid>
		<description><![CDATA[InputEx is a neat Javascript library by Eric Abouaf and other contributors to dynamically create forms. It&#8217;s best shown by example, so:

detailed examples of how to create all individual fields
a form builder in Javascript (click on the pencil to close popups or try my version &#8211; see the notes below)

I&#8217;m working on a project called [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://javascript.neyric.com/inputex/">InputEx</a> is a neat Javascript library by <a href="http://javascript.neyric.com/blog/">Eric Abouaf</a> and other contributors to dynamically create forms. It&#8217;s best shown by example, so:</p>
<ul>
<li><a href="http://javascript.neyric.com/inputex/doc/js_docs_out/examples.html">detailed examples of how to create all individual fields</a></li>
<li><a href="http://javascript.neyric.com/inputex/inputExBuilder/inputExBuilder.html">a form builder in Javascript</a> (click on the pencil to close popups <a href="http://localhost/~davidjanes/genx/inputex/inputExBuilder/inputExBuilder.html">or try my version</a> &#8211; see the notes below)</li>
</ul>
<p>I&#8217;m working on a project called <a href="http://code.davidjanes.com/genx/demo/">GenX</a> that allows people to dynamically lookup, edit and create data in editors (such as in WordPress). One of the features I want is the ability to add maps so after a week of research, I&#8217;ve created a MapField for inputEx:</p>
<ul>
<li><a href="http://code.davidjanes.com/inputex/demo/examples/map_field.html">see the MapField example</a></li>
</ul>
<h4>Notes</h4>
<ul>
<li>this is just a preliminary version; there&#8217;s probably some code style and idiom issues that need to be worked out</li>
<li>I&#8217;m going to ask the InputEx group to pick this up; I reserve no rights</li>
<li>it&#8217;s not fully integrated into the Builder example yet</li>
<li>it works with Google Maps, Yahoo Maps and Microsoft&#8217;s Virtual Earth. You will need a key for your domain for Google Maps, see the example above about how to insert your key</li>
<li>it introduces a concept of a Globals for MapField, as there are certain settings (i.e. your mapping keys) that really belong at &#8220;class&#8221; level rather than instantiated object level</li>
<li>Mapping APIs are <a href="http://code.davidjanes.com/blog/2008/11/08/how-to-dynamically-load-map-apis/">dynamically loaded</a></li>
<li>Zoom levels are returned in native format and &#8220;<a href="http://code.davidjanes.com/blog/2008/11/08/switching-between-mapping-apis-and-universal-map-levels/">universal format</a>&#8220;</li>
<li>I&#8217;ve done all my testing of FF3, so there may be browser issues I need to look at</li>
</ul>
<h4>Code changes</h4>
<ul>
<li>the only files needed are
<ul>
<li><code>examples/map_field.html</code></li>
<li><code>js/fields/MapField.js</code></li>
</ul>
</li>
</ul>
<h4>Where this is going</h4>
<ul>
<li>I&#8217;ve spent the last week working on maps; I need to get back to <em>using</em> this code rather than improving and documenting it</li>
<li>I want to add a geocoder</li>
<li>I want the geocoder to be able to be sensitive to other form fields, so for example if you&#8217;re entering an address it can actually use those as an input</li>
</ul>
<h4>One final mod to inputEx</h4>
<p>I&#8217;ve modified the builder to make the pencil icon more obviously become the close button when you&#8217;ve opened a subpanel. <a href="http://code.davidjanes.com/inputex/demo/inputExBuilder/inputExBuilder.html">You can see the demo here</a>. Here&#8217;s the change set:</p>
<p>In <code>images</code>:</p>
<pre>curl --location http://www.famfamfam.com/lab/icons/silk/icons/pencil_delete.png \
 &gt; pencil_delete.png</pre>
<p>In <code>inputex/inputExBuilder/css/inputExBuilder.css</code> add:</p>
<pre>div.inputEx-TypeField-EditButton.opened {
   background-image: url(../../images/pencil_delete.png);
}</pre>
<p>In <code>inputex/js/fields/TypeField.js</code> replace <code>onTogglePropertiesPanel</code> with:</p>
<pre>   onTogglePropertiesPanel: function() {
      if (this.propertyPanel.style.display == 'none') {
         this.propertyPanel.style.display = '';
         YAHOO.util.Dom.addClass(this.button, "opened");
      } else {
         this.propertyPanel.style.display = 'none';
         YAHOO.util.Dom.removeClass(this.button, "opened");
      }
   },</pre>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/09/adding-mapfield-to-inputex/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Switching between mapping APIs and universal zoom levels</title>
		<link>http://code.davidjanes.com/blog/2008/11/08/switching-between-mapping-apis-and-universal-map-levels/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/08/switching-between-mapping-apis-and-universal-map-levels/#comments</comments>
		<pubDate>Sat, 08 Nov 2008 19:03:30 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[html / javascript]]></category>
		<category><![CDATA[maps]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=152</guid>
		<description><![CDATA[Did you know that Google Maps, Yahoo Maps and Virtual Earth all use the same map tile resolutions? That is, you can actually seamlessly switch between mapping systems and have everything line up exactly the same way.  If you&#8217;d like to play with this, look at our map examples:

Google Maps example
Virtual Earth example
Yahoo Maps [...]]]></description>
			<content:encoded><![CDATA[<p>Did you know that <a href="http://code.google.com/apis/maps/">Google Maps</a>, <a href="http://developer.yahoo.com/maps/">Yahoo Maps</a> and <a href="http://dev.live.com/virtualearth/sdk/">Virtual Earth</a> all use the same map tile resolutions? That is, you can actually seamlessly switch between mapping systems and have everything line up exactly the same way.  If you&#8217;d like to play with this, look at our map examples:</p>
<ul>
<li><a href="http://code.davidjanes.com/examples/2008-11-02/map-google.html">Google Maps example</a></li>
<li><a href="http://code.davidjanes.com/examples/2008-11-02/map-virtualearth.html">Virtual Earth example</a></li>
<li><a href="http://code.davidjanes.com/examples/2008-11-02/map-yahoo.html">Yahoo Maps example</a> (change the zoom level to 5)</li>
</ul>
<p>But it&#8217;s even easier to show this using a graphic (thank you to <a href="http://peapod.ca/blog/">Alistair Morton</a> of <a href="http://www.peapod.ca/">Peapod Studios</a> for compositing): <img src="http://code.davidjanes.com/examples/2008-11-08/all-maps2.jpg" border="0" alt="All Maps" /></p>
<h4>Table of map zoom level equivalents</h4>
<p>Google Maps and Virtual Earth the same zoom levels, excepting that Google has a level 0. Bigger numbers are closer to the ground, smaller numbers are up into space. Yahoo Maps has fewer levels to work with &#8211; it doesn&#8217;t let you drill down below the block level. Yahoo numbers its zoom levels the opposite of Google and Virtual Earth, small numbers being closer to the ground and so on and so forth.</p>
<p>To allow seamless switching of data between APIs, I propose here <strong>universal zoom levels</strong>, which can be used as-is on any of these mapping APIs. To avoid confusion of which type of zoom level one is using, we use the negative number range for universal zoom levels. As Google and Microsoft are using the same zoom levels, I&#8217;ve decided that the universal zoom levels should simply be the inverse of their zoom levels, bounded by (-1, -19) inclusive.</p>
<table border="0">
<thead>
<tr>
<th></th>
<th>Google Maps</th>
<th>Virtual Earth</th>
<th>Yahoo Maps</th>
<th>Universal</th>
</tr>
</thead>
<thead></thead>
<tbody>
<tr>
<th>Ground</th>
<td>19</td>
<td>19</td>
<td>-</td>
<td>-19</td>
</tr>
<tr>
<td></td>
<td>18</td>
<td>18</td>
<td>-</td>
<td>-18</td>
</tr>
<tr>
<th>Block</th>
<td>17</td>
<td>17</td>
<td>1</td>
<td>-17</td>
</tr>
<tr>
<td></td>
<td>16</td>
<td>16</td>
<td>2</td>
<td>-16</td>
</tr>
<tr>
<td></td>
<td>15</td>
<td>15</td>
<td>3</td>
<td>-15</td>
</tr>
<tr>
<td></td>
<td>14</td>
<td>14</td>
<td>4</td>
<td>-14</td>
</tr>
<tr>
<th>City</th>
<td>13</td>
<td>13</td>
<td>5</td>
<td>-13</td>
</tr>
<tr>
<td></td>
<td>12</td>
<td>12</td>
<td>6</td>
<td>-12</td>
</tr>
<tr>
<td></td>
<td>11</td>
<td>11</td>
<td>7</td>
<td>-11</td>
</tr>
<tr>
<td></td>
<td>10</td>
<td>10</td>
<td>8</td>
<td>-10</td>
</tr>
<tr>
<td></td>
<td>9</td>
<td>9</td>
<td>9</td>
<td>-9</td>
</tr>
<tr>
<td></td>
<td>8</td>
<td>8</td>
<td>10</td>
<td>-8</td>
</tr>
<tr>
<th>State</th>
<td>7</td>
<td>7</td>
<td>11</td>
<td>-7</td>
</tr>
<tr>
<td></td>
<td>6</td>
<td>6</td>
<td>12</td>
<td>-6</td>
</tr>
<tr>
<td></td>
<td>5</td>
<td>5</td>
<td>13</td>
<td>-5</td>
</tr>
<tr>
<td></td>
<td>4</td>
<td>4</td>
<td>14</td>
<td>-4</td>
</tr>
<tr>
<td></td>
<td>3</td>
<td>3</td>
<td>15</td>
<td>-3</td>
</tr>
<tr>
<td></td>
<td>2</td>
<td>2</td>
<td>16</td>
<td>-2</td>
</tr>
<tr>
<th>Space</th>
<td>1</td>
<td>1</td>
<td>17</td>
<td>-1</td>
</tr>
<tr>
<td></td>
<td>0</td>
<td>-</td>
<td>-</td>
<td>-</td>
</tr>
</tbody>
</table>
<h4>Conversion Formulae</h4>
<p>Here&#8217;s Javascript to convert between your favorite mapping API&#8217;s zoom levels and universal zoom levels. Note that all <code>to_native</code> functions accept positive numbers as-is.</p>
<pre>zoom = {
  google : {
    to_univeral : function(native) {
      return  Math.min(-1, -native);
    },  

    to_native : function(universal) {
      return  universal &gt; 0 ? universal : -universal;
    }
  },

  virtual_earth : {
    to_univeral : function(native) {
      return  Math.min(-1, -native);
    },  

    to_native : function(universal) {
      return  universal &gt; 0 ? universal : -universal;
    }
  },

  yahoo : {
    to_univeral : function(native) {
      return  Math.min(-1, native - 18);
    },  

    to_native : function(universal) {
      return  universal &gt; 0 ? universal : Math.max(universal + 18, 1);
    }
  }
};</pre>
<h4>End Notes</h4>
<p>A truly universal zoom level would just use altitude; dealing with a simple integer is easier and less complication prone though. MapQuest is not included in this post as its tiles do not line up with the other APIs.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/08/switching-between-mapping-apis-and-universal-map-levels/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>How to dynamically load map APIs</title>
		<link>http://code.davidjanes.com/blog/2008/11/08/how-to-dynamically-load-map-apis/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/08/how-to-dynamically-load-map-apis/#comments</comments>
		<pubDate>Sat, 08 Nov 2008 17:11:01 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[html / javascript]]></category>
		<category><![CDATA[maps]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=140</guid>
		<description><![CDATA[When using various map APIs it&#8217;s often useful for performance reasons not to actually load the API until we&#8217;re sure we&#8217;re going to need it. This is called dynamic loading or lazy loading. The post explains how to do this on the three major mapping APIs.
Note about the examples
These have been excerpted from a project [...]]]></description>
			<content:encoded><![CDATA[<p>When using various map APIs it&#8217;s often useful for performance reasons not to actually load the API until we&#8217;re sure we&#8217;re going to need it. This is called dynamic loading or lazy loading. The post explains how to do this on the three major mapping APIs.</p>
<h4>Note about the examples</h4>
<p>These have been excerpted from a project I am currently working on, and so don&#8217;t work as-is. The basic calling structure (not shown) is as follows:</p>
<ul>
<li>assume each function is being called from <code>CALLER</code>.</li>
<li>If <code>true</code> is returned we allow the dynamic loader to do it&#8217;s work; when that is complete it calls <code>CALLER.CREATE_MAP</code>.</li>
<li>If <code>true</code> isn&#8217;t returned, we assume everything is good to go and the caller directly calls <code>CALLER.CREATE_MAP</code> &#8211; this will typically happen when the Map API is detected in Javascript!</li>
</ul>
<p>There&#8217;s also a global context in <code>GLOBALS</code> used for keeping track of state. In particular, we assume the user may be trying to create multiple maps so we have to make sure all the <code>CREATE_MAP</code> callbacks are triggered once all the Javascript has been loaded!</p>
<p>In the Google Maps and Virtual Earth we see the Javascript-with-callback pattern:</p>
<ul>
<li>a callback function is passed in the URL as a parameter</li>
<li>the downloaded Javascript document is dynamically modified so that it calls that function. Hence, you know the Javascript has been loaded.</li>
</ul>
<p>If you&#8217;re a Javascript noob, scripts are dynamically loaded into your HTML document by creating a <code>SCRIPT</code> element and attaching it to the document <code>HEAD</code>.</p>
<h4>Google Maps API</h4>
<p><a href="http://code.google.com/apis/maps/">Google Maps API</a> uses a multi-phase loading scheme:</p>
<ul>
<li>get the generic loader, giving it a callback function to invoke when it&#8217;s completely loaded</li>
<li>when that&#8217;s loaded (into <code>google</code>)&#8230;</li>
<li>call the loader to get the maps API</li>
<li>when that&#8217;s loaded, create the map</li>
</ul>
<p>This feature is documented <a href="http://code.google.com/apis/ajax/documentation/#Dynamic">here</a>.</p>
<pre>google_preload : function(CALLER) {
    if (window.GMap2) {
        return;
    }

    var api_key = YOUR_GOOGLE_API_KEY_FOR_YOUR_DOMAIN;

    var preloader = 'MapGooglePreloader_' + GLOBALS.MapFieldsNumber;
    GLOBALS[preloader] = function() {
        google.load("maps", "2", {
            "callback" : function() {
                CALLER.CREATE_MAP();
            }
        });
    }

    if (window.google) {
        GLOBALS[preloader]();
    } else {
        var script = document.createElement("script");
        script.src = "http://www.google.com/jsapi?key=" + api_key +
        "&amp;callback=GLOBALS." + preloader;
        script.type = "text/javascript";

        document.getElementsByTagName("head")[0].appendChild(script);
    }

    return  true;
}</pre>
<h4>Microsoft Virtual Earth</h4>
<p>The <a href="http://dev.live.com/virtualearth/sdk/">Virtual Earth API</a> is easy to dynamically load also. As with Google this feature is directly supported through a Javascript callback mechanism; unlike Google it&#8217;s essentially a single phase design.</p>
<p>One issue I ran into was the error message <strong><code>p_elSource.attachEvent is not a function</code></strong> error. Although a <a href="http://www.google.ca/search?hl=en&amp;ampq=p_elSource.attachEvent+is+not+a+function&amp;ampbtnG=Google+Search&amp;ampmeta=">Google search for a solution</a> mostly turns up a blank, a tip of the hat to <a href="http://soulsolutions.com.au/Blog/tabid/73/EntryID/519/Default.aspx">Soul Solutions in Australia</a> for finding a work-around (and have similarly solved dynamic API loading at the link).</p>
<pre>virtualearth_preload : function(CALLER) {
    if (window.VEMap) {
        return;
    }

    var preloader = 'MapVEPreloader_' + GLOBALS.MapFieldsNumber;
    GLOBALS[preloader] = function() {
        CALLER.CREATE_MAP();
    }

    if (!window.attachEvent) {
        var script = document.createElement("script");
        script.src = "http://dev.virtualearth.net/mapcontrol/v6.2/js/atlascompat.js";
        script.type = "text/javascript";

        document.getElementsByTagName("head")[0].appendChild(script);
    }

    var script = document.createElement("script");
    script.src = "http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2" +
      "&amp;onScriptLoad=GLOBALS." + preloader;
    script.type = "text/javascript";

    document.getElementsByTagName("head")[0].appendChild(script);

    return  true;
}</pre>
<h4>Yahoo AJAX Map API</h4>
<p>The <a href="http://developer.yahoo.com/maps/ajax/">Yahoo AJAX Map API</a> does not directly support dynamic API loading. However, just loading the Javascript and running a timer that waits to see whether the script has loaded seems to do the trick. If you&#8217;re new-ish to Javascript, remember that it&#8217;s not multi-threaded so we can always be sure that when a Javascript file is loaded, it is completely loaded (excepting errors, of course).</p>
<pre>yahoo_preload : function(CALLER) {
    if (window.YMap) {
        return;
    }

    var preloader = 'MapYahooPreloader_' + GLOBALS.MapFieldsNumber;
    if (!GLOBALS[preloader]) {
        GLOBALS[preloader] = 1;

        window.YMAPPID = YOUR_YAHOO_API_KEY;

        var script = document.createElement("script");
        script.src = "http://us.js2.yimg.com/us.js.yimg.com/lib/map/js/api/ymapapi_3_8_0_7.js";
        script.type = "text/javascript";

        document.getElementsByTagName("head")[0].appendChild(script);
    }

    window.setTimeout(function() {
        if (window.YMap) {
            CALLER.CREATE_MAP();
        } else {
            CALLER.yahoo_preload(CALLER);
        }
    }, 0.1);

    return  true;
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/08/how-to-dynamically-load-map-apis/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>How to use the Google Maps API</title>
		<link>http://code.davidjanes.com/blog/2008/11/07/how-to-use-the-google-maps-api/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/07/how-to-use-the-google-maps-api/#comments</comments>
		<pubDate>Fri, 07 Nov 2008 10:32:15 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[demo]]></category>
		<category><![CDATA[html / javascript]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=121</guid>
		<description><![CDATA[The Google Maps API is the great granddaddy of mapping API. Originally, the GMap API was an internal private Google API until reverse engineered by Adrian Holovaty to create the first great mapping mashup, Chicago Crime (now folded into Every Block). The API is well documented, well understood and easy-to-use but suffers from the look [...]]]></description>
			<content:encoded><![CDATA[<p><img style="float: right" src="http://code.davidjanes.com/examples/2008-11-02/map-google.png" alt="" />The Google Maps API is the great granddaddy of mapping API. Originally, the GMap API was an internal private Google API until <a href="http://42topics.com/blog/2008/06/an-interview-with-adrian-holovaty/">reverse engineered</a> by <a href="http://holovaty.com/">Adrian Holovaty</a> to create the first great mapping mashup, Chicago Crime (now folded into <a href="http://chicago.everyblock.com/crime/">Every Block</a>). The API is well documented, well understood and easy-to-use but suffers from the look getting a little long in the tooth and the API key design imposing a higher administrative burden than the competing packages.</p>
<p>The way we set up the events in Google Maps is a little different than we did in <a href="http://code.davidjanes.com/blog/2008/11/04/how-to-use-the-mapquest-api/">MapQuest</a>, <a href="http://code.davidjanes.com/blog/2008/11/02/how-to-use-the-yahoo-maps-service-ajax-api/">Yahoo Maps</a> and <a href="http://code.davidjanes.com/blog/2008/11/05/how-to-use-the-microsoft-virtual-earth-api/">Visual Earth</a>. GMaps uses a two phase creation scheme, using one call to create the map object and a second call to actually display it somewhere. I like this and it would have got around <a href="http://code.davidjanes.com/blog/2008/11/05/how-to-use-the-microsoft-virtual-earth-api/">the &#8220;jumping map&#8221; issue we saw in Virtual Earth</a>. Because we want to capture the load event &#8211; to get the initial state of the map &#8211; we have to put it between these two calls otherwise we&#8217;ll miss the load event (it would be nice if Google just <em>called </em>your &#8220;onload&#8221; callback if the map was already loaded).</p>
<p>My least favorite part of the GMap API is that you need a <em>per-domain</em> API key. This is the most restrictive licensing of any of the mapping packages. Amongst the problems this will cause you:</p>
<ul>
<li>if you&#8217;re working in development, staging, deployment environments you&#8217;ll have to drive your map from dynamic HTML, as you&#8217;ll need to switch in the correct key</li>
<li><span style="text-decoration: line-through;"><code>http://<em>user</em>.example.com</code>, it will mean that all your users will have to individually sign up for API keys &#8212; e.g. uptake will be slow.</span> <strong>update</strong>: see the comments</li>
</ul>
<p>The <a href="http://code.google.com/apis/maps/documentation/index.html">documentation</a> for the GMap API is by far the best of any of the mapping package. Everything is cleanly laid out and there&#8217;s no question how you get from concepts, to examples, to the API spec.</p>
<p>Here’s our <strong><a href="http://code.davidjanes.com/examples/2008-11-02/map-google.html">example map application</a></strong> and the source below. You&#8217;ll have to get your own API key and substitute it in if you want to start using this example. Geocoding is almost as easy as in the Yahoo API, with the caveat that you really want to set the <code>baseCountryCode</code>, as it won&#8217;t make a guess for the country on your behalf. Unlike all the other applications, the GMap API will <em>not</em> take strings where it expects numbers, hence all the <code>parseFloat</code>s in the example below.</p>
<pre>&lt;html&gt;
&lt;head&gt;&lt;script
    type="text/javascript"
    src="http://maps.google.com/maps?file=api&amp;amp;v=2&amp;amp;key=YOURKEY"&gt;&lt;/script&gt;
&lt;style type="text/css"&gt;
#id_map {
    height: 75%;
    width: 100%;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id="id_map"&gt;&lt;/div&gt;
&lt;p&gt;
Lat: &lt;input type="text" id="id_lat" onchange="map_js.onupdate_ll()" /&gt;
Lon: &lt;input type="text" id="id_lon" onchange="map_js.onupdate_ll()" /&gt;
Zoom: &lt;input type="text" id="id_zoom" onchange="map_js.onupdate_zoom()" /&gt;
&lt;/p&gt;
&lt;script type="text/javascript"&gt;
map_js = {
    e_lat : null,
    e_lon : null,
    e_map : null,
    g_map : null,
    g_geocoder : null,

    create : function() {
        map_js.e_map = document.getElementById("id_map");
        map_js.e_lat = document.getElementById("id_lat");
        map_js.e_lon = document.getElementById("id_lon");
        map_js.e_zoom = document.getElementById("id_zoom");

        map_js.g_map = new GMap2(map_js.e_map);
        map_js.g_geocoder = new GClientGeocoder();
        map_js.g_geocoder.setBaseCountryCode("ca")

        GEvent.addListener(map_js.g_map, "load", map_js.onposition);
        GEvent.addListener(map_js.g_map, "moveend", map_js.onposition);
        GEvent.addListener(map_js.g_map, "zoomend", map_js.onposition);

        map_js.g_map.addControl(new GSmallMapControl());
        map_js.g_map.addControl(new GMapTypeControl());

        map_js.g_geocoder.getLatLng("Toronto, ON", map_js.ongeocoded);
        // map_js.g_map.setCenter(new GLatLng(43.648565, -79.385329), 13);
    },

    ongeocoded : function(point) {
        if (!point) {
            alert("not found");
        } else {
            map_js.g_map.setCenter(point, 13);
        }
    },

    onposition : function() {
        var c = map_js.g_map.getCenter();
        map_js.e_lat.value = c.lat();
        map_js.e_lon.value = c.lng();

        var z = map_js.g_map.getZoom();
        map_js.e_zoom.value = z;
    },

    onupdate_ll : function() {
        map_js.g_map.panTo(
            new GLatLng(parseFloat(map_js.e_lat.value), parseFloat(map_js.e_lon.value)));
    },

    onupdate_zoom : function() {
        map_js.g_map.setZoom(parseInt(map_js.e_zoom.value));
    },

    end : 0
};
map_js.create();
&lt;/script&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/07/how-to-use-the-google-maps-api/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>How to use the Microsoft Virtual Earth API</title>
		<link>http://code.davidjanes.com/blog/2008/11/05/how-to-use-the-microsoft-virtual-earth-api/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/05/how-to-use-the-microsoft-virtual-earth-api/#comments</comments>
		<pubDate>Wed, 05 Nov 2008 17:40:47 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[demo]]></category>
		<category><![CDATA[html / javascript]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=112</guid>
		<description><![CDATA[ Next up in our tour of Javascript mapping APIs is Microsoft&#8217;s Virtual Earth. VE is a full-featured mapping API with a visually appealing look, but with a number of gotchas what watchfors which I&#8217;ll list here.
VE is rather picky about the CSS and styles it sees (not nearly so much as MapQuest though!). In [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://code.davidjanes.com/examples/2008-11-02/map-virtualearth.png" style="float: right" /> Next up in our tour of Javascript mapping APIs is <a href="http://dev.live.com/virtualearth/sdk/">Microsoft&#8217;s Virtual Earth</a>. VE is a full-featured mapping API with a visually appealing look, but with a number of gotchas what watchfors which I&#8217;ll list here.</p>
<p>VE is rather picky about the CSS and styles it sees (not nearly so much as MapQuest though!). In particular:</p>
<ul>
<li>make sure you add a <code>position: relative</code> or <code>position: absolute</code> to the CSS definitions for the map&#8217;s DIV, otherwise it will go crazy on at least Firefox. I added <code>position: relative</code> and it worked fine</li>
<li>contrary to the documentation, VE wants to see the style rules directly on the element rather than inherited from CSS, otherwise it seems to default to the 600px by 400px default. Fortunately, once you&#8217;ve done this it does understand <code>width: 100%</code> and similar.</li>
</ul>
<p>Unlike MapQuest and Yahoo Maps, VE comes with a rather comprehensive map control installed. The downside of this is that if you want a simpler interface you&#8217;re going to have to code it yourself. In particular, there&#8217;s an option for a &#8220;Bird&#8217;s Eye&#8221; view of the map you&#8217;re looking at. Once you click on this, concepts like the map having a latitude and longitude go out the window (for reasons I don&#8217;t grasp). You can see in the example below that we actually test to see if Lat/Lon is available before attempting to display it. Also note that <a href="http://msdn.microsoft.com/en-us/library/bb412539.aspx">the documentation</a> for <code>VEMap.GetCenter</code> is wrong &#8212; a <code>null</code> is <em>not </em>returned; instead Latitude and Longitude are <code>null</code>.</p>
<p>Microsoft really needs to adopt a more modern view of Javascript. One obvious thing would be to start using namespaces to isolate code &#8212; use VE.Map rather than VEMap. The VEMap constructor doesn&#8217;t accept a (DOM) element as an argument, you have to pass the ID. Another ugliness is the use of lengthy optional argument lists, <a href="http://msdn.microsoft.com/en-us/library/bb429645.aspx">such as this atrocity</a>:</p>
<pre>VEMap.Find(<em>what</em>, <em>where</em>, <em>findType</em>, <em>shapeLayer</em>, <em>startIndex</em>,
  <em>numberOfResults</em>, <em>showResults</em>, <em>createResults</em>, <em>useDefaultDisambiguation</em>,
  <em>setBestMapView</em>, <em>callback</em>);</pre>
<p>This was understandable in the Win32 C-code days but not so much when passing a dictionary would accomplish much of the same in a simpler manner.</p>
<p>VE includes a rather straightforward geocoding call &#8211; despite what the documentation above implies. Just do:</p>
<pre>map_js.ve_map.Find(null, "Toronto, ON");</pre>
<p>Unfortunately, this has a two shortcomings:</p>
<ul>
<li>you cannot &#8220;Geocode at setup time&#8221; like you can in Yahoo Maps, so you have to display one location, then jump to the one you really want</li>
<li>the Geocoder changes you&#8217;re zoom level, whether you want it to or not. From a mapping point-of-view I could see how this makes sense (e.g. show all of Toronto), but it would be nice if it was optional</li>
</ul>
<p>We&#8217;ve got the geocoder in the example below commented out, but you may find it useful. Just remember that it&#8217;s asynchronous, so the actual map jump will not happen until after your current JS terminates.</p>
<p>Finally, to end on high note, VE doesn&#8217;t appear to need a developer or application key meaning you can just take this example to modify and run as you please. Here&#8217;s <strong><a href="http://code.davidjanes.com/examples/2008-11-02/map-virtualearth.html">our example map application</a></strong> and the source below:</p>
<pre>&lt;html&gt;
&lt;head&gt;
&lt;script charset="UTF-8" type="text/javascript"
  src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2&amp;mkt=en-us"&gt;&lt;/script&gt;
&lt;style type="text/css"&gt;
#id_map{
position: relative;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id="id_map" style="width: 100%; height: 75%;"&gt;&amp;nbsp;&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;
Lat: &lt;input type="text" id="id_lat" onchange="map_js.onupdate_ll()" /&gt;
Lon: &lt;input type="text" id="id_lon" onchange="map_js.onupdate_ll()" /&gt;
Zoom: &lt;input type="text" id="id_zoom" onchange="map_js.onupdate_zoom()" /&gt;

&lt;/p&gt;
&lt;script type="text/javascript"&gt;
map_js = {
	e_lat : null,
	e_lon : null,
	e_map : null,
	ve_map : null,

	create : function() {
		map_js.e_lat = document.getElementById("id_lat");
		map_js.e_lon = document.getElementById("id_lon");
		map_js.e_zoom = document.getElementById("id_zoom");

		map_js.ve_map = new VEMap("id_map");
		map_js.ve_map.LoadMap(new VELatLong(43.648565, -79.385329), 13,
		  VEMapStyle.Road, false, VEMapMode.Mode2D, true, 1);
		// map_js.ve_map.Find(null, "Toronto, ON");

		map_js.ve_map.AttachEvent("onendzoom", map_js.onposition);
		map_js.ve_map.AttachEvent("onendpan", map_js.onposition); 

		map_js.onposition();
	},

	onposition : function() {
		var c = map_js.ve_map.GetCenter();
		if (!c || !c.Latitude) {
			return;
		}

		map_js.e_lat.value = c.Latitude;
		map_js.e_lon.value = c.Longitude;

		var z = map_js.ve_map.GetZoomLevel();
		map_js.e_zoom.value = z;
	},

	onupdate_ll : function() {
		map_js.ve_map.PanToLatLong(new VELatLong(map_js.e_lat.value, map_js.e_lon.value));
	},

	onupdate_zoom : function() {
		map_js.ve_map.SetZoomLevel(map_js.e_zoom.value);
	},

	end : 0
};
map_js.create();
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/05/how-to-use-the-microsoft-virtual-earth-api/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to use the MapQuest API</title>
		<link>http://code.davidjanes.com/blog/2008/11/04/how-to-use-the-mapquest-api/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/04/how-to-use-the-mapquest-api/#comments</comments>
		<pubDate>Tue, 04 Nov 2008 12:02:13 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[demo]]></category>
		<category><![CDATA[html / javascript]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=93</guid>
		<description><![CDATA[This post should be subtitled &#8220;MapQuest, I&#8217;m disappointed in you&#8221;. I have to say I was looking for a lot more out of this toolkit, because they&#8217;re a late entrant to the modern AJAX-y map interface so they should have known what will work and what would; because they&#8217;re still (I think) the #1 online [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://code.davidjanes.com/examples/2008-11-02/map-mapquest.png" style="float: right" />This post should be subtitled &#8220;<a href="http://www.mapquest.com/">MapQuest</a>, I&#8217;m disappointed in you&#8221;. I have to say I was looking for a lot more out of this toolkit, because they&#8217;re a late entrant to the modern AJAX-y map interface so they should have known what will work and what would; because they&#8217;re still (I think) the #1 online mapping company;  because I like cheering for scrappy underdog even if they&#8217;re really giant behemoths; and finally because I saw Kevin Survance, CTO of MapQuest <a href="http://www.eng.ajaxian.com/archives/tae-keynote-ajax-through-the-looking-glass">speak at the Ajax Experience in Boston in 2007</a> and thought his presentation rocked.</p>
<p>Alas, there&#8217;s a number of shortcomings you should know about before you throw away your Google Maps (Yahoo Maps, Live Maps) application:</p>
<ul>
<li>the maps don&#8217;t look that great &#8211; there&#8217;s a lot pixelation due to light or non-existent anti-aliasing</li>
<li><em>the map size has to be set explicitly as a style tag using pixels, not percentages</em>! No CSS for you!</li>
<li>the Geocoding feature <em>requires a local proxy</em> &#8211; while I understand the technical appeal of this, all the other mapping packages have got around this, why can&#8217;t MapQuest? As a result, our example app below does not demonstrate geocoding, it just hard-codes the lat/lon</li>
<li>I wasn&#8217;t that impressed with the documentation / &#8220;hello world&#8221;-type examples. One issue here is that MapQuest may be targeting desktop applications and so browser JS is suffering for attention</li>
</ul>
<p>Now, there seems to be a fairly complete API so there may be further virtues to the MapQuest API that I&#8217;m missing, so take that as a caveat. On the other hand, there&#8217;s a level of equivalency in map dimensions between all the other mapping packages that MapQuest doesn&#8217;t have; I&#8217;ll quantify this after I complete this survey of map APIs.</p>
<p>I’ve created <strong><a href="http://code.davidjanes.com/examples/2008-11-02/map-mapquest.html">an example map application</a></strong> which displays a map, the current lat/lon and zoom level, and lets the map position to be adjusted by editing those same values. If you’d like to get started with the MapQuest API yourself:</p>
<ul>
<li><a href="http://developer.mapquest.com/Home/WhyJoin">register with MapQuest to get developer keys</a>, etc.. Note that the examples here is using the default MapQuest key and seem to work fine for testing; I just wouldn&#8217;t use that for production purposes<a href="https://developer.yahoo.com/wsregapp/"><br />
</a></li>
<li>copy the code below to “map.html” in favorite hosting environment — it should even work off your disk</li>
<li>add your developer key, if you got one, in the appropriate place</li>
<li>run, enjoy, modify</li>
</ul>
<p>Further reading:</p>
<ul>
<li> <a href="http://developer.mapquest.com/Library/CodeSamples/JavaScript">Javascript code samples</a></li>
<li> <a href="http://developer.mapquest.com/betaAPI/docs/API_5.3_Developer_Reference/files/mqa-tilemap-js.html">Tiled Map reference</a></li>
<li> <a href="http://developer.mapquest.com/content/documentation/ApiDocumentation/53/JavaScript/JS_DeveloperGuide_v5.3.0.1.htm">Javascript reference (complete looking)</a></li>
</ul>
<p>Source (note the <code>script</code> <code>src</code> has been split for formatting purposes):</p>
<pre>&lt;html&gt;
&lt;head&gt;
&lt;script src="http://btilelog.access.mapquest.com/tilelog/transaction?transaction=script&amp;
key=mjtd%7Clu6t2h07n1%2C2x%3Do5-lw7l9&amp;itk=true&amp;v=5.3.s&amp;ipkg=controls1,traffic&amp;ipr=false"
    type="text/javascript"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id="id_map" style="width: 1024px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;
Lat: &lt;input type="text" id="id_lat" onchange="map_js.onupdate_ll()" /&gt;
Lon: &lt;input type="text" id="id_lon" onchange="map_js.onupdate_ll()" /&gt;
Zoom: &lt;input type="text" id="id_zoom" onchange="map_js.onupdate_zoom()" /&gt;
&lt;/p&gt;
&lt;script type="text/javascript"&gt;
map_js = {
    e_lat : null,
    e_lon : null,
    e_map : null,
    mq_map : null,

    create : function() {
        map_js.e_map = document.getElementById('id_map');
        map_js.e_lat = document.getElementById("id_lat");
        map_js.e_lon = document.getElementById("id_lon");
        map_js.e_zoom = document.getElementById("id_zoom");

        map_js.mq_map = new MQA.TileMap(map_js.e_map, 9,
             new MQA.LatLng(43.648565, -79.385329), "map");
        map_js.mq_map.addControl(new MQA.ZoomControl());
        map_js.mq_map.addControl(new MQA.ViewControl());

        MQA.EventManager.addListener(map_js.mq_map, "zoomend", map_js.onposition);
        MQA.EventManager.addListener(map_js.mq_map, "dragend", map_js.onposition);

        map_js.onposition();
    },

    onposition : function() {
        var c = map_js.mq_map.getCenter();
        map_js.e_lat.value = c.getLatitude();
        map_js.e_lon.value = c.getLongitude();

        var z = map_js.mq_map.getZoomLevel();
        map_js.e_zoom.value = z;
    },

    onupdate_ll : function() {
        map_js.mq_map.panToLatLng(new MQA.LatLng(map_js.e_lat.value, map_js.e_lon.value));
    },

    onupdate_zoom : function() {
        map_js.mq_map.setZoomLevel(map_js.e_zoom.value);
    },

    end : 0
};
map_js.create();
&lt;/script&gt;
&lt;/body&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/04/how-to-use-the-mapquest-api/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>How to use the Yahoo Maps Service AJAX API</title>
		<link>http://code.davidjanes.com/blog/2008/11/02/how-to-use-the-yahoo-maps-service-ajax-api/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/02/how-to-use-the-yahoo-maps-service-ajax-api/#comments</comments>
		<pubDate>Sun, 02 Nov 2008 12:02:07 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[demo]]></category>
		<category><![CDATA[html / javascript]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=87</guid>
		<description><![CDATA[Yahoo is a nice alternative service to Google Maps for displaying maps on your website or service. Amongst its benefits:

it&#8217;s super easy to set up, as we&#8217;ll show below
it requires an &#8220;application key&#8221;, but once you have this you can run on any domain. GMaps requires a per-domain key, which means that if your deploying [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://code.davidjanes.com/examples/2008-11-02/map-yahoo.png" style="float: right" />Yahoo is a nice alternative service to Google Maps for displaying maps on your website or service. Amongst its benefits:</p>
<ul>
<li>it&#8217;s super easy to set up, as we&#8217;ll show below</li>
<li>it requires an &#8220;application key&#8221;, but once you have this you can run on any domain. GMaps requires a <em>per-domain key</em>, which means that if your deploying to multiple domains &#8212; for example, if you have a http://<em>user</em>.example.com type site &#8212; you&#8217;re suddenly going to find yourself with an intractable problem</li>
<li>it plays moderately well with <a href="http://developer.yahoo.com/yui/">YUI</a> conceptually, <span style="text-decoration: line-through;">though it doesn&#8217;t seem to use the same code base</span>. UPDATE: <a href="http://yuiblog.com/blog/2006/12/14/maps-plus-yui/">you have to do hacks to work with YUI</a>. Sigh.</li>
</ul>
<p>Note that Yahoo provides several APIs for maps, <a href="http://developer.yahoo.com/maps/ajax/">the AJAX API we&#8217;re using here</a>, <a href="http://developer.yahoo.com/flash/maps/">an API for Flash/Actionscript</a> and <a href="http://developer.yahoo.com/maps/rest/V1/">a REST API for getting map images</a>. There all different, so make sure you&#8217;re not reading the wrong docs for what you&#8217;re doing.</p>
<p>I&#8217;ve created <strong><a href="http://code.davidjanes.com/examples/2008-11-02/map-yahoo.html">an example map application</a></strong> which displays a map, the current lat/lon and zoom level, and lets the map position to be adjusted by editing those same values. If you&#8217;d like to get started with the Yahoo AJAX maps API:</p>
<ul>
<li><a href="https://developer.yahoo.com/wsregapp/">get an application key</a> &#8211; do not reuse mine or anyone else&#8217;s please<a href="https://developer.yahoo.com/wsregapp/"><br />
</a></li>
<li>copy the code below to &#8220;map.html&#8221; in favorite hosting environment &#8212; it should even work off your disk</li>
<li>add your application key in the appropriate place</li>
<li>run, enjoy, modify</li>
</ul>
<p>Further reading:</p>
<ul>
<li><a href="http://developer.yahoo.com/maps/ajax/">Yahoo&#8217;s getting started guide</a></li>
<li><a href="http://developer.yahoo.com/maps/ajax/V3.8/index.html">Yahoo&#8217;s reference guide</a></li>
</ul>
<p>Source:</p>
<pre>&lt;html&gt;
&lt;head&gt;
&lt;script type="text/javascript"
src="http://api.maps.yahoo.com/ajaxymap?v=3.8&amp;appid=YOURAPPID"&gt;&lt;/script&gt;
&lt;style type="text/css"&gt;
#map{
height: 75%;
width: 100%;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id="map"&gt;&lt;/div&gt;
&lt;p&gt;
Lat: &lt;input type="text" id="id_lat" onchange="map_js.onupdate_ll()" /&gt;
Lon: &lt;input type="text" id="id_lon" onchange="map_js.onupdate_ll()" /&gt;
Zoom: &lt;input type="text" id="id_zoom" onchange="map_js.onupdate_zoom()" /&gt;
&lt;/p&gt;
&lt;script type="text/javascript"&gt;
map_js = {
    e_lat : null,
    e_lon : null,
    e_map : null,
    y_map : null,

    create : function() {
        map_js.e_map = document.getElementById('map');
        map_js.e_lat = document.getElementById("id_lat");
        map_js.e_lon = document.getElementById("id_lon");
        map_js.e_zoom = document.getElementById("id_zoom");

        map_js.y_map = new YMap(map_js.e_map);
        map_js.y_map.addTypeControl();
        map_js.y_map.addZoomLong();
        map_js.y_map.addPanControl();
        map_js.y_map.setMapType(YAHOO_MAP_REG);

        YEvent.Capture(map_js.y_map, EventsList.endMapDraw, map_js.onposition);
        YEvent.Capture(map_js.y_map, EventsList.changeZoom, map_js.onposition);
        YEvent.Capture(map_js.y_map, EventsList.endPan, map_js.onposition);

        map_js.y_map.drawZoomAndCenter("Toronto, ON", 5);
    },

    onposition : function() {
        var c = map_js.y_map.getCenterLatLon();
        map_js.e_lat.value = c.Lat;
        map_js.e_lon.value = c.Lon;

        var z = map_js.y_map.getZoomLevel();
        map_js.e_zoom.value = z;
    },

    onupdate_ll : function() {
        map_js.y_map.panToLatLon(new YGeoPoint(map_js.e_lat.value, map_js.e_lon.value));
    },

    onupdate_zoom : function() {
        map_js.y_map.setZoomLevel(map_js.e_zoom.value);
    },

    end : 0
};
map_js.create();
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/02/how-to-use-the-yahoo-maps-service-ajax-api/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
