jQuery OR Selector?

325

Me pregunto si hay una manera de tener la lógica "OR" en los selectores jQuery. Por ejemplo, sé que un elemento es un descendiente de un elemento con clase classA o classB, y quiero hacer algo así elem.parents('.classA or .classB'). ¿JQuery proporciona dicha funcionalidad?

Suan
fuente

Respuestas:

494

Usa una coma.

'.classA, .classB'

Puede optar por omitir el espacio.

Daniel A. White
fuente
43
Cabe señalar que esto no es realmente un selector 'o', más como múltiples selectores en uno.
alex
49
@alex: pero no seleccionará el mismo elemento dos veces (lo que haría un operador de concatenación). Realmente es un selector OR porque crea una UNIÓN de dos o más conjuntos (mientras que AND es una intersección).
cletus
Gracias, eso funciona. Debido a una supervisión de depuración, pensé que usar una coma significa 'Y'.
Suan
38
ANDsería .classA.classB.
Daniel A. White
2
De hecho, depende de lo que la pregunta original implicaba ... es decir: clásicamente, un operador 'o' cortocircuitará. Por lo tanto, un operador 'o' en lenguaje jerárquico, posiblemente también podría provocar un cortocircuito.
Mateo
71

El uso de una coma puede no ser suficiente si tiene varios objetos jQuery que deben unirse.

El método .add () agrega los elementos seleccionados al conjunto de resultados:

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

Es más detallado que '.classA, .classB', pero le permite crear selectores más complejos como el siguiente:

// (classA which has <p> descendant) OR (<div> ancestors of classB)
jQuery('.classA').has('p').add(jQuery('.classB').parents('div'));
Montaña
fuente
22

He escrito un complemento increíblemente simple (5 líneas de código) para exactamente esta funcionalidad:

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

Le permite decir efectivamente "obtenga este elemento, o si ese elemento no existe, use este elemento". Por ejemplo:

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

Si bien la respuesta aceptada proporciona una funcionalidad similar a esta, si existen ambos selectores (antes y después de la coma), se devolverán ambos selectores.

Espero que sea útil para cualquiera que pueda acceder a esta página a través de Google.

Por Richard Powell
fuente
44
Así no funciona el operador OR booleano. Si ambos selectores devuelven elementos, el operador OR debe devolverlos todos y no solo los elementos del primer selector. Su complemento debe llamarse "ifEmpty" o "else" o algo así.
Alp
13
@Alp: Considere el comportamiento de "a" || "b"vs. null || "b"en vanilla JS. Si aplicamos el mismo comportamiento aquí, $(a).or(b)debería regresar $(a)si existe, de lo contrario debería regresar $(b). No creo que haya nada malo con esta nomenclatura, ya que "o" coincide con el comportamiento de JS "||" (o) operador.
FtDRbwLXw6
44
También lo veo como un or. De lo que otros están hablando es más como una concato mergeacción.
Léon Pelletier
1
Personalmente, no llamaría a esto "o", ya que puede generar confusión (incluso si técnicamente puede ser correcto, ya que es un tipo especial de si / o). Esto es efectivamente una fusión nula, que se llama cosas diferentes y tiene diferentes operadores en diferentes idiomas: en.wikipedia.org/wiki/Null_coalescing_operator
JanErikGunnar
El término 'xor' (exclusivo o) sería el término exacto, pero a menudo las personas buscan o cuando buscan xor, ya que xor generalmente es, en términos comunes, un tipo específico de 'o'.
liljoshu el
17

Si está buscando usar la construcción estándar de element = element1 || element2 donde JavaScript devolverá el primero que sea verdadero, podría hacer exactamente eso:

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

que devolvería el primer elemento que se encuentre realmente. Pero una mejor manera probablemente sería usar la construcción de coma del selector jQuery (que devuelve una matriz de elementos encontrados) de esta manera:

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

que devolverá el primer elemento encontrado.

Lo uso de vez en cuando para encontrar un elemento activo en una lista o algún elemento predeterminado si no hay un elemento activo. Por ejemplo:

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

que devolverá cualquier li con una clase de activo o, si no hubiera ninguno, solo devolverá el último li.

Cualquiera de los dos funcionará. Sin embargo, existen posibles sanciones de rendimiento, ya que || detendrá el procesamiento tan pronto como encuentre algo verdadero, mientras que el enfoque de matriz intentará encontrar todos los elementos, incluso si ya ha encontrado uno. Por otra parte, utilizando el || La construcción podría tener problemas de rendimiento si tiene que pasar por varios selectores antes de encontrar el que devolverá, ya que tiene que llamar al objeto jQuery principal para cada uno (realmente no sé si esto es un golpe de rendimiento o no, simplemente parece lógico que pueda ser). Sin embargo, en general, uso el enfoque de matriz cuando el selector es una cadena bastante larga.

Ken Dickinson
fuente
Creo que find ('. SomethingToBeFound, .somethingElseToBeFound') no es lo mismo que || construir. Porque encontrar si .somethingElseToBeFound está en DOM antes de .somethingToBeFound, se devolverá incluso si existe .somethingToBeFound.
remo
0

Finalmente encontré hackear cómo hacerlo:

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

(selecciona div con clase classAOR classBcon intervalo secundario directo)

Midlan
fuente
-2

Daniel A. White Solution funciona muy bien para las clases.

Tengo una situación en la que tuve que encontrar campos de entrada como donee_1_card donde 1 es un índice.

Mi solución ha sido

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

Aunque no estoy seguro de lo óptimo que es.

FDussault
fuente