Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the most efficient way to traverse up in jQuery

I'm trying to close a parent container when an internally nested button is clicked. In my UI -- I have many of these parent containers (I'm rendering preview windows of my product catalogue on a product category page).

As you can see from my mark-up below -- the CLOSE button is deeply nested in the DOM. When the user clicks on the CLOSE Button -- I need to hide() the parent Box-1. Keep in mind I may have upto to 100 products being displayed on a page (100 boxes of "Box-1"s) at a time.

My markup looks like this:

<div class="box-1">
  <div class="box-2">
    <div class="box-3">...</div> <!-- end box-3 -->

    <div class="box-4">
      <div class="box-5">...</div> <!-- end box-5 -->
        <a class="btn-close" href="#">CLOSE</a>  <!-- this triggers the close event -->
    </div> <!-- end box-4 -->
  </div> <!-- end box-2 -->

  <div class="box-6">
    <div class="box-7">...</div> <!-- end box-7 -->

    <div class="box-8">
      ...
      <div class="box-9">...</div> <!-- end box-9 -->
    </div> <!-- end box-8 -->
  </div> <!-- end box-6 -->
</div> <!-- end box-1 -->

My question is -- how do I best (and most efficiently) traverse back up the DOM to get hold of the "box-1" and issue the .hide() method ... here is my existing code.

<script>
$productsResultItems.delegate('.btn-close', 'click', function (e) {
    //box-1
    $(this).parents('div.box-1').hide(); // <-- is this the best way?????
    e.preventDefault();
</script>

Initially, I was trying this --

$this.parents().find('.hover-box-large').hide();

which was proving to be very slow in IE7 and IE8.

I found adding more detail to the selector improved performance nearly 100-fold for IE7, but only 4-fold faster in IE8 :( IE8 still requires about 200ms to close the parent container. Where now all other browsers (Chrome, Safari, Firefox and IE7) close the container in less than 20ms.

$this.parents('div.hover-box-large').hide();

But is there a selector method that is even better? Any particular reason IE8 is soooo bad at this type of upward traversal??

like image 801
rsturim Avatar asked Jun 06 '11 14:06

rsturim


2 Answers

The best method to use is closest, which finds the nearest ancestor element that matches a selector:

$this.closest('div.box-1').hide();
like image 164
lonesomeday Avatar answered Oct 28 '22 00:10

lonesomeday


Actually .closest() should be quicker than .parents().

In the jQuery Docs on .closest(), you can find:

.closest()

  • Begins with the current element
  • Travels up the DOM tree until it finds a match for the supplied selector
  • The returned jQuery object contains zero or one element

.parents()

  • Begins with the parent element
  • Travels up the DOM tree to the document's root element, adding each ancestor element to a temporary collection; it then filters that collection based on a selector if one is supplied
  • The returned jQuery object contains zero, one, or multiple elements

So in your case, .closest() would be the most suitable one, as you need to find one element, the closest ancestor that matches your selector. parents() would filter through all the possible ancestor elements, even if it already found the one you need.

like image 25
kapa Avatar answered Oct 28 '22 00:10

kapa