jQuery OU Selector?

325

Je me demande s'il existe un moyen d'avoir une logique "OU" dans les sélecteurs jQuery. Par exemple, je sais qu'un élément est soit un descendant d'un élément avec la classe classA ou classB, et je veux faire quelque chose comme elem.parents('.classA or .classB'). JQuery fournit-il une telle fonctionnalité?

Suan
la source

Réponses:

494

Utilisez une virgule.

'.classA, .classB'

Vous pouvez choisir d'omettre l'espace.

Daniel A. White
la source
43
Il convient de noter que ce n'est pas vraiment un sélecteur «ou», plus comme plusieurs sélecteurs en un.
alex
49
@alex: mais il ne sélectionnera pas deux fois le même élément (ce que ferait un opérateur de concaténation). Il s'agit vraiment d'un sélecteur OU car il crée une UNION de deux ensembles ou plus (alors que ET est une intersection).
cletus le
Merci, ça marche. En raison d'une erreur de débogage, j'ai pensé que l'utilisation d'une virgule signifie «ET».
Suan
38
ANDserait .classA.classB.
Daniel A. White
2
Cela dépend en fait de ce que la question initiale impliquait ... c'est-à-dire: classiquement, un opérateur "ou" court-circuitera. Ainsi, un opérateur «ou» dans le langage jquery pourrait également court-circuiter.
Mathew
71

L'utilisation d'une virgule peut ne pas être suffisante si vous avez plusieurs objets jQuery qui doivent être joints.

La méthode .add () ajoute les éléments sélectionnés au jeu de résultats:

// classA OR classB
jQuery('.classA').add('.classB');

Il est plus verbeux que '.classA, .classB', mais vous permet de créer des sélecteurs plus complexes comme celui-ci:

// (classA which has <p> descendant) OR (<div> ancestors of classB)
jQuery('.classA').has('p').add(jQuery('.classB').parents('div'));
Alp
la source
22

J'ai écrit un plugin incroyablement simple (5 lignes de code) pour exactement cette fonctionnalité:

http://byrichardpowell.github.com/jquery-or/

Il vous permet de dire efficacement "obtenez cet élément, ou si cet élément n'existe pas, utilisez cet élément". Par exemple:

$( '#doesntExist' ).or( '#exists' );

Bien que la réponse acceptée offre des fonctionnalités similaires à celle-ci, si les deux sélecteurs (avant et après la virgule) existent, les deux sélecteurs seront retournés.

J'espère que cela s'avérera utile à tous ceux qui pourraient atterrir sur cette page via google.

Par Richard Powell
la source
4
Ce n'est pas ainsi que fonctionne l'opérateur booléen OR. Si les deux sélecteurs renvoient des éléments, l'opérateur OR doit tous les renvoyer et pas seulement les éléments du premier sélecteur. Votre plugin doit être nommé "ifEmpty" ou "else" ou quelque chose comme ça.
Alp
13
@Alp: Considérez le comportement de "a" || "b"vs. null || "b"dans vanilla JS. Si nous appliquons le même comportement ici, $(a).or(b)devrait retourner $(a)s'il existe, sinon il devrait revenir $(b). Je ne pense pas qu'il y ait quelque chose de mal avec cette nomenclature, car le "ou" correspond au comportement du JS "||" (ou) opérateur.
FtDRbwLXw6
4
Je le vois aussi comme un or. Ce dont les autres parlent est plus comme une action concatou merge.
Léon Pelletier
1
Personnellement, je n'appellerais pas cela "ou", car cela peut prêter à confusion (même si cela peut être techniquement correct car il s'agit d'un type spécial de si / ou). Il s'agit en fait d'une coalescence nulle, qui s'appelle des choses différentes et a différents opérateurs dans différentes langues: en.wikipedia.org/wiki/Null_coalescing_operator
JanErikGunnar
Le terme 'xor' (exclusif ou) serait le terme exact, mais souvent les gens recherchent ou recherchent xor, car xor est généralement, en termes courants, un type spécifique de 'ou'.
liljoshu
17

Si vous cherchez à utiliser la construction standard de element = element1 || element2 où JavaScript retournera le premier qui est véridique, vous pouvez faire exactement cela:

element = $('#someParentElement .somethingToBeFound') || $('#someParentElement .somethingElseToBeFound');

qui retournerait le premier élément réellement trouvé. Mais une meilleure façon serait probablement d'utiliser la construction virgule du sélecteur jQuery (qui renvoie un tableau d'éléments trouvés) de cette façon:

element = $('#someParentElement').find('.somethingToBeFound, .somethingElseToBeFound')[0];

qui renverra le premier élément trouvé.

Je l'utilise de temps en temps pour trouver un élément actif dans une liste ou un élément par défaut s'il n'y a pas d'élément actif. Par exemple:

element = $('ul#someList').find('li.active, li:first')[0] 

qui renverra tout li avec une classe d'actif ou, s'il n'y en a pas, renverra simplement le dernier li.

Soit fonctionnera. Il existe cependant des pénalités de performance potentielles, car le || arrêtera le traitement dès qu'il trouvera quelque chose de véridique alors que l'approche tableau essaiera de trouver tous les éléments même s'il en a déjà trouvé un. Là encore, en utilisant le || La construction peut potentiellement avoir des problèmes de performances si elle doit passer par plusieurs sélecteurs avant de trouver celui qu'elle renverra, car elle doit appeler l'objet jQuery principal pour chacun (je ne sais vraiment pas s'il s'agit d'un résultat de performance ou non, il semble juste logique que cela puisse être). En général, cependant, j'utilise l'approche tableau lorsque le sélecteur est une chaîne assez longue.

Ken Dickinson
la source
Je pense que find ('. SomethingToBeFound, .somethingElseToBeFound') n'est pas identique à || construction. Parce que trouver si .somethingElseToBeFound est dans DOM avant .somethingToBeFound, il serait retourné même si .somethingToBeFound existe.
remo
0

Enfin, j'ai trouvé comment faire:

div:not(:not(.classA,.classB)) > span

(sélectionne div avec classe classAOU classBavec portée enfant directe)

midlan
la source
-2

Daniel A. White Solution fonctionne très bien pour les cours.

J'ai une situation où j'ai dû trouver des champs de saisie comme donee_1_card où 1 est un index.

Ma solution a été

$("input[name^='donee']" && "input[name*='card']")

Bien que je ne sais pas à quel point c'est optimal.

FDussault
la source