views:

1352

answers:

4

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");

Just curious if there's a more elegant solution to this...

A: 
 $('div.foo, div.foo > *').css('color','red');

The main idea is that you can separate different rules to match on by commas. Just like in css. As far as I know everything here is supoprted by jquery and can be "ORed" by comma-separating.

rz
This would select all .foo in the document, and all children of .foo
Sam
Right... I thought that's what you meant.
rz
Ahh, sorry, I've clarified the question.
Sam
Ok now the answer is: all divs of class foo and all their children. Satisfactory?
rz
The answer is "all children of [some object] that match [expression] as well as [some object] if it matches [expression]"
Sam
A: 

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); 
}
Sam
I think I'll just use this and extend jQuery to make it "findAndSelf()" or something like that.
Sam
A: 

Doesn't this do what you want (unless I misunderstand...)

$(document).ready(function(){
 $("div.foo").css("color", "red");
});
cLFlaVA
+2  A: 

If I understand you correctly:

$(currentDiv).contents().andSelf().filter('.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').andSelf().filter('.foo').css('color','red');
tvanfosson
Ah, 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.
Sam