Wählen Sie das Element anhand der genauen Übereinstimmung seines Inhalts aus

160

Gut, ich frage mich, ob es eine Möglichkeit gibt, den :contains()Selektor von jQuery so zu gestalten, dass Elemente nur mit der eingegebenen Zeichenfolge ausgewählt werden

zum Beispiel -

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

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

Der Selektor wählt beide pElemente aus und macht sie fett, aber ich möchte, dass nur das erste ausgewählt wird.

julianisch
quelle
Nun, Sie könnten den :containsSelektor mit Ihrem eigenen Code überschreiben , aber ich nehme nicht an, dass Sie das gemeint haben?
Blazemonger
Sie können einen benutzerdefinierten Selektor definieren: stackoverflow.com/questions/12244929/…
BLSully
Mögliches Duplikat von: Jquery Selector, enthält gleich
BinaryTox1n
Mögliches Duplikat von Link per Text
auswählen

Antworten:

214

Nein, es gibt keinen jQuery- (oder CSS-) Selektor, der das macht.

Sie können leicht verwenden filter:

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

Es ist kein Selektor , aber es macht den Job. :-)

Wenn Sie vor oder nach dem "Hallo" mit Leerzeichen umgehen möchten, können Sie ein $.trim:

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

Für die vorzeitigen Optimierer da draußen können Sie <p><span>hello</span></p>die Aufrufe an $und textdurch innerHTMLdirekte Verwendung vermeiden , wenn Sie sich nicht darum kümmern, dass es nicht übereinstimmt und ähnlich ist :

return this.innerHTML === "hello";

... aber Sie müssten viele Absätze haben, damit es wichtig ist, so viele, dass Sie wahrscheinlich zuerst andere Probleme haben würden. :-)

TJ Crowder
quelle
7
Vielleicht möchten Sie $.trimes auch von streunenden Leerzeichen, bevor Sie den Vergleich durchführen.
Blazemonger
Aus irgendeinem Grund musste ich "==" verwenden, damit dies anstelle von "===" funktioniert.
Stephan
3
@Stephan: Wenn Sie mit einer Reihe wurden zu vergleichen, würden Sie zu jedem Gebrauch haben ==( == 2) oder die Zahl in einem String (Put === "2"), weil der Wert , den Sie von zu bekommen text()oder innerHTMLimmer eine Zeichenfolge ist. Wenn Sie mit einer Zeichenfolge verglichen haben, spielt es keine Rolle, ob Sie ==oder verwenden ===.
TJ Crowder
Es ist eine Schande, dass jQuery :containsetwas komplexer implementiert hat, aber keinen Selektor für die genaue Textübereinstimmung implementiert hat. = {
Paulo Bueno
54

Versuchen Sie, eine erweiterte Pseudofunktion hinzuzufügen:

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

Dann können Sie tun:

$('p:textEquals("Hello World")');
Amadu Bah
quelle
2
Tolle Lösung: kleine Ergänzung: Um sicherzustellen, dass Sie einen vorhandenen Ausdruck nicht überschreiben, würde ich $.expr[':'].textEquals = $.expr[':'].textEquals || $.expr.createPseudo(function(arg) {
Folgendes
9

Sie können dazu die filter () -Funktion von jQuery verwenden .

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

Amandus Antwort funktioniert also meistens. Bei der Verwendung in freier Wildbahn stieß ich jedoch auf einige Probleme, bei denen Dinge, von denen ich erwartet hätte, dass sie gefunden werden, nicht gefunden wurden. Dies lag daran, dass der Text des Elements manchmal von einem zufälligen Leerraum umgeben ist. Ich glaube, wenn Sie nach "Hello World" suchen, möchten Sie immer noch, dass es mit "Hello World" oder sogar "Hello World \ n" übereinstimmt. Daher habe ich der Funktion gerade die Methode "trim ()" hinzugefügt, mit der umgebende Leerzeichen entfernt werden, und sie begann besser zu funktionieren.

Speziell...

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

Beachten Sie auch, dass diese Antwort der Option Link nach Text auswählen sehr genau entspricht (genaue Übereinstimmung).

Und sekundäre Anmerkung ... trimentfernt nur Leerzeichen vor und nach dem gesuchten Text. Leerzeichen in der Mitte der Wörter werden nicht entfernt. Ich glaube, das ist wünschenswertes Verhalten, aber Sie können das ändern, wenn Sie wollen.

bwest87
quelle
5

Ich habe einen Weg gefunden, der für mich funktioniert. Es ist nicht 100% genau, aber es werden alle Zeichenfolgen entfernt, die mehr als nur das gesuchte Wort enthalten, da ich prüfe, ob die Zeichenfolge auch keine einzelnen Leerzeichen enthält. Diese "" brauchen Sie übrigens nicht. jQuery weiß, dass Sie nach einer Zeichenfolge suchen. Stellen Sie sicher, dass Sie nur ein Leerzeichen im Teil: enthält () haben, da dies sonst nicht funktioniert.

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

Und ja, ich weiß, es wird nicht funktionieren, wenn Sie solche Sachen haben <p>helloworld</p>

rf1234
quelle
1
Clevere Verwendung einfacher Übereinstimmungen mit enthält (..) ohne Verwendung eines Filters oder einer Erweiterung! Arbeitet nicht an irgendetwas, das Leerzeichen im ersten enthält, enthält (..), sondern versucht, eine Lösung dafür zu finden. Vielen Dank!
JoePC
3

Wie oben bei TJ Crowder erwähnt, wirkt die Filterfunktion Wunder. In meinem speziellen Fall hat es bei mir nicht funktioniert. Ich musste mehrere Tabellen und ihre jeweiligen td-Tags in einem div durchsuchen (in diesem Fall einen jQuery-Dialog).

$("#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.
    }
});

Ich hoffe das ist hilfreich für jemanden!

Greg A.
quelle
Ich bin ziemlich neu in jquery, würde aber denken, dass es etwas besser wäre, each () anstelle von filter () zu verwenden, da das Ziel von filter darin besteht, ein Subarray zurückzugeben. Aber inspirierte die Lösung definitiv, da ich die gleichen Probleme hatte :)
JeopardyTempest
0

Ein Einzeiler, der mit alternativen Bibliotheken zu jQuery arbeitet:

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

Und dies entspricht dem a:contains("pattern")Selektor eines jQuery :

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

Die .first () hilft hier

$('p:contains("hello")').first().css('font-weight', 'bold');
tymeJV
quelle
Sicher ... in diesem speziellen Fall. Was ist, wenn die Reihenfolge zur Entwicklungszeit nicht bekannt ist?
BLSully