Welcome to MSDN Blogs Sign in | Join | Help

Almost a year back, i had to write my first module using JQuery. Within days of using it, i fell in love with the library. And it wasn’t because of the numerous features that it offers but the lean and intuitive APIs  that it exposes. Till then i was just a regular C# developer and knew traditional JavaScript very well but did not enjoy programming in it. JQuery changed it. How you may ask. Well let me explain using a analogy:

As a C# developer, I was glad MS released Linq support in 3.0 version of the language. It brought  SQL query like syntax to C#. Filtering a collection of objects became far easier. You could do the same without Linq too but Linq queries appealed to your natural sense. With just few lines, you could implement fairly complex filtering and querying logic.

Now what Linq is to C#, JQuery is to JavaScript. JQuery isn’t a new language. Everything that you can do with JQuery, you can do that using traditional JavaScript too. But it brings the query like syntax to client side programming. The object collection it operates on is the entire DOM. The selector API of the library enables you to query the DOM objects using any of the CSS selectors. The API returns the collection of matching objects. You can use different APIs on this collection to further filter or perform a common function on the entire collection.

For further reading on JQuery, refer to the following msdn article.    

One of the popular design pattern documented by Gang of Four is the Chain of Responsibility pattern. The Chain of Responsibility pattern allows decoupling between objects by passing a request from one object to the next in a chain until the request is recognized. It is about avoiding coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

This post talks about my take on implementing Chain of Responsibility pattern in JavaScript. Here we take an example of a wizard where functionality for each tab in the wizard is handled by separate JavaScript objects which we call the tab objects and there is a single wizard object that receives the request and passes it to the object that takes care of the current tab functionality.

There is a single parent wizard page containing UI that defines the chrome of the wizard and the previous and next buttons. In an external JavaScript file, we write the code that handles the wizarding functionality. We define a single wizard object using constructor function:

var Wizard = function(arr) {

this.tabObjects = arr;

……………

}

The constructor function accepts an array of tab objects of the form:

var abc = {

name:'Step 1', scriptFile:'/jscripts/step1.js'

}

var mno = {

name:'Step 2', scriptFile:'/jscripts/step2.js'

}

var xyz = {

name:'Step 3', scriptFile:'/jscripts/step2.js'

}

var myWizard = new Wizard([ abc, mno, xyz]);

Each of these objects has two properties – ‘name’ which is the text to be shown on the tab and the ‘scriptfile’ which points to the location of the JavaScript file that implements the functionality for that tab.

The constructor function calls an init method that constructs a tab for each of the tab object and asynchronously downloads each script file of each tab.

Wizard.prototype.init = function() {

for (var i = 0; i < tabsObjects.length; i++) {

$.getScript(this. tabsObjects[i].scriptFile, (function(y, z) {

function makeClosure(a, b) {

return function() {

a.htmlLoaded = false;

$("#div" + b).load(a.htmlFileName, function() { a.init(); });

}

}

return makeClosure(y, z);

})(this.tabsObjects[i], i));

}

$('.nextButton').click(this.nextButtonClicked);

$('.prevButton').click(this.previousButtonClicked);

this.currentTabIndex = 0;

this.currentTabObj = this.tabsObjects[this.currentTabIndex];

}

‘currentTabIndex’ and ‘currentTabObject’ are additional properties on the Wizard object that hold the index and object of the current tab, respectively. Note we have use jquery here. $(“#div” + b) refers to the divs that we create for each tab. The variable b is the index for each tab.

In the script files of each tab, we further augment the corresponding tab object with additional properties and methods.

abc.htmlFileName = escape('/htmls/step1.htm');

abc.loadPageData = function(obj) {...}

abc.validatePageData = function(obj) { return true; }

abc.savePageData = function(obj) {...}

abc.init = function(obj){...}

Each file at minimum augments the corresponding tab object with a property htmlFileName which points to the file containing the html for that tab and four methods – loadPageData which is called when the tab is loaded, validatePageData which is called when user clicks next on the tab and if it returns true, savePageData is called. ‘init’ is called when the html file is downloaded and loaded into the wizard DOM.

The Wizard defines an empty object called:

var wizardGlobalObject = {};

This object is passed to each of the above methods as argument. This object is passed around from tab to tab and basically will hold all the information the user enter in the tabs. We can define the content of this object with the fields that we want to pass from tab to tab.

Now we define functions on wizard object that handles navigation:

Wizard.prototype.processCurrentTab = function() {

this.currentTabObj.loadPageData(wizardGlobalObject);

}

Wizard.prototype.nextButtonClicked = function() {

if {

(this.currentTabObj.validatePageData(wizardGlobalObject)) {

this.currentTabObj.savePageData(wizardGlobalObject);

this.currentTabIndex++;

this.currentTabObj = this.tabsObjects[this.currentTabIndex];

this.processCurrentTab();

}

}

Wizard.prototype.previousButtonClicked = function() {

this.currentTabIndex--;

this.currentTabObj = this.tabsObjects[this.currentTabIndex];

this.processCurrentTab();

}

‘processCurrentTab’ method calls the loadPageData of the current active tab. This method is called immediately after a tab becomes active i.e. the user lands on the tab. The method reads the content from the object and populates the fields of the tab accordingly. ‘nextButtonClicked’ is called when user clicks on the next button. The method calls validateData method passing in the wizard global object. The method checks whether data for all compulsory fields are entered for each tab. If validated successfully, the method returns true else false. If true, savePageData is called which stores the data entered in the global object. The current tab index is incremented and loaded. previoisButtonClicked is called when previous button clicked. It decrements the currentTabIndex and load previous tab. The final version of the constructor method looks like following:

var Wizard = function(objsArray) {

this.tabsObjects = objsArray;

this.currentTabObj = {};

this.currentTabIndex = -1;

this.init();

}

As user moves from one tab to next, the wizard object loads corresponding tab objects and passes on the processing to these objects. That is to say, the responsibility is chained from wizard objects to tab objects. In some manner, we even employed factory pattern too for getting the tab object for the current tab based on the tab index.

 

A disclaimer first: This post will make sense to you only if you have read and understood my post on lexical scoping in JavaScript .

 

And if you have read my post then i don’t have much to explain here.

Now, since JavaScript is lexically scoped, the following script is perfectly valid:

 

function localise(greeting) {

return function(name) { alert(greeting + ‘ ‘ + name };

}

var english = localise(‘Hello’);

var french = localise(‘Bonjour’);

english(‘kartik’);                                 // alert box with “Hello kartik”

french(‘kartik’)                                   // alert box with “Bonjour kartik”

 

Here, we have defined a parent function called localise which returns an anonymous inner function. This inner function remembers the variable greeting value even when at runtime the variable does not exist.

This is because when the inner function is defined, the greeting variable was part of the scope.

We say that the inner function is closed over the containing scope, or for short, that the inner function is a closure.

In other words, the result is that the procedure body is always evaluated in the context of the environment that was current when the procedure was created.

 

This is an extremely powerful functional language feature, but it is important to not misuse it. There are ways to cause memory-leak-like situations using closures. to know more about how closures can cause memory leaks, refer to a post by Eric Lippert at

http://blogs.msdn.com/ericlippert/archive/2003/09/17/53028.aspx.

I was planning to post a write up on closures in javascript but it made sense to first introduce you to concept of lexical scoping (or static scoping).

In JavaScript, functions have lexical scope. This means that functions create their environment (scope) when they are defined, not when they are executed.  With static scope, a variable always refers to its top-level environment. This is a property of the program text and unrelated to the runtime call stack. Because matching a variable to its binding only requires analysis of the program text, this type of scoping is called lexical scoping.

Consider the two examples given below:

Example 1:

function f1() {
    var a = 20;
    return function () { alert(a); }
}

var b = f1();
b();

Example 2:

function f1() {
    var a = 20;
    return f2
}

function f2() {
    alert(a);
}

var b = f1();
b();

 

In example 1 with the anonymous function, the command b() will generate a pop up with 20 whereas in example 2, you will get a has undefined.

This is because, when the anonymous function in example 1 was created, variable ‘a’ was present in the environment and hence, you get 20 as pop up. But in example 2, the in the function f2(), there isn’t a variable ‘a’ declared and assigned any value.

When a function is defined, it "remembers" its environment, its scope chain. This doesn't mean that the function also remembers every single variable that is in scope. Just the opposite—you can add, remove or update variables inside the scope of the function and the function will see the latest, up-to-date state of the variables. This behaviour gives JavaScript great flexibility—you can add and remove variables and add them again, and it's totally fine, because all it needs to know is how to access its scope and not what this scope used to contain at some point in time.

“Lexical scope” in general is the idea that

  • an identifier at a particular place in a program always refers to the same variable location — where “always” means “every time that the containing expression is executed”, and that
  • the variable location to which it refers can be determined by static examination of the source code context in which that identifier appears, without having to consider the flow of execution through the program as a whole.

I was talking to a friend of mine who had recently moved from years of developing windows application to a project which is a complete web app. 10 minutes into discussion and i could clearly comprehend his frustration.

He was full of complaints with development for web. No session management, primitive browser languages like HTML and JavaScript, no out of box support for security, protocol underneath with little stress on performance …. he went on for sometime.

Hmm… for a moment i thought he made some good points .. technically speaking, Internet still runs on pretty much primitive infrastructure. But then question is .. why is Internet so popular?

The primary reason for its popularity is its simplicity. The fact that it runs on a platform that is not state of the art makes it easy to learn and work with. Think about it!

The easiest part of creating a website is the actual creation itself. Its amazing a declarative language like HTML along with CSS with limited vocabulary can produce so colourful and structured document of information.

The product is best for human consumption. You don’t have to major in computer science to create one. 

Most website out there do not require session management or security. They are plain vanilla sites with motive to disseminate information. Performance is never key criteria for them. The ISPs can take care of that. Then why bother them with technical concepts of session, security and performance. Websites that need such features can get wise programmers to do that for them.

The standardized and plain simple HTTP protocol is also one reason why several easy to use browsers are available. Data exchange is seamless between heterogeneous system. Regardless of what time zone or country you are in, the Net never sleeps.

The dynamic nature of JavaScript makes it fascinating. The fact that function can be created as well as modified at runtime is one of the amazing stuff you can do in JavaScript unlike in static languages like Java and C#.

Consider an example of function rewriting at runtime below:

function temp() {

alert('first time only');

temp = function () {

       alert('rest of the time');

}

}

temp();

temp();

temp();

temp();

The first call to temp() will generate a pop up with message ‘first time only’ and all subsequent will generate pop up with message ‘rest of the time’.

Function rewriting can be used intelligently to boost performance of your JavaScript code. Often in your code you have one off statements to execute or conditions that evaluate to same value every time.

Like the one below which returns an DOM object using document.all if it is IE else document.getElementById()

function GetDOMObject(id) {

if (isIE()) {

        return document.all[id]

}

else {

       return document.getElementById(id);

}

}

The function isIE() returns true if the browser is IE else returns false.

Now as browser features don’t change as you interact with a web page, the ‘if.. else’ condition seems an overhead whenever call to GetDOMObject is made. With some smart rewriting the function can be modified to:

function GetDOMObject(id) {

if (isIE()) {

         GetDOMObject = function (id) { return document.all[id]; }

         return document.all[id];

}

else {

        GetDOMObject = function (id) { return document.getElementById(id); }

        return document.getElementById(id);

}

}

When the method is access for the first time, the isIE() method is called to determine the type of the browser. Depending on the value return, the function GetDOMObject is rewritten to eliminate the if .. else conditions. So if the browser is IE, the function GetDOMObject() is modified to : function GetDOMObject(id) { return document.all[id]; }

The function GetDOMObject() can further be modified to reduce a line or two:

function GetDOMObject(id) {

if (isIE()) {

      return  (GetDOMObject = function (id) { return document.all[id]; } )()        

}

else {

      return ( GetDOMObject = function (id) { return document.getElementById(id); } )();

}

}

The trailing parenthesis to the assignment statement execute the modified GetDOMObject() function there itself.

However, though function rewriting is a smart way to speed up your JavaScript code, the performance improvement may not be significant unless your website is JavaScript intensive. 

 
Page view tracker