Élément de filtre basé sur la clé / valeur .data ()

116

Disons que j'ai 4 éléments div avec class .navlink, qui, lorsqu'ils sont cliqués, utilisent .data()pour définir une clé appelée 'selected', à une valeur de true:

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

Chaque fois que vous .navlinkcliquez sur un nouveau , je souhaite stocker le précédent sélectionné navlinkpour une manipulation ultérieure. Existe-t-il un moyen rapide et facile de sélectionner un élément en fonction de ce qui a été stocké .data()?

Il ne semble pas y avoir de jQuery : des filtres qui correspondent à la facture, et j'ai essayé ce qui suit (dans le même événement de clic), mais pour une raison quelconque, cela ne fonctionne pas:

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

Je sais qu'il existe d'autres façons d'accomplir cela, mais pour le moment, je suis surtout curieux de savoir si cela peut être fait via .data().

utilisateur113716
la source

Réponses:

192

votre filtre fonctionnerait, mais vous devez retourner true sur les objets correspondants dans la fonction passée au filtre pour qu'il les récupère.

var $previous = $('.navlink').filter(function() { 
  return $(this).data("selected") == true 
});
BaroqueBobcat
la source
6
Veuillez noter que ce n'est plus le seul moyen de le faire, StefanoP a fourni des alternatives
Nathan Koop
3
@NathanKoop, pas tout à fait. Voir mon commentaire sur sa réponse.
Bryan Downing
Pour ceux qui utilisent un attribut de données pour trouver un élément autrement introuvable (id less divs etc ... auquel vous devez pouvoir accéder pour une raison quelconque) à n'importe quel endroit du document:$("*").filter(function() { return $(this).data("DATA IDENTIFIER HERE") == DATA VALUE HERE; });
Tschallacka
ce n'est pas "compliqué" - c'est le seul moyen sûr de filtrer sur des termes arbitraires sans exiger que vous "échappiez" à ces valeurs pour vous assurer que la concaténation du terme de recherche avec le reste du sélecteur ne crée pas un sélecteur illégal.
Alnitak
145

Juste pour mémoire, vous pouvez filtrer sur les données avec jquery (cette question est assez ancienne, et jQuery a évolué depuis, il est donc juste d'écrire cette solution également):

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

ou mieux (pour les performances):

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

ou, si vous voulez obtenir tous les éléments avec data-selectedset:

$('[data-selected]')

Notez que cette méthode ne fonctionnera qu'avec les données définies via les attributs html. Si vous définissez ou modifiez des données avec l' .data()appel, cette méthode ne fonctionnera plus.

StefanoP
la source
9
si le faible nombre de votes pour cette réponse vous fait peur - c'est la réponse acceptée avec plus de 100 votes pour une question pratiquement identique stackoverflow.com/questions/4146502
Simon_Weaver
48
-1 Cela ne fonctionne pas lorsque les données sont définies avec la .data()méthode au lieu d'un data-attribut. Voir ce violon: jsfiddle.net/bryandowning/tySWC - De plus, la .find()méthode recherche les enfants du sélecteur précédent. Dans l'exemple donné, data-selectedest un attribut de .navlink, pas un enfant de .navlink. Aussi, $('div p')et $('div').find('p')sont essentiellement équivalents. L'utilisation .find()semble être plus lente en raison de l'appel de fonction supplémentaire (bien que je ne sois pas certain à ce sujet). Veuillez me corriger si je me trompe à ce sujet (je souhaite vraiment que cette méthode fonctionne).
Bryan Downing
3
deux ou trois choses: 1) vous avez raison de dire que cela ne fonctionne pas si vous définissez des données avec .data(), puisque jQuery recherche dans le DOM, je l'ai posté pour ceux (comme moi) qui sont arrivés à cette question pour d'autres raisons; 2) correct, .find()recherche parmi les enfants, donc c'est faux dans cet exemple; 3) vous vous trompez, ils ne sont pas équivalents, car jQuery recherche de droite à gauche, voir jonraasch.com/blog
...
2
Voter pour $('[data-selected]')cela m'a aidé pour quelque chose comme$('ul.categories a[data-categories_id]').click(......);
Luke Cousins
De plus, il semble que si vous mettez à jour l'attribut de données à l'aide de .attr, si vous le récupérez à l'aide de .data, la valeur ne sera pas mise à jour - soyez donc prudent lorsque vous mélangez les deux
Fabio Lolli
13

Nous pouvons créer un plugin assez facilement:

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

Utilisation (vérification d'un bouton radio):

$('input[name=location_id]').filterData('my-data','data-val').prop('checked',true);
mpen
la source
Vous voulez dire la méthode du plugin sinon c'est la même chose que la réponse acceptée ...
jave.web
@ jave.web En effet. Mais tout le monde ne sait pas comment le transformer en plugin. Verbiage mis à jour.
mpen
ne vous méprenez pas, votre réponse est excellente, mais les mots ici sont très importants, merci pour la mise à jour :)
jave.web
8

Deux choses que j'ai remarquées (ce sont peut-être des erreurs du moment où vous l'avez écrit).

  1. Vous avez manqué un point dans le premier exemple ( $('.navlink').click)
  2. Pour que le filtre fonctionne, vous devez renvoyer une valeur ( return $(this).data("selected")==true)
Thomas
la source
-1

Sonne comme plus de travail que sa valeur.

1) Pourquoi ne pas avoir une seule variable JavaScript qui stocke une référence à l'élément \ jQuery actuellement sélectionné.

2) Pourquoi ne pas ajouter une classe à l'élément actuellement sélectionné. Ensuite, vous pouvez interroger le DOM pour la classe ".active" ou quelque chose.

Bryan Migliorisi
la source
Ouais, mais comme je l'ai dit, je savais qu'il y avait d'autres moyens de le faire. Je me demandais simplement si cela pouvait être filtré via data () et pourquoi filter () ne fonctionnait pas pour moi. Merci quand même.
user113716
Désolé. J'ai manqué cette partie de votre question.
Bryan Migliorisi