Difference between revisions of "Google Maps"

From Organic Design wiki
(Filter form: add css version)
(Filter form: version 3 of filter form)
Line 105: Line 105:
 
A filter form option needs to be supplied so that, if enabled, a form is available that allows users to check or un-check options such as "Dog friendly" and the markers will be added/removed dynamically to match the query.
 
A filter form option needs to be supplied so that, if enabled, a form is available that allows users to check or un-check options such as "Dog friendly" and the markers will be added/removed dynamically to match the query.
  
[[File:Ajaxmap-filter-form.jpg]] [[File:Ajaxmaps-filter-form-css.jpg|right]]
+
{|
 +
|-
 +
|valign=top|[[File:Ajaxmap-filter-form.jpg]]
 +
|   
 +
|valign=top|[[File:Ajaxmaps-filter-form-css.jpg|right]]
 +
|   
 +
|[[File:Ajaxmap-filter-3.jpg]]
 +
|}
  
 
== Current TODO ==
 
== Current TODO ==

Revision as of 00:06, 18 February 2012

This was job which I did at the beginning of 2012 for Trail WIKI, I'm documenting it here because it involved many different interesting aspects and also included some useful information which will help with later jobs.

The wiki contains many pages which represent hiking trails. It uses an infobox template so that various information about each trail such as its distance, elevation and other attributes can be contained in a structured way in the article.

On the main page is a Google map which has markers for all the trails, and when one is clicked a popup is revealed containing a link to the associated trail article.

The client wanted to have this map functionality extended such that the infobox that pops up is customised to the style of the site and contains some of the key information from the trail article's infobox. Also he wanted to use the Semantic Maps extension so that he could have other maps throughout the wiki which shows only very specific sets of markers such as trails with a certain region or above a certain elevation.

Another issue is that the wiki will eventually contain thousands of trails, so the maps need to load the trail location data after the page has loaded, and the popup boxes in the markers need to load their content on-demand too.

Semantically annotating the infobox template

AjaxMap - Pages using coordinates property.jpg     AjaxMap - semantic markers.jpg

Retrieving the location data via AJAX

AjaxMap - ajax result.jpg


<js>$.ajax({

type: 'GET', url: mw.util.wikiScript(), data: { action: 'traillocations' }, dataType: 'json', success: function( data ) { for( i in data ) { var pos = i.split(','); var marker = new google.maps.Marker({ position: new google.maps.LatLng(pos[0], pos[1]), icon: icon, map: map, titles: data[i] }); google.maps.event.addListener( marker, 'click', function() { new InfoBox(this); }); } } });</js>


{{{1}}}

Creating a custom popup box using the overlay method

I started with this script from the exampled in the Google documentation.

AjaxMap - custom-overlay.jpg

Populating the popup box with data via AJAX

AjaxMap - multiple-results-one-location.jpg

{{{1}}}


AjaxMap - icons and data.jpg

Selecting markers with SMW queries

AjaxMaps - query.jpg

This was achieved by allowing a query parameter to be added to the #ajaxmap parser-function that contains a SMW #ask query (or in fact any other kind of query that produces a list of title links as a result such as DPL). These article titles are then extracted out of the resulting list and included in the ajaxmap_opt array defined in the JavaScript for that map. The JavaScript Ajax request then includes these titles in its query parameter when it asks for the location information.

This is not perfect because the list of titles should not have to be sent to and from the client, it would be better for the Ajax request to send just an identifier that the PHP can use to perform the #ask query then rather than performing it when the parser-function was first expanded.

Finishing up phase one

AjaxMap - final result.jpg

Marker clustering

A new requirement has been added to help speed up the rendering of the maps with many markers. The idea is to combine markers that are very close into a single cluster that works similarly to the markers that are in identical positions (due to multiple trails starting at the same location). The proximity is in terms of pixels though, not geographic distance, so the clustering depends on the scale.

A function would be added which transforms the location data (an list of geographic locations, each containing a list of trail titles) into a new list of the same format, but with the geographic locations merged if their current pixel distance is less than a certain amount. There should really be an additional array of pre-defined named-regions that could be made to apply above a given scale. The region title would be used in the title bar of the popup box instead of the first trail title.

This function to transform the data that the markers are based on would be called when the data is first collected, and again whenever the scale changes. The function needs to detect which markers are affected and create/delete them to match the new locations table. It would do this by creating the new data in a temporary table, then updating the markers by comparing the new transformed table with the last transformed table and then making the new table current.

Another useful addition would be to allow this transform to separate out the trails that start at identical locations into a circle so they can be seen separately at a small enough scale.

Before actually starting to write the clustering, lets check what's already been done ;-)

These clusterers don't really do quite what we want - they're grid-based for one thing. I think the best way would be to get the PHP to handle the clustering and cache the data (and may as well cache the query lists along with it). The cluster cache can be invalidated when new location data is saved, and the query data whenever any trail data is updated.

Filter form

A filter form option needs to be supplied so that, if enabled, a form is available that allows users to check or un-check options such as "Dog friendly" and the markers will be added/removed dynamically to match the query.

Ajaxmap-filter-form.jpg    
Ajaxmaps-filter-form-css.jpg
    Ajaxmap-filter-3.jpg

Current TODO

  • Allow multiple maps per page
  • Change the loading order to the following:
    • Load visible marker locations and create markers for them
    • Load invisible marker locations and create markers for them
    • Load all trail data as JSON not HTML
  • Change the popup routine to render HTML from the local trail data that was loaded as JSON rather than by doing an AJAX request for that trail info
  • Create the transform table method that adds/removes/updates markers to the current table, currently just with filtering not zoom-based combining

Later (maybe)

  • Store article lists from ask queries in DB so the lists aren't sent to and from the client
  • Store the icon paths in the JS so they're not sent to client
  • Image links can be made more effciient since they double-up the name and include a constant "140px"