Seleziona l'elemento per corrispondenza esatta del suo contenuto


161

Va bene, mi chiedo se c'è un modo per fare in modo che il :contains()selettore di jQuery selezioni gli elementi con solo la stringa digitata

per esempio -

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

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

Il selettore selezionerà entrambi gli pelementi e li renderà audaci, ma voglio che selezioni solo il primo.


Bene, potresti sovrascrivere il :containsselettore con il tuo codice, ma non credo sia questo che intendevi?
Blazemonger,


Si potrebbe definire un selettore personalizzato: stackoverflow.com/questions/12244929/...
BLSully


Risposte:


215

No, non esiste un selettore jQuery (o CSS) che lo faccia.

Puoi usare prontamente filter:

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

Non è un selettore , ma fa il lavoro. :-)

Se si desidera gestire gli spazi bianchi prima o dopo il "ciao", è possibile inserire un $.trim:

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

Per gli ottimizzatori prematuri là fuori, se non ti interessa che non corrisponda <p><span>hello</span></p>e simili, puoi evitare le chiamate a $e textutilizzando innerHTMLdirettamente:

return this.innerHTML === "hello";

... ma dovresti avere molti paragrafi per essere importante, così tanti che probabilmente avresti prima altri problemi. :-)


7
Potrebbe anche $.trimvolerci uno spazio bianco prima di fare il confronto.
Blazemonger,

Per qualche motivo ho dovuto usare "==" per far funzionare questo invece di "===".
Stephan,

3
@Stephan: Se ti stessi confrontando con un numero, dovresti utilizzare ==( == 2) o inserire il numero in una stringa ( === "2"), perché il valore che ottieni text()o innerHTMLè sempre una stringa. Se stai confrontando con una stringa, non importa se usi ==o ===.
TJ Crowder,

È un peccato che jQuery abbia implementato :containsche è un po 'più complesso, ma non ha implementato un selettore per la corrispondenza esatta del testo. = {
Paulo Bueno,

54

Prova ad aggiungere una pseudo funzione estesa:

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

Quindi puoi fare:

$('p:textEquals("Hello World")');

2
ottima soluzione: piccola aggiunta: per assicurarmi di non sovrascrivere un expr esistente, farei:$.expr[':'].textEquals = $.expr[':'].textEquals || $.expr.createPseudo(function(arg) {
Mischa Molhoek

9

È possibile utilizzare la funzione filter () di jQuery per ottenere ciò.

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

9

Quindi la risposta di Amandu funziona principalmente. Usandolo in natura, tuttavia, ho riscontrato alcuni problemi, in cui le cose che mi sarei aspettato di trovare non venivano trovate. Questo perché a volte c'è uno spazio bianco casuale che circonda il testo dell'elemento. Sono convinto che se stai cercando "Hello World", vorresti comunque che corrisponda a "Hello World", o anche "Hello World \ n". Pertanto, ho appena aggiunto il metodo "trim ()" alla funzione, che rimuove gli spazi bianchi circostanti e ha iniziato a funzionare meglio.

In particolare ...

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

Inoltre, nota, questa risposta è estremamente simile a Seleziona collegamento per testo (corrispondenza esatta)

E la nota secondaria ... trimrimuove solo gli spazi bianchi prima e dopo il testo cercato. Non rimuove gli spazi bianchi nel mezzo delle parole. Credo che questo sia un comportamento desiderabile, ma potresti cambiarlo se lo desideri.


5

Ho trovato un modo che funziona per me. Non è esatto al 100% ma elimina tutte le stringhe che contengono più della sola parola che sto cercando perché controllo anche se la stringa non contiene spazi singoli. A proposito non hai bisogno di questi "". jQuery sa che stai cercando una stringa. Assicurati di avere solo uno spazio nella parte: Includes () altrimenti non funzionerà.

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

E sì, lo so che non funzionerà se hai cose del genere <p>helloworld</p>


1
L'uso intelligente di partite semplici con contiene (..) senza usare un filtro o un'estensione! Non funzionerà su nulla che richieda spazi nei primi contiene (..), ma cercando di trovare una soluzione per questo. Grazie!
JoePC,

3

Come TJ Crowder ha affermato sopra, la funzione filtro fa miracoli. Non funzionava per me nel mio caso specifico. Avevo bisogno di cercare più tabelle e i rispettivi tag td all'interno di un div (in questo caso una finestra di dialogo jQuery).

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

Spero che questo sia utile a qualcuno!


Sono abbastanza nuovo su jquery, ma penso che sarebbe leggermente meglio usare each () invece di filter () poiché l'obiettivo di filter è di restituire un subarray. Ma ho sicuramente ispirato la soluzione, dato che avevo gli stessi problemi :)
JeopardyTempest,

0

Un one-liner che funziona con librerie alternative a jQuery:

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

E questo è l'equivalente di un a:contains("pattern")selettore di jQuery :

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

-4

Il .first () aiuterà qui

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

Certo ... in questo caso specifico. cosa succede se l'ordine non è noto al momento dello sviluppo?
BLSully
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.