tags:

views:

56

answers:

3

The jQuery find(..) traversal method doesn't include the current node - it starts with the children of the current node. What is the best way to call a find operation that includes the current node in its matching algorithm? Looking through the docs nothing immediately jumps out at me.

+3  A: 

I think andSelf is what you want:

obj.find(selector).andSelf()

Note that this will always add back the current node, whether or not it matches the selector.

interjay
+4  A: 

You can't do this directly, the closest I can think of is using .andSelf() and calling .filter(), like this:

$(selector).find(oSelector).andSelf().filter(oSelector)
//or...
$(selector).find('*').andSelf().filter(oSelector);

Unfortunately .andSelf() doesn't take a selector, which would be handy.

Nick Craver
You even added a comment to the jquery page right after answering this question http://api.jquery.com/andSelf/#comment-50124533 Now that's thoroughness. Nice! I did my due diligence and 'Liked' that one too.
John K
The second one would be mindbogglingly slow. The first is simply just slow.
Tgr
@Tgr - I don't disagree, though the first shouldn't be that show unless you're dealing with a *very* large number of elements. If you don't need to chain you can skip re-filtering those elements for sure.
Nick Craver
Interestingly, `closest(..)` includes the current DOM element and up the tree whereas all down-the-tree traversal methods like `find(..)` etc don't match the current element. It's as if the jQuery team purposefully implemented these for no overlap when both operations used together for a full vertical search.
John K
@jdk - `.find()` is more analogous to `.parents()` in this case...if you look at what's available though, any parent operation can climb `.parentNode` (this is what happens inside jQuery), so it's a much easier than finding descendants...since there's not a lot there for a child tree, you have to compare a whole tree instead of a linear path.
Nick Craver
+1  A: 
$('selector').find('otherSelector').add($('selector').filter('otherSelector'))

You can store $('selector') in a variable for speedup. You can even write a custom function for this if you need it a lot:

$.fn.andFind = function(expr) {
  return this.find(expr).add(this.filter(expr));
};

$('selector').andFind('otherSelector')
Tgr
This only works if you're *starting* with a selector though, which may not be the case. Also, it's incorrect, it would be `$('selector').find('otherSelector').add($('otherSelector'))`, what you have now is equivalent to `.andSelf()`. Lastly, the `.andFind()` doesn't filter based on the expression, you would need to `.add($(this).filter(expr))` :)
Nick Craver
@Nick Craver: yeah, I forgot the filtering part, fixed now. It doesn't really matter if `$('selector')` is replaced by some other method of getting a jQuery object (if that is what you meant by not starting with a selector), `add()` can handle anything just as `$()` can.
Tgr
@Tgr - My point was that your `$('selector')` may be `$('selector').children('filter').closest('.class').last()`...it may be in a chain and you have no idea what that object you're adding is, so the generic solution should take the previous object like the filter does :)
Nick Craver
I still don't see why that would be a problem. `this` is whatever jQuery object a plugin was called on. It could be just as well be the result of a call chain.
Tgr