Znajdź ciąg tekstowy za pomocą jQuery?


241

Powiedzmy, że strona internetowa ma ciąg taki jak „Jestem prostym ciągiem”, który chcę znaleźć. Jak mam to zrobić za pomocą JQuery?

Odpowiedzi:


327

jQuery ma metodę zawiera. Oto fragment dla Ciebie:

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

Selektor powyżej wybiera dowolny element zawierający ciąg docelowy. Foundin będzie obiektem jQuery zawierającym dowolny dopasowany element. Zobacz informacje API na: https://api.jquery.com/contains-selector/

Jedną rzeczą, na którą należy zwrócić uwagę za pomocą symbolu wieloznacznego „*”, jest to, że otrzymasz wszystkie elementy, w tym HTML i elementy treści, których prawdopodobnie nie chcesz. Dlatego większość przykładów w jQuery i innych miejscach używa $ („div: zawiera („ Jestem prosty ciąg znaków ”)”)


12
@ Tony, jak mógłbym zająć się manipulowaniem tylko pasującym tekstem, a nie tylko całym parapgraphem, div itp.?
Keith Donegan

12
Należy zauważyć, że w tym rozróżniana jest wielkość liter. Użytkownik o nazwie „ja” napisał to na stronie dokumentacji jQuery: $ .expr [':']. Icontains = function (obj, index, meta, stack) {return (obj.textContent || obj.innerText || jQuery ( obj) .text () || '') .toLowerCase (). indexOf (meta [3] .toLowerCase ())> = 0; }; Przykład: $ („div: icontains ('John')”). Css („dekoracja tekstu”, „podkreślenie”);
Brandon Bloom,

czy to działa dla JSona? Co jeśli chcę przefiltrować tekst w wartości JSON?
Chamilyan

5
To nie zadziała, jeśli węzeł tekstowy ma podział wiersza np. „Jestem prostym ciągiem \ n”. Pamiętaj, że podział linii nie będzie renderowany, więc użytkownik nie będzie nawet wiedział, gdzie jest problem. Wszystkie te rozwiązania mają ten problem. Zobacz jsfiddle.net/qPeAx
jesper

9
-1, nie działa. Zwraca wszystkie węzły nadrzędne w drzewie, chcesz tylko najniższy.
TMS

51

Zazwyczaj selektory jQuery nie wyszukują w „węzłach tekstowych” w DOM. Jeśli jednak użyjesz funkcji .contents (), zostaną uwzględnione węzły tekstowe, możesz użyć właściwości nodeType do filtrowania tylko węzłów tekstowych, a właściwości nodeValue do przeszukania ciągu tekstowego.

    $ („*”, „body”)
        .andSelf ()
        .zawartość()
        .filter (function () {
            return this.nodeType === 3;
        })
        .filter (function () {
            // Dopasuj tylko wtedy, gdy zawiera „prosty ciąg” w dowolnym miejscu tekstu
            zwraca this.nodeValue.indexOf ('prosty ciąg')! = -1;
        })
        .each (function () {
            // Zrób coś z this.nodeValue
        });

8
Aby to wyjaśnić, jak wspomniał Tony, możesz użyć selektora „: zawiera ()” do wyszukiwania w obrębie węzłów tekstowych, ale jQuery nie zwróci poszczególnych węzłów tekstowych w wynikach (tylko listę elementów). Ale kiedy używasz .contents (), wtedy jQuery zwraca zarówno elementy, jak i węzły tekstowe. Więcej informacji: docs.jquery.com/Traversing/contents
BarelyFitz

5
Zastanawiam się, dlaczego używasz .andSelf(). Od api.jquery.com/andSelf : „Obiekty jQuery utrzymują wewnętrzny stos, który śledzi zmiany w dopasowanym zestawie elementów. Po wywołaniu jednej z metod przejścia DOM nowy zestaw elementów jest wypychany na stos. Jeśli poprzedni zestaw elementów jest również pożądany, .andSelf () może pomóc. " Nie widzę wcześniejszego kontekstu, czego mi brakuje?
Alan H.

1
Pozytywne! Powinno być przyjętą odpowiedzią, ponieważ odfiltrowuje wszystkie węzły nadrzędne, co moim zdaniem jest powszechną potrzebą w większości scenariuszy.
LucaM,

29

Spowoduje to wybranie tylko elementów liścia, które zawierają „Jestem prostym ciągiem”.

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

Wklej następujące elementy w pasku adresu, aby go przetestować.

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

Jeśli chcesz złapać tylko „Jestem prostym ciągiem” . Najpierw zawiń tekst w takim elemencie.

$('*: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>' 
               )  
           ) 
});

a następnie zrób to.

$('*[containsStringImLookingFor]').css("border","solid 2px red");

3
funkcja .filter () byłaby bardziej przydatna niż .each () tutaj. W rzeczywistości możesz umieścić go w jednym selektorze: „*: zawiera („ bla ”): pusty”
nickf

2
#nickf -: pusty nie wybierze węzła tekstowego zawierającego tekst. Więc jeśli węzeł tekstowy zawiera „Jestem prostym ciągiem”, jest wykluczony. docs.jquery.com/Selectors/empty
Slim

2
Wiem, że jestem tu trochę spóźniony, ale czy to nie zignoruje żadnych bloków tekstowych, w których łańcuch istnieje na najwyższym poziomie, ale są w nim dzieci? np .: <blockquote> Jestem prostym ciągiem <span style = "font-weight: bold;"> ŻYCIE NA KRAWĘDZI </span> </blockquote>
Ken Bellows

Chcę tylko wspomnieć, że „zawieraStringImLookingFor” nie jest prawidłowym atrybutem HTML. Użyj dla HTML 5 „data-zawieraStringImLookingFor”. Wersja HTML wcześniejsza niż 5 nie ma możliwości dodania niestandardowych atrybutów ...
Snickbrack

17

Jeśli chcesz, aby węzeł znajdował się najbliżej szukanego tekstu, możesz użyć tego:

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

Działa to nawet, jeśli Twój HTML wygląda następująco:

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

Użycie powyższego selektora spowoduje znalezienie <strong>znacznika, ponieważ jest to ostatni znacznik, który zawiera cały ciąg.


1
To nie działa. Na przykład na tej stronie *: zawiera („the”): last zwraca tylko 1 element.
bzlm

4
@bzlm: cóż, niekoniecznie musiało to oznaczać, że chciał znaleźć wiele wystąpień.
nickf

2
Aha. Czy istnieje sposób, aby działał w przypadku wielu wystąpień? Myślę, że jest to bardziej eleganckie rozwiązanie niż te z rekurencyjnym sprawdzaniem typu węzłów itp.
bzlm

1
jedynym sposobem, w jaki mogłem wymyślić wszystkie węzły, ale nie wszyscy przodkowie w linii byliby zapętlający wynik, usuwając wszystkich rodziców, chociaż możesz mieć problemy, np .: <p>my text <b>my text</b></p>- usunięcie przodków <b>tagu przegrać drugi mecz
nickf


7

Po prostu dodałem do odpowiedzi Tony'ego Millera, ponieważ dzięki temu uzyskałem 90% w stosunku do tego, czego szukałem, ale nadal nie działało. Dodanie .length > 0;na końcu jego kodu uruchomiło mój skrypt.

 $(function() {
    var foundin = $('*:contains("I am a simple string")').length > 0;
 });

jak dodać nowe słowo do znalezionego łańcucha? Chcę dodać gwiazdkę do tej znalezionej pracy.
userAZLogicApps

@SaMolPP foundin += '*';
Pixelomo,

2

ta funkcja powinna działać. w zasadzie dokonuje rekurencyjnego wyszukiwania, dopóki nie otrzymamy wyraźnej listy węzłów liści.

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;
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.