Enhancing scalability & maintainability of your JavaScript/jQuery code – JS Design patterns

Are you building a huge, jQuery-ASP.NET web application, which is subjected to a lot of global code changes in your client script? If yes, you should probably consider the below design pattern, which would help you have a better control on code execution.

Maintainability problem with large chunks of JavaScript code :

Imagine a web application having ~400 .js files. Each .js file would have code for AJAX calls/DOM manipulations for the respective .aspx page. But there would be some code which is redundant and can be moved to a common global function, which can be accessed by all .js files. With respect to ASP.NET paradigm, this can be compared to - your code behind partial class inheriting a base class. So whenever you have a global change, you can just change the base class and all .aspx files will have the changes.

However, there is a huge difference in the above comparison. ASP.NET has a powerful page life cycle which strictly defines which piece of code should be executed at what event. i.e., Pre Init, Init, Page Load, Pre Render etc. In the case of JavaScript, it is just dependent on ‘where you place your code’. i.e., even if you call a global function on line 1, developers can always add lines above and below it, which will mess up your code execution sequence.  This pattern is an attempt to have control on JS code execution, having Pre and Post events.

Solution- Using wrapper which can provide pre/post events:

Let’s say for every page, we need to prevent post back on click of any button. i.e., writing “e.preventDefault()” on button click events. I call this as a “Pre Event”, since this is to be executed before any click events are written.

Similarly, let’s say, for every page, we need to disable/show/hide certain controls, based on few conditions. I call this as a “Post Event”, since this code has to be executed at the end (similar to pre render event of asp.net model). So here is how we can try to enforce this.

Enhancing our chainable JavaScript library:

The following description is based on my previous article, building a chainable JavaScript library. For the global “Pre” and “Post” events, I’m going to extend the chainable JavaScript library with the “execute” method, like this:

(function(){
    var value='Hello world';
    var preInit=function(){
        console.log('pre Init');
    }   
    var preRender=function(){
        console.log('pre Render');
    }
    var mySpace=function(){
        return new PrivateSpace();
    }
    var PrivateSpace=function(){
 
    };    
    PrivateSpace.prototype={
        init:function(){
            console.log('init this:', this);
            return this;
        },
        ajax:function(){
            console.log('make ajax calls here');
            return this;
        },
        cache:function(){
            console.log('cache selectors here');
            return this;
        },
        setValue: function(newValue){
            value=newValue;
            return this;    
        },
        getValue: function(callbackFunc){
            callbackFunc.call(this,value);
            return this;    
        },
        execute:function(oldClass){
            preInit();
            var obj=new oldClass();
            obj.init.call(this);
            preRender();
        }
    }
    window.my$=mySpace();
})(); 

To explain the execute method, let’s consider the below code:

var CommonSearch=function(){
    var pageLoad=function(){
        console.log("page load operations here...");
    }
    return{
        init: pageLoad
    }
}

The above code is what resides in your ‘.js’ file. It is written in revealing module pattern. Here, CommonSearch is a constructor function and to execute it, we should say:

$(document).ready(function(){
    var objCommonSearch=new CommonSearch();
    objCommonSearch.init();
});

This does not have “Pre” and “Post” events. So if we need some global changes, we are lost! We have to manually change all 400 “.js” files. To troubleshoot this problem, if we use our my$.execute method, we can say:

$(document).ready(function(){
    my$.execute(CommonSearch);
});

Note that in the above snippet, we are not creating instance of CommonSearch constructor function. Instead, we are passing it to my$.execute, which internally calls the private “PreInit()” method first, then executes “init()” of  CommonSearch, and calls the private “preRender()” method. So, we are enforcing a particular sequence of code execution, which solves our problem.

[Note: As far as I know, 100% enforcement is impossible in JavaScript. If you are a JS Ninja, you can easily bypass whatever enforcement is set. That is the beauty of the language!!]

How this is different from using a common global function in document.ready, which can do the same functionality as my$.execute? Simple…we have good name spacing and chainability in our my$ function, which prevents conflicts with other modules.

If you are a JavaScript newbie, this article might sound a bit weird., but actually it is not so. I’m no JS guru to say this is the best approach. But this approach helped me a lot in scaling up easily and maintaining huge .js files, without any issues. If you can think of a better approach, please suggest. I’m waiting to learn..

Happy coding Smile

jQuery event delegation - Adding/removing markup dynamically

First of all, my Happy New Year wishes to all netizens! As you journey through 2010, leave a trail of hardwork, innovation, passion and excellence...

Coming to the topic, in web apps, most of the times, we would require adding and removing controls to a web page dynamically. E.g.,adding "Browse" buttons for email attachments(live mail, gmail etc). In a traditional ASP.NET app, we used to build a string containing markup and append it to some control. However, this requires postback. Here is the end result which we would want to achieve:

With the help of jQuery, we can achieve this functionality with ease. Let us see the various ways of implementing this functionality.

1. Using jQuery “clone(true)” function:

Many of us know about jQuery clone() function, which will clone any jQuery selector. But the hidden feature is, it accepts a boolean parameter. When the param is set to true, it will clone DOM elements along with their event handlers.

Though this method can help us achieve the end result, the disadvantage is, it will fail to initialize complex controls like date pickers, auto suggest textboxes etc.

2. Using jQuery “live” event:

jQuery live looks like a perfect choice for this requirement. Live events are added for current as well as future elements in the DOM and hence events for “+”, “-“ buttons can be written only once using Live.

Though this works as expected in simple screens, even this is not a perfect approach! If suppose you are loading pages via AJAX, the events would be bound multiple times. So clicking on “+” will add more than 1 row, as multiple click events are bound. This is because, Live adds events to the document and not to the element. Check this article to see how live works.

3. Using jQuery Event Delegation:

Yup! This will solve the problems caused by above methods. I don’t want to explain about event delegation as there are very good articles already available. Check these:

The concept is very simple. Suppose you have a html table with 100 cells and you need to fire an event when any cell is clicked, instead of writing the below code:

$('#myTable TD').click(function(){
    $(this).css('background', 'blue');
});

you can write code like this:

$('#myTable').click(function(e) {
    var clickedElement = $(e.target);
    clickedElement.css('background', 'blue');
});

So instead of binding 100 events as in case 1, you can achieve the same output by binding only a single event, as in case 2.

This will solve the problem of Live, as the events are not added at document level, but are added to parent container. This will also solve the problem of Clone as date pickers will be initialized properly.

DEMO: Here is a demo for the above functionality using LIVE (Use it only when you are not loading pages via AJAX). I shall very soon come up with a demo using event delegation. This is a real time problem which I faced in a large scale project. So wanted to share immediately, so that others might not fall in the traps in which I fell!

Happy Coding :)

Love JavaScript design patterns, love your jQuery code even more!

The goal of this article is to educate budding jQuery developers (who do not have much exposure to JavaScript), to write clean, readable, maintainable code. This is in fact, a pointer to articles written by several JavaScript gurus.

For a jQuery developer, who does not have good expertise of JavaScript object oriented programming concepts, the entire code of a JavaScript file would reside in the "$(document).ready()” function. This includes various events, ajax calls, their call backs, UI effects etc.

In the case of a large scale business application (having hundreds of JavaScript files, each file having few thousands of lines), this would mean a lot of effort during reviews, white box testing and especially maintenance. Therefore, apart from learning the library, knowledge of good practices of core JavaScript language is a must.

Here is a collection of some of the best links, which would change the way you code. Read them in this sequence :)

1. JavaScript Best Practices by Christian Heilmannhttp://dev.opera.com/articles/view/javascript-best-practices/

2. Show love to the object literal - http://www.wait-till-i.com/2006/02/16/show-love-to-the-object-literal/

3. Closures and lexical scoping in JavaScript - http://mark-story.com/posts/view/picking-up-javascript-closures-and-lexical-scoping

4. Private Members in JavaScript by Douglas Crockford - http://www.crockford.com/javascript/private.html

5. JavaScript programming patterns - http://www.klauskomenda.com/code/javascript-programming-patterns 

6. Five things to do to a script before handing it over to the next developer - http://www.wait-till-i.com/2008/02/07/five-things-to-do-to-a-script-before-handing-it-over-to-the-next-developer/

Out of all the JavaScript design patterns in link #5, these are quite popular:

 a. Singleton pattern [Thanks to HB Stone for explaining the concept in simpler terms]

 b. Module pattern [Thanks to Christian Heilmann for the contribution]

 c. Revealing module pattern [An updation to module pattern by Christian Heilmann]

I have tried these and like many others, I fell in love with the Revealing module pattern. The core of these patterns is the concept of closures. So make sure you are good at the basics!

Before trying out patterns, my jQuery code was like this:

$(document).ready(function() {
   //page load ajax call 
    $.ajax({
        type: "POST",
        url: "CTypesHandler.ashx",
        data:"{}",
        success: callBackFunction,
        error: function(){}
    });
 
    //ajax success callback function
    callBackFunction(response)
    {
        //process ajax response here...
    }
    
    //form validation code
    $('#FormId').validate(){
        //code for validation
    }
    
    //click events
    $('#submitButton').click(function(){
      //code for submit click event
    });
    
    $('#saveButton').click(function(){
      //code for save click event
    });
});

After trying out Revealing Module pattern, my jQuery code is very clean like this:

var mySamplePage=function(){
    var counter=0;
    
    var callBackFunction = function(response)
    {
        //process ajax response here...
    };
    
    var pageLoadAjaxCalls=function(){
        $.ajax({
            type: "POST",
            url: "CTypesHandler.ashx",
            data:"{}",
            success: callBackFunction,
            error: function(){}
        });
    };
    
    var bindEvents=function(){
        $('#submitButton').click(function(){
          //code for submit click event
            counter++;
        });
        
        $('#saveButton').click(function(){
          //code for save click event
        });
    };
    
    var validate=function(){
      $('#FormId').validate(){
          //code for validation
      };
    };
    
    var pageLoadOperations=function(){
        validate();
        pageLoadAjaxCalls();
        bindEvents();
    };
    
    return{
        init:pageLoadOperations
    };   
}
 
$(document).ready(function(){
    vare page= new mySamplePage();
    page.init();
});

To explain the differences in short, the first snippet has all code in document.ready function. This means, all variables, functions used are global. There is no modularization in the code. So if new events, UI logic are to be added, they add up to the mess.

In the case of patterns snippet, the code is clearly modularized. There are no global variables/functions. All members, functions are private. Only certain methods are exposed(by adding pointer in return statement). If new code has to be added in future, it can be added to the respective functions (like pageLoadAjaxCalls, bindEvents etc). Our document.ready is now very clean, and has control on what to be done, with ease.

Using good jQuery selectors gives optimized code; Using JavaScript design patterns gives clean and maintainable code. Happy coding :)