Welcher JQuery-Selektor schließt Elemente mit einem übergeordneten Element aus, das einem bestimmten Selektor entspricht?

72

ich habe

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

um alle Elemente auszuwählen, deren Klassen entweder foooder sind barund die nicht von einem Element abstammen, dessen Klasse ist baz. Gibt es einen Selektor, der dasselbe erreicht, ohne dass ein Filter-Lambda erforderlich ist?

<div class='foo'/><!--match this-->
<div class='bar'/><!--match this-->
<div class='baz'>
    <div class='foo'/> <!--don't match this-->
</div>
Dan Davies Brackett
quelle
2
Sie können die closestMethode verwenden, anstatt parentssie schneller zu machen. closesthört auf zu suchen, sobald ein übereinstimmendes Element gefunden wurde, während parentsder DOM-Baum zum Stammelement des Dokuments hochgerechnet wird, um übereinstimmende Elemente zu finden.
RayOnAir

Antworten:

79

Die Wahrheit ist, dass jQuery einfach keine besonders elegante Möglichkeit hat, das zu tun, was Sie wollen. Während die Antwort von Chaos funktioniert, müssen Sie sich fragen, ob sich der komplizierte Selektor (der ungefähr so ​​langsam wäre wie ein Selektor auf einer komplizierten Webseite) für die ausführlichere, aber schnellere Filterfunktion lohnt. Das ist nicht wirklich eine große Sache, ich persönlich bin es besonders leid, besonders lange, verschlungene Selektoren zu haben, wenn ich es vermeiden kann.

Eine andere Möglichkeit besteht darin, einen eigenen Selektor zu erstellen, da jQuery fantastisch ist:

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

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

Die exprKarte ist Teil der Sizzle Selector Engine. Die Dokumentation finden Sie hier: Sizzle Custom Pseudo-Selectors

Paolo Bergantino
quelle
Akzeptieren, weil es vollständiger ist als Chaos. Wo finde ich die Dokumentation zur API für das expr-Array?
Dan Davies Brackett
Soweit ich weiß, gibt es eigentlich keine.
Paolo Bergantino
10
Das ist ordentlich, obwohl ich denke, ich könnte den Ausdrucksnamen in noparents ändern, da dies beschreibt, was es ein bisschen besser macht.
Matt Sach
Der Link zu dieser JSBin stimmt nicht mit der Antwort überein. Es ist eine Weile her, also muss die URL recycelt worden sein.
Gfullam
Ich habe einen Verweis auf die Dokumentation exprzu dieser Antwort hinzugefügt .
Matpie
31
$('.foo:not(.baz .foo),.bar:not(.baz .bar)')
Chaos
quelle
18

Ich konnte das nicht zum Laufen bringen:

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

Aber ich kann das zum Laufen bringen:

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

Hinweis: Ich bin mir nicht sicher, ob dies etwas mit der von mir verwendeten jQuery-Version 1.2.6 zu tun hat

gehen
quelle
Verwenden $().not()ist die einfachste Lösung. Und ist gut dokumentiert , um genau das zu tun, was gefragt wurde.
Peter
4

Probier diese:

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

Das Selektor- Chaos sollte funktionieren:

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

Ich wollte Ihnen nur einen Tipp zu einer Erweiterung von FireBug namens FireFinder geben , mit der Sie Ihre CSS- / JQuery-Selektoren testen können.

Von der Website: Firefinder ist eine Erweiterung von Firebug (in Firefox) und bietet die Funktionalität, auf schnelle Weise HTML-Elemente zu finden, die mit ausgewählten CSS-Selektoren oder XPath-Ausdrücken übereinstimmen. Sie können Ihre CSS-Selektoren auf der Seite sofort testen und gleichzeitig den Inhalt anzeigen. Übereinstimmende Elemente werden hervorgehoben.

BengtBe
quelle
1

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

Ich verwende das Roots-Thema und sie ändern die Dropdowns von "Untermenü" in ".dropdown-Menü".

Devin Walker
quelle
0

Fügen Sie Ihrem Selektor der obersten Ebene ein: not ('. Baz') hinzu.

Dave Ward
quelle