Include Wikipedia POIs in your Virtual Earth Map
Several websites offer their users the possibility to show Wikipedia articles on their map. In most cases this feature is an easy way to add value to your map. In this tutorial I am showing you how you can use the free Wikipedia webservices to include Wikipedia Points of Interest in your own VEMap.
Step 1: Find the right webservice for your application
When it comes to Wikipedia webservices GeoNames.org ist the right place to look for a webservice. Geonames provides a large list of Wikipedia based webservices for free and commercial use. Just visit the Webservice overwiew page (http://www.geonames.org/export/ws-overview.html) to select the webservice which best meets your requirements.
In most cases the wikipediaBoundingBox webservice is a good way to start. Therefore I am going to use it in this tutorial. The first thing should be to take a look at the example URL to see the JSON returned by the webservice:
Example URL:
http://ws.geonames.org/wikipediaBoundingBoxJSON?north=44.1&south=-9.9&east=-22.4&west=55.2
Step 2: Build up your AJAX proxy
The wikipediaBoundingBox requires the coordinates of a bounding box and will return Wikipedia articles within the bounding box area. Please notice that only Wikipedia articles which are geocoded will be returned by the webservice!
The first thing we need is some kind of a proxy script because AJAX calls are not allowed to make cross domain requests. In this example I am using PHP but you can use any other server-side language you prefer (like ASP, Java, Perl, etc.). A very simple proxy.php could look like:
<?php
print file_get_contents($_GET['url']);
?>
Our AJAX call is going to call the proxy.php and send the URL to the GeoNames Webservice as a GET parameter called "url".
Step 3: Build your HTML page
Now that we have our AJAX proxy we can start to build the HTML code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script charset="UTF-8" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2" type="text/javascript"></script>
<script src="http://yui.yahooapis.com/2.7.0/build/utilities/utilities.js"></script>
<style type="text/css">
img { border:0; }
</style>
</head>
<body onload="init()">
<div id="map" style="position:absolute; width:800px; height:400px;"></div>
</body>
</html>
You may have noticed that I also included an utilties.js file. This file is part of the YUI JavaScript framework and supports an easy to use interface for AJAX calls. You can use any framework you prefer (e.g. Prototype, ExtJS or similar) or you can use your own functions for AJAX calls.
The second thing to notice is the onload function we use. It is just called init() and is called when the page has finished loading.
Step 4: Insert your JavaScript code
In the last step we have to integrate the JavaScript Code. First we start with building our map within the init() method:
function init() {
// create our map and set the center point
map = new VEMap('map');
map.LoadMap(new VELatLong(60, 11), 10);
// create a shape layer for our pins
wikipediaLayer = new VEShapeLayer();
// turn clustering on - uncomment the following line to turn clustering off
wikipediaLayer.SetClusteringConfiguration(VEClusteringType.Grid);
map.AddShapeLayer(wikipediaLayer);
// call findWikipedia() every time the map is zoomed or panned
map.AttachEvent('onendpan', findWikipedia);
map.AttachEvent('onendzoom', findWikipedia);
// we want to show the pins on startup - so call findWikipedia()
findWikipedia();
}
So we first create a VEMap. Afterwards we are creating a new VEShapeLayer which will hold the Wikipedia pins. We are also using the clustering mechanism provided by Virtual Earth. If you don't want your pins to be clusterd uncomment the line.
We also attach two events to our map (onendpan and onendzoom). This is necessary because we have to reload the Wikipedia pins when the users zooms in/out or pans the map. So everytime the users zooms or pans a method called findWikipedia() is called. This method could look like this:
function findWikipedia() {
// remove all pins from our wikipedia Layer
wikipediaLayer.DeleteAllShapes();
// we need to get the coordinates of our bounding box
var view = map.GetMapView();
var south = view.TopLeftLatLong.Latitude;
var west = view.TopLeftLatLong.Longitude;
var north = view.BottomRightLatLong.Latitude;
var east = view.BottomRightLatLong.Longitude
// the url to the geonames webservice
var wikiUrl = 'http://ws.geonames.org/wikipediaBoundingBoxJSON?north='+north+'&south='+south+'&east='+east+'&west='+west+'&lang=en';
var proxyUrl = 'proxy.php?url='+escape(wikiUrl);
// our callback object - onsuccess is called when loading has finished
var callback = {
success: function(o) {
// data now has the object returned by the webservice
var data = eval('(' + o.responseText + ')');
if(data.geonames) {
// loop through every wikipedia POI which was returned
for(var i=0; i<data.geonames.length; i++) {
var poi = data.geonames[i];
// create a pin and set title, description and photo
var pin = new VEShape(VEShapeType.Pushpin, new VELatLong(poi.lat, poi.lng));
pin.SetTitle(poi.title);
pin.SetDescription(poi.summary);
pin.SetMoreInfoURL(poi.wikipediaUrl);
pin.SetPhotoURL(poi.thumbnailImg);
// add the pin to our wikipedia Layer
wikipediaLayer.AddShape(pin);
}
}
}
};
// AJAX call to our proxy.php
var transaction = YAHOO.util.Connect.asyncRequest('GET', proxyUrl, callback, null);
}
This method is the essential part. It first deletes all shapes on the layer. This is important because otherwise the number of shapes could grow too large and make your map slow. The next task is to create the URL to the webservice by getting the bounding box using the VEMap.GetMapView() method.
Within the success method of our AJAX callback we are then looping through the results and creating the pins for our map. Take a look at the response of your proxy.php to see other properties of the GeoName webservice. In this example we are using the title, summary, wikipediaUrl and the thumbnailImg.
This is just the start... Your map should now show the wikipedia POIs. You can now add additional functionality if you like (e.g. using checkboxes to turn the wikipediaLayer on or off). You should also be able to use similar GeoNames webservices.