Finding an Element Using jQuery’s andSelf() Function

The jQuery @andSelf@ function is described in the “jQuery API documentation”:http://api.jquery.com/andSelf/ as follows:

bq. Description: Add the previous set of elements on the stack to the current set.

This can be very useful when you are looking for an element that matches a selector and are given an element that itself might match, or that may have a descendant that matches.

I ran into this case when I had a function that was expecting to be given a container element and would then @find()@ the correct descendant element to manipulate. At some point I ended up with an event handler on the descendant element and needed to call my function from the event handler. It seemed silly to have to search upwards to find the container just so the function could search back down to find the descendant element I had been given in the event handler.

Instead I modified the function to look at the element passed in as well as the descendant elements to find the one that needed to be manipulated. Here is an example that does this using @andSelf@:


var addToTheList = function($elem, value) {
  var itemHtml = '
  • ' + value + '
  • ', selector = ".list"; $elem.find(selector).andSelf().filter(selector).append(itemHtml); };

    Note that I must @filter()@ the results after calling @andSelf()@ to avoid including the passed in element if it doesn’t match the .list selector. The result is that given this HTML

    
    <div class="container">
      <div class="inner-container">
        <ul class="list">
          <li>one</li>
          <li>two</li>
          <li>three</li>
        </ul>
      </div>
    </div>
    

    I can call the function passing in any of the container elements or the list itself and the function will properly append to the correct element.

    
    addToTheList($('.container'), "four");
    addToTheList($('.inner-container'), 'five');
    addToTheList($('.list'), 'six');
    

    You can run “this example”:http://jsfiddle.net/baconpat/yEHYN/ and experiment with it on jsFiddle.

    Conversation
  • Marcus Tucker says:

    Interesting, but isn’t the same selector-based filter operation being performed twice on the matching descendent elements – once in the initial .find() and once more in .filter() once the passed in element has been added – which is surely ineffecient? There must be a neater solution to this…?!

    • Marcus – Yes, I believe you are right, it is going to filter the matching descendant elements twice. If this is a performance problem you can use something like the following which should only scan through the elements once, but with a bit more duplication compared ($elem is repeated) to the original solution:

      $elem.filter(selector).add($elem.find(selector)).append(itemHtml);

      Slightly less elegant in my opinion, but should perform better.

  • Comments are closed.