94

Using jQuery, I want to select a link that contains exactly some kind of text. For example:

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

I have tried this:

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

But it picks the first AND the second link. I just want the first link, which contains exactly "This One". How can I do that?

FishBasketGordo
  • 22,904
  • 4
  • 58
  • 91
Endy Tjahjono
  • 24,120
  • 23
  • 83
  • 123
  • Possible duplicate of [Select element based on EXACT text contents](http://stackoverflow.com/questions/2338439/select-element-based-on-exact-text-contents) – Steve Chambers Nov 09 '16 at 10:20

10 Answers10

140

You can do this:

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

Reference: http://api.jquery.com/filter/

FishBasketGordo
  • 22,904
  • 4
  • 58
  • 91
  • 5
    Either would work in this case, but I tend to use === because it matches on value and type, i.e. it won't coerce the types. http://stackoverflow.com/questions/359494/javascript-vs-does-it-matter-which-equal-operator-i-use – FishBasketGordo Jul 13 '11 at 03:46
  • 1
    You missed `return`. I have to change it to `function(index) { return (this.text === 'This One') }` – Endy Tjahjono Jul 13 '11 at 03:54
  • Additionally, you can check for text length. – estinamir Jan 06 '20 at 23:03
40

A coworker of mine extended jQuery with a function to do this:

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

The result is that you can select something by exact text this way:

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

This makes it easy, since you don't have to remember the exact syntax each time. His entire post is here: jQuery Custom Selector for selecting elements by exact text :textEquals

Narnian
  • 3,858
  • 1
  • 26
  • 29
30

To expand on FishBasketGordo's answer. If you are trying to make the selection on a large amount of elements, use :contains() first to narrow down and then apply the filter.

This will improve the overall speed:

$('a:contains("This One")').filter(function(index)
{
    return $(this).text() === "This One";
});
Andrei
  • 3,086
  • 2
  • 19
  • 24
djhansel
  • 401
  • 4
  • 2
  • Voted up for speed/efficiency. Also, avoids the need $.trim() spaces within .filter(..). – JoePC Jul 30 '18 at 18:19
8

had to modify Nariman's solution to be:

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

Otherwise didn't work on chrome (Linux)

Archer
  • 5,073
  • 8
  • 50
  • 96
6

I was using the extension

$.expr[':'].textEquals

But I have found that the implementation no longer works with jQuery 1.7 (apparently a change in Sizzla.filter). After struggling for some time to make it work I have simply written a jQuery plugin to accomplish the same.

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

Use:

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

Just wanted to share, in case someone else runs into this (,

Alvis
  • 3,543
  • 5
  • 36
  • 41
5
$('a:contains("This One")')[0];

I feel like I'm missing something based on everyone else's answer to filter but why not just select the first item within the array of elements that's returned by 'contains'?

This works, only if you know that the first link has the exact match you're looking for. Other answers work better, if you're not sure which order the links will be in.

Michael Khalili
  • 933
  • 12
  • 13
3

So Narnian's answer works pretty well. Using it in the wild, however, I ran into some issues, where things that I would have expected to get found were not getting found. This was because sometimes there is random white space surrounding the element's text. It is my belief that if you're searching for "Hello World", you would still want it to match " Hello World ", or even "Hello World \n". Thus, I just added the "trim()" method to the function, which removes surrounding whitespace, and it started to work better. Also, I modified the variable names to be a little clearer to my mind.

Specifically...

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

And secondary note... trim only removes whitespace before and after the searched text. It does not remove whitespace in the middle of the words. I believe this is desirable behavior, but you could change that if you wanted.

bwest87
  • 1,223
  • 13
  • 12
2

How to get the selected value from a 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")); - it will return the value of the drop-down

j0k
  • 22,600
  • 28
  • 79
  • 90
2
var link = $('a').filter(function(index) { return $(this).text() === "Availability"; });
 $(link).hide();
        $(link).removeAttr('href');
David Fawzy
  • 1,056
  • 15
  • 17
  • 1
    Please add explanation to you answer. – Michał Perłakowski Jan 13 '16 at 10:12
  • the first line to select any link with that text , second and third lines what can you do with the link to hide them or disable the link look at filter in jquery documentation http://api.jquery.com/filter/ – David Fawzy Jan 17 '16 at 01:19
  • @DavidFawzy - sorry, umm...what?? I don't think the 2nd or 3rd lines have anything to do with the OP's question - it just adds confusion. – jbyrd Mar 14 '19 at 19:03
2

Sorry, if this exactly matches anybody's answer above,

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

Here is some output in the Linkedin search result page console.

$("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

It has case sensitivity support as well and is not using :contains()

Edit (May 22, 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
  • 1,793
  • 22
  • 21