Sélectionnez l'élément par correspondance exacte de son contenu

161

Très bien, je me demande s'il existe un moyen de faire en sorte que le :contains()sélecteur de jQuery sélectionne des éléments avec uniquement la chaîne qui est tapée

par exemple -

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

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

Le sélecteur sélectionnera les deux péléments et les mettra en gras, mais je veux qu'il ne sélectionne que le premier.

julien
la source
Eh bien, vous pouvez remplacer le :containssélecteur avec votre propre code, mais je ne suppose pas que ce soit ce que vous vouliez dire?
Blazemonger
Vous pouvez définir un sélecteur personnalisé: stackoverflow.com/questions/12244929/…
BLSully
Doublon
duplication possible du lien Sélectionner par texte (correspondance exacte)
FishBasketGordo

Réponses:

215

Non, il n'y a pas de sélecteur jQuery (ou CSS) qui fait cela.

Vous pouvez facilement utiliser filter:

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

Ce n'est pas un sélecteur , mais il fait le travail. :-)

Si vous voulez gérer les espaces avant ou après le "bonjour", vous pouvez y jeter un $.trim:

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

Pour les optimiseurs prématurés, si vous ne vous souciez pas que cela ne corresponde pas <p><span>hello</span></p>et similaire, vous pouvez éviter les appels vers $et texten utilisant innerHTMLdirectement:

return this.innerHTML === "hello";

... mais il vous faudrait beaucoup de paragraphes pour que cela compte, tellement que vous auriez probablement d'autres problèmes en premier. :-)

TJ Crowder
la source
7
Peut-être aussi le souhaiter $.trimde tout espace parasite avant de faire la comparaison.
Blazemonger
Pour une raison quelconque, j'ai dû utiliser "==" pour que cela fonctionne au lieu de "===".
Stephan
3
@Stephan: Si vous compariez avec un nombre, vous devrez soit utiliser ==( == 2), soit mettre le nombre dans une chaîne ( === "2"), car la valeur que vous obtenez text()ou innerHTMLest toujours une chaîne. Si vous comparez avec une chaîne, peu importe que vous utilisiez ==ou ===.
TJ Crowder
C'est dommage que jQuery ait implémenté ce :containsqui est un peu plus complexe, mais n'a pas implémenté de sélecteur pour la correspondance exacte du texte. = {
Paulo Bueno
54

Essayez d'ajouter une pseudo fonction d'extension:

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

Ensuite, vous pouvez faire:

$('p:textEquals("Hello World")');
Amadu Bah
la source
2
excellente solution: petit ajout: pour être sûr de ne pas écraser une expr existante, je ferais:$.expr[':'].textEquals = $.expr[':'].textEquals || $.expr.createPseudo(function(arg) {
Mischa Molhoek
9

Vous pouvez utiliser la fonction filter () de jQuery pour y parvenir.

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

La réponse d'Amandu fonctionne donc principalement. En l'utilisant dans la nature, cependant, j'ai rencontré des problèmes, où les choses que j'aurais espéré trouver ne l'étaient pas. En effet, il y a parfois un espace blanc aléatoire autour du texte de l'élément. Je pense que si vous recherchez "Hello World", vous voudrez toujours qu'il corresponde à "Hello World", ou même "Hello World \ n". Ainsi, je viens d'ajouter la méthode "trim ()" à la fonction, qui supprime les espaces blancs environnants, et cela a commencé à mieux fonctionner.

Plus précisément...

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

Notez également que cette réponse est extrêmement similaire à Sélectionner le lien par texte (correspondance exacte)

Et la note secondaire ... trimsupprime uniquement les espaces avant et après le texte recherché. Il ne supprime pas les espaces au milieu des mots. Je pense que c'est un comportement souhaitable, mais vous pouvez changer cela si vous le souhaitez.

bwest87
la source
5

J'ai trouvé un moyen qui fonctionne pour moi. Ce n'est pas exact à 100% mais cela élimine toutes les chaînes qui contiennent plus que le mot que je recherche car je vérifie la chaîne ne contenant pas d'espaces individuels. Au fait, vous n'avez pas besoin de ces "". jQuery sait que vous recherchez une chaîne. Assurez-vous que vous n'avez qu'un seul espace dans la partie: contains () sinon cela ne fonctionnera pas.

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

Et oui je sais que ça ne marchera pas si tu as des trucs comme <p>helloworld</p>

rf1234
la source
1
Utilisation intelligente de correspondances simples avec contains (..) sans utiliser de filtre ou d'extension! Ne fonctionnera pas sur tout ce qui nécessite des espaces dans le premier contient (..), mais en essayant de trouver une solution pour cela. Merci!
JoePC
3

Comme TJ Crowder l'a déclaré ci-dessus, la fonction de filtre fait des merveilles. Cela ne fonctionnait pas pour moi dans mon cas spécifique. J'avais besoin de rechercher plusieurs tables et leurs balises td respectives dans un div (dans ce cas, une boîte de dialogue 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.
    }
});

J'espère que cela sera utile à quelqu'un!

Greg A
la source
Je suis assez nouveau dans jquery, mais je pense qu'il serait légèrement préférable d'utiliser each () au lieu de filter () puisque le but de filter est de renvoyer un sous-tableau. Mais j'ai définitivement inspiré la solution, car j'avais les mêmes problèmes :)
JeopardyTempest
0

Un one-liner qui fonctionne avec des bibliothèques alternatives à jQuery:

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

Et c'est l'équivalent du a:contains("pattern")sélecteur d' un jQuery :

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

Le .first () aidera ici

$('p:contains("hello")').first().css('font-weight', 'bold');
tymeJV
la source
Bien sûr ... dans ce cas précis. et si l'ordre n'est pas connu au moment du développement?
BLSully