Vishful thinking…

Using client side routing in web mapping applications

Posted in GIS, javascript by viswaug on February 7, 2012

Thought I would share how I have been using client side routing in a web mapping application that I have been working on for a little while now. The application is coming along nicely and I have been having quite a blast writing CoffeeScript for the app. If you haven’t looked into CoffeeScript yet, please consider doing so. I found it to be very very helpful.

But CoffeeScript is not the point of this post. There are a lot more resources out there on the web to help you pick up CoffeeScript. Client side routing is something that I have been doing with backbone.js. backbone.js is a neat little library that helps users build cleaner web apps by encouraging the MVC style development in web pages. backbone.js might seems a little intimidating at first but if you stick with it, you will find it very helpful. Although, I wouldn’t suggest using backbone.js for simple web pages. It is mainly targeted towards single page web apps where you are writing a lot of javascript and updating only some sections of the web page based on ajax requests.

Speaking of single page web apps, i think a lot of web based mapping apps fall in that bucket, especially since a lot of GIS users expect to see all their favorite ArcMAP functionality in their web apps also. That is a battle that I have been fighting for a while now and have a sneaky suspicion that there is a long way to go. Although, I should mention that I have been able to push a ‘workflow driven app’ over ‘map driven workflow’ a little bit further along than I have been able to do in my earlier projects. The feedback so far has not been too shabby either. As far as I can tell, no user has reported the ‘Map Toolbar’ missing 🙂

The client side routing techniques uses the hash tag to refresh sub sections of a web pages optionally thru AJAX and without the need for a full page postback. Ok, so, what does all this stuff have to do with web mapping apps? Well, I am leveraging the client side routing technique to allow users to select features on the map via the URL. Hopefully, the screenshots below will shed more light on it

The above screenshot shows the URL in the browser address bar reflecting the selected feature on the map. The URL in the address bar reads “…/StewardshipPlan/18701/Stands#/Stand/1904”. The initial “…/StewardshipPlan/18701/Stands” portion of the URL indicates the page that is currently loaded by the browser. The page contains the map that the user can interact with. The latter “#/Stand/1904” portion of the URL is the client side route and allows backbone.js to call our javascript that triggers the selection of the feature on the map. The selected feature on the map and the client side route of the URL in the address bar is synchronized. That is, the user can type in the URL in the address bar and the page will open up with the stated feature selected on the map, or the user can browse around the map and select other features by clicking them and the client side route will update to reflect the current feature selection. Here is another screenshot with another feature selected

That is a neat trick, but what does it buy me? Well, for starters, you can email around URLs for features to the people you are collaborating with and when they browse to the link, they will arrive at the specific feature itself on the map and with it’s attribute window open and ready for editing it needed. Also, not sure how useful this is, but if you want to go back to your previously selected feature, just click te browser back button. But as a developer, building my app this way helped me get rid of a lot of gluey jquery event binding to button click events and replace them with just links on the page which trigger the right javascript  via client side routing. Also, it almost forces me to write modular javascript which is very important for maintenance.

I have taken this line of thought a little further out and have enabled our split and merge functionalities to be routable too. Check the screenshots

The Merge and the split URLs perform the right feature selection and enable all the right map tools when the user navigates to the URL shown in the screenshots.

This is the first time I have used client side routing to build web mapping features like the ones described above. So far, i would say that it has worked out pretty good from a developer’s perspective. Any thoughts/suggestions about it is welcome and would be appreciated.

Advertisement

Moving away from the javascript module pattern

Posted in javascript by viswaug on March 2, 2011

A while ago I had written about using the javascript module pattern to organize code a little better. But off late, I have moved away from using the module pattern because of some reasons which i will outline below. But the pattern to use is really a matter of preference in my opinion. I have now gone back to basics and am using the javascript prototype pattern and have been loving it. Here is why i made the switch

  • the ‘this’ keyword in my class method means what I really expect/want it to mean
  • creating multiple instances of my class doesn’t consume more memory for creating more function instances since all instances use the functions on the prototype
  • the ‘instanceof’ operator can be used to determine if any object is an instance of the class

Here is a simple example illustrating how to create a class. The snippet below creates a class called ‘MyClass’ with the ‘getOption’, ‘calculatePay’, ‘getDisplayPay’ methods.

function MyClass(options) {//constructor
  this.options = options;
};

MyClass.prototype.getOption = function(name) {
  return this.options[name];
};

MyClass.prototype.calculatePay = function(hours) {
  return hours * this.options['hourlyRate'];
};

MyClass.prototype.getDisplayPay = function(hours) {
  return this.getOption('name') + " - " + this.calculatePay(hours);
};

To create an instance of the class above

var inst = new MyClass({‘name’ : ‘Jeff’, ‘hourlyRate’ : 1000});

Also, the following works too

inst.constructor === MyClass; //returns true

if( inst instanceof MyClass ) //evaluates to true

Pretty simple and sweet. Here are a couple of examples of classes written like above

g2kml

g2geojson

I am also using the standalone YUITest for unit testing javascript which doesn’t require the YUI framework which looks more attractive in YUI3. It was a very close call between YUITest and QUnit for the unit testing framework. I went with YUITest because it came with Selenium drivers

YUITest example for g2kml

YUITest example for g2geojson

Writing better javascript – Part 10

Posted in javascript by viswaug on November 29, 2008

Parasitic Inheritance

I had written about using the JavaScript module pattern to better organize and structure your code. If you like using the module pattern and are liking it enough to be writing complex code libraries with it, then you might want to explore and utilize OO inheritance in your classes. This can be achieved by using the parasitic inheritance pattern.

Let’s say that you have written a base class called ‘MapToolbarItem’ using the module pattern like below.

Base Class

var MapToolbarItem = function(toolbarItemID, options) {
    //Declare private variables here
    var _element;

//Declare private methods here
    var _enable = function() {
        //implement function here
    };

var _disable = function() {
        //implement function here
    };

return {
        //Declare public variables here
        element: _element,

//Declare public methods here
        enable: function() {
            _enable();
        },

disable: function() {
            _disable();
        }
    };
};

The class below illustrates how to create a ‘MapTool’ class that inherits from the ‘MapToolbarItem’ class using the parasitic inheritance pattern.

Inherited Class

var MapTool = function(toolID, options) {

//Declare a variable (called ‘that’ here) and assign an instance of the base class to it
    var that = new MapToolbarItem(toolID, options);

//Declare private variables here
    var _state;

//Declare private methods here
    var _select = function() {
        //Implement function here
        //Public variables of the base class can be used here
        that.enable();
    };

var _unselect = function() {
        //Implement function here
        //Public variables of the base class can be used here
        var el = that.element;
    };

//Declare public variables here
    //The public variables are created on the ‘that’ variable holding the base class instance
    that.state = _state;

//Declare public variables here
    //The public methods are created on the ‘that’ variable holding the base class instance
    that.select = function() {
    };

that.unselect = function() {
    };

//return the ‘that’ object
    return that;
};

The pattern is pretty simple enough where new public variables and methods are attached to an instance of the base class and then the instance of the base class is returned

Writing better javascript – Part 8

Posted in javascript by viswaug on November 21, 2008

JavaScript event model

This is another practice I have adopted in my JavaScript development to enable the components I create be able to raise custom events and have an event model that will support consumers to be able to use them as needed. That said, please do let me know if this event model can be improved upon in anyway possible. Always open to comments and suggestions…

In the code illustration below, I am adding the ‘click’, ‘select’, ‘unselect’, ‘enable’ and ‘disable’ event support to my MapTool JavaScript component. If you have been building mapping application then it should be evident why I would need those events on my map tools. I create a private listeners object where I store the listeners for every supported event as properties with the same name as that of the event. That makes it a little easier to retrieve the array of listeners for a certain named event. I also throw an error if the user tries to add a listener to an event that has not been pre-defined. This is obviously optional and be handled a couple of different ways. If the user tries to add a listener to an event that has not been pre-defined, the add listener call can just be ignored or a new event with that name can be added to the listeners object (but I don’t have such requirements in my applications so I throw an error). I also use the code snippet from John Resig (jQuery’s father) to be able to remove items from an array. That function can also be added to the array prototype if you are comfortable with messing the Array prototype.

var MapTool = function(toolID, options) {
    //private properties
    var _listeners = new Object(); //Create an object that hold the arrays of listeners as its properties
    //Predefine known events on the object – optional
    _listeners.click = new Array();
    _listeners.select = new Array();
    _listeners.unselect = new Array();
    _listeners.enable = new Array();
    _listeners.disable = new Array();

    //Adding John Resig’s array remove function
    _removeFromArray = function(array, from, to) {
        var rest = array.slice((to || from) + 1 || array.length);
        array.length = from < 0 ? array.length + from : from;
        return array.push.apply(array, rest);
    };
    //

    var _raiseEvent = function(eventName, e) {
        if (_listeners[eventName]) {
            for (var i = 0; i < _listeners[eventName].length; i++) {
                if (_listeners[eventName][i]) {
                    _listeners[eventName][i](e);
                }
            }
        }
    };

    var _clearListeners = function(eventName) {
        if (_listeners[eventName]) {
            _listeners[eventName] = new Array();
        }
    };

    return {
        createListener: function(eventName) {
            if (!_listeners[eventName]) {
                _listeners[eventName] = new Array();
            }
        },

        addListener: function(eventName, listener) {
            if(typeof(eventName) !== ‘string’ || typeof(listener) !== ‘function’) {
                if (!_listeners[eventName]) {
                    throw “The event ‘” + eventName + “‘ is not supported by MapTool.”;
                    //_listeners[eventName] = new Array(); – this is another option if you don’t want to throw an error if the user tries to add a listener for an unknown event
                }
                return { name: eventName, index: _listeners[eventName].push(listener) };
            }
            else {
                throw “Cannot add event listener. Invalid argument. A valid event name and listener function is required.”;
            }
        },

        removeListener: function(eventObj) {
            if (eventObj && eventObj.name && (eventObj.index || eventObj.index === 0)) {
                if (_listeners[eventObj.name]) {
                    _removeFromArray(_listeners[eventObj.index], index);
                }
            }
            else {
                throw “Cannot remove listener. Inavalid event listener object.”;
            }
        }
    };
};

 

The above event model has been working pretty good for me and the requirements in my applications.

Writing better javascript – Part 7

Posted in javascript by viswaug on November 21, 2008

The options argument

This practice is something that came to me after I ran into some flexibility issues with the JavaScript components I was creating. If you have been following this series, you might have noticed that I use the module pattern to create my JavaScript classes. As our JavaScript library started growing in size and the components I was creating was getting more complex, there was a need to be able to allow for ways to configure them wherever possible. Coming from the .NET universe, I started doing what I would have done if I was writing C# classes. I started modifying the constructor for the classes and started adding the different configurations points as arguments to the constructor like below.

var FormHelper = function(formID, cssClass, validationRules, submitHandler, cancelHandler/*constructor arguments defined here*/) {

    //Declare private variables here

    //Declare private methods here

    return {

    //Declare public properties here

    //Declare public methods here

};
};

The class just started off with ‘formID’ as the only argument. But as I started adding more extensibility points, I had started adding more arguments seen above like ‘cssClass’, ‘validationRules’, ‘submitHandler’ and ‘cancelHandler’ etc. These arguments started getting out of hand as I needed more extensibility points. And since JavaScript is JavaScript, I had to pass in the correct arguments in the exact index at which the argument is expected. Not a real good way of doing things. Thinking about it a little more and dwelling on it for a while I realized that the solutions was just to take an options argument that contains all the extensibility points as properties on it. See the changes below

var FormHelper = function(formID, options/*constructor arguments defined here*/) {

    //Declare private variables here

    //Declare private methods here

    return {

    //Declare public properties here

    //Declare public methods here

    };
};

var formOptions = {
    cssClass: “someClass”,
    validationRules: rules,
    submitHandler: handleSubmit,
    cancelHandler: handleCancel
};

var test = new FormHelper(“LatLongForm”, formOptions);

Doing it that was much cleaner. And didn’t have to change the definition of the constructor every time I wanted to add more extensibility points. Once I started writing my classes that way, I started noticing that the above pattern was used all the major JavaScript libraries. Probably should have seen the reason behind it earlier when I was using those libraries. But, now I know and am probably a better developer for it. But you don’t have to make that mistake and learn from my experience and follow this pattern from the get go.

Writing better javascript – Part 6

Posted in javascript by viswaug on November 19, 2008

 

One of the most commonly used debugging techniques when writing JavaScript is to use the ‘console.log(…)’ function available when using Firebug to print out useful information to help understand context and program flow. But the Firebug console object comes packed with a whole suite of other functions that can make your life even easier. The ones that I use most often are the ‘console.dir(object)’, ‘console.time(name) & console.timeEnd(name)’ and the ‘console.profile([title]) & console.profileEnd()’ functions.

console.dir(object) – Prints an interactive listing of all properties of the object. So, now you won’t have to find the code block and specify a breakpoint everytime you debug.

console.time(name) & console.timeEnd(name) – This pair of function starts and stops a named timer. So, this is invaluable in scenarios where you would like to have time estimates on processing heavy operations. I made heavy use of it when I was utilizing JavaScript templating in my applications. I was able to obtain the time taken for the processing the template and also for applying the template to an Object. I hope to be posting about the JavaScript templating techniques and their performance pretty soon in this series.

console.time(“Process template”);

var template = processTemplate(templ);

console.timeEnd(“Process template”);

console.time(“Apply template”);

var result = applyTemplate(template, data);

console.timeEnd(“Apply template”);

console.profile([title]) & console.profileEnd() – The profile view of the console tab in Firebug can sometimes be too overwhelming. In those cases, using this function pair will help narrow down your scope of search.

There are a bunch of other functions on the console object too and you should check it out. You never know when some of those functions could save your computer from having to listen to all those obscenties that you yell at it.

Writing better javascript – Part 5

Posted in javascript by viswaug on November 19, 2008

Use the module pattern to better organize your code.

Good JavaScript programming practices will help you debug and diagnose problems better. It will also keep you sane when the applications grow bigger and will be more maintainable. One of the things that I tend to do these days when I see any applications developed using the ESRI JS API, Google Maps API or the VirtualEarth API is to do a “View Page Source” on the we page. It is surprising to see many of those applications have a considerable amount of application logic on the web page itself as a series of javascript functions. I have been using the JavaScript module pattern to better organize my code and I find it satisfactory for most of my requirements. Obviously, that is not the only way to organize your code but I like it because it helps me think in terms of classes with private & public properties and methods.

Creating a class using the module pattern is pretty simple. The snippet below illustrates how to create a new class. It is only an illustration of the technique and doesn’t mean much.

var MapManager = function(/*constructor arguments defined here*/) {

    //Declare private variables here
    var _mapElement;

    //Declare private methods here
    var _addLayer = function(layer) {
        //private properties and methods CAN be accessed here
        //public properties and methods CANNOT be accessed here

        //add the layer here
    };

    return {

        //Declare public properties here
        element: _mapElement,
        data: new Object(),

        //Declare public methods here
        addLayer: function(layer) {
            //private properties and methods CAN be accessed here
            _addLayer(layer);
        }
    };
};

The class ‘MapManager’ defined above defines its private and public memebers. When an instance of the ‘MapManager’ class is created the instance returned can only be used to access and change its public properties and methods and not its private members.  The ‘new’ keyword can be used to create an instance of the ‘MapManger’ class like below.

var instance = new MapManager();

Just for a little insight into the technique, when you create an instance of the class, the object that is defined as a JSON literal after the ‘return’ keyword is the object that gets returned. And this returned object still has access to the private members in the class definition above because of the concept of closures in JavaScript.

This technique should be satisfactory for most simple design needs but most JavaScript frameworks offer their own technique to create classes, inherit from them and other advanced OO concepts. I hope to post at a later time on inheritance when using the module pattern.

Writing better javascript – Part 4

Posted in javascript by viswaug on November 19, 2008
JavaScript arrays are not associative.

I am not going to be writing about a JavaScript technique here but just about a JavaScript syntax which sometimes is not well understood. Arrays in JavaScript can be used a couple of ways like below.

var test = new Array();
test[0] = “Here is something”;
test[“name”] = “Here is another thing”;

As you can see, the array instance above is indexed using an integer and then a string. But an array by definition should only be indexed by an integer and not a string. So, how does JavaScript allow this? Well, JavaScript really doesn’t. Then how does the above piece of code work? Well, when you write something like “test[‘name’] = ‘Here is another thing'” what is really happening is that the value specified is not added to the list of items in the array but it gets stored in a property called ‘name’ on the array. The only reason the above syntax works is because an Array in JavaScript is also an Object. So, the value can also be retrieved by referencing ‘test.name’.

One last thing that I want to add to this post is how to iterate over all the properties of an Object.

var test = new Object();
test[“firstname”] = “Bill”;
test.lastname = “Gates”;
for(var item in test) {   
alert(test[item]);
}
//this should alert ‘Bill’ and ‘Gates’

This may not be news to everybody but it took me a while to realize this when i started writing JavaScript.

Writing better javascript – Part 3

Posted in javascript by viswaug on November 18, 2008

Writing AJAX applications involves a lot of scenarios where the data sent from the server to the browser needs to be inserted into the web page as appropriate HTML elements. When using JavaScript to dynamically inject contents into your HTML page, it is better to use the ‘innerHTML’ property of the DOM element and injecting all the contents as a string into the HTML page. This method even though seemingly ugly is faster than using DOM manipulation methods on the document object like ‘document.createElement(…)’ and ‘element.appendChild(…)’ etc to insert dynamic contents.

Check out the benchmarks on the performance benefits of using the ‘innerHTML’ property over the DOM manipulation methods here at QuirksMode. If you are a bigger stickler for performance and the gains from using ‘innerHTML’ doesn’t satisfy you, then you might consider using the ‘replaceHTML’ function below as per the suggestions posted here.

function replaceHtml(el, html) {
	var oldEl = typeof el === "string" ? document.getElementById(el) : el;
	/*@cc_on // Pure innerHTML is slightly faster in IE
		oldEl.innerHTML = html;
		return oldEl;
	@*/
	var newEl = oldEl.cloneNode(false);
	newEl.innerHTML = html;
	oldEl.parentNode.replaceChild(newEl, oldEl);
	/* Since we just removed the old element from the DOM, return a reference
	to the new element, which can be used to restore variable references. */
	return newEl;
};

Writing better javascript – Part 2

Posted in javascript by viswaug on November 18, 2008

If you find yourself writing code like below often enough

if(!test)
{
test = new Array();
}

then you might be able to delay the onset of carpal tunnel by using the syntax below.

test = test || new Array();

The ‘||’ can be used kind of like the null coalescing operator for JavaScript. The above syntax will come in real handy when you want to set some default values for optional arguments in JavaScript functions.

Update: watch out when using the above syntax for assigning default values for boolean and number argument types. Even though false and 0 are valid arguments, they will still evaluate to falsey and end up taking the default value.