jQuery OU seletor?

325

Eu estou querendo saber se existe uma maneira de ter lógica "OU" nos seletores de jQuery. Por exemplo, eu sei que um elemento é um descendente de um elemento com a classe classA ou classB, e quero fazer algo assim elem.parents('.classA or .classB'). O jQuery fornece essa funcionalidade?

Suan
fonte

Respostas:

494

Use vírgula.

'.classA, .classB'

Você pode optar por omitir o espaço.

Daniel A. White
fonte
43
Deve-se notar que esse não é realmente um seletor 'ou', mais como vários seletores em um.
Alex
49
@alex: mas ele não seleciona o mesmo elemento duas vezes (o que um operador de concatenação faria). É realmente um seletor OR porque cria uma UNIÃO de dois ou mais conjuntos (enquanto AND é uma interseção).
Cletus
Obrigado, isso funciona. Por causa de uma supervisão de depuração, pensei que usar vírgula significa 'AND'.
Suan
38
ANDseria .classA.classB.
Daniel A. White
2
Na verdade, depende do que a pergunta original implicava ... ou seja: classicamente um operador 'ou' entrará em curto-circuito. Assim, um operador 'ou' na linguagem jquery também poderia entrar em curto-circuito.
Mathew
71

Usar uma vírgula pode não ser suficiente se você tiver vários objetos jQuery que precisam ser unidos.

O método .add () adiciona os elementos selecionados ao conjunto de resultados:

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

É mais detalhado que '.classA, .classB', mas permite criar seletores mais complexos, como o seguinte:

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

Eu escrevi um plugin incrivelmente simples (5 linhas de código) para exatamente essa funcionalidade:

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

Ele permite que você efetivamente diga "obtenha esse elemento ou, se esse elemento não existir, use esse elemento". Por exemplo:

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

Embora a resposta aceita forneça uma funcionalidade semelhante a esta, se os dois seletores (antes e depois da vírgula) existirem, ambos os seletores serão retornados.

Espero que seja útil para qualquer pessoa que possa acessar esta página via google.

Por Richard Powell
fonte
4
Não é assim que o operador OR booleano funciona. Se os dois seletores retornarem elementos, o operador OR deve retornar todos eles e não apenas os elementos do primeiro seletor. Seu plugin deve ser nomeado "ifEmpty" ou "else" ou algo parecido.
Alp
13
@ Alp: considere o comportamento de "a" || "b"vs. null || "b"na baunilha JS. Se aplicarmos o mesmo comportamento aqui, $(a).or(b)deve retornar $(a)se existir, caso contrário, deve retornar $(b). Não acho que haja algo errado com essa nomenclatura, pois o "ou" corresponde ao comportamento do JS "||" (ou) operador.
FTDRbwLXw6 #
4
Eu também vejo isso como um or. Que outros estão falando é mais como um concatou mergeação.
Léon Pelletier
1
Pessoalmente, eu não chamaria isso de "ou", pois isso pode causar confusão (mesmo que tecnicamente esteja correto, pois é um tipo especial de se / ou). Isso é coalescência efetivamente nula, que é chamada de coisas diferentes e tem operadores diferentes em diferentes idiomas: en.wikipedia.org/wiki/Null_coalescing_operator
JanErikGunnar
O termo 'xor' (exclusivo ou) seria o termo exato, mas geralmente as pessoas pesquisam ou procuram xor, pois xor é geralmente, em termos comuns, um tipo específico de 'ou'.
liljoshu
17

Se você deseja usar a construção padrão de element = element1 || element2, em que o JavaScript retornará o primeiro verdadeiro, você pode fazer exatamente isso:

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

que retornaria o primeiro elemento encontrado. Mas uma maneira melhor provavelmente seria usar a construção de vírgula do seletor jQuery (que retorna uma matriz de elementos encontrados) desta maneira:

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

que retornará o primeiro elemento encontrado.

Eu uso isso de tempos em tempos para encontrar um elemento ativo em uma lista ou algum elemento padrão, se não houver um elemento ativo. Por exemplo:

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

que retornará qualquer li com uma classe de ativo ou, se não houver, retornará apenas o último li.

Qualquer um vai funcionar. Existem possíveis penalidades de desempenho, pois o || interromperá o processamento assim que encontrar algo verdadeiro, enquanto a abordagem de matriz tentará encontrar todos os elementos, mesmo que já tenha encontrado um. Então, novamente, usando o || o construto pode ter problemas de desempenho se precisar passar por vários seletores antes de encontrar o que retornará, porque ele deve chamar o objeto principal do jQuery para cada um (eu realmente não sei se esse é um problema de desempenho ou não, parece lógico que poderia ser). Em geral, porém, eu uso a abordagem de matriz quando o seletor é uma string bastante longa.

Ken Dickinson
fonte
Eu acho que find ('. SomethingToBeFound, .sething SomethingseseBoundFound') não é o mesmo que || construir. Como localize se .somethingElseToBeFound está no DOM antes de .somethingToBeFound, ele será retornado mesmo que exista .somethingToBeFound.
remo
0

Finalmente eu encontrei o hack como fazê-lo:

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

(seleciona div com classe classAOR classBcom span filho direto)

Midlan
fonte
-2

Daniel A. White Solution funciona muito bem para as aulas.

Eu tenho uma situação em que tive que encontrar campos de entrada como donee_1_card em que 1 é um índice.

Minha solução foi

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

Embora eu não tenha certeza de quão ideal é.

FDussault
fonte