Selecionar elemento pela correspondência exata de seu conteúdo

160

Tudo bem, gostaria de saber se existe uma maneira de fazer o :contains()seletor do jQuery selecionar elementos apenas com a string digitada.

por exemplo -

<p>hello</p>
<p>hello world</p>

$('p:contains("hello")').css('font-weight', 'bold');

O seletor selecionará os dois pelementos e os tornará em negrito, mas quero que selecione apenas o primeiro.

juliano
fonte
Bem, você pode substituir o :containsseletor por seu próprio código, mas não acho que seja isso que você quis dizer?
Blazemonger 12/03
Você pode definir um seletor personalizado: stackoverflow.com/questions/12244929/…
BLSully:
Possível duplicata de: Seletor de Jquery, contém para iguais
BinaryTox1n 12/12
possível duplicação do link Selecionar por texto (correspondência exata)
FishBasketGordo 12/13

Respostas:

214

Não, não há seletor jQuery (ou CSS) que faça isso.

Você pode usar facilmente filter:

$("p").filter(function() {
    return $(this).text() === "hello";
}).css("font-weight", "bold");

Não é um seletor , mas faz o trabalho. :-)

Se você deseja lidar com espaços em branco antes ou depois do "olá", você pode inserir um $.trim:

return $.trim($(this).text()) === "hello";

Para os otimizadores prematuros por aí, se você não se importa que ele não corresponda <p><span>hello</span></p>e similar, você pode evitar as chamadas $e textusando innerHTMLdiretamente:

return this.innerHTML === "hello";

... mas você teria que ter muitos parágrafos para que isso importasse, tantos que você provavelmente teria outros problemas primeiro. :-)

TJ Crowder
fonte
7
Também pode querer $.trimqualquer espaço em branco perdido antes de fazer a comparação.
Blazemonger 12/03
Por alguma razão, tive que usar "==" para que isso funcionasse, em vez de "===".
Stephan
3
@ Stephan: Se você estivesse comparando com um número, teria que usar ==( == 2) ou colocar o número em uma string ( === "2"), porque o valor obtido text()ou innerHTMLsempre é uma string. Se você estava comparando com uma string, não importa se você usa ==ou ===.
TJ Crowder
É uma pena que o jQuery tenha implementado, :containsque é bem mais complexo, mas não implementou um seletor para a correspondência exata do texto. = {
Paulo Bueno
54

Tente adicionar uma função de extensão pseudo:

$.expr[':'].textEquals = $.expr.createPseudo(function(arg) {
    return function( elem ) {
        return $(elem).text().match("^" + arg + "$");
    };
});

Então você pode fazer:

$('p:textEquals("Hello World")');
Amadu Bah
fonte
2
grande solução: pouco além: para se certificar de que você não substituir um expr existente, eu faria:$.expr[':'].textEquals = $.expr[':'].textEquals || $.expr.createPseudo(function(arg) {
Mischa Molhoek
9

Você pode usar a função filter () do jQuery para conseguir isso.

$("p").filter(function() {
// Matches exact string   
return $(this).text() === "Hello World";
}).css("font-weight", "bold");
dsgriffin
fonte
9

Então a resposta de Amandu funciona principalmente. No entanto, ao usá-lo na natureza, encontrei alguns problemas em que coisas que eu esperava encontrar não estavam sendo encontradas. Isso ocorre porque, às vezes, há espaços em branco aleatórios ao redor do texto do elemento. É minha convicção que, se você estiver pesquisando "Hello World", ainda assim desejará que ele corresponda a "Hello World" ou mesmo "Hello World \ n". Assim, acabei de adicionar o método "trim ()" à função, que remove os espaços em branco circundantes, e começou a funcionar melhor.

Especificamente...

$.expr[':'].textEquals = function(el, i, m) {
    var searchText = m[3];
    var match = $(el).text().trim().match("^" + searchText + "$")
    return match && match.length > 0;
}

Além disso, observe que esta resposta é extremamente semelhante a Selecionar link por texto (correspondência exata)

E a nota secundária ... trimremove apenas os espaços em branco antes e depois do texto pesquisado. Não remove espaços em branco no meio das palavras. Acredito que esse seja um comportamento desejável, mas você pode mudar isso se quiser.

bwest87
fonte
5

Eu encontrei uma maneira que funciona para mim. Não é 100% exato, mas elimina todas as strings que contêm mais do que apenas a palavra que estou procurando, porque verifico se a string não contém espaços individuais também. A propósito, você não precisa desses "". O jQuery sabe que você está procurando uma string. Verifique se você possui apenas um espaço na parte: contains (), caso contrário não funcionará.

<p>hello</p>
<p>hello world</p>
$('p:contains(hello):not(:contains( ))').css('font-weight', 'bold');

E sim, eu sei que não vai funcionar se você tiver coisas como <p>helloworld</p>

rf1234
fonte
1
Uso inteligente de correspondências simples com contém (..) sem usar um filtro ou extensão! Não funcionará em nada que exija espaço no primeiro conteúdo (..), mas tente encontrar uma solução para isso. Obrigado!
30718 JoePC
3

Como TJ Crowder afirmou acima, a função de filtro faz maravilhas. Não estava funcionando para mim no meu caso específico. Eu precisava pesquisar várias tabelas e suas respectivas tags td dentro de uma div (neste caso, uma caixa de diálogo jQuery).

$("#MyJqueryDialog table tr td").filter(function () {
    // The following implies that there is some text inside the td tag.
    if ($.trim($(this).text()) == "Hello World!") {
       // Perform specific task.
    }
});

Espero que isso seja útil para alguém!

Greg A
fonte
Eu sou muito novo no jquery, mas acho que seria um pouco melhor usar each () em vez de filter (), pois o objetivo do filtro é retornar um subarray. Mas inspirou a solução definitivamente, como eu tive os mesmos problemas :)
JeopardyTempest
0

Um one-liner que trabalha com bibliotecas alternativas ao jQuery:

$('p').filter((i, p) => $(p).text().trim() === "hello").css('font-weight', 'bold');

E isso é equivalente ao a:contains("pattern")seletor de um jQuery :

var res = $('a').filter((i, a) => $(a).text().match(/pattern/));
leogama
fonte
-4

O .first () ajudará aqui

$('p:contains("hello")').first().css('font-weight', 'bold');
tymeJV
fonte
Claro ... neste caso específico. e se o pedido não for conhecido no momento do desenvolvimento?
BLSully