SiteCrafting, Inc.

7 Apr

$.delegate() and you

jQuery 1.4.2 added a set of new functions: $.delegate() and $.undelegate(). $.delegate() is a hybrid between $.bind() and $.live(). Here is an example of how the three functions differ, and how to implement $.delegate() in existing code.


History

Attaching events to elements in jQuery is fairly straight forward. Simply select your element and run the bind function with the event name string and callback function. As an example, imagine you want to recreate the < ol> tag using < ul> (not that it's a good idea, it's just a well known example). An < ol> tag will automatically number the < li> tags within it, whereas the < ul> tag will not. The HTML will look something like this:
<ul id="fake_ol">
    <li>1. Static</li>
    <li>2. Static</li>
    <li>3. Static</li>
</ul>
Now lets say you want add a new element every time you click one of these < li> tags. The jQuery would look something like this:
var num = 3;
$('#fake_ol li').bind('click', function() {
    num += 1;
    $(this).parent().append('<li>'+num+'. Dynamic</li>');
});
If you were to try this example, you would notice that the dynamic < li> tags do not create more dynamic tags. jQuery 1.3 solved this with a new function called $.live(). It looks the same, only the event is stored in document, and the events bubble up to it. The code is easy to modify to use live:
var num = 3;
$('#fake_ol li').live('click', function() {
    num += 1;
    $(this).parent().append('<li>'+num+'. Dynamic</li>');
});
Infact, the only difference is we call $.live() instead of $.bind(). This works really well for small sites with not a lot of content. But when you have a much large site, and performance becomes an issue, all this bubbling up and checking if the event should fire becomes expensive. Is there a way we can attach the event to something closer to the target?

$.delegate()

jQuery 1.4.2 added set of functions: $.delegate() and $.undelegate(). $.undelegate works exactly like you would think, it remove the event handler. What $.delegate() does is far more interesting. It will add the live event to something closer to the target so the bubbling doesn't have to search the whole document. This is a huge performance increase, especially for large sites. There are a few changes that need made, but they are trivial:
var num = 3;
$('#fake_ol').delegate('li', 'click', function() {
    num += 1;
    $(this).parent().append('<li>'+num+'. Dynamic</li>');
});
The difference now is the use of the $.delegate() function and the selector. This time, you select the element directly (so it must be called after document load), and delegate listening for click events which happen on any < li> tag. Now jQuery doesn't have to walk all the way up the document tree to find the event, and doesn't have to walk all the way back down to verify and call the event.

Summary

The $.delegate() function works similar to the $.live() function, in that it will run events to dynamically added tags. But unlike $.live(), $.delegate() is stored in the selected element similarly to $.bind(), which requires document less tree traversal. With just a few tweaks, you can get some of the performance benefits of localization of $.bind(), but the dynamic eventing of $.live().
Coding Techniques, From the Workbench, Javascript
by Paul Sayre | 4/7/2010 10:00am | Comments (4)

Nice and straightforward article.

One typo though: "document less tree" -> "less document tree"

Left by JustinJohnson.org | Apr 15, 2010

Nice and quick "how to" for .delegate - any chance you know how to use .delegate in place of .load?

Thanks in advance!

Left by Chicago Web Design | Aug 27, 2010

@Chicago

The thing about .deletage() is that it applies to a specific element (or set of elements). So the element has to be on the page at the time you are calling the function. So you will likely need to wait until the document loads before attaching delegate events.

Were you thinking in place of .live() ?

Left by Paul Sayre | Aug 27, 2010

Thanks for your reply!

It's def in place of .load that I'm looking to get around. Once I populate a div with .load, jquery won't allow me to manipulate it in any way (ie. addclass, fade, etc). Basically, no JS works on the content that was .load(ed)

Left by Chicago Web Design | Aug 27, 2010

Leave a Comment




* required    Comment Guidelines