jQuery select descendants, including the parent

Sam picture Sam · Dec 13, 2008 · Viewed 12.3k times · Source

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 possibly obj? 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?

Answer

tvanfosson picture tvanfosson · Dec 13, 2008

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