Textzeichenfolge mit jQuery suchen?


241

Angenommen, eine Webseite enthält eine Zeichenfolge wie "Ich bin eine einfache Zeichenfolge", die ich finden möchte. Wie würde ich mit JQuery vorgehen?

Antworten:


327

jQuery hat die Methode enthält. Hier ist ein Ausschnitt für Sie:

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

Der obige Selektor wählt jedes Element aus, das die Zielzeichenfolge enthält. Das Foundin ist ein jQuery-Objekt, das ein übereinstimmendes Element enthält. Siehe die API-Informationen unter: https://api.jquery.com/contains-selector/

Eine Sache, die Sie mit dem Platzhalter '*' beachten sollten, ist, dass Sie alle Elemente erhalten, einschließlich Ihrer HTML- und Body-Elemente, die Sie wahrscheinlich nicht möchten. Aus diesem Grund verwenden die meisten Beispiele bei jQuery und anderen Orten $ ('div: enthält ("Ich bin eine einfache Zeichenfolge")').


12
@ Tony, wie würde ich vorgehen, um nur den passenden Text und nicht nur den gesamten Parapgraphen, Div usw. usw. zu manipulieren?
Keith Donegan

12
Sollte darauf hinweisen, dass dies zwischen Groß- und Kleinschreibung unterscheidet. Ein Benutzer mit dem Namen "me" hat dies auf der Seite mit den jQuery-Dokumenten geschrieben: $ .expr [':']. Icontains = function (obj, index, meta, stack) {return (obj.textContent || obj.innerText || jQuery ( obj) .text () || '') .toLowerCase (). indexOf (meta [3] .toLowerCase ())> = 0; }; Beispiel: $ ("div: icontains ('John')"). CSS ("Textdekoration", "Unterstreichung");
Brandon Bloom

funktioniert das für json? Was ist, wenn ich Text in einem JSON-Wert filtern möchte?
Chamilyan

5
Dies funktioniert nicht, wenn der Textknoten einen Zeilenumbruch aufweist, z. "Ich bin eine einfache \ n Zeichenfolge". Beachten Sie, dass Zeilenumbrüche nicht gerendert werden, sodass der Benutzer nicht einmal weiß, wo das Problem liegt. Alle diese Lösungen haben dieses Problem. Siehe jsfiddle.net/qPeAx
jesper

9
-1, funktioniert nicht. Es werden alle übergeordneten Knoten im Baum zurückgegeben, Sie möchten nur den niedrigsten.
TMS

51

Normalerweise suchen jQuery-Selektoren nicht innerhalb der "Textknoten" im DOM. Wenn Sie jedoch die Funktion .contents () verwenden, werden Textknoten eingeschlossen. Mit der Eigenschaft nodeType können Sie nur die Textknoten filtern, und mit der Eigenschaft nodeValue können Sie die Textzeichenfolge durchsuchen.

    $ ('*', 'body')
        .andSelf ()
        .Inhalt()
        .filter (function () {
            return this.nodeType === 3;
        })
        .filter (function () {
            // Nur übereinstimmen, wenn irgendwo im Text 'einfache Zeichenfolge' enthalten ist
            return this.nodeValue.indexOf ('einfache Zeichenfolge')! = -1;
        })
        .each (function () {
            // Mach etwas mit this.nodeValue
        });

8
Wie Tony bereits erwähnt hat, können Sie zur Verdeutlichung den Selektor ": enthält ()" verwenden, um innerhalb der Textknoten zu suchen. JQuery gibt jedoch nicht die einzelnen Textknoten in den Ergebnissen zurück (nur eine Liste von Elementen). Wenn Sie jedoch .contents () verwenden, gibt jQuery sowohl Elemente als auch Textknoten zurück. Für weitere Informationen: docs.jquery.com/Traversing/contents
BarelyFitz

5
Ich bin verwirrt, warum Sie verwenden .andSelf() . Von api.jquery.com/andSelf : "jQuery-Objekte verwalten einen internen Stapel, der Änderungen an der übereinstimmenden Gruppe von Elementen verfolgt. Wenn eine der DOM-Durchquerungsmethoden aufgerufen wird, wird die neue Gruppe von Elementen auf den Stapel verschoben Der vorherige Satz von Elementen ist ebenfalls erwünscht. .andSelf () kann helfen. " Ich sehe keinen vorherigen Kontext. Was fehlt mir?
Alan H.

1
Upvoted! Sollte die akzeptierte Antwort sein, da sie alle übergeordneten Knoten herausfiltert, was meiner Meinung nach in den meisten Szenarien die häufigste Notwendigkeit ist.
LucaM

29

Dadurch werden nur die Blattelemente ausgewählt, die "Ich bin eine einfache Zeichenfolge" enthalten.

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

Fügen Sie Folgendes in die Adressleiste ein, um es zu testen.

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

Wenn Sie nur "Ich bin eine einfache Zeichenfolge" greifen möchten . Wickeln Sie zuerst den Text in ein Element wie dieses.

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

und dann mach das.

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

3
Die Funktion .filter () wäre hier nützlicher als .each (). Tatsächlich könnte man es tatsächlich in einen Selektor setzen: "*: enthält ('blah'): leer"
nickf

2
#nickf -: leer wählt keinen Textknoten aus, der Text enthält. Wenn der Textknoten also "Ich bin eine einfache Zeichenfolge" enthält, wird er ausgeschlossen. docs.jquery.com/Selectors/empty
Slim

2
Ich weiß, dass ich hier etwas spät dran bin, aber ignoriert dies keine Textblöcke, in denen die Zeichenfolge auf der obersten Ebene vorhanden ist, aber Kinder darin enthalten sind? Beispiel: <blockquote> Ich bin eine einfache Zeichenfolge <span style = "font-weight: bold;"> LEBEN AM RAND </ span> </ blockquote>
Ken Bellows

Ich möchte nur erwähnen, dass "enthältStringImLookingFor" kein gültiges HTML-Attribut ist. Bitte verwenden Sie für HTML 5 "data-enthältStringImLookingFor". Es gibt keine Möglichkeit für HTML-Version vor 5, benutzerdefinierte Attribute hinzuzufügen ...
Snickbrack

17

Wenn Sie nur den Knoten möchten, der dem gesuchten Text am nächsten liegt, können Sie Folgendes verwenden:

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

Dies funktioniert sogar, wenn Ihr HTML so aussieht:

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

Wenn Sie den obigen Selektor verwenden, wird das <strong>Tag gefunden, da dies das letzte Tag ist, das die gesamte Zeichenfolge enthält.


1
Das scheint nicht zu funktionieren. Auf dieser Seite enthält beispielsweise *: enthält ("the"): last gibt nur 1 Element zurück.
Bzlm

4
@bzlm: Nun, es wurde nicht unbedingt angegeben, dass er mehrere Vorkommen finden wollte.
Nickf

2
Aha. Gibt es eine Möglichkeit, es für mehrere Vorkommen zum Laufen zu bringen? Ich denke, es ist eine elegantere Lösung als die mit rekursiver Knotentypprüfung usw.
bzlm

1
Der einzige Weg, den ich mir vorstellen könnte, um alle Knoten, aber nicht alle Vorfahren auf der Linie zu bekommen, wäre, das Ergebnis zu durchlaufen und alle Eltern zu entfernen, obwohl Sie Probleme haben könnten, z. B.: <p>my text <b>my text</b></p>- Entfernen der Vorfahren des <b>Tags würde verlieren das andere Spiel
Nickf


7

Nur zu Tony Millers Antwort hinzuzufügen, da dies mich zu 90% zu dem brachte, wonach ich suchte, aber immer noch nicht funktionierte. Durch .length > 0;das Hinzufügen am Ende seines Codes funktionierte mein Skript.

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

Wie füge ich ein neues Wort an die gefundene Zeichenfolge an? Ich möchte ein Sternchen zu dieser gefundenen Arbeit hinzufügen.
userAZLogicApps

@ SaMolPP foundin += '*';
Pixelomo

2

Diese Funktion sollte funktionieren. Im Grunde führt eine rekursive Suche durch, bis wir eine eindeutige Liste von Blattknoten erhalten.

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;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.