NovoGeek.com - Krishna's weblog

A technical blog on jQuery, AJAX, JavaScript & modern web technologies

In my previous article, I have discussed about few scenarios where AJAX can be an overkill for our web apps. I would like to add few more such scenarios in this post.

(4) Heavy dropdowns: 

A dropdown control enforces the user to select a value, preventing the entry of unwanted choices. This would make sense if a dropdown has limited options. But we tend to populate the dropdown with hundreds/thousands of options (probably this is the case with list of all cities in a country).

The scenario gets worse when we make an AJAX call to fill such huge dropdowns. There are many articles which show 'how to fill a dropdown using AJAX', but none of them stress on the limit of options. So, for a dropdown with 3000 options you are adding 3000 DOM elements, thereby degrading the performance of your page. Imagine 5 such dropdowns in a page!

Another scenario could be a row having a dropdown with 300 options, which repeats for ‘n’ times! These are unseen dangers which slow down your site.

Bottom line: Use dropdowns when you want to display limited(say ~50) elements. For anything more than this, use auto complete feature(You may choose between local/remote data based on number of records). The same rule holds good for cascading dropdowns. Keep your DOM as small as possible!

(5) Accordions: 

This is another beautiful UI technique almost similar to Tabs, the main difference being-tabs appear horizontally whereas accordions appear vertically. The problems faced in accordions are exactly the same ones which I have explained for tabs (please refer to my previous article).

Bottom line: If your page is too huge, do not fetch the entire DOM for building an accordion. On page load, build accordion structure and fetch the content of first pane only. On clicking the next header, remove markup from the previous pane and populate the current pane. This way, your page will always contain limited number of elements(though huge DOM manipulations can cause a little delay).

(6) Page load AJAX Calls/Multiple domains:

If you profile most of the web apps, they make a number of AJAX calls on page load for business functionality. e.g., If you are trying to fill 5 dropdowns on page load using AJAX calls, you are inviting performance problems.In most cases, we can get rid of such calls by injecting JavaScript objects into the page

Bottom line: If AJAX calls on page load are still unavoidable, instead of making multiple calls, make only a single call. In your web method, hit multiple controllers and fetch the desired response and club the responses using .NET’s Dictionary object. This way, you will reduce some network traffic.

You may also try to move some of your web services to different domains and access the data through JSONP.  The maximum number of parallel calls per domain in IE8/FF3 are 6. This means, by chance if you are making more than 6 AJAX calls, the remaining would be queued. By splitting your services across multiple domains, you can still make more than 6 calls in parallel!

On a closing note, I think I’m writing more of theoretical aspects without any code, but I don’t want to lose these experiences in the darkness of my memories. Following these simple guidelines helped me solve many performance bottlenecks in a large scale project. I feel this would be useful for developers at all levels while taking design decisions. Do let me know your views!

Follow me on twitter for live updates. Happy coding :)


AJAX libraries have simplified developer’s life by providing clean & easy-to-use API. Their usage is so simple that we developers over use it, without realizing the performance impacts. In this article, I would like to explain few scenarios in which AJAX can be an overkill for your web apps.

The motto is to help fellow developers take better design decisions at an early stage, rather than repenting and fine tuning later. Below are real time problems, faced in a large scale ASP.NET/jQuery AJAX based web app, which should be given a serious thought:

(1) AJAX based navigation: 

“Keep DOM manipulations to the minimum” is what every JavaScript library says, but over use of AJAX based navigation defeats this purpose and you may rethink the design, unless your client specifically wants it.

If you are wondering what AJAX based navigation means, check jqGrid demos site. There are no post backs at all even while navigation. Content pages are fetched via AJAX and injected into a parent page, with a huge DOM manipulation.

If the page is small with very less number of DOM elements, AJAX navigation is fine. As the number of elements increase in the page, injecting the page takes longer time and beyond a point, causes ‘stop running script’ error, as discussed in my previous article. Typically, business applications contain hundreds of controls in a page, causing severe performance bottlenecks.

If you see Facebook, the Home, Profile, Account etc links on the top do a full post back and fetch the page, while any other operation is an AJAX call, which is a cooler approach.

Bottom line: AJAX navigation has performance problems when pages are huge. But it can solve problems like maintaining state by storing data in DOM elements, reducing session variables and reducing load on the server. So weigh these choices before taking a call.

You may find the total number of elements in the page using the jQuery code, $(‘*’).length; So be cautious of this count while injecting a page. In a complex page like Yahoo.com, there are about 780 elements (each html tag corresponds to one element). Make sure your page is having not more than 1000 DOM elements. If the count is running into thousands, then split your pages.

(2) Client side templating:

If you liked asp.net repeater and are looking for client side templating, hold on! There is a difference between asp.net repeater and client side templates.

In the case of a repeater, processing takes place on the server and not much load is on the browser. However, in the case of templates, processing as well as injection is on the client. Imagine templating 100 rows, with each row containing 30 elements. You end up having 3000 elements which is alarming!

I can give you the example of twitter.com or facebook.com. Both have a ‘more’ sort of button at the bottom, which fetch more records. What happens if you want to see the posts of last ten days? You end up with thousands of DOM elements and your browser slows down.

Bottom line: In terms of performance, what is apparent to the developer is only the time taken to process the template. But what is hidden is, the time taken for clearing events, handling memory leaks, cleaning missing tags and injecting the template. All this happens in jQuery’s .html() method.

So, if you want to template huge data, make sure you are implementing pagination. Again, as in the above case, $(‘*’).length is the key.

(3) Tabs:

Thanks to this fancy UI technique, which gives a wizard sort of appearance to the content. If you are looking only at the fundo part of it, you are getting into problems! The scenario gets worst when you have AJAX tabs which fetch huge pages.

Let’s say each page has ~700 elements. So if you have 5 tabs, you are having ~3500 elements. Imagine having blur, click, live events for so many elements. It’s a complete mess! Also, you will be running into context related issues, since 2 tabs can have 2 different controls with the same ID. When you are on an active tab, the content of the rest of the tabs is only hidden, but not removed. So your app’s performance is bad yet again.

Bottom line: If you want to use tabs with optimal performance, make sure you are clearing the mark up of the tabs which are not active. At any point of time, make sure your $(‘*’).length is always less than 1000, for better results.

I think I have covered quite a lot. I’m still facing several bottlenecks in my beautiful project and trying to figure out the solutions with my architect. Will cover more scenarios in my next article.

Happy coding :)


Before starting with the article, I would like to share something which encouraged me a lot. Now I'm a Microsoft Most Valuable Professional (MVP) for ASP.NET. Thanks to Microsoft folks for recognizing my efforts. :)

 

Coming to the point., have you ever faced the below “Stop running script” error message in your thick client web apps? This is one of the most frustrating errors, which hangs the browser, spikes CPU usage and slows down your operations.

 

 

Nicholas C. Zakas has an excellent article on why it occurs in various browsers. In short, his research says that the error occurs in various browsers due to exceedingly high number of operations taking place(~5 million statements in IE), or due to script executing for a very long time(~10 secs in FF).

For best performance, Nich says that no script should take longer than 100 ms to execute on any browser, at any point of time.

 

Now, why should jQuery developers worry about this?

They should, because jQuery is made of nothing but JavaScript and chances of getting this error are more, if you don't understand the core methods properly. Let's see in detail what this means.

 

Take the below script as example. Execute in Firebug console or in IE8 script panel or simply copy/paste in a html file and open it.

(function exec(){ 
    var str=''; 
    for(i=0;i<10000;i++) 
    { 
        str+='<div>test div '+i+'</div>'; 
    } 
    $('body').append('<div id="TestDiv"></div>');
    $('#TestDiv').html(str); 
})();

Note: The above code might crash your browser. So please try in stand alone instance. If you are not getting the error or experiencing different behaviour, probably you have better CPU which does not spike up to 100% for this code. The point here is about wrong usage of code. So increasing the max condition should give the error. This analysis is as per jQuery version: 1.3.2.

 

What I'm doing here is pretty straight forward. Just looping and creating 10000 elements and injecting them into the DOM. Now, what's so important here?

It's just a simple piece of code. 10000 operations in a loop is way beyond the threshold of 5 million operations. When you run this code for the first time, browser stops responding and when you run this for the second time, you get the 'stop running script' error.

 

This might sound silly at a first glance. Such huge loops will obviously cause such errors. But what if you are doing this in your code without your knowledge? Do you know that this error occurs in several facebook apps & in twitter? There is something beyond the loop.

 

$().html vs element.innerHTML:

Replace the line:

$('#TestDiv').html(str);

with this one:

$('#TestDiv')[0].innerHTML=str;

and now try. We are using native JavaScript's innerHTML to inject DOM elements. This is faster than jQuery's .html() and hence no error.

 

Does this mean this is the mistake of jQuery?? No! It's purely developer’s ignorance. First of all, such huge DOM manipulations should not be made (This is commonly used, unknowingly.). Then, you should be aware of what .html() does.

 

$(‘selector’).html() internally removes event handlers attached to every child element in the selector’s DOM tree , cleans up the incoming mark up by adding unclosed tags and then injects the new mark up. So for the first time, since no DOM elements were there, .html() only cleans the new mark up and injects it. For the second time, it has the additional task of removing the event handlers and hence the number of operations are increased, giving the error.

 

So when should I use .innerHTML and when should I use .html()?

Genuine doubt! Use .innerHTML if you are SURE that you have to JUST replace the mark up, provided your mark up does not contain any events attached to it. Use jQuery’s .html() when you want to unbind events attached to elements and take care of garbage collection/memory leaks. (You may refer to “jQuery cookbook” for more info on this).

 

This is not the only pitfall. JavaScript’s native for(;;) loop is faster than jQuery's $.each() loop. So before enjoying the benefits of the library, analyze the bottle necks too.

 

(Q) When does such scenarios arise? Why would someone loop some 10000 times in their code?

(A) Though practically no developer loops ten thousand times in his code, knowing that it’s a performance issue, people tend to make this mistake unknowingly. The analogy here is about larger DOM manipulations. I shall explain such scenarios in my next article.

 

Happy coding :)


Function overriding is an important feature in any programming language. In advanced languages like .NET, Java, it can be accomplished easily through a set of key words. But this is not the same in JavaScript and this is where closures come to your rescue.

This article is not something new. Infact, it is a part of every JavaScript geek's  toolkit, which does not have much exposure. So just wanted to throw some light on it. (If you are not very clear of closures, please visit this article and come back).

Let us take a vey simple example. Assume that you have a button, for which a click event is bound.

<input type="button" id="btnTest" value="Test Button"/>

var originalClick=function(e){ 
    e.preventDefault(); 
    console.log('original button click'); 
}; 
 
$(document).ready(function() { 
    $('#btnTest').click(originalClick); 
}); 

Now, if there is some requirement change and you need to add extra functionality to this button click, then instead of messing up its method, you can extend the originalClick method using closures, like this:

(function() { 
    var extendedClick= originalClick; 
    originalClick= function() { 
        console.log('Extending Test Button click'); 
        return extendedClick.apply(this, arguments); 
    }; 
})(); 

The above code is nothing but a self executing anonymous function (gets executed immediately after its definition). In the first line, we are storing the actual function in a variable 'extendedClick' (we'l use this later). Then we are creating a function with the same name as our original button click function (originalClick).

In the inner function, we are writing our extended logic and executing 'extendedClick' using .apply() method. (passing 'this' as first param to .apply() makes sure that the context is still the same as original method). So the entire code would be:

var originalClick=function(e){
    e.preventDefault();
    console.log('original button click');
};
 
(function() {
    var extendedClick= originalClick;
    originalClick= function() {
        console.log('Extending Test Button click');
        return extendedClick.apply(this, arguments);
    };
})(); 
 
$(document).ready(function() {
    $('#btnTest').click(originalClick);
}); 

Thats it! Your method is now overridden!! Ok, now let us see what exactly happened.

As per the definition of closure, we have 2 functions which are nested and extendedClick is a local variable. The outer function is a self executing one. During its execution, ‘extendedClick’ is obviously available inside the inner function ‘originalClick’, since it is defined in the parent context. The magic of closure comes after the outer anonymous function is executed. How?

When you click on button, the overwritten ‘originalClick’ function will be fired, which will print the console statement ‘Extending Test Button click’. Then the ‘extendedClick’ function, which has a copy of the first ‘originalClick’ function, will be fired. But why is it still accessible? The variable ‘extendedClick’ is private to the outer anonymous function, which means, it should have been destroyed after the outer function executed. But it is still accessible, which is the power of closure.

(Q) How can I override core jQuery methods using this concept?
(A) Ben Nadel
explained it clearly in his article, which I happened to see while I started this article. It is the same concept, but still I wanted to write and explain in layman’s terms. Thanks to Ben for his great blog posts and for quick turn out in times of need.

Using this technique, you can override even $(document).ready function! This would help you the most when you are in a maintenance project and have to do bulk changes in code with minimal impact.

Happy coding :)


One of the most important Usability requirements in business applications is, to periodically inform the users when there is any unsaved data on their web pages. This can be seen in email apps like Live mail/Gmail (compose a new mail and try to navigate to Inbox, without saving or sending the mail. An alert will pop out asking to save the mail).

To meet this requirement, one page load, one should loop through all the controls of the page, store the initial values of the controls, bind blur event handlers to all the controls, on blur event compare the final value with the initially stored values. If there is any change in the value, mark the form as dirty (unsaved data), else mark it as clean (saved data).

jQuery Dirty Form plug-in:

I started writing my own code, but found the beautiful dirty form plug-in. Thanks to the author Wilson for the plug-in, which does exactly the same as my pseudo-code. To check for a dirty form, all you need to do is:

$(document).ready(function(){
   $("#YourFormId")
     .dirty_form()
     .dirty(function(event, data){
       //The dirty event fires when you blur from a control after changing its value.
     })
 });

The plug-in is not well documented, hence you should spend time walking through the code. The plug-in will set a flag to the form’s data, to indicate if it is dirty or not, like this:

form.data("dirty", true) 

The dirty() event in snippet 1 will set the dirty flag to true. So at a later stage if you need to check the form’s status, you should use the form’s data. To a good extent I could leverage the the plug-in, but to meet my project specifications, I had to tweak it a lot.

Bug in Dirty Form plug-in and fix for the bug:

The plug-in has a function called “input_checker”, which will check for form status on each control’s blur. As said earlier, it will compare the initially stored values with final ones, which is fine. However, if you switch between forms, the data of one form will be compared with data of latest form, which spoils the show. I’m not sure why others haven’t raised the bug, but I’m very sure of it. Hence publishing the below fix:

In the “input_checker” function, replace the below code

input_checker : function(event){
    var npt... ... ...
    inputs = event.data.inputs, settings = event.data.settings

with this one:

input_checker : function(event){
    var npt ... ... ...
    inputs = $(':input:not(:hidden,:submit,:password,:button)', form), settings = event.data.settings

What is happening is, the plug-in is caching all the inputs to be checked in data parameter of the form. When we navigate to a new form, the controls of old form(from cache) are being checked, instead of the controls from new form. Hence I am querying the controls of new form again and using it for comparison. This would solve the problem :)

Here are some of the functionalities which I could leverage using the plug-in:

(1) On page load you can disable save buttons and enable them only in the dirty() event.

(2) You can check for form dirty flag and decide to extend user’s session accordingly.

(3) You can give a warning when user navigates to another page without saving data (similar to Gmail/Live mail).

Thanks to Wilson once again for the plug-in. Hope the fix would help some of the folks who are facing similar issues. 

Happy coding :)


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 :)


Exception handling is an important feature in any business application. In simple words, it is all about catching ugly errors thrown by server and displaying them in a user friendly manner to the end user. (Of course, logging exceptions/notifications etc may also be a part of exception handling. )

ASP.NET provides API for handling exceptions and displaying them in custom error pages. Custom error pages can also be defined for different HTTP error status codes, which provides good experience to end users in case of exceptions.

However, if you are using AJAX in your ASP.NET application(I’m using jQuery library for AJAX), you would not like to redirect users to a custom error page, as that kills the primary motto of AJAX. You would instead like to display error messages in the same page, as in facebook or twitter. So here is how this can be done using jQuery:

jQuery’s $.ajax method has a special function, $.ajaxSetup, where global settings can be made for handling AJAX requests. If you use this global function, you need not write error callbacks for each of your AJAX requests. All erroneous AJAX requests will be handled by the global error callback in $.ajaxSetup function. We can take advantage of this and write our exception handling wrapper.

$.ajaxSetup({
    error: function(XHR, errStatus, errorThrown) {
 
        if (XHR.status == 0) {
            alert('You are offline!\n Please check your network.');
        } else if (XHR.status == 404) {
            alert('Requested URL not found.');
        } else if (XHR.status == 500) {
            var errorMessage = 'Internal server error';
            try {//Error handling for POST calls
                var err = JSON.parse(XHR.responseText);
                errorMessage = err.Message;
            }
            catch (ex) {//Error handling for GET calls
                $('#divMaster').append('<div id="divErrorResponse" class="DisplayNone">' + XHR.responseText + '</div>');
                errorMessage = 'Page load error: ';
                errorMessage += $('#divErrorResponse').find('h2 i').html();
            }
            alert(errorMessage);
        } else if (errStatus == 'parsererror') {
            alert('Error.\nParsing JSON Request failed.');
        } else if (errStatus == 'timeout') {
            alert('Request timed out..Please try later');
        } else {
            alert('Unknown Error.\n' + XHR.responseText);
        }
    }
});

In the above code, we are checking for status codes(which are self explanatory) and handling error conditions based on these codes. Most of the times, the status code will be “500”, which says “Internal Server Error”. i.e., error in your server side code. Please refer this article from Encosia.com, which explains the core of what I am writing now.

Now, this “500 – Internal Server Error” may arise in both GET as well as POST requests. In POST request, if your web method throws error, it returns a JSON object, which you can parse as explained in the above link. But this does not work in case of GET requests.

Assume that you are loading a remote page into a master page using jQuery AJAX. If your “Page_Load” event throws exception, your response would be in HTML format (unlike the case of POST request, where the response is JSON object), which you cannot parse using JSON.parse or eval(). To differentiate between GET & POST responses, I’m simply using JSON.parse() in try() method. If it throws exception, it is surely due to a GET response, which is html. For better user experience, you may use jGrowl plugin for displaying error messages.

Conclusion: For exceptions in GET requests, you can query the resultant html using jQuery’s DOM selectors and display user friendly messages. For exceptions in POST responses, you can simply parse the resultant JSON object and display user friendly messages. If you feel there could be a better way of handling exceptions in GET requests, let me know.

Hope this article saves the time of folks who are facing similar problems. Happy coding :)


Localization is a very important feature required in medium-large scale business applications. As always, ASP.NET makes developers life easy by providing inbuilt localization mechanism. Using resource files, all the elements in a web page can be localized.

However, if you are building a rich client side app using JavaScript/jQuery, you may need to fetch error messages and other strings from locale specific external file, without post back. In such cases, jQuery localization plugins come to rescue. Below are some of the best jQuery plugins, which help in localization:

  1. http://keith-wood.name/localisation.html
  2. http://codingwithcoffee.com/?p=272
  3. http://sundaymorning.jaysalvat.com/ 

The third one is cool with integrated Google translation API,  The second plugin is used by jqGrid & other plugins for localization. However, I really loved the first one - Keith wood's plugin, which gives a basic but powerful localisation features. All it does is, make synchronous call to the server and load locale specific JS file, which will override the variables of your base file. When you use custom events to change localized messages, the first one is the best, owing to its simplistic nature.

The question now is, how to get the UI culture of user's browser on page load.

Though the plugin is expected to do this, somehow, this is a missing feature. But you need not worry, as ASP.NET does this easily for you.In the "Session_Start" event of global.asax, just use this code:

Response.Cookies("UICultureCookie").Value = Request.UserLanguages(0)

This stores the first preferred UI culture of user's browser in a cookie. Using the information in this cookie is pretty simple using jQuery's cookie plugin. Just say:

var clientCulture = $.cookie("UICultureCookie");
$.localise('JavaScript/Constants/constants', { language: clientCulture }); 

That's it!  Now even your client side messages in ASP.NET can be localized, without postback, using the power of jQuery.

P.S:  I didn't write much about how to use these plugins, as their home pages have clear documentation & demos, which are self explanatory.


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 :)


Developers who have tried jQuery UI Tabs plugin might have tried AJAX mode, which is really useful in meeting several requirements. The documentation clearly explains how to start using AJAX tabs.  However, there would be few hiccups if the plugin is not clearly understood. Below are some of them which I have faced recently:

Problem 1: In AJAX mode, sometimes, tabs do not load on a single click. You need to select a tab twice (double click) to open a tab.

Reason: Unfortunately, this is due to a bug in the plugin and happens when your AJAX calls fail.  Error handling is not done properly in jQuery tabs plugin as of the current version(1.7.2). More about this bug here. It can be resolved by applying the patch as described in the ticket. Hopefully, it would be fixed in the next release.

Problem 2: The “spinner“ option does not work by default (Spinner lets you provide a default “loading…” message in the tab, during tab load).

Resolution: To show spinner, the content of anchor tags inside “<li>” must be enclosed in “<span>” tags. More info here…

Problem 3: Displaying custom “loading” message in the tab body (and NOT in the tab).

Resolution: Overwrite the default spinner and make use of “select”, “show” functions. More Info here…
(Note: When tabs are cached, “load” will not get triggered for the second time. So use “show” instead of “load” while caching).

Problem 4: Remove “flickering” of tabs on page load.

Resolution: As you might have expected, simply hide the tabs container using CSS (display:none) and show it using jQuery after tabs are built as below:

$('#TabsDiv').tabs({.....}).css('display','block');

Problem 5: Tab panel/body is not removed from the DOM when a tab is closed.

Resolution: This is indeed a tricky problem. This happens when tabs are disabled! Wondering what is the relation? It’s simple. When a tab is disabled, the “<li>” element, which makes the tab header, will be displayed in a dull style. But the corresponding “div”, which makes the tab panel/body is not rendered.

So, there would be a difference in indexing between tab header & body and thus the tab body is not deleted. Hence, do not disable tabs when you want to remove them based on index! (You may debug the first two lines of “remove:” function in the plugin to test this).

Problem 6: Prevent “auto selection” of adjacent tab, when a tab is closed.

Resolution: The Tabs plugin mimics “Firefox” tabs with respect to auto selection of a tab, when another tab is closed. However, sometimes, you might need to select a farther tab on closing of a particular tab. This cannot be achieved by overriding the “remove” callback. So simply comment the below lines in “remove” function and write your code to select the desired tab in your close button click event.

// If selected tab was removed focus tab to the right or 
        // in case the last tab was removed the tab to the left. 
        if ($li.hasClass('ui-tabs-selected') && this.anchors.length > 1) { 
            this.select(index + (index + 1 < this.anchors.length ? 1 : -1)); 
        }

Note: I’m using jQuery tabs inside UI.Layout plugin in my project. At first, I thought that the layout plugin is messing up my code and causing these issues. After straining for 3 days, I could figure out the above solutions. So folks using the UI.Layout plugin need not worry about Tabs plugin integration. Their combination works perfectly.

Hope this article saves the time of many enthusiasts who might face similar problems. Happy coding :)


  • Share/Save/Bookmark
  • Entries (RSS)
  • Comments (RSS)

About

ProfilePic Hi, My name is Krishna Chaitanya and I'm a web developer from Hyderabad, India.

This is my online abode where I write about various technical topics, my little experiments related to web development in ASP.NET, jQuery etc. More...