.closest(Array) in jQuery 1.4


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:

  1. #mouseme check on #mouseme (load Sizzle)
  2. Return.
  3. #main check on #mouseme (load Sizzle)
  4. Walk up tree.
  5. #main check on #test (load Sizzle)
  6. Walk up tree.
  7. #main check on #main (load Sizzle)
  8. Return.
  9. body check on #mouseme (load Sizzle)
  10. Walk up tree.
  11. body check on #test (load Sizzle)
  12. Walk up tree.
  13. body check on #main(load Sizzle)
  14. Walk up tree.
  15. body check on body (load Sizzle)
  16. Return.
  17. body check on #mouseme (load Sizzle)
  18. Walk up tree.
  19. body check on #test (load Sizzle)
  20. Walk up tree.
  21. body check on #main(load Sizzle)
  22. Walk up tree.
  23. body check on body (load Sizzle)
  24. Return.
  25. Sort all element results.
  26. Loop through the results to trigger.

In jQuery 1.4:

  1. #mouseme check on #mouseme (load Sizzle)
  2. #main check on #mouseme (load Sizzle)
  3. body check on #mouseme (load Sizzle)
  4. Walk up tree.
  5. #main check on #test (load Sizzle)
  6. body check on #test (load Sizzle)
  7. Walk up tree.
  8. #main check on #main (load Sizzle)
  9. body check on #main (load Sizzle)
  10. Walk up tree.
  11. body check on body (load Sizzle)
  12. Return.
  13. 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.

Posted: December 18th, 2009 · Tags: closest, live, jquery ·

48 Comments

  1. 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

  2. Justin (December 18, 2009 at 6:48 pm)

    This is really great to hear. Can't wait for 1.4 to release!

  3. 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.

  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.

  5. 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 () {}
    });

  6. 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... ;)

  7. 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
    }
    });

  8. 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);

  9. a. (December 29, 2009 at 12:29 am)

    let's say you have a very big table (say a table with 500x500), 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?)

  10. a. (December 29, 2009 at 12:30 am)

    "very big table (say a table with 500x500)" should read as

    very big table (for example 500x500 cells)

  11. 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.

  12. Stochastik (February 3, 2010 at 9:36 am)

    @john R., are you well versed in Java and/or C ?

  13. Spiele Spielen (February 12, 2010 at 5:10 am)

    Sitting at hom and waiting for 1.4. Feeling like cristmas is coming home;)

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

  15. footprints (February 18, 2010 at 8:29 am)

    great news someone should update with vids,

  16. 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

  17. snow shovel (February 20, 2010 at 12:16 am)

    there is a dearth of live event handlers,so this is refreshing and welcome

  18. henryEb (February 24, 2010 at 8:46 pm)

    awesome code thanks i am new with all of this
    Online Bachelor degree

  19. billigflug (February 27, 2010 at 4:18 am)

    Hi, very very thanks, this website is helpful.

  20. Vikash Mor (March 3, 2010 at 3:09 am)

    hi john i am interested to learn and work in programing but i am in seo company. i feel happy in programing. to day i found from a blog and when i read here lot of things , so i become your fan. thanks for give here lot of knowledge.

  21. Howtogetyourexback (March 7, 2010 at 8:07 pm)

    I was hoping to see some more examples. May be if you could create some more and show us mortals some tricks ;)

  22. SEO (March 9, 2010 at 10:57 pm)

    Thanks for give here lot of knowledge. I feel happy in your blog.

  23. 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.

  24. social bookmarking (March 26, 2010 at 8:36 pm)

    I work with jQuery everyday. Thank you for sharing. I love this story.

  25. Bing (May 4, 2010 at 12:00 pm)

    Nice blog, just bookmarked it for later reference
    Good post and nice design, is this a regular template?

  26. khaosanpalace (May 5, 2010 at 11:21 pm)

    You know i feel happy in programing. to day i found from a blog and when i read here lot of things. Thanks.

  27. cheap biker patches (May 7, 2010 at 8:10 pm)

    Hey, for those guys having browser issues you can attempt something that worked for me. I simply cleared my cache then reloaded the page. Hope that was useful.

  28. buy hearing aids (May 7, 2010 at 8:13 pm)

    Hey everybody. Interesting subject for a blog. I have been reading many blogs and forums lately. Some are really informative some are entertaining and some are a real crack up. I've got to say, terrific job on this blog, I'll be sure to look in again real soon.

  29. Shiela (May 8, 2010 at 5:15 am)

    interesting but where to you learn this

  30. Addlinklist (May 12, 2010 at 10:31 am)

    Thank you for update I love jQuery. I update information everyday.
    An improve my website.

  31. apache attack helicopter (May 19, 2010 at 4:39 am)

    1.Concept and Building History
    The need of a new and highly secure helicopter was first felt in the beginning of the 1990s. The great military power, the British Army, identified this need and by February 1993 they finalised the need with an invitation to bid for the design, construction and trial of the new concept.
    Among the bidding companies were: Boeing and Sikorsky with the RAH-66 Comanche, Agusta with the A129 Mangusta, British Aerospace and Eurocopter with the Tiger, GEC Marconi and Bell Helicopter the Cobra Venom, and Westland and McDonnell Douglas with the AH-64 Apache. The decision was taken later in July in 2005 and the winning aircraft builder was Westland and McDonnell Douglas with the Apache. One year later in 2006 the tow Parties signed a contract for 67 helicopters. This is how the WAH-64D Apache era started.
    The 67 WAH-64D Apache attack helicopters were built by the merged companies Boeing and McDonnell Douglas (1997) and Westland between 1999 and 2004. The first aircraft was built by Boeing and delivered to the Army in March 1999, followed by the Westland, who built their first aircraft in 2000 and delivered in July 2000. The last aircraft was built and delivered in July 2004.
    2.What makes it better?
    The WAH-64D Apache is the successor of the AH-64D Apache, built with some major differences, the most important of which are the folding blade mechanism and the Rolls Royce Turbomeca RTM322 engine instead of the General Electric T700s (the Rolls Royce engine can produce almost 25% more power than the General Electric engine, but it’s not exploited except during the take-off because of the Apache transmission system. There is a development program for a new transmission system that would use all the power provided by the Rolls engine).
    The WAH-64D Apache is designed to destroy difficult and important targets such as tanks and other ground military machines. It is capable to fire CRV7 rockets. The WAH-63D Apache is design with protection against ice for the rotor blades. It is capable of detecting over 250 potential targets simultaneously, classify and prioritize them. It can operate in all weathers, day and night, has Selex Helicopter Integrated Defensive Aids System, and is to be provided with Bowman secure communications system in the near future.
    3.
    The WAH-64D Apache is by far the best attack helicopter the British Army owns and it has been used in many military actions in the Middle East, where its effectiveness and capabilities were proven. It became a good investment, even though at the end the costs were a lot different than was initially predicted. Thus the British force became a more powerful military force that can use the WAH-64D Apache to take action in the war zones with high risks where the ground battle is dangerous. The WAH-64D Apache is now used in many operations with great success.
    Here are some of the important operations in which the WAH-64D Apache was used and its interventions were successful:
    The WAH-64D Apache’s first operation took place in Afghanistan and was part of the 16 Air Assault Brigade on the 22-th of May, 2006 in Afghanistan’s South Helmand province. Here the WAH-64D Apache used one of the Hellfire missiles in order to destroy a French armored vehicle damaged during a fight the day before. The decision of destroying it was based on the high difficulty of recovering it.

  32. seo (May 19, 2010 at 12:51 pm)

    HI john
    Very interesting post- Just subscriped to your RSS feed.. Thanks

  33. world cup football (May 24, 2010 at 2:18 am)

    Well this post is so interesting, I think if you can change anything else is the interface of this site :D

  34. garden gloves for women (May 25, 2010 at 10:14 pm)

    This is really indeed a good post.
    It contains all the valuable information which a user wants.
    I must thank to the author for creating such an interesting website.
    Keep up the good work always!!!!!!

  35. cork boards for sale (May 25, 2010 at 10:31 pm)

    Advertising is a non-personal form of communication intended to persuade an audience to purchase or take some action upon products, ideals, or services.

  36. Microsoft dynamics company (May 26, 2010 at 2:29 am)

    Can you access a computer from the iPod touch without installing anything onto the computer?

  37. credit debt settlement (May 26, 2010 at 11:26 am)

    As funds come in and so that transparency is ensured, we will post actual screenshots here on our blog of our Paypal account in real-time each week. We will also report on any purchases and actual distributions to each of these schools as they occur. Check back for those updates.

    PiCED Executive Director Sandra King Young also announced a partnership with well-known U.S. personal trainer, Val Fujii, the Folsom-based owner of Superwomen Boot Camp. Fujii has teamed up with Matt Sgro of Boot Camps With a Purpose to form “Superwomen Give Back: A Boot Camp Benefiting the Children of American Samoa”, a charity that has been set-up to raise funds for the recent tsunami disaster in American Samoa.

  38. 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.

  39. 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

  40. hearing aids (June 4, 2010 at 9:36 pm)

    Can you explain in mor detail jQuery 1.4?

  41. 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.

  42. 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

  43. 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!!

  44. Günter Hogrefe (August 17, 2010 at 2:13 am)

    sehr informativ.

  45. Sukhumvit (August 18, 2010 at 1:59 am)

    HI john
    Very interesting post- Just subscriped to your RSS feed.. Thank You very much.

  46. Hotels Thailand (August 18, 2010 at 2:03 am)

    there is a dearth of live event handlers,so this is refreshing and welcome

  47. Virtual Services (August 20, 2010 at 1:10 am)

    what is your plane, i will recommend you to go for Expression engine solution, else PHPBB

  48. birim çevir (August 24, 2010 at 5:12 am)

    Nice method, very easy to apply to my project, I like it very much.
    Thanks for share.

Leave a Comment

Note: Wrap all of your code blocks in <code>...</code> and replace < and > with &lt; and &gt;, respectively.

JavaScript Books

Secrets of the JavaScript Ninja

JavaScript Secrets

Secret techniques of top JavaScript programmers.

Pro JavaScript Techniques

Pro JavaScript

The best techniques for professional JavaScript. Published by Apress.

Micro Updates

John Resig Twitter Updates

@jeresig

Infrequent, short, updates and links.

JavaScript Jobs



Hosting provided by: Ruby Hosting by Engine Yard