¿Cómo encontrar un elemento basado en un valor de atributo de datos?

994

Tengo el siguiente escenario:

var el = 'li';

y hay 5 <li>en la página cada uno con un data-slide=numberatributo (el número es 1,2,3,4,5 respectivamente) .

Ahora necesito encontrar el número de diapositiva activo actualmente que se asigna var current = $('ul').data(current);y se actualiza en cada cambio de diapositiva.

Hasta ahora, mis intentos no han tenido éxito, tratando de construir el selector que coincida con la diapositiva actual:

$('ul').find(el+[data-slide=+current+]);

no coincide / devuelve nada ...

La razón por la que no puedo codificar la liparte es que esta es una variable accesible para el usuario que se puede cambiar a un elemento diferente si es necesario, por lo que puede no ser siempre una li.

¿Alguna idea de lo que me falta?

Jannis
fuente
66
¿Estás seguro de que dentro de ti .find(el+[data-slide=+current+]);está el código que escribes? parece que te perdiste algunas citas para"[data-slide]"
xandy
Eso es lo que me ayudó a seleccionar todos los atributos de datos (independientemente del valor): $('*[data-slide]')puede usarlo con, por ejemplo$('*[data-slide]').each( function() { ... });
Kai Noack el

Respuestas:

1481

Debe inyectar el valor de currenten un selector de Atributo igual :

$("ul").find(`[data-slide='${current}']`)

Para entornos JavaScript más antiguos ( ES5 y anteriores):

$("ul").find("[data-slide='" + current + "']"); 
Frédéric Hamidi
fuente
8
@ Jannis, podrías hacerlo $("ul").find(el + "[data-slide='" + current +"']");.
Frédéric Hamidi
77
@ c00lryguy, jQuery UI define uno, y existen implementaciones independientes . Parece que los intentos de agregarlo a jQuery Core fueron rechazados . Dos veces .
Frédéric Hamidi
66
esta respuesta en una publicación similar tiene un ejemplo de la función de filtro
drzaus
77
Me preocupa que esto no funcione si los datos se agregaron a través de la función jQuery .data (...), ya que esto no siempre representa un atributo y algunas veces utiliza un mecanismo de almacenamiento específico del navegador. Otra razón por la que desearía que jQuery core tuviera un selector de datos específicos.
AaronLS
77
Observe que no funciona para los elementos donde establece datos con $ ('# elemento'). Data ('some-att-name', value); pero solo para aquellos con atributos codificados. Tengo este problema y para que funcione, establezca los datos escribiendo el atributo directamente $ ('# element'). Attr ('data-some-att-name', value);
Pawel
463

en caso de que no desee escribir todo eso, aquí hay una forma más corta de consultar por atributo de datos:

$("ul[data-slide='" + current +"']");

FYI: http://james.padolsey.com/javascript/a-better-data-selector-for-jquery/

KevinDeus
fuente
31
Para aquellos de ustedes a quienes les importa, dada la estructura, <ul><li data-slide="item"></li></ul>el selector de esta respuesta volverá indefinido, por lo que no funciona dado el escenario del usuario. Esta respuesta FUNCIONARÁ para la estructura <ul data-slide="item"><li></li></ul> Si bien entiendo por qué su popularidad debido a la brevedad, técnicamente es una respuesta incorrecta. jsfiddle.net/py5p2abL/1
akousmata
44
No olvides tratarlo como una matriz. Use [0]para acceder al primer elemento encontrado.
Aminah Nuraini
Un extraño efecto secundario ... este método funcionó haciendo coincidir el elemento con el atributo de datos cuando .find("[data-attrib='value']")no funcionó. No sé si los valores eran atributos de datos agregados por jQuery o no ...
error
1
No es extraño porque las dos respuestas hacen 2 cosas diferentes. encuentra$.find específicamente los descendientes de ese elemento, pero el uso de la sintaxis de filtro en la cadena de selección simplemente filtrará los resultados.
Phil
227

Cuando busque con [data-x = ...], tenga cuidado, no funciona con jQuery.data (..) setter :

$('<b data-x="1">'  ).is('[data-x=1]') // this works
> true

$('<b>').data('x', 1).is('[data-x=1]') // this doesn't
> false

$('<b>').attr('data-x', 1).is('[data-x=1]') // this is the workaround
> true

Puedes usar esto en su lugar:

$.fn.filterByData = function(prop, val) {
    return this.filter(
        function() { return $(this).data(prop)==val; }
    );
}

$('<b>').data('x', 1).filterByData('x', 1).length
> 1
psycho brm
fuente
1
el $.fn.filterByDataes brillante; sin embargo, esta es una advertencia para los copy-pasters ... solo necesita $('<b>').filterByData('x', 1)encontrar <b>etiquetas con data-x="1". si copia y pega la .data(x, 1)parte ... configurará su data-x"1" antes de filtrar.
WEBjuju
39

Creo que he mejorado en filterByData extensión de BRM psico a jQuery.

Cuando la extensión anterior buscó en un par clave-valor, con esta extensión también puede buscar la presencia de un atributo de datos, independientemente de su valor.

(function ($) {

    $.fn.filterByData = function (prop, val) {
        var $self = this;
        if (typeof val === 'undefined') {
            return $self.filter(
                function () { return typeof $(this).data(prop) !== 'undefined'; }
            );
        }
        return $self.filter(
            function () { return $(this).data(prop) == val; }
        );
    };

})(window.jQuery);

Uso:

$('<b>').data('x', 1).filterByData('x', 1).length    // output: 1
$('<b>').data('x', 1).filterByData('x').length       // output: 1

O el violín: http://jsfiddle.net/PTqmE/46/

bPratik
fuente
34

Sin JQuery, ES6

document.querySelectorAll(`[data-slide='${current}']`);

Sé que la pregunta es sobre JQuery, pero los lectores pueden querer un método JS puro.

rap-2-h
fuente
33

Me he enfrentado al mismo problema al buscar elementos usando jQuery y el atributo data- *.

así que para su referencia, el código más corto está aquí:

Este es mi código HTML:

<section data-js="carousel"></section>
<section></section>
<section></section>
<section data-js="carousel"></section>

Este es mi selector jQuery:

$('section[data-js="carousel"]');
// this will return array of the section elements which has data-js="carousel" attribute.
usuario1378423
fuente
19
$("ul").find("li[data-slide='" + current + "']");

Espero que esto funcione mejor

Gracias

Jomin George Paul
fuente
15

Este selector $("ul [data-slide='" + current +"']");funcionará para la siguiente estructura:

<ul><li data-slide="item"></li></ul>  

Si bien esto $("ul[data-slide='" + current +"']");funcionará para:

<ul data-slide="item"><li></li></ul>

Matas Vaitkevicius
fuente
12

Volviendo a su pregunta original, sobre cómo hacer que esto funcione sin conocer de antemano el tipo de elemento, lo siguiente hace esto:

$(ContainerNode).find(el.nodeName + "[data-slide='" + current + "']");
Bryan Garaventa
fuente