Selecione o link por texto (correspondência exata)

89

Usando jQuery, quero selecionar um link que contém exatamente algum tipo de texto. Por exemplo:

<p><a>This One</a></p>
<p><a>"This One?"</a></p>
<p><a>Unlikely</a></p>

Eu tentei isso:

$('a:contains("This One")')

Mas ele escolhe o primeiro E o segundo link. Eu só quero o primeiro link, que contém exatamente "Este". Como eu posso fazer isso?

Endy Tjahjono
fonte
Possível duplicata do elemento Select com base no conteúdo de texto EXATO
Steve Chambers

Respostas:

138

Você consegue fazer isso:

$('a').filter(function(index) { return $(this).text() === "This One"; });

Referência: http://api.jquery.com/filter/

FishBasketGordo
fonte
5
Qualquer um funcionaria neste caso, mas eu tendo a usar === porque ele combina com valor e tipo, ou seja, não coagirá os tipos. stackoverflow.com/questions/359494/…
FishBasketGordo
1
Você errou return. Tenho que mudar parafunction(index) { return (this.text === 'This One') }
Endy Tjahjono
Além disso, você pode verificar o comprimento do texto.
bestinamir
39

Um colega meu estendeu o jQuery com uma função para fazer isso:

$.expr[':'].textEquals = function(a, i, m) {
    return $(a).text().match("^" + m[3] + "$");
};

O resultado é que você pode selecionar algo pelo texto exato desta forma:

$("label:textEquals('Exact Text to Match')");

Isso torna mais fácil, pois você não precisa se lembrar da sintaxe exata todas as vezes. Sua postagem inteira está aqui: jQuery Custom Selector para selecionar elementos pelo texto exato: textEquals

Narniano
fonte
28

Para expandir a resposta da FishBasketGordo. Se você estiver tentando fazer a seleção em uma grande quantidade de elementos, use :contains()primeiro para restringir e depois aplique o filtro.

Isso vai melhorar a velocidade geral:

$('a:contains("This One")').filter(function(index)
{
    return $(this).text() === "This One";
});
Djhansel
fonte
Votado por velocidade / eficiência. Além disso, evita a necessidade de espaços $ .trim () dentro de .filter (..).
JoePC
8

teve que modificar a solução de Nariman para ser:

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

Caso contrário, não funcionou no Chrome (Linux)

Arqueiro
fonte
6

Eu estava usando a extensão

$.expr[':'].textEquals

Mas descobri que a implementação não funciona mais com jQuery 1.7 (aparentemente uma mudança em Sizzla.filter). Depois de lutar por algum tempo para fazê-lo funcionar, simplesmente escrevi um plugin jQuery para fazer o mesmo.

$.fn.textEquals = function (text) {
    var match = false;
    $(this).each(function () {
        if ($(this).text().match("^" + escapeRegex(text) + "$")) {
            match = true;
            return false;
        }
    });
    return match;
};

Usar:

$(".ui-autocomplete li").textEquals('Exact Text to Match');

Só queria compartilhar, caso outra pessoa se depare com isso (,

Alvis
fonte
3

Portanto, a resposta de Narnian funciona muito bem. Usando-o em estado selvagem, no entanto, me deparei com alguns problemas, em que coisas que eu esperava encontrar não estavam sendo encontradas. Isso acontecia porque às vezes há um espaço em branco aleatório em torno do texto do elemento. Acredito que, se você estiver pesquisando "Hello World", ainda assim desejará que corresponda a "Hello World" ou mesmo a "Hello World \ n". Portanto, acabei de adicionar o método "trim ()" à função, que remove os espaços em branco ao redor, e ela começou a funcionar melhor. Além disso, modifiquei os nomes das variáveis ​​para ficar um pouco mais claro em minha mente.

Especificamente...

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

E nota secundária ... o corte remove 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 este seja um comportamento desejável, mas você poderia mudar isso se quisesse.

bwest87
fonte
3
$('a:contains("This One")')[0];

Sinto que estou perdendo algo com base na resposta de todos para filtrar, mas por que não selecionar apenas o primeiro item na matriz de elementos que é retornado por 'contém'?

Isso funciona apenas se você souber que o primeiro link tem a correspondência exata que você está procurando. Outras respostas funcionam melhor, se você não tiver certeza da ordem em que os links estarão.

Michael Khalili
fonte
Porque ele nem sempre sabe que o que ele quer é o primeiro
Cameron
A questão pergunta especificamente "Eu só quero o primeiro link".
Michael Khalili
A questão pede a correspondência exata, o autor indica o primeiro elemento para explicar qual elemento deseja.
dlopezgonzalez
2

Como obter o valor selecionado de um drop-dwon:

$.fn.textEquals = function (text) {
    var match = false; 
    var values="";
    $(this).each(function () {
        if ($(this).text().match("^" + text + "$")) {
            values=$(this).val();
            match = true;
            return false;
        }
    });
    return values;
};

console.log($("option").textEquals("Option One")); - ele retornará o valor do menu suspenso

Iulia Lucaciu
fonte
2
var link = $('a').filter(function(index) { return $(this).text() === "Availability"; });
 $(link).hide();
        $(link).removeAttr('href');
David Fawzy
fonte
1
Por favor, adicione uma explicação para sua resposta.
Michał Perłakowski
a primeira linha para selecionar qualquer link com esse texto, segunda e terceira linhas o que você pode fazer com o link para ocultá-los ou desabilitar o link veja o filtro na documentação do jquery api.jquery.com/filter
David Fawzy
@DavidFawzy - desculpe, umm ... o quê ?? Não acho que a 2ª ou a 3ª linhas tenham algo a ver com a pergunta do OP - apenas adiciona confusão.
jbyrd
2

Desculpe, se isso corresponde exatamente à resposta de alguém acima,

   $.fn.equalsText = function (text, isCaseSensitive) {
      return $(this).filter(function () {
         if (isCaseSensitive) {
            return $(this).text() === text
         } else {
            return $(this).text().toLowerCase() === text.toLowerCase()
         }
      })
   }

Aqui estão algumas saídas no console da página de resultados de pesquisa do Linkedin.

$("li").equalsText("Next >", false)
[<li class=​"next">​…​</li>​] // Output

$("li").equalsText("next >", false)
[<li class=​"next">​…​</li>​] // Output

$("li").equalsText("Next >", true)
[<li class=​"next">​…​</li>​] // Output

$("li").equalsText("next >", true)
[] // Output

Ele também tem suporte para diferenciação de maiúsculas e minúsculas e não está usando :contains()

Editar (22 de maio de 2017): -

   $.fn.equalsText = function (textOrRegex, isCaseSensitive) {
      return $(this).filter(function () {
         var val = $(this).text() || this.nodeValue
         if (textOrRegex instanceof RegExp) {
            return textOrRegex.test(val)
         } else if (isCaseSensitive) {
            return val === textOrRegex
         } else {
            return val.toLowerCase() === textOrRegex.toLowerCase()
         }
      })
   }
Vikas Gautam
fonte