views:

1003

answers:

5

I have

var $set = $('.foo,.bar').filter(
    function() {return $(this).parents('.baz').length < 1;});

as a way to select all the elements whose classes are either foo or bar and who do not descend from an element whose class is baz. Is there a selector that will accomplish the same thing without the need for a filtering lambda?

<div class='foo'/><!--match this-->
<div class='bar'/><!--match this-->
<div class='baz'>
    <div class='foo'/> <!--don't match this-->
</div>
+1  A: 
$('.foo:not(.baz .foo),.bar:not(.baz .bar)')
chaos
+1  A: 

Add a :not('.baz') to your top level selector.

Dave Ward
A: 

The selector chaos gives should work:

$('.foo:not(.baz .foo),.bar:not(.baz .bar)')

Just wanted to give you a tip about an extension to FireBug called FireFinder that you can use to test your css/jquery selectors.

From the website: Firefinder is an extension to Firebug (in Firefox) and offers the functionality to, in a quick way, find HTML elements matching chosen CSS selector(s) or XPath expression. It allows you to instantly test your CSS selectors in the page while seeing the content at the same time, and matching elements will be highlighted.

BengtBe
+3  A: 

The truth of the matter is that jQuery simply does not have a particularly elegant way to do what you want. While chaos' answer does work, you have to wonder whether the complicated selector (that would be about as slow as a selector can be in a complicated webpage) is worth it over the more verbose but faster filter function you have. This is not really that big of a deal, I am just personally weary of particularly long, convoluted selectors when I can avoid it.

A different option is to create your own selector, since jQuery is awesome:

jQuery.expr[':'].parents = function(a,i,m){
    return jQuery(a).parents(m[3]).length < 1;
};

$('.foo,.bar').filter(':parents(.baz)');

Tested and works.

Paolo Bergantino
accepting because it's more complete than chaos' - where do I find the documentation on the API for the expr array?
DDaviesBrackett
There's not really any, as far as I know.
Paolo Bergantino
This answer solved a similar problem for me. +1
friedo
+1  A: 

I couldn't get this to work:

$(".children:not(#parent .children)");

But I can get this to work:

$(".children").not($("#parent .children"));

Note: Not sure if this has something to do with the jQuery version I'm using 1.2.6

xiaohouzi79