15 excellent tips - Improve your jQuery

jQuery is an awesome framework. And I think a lot of users have been using it for about several years. Here I would like to share some of tips, tricks and techniques on jQuery.

  1.    Load the framework from Google Code
  2.    Combine and minify you scripts
  3.    Minimum DOM manipulation
  4.    Use IDs instead of classes
  5.    Supply context to your selectors
  6.    Use chaining properly
  7.    Use animate function
  8.    Learn about event delegation
  9.    Use classes to store state
  10.    Use jQuery data() method to store state
  11.    Create your own selectors
  12.    Use jQuery utility functions
  13.    Resolve conflict when using jQuery with other frameworks
  14.    How to tell when images have loaded
  15.    Return 'false' to prevent default behaviour

1. Load jQuery framework from Google

Google have been hosting jQuery libraries for a period of time. And there are two advantages of loading jQuery from Google.

  • Save bandwidth and load quickly since Google have CDN;
  • Possibly cached if user has visited a site which delivers jQuery from Google Code;

To do it, simply include the jQuery as follow:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
    // Load jQuery
    google.load("jquery", "1.2.6");
    google.setOnLoadCallback(function() {        // Your code goes here.
    });
</script>

2. Combine and minify you scripts

Many web site used a lot of jQuery plugins, like lightbox, localScroll, Photo Slideshow. However, browsers cannot load scripts concurrently which means that if you've got several scripts downloading one at a time then you're really slowing down the loading of your page. Hence, if you combine all the scripts files into one single file, then that should be able to speed up loading speed.

Also, minify your scripts is an very important steps as well. Normally, we would use GZIP to reduce the file size of the javascript file. 

3. Minimum DOM manipulation

To speed up the code to execute, we have to cut down the number of times we insert into DOM. DOM refer to insertion operations like .append(), .prepend(), .after() and .wrap() are relatively costly and performing lots of them really slow things down.

To prevent that, we need to do is use string concatenation instead. It builds the list and then use a single function to add them like .html() is much quicker. Let illustrate the example as follow:
 

var myList = $('#domlist');

for (i=0; i<1000; i++){
    myList.append('This is list item ' + i);
}

The above code, it takes 216 milliseconds. However, if we build the list items as string and use the .html() to inset, 
 

var myList = $('#domlist');
var myListItems = '';

for (i = 0; i < 1000; i++) {
    myListItems += '<li>This is list item ' + i + '</li>';
}
myList.html(myListItems);


It takes 185 milliseconds only.

4. Use IDs instead of classes

The beauty of jQuery makes selecting DOM elements using classes as easy as selecting elements by ID. However, it is much better to select by ID if possible, as jQuery uses browser's native method (getElementByID) to do this and doesn't have to do any of its own DOM traversal. Hence, select by IDs is much faster. Here an example to illustrate how much faster.
 

// Create our list
var myList = $('#List');
var myListItems = '<ul>';

for (i = 0; i < 1000; i++) {
    myListItems += '<li class="listItem' + i + '">This is a list item</li>';
}

myListItems += '</ul>';
myList.html(myListItems);

// Select each item once
for (i = 0; i < 1000; i++) {
    var selectedItem = $('.listItem' + i);
}
 

The above code finished in 5066 milliseconds. To modify the code to give each item an ID instead of class then select them using ID.

// Create our list
var myList = $('#List'');
var myListItems = '<ul>';
for (i = 0; i < 1000; i++) {
   myListItems += '<li id="listItem' + i + '">This is a list item</li>';
}
myListItems += '</ul>';
myList.html(myListItems);
// Select each item once
for (i = 0; i < 1000; i++) {
   var selectedItem = $('#listItem' + i);
}


This time, it just take 61 milliseconds only to complete. Almost 100x faster.

5. Supply context to your selectors

When you use a selector such as $('.myList') the whole of the DOM will be traversed which depending on the page could be expensive.

However, jQuery function could takes a second parameter when performing a selection.
 

jQuery( expression, context )


By providing a context to the selector, jQuery is given an element to start searching within and it doesn't have to traverse the whole of the DOM.

To illustrate the different, let takes the example at #1 to explain. 
 

var selectedItem = $('#listItem' + i);


The above code creates an unordered list with 1000 items with individual class of each. It then loops through and selects each item once. You'll remember that when selecting by class it took just over 5 seconds to select all 1000 of them using this selector.

Here, I added a context so that it was only running the selector inside the unordered list, like this...
 

var selectedItem = $('#listItem' + i, $('.myList'));


Here, it took 3818 milliseconds and it is 25% speed inprovement by making a small modification to a selector.

6. Use chaining properly

Another prettiest thing that jQuery has the ability to chain method calls together. For example, like this:
 

$('myDiv').removeClass('off').addClass('on');


If you think that the above code is not your style, you can do chaining across line breaks which means you can write neat code like this:
 

$('#mypanel')
    .find('TABLE .firstCol')
    .removeClass('.firstCol')
    .css('background' : 'red')
    .append('<span>This cell is now red</span>');


Chaining automatically helps you to cut down on your selector use. Let explain with an example.
 

$('#myTable')
    .find('.firstColumn')
        .css('background','red')
    .end()
    .find('.lastColumn')
        .css('background','blue');


Let say, we selected a table and would like to find cells with a class of "firstColumn" and coloured them in red. Moreover, we also want to colour all the cells with a class "lastColumn" as blue. Because we've used the find() funciton we've filtered out all the cells that don't have a class of "firstColumn" so we need to use the selector again to get the table element and we can't continue chaining, right? Luckily jQuery has an end() function which actually reverts back to the previous unaltered selection so you can carry on chaining, like the code on above.

7. Use animate function

When I started using jQuery, I loved that jQuery provide easy to use pre-defined animations function like slideDown(), fadeIn(). If you look at the jQuery source code, you will see that those methods are just shortcut which use the animate() function. Hence, we can start learn to use animate() function.

Let take an example, if you want to animate all your menu items grow to 100 pixels high when you roll over.
 

$('#myList li').mouseover(function() {
    $(this).animate({"height": 100}, "slow");
});


Unlike other jQuery functions, animations are automatically queued. If you want to run a second animation after the first is finished then just call the animate method twice.
 

$('#myBox').mouseover(function() {
    $(this).animate({ "width": 200 }, "slow");
    $(this).animate({"height": 200}, "slow");
});


However, if you want the animations to happen concurrently then put both styles in params object of a single call.
 

$('#myBox').mouseover(function() {
    $(this).animate({ "width": 200, "height": 200 }, "slow");
});

8. Learn about event delegation

jQuery makes ever easier then ever to attach events to elements in DOM. But adding too many events is inefficient. And event delegation allows you to add less events to achieve the same result in many suitations. Here is an example to illustrate.
 

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

 

The above simple function which turns cells in a table red when you click on them. Let's say that you've got a grid with 10 columns and 50 rows though, that's 500 events bound. Wouldn't it be neater if we could just attach a single event to the table and when the table is clicked have the event handler work out which cell was clicked before turning it red?
 

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


To implement is easy like the code above. The 'e' contains information about the event like the target element that actually recieved the click. And what we have to do is inspect it to see which cell was actually clicked. 

Event delegation has another benefit. Normally, When you bind a handler to a collection of elements it gets attached to those elements and those elements only. If you add new elements to the DOM which would have been matched by the selector then they don't have the event handler bound to them (are you following me?) then nothing will happen.

When using event delegation you can add as many matching elements to the DOM as you like after the event is bound and they work too.

9. Use classes to store state

The basic way to store information about a block of html is to manipulate elements based upon their classes. Here is an example.
 

<div class="menuItem expanded">
    <div class="button">
        click me
    </div>
    <div class="panel">
        <ul>
            <li>Menu item 1</li>
            <li>Menu item 2</li>
            <li>Menu item 3</li>
        </ul>
    </div>
</div>


To create an expanding menu, like user click the button, the panel slideDown() if it is currently closed or slideUp(). To accomplish this requirement, we created a jQuery script to add an extra class to the wrapper div which serves no other purpose other than tell us the state of the item. So all we need is a click event handler which performs slideUp() or slideDown() on the corresponding panel when the button is clicked.
 

$('.button').click(function() {

    var menuItem = $(this).parent();
    var panel = menuItem.find('.panel');

    if (menuItem.hasClass("expanded")) {
        menuItem.removeClass('expanded').addClass('collapsed');
        panel.slideUp();
    }
    else if (menuItem.hasClass("collapsed")) {
        menuItem.removeClass('collapsed').addClass('expanded');
        panel.slideDown();
    }
});


This is a very simple example, but we can easily store the status by add extra classes about element or HTML fragment.

10. Use jQuery data() method to store state

jQuery has an internal data() method which can be used to store information in key/value pairs against any DOM elements. Storing a piece of data is as simple as this:
 

$('#myDiv').data('currentState', 'off');


By applying this method, we can apply this method to the pervious example on #9. We will keep the same HTML, but without add any class on the HTML and use data() function instead.
 

$('.button').click(function() {

    var menuItem = $(this).parent();
    var panel = menuItem.find('.panel');

    if (menuItem.data('collapsed')) {
        menuItem.data('collapsed', false);
        panel.slideDown(); 
    }
    else {
        menuItem.data('collapsed', true);
        panel.slideUp();
    }
});


And this method is much neater. For more information about data() and removeDate(), please visit jQuery internals.

11. Create your own selectors

jQuery has loads of built-in selectors for selecting elements by ID, class, tag, attribute...etc. However, if you come to an suitation that you need to select elements based on something else that jQuery does not have such selector?

Actually, jQuery provide the ability to create your own selector.
 

$.extend($.expr[':'], {
    over100pixels: function(a) {
        return $(a).height() > 100;
    }
});

 

$('.box:over100pixels').click(function() {
    alert('The element you clicked is over 100 pixels high');
});


The first block of code creates a custom selector which finds any element that is more than 100 pixels tall. And the second block just used to add click handlers to all of those elements.

Here, I am not going to explain im any more detail. However, here can demonistrate how powerful is it. And if you are looking for any things more about it, you can goole for "custom jquery selector" for more examples.

12. Use jQuery utility functions

Another coolest things of jQuery that is come with some really useful methods which fill a few gaps in JavaScript's repertoire.For example, the ordinary JavaScript support for certain common array functions. However, jQuery has methods for iterating, filtering, cloning, merging and removing duplicates from Arrays.

Other common functions that are difficult in Javascript include getting the selected item in a drop down list. In plain old JavaScript you'd have to get the <select> element using getElementByID, get the child elements as an array and iterate through them checking whether each one was selected or not. jQuery makes it easy..
 

$('#selectList').val();


To know about jQuery utility function, it is worth spending some time looking through the Jquery documentation and know some of the lesser known functions.

13. Resolve conflict when using jQuery with other frameworks

Most JavaScript frameworks make use of the the '$' symbol as a shorthand and this could cause clashes when using more than one framework on the same page. To solve this, .noconflict() function gives control of the $ back and allows you to set your own variable name, like this...
 

var $j = jQuery.noConflict();
$j('#myDiv').hide();

 

14. How to tell when images have loaded

This is another one of those problems that doesn't seem to be as well documented as it should be (not when I went looking anyway) and it's a fairly common requirement when building photo galleries, carousels etc, but it's fairly easy.

All you have to do is use the .load() method on an IMG element and put a callback function in it. The following example changes the "src" attribute of an image tag to load a new image and attaches a simple load function.
 

$('#myImage').attr('src', 'image.jpg').load(function() {
    alert('Image Loaded');
});


And here, alert is called as soon as the image is loaded.

15. Return 'false' to prevent default behaviour

$('popup').click(function(){
    // Launch popup code
});

<a href="#" class="popup">Click me!</a>


The above code work well to launch a popup code, however, if your page is long, you will notice that the # would cause the page jump to the top when user click event is triggered.

Hence, always add return false to prevent andy default behaviour.
 

$('popup').click(function(){
    // Launch popup code
    return false;
});

 

 

Tags: Javascript / JQuery