A new method signature is slated for jQuery 1.4: .closest(Array). It builds upon the previous .closest() method and hyper-optimizes the logic needed for handling event delegation (and live events).
closest() (and by extension, is()) has become a critical function in jQuery. With more people using live events reducing any overhead has become of the utmost importance. Every time an event fires that live is bound to (such as click or mousemove) jQuery uses the closest() method to go from the target element and find the nearest element that matches the specific selector. The more handlers that are bound, though, the more computationally expensive it becomes.
In jQuery 1.4 we’ve added closest(Array) which gives us the ability to batch these selector checks together and reduce the amount of time that we spend traversing the DOM.
Example
<html> <body> <div id="main"> <div id="test"> <div id="mouseme"></div> </div> </div> </body> </html>
And the following handlers are bound:
$("#mouseme").live("mousemove", ...) $("#main").live("mousemove", ...) $("body").live("mousemove", ...) // (plugin A) $("body").live("mousemove", ...) // (plugin B)
Let’s pretend that a ‘mousemove’ event occurs on #mouseme.
In jQuery 1.3.2:
- #mouseme check on #mouseme (load Sizzle)
- Return.
- #main check on #mouseme (load Sizzle)
- Walk up tree.
- #main check on #test (load Sizzle)
- Walk up tree.
- #main check on #main (load Sizzle)
- Return.
- body check on #mouseme (load Sizzle)
- Walk up tree.
- body check on #test (load Sizzle)
- Walk up tree.
- body check on #main(load Sizzle)
- Walk up tree.
- body check on body (load Sizzle)
- Return.
- body check on #mouseme (load Sizzle)
- Walk up tree.
- body check on #test (load Sizzle)
- Walk up tree.
- body check on #main(load Sizzle)
- Walk up tree.
- body check on body (load Sizzle)
- Return.
- Sort all element results.
- Loop through the results to trigger.
In jQuery 1.4:
- #mouseme check on #mouseme (load Sizzle)
- #main check on #mouseme (load Sizzle)
- body check on #mouseme (load Sizzle)
- Walk up tree.
- #main check on #test (load Sizzle)
- body check on #test (load Sizzle)
- Walk up tree.
- #main check on #main (load Sizzle)
- body check on #main (load Sizzle)
- Walk up tree.
- body check on body (load Sizzle)
- Return.
- Loop through the results to trigger.
In summary: There is less walking up the tree, no running of duplicate selectors, and no sorting of element results.
We’re still on track to push out a new alpha very soon and the final release on January 14th.
Mario (December 18, 2009 at 6:04 pm)
It is looking good. With version 1.3 .live has been a performance bottleneck. I had to change the code many times to make everything faster. I have been following Louis-Rémi Babé advice on learningjquery.com and everything is much better now.
Best Regards
Justin (December 18, 2009 at 6:48 pm)
This is really great to hear. Can’t wait for 1.4 to release!
Fernando Serboncini (December 18, 2009 at 7:25 pm)
John,
two things.
First: On the 1.4 pass, I think step 9 is “body check on #main”, right?
Second: I understand how this new grouped closest() can improve duplicate selectors, but I don’t see why there should be a big performance impact for less walking up the tree. Isn’t it just a “node = node.parentNode”? Why is this slower than looping through the selectors array on every node? My feeling is that it could be a bit better, but nothing noticeable. Could you elaborate a bit on this?
Anyway, wonderful work on jquery 1.4.
John Resig (December 18, 2009 at 8:03 pm)
@Fernando: Fixed the first point, thanks.
Unfortunately any accesses on DOM properties is inherently slow (especially so for IE) – it’s dramatically slower than walking through an array. Any chance that we can take to reduce the walks through the DOM yields a big performance boost.
Nate (December 18, 2009 at 9:53 pm)
John, will 1.4 ship with something more intuitive for delegation in cases where the live()-specific functionality isn’t required? The name “live” itself hints at the fact that all events are attached to the document (so as to ensure events are triggered for new elements added to the DOM which match the selector), yet the fact is that most daily delegation tasks do *not* require this.
I think I read somewhere that 1.4 would provide the ability to pass a context other than document to live(). While this would fix the “attaching mousemove to document for no reason”, it still leaves a lot to desire in terms of intuitive and minimalist code.
Example, where I’m wanting to detect mouseover for both ‘li a’ and ‘li’ within parent ‘#ul-elem’:
// 1.3.2 - the fastest/best way(?), but excessive code
$('#ul-elem').mouseover(function (evt) {
var target = $(evt.target), node;
if (node = target.closest('li a')) {}
if (node = target.closest('li')) {}
});
// 1.3.2 - multiple events! and on document to boot!
$('#ul-elem li a').live('mouseover', function () {});
$('#ul-elem li').live('mouseover', function () {});
// maybe in 1.4? live() contexts, still ugly!
var ul = $('#ul-elem')[0];
$('li a', ul).live('mouseover', function () {});
$('li', ul).live('mouseover', function () {});
// how it *should* be. even reads as English:
// "#ul-elem delegates mouseover for: 'li', 'li a'"
$('#ul-elem').delegate('mouseover', {
'li': function () {},
'li a': function () {}
});
// can even replicate live() functionality
$(document).delegate('mouseover', {
'#ul-elem li': function () {},
'#ul-elen li a': function () {}
});
Nate (December 18, 2009 at 10:05 pm)
P.S.: If you haven’t noticed, your blog gets confused when it encounters an empty line within <code> tags. It would appear the automatic insertion of <p> tags on double newline isn’t being ignored within <code> tags… ;)
kik (December 19, 2009 at 7:37 am)
Nate has a point, here, attaching all events to document is ugly and useless. I even don’t understand why the whole thing is so complicated.
Why is it the selector to match that receive the method call? It should be the object on which events are attached.
$( '#menu' ).click( function( event ){
if ( $( event.target ).is( 'a.trigger' )
{
event.stopPropagation();
event.preventDefault();
// do something
}
});
Sean Hogan (December 19, 2009 at 8:08 pm)
Having live event handlers being triggered only for the closest matching ancestor (of the event target) results in some surprising behavior. A couple off the top of my head:
1.
$("div").live("click", handler);
is different to
$("div").bind("click", handler);
2.
$("#main, #test").live("click", handler);
is different to
$("#main").live("click", handler);
$("#test").live("click", handler);
a. (December 29, 2009 at 12:29 am)
let’s say you have a very big table (say a table with 500×500), and you want to handle the click event on cells. you’ll use live() to avoid allocation 25k event handlers:
$(“#mytable td”).live(…)
but what if the table already generated (server script built it first)? yes, the $(“#mytable td”) will collect all the 25k cells, and after it built an array of TDs whihc will not be ever used, will register the live event.
why isn’t there a special (“static”) method for creating live bindings without enumerating the DOM? (yes, live() can be used to chain additional operations, but what’s the point for that?)
a. (December 29, 2009 at 12:30 am)
“very big table (say a table with 500×500)” should read as
very big table (for example 500×500 cells)
Mark Gibson (January 7, 2010 at 8:21 pm)
@a, I think for your large table example, live wouldn’t be the most appropriate technique anyway. You’d be much better off using a single handler and the closest function…
$('#mytable').bind('click', function(event) {
var cell = $(event.target).closest('td');
// ... do whatever to need to with cell ...
});
Also, live events can be bound prior to the ready event, so you could do your $(“#mytable td”).live(…) in a script in head outside of the usual ready handler.
Stochastik (February 3, 2010 at 9:36 am)
@john R., are you well versed in Java and/or C ?
Spiele Spielen (February 12, 2010 at 5:10 am)
Sitting at hom and waiting for 1.4. Feeling like cristmas is coming home;)
scuba (February 18, 2010 at 8:24 am)
have been following it up avidly, 1.4 should rock:)
its here http://blog.jquery.com/2010/01/29/14-days-of-jquery-summary-days-8-14-jquery-1-4-1-released/
hallelueah:)
footprints (February 18, 2010 at 8:29 am)
great news someone should update with vids,
ENT poblems (February 18, 2010 at 8:34 am)
live event handlers being triggered only for the closest matching earlier3.1 is following automatic progression
snow shovel (February 20, 2010 at 12:16 am)
there is a dearth of live event handlers,so this is refreshing and welcome
henryEb (February 24, 2010 at 8:46 pm)
awesome code thanks i am new with all of this
Online Bachelor degree
haccp (March 15, 2010 at 5:37 am)
jQuery is great, I’m getting more and more used to it every day. I already built few websites for my clients with jQuery and I simply love it :)
Also, I would like to point out jQuery is much better than Dojo in my opinion ! Keep up the good work people.
Addlinklist (May 12, 2010 at 10:31 am)
Thank you for update I love jQuery. I update information everyday.
An improve my website.
computer repair in lincoln (June 3, 2010 at 11:01 am)
So, I’m implementing this on my site and the WYSIWYG editor I’m using (Web Easy 7) generates this:
body onload=”if(IE||V5) OnWeLoad()”
for the body tag so it can use a different stylesheet if it’s IE.
When viewing the code in FF, the hints don’t display. When using IE they do.
If I just go with the normal “body” tag, and take out the onload=”if(IE||V5) OnWeLoad()” part, then it works fine in FF and IE. However, I’m worried about other adverse effects taking out the IE-specific stylesheet might have for IE users.
Any thoughts on how I can have both?
Thanks.
Mario and Luigi (June 4, 2010 at 2:40 am)
Extremely helpful. I like the way you write. Do you have an RSS feed?
Mario and Luigi
hearing aids (June 4, 2010 at 9:36 pm)
Can you explain in mor detail jQuery 1.4?
Mikasa (June 23, 2010 at 12:41 pm)
Awesome post buddy! The array related to mouse over program is really help me a lot. Thanks for such nice post. Nice blog, just bookmarked it for later reference. Awaiting for your next post.
Tom (July 15, 2010 at 12:20 pm)
Nice method, very easy to apply to my project, I like it very much.
Thanks for share.
————-
Article Directory
indir (August 9, 2010 at 10:50 am)
I agree!
Star out those beastly feet if you want to save us all! OH THE HUMANITY!!
Günter Hogrefe (August 17, 2010 at 2:13 am)
sehr informativ.
Sukhumvit (August 18, 2010 at 1:59 am)
HI john
Very interesting post- Just subscriped to your RSS feed.. Thank You very much.
Hotels Thailand (August 18, 2010 at 2:03 am)
there is a dearth of live event handlers,so this is refreshing and welcome