MediaWiki:GoogleMaps.js

//registers the Gmap_onload function as a window.onload event hookEvent('load', Gmap_onload);

//searches for all maps on the current page and calls their render function function Gmap_onload() { var maps = getElementsByClass('div', 'googleMap');

	for (i = 1; i <= maps.length; i++) {

var gmap_id = 'gmap_'+i; var form_id = 'mapform_'+i;

var renderer = document.getElementById(form_id).renderer;

if (!renderer) { alert('The Google Maps extensions is broken. Could not find renderer.'); } else { if (!window[renderer.value]) { alert('The map renderer ' + renderer.value + ' is not a valid function'); } else { window[renderer.value](i); } } }

}

//renders map n on a page //data is read from a form with name and id "mapform_n" where n is an integer starting at 1 and incrementing by 1 //the creation of this form is handled by the gmap extension function Gmap_renderMapOld(n) {

 gmap_id = 'gmap_'+n;
 form_id = 'mapform_'+n;
 message_id = 'gmapmessage_'+n;
 document.getElementById(gmap_id).style.width = document.getElementById(form_id).width.value;
 document.getElementById(gmap_id).style.height = document.getElementById(form_id).height.value;
 var map = new GMap2(document.getElementById(gmap_id));
 map.addControl(new GSmallMapControl());
 map.setCenter(new GLatLng(document.getElementById(form_id).lat.value, document.getElementById(form_id).lon.value, true), parseInt(document.getElementById(form_id).zoom.value), G_NORMAL_MAP);
 if (document.getElementById(form_id).controls.value == 'yes') {
   map.addControl(new GMapTypeControl());
 }
 if (document.getElementById(form_id).type.value == 'G_SATELLITE_MAP') {
   map.setMapType(G_SATELLITE_MAP);
 }
 else if (document.getElementById(form_id).type.value == 'G_NORMAP_MAP') {
   map.setMapType(G_NORMAL_MAP);
 }
 else if (document.getElementById(form_id).type.value == 'G_HYBRID_MAP') {
   map.setMapType(G_HYBRID_MAP);
 }
 GEvent.addListener(map, "moveend", function() {
   var center = map.getCenter();
   var latLngStr = '(' + center.y + ', ' + center.x + ')';
   document.getElementById(message_id).innerHTML = latLngStr;
 });


 if (document.getElementById(form_id).rss){
   //if the rss form element is defined, plot datapoints from an rss feed
   feedarray = document.getElementById(form_id).rss.value.split('|');
   for (var i = 0; i < feedarray.length; i++) {
     renderRSSFeed(map, feedarray[i]);
   }
 }
 else {
   var request = GXmlHttp.create();
   //the php script returns a very simple XML document
   request.open("GET", "/Special:GraphStructure/xml/locations", true);
   request.onreadystatechange = function() {
   	if (request.readyState == 4) {
       	var doc = request.responseXML;
       	var nodes = doc.documentElement.getElementsByTagName('node');
       	
       	for (var i = 0; i < nodes.length; i++) {
        		var node = nodes[i];
        		if (node.hasAttribute('smw:Coordinates')) {
        	    	var nodeType = node.getAttribute('type');
          	  	    var nodeTitle = node.getAttribute('title');
         	        var nodePoint = node.getAttribute('smw:Coordinates');
          	        var nodeURI = nodeTitle.replace(/ /g, '_');
               	if (nodeType == 'category') {
                   	nodeURI = "Category:" + nodeURI;

}

var html = "
<a href=\"/" + nodeURI + "\">" + nodeTitle + "</a>"; html += "
Location: " + nodePoint + "
";

//we find entities "located in" this node by using xpath foundNodes = findNodesWithRelationTo(doc, node.getAttribute("id"), "Located in");

if (foundNodes.length > 0) {

html += "
Located Here:</strong>
    "; for (var j = 0; j < foundNodes.length; j++) { var insertLink = foundNodes[j].getAttribute("title"); if (foundNodes[j].getAttribute("namespace") == 0) { insertLink = "<a href=\"/" + foundNodes[j].getAttribute("title").replace(/ /g, '_') + "\">" + insertLink + "</a>"; } html += "
  • " + insertLink + "
  • ";

    }

    html += "
";

}

           	    var point = parsePoint(nodePoint);
               	var marker = createMarker(point, html);
               	map.addOverlay(marker);
           	}
       	}
       }
   }
   request.send(null);
 }

}

//finds all nodes having relation to a destination node //for example, dstNode=6 relation="Located In" function findNodesWithRelationTo(doc, dstNode, relation) { var nodes = doc.documentElement.getElementsByTagName("node"); var foundNodes = new Array();

var foundEdgesPattern = "/MediaWikiGraph/edge[@relation='"+relation+"'][@to='"+dstNode+"']";

var resultEdges = doc.evaluate(foundEdgesPattern, doc.documentElement, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);

var thisEdge = resultEdges.iterateNext();

while (thisEdge) { //find the node in the document for (var i = 0; i < nodes.length; i++) { var node = nodes[i]; if (node.getAttribute("id") == thisEdge.getAttribute("from")) { foundNodes.push(node); } }

thisEdge = resultEdges.iterateNext(); }

return foundNodes;

}

function arcDegrees(arcminutes, arcseconds) {

   arcminutes = parseFloat(arcminutes);
   arcseconds = parseFloat(arcseconds);
   return (arcminutes / 60.0 + arcseconds / 3600.0);

}

function parsePoint(str) {

   var values = str.split(/\s*,\s*/);
   //            1         2           3               4
   var expr = /(\d+)&.*?;(\d+)&.*?;(\d+.?\d*)&.*?;\s*(\w)/;
   var lat = expr.exec(values[0]);
   var lng = expr.exec(values[1]);
   var latitude = parseFloat(lat[1]) + arcDegrees(lat[2], lat[3]);
   var longitude = parseFloat(lng[1]) + arcDegrees(lng[2], lng[3]);
   if (lat[4] == 'S') {
       latitude *= -1;
   }
   if (lng[4] == 'W') {
       longitude *= -1;
   }
   return new GLatLng(latitude, longitude, true);

}

function renderRSSFeed(map, rssurl) {

 var request = GXmlHttp.create();
 //the request.open method doesn't like URL's not on our server
 //the proxy.php script is a very simplistic proxy with some security features
 rssurl = "/misc/proxy.php?" + rssurl;
 request.open("GET", rssurl, true);
 request.onreadystatechange = function() {
   if (request.readyState == 4) {
      var xmlDoc = request.responseXML;
      var items = xmlDoc.documentElement.getElementsByTagName("item");
      for (var i = 0; i < items.length; i++) {
         var marker = createMarkerFromRSSItem(items[i]);
         map.addOverlay(marker);
      }
   }
 }
 request.send(null);

}

function createMarkerFromRSSItem(item) {

 var title = item.getElementsByTagName("title")[0].childNodes[0].nodeValue;
 var description = item.getElementsByTagName("description")[0].childNodes[0].nodeValue;
 var link = item.getElementsByTagName("link")[0].childNodes[0].nodeValue;
 var lat = item.getElementsByTagNameNS("http://www.w3.org/2003/01/geo/wgs84_pos#", "lat")[0].childNodes[0].nodeValue;
 var lon = item.getElementsByTagNameNS("http://www.w3.org/2003/01/geo/wgs84_pos#", "long")[0].childNodes[0].nodeValue;
 var point = new GPoint(parseFloat(lon), parseFloat(lat));
 var marker = new GMarker(point);
 var html = '<a href="' + link + '">' + title + '</a><p />' + description;
 GEvent.addListener(marker, "click", function() {
   marker.openInfoWindowHtml(html);
 });
 return marker;

}


function createMarker(point, html) {

 var marker = new GMarker(point);
 GEvent.addListener(marker, "click", function() {
   marker.openInfoWindowHtml(html);
 });
 return marker;

}

//a helper function that returns an array of element ids of a given type and class function getElementsByClass(elem, classname) {

 classes = new Array();
 alltags = document.getElementsByTagName(elem);
 for (i=0; i<alltags.length; i++) {
   if (alltags[i].className == classname) {
     classes.push(alltags[i].id);
   }
 }
 return classes;

}



var brianScript = {

'arcDegrees': function(arcminutes, arcseconds) {

   arcminutes = parseFloat(arcminutes);
   arcseconds = parseFloat(arcseconds);
   return (arcminutes / 60.0 + arcseconds / 3600.0);

},

'parsePoint': function(str) {

   var values = str.split(/, /);
   var expr = /(\d+)(?:\D|(?:°))(\d+)(?:\D|(?:′))(\d+\.?\d*)(?:\D|(?:″)) ([NSEW])/;
   var lat = values[0].match(expr);
   var lng = values[1].match(expr);
   var latitude = parseFloat(lat[1]) + brianScript.arcDegrees(lat[2], lat[3]);
   var longitude = parseFloat(lng[1]) + brianScript.arcDegrees(lng[2], lng[3]);
   if (lat[4] == 'S') {
       latitude *= -1;
   }
   if (lng[4] == 'W') {
       longitude *= -1;
   }
   return new GLatLng(latitude, longitude, true);

},

'handleHttpResponse': function() {

   var request = brianScript._request;
   var map = brianScript._map;
   if (request.readyState == 4) {
       var doc = request.responseXML;
       var smwNS = "http://opensource.case.edu/projects/MediaWikiHacks/"
       var nodes = doc.documentElement.getElementsByTagName('node');
       var nodeMap = {};
       // Build a node map once so we don't have to iterate
       // it scanning for node IDs every time.
       for (var i = 0; i < nodes.length; i++) {
           var node = nodes[i];
           nodeMap[node.getAttribute('id')] = node;
       }
       // Build a relation map for every node.
       var relationMap = brianScript.buildRelationMap(doc, nodeMap, 'Located in');
       for (var i = 0; i < nodes.length; i++) {
           var node = nodes[i];
           if (node.hasAttributeNS(smwNS, 'Coordinates')) {
               var nodeID = node.getAttribute('id');
               var nodeType = node.getAttribute('type');
               var nodeTitle = node.getAttribute('title');
               var nodePoint = node.getAttributeNS(smwNS, 'Coordinates');
               var nodeURI = brianScript.makeNodeURI(node);
var html = '
'
               html += '<a href="' + nodeURI + '">' + nodeTitle + '</a>
'; html += 'Location: ' + nodePoint + '
'; var related = relationMap[nodeID]; related = related ? related : new Array(); if (related.length) { html += 'Located here:
';
html += '
    '; for (var j = 0; j < related.length; j++) { var relNode = related[j]; var relTitle = relNode.getAttribute('title'); var relURI = brianScript.makeNodeURI(relNode); html += '
  • <a href="' + relURI + '">' + relTitle + '</a>
  • ';
                       }
    
    html += '
';
               }

html += '
';
               var point = brianScript.parsePoint(nodePoint);
               var marker = createMarker(point, html);
               map.addOverlay(marker); 
           }
       }
   }

},

'makeNodeURI': function(node) {

   var uri = node.getAttribute('title').replace(/ /g, '_');
   if (node.getAttribute('type') == "category") {
       uri = "Category:" + uri;
   }
   return '/' + uri;

},


'buildRelationMap': function(doc, nodeMap, relation) {

   var relations = {};
   if (doc.evaluate) {
       var foundEdgesPattern = "/MediaWikiGraph/edge[@relation='" + relation + "']";
       var resultEdges = doc.evaluate(foundEdgesPattern, doc.documentElement, null,
                                      XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
       var thisEdge = resultEdges.iterateNext();
       while (thisEdge) {
           var fromID = thisEdge.getAttribute('from');
           var toID = thisEdge.getAttribute('to');
           var node = nodeMap[fromID];
           if (relations[toID]) {
               relations[toID].push(node);
           }
           else {
               relations[toID] = [node];
           }
           thisEdge = resultEdges.iterateNext();
       }
   }
   else {
       var edges = doc.documentElement.getElementsByTagName('edge');
       for (var i = 0; i < edges.length; i++) {
           var edge = edges[i];
           var edgeRel = edge.getAttribute('relation');
           if (edgeRel == relation) {
               var fromID = edge.getAttribute('from');
               var toID = edge.getAttribute('to');
               var node = nodeMap[fromID];
               if (relations[toID]) {
                   relations[toID].push(node);
               }
               else {
                   relations[toID] = [node];
               }
           }
       }
   }
   return relations;

},

'renderMap': function(n) {

   gmap_id = 'gmap_'+n;
   form_id = 'mapform_'+n;
   message_id = 'gmapmessage_'+n;
   document.getElementById(gmap_id).style.width = document.getElementById(form_id).width.value;
   document.getElementById(gmap_id).style.height = document.getElementById(form_id).height.value;
   var map = new GMap2(document.getElementById(gmap_id));
   map.addControl(new GSmallMapControl());
   map.setCenter(new GLatLng(document.getElementById(form_id).lat.value, document.getElementById(form_id).lon.value, true), parseInt(document.getElementById(form_id).zoom.value), G_NORMAL_MAP);
   if (document.getElementById(form_id).controls.value == 'yes') {
       map.addControl(new GMapTypeControl());
   }
   if (document.getElementById(form_id).type.value == 'G_SATELLITE_MAP') {
       map.setMapType(G_SATELLITE_MAP);
   }
   else if (document.getElementById(form_id).type.value == 'G_NORMAP_MAP') {
       map.setMapType(G_NORMAL_MAP);
   }
   else if (document.getElementById(form_id).type.value == 'G_HYBRID_MAP') {
       map.setMapType(G_HYBRID_MAP);
   }
   GEvent.addListener(map, "moveend", function() {
       var center = map.getCenter();
       var latLngStr = '(' + center.y + ', ' + center.x + ')';
       document.getElementById(message_id).innerHTML = latLngStr;
   });


   if (document.getElementById(form_id).rss) {
       //if the rss form element is defined, plot datapoints from an rss feed
       feedarray = document.getElementById(form_id).rss.value.split('|');
       for (var i = 0; i < feedarray.length; i++) {
           renderRSSFeed(map, feedarray[i]);
       }
   }
   else {
       var request = GXmlHttp.create();
       //the php script returns a very simple XML document
       request.open("GET", "/Special:GraphStructure/xml/locations", true);
       brianScript._map = map;
       brianScript._request = request;
       request.onreadystatechange = brianScript.handleHttpResponse;
       request.send(null);
   }

}

}

var Gmap_renderMap = brianScript.renderMap;

This page has been accessed 683 times.
This page was last modified 15:52, October 26, 2006 by Gregory Szorc.
About | Disclaimers