Seleccionar enlace por texto (coincidencia exacta)

89

Usando jQuery, quiero seleccionar un enlace que contenga exactamente algún tipo de texto. Por ejemplo:

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

He intentado esto:

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

Pero elige el primer Y el segundo enlace. Solo quiero el primer enlace, que contiene exactamente "Este". ¿Cómo puedo hacer eso?

Endy Tjahjono
fuente
Posible duplicado del elemento Seleccionar basado en contenido de texto EXACTO
Steve Chambers

Respuestas:

138

Puedes hacerlo:

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

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

PescadoCestaGordo
fuente
5
Cualquiera de los dos funcionaría en este caso, pero tiendo a usar === porque coincide con el valor y el tipo, es decir, no coaccionará los tipos. stackoverflow.com/questions/359494/…
FishBasketGordo
1
Te perdiste return. Tengo que cambiarlo afunction(index) { return (this.text === 'This One') }
Endy Tjahjono
Además, puede verificar la longitud del texto.
bestinamir
39

Un compañero de trabajo extendió jQuery con una función para hacer esto:

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

El resultado es que puede seleccionar algo por texto exacto de esta manera:

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

Esto lo hace fácil, ya que no tiene que recordar la sintaxis exacta cada vez. Su publicación completa está aquí: jQuery Custom Selector para seleccionar elementos por texto exacto: textEquals

Narnia
fuente
28

Para ampliar la respuesta de FishBasketGordo. Si está intentando hacer la selección en una gran cantidad de elementos, utilice :contains()primero para reducir y luego aplique el filtro.

Esto mejorará la velocidad general:

$('a:contains("This One")').filter(function(index)
{
    return $(this).text() === "This One";
});
djhansel
fuente
Votado por velocidad / eficiencia. Además, evita la necesidad de espacios $ .trim () dentro de .filter (..).
JoePC
8

tuvo que modificar la solución de Nariman para ser:

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

De lo contrario, no funcionó en Chrome (Linux)

Arquero
fuente
6

Estaba usando la extensión

$.expr[':'].textEquals

Pero descubrí que la implementación ya no funciona con jQuery 1.7 (aparentemente un cambio en Sizzla.filter). Después de luchar durante un tiempo para que funcione, simplemente escribí un complemento jQuery para lograr lo mismo.

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

Utilizar:

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

Solo quería compartir, en caso de que alguien más se encuentre con esto (,

Alvis
fuente
3

Entonces, la respuesta de Narnian funciona bastante bien. Sin embargo, al usarlo en la naturaleza, me encontré con algunos problemas, en los que no se encontraban las cosas que esperaba encontrar. Esto se debe a que a veces hay espacios en blanco aleatorios alrededor del texto del elemento. Creo que si estás buscando "Hello World", aún querrás que coincida con "Hello World" o incluso con "Hello World \ n". Por lo tanto, acabo de agregar el método "trim ()" a la función, que elimina los espacios en blanco circundantes, y comenzó a funcionar mejor. Además, modifiqué los nombres de las variables para que fueran un poco más claros en mi mente.

Específicamente...

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

Y nota secundaria ... recortar solo elimina los espacios en blanco antes y después del texto buscado. No elimina los espacios en blanco en medio de las palabras. Creo que este es un comportamiento deseable, pero podrías cambiarlo si quisieras.

bwest87
fuente
3
$('a:contains("This One")')[0];

Siento que me falta algo basado en la respuesta de todos los demás al filtro, pero ¿por qué no seleccionar el primer elemento dentro de la matriz de elementos que devuelve 'contiene'?

Esto funciona, solo si sabe que el primer enlace tiene la coincidencia exacta que está buscando. Otras respuestas funcionan mejor si no está seguro de en qué orden estarán los enlaces.

Michael Khalili
fuente
Porque no siempre sabe que el que quiere es el primero
Cameron
La pregunta pregunta específicamente "Solo quiero el primer enlace".
Michael Khalili
La pregunta pide la coincidencia exacta, el autor indica el primer elemento para explicar qué elemento quiere.
dlopezgonzalez
2

Cómo obtener el valor seleccionado de 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")); - devolverá el valor del menú desplegable

Iulia Lucaciu
fuente
2
var link = $('a').filter(function(index) { return $(this).text() === "Availability"; });
 $(link).hide();
        $(link).removeAttr('href');
David Fawzy
fuente
1
Agregue una explicación a su respuesta.
Michał Perłakowski
la primera línea para seleccionar cualquier enlace con ese texto, segunda y tercera líneas, ¿qué puede hacer con el enlace para ocultarlos o deshabilitar el enlace? Ver el filtro en la documentación de jquery api.jquery.com/filter
David Fawzy
@DavidFawzy - lo siento, umm ... ¿qué ?? No creo que la segunda o la tercera línea tengan nada que ver con la pregunta del OP, solo agrega confusión.
jbyrd
2

Lo siento, si esto coincide exactamente con la respuesta anterior de alguien,

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

Aquí hay algunos resultados en la consola de la página de resultados de búsqueda de 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

También tiene compatibilidad con mayúsculas y minúsculas y no utiliza :contains()

Editar (22 de mayo de 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
fuente