What JQuery selector excludes items with a parent that matches a given selector?

JqueryJquery SelectorsCss Selectors

Jquery Problem Overview


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>

Jquery Solutions


Solution 1 - Jquery

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

The expr map is part of the Sizzle selector engine and documentation can be found here: Sizzle Custom Pseudo-Selectors

Solution 2 - Jquery

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

Solution 3 - Jquery

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

Solution 4 - Jquery

try this one:

$('div').filter(function () {
  return ($(this).parent().not('.baz'));
})

Solution 5 - Jquery

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.

Solution 6 - Jquery

var $li = jQuery('li', this).not('.dropdown-menu > li');

I'm using Roots theme and they change the dropdowns from 'sub-menu' to '.dropdown-menu'

Solution 7 - Jquery

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDan Davies BrackettView Question on Stackoverflow
Solution 1 - JqueryPaolo BergantinoView Answer on Stackoverflow
Solution 2 - JquerychaosView Answer on Stackoverflow
Solution 3 - JquerygoingView Answer on Stackoverflow
Solution 4 - JquerySebastian ViereckView Answer on Stackoverflow
Solution 5 - JqueryBengtBeView Answer on Stackoverflow
Solution 6 - JqueryDevin WalkerView Answer on Stackoverflow
Solution 7 - JqueryDave WardView Answer on Stackoverflow