Sélectionnez le lien par texte (correspondance exacte)

89

En utilisant jQuery, je souhaite sélectionner un lien qui contient exactement une sorte de texte. Par exemple:

<p><a>This One</a></p>
<p><a>"This One?"</a></p>
<p><a>Unlikely</a></p>

J'ai essayé ceci:

$('a:contains("This One")')

Mais il choisit le premier ET le deuxième lien. Je veux juste le premier lien, qui contient exactement "Celui-ci". Comment puis je faire ça?

Endy Tjahjono
la source
Reproduction possible de l' élément Select basé sur le contenu du texte EXACT
Steve Chambers

Réponses:

138

Tu peux le faire:

$('a').filter(function(index) { return $(this).text() === "This One"; });

Référence: http://api.jquery.com/filter/

PoissonPanierGordo
la source
5
Les deux fonctionneraient dans ce cas, mais j'ai tendance à utiliser === car il correspond à la valeur et au type, c'est-à-dire qu'il ne contraindra pas les types. stackoverflow.com/questions/359494/…
FishBasketGordo
1
Vous avez manqué return. Je dois le changer pourfunction(index) { return (this.text === 'This One') }
Endy Tjahjono
En outre, vous pouvez vérifier la longueur du texte.
bestinamir
39

Un de mes collègues a étendu jQuery avec une fonction pour faire ceci:

$.expr[':'].textEquals = function(a, i, m) {
    return $(a).text().match("^" + m[3] + "$");
};

Le résultat est que vous pouvez sélectionner quelque chose par texte exact de cette façon:

$("label:textEquals('Exact Text to Match')");

Cela facilite les choses, car vous n'avez pas à vous souvenir de la syntaxe exacte à chaque fois. Son article entier est ici: jQuery Custom Selector pour sélectionner des éléments par texte exact: textEquals

Narnian
la source
28

Pour développer la réponse de FishBasketGordo. Si vous essayez de faire la sélection sur une grande quantité d'éléments, utilisez d' :contains()abord pour affiner, puis appliquez le filtre.

Cela améliorera la vitesse globale:

$('a:contains("This One")').filter(function(index)
{
    return $(this).text() === "This One";
});
Djhansel
la source
Voté pour la vitesse / efficacité. De plus, évite le besoin d'espaces $ .trim () dans .filter (..).
JoePC
8

a dû modifier la solution de Nariman pour être:

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

Sinon, ne fonctionnait pas sur Chrome (Linux)

Archer
la source
6

J'utilisais l'extension

$.expr[':'].textEquals

Mais j'ai trouvé que l'implémentation ne fonctionne plus avec jQuery 1.7 (apparemment un changement dans Sizzla.filter). Après avoir lutté pendant un certain temps pour le faire fonctionner, j'ai simplement écrit un plugin jQuery pour accomplir la même chose.

$.fn.textEquals = function (text) {
    var match = false;
    $(this).each(function () {
        if ($(this).text().match("^" + escapeRegex(text) + "$")) {
            match = true;
            return false;
        }
    });
    return match;
};

Utilisation:

$(".ui-autocomplete li").textEquals('Exact Text to Match');

Je voulais juste partager, au cas où quelqu'un d'autre rencontrerait ceci (,

Alvis
la source
3

La réponse de Narnian fonctionne donc plutôt bien. En l'utilisant dans la nature, cependant, j'ai rencontré des problèmes, où les choses que je m'attendais à trouver ne l'étaient pas. En effet, parfois, il y a un espace blanc aléatoire entourant le 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. De plus, j'ai modifié les noms des variables pour être un peu plus clairs dans mon esprit.

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;
}

Et note secondaire ... trim ne supprime que 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
3
$('a:contains("This One")')[0];

J'ai l'impression que je manque quelque chose en fonction de la réponse de tout le monde à filtrer, mais pourquoi ne pas simplement sélectionner le premier élément dans le tableau d'éléments retourné par «contient»?

Cela ne fonctionne que si vous savez que le premier lien a la correspondance exacte que vous recherchez. Les autres réponses fonctionnent mieux, si vous ne savez pas dans quel ordre les liens seront.

Michael Khalili
la source
Parce qu'il ne sait pas toujours celui qu'il veut, c'est le premier
Cameron
La question demande spécifiquement "Je veux juste le premier lien".
Michael Khalili
La question demande la correspondance exacte, l'auteur indique le premier élément pour expliquer quel élément veut.
dlopezgonzalez
2

Comment obtenir la valeur sélectionnée à partir d'un drop-dwon:

$.fn.textEquals = function (text) {
    var match = false; 
    var values="";
    $(this).each(function () {
        if ($(this).text().match("^" + text + "$")) {
            values=$(this).val();
            match = true;
            return false;
        }
    });
    return values;
};

console.log($("option").textEquals("Option One")); - il retournera la valeur du menu déroulant

Iulia Lucaciu
la source
2
var link = $('a').filter(function(index) { return $(this).text() === "Availability"; });
 $(link).hide();
        $(link).removeAttr('href');
David Fawzy
la source
1
Veuillez ajouter une explication à votre réponse.
Michał Perłakowski
la première ligne pour sélectionner n'importe quel lien avec ce texte, deuxième et troisième lignes que pouvez-vous faire avec le lien pour les masquer ou désactiver le lien regarder le filtre dans la documentation jquery api.jquery.com/filter
David Fawzy
@DavidFawzy - désolé, euh ... quoi ?? Je ne pense pas que les 2e ou 3e lignes aient quoi que ce soit à voir avec la question du PO - cela ne fait qu'ajouter à la confusion.
jbyrd
2

Désolé, si cela correspond exactement à la réponse de quelqu'un ci-dessus,

   $.fn.equalsText = function (text, isCaseSensitive) {
      return $(this).filter(function () {
         if (isCaseSensitive) {
            return $(this).text() === text
         } else {
            return $(this).text().toLowerCase() === text.toLowerCase()
         }
      })
   }

Voici une sortie dans la console de la page de résultats de recherche Linkedin.

$("li").equalsText("Next >", false)
[<li class=​"next">​…​</li>​] // Output

$("li").equalsText("next >", false)
[<li class=​"next">​…​</li>​] // Output

$("li").equalsText("Next >", true)
[<li class=​"next">​…​</li>​] // Output

$("li").equalsText("next >", true)
[] // Output

Il prend également en charge la sensibilité à la casse et n'utilise pas :contains()

Edit (22 mai 2017): -

   $.fn.equalsText = function (textOrRegex, isCaseSensitive) {
      return $(this).filter(function () {
         var val = $(this).text() || this.nodeValue
         if (textOrRegex instanceof RegExp) {
            return textOrRegex.test(val)
         } else if (isCaseSensitive) {
            return val === textOrRegex
         } else {
            return val.toLowerCase() === textOrRegex.toLowerCase()
         }
      })
   }
Vikas Gautam
la source