Creating a provider-agnostic online mapping application - Part 1

Posted : Sunday, 18 October 2009 22:56:15

Not so long ago I was tasked with writing a new online mapping application that would take a number of locations stored in a database and plot them onto a map. The project brief didn't mention which map provider would be used in production as that would be a business decision made closer to the end of the develoment cycle. In any event it would most likely be GoogleMaps so I began to build my first prototype of the application. The initial prototype was well received so I continued to develop the product and extend the initial functionality to fulfill the brief. The functionality of the application was duly signed off and I handed the project over to the design department for final amends and tweaks. Can you guess whats coming?

Yep sure enough, around the time the project was nearing final sign off, the decision was made and a contract with Microsoft was signed meaning that the mapping components of the application would be served using Bing(at that time known as VirtualEarth) as the provider. I had to rewrite the application to use a completely different API. Tsk! Shame on me - had I devoted more time/thought during the architecture phase of the project then the impending rewrite would have been far less arduous. The purpose of this post is to explain the basic archictecture I came up with to achieve a provider-agnostic mapping application. I will create a basic online mapping application called GeoTagger that will allow users to plot points on a map and add captions - these locations will be persisted to an online datastore. The application will also allow users to switch between providers and have their GeoTags replotted. Although a simple concept it is a reasonably extensive application so I will break it into chunks and cover the entire application over the next few posts. This first post will cover the basic javascript architecture.

Looking at the project logically we will need a core library of functions that will be required to make the application work, these will be present regardless of which provider is being used. There will also need to be a set of provider-specific functions that will implement a common interface for the core library to use. Another component that will be required is a map-manager object that can be used initialize and manage whatever map provider is currently in use as well as switch providers if required. The last piece of the puzzle is a principle application script object that will be used to manage all the other components. Given the wholly fantastic nature of jQuery I will be using it extensively for this sample application. For those who have yet to be converted, I suggest you go to the jQuery site to check it out - there are loads of examples to help you get started.

The first thing we need to get things going is a html page - I created a simple a page and added to it a div that will contain the map tiles, a couple of radio buttons to facilitate switching bewteen different map providers, some css code and a couple of script references. The html is pretty simple so I wont say anymore than that. Things start to get interesting when we look at the script so lets jump in. There are two script references, one is the jQuery library, the second contains most of the functionality of our application. In subsequent posts I will refactor this script and split it out into multiple files but for now we'll keep it in one file.

So I think the best place to start is the core function library that will be reponsible for all common map related functionality that does not involve any provider-specific script. For this first post there isn't a great deal to this object:

   48 /* MapObject constructor - mapDivId is id of html div */

   49 function MapObject(mapDivId) {

   50     this.MapDivId = mapDivId;

   51     this.MapDiv = $('#'+this.MapDivId);

   52 };

   53 /* MapObject.prototype - contains all common functionality  */

   54 MapObject.prototype = {

   55     DefaultZoomLevel: 4,

   56     DefaultLat: 53.800651,

   57     DefaultLon: -4.064941,

   58     addOverlay: function() {

   59         $('<div class="loadingOverlay"></div>')

   60         .css({

   61             top: 0,

   62             left: 0,

  • (This will not appear on the site)