Makers.xslt
Before we render the markers on a map we need a datasource, just plain xml.
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxml="urn:schemas-microsoft-com:xslt" xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets "> <xsl:output method="xml" omit-xml-declaration="yes"/> <xsl:param name="currentPage"/> <xsl:template match="/"> <!-- change the mimetype for the current page to xml --> <xsl:value-of select="umbraco.library:ChangeContentType('text/xml')"/> <xsl:text disable-output-escaping="yes"><?xml version="1.0" encoding="UTF-8"?></xsl:text> <markers> <xsl:apply-templates select="$currentPage/ancestor-or-self::root//node [@nodeTypeAlias='Organisatie' and (data[@alias='longitude'] != '') and (data[@alias='lattitude'] != '')]"> </xsl:apply-templates> </markers> </xsl:template> <xsl:template match="node"> <marker> <xsl:variable name="lattitude"> <xsl:choose> <xsl:when test="number(substring-before(./data[@alias='lattitude'], '.')) > 10"> <xsl:value-of select="./data[@alias='lattitude']"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="./data[@alias='longitude']"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="longitude"> <xsl:choose> <xsl:when test="number(substring-before(./data[@alias='longitude'], '.')) < 10"> <xsl:value-of select="./data[@alias='longitude']"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="./data[@alias='lattitude']"/> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:attribute name="name"><xsl:value-of select="./data[@alias='naam']"/></xsl:attribute> <xsl:attribute name="adres"><xsl:value-of select="./data[@alias='straatHuisnummer']"/></xsl:attribute> <xsl:attribute name="zip"><xsl:value-of select="./data[@alias='postcode']"/></xsl:attribute> <xsl:attribute name="url"><xsl:value-of select="umbraco.library:NiceUrl(./@id)"/></xsl:attribute> <xsl:attribute name="lat"><xsl:value-of select="$lattitude"/></xsl:attribute> <xsl:attribute name="lang"><xsl:value-of select="$longitude"/></xsl:attribute> </marker> </xsl:template> </xsl:stylesheet>
Using umbraco, we render the xml using some fields:
Markers.xml
This will render an xml document like this:
<?xml version="1.0" encoding="UTF-8"?> <markers> <marker name="Bibliotheek, Banne Buiksloot" adres="Ankerplaats 18 (winkelcentrum)" zip="1034 KC Amsterdam" url="/organisaties/bibliotheek,-banne-buiksloot.aspx" lat="52.407393" lang="4.917412" /> <marker name="Bibliotheek, Betondorp" adres="Brink 45" zip="1097 TV Amsterdam " url="/organisaties/bibliotheek,-betondorp.aspx" lat="52.340157" lang="4.94315" /> <marker name="Bibliotheek, Bijlmermeer " adres="Bijlmerplein 93 (Amsterdamse Poort) " zip="1102 DA Amsterdam " url="/organisaties/bibliotheek,-bijlmermeer-.aspx" lat="52.31409" lang="4.951436" /> <marker name="Bibliotheek, Bos en Lommer " adres="Bos en Lommerplein 176" zip="1055 EK Amsterdam" url="/organisaties/bibliotheek,-bos-en-lommer-.aspx" lat="52.378402" lang="4.845014" /> </markers>
Template
Now we have to make some template with corresponding javascripts to get the markers from the xml en render them on the map, using an additional script for handling a large amount of markers.
Fun!!!
Well,this is where the fun begins, speaking in Umbraco terms;-)
- We’ll need to define the map
- get the markers
- create the boundaries
- and cluster the markers.
Define some variables and define the map
var map; var lastWindow; var bounds; var icon; var fluster; var latlng; $(document).ready(function(){ latlng = new google.maps.LatLng(52.37832379564726, 4.891319274902344); bounds = new google.maps.LatLngBounds(); var myOptions = { zoom:9, center: latlng, mapTypeControl: true, mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU}, navigationControl: true, navigationControlOptions: {style: google.maps.NavigationControlStyle.SMALL}, mapTypeId: google.maps.MapTypeId.ROADMAP }; map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); fluster = new Fluster2(map); });
Get markers with AJAX request using jquery.ajax, define the boundaries and ad markers to the fluster collection.
$('#map_canvas').ready(function(){ $.ajax({ type: "GET", url: "organisatiesxml.aspx", dataType: "xml", success: function(xml){ $(xml).find('marker').each(function(){ // Retrieve all needed values from XML var title = $(this).attr('name'); var adres = $(this).attr('adres'); var zip = $(this).attr('zip'); var url= $(this).attr('url'); var latitude = $(this).attr('lat'); var longitude = $(this).attr('lang'); var htmlString = "<strong>" + title + "</strong> " + adres + " " + zip + " " + "<a>Bekijk organisatie</a>"; // create a marker var myLatlng = new google.maps.LatLng(latitude,longitude); bounds.extend(myLatlng); var marker = new google.maps.Marker( { position: myLatlng, map: map, title: title, icon: icon }); fluster.addMarker(marker); addInfoWindow(marker, map, htmlString); });// end each } }); // end $.ajax map.fitBounds(bounds); // Set styles // These are the same styles as default, assignment is only for demonstration ... fluster.styles = { // This style will be used for clusters with more than 0 markers 0: { image: 'http://gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/images/m1.png', textColor: '#FFFFFF', width: 53, height: 52 }, // This style will be used for clusters with more than 10 markers 10: { image: 'http://gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/images/m2.png', textColor: '#FFFFFF', width: 56, height: 55 }, 20: { image: 'http://gmaps-utility-library.googlecode.com/svn/trunk/markerclusterer/1.0/images/m3.png', textColor: '#FFFFFF', width: 66, height: 65 } }; // Initialize Fluster // This will set event handlers on the map and calculate clusters the first time. fluster.initialize(); });// end function function addInfoWindow(marker, map, message){ /* set balloon */ var infowindow = new google.maps.InfoWindow( { content: message }); /* add listener to marker */ google.maps.event.addListener(marker, 'click' ,function(){ infowindow.open(map,marker); if(lastWindow) { lastWindow.close(); lastWindow = null; } lastWindow = infowindow; }); };/* end function */
Additional function for the tooltip window
function addMarkerBubble(marker, map, message){ // set balloon var infowindow = new google.maps.InfoWindow( { content: message, size: new google.maps.Size(400,200) }); // add listener to marker google.maps.event.addListener(marker, 'click' ,function(){ infowindow.open(map,marker); }); if(lastWindow) { lastWindow.close(); lastWindow = null; } lastWindow = infowindow; };
final result
These functions will generate a map like:
Clicking a cluster will zoom in on the map.