Encontre uma string de texto usando jQuery?

241

Digamos que uma página da Web tenha uma sequência como "Eu sou uma sequência simples" que desejo encontrar. Como eu faria isso usando o JQuery?

Keith Donegan
fonte

Respostas:

327

O jQuery possui o método contains. Aqui está um trecho para você:

<script type="text/javascript">
$(function() {
    var foundin = $('*:contains("I am a simple string")');
});
</script>

O seletor acima seleciona qualquer elemento que contenha a sequência de destino. O foundin será um objeto jQuery que contém qualquer elemento correspondente. Consulte as informações da API em: https://api.jquery.com/contains-selector/

Uma coisa a se notar com o curinga '*' é que você obterá todos os elementos, incluindo os elementos html e body, que provavelmente não deseja. É por isso que a maioria dos exemplos no jQuery e em outros lugares usa $ ('div: contains ("sou uma string simples")')

Tony Miller
fonte
12
@ Tony, como eu iria manipular apenas o texto correspondente e não apenas todo o parapgraph, div etc etc?
Keith Donegan #
12
Deve salientar que isso faz distinção entre maiúsculas e minúsculas. Um usuário chamado "me" escreveu isso na página de documentos do jQuery: $ .expr [':']. Icontains = function (obj, index, meta, stack) {return (obj.textContent || obj.innerText || jQuery ( obj) .text () || '') .toLowerCase (). indexOf (meta [3] .toLowerCase ())> = 0; }; Exemplo: $ ("div: icontains ('John')"). Css ("text-decoration", "underline");
Brandon Bloom
isso funciona para json? E se eu quiser filtrar algum texto em um valor json?
Chamilyan
5
Isso não funcionará se o nó de texto tiver quebra de linha, por exemplo. "Eu sou uma simples \ n string". Observe que a quebra de linha não será renderizada, portanto o usuário nem saberá onde está o problema. Todas essas soluções têm esse problema. Veja jsfiddle.net/qPeAx
jesper
9
-1, não funciona. Ele retorna todos os nós pais na árvore; você deseja apenas o menor.
TMS
51

Normalmente, os seletores de jQuery não pesquisam nos "nós de texto" no DOM. No entanto, se você usar a função .contents (), os nós de texto serão incluídos, e você poderá usar a propriedade nodeType para filtrar apenas os nós de texto e a propriedade nodeValue para pesquisar a sequência de texto.

    $ ('*', 'corpo')
        .andSelf ()
        .conteúdo()
        .filter (function () {
            retorne this.nodeType === 3;
        })
        .filter (function () {
            // Corresponde apenas quando contém 'string simples' em qualquer lugar do texto
            retorne this.nodeValue.indexOf ('string simples')! = -1;
        })
        .each (function () {
            // Faça algo com this.nodeValue
        });
BarelyFitz
fonte
8
Para esclarecer, como Tony mencionou, você pode usar o seletor ": contains ()" para pesquisar nos nós de texto, mas o jQuery não retornará os nós de texto individuais nos resultados (apenas uma lista de elementos). Mas quando você usa .contents (), o jQuery retorna elementos e nós de texto. Para obter mais informações: docs.jquery.com/Traversing/contents
BarelyFitz
5
Estou intrigado com o motivo de você estar usando .andSelf(). Em api.jquery.com/andSelf : "os objetos jQuery mantêm uma pilha interna que controla as alterações no conjunto de elementos correspondente. Quando um dos métodos de passagem DOM é chamado, o novo conjunto de elementos é empurrado para a pilha. Se o conjunto anterior de elementos também é desejado, .eSelf () pode ajudar. " Não vejo contexto anterior, o que estou perdendo?
Alan H.
1
Voto a favor! Deve ser a resposta aceita, porque filtra todos os nós pais, que eu acho que é a necessidade comum na maioria dos cenários.
LucaM
29

Isso selecionará apenas os elementos da folha que contêm "Eu sou uma sequência simples".

$('*:contains("I am a simple string")').each(function(){
     if($(this).children().length < 1) 
          $(this).css("border","solid 2px red") });

Cole o seguinte na barra de endereço para testá-lo.

javascript: $('*:contains("I am a simple string")').each(function(){ if($(this).children().length < 1) $(this).css("border","solid 2px red") }); return false;

Se você quiser pegar apenas "Eu sou uma string simples" . Primeiro, envolva o texto em um elemento como esse.

$('*:contains("I am a simple string")').each(function(){
     if($(this).children().length < 1) 
          $(this).html( 
               $(this).text().replace(
                    /"I am a simple string"/
                    ,'<span containsStringImLookingFor="true">"I am a simple string"</span>' 
               )  
           ) 
});

e então faça isso.

$('*[containsStringImLookingFor]').css("border","solid 2px red");
Fino
fonte
3
a função .filter () seria mais útil que .each () aqui. De fato, você poderia colocá-lo em um seletor: "*: contains ('blah'): empty"
nickf
2
#nickf -: vazio não selecionará um nó de texto que contenha texto. Portanto, se o nó de texto contiver "Eu sou uma sequência simples", ele será excluído. docs.jquery.com/Selectors/empty
Slim
2
Sei que estou um pouco atrasado aqui, mas isso não ignorará nenhum bloco de texto em que a string exista no nível superior, mas haja crianças nela? por exemplo: <blockquote> Eu sou uma string simples <span style = "font-weight: bold;"> VIVENDO NA BORDA </span> </blockquote> #
Ken Bellows #
Eu só quero mencionar que "containsStringImLookingFor" não é um atributo HTML válido. Por favor, use para o HTML 5 "data-containsStringImLookingFor". Não há nenhuma maneira para HTML versão mais cedo do que 5 para adicionar atributos personalizados ...
Snickbrack
17

Se você deseja apenas o nó mais próximo do texto que está procurando, você pode usar o seguinte:

$('*:contains("my text"):last');

Isso funcionará mesmo se o seu HTML estiver assim:

<p> blah blah <strong>my <em>text</em></strong></p>

O uso do seletor acima encontrará a <strong>tag, pois essa é a última tag que contém toda a string.

nickf
fonte
1
Isso não parece funcionar. Nesta página, por exemplo, *: contains ("the"): last retorna apenas 1 elemento.
bzlm
4
@ bzlm: bem, não especificou necessariamente que ele queria encontrar várias ocorrências.
nickf
2
Aha. Existe uma maneira de fazê-lo funcionar para várias ocorrências? Eu acho que é uma solução mais elegante do que as que envolvem a verificação tipo de nó recursiva etc.
bzlm
1
a única maneira que eu poderia pensar em obter todos os nós, mas nem todos os ancestrais na linha seriam percorrer o resultado, removendo todos os pais, embora você pudesse ter problemas, por exemplo: <p>my text <b>my text</b></p>- remover os ancestrais da <b>tag perder a outra partida
nickf 14/03/10
13

Dê uma olhada no destaque (plugin jQuery).

Chris Doggett
fonte
7

Apenas adicionando à resposta de Tony Miller, isso me deu 90% do que eu estava procurando, mas ainda não funcionou. Adicionando .length > 0;ao final de seu código, meu script funcionou.

 $(function() {
    var foundin = $('*:contains("I am a simple string")').length > 0;
 });
Pixelomo
fonte
como acrescentar uma nova palavra na string encontrada?, Quero adicionar um asterik no trabalho encontrado.
userAZLogicApps
@SaMolPP foundin += '*';
Pixelomo 5/04/19
2

esta função deve funcionar. basicamente faz uma pesquisa recursiva até obter uma lista distinta de nós de folha.

function distinctNodes(search, element) {
    var d, e, ef;
    e = [];
    ef = [];

    if (element) {
        d = $(":contains(\""+ search + "\"):not(script)", element);
    }
    else {
            d = $(":contains(\""+ search + "\"):not(script)");
    }

    if (d.length == 1) {
            e.push(d[0]);
    }
    else {
        d.each(function () {
            var i, r = distinctNodes(search, this);
            if (r.length === 0) {
                e.push(this);
            }
            else {
                for (i = 0; i < r.length; ++i) {
                    e.push(r[i]);
                }
            }
        });
    }
    $.each(e, function () {
        for (var i = 0; i < ef.length; ++i) {
            if (this === ef[i]) return;
        }
        ef.push(this);
    });
    return ef;
}
danatcofo
fonte