jQuery select descendants, including the parent
Solution 1
If I understand you correctly:
$(currentDiv).contents().addBack('.foo').css('color','red');
I renamed the "div" to "currentDiv" for clarity. This selects the current element and all of the elements it contains, then filters out the ones that do not have class foo
and applies the style to the remainder, i.e., the ones that do have class foo
.
EDIT A slight optimization
$(currentDiv).find('.foo').addBack('.foo').css('color','red');
EDIT
This answer has been updated to incorporate newer jQuery methods. It was originally
$(currentDiv).find('.foo').andSelf().filter('.foo').css('color','red');
which is still required for jQuery older than 1.8
Solution 2
jQuery 1.8 introduced .addBack(), which takes a selector, in favor of .andSelf().So tvanfosson's code becomes much more efficient as
$(currentDiv).find(".foo").addBack(".foo").css("color", "red");
If you didn't have that, I think that
$(currentDiv).find(".foo").add(currentDiv.filter(".foo")).css("color", "red");
would be pretty efficient, if not very pretty.
Solution 3
Andrew's answer was so useful and the most efficient of all the answers (from jQuery 1.8 onward), so I did as Sam suggested and turned it into a trivial jQuery extension method for everyone to use:
Extension code:
jQuery.fn.findAndSelf = function (selector){
return this.find(selector).addBack(selector);
};
use like this:
$(function(){
$('#obj').findAndSelf('.foo').css('color', 'red');
});
JSFiddle: http://jsfiddle.net/BfEwK/
Full credit to Andrew for suggesting addBack()
as the best option (as at this date). Have upvoted him accordingly and suggest everyone do the same.
Solution 4
Barring a nicer solution, I've created a new function and use it instead of $:
var _$ = function(expr, parent){
return $(parent).is(expr) ? $(expr, parent).add(parent) : $(expr, parent);
}
Related videos on Youtube
Sam
Updated on October 28, 2020Comments
-
Sam over 3 years
Consider the following HTML:
<div class="foo" id="obj"> I should be changed red <div class="bar" style="color:black;"> I should not be changed red. <div class="foo">I should be changed red.</div> </div> </div>
Given a DOM element
obj
and an expression, how do I go about selecting any children and possiblyobj
? I'm looking for something similar to "select descendants" but also including the parent, if it matches the expression.var obj = $("#obj")[0]; //wrong, may include siblings of 'obj' $(".foo", $(obj).parent()).css("color", "red"); //wrong -- excludes 'obj' $(".foo", obj).css("color", "red"); //correct way, but it's annoying var matches = $(".foo", obj); if ($(obj).is(".foo")) matches = matches.add(obj); matches.css("color", "red");
Is there a more elegant solution to this?
-
Gone Coding almost 10 years+1: Great question. Just hit this situation today. Have taken Andrew's answer and your comment and added a trivial jQuery
findAndSelf
extension as you suggested for everyone to use. Cheers.
-
-
Sam over 15 yearsThis would select all .foo in the document, and all children of .foo
-
rz. over 15 yearsRight... I thought that's what you meant.
-
Sam over 15 yearsAhh, sorry, I've clarified the question.
-
rz. over 15 yearsOk now the answer is: all divs of class foo and all their children. Satisfactory?
-
Sam over 15 yearsThe answer is "all children of [some object] that match [expression] as well as [some object] if it matches [expression]"
-
Sam over 15 yearsAh, thank you... the "andSelf()" is what I was missing. Unfortunately this method is ineffecient... all of the children and found and then all are traversed to be filtered, rather than just a single pass.
-
Gone Coding almost 10 yearsNo. They only want the parent element selected if it also has
.foo
, but yours just includes it. -
Gone Coding almost 10 yearsThis will "work", but only because they happened to all be
divs
in the example. The question was how to include an initial element (if it matches) along with any descendants (that also match). What if there were more.foo
s outside of#obj
? They would also be included (which is not the desired behavior). -
Gone Coding almost 10 yearsThis is still slightly less efficient than
addback
(JQ 1.8 onward) as this runs thefilter
a second time on the descendants even though they all already match. -
Gone Coding almost 10 yearsHave applied your
findAndSelf
suggestion (good name) to Andrew's answer instead and posted for all to cut & paste. -
Gone Coding almost 10 yearsDefinitely preferred from jQuery 1.8. Have added your suggestion as a jQuery
findAndSelf
extension method below. Turned out very clean usingaddBack
, full credit to you. Cheers :) -
dsdsdsdsd over 9 years
Note: This function has been deprecated and is now an alias for .addBack(), which should be used with jQuery 1.8 and later
-
The Dembinski over 7 yearsHow has nobody seemingly noticed this. You deserve a hug and a high-five.
-
Gone Coding over 7 years@TheDembinski: Hug accepted with thanks (I don't do high 5's however) :)