Elemento de filtro basado en clave / valor .data ()

116

Digamos que tengo 4 elementos div con clase .navlink, que, cuando se hace clic, se usan .data()para establecer una clave llamada 'selected', en un valor de true:

$('.navlink')click(function() { $(this).data('selected', true); })

Cada vez que .navlinkse hace clic en un nuevo , me gustaría almacenar el seleccionado previamente navlinkpara su posterior manipulación. ¿Existe una forma rápida y sencilla de seleccionar un elemento en función de lo que se almacenó usando .data()?

No parece haber ningún jQuery : filtros que se ajusten a la factura, e intenté lo siguiente (dentro del mismo evento de clic), pero por alguna razón no funciona:

var $previous = $('.navlink').filter( 
    function() { $(this).data("selected") == true }
);

Sé que hay otras formas de lograr esto, pero en este momento solo tengo curiosidad por saber si se puede hacer a través de .data().

usuario113716
fuente

Respuestas:

192

su filtro funcionaría, pero debe devolver verdadero en los objetos coincidentes en la función pasada al filtro para que los capture.

var $previous = $('.navlink').filter(function() { 
  return $(this).data("selected") == true 
});
BarrocoBobcat
fuente
6
Tenga en cuenta que esta ya no es la única forma de hacer esto, StefanoP ha proporcionado alternativas
Nathan Koop
3
@NathanKoop, no del todo. Vea mi comentario sobre su respuesta.
Bryan Downing
Para aquellos que usan un atributo de datos para encontrar un elemento que de otro modo no se podría encontrar (id menos divs, etc. ... al que deben poder acceder por cualquier motivo) en cualquier lugar del documento:$("*").filter(function() { return $(this).data("DATA IDENTIFIER HERE") == DATA VALUE HERE; });
Tschallacka
esto no es "complicado" - esta es la única forma segura de filtrar en términos arbitrarios sin requerir que "escape" esos valores para asegurarse de que la concatenación del término de búsqueda con el resto del selector no cree un selector ilegal.
Alnitak
145

Solo para el registro, puede filtrar los datos con jquery (esta pregunta es bastante antigua y jQuery evolucionó desde entonces, por lo que también es correcto escribir esta solución):

$('.navlink[data-selected="true"]');

o mejor (por rendimiento):

$('.navlink').filter('[data-selected="true"]');

o, si desea obtener todos los elementos con data-selectedset:

$('[data-selected]')

Tenga en cuenta que este método solo funcionará con datos que se establecieron a través de atributos html. Si configura o cambia datos con la .data()llamada, este método ya no funcionará.

StefanoP
fuente
9
si el recuento bajo de votos para esta respuesta lo asusta, es la respuesta aceptada con más de 100 votos para una pregunta prácticamente idéntica stackoverflow.com/questions/4146502
Simon_Weaver
48
-1 Esto no funciona cuando los datos se establecen con el .data()método en lugar de un data-atributo. Vea este violín: jsfiddle.net/bryandowning/tySWC - Además, el .find()método busca elementos secundarios del selector anterior. En el ejemplo dado, data-selectedes un atributo de .navlink, no un hijo de .navlink. Además, $('div p')y $('div').find('p')son esencialmente equivalentes. El uso .find()parece que puede ser más lento debido a la llamada de función adicional (aunque no estoy seguro de esto). Por favor, corrígeme si me equivoco en algo de esto (realmente deseo que este método funcione).
Bryan Downing
3
un par de cosas: 1) tienes razón en que esto no funciona si configuras datos con .data(), dado que jQuery busca a través del DOM, lo publiqué para aquellos (como yo) que llegaron a esta pregunta por otras razones; 2) correcto, .find()busca entre los niños, por lo que está mal en este ejemplo; 3) estás equivocado, no son equivalentes, ya que jQuery busca de derecha a izquierda, consulta jonraasch.com/blog/…
StefanoP
2
El voto a favor $('[data-selected]')me ayudó en algo como$('ul.categories a[data-categories_id]').click(......);
Luke Cousins
Además, parece que si actualiza el atributo de datos usando .attr, si lo recupera usando .data, el valor no se actualizará, así que tenga cuidado al mezclar los dos
Fabio Lolli
13

Podemos hacer un complemento con bastante facilidad:

$.fn.filterData = function(key, value) {
    return this.filter(function() {
        return $(this).data(key) == value;
    });
};

Uso (marcando un botón de radio):

$('input[name=location_id]').filterData('my-data','data-val').prop('checked',true);
mpen
fuente
Te refieres al método de complemento, de lo contrario, esto es lo mismo que la respuesta aceptada ...
jave.web
@ jave.web De hecho. Pero no todo el mundo sabe cómo convertirlo en un complemento. Verborrea actualizada.
mpen
no me malinterpretes, tu respuesta es genial, sin embargo, las palabras aquí son muy importantes, gracias por la actualización :)
jave.web
8

Dos cosas que noté (aunque pueden ser errores de cuando lo escribiste).

  1. Te perdiste un punto en el primer ejemplo ( $('.navlink').click)
  2. Para que el filtro funcione, debe devolver un valor ( return $(this).data("selected")==true)
Thomas
fuente
-1

Parece más trabajo de lo que vale.

1) ¿Por qué no tener una única variable de JavaScript que almacene una referencia al elemento \ jQuery objeto actualmente seleccionado?

2) ¿Por qué no agregar una clase al elemento seleccionado actualmente? Entonces podrías consultar el DOM para la clase ".active" o algo así.

Bryan Migliorisi
fuente
Sí, pero como dije, sabía que había otras formas de lograrlo. Estaba atascado sobre si se podía filtrar a través de datos () y por qué filter () no funcionaba para mí. Pero gracias.
user113716
Lo siento. Me perdí esa parte de tu pregunta.
Bryan Migliorisi