Wybierz link według tekstu (dopasowanie ścisłe)

89

Korzystając z jQuery, chcę wybrać łącze zawierające dokładnie jakiś tekst. Na przykład:

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

Próbowałem tego:

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

Ale wybiera pierwsze ORAZ drugie łącze. Chcę tylko pierwszego linku, który zawiera dokładnie „Ten”. Jak mogę to zrobić?

Endy Tjahjono
źródło

Odpowiedzi:

139

Możesz to zrobić:

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

Źródła: http://api.jquery.com/filter/

FishBasketGordo
źródło
5
W tym przypadku w obu przypadkach działałoby, ale zwykle używam ===, ponieważ dopasowuje się do wartości i typu, tj. Nie wymusza typów. stackoverflow.com/questions/359494/…
FishBasketGordo,
1
Przegapiłeś return. Muszę to zmienić nafunction(index) { return (this.text === 'This One') }
Endy Tjahjono
Dodatkowo możesz sprawdzić długość tekstu.
bestinamir
39

Mój współpracownik rozszerzył jQuery o funkcję, która to robi:

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

W rezultacie możesz wybrać coś dokładnym tekstem w ten sposób:

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

Ułatwia to, ponieważ nie musisz za każdym razem pamiętać dokładnej składni. Cały jego post jest tutaj: jQuery Custom Selector do wybierania elementów według dokładnego tekstu: textEquals

Narnijski
źródło
28

Aby rozwinąć odpowiedź FishBasketGordo. Jeśli próbujesz dokonać wyboru na dużej liczbie elementów, użyj :contains()najpierw, aby zawęzić, a następnie zastosuj filtr.

Poprawi to ogólną prędkość:

$('a:contains("This One")').filter(function(index)
{
    return $(this).text() === "This One";
});
djhansel
źródło
Głosowano za szybkość / wydajność. Ponadto unika konieczności stosowania spacji $ .trim () w .filter (..).
JoePC
8

musiał zmodyfikować rozwiązanie Narimana, aby było:

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

W przeciwnym razie nie działało na Chrome (Linux)

Łucznik
źródło
6

Używałem rozszerzenia

$.expr[':'].textEquals

Ale odkryłem, że implementacja nie działa już z jQuery 1.7 (najwyraźniej zmiana w Sizzla.filter). Po pewnym czasie zmagania się, aby to działało, po prostu napisałem wtyczkę jQuery, aby osiągnąć to samo.

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

Posługiwać się:

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

Chciałem tylko udostępnić, na wypadek gdyby ktoś inny wpadł na to (,

Alvis
źródło
3

Zatem odpowiedź Narniana działa całkiem nieźle. Używając go na wolności, napotkałem jednak pewne problemy, w których rzeczy, których bym się spodziewał, nie zostały znalezione. Dzieje się tak, ponieważ czasami istnieje przypadkowa biała przestrzeń otaczająca tekst elementu. Wierzę, że jeśli szukasz „Hello World”, nadal chciałbyś, aby pasowało do „Hello World”, a nawet „Hello World \ n”. Dlatego właśnie dodałem do funkcji metodę „trim ()”, która usuwa otaczające ją białe znaki i zaczęła działać lepiej. Ponadto zmodyfikowałem nazwy zmiennych, aby były trochę jaśniejsze dla mojego umysłu.

Konkretnie...

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

I uwaga dodatkowa ... przycinanie usuwa tylko białe znaki przed i po wyszukanym tekście. Nie usuwa białych znaków w środku słów. Uważam, że jest to pożądane zachowanie, ale możesz to zmienić, jeśli chcesz.

bwest87
źródło
3
$('a:contains("This One")')[0];

Czuję, że brakuje mi czegoś opartego na odpowiedziach wszystkich innych dotyczących filtrowania, ale dlaczego nie wybrać po prostu pierwszego elementu w tablicy elementów, który jest zwracany przez „zawiera”?

Działa to tylko wtedy, gdy wiesz, że pierwszy link ma dokładne dopasowanie, którego szukasz. Inne odpowiedzi działają lepiej, jeśli nie masz pewności, w jakiej kolejności będą znajdować się linki.

Michael Khalili
źródło
Ponieważ nie zawsze wie, że ten, którego chce, jest pierwszy
Cameron
Pytanie dotyczy konkretnie „Chcę tylko pierwszego linku”.
Michael Khalili
Pytanie prosi o dokładne dopasowanie, autor wskazuje pierwszy element, aby wyjaśnić, który element chce.
dlopezgonzalez
2

Jak uzyskać wybraną wartość z 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")); - zwróci wartość listy rozwijanej

Iulia Lucaciu
źródło
2
var link = $('a').filter(function(index) { return $(this).text() === "Availability"; });
 $(link).hide();
        $(link).removeAttr('href');
David Fawzy
źródło
1
Proszę dodać wyjaśnienie do odpowiedzi.
Michał Perłakowski
pierwsza linia, aby wybrać dowolny link z tym tekstem, druga i trzecia linia, co możesz zrobić z linkiem, aby je ukryć lub wyłączyć link, spójrz na filtr w dokumentacji jquery api.jquery.com/filter
David Fawzy
@DavidFawzy - przepraszam, umm ... co ?? Nie sądzę, aby druga lub trzecia linia miała cokolwiek wspólnego z pytaniem OP - to po prostu dodaje zamieszania.
jbyrd
2

Przepraszamy, jeśli to dokładnie pasuje do czyjejś odpowiedzi powyżej,

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

Oto niektóre dane wyjściowe w konsoli strony wyników wyszukiwania w serwisie 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

Obsługuje również rozróżnianie wielkości liter i nie używa :contains()

Edycja (22 maja 2017 r.): -

   $.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
źródło