J'ai besoin de sélectionner des éléments en fonction des valeurs stockées dans l' .data()
objet d' un élément . Au minimum, j'aimerais sélectionner les propriétés de données de niveau supérieur à l'aide de sélecteurs, peut-être comme ceci:
$('a').data("category","music");
$('a:data(category=music)');
Ou peut-être que le sélecteur serait au format de sélecteur d'attribut normal:
$('a[category=music]');
Ou au format d'attribut, mais avec un spécificateur pour indiquer qu'il est dans .data()
:
$('a[:category=music]');
J'ai trouvé la mise en œuvre de James Padolsey simple, mais bonne. Les formats de sélecteur ci-dessus reflètent les méthodes affichées sur cette page. Il y a aussi ce patch Sizzle .
Pour une raison quelconque, je me souviens avoir lu il y a quelque temps que jQuery 1.4 inclurait la prise en charge des sélecteurs sur les valeurs de l' .data()
objet jquery . Cependant, maintenant que je le cherche, je ne le trouve pas. C'était peut-être juste une demande de fonctionnalité que j'ai vue. Y a-t-il un soutien pour cela et je ne le vois tout simplement pas?
Idéalement, j'aimerais prendre en charge les sous-propriétés dans data () en utilisant la notation par points. Comme ça:
$('a').data("user",{name: {first:"Tom",last:"Smith"},username: "tomsmith"});
$('a[:user.name.first=Tom]');
Je voudrais également prendre en charge plusieurs sélecteurs de données, où seuls les éléments avec TOUS les sélecteurs de données spécifiés sont trouvés. Le sélecteur multiple jquery régulier effectue une opération OR. Par exemple, $('a.big, a.small')
sélectionne les a
balises avec la classe big
ou small
). Je recherche un ET, peut-être comme ceci:
$('a').data("artist",{id: 3281, name: "Madonna"});
$('a').data("category","music");
$('a[:category=music && :artist.name=Madonna]');
Enfin, ce serait formidable si les opérateurs de comparaison et les fonctionnalités regex étaient disponibles sur les sélecteurs de données. Ce $(a[:artist.id>5000])
serait donc possible. Je me rends compte que je pourrais probablement faire une grande partie de cela en utilisant filter()
, mais ce serait bien d'avoir un format de sélecteur simple.
Quelles solutions sont disponibles pour ce faire? Est-ce que Jame's Padolsey est la meilleure solution en ce moment? Ma préoccupation concerne principalement les performances, mais aussi les fonctionnalités supplémentaires telles que la notation par points de sous-propriété et les sélecteurs de données multiples. Y a-t-il d'autres implémentations qui prennent en charge ces choses ou qui sont meilleures d'une certaine manière?
la source
Réponses:
J'ai créé un nouveau
data
sélecteur qui devrait vous permettre d'effectuer des requêtes imbriquées et des conditions AND. Usage:$('a:data(category==music,artist.name==Madonna)');
Le modèle est:
:data( {namespace} [{operator} {check}] )
"opérateur" et "contrôle" sont facultatifs. Donc, si vous l'avez seulement, vous
:data(a.b.c)
vérifierez simplement la véracité dea.b.c
.Vous pouvez voir les opérateurs disponibles dans le code ci-dessous. Parmi eux, il est
~=
possible de tester les regex:$('a:data(category~=^mus..$,artist.name~=^M.+a$)');
Je l'ai testé avec quelques variantes et il semble fonctionner assez bien. Je vais probablement l'ajouter bientôt en tant que dépôt Github (avec une suite de tests complète), alors gardez un œil sur!
Le code:
(function(){ var matcher = /\s*(?:((?:(?:\\\.|[^.,])+\.?)+)\s*([!~><=]=|[><])\s*("|')?((?:\\\3|.)*?)\3|(.+?))\s*(?:,|$)/g; function resolve(element, data) { data = data.match(/(?:\\\.|[^.])+(?=\.|$)/g); var cur = jQuery.data(element)[data.shift()]; while (cur && data[0]) { cur = cur[data.shift()]; } return cur || undefined; } jQuery.expr[':'].data = function(el, i, match) { matcher.lastIndex = 0; var expr = match[3], m, check, val, allMatch = null, foundMatch = false; while (m = matcher.exec(expr)) { check = m[4]; val = resolve(el, m[1] || m[5]); switch (m[2]) { case '==': foundMatch = val == check; break; case '!=': foundMatch = val != check; break; case '<=': foundMatch = val <= check; break; case '>=': foundMatch = val >= check; break; case '~=': foundMatch = RegExp(check).test(val); break; case '>': foundMatch = val > check; break; case '<': foundMatch = val < check; break; default: if (m[5]) foundMatch = !!val; } allMatch = allMatch === null ? foundMatch : allMatch && foundMatch; } return allMatch; }; }());
la source
$("a:data(condition),a:data(orCondition)")
... cela aura le même effet. Plus vous ajoutez de fonctionnalités, plus ce sera lent. Si la logique est complexe, utilisez$(foo).filter(function(){...})
.jQuery.data
, qui n'obtient pas les données définies dans les attributs HTML5. Si vous voulez cette fonctionnalité, vous pouvez passerjQuery.data
à$('selector').data
, mais c'est un compromis pour la vitesse.Pour le moment, je sélectionne comme ceci:
$('a[data-attribute=true]')
Ce qui semble fonctionner très bien, mais ce serait bien si jQuery pouvait sélectionner par cet attribut sans le préfixe «data-».
Je n'ai pas testé cela avec des données ajoutées aux éléments via jQuery dynamiquement, donc cela pourrait être la chute de cette méthode.
la source
Vous pouvez également utiliser une fonction de filtrage simple sans aucun plug-in. Ce n'est pas exactement ce que vous voulez mais le résultat est le même:
$('a').data("user", {name: {first:"Tom",last:"Smith"},username: "tomsmith"}); $('a').filter(function() { return $(this).data('user') && $(this).data('user').name.first === "Tom"; });
la source
filter
fonction de traversée pourrait accepter une fonction de test =) merciJe veux vous avertir que
$('a[data-attribute=true]')
cela ne fonctionne pas, selon la réponse d'Ashley, si vous avez joint des données à un élément DOM via la fonction data ().Cela fonctionne comme vous vous en doutez si vous avez ajouté un data-attr réel dans votre HTML, mais jQuery stocke les données en mémoire, de sorte que les résultats que vous obtiendrez ne
$('a[data-attribute=true]')
seraient pas corrects.Vous devrez utiliser le plugin de données http://code.google.com/p/jquerypluginsblog/ , utiliser la
filter
solution de Dmitri ou faire un $ .each sur tous les éléments et vérifier .data () de manière itérativela source
Il y a un
:data()
plugin de filtre qui fait exactement cela :)Quelques exemples basés sur votre question:
$('a:data("category=music")') $('a:data("user.name.first=Tom")'); $('a:data("category=music"):data("artist.name=Madonna")'); //jQuery supports multiple of any selector to restrict further, //just chain with no space in-between for this effect
Les performances ne seront pas extrêmement bonnes par rapport à ce qui est possible , sélectionner
$._cache
et saisir les éléments correspondants est de loin le plus rapide, mais beaucoup plus rond et pas très "jQuery-ey" en termes de comment vous y arriver trucs (vous venez généralement du côté de l'élément). De toute façon, je ne suis pas sûr que ce soit le plus rapide, car le processus de passage de l'identifiant unique à l'élément est compliqué en lui-même, en termes de performances.Le sélecteur de comparaison que vous avez mentionné sera préférable de le faire dans un
.filter()
, il n'y a pas de support intégré pour cela dans le plugin, bien que vous puissiez l'ajouter sans trop de problèmes.la source
data-*
attributs HTML5 et les sélectionner serait plus rapide que sélectionner des.data()
propriétés? Aussi, une idée où puis-je en savoir plus sur $ ._ cache? J'ai cherché sur Google, mais je ne trouve pas grand-chose.$.cache
pas$._cache
, vous pouvez voir comment il est implémenté et utilisé dans jQuery core ici: github.com/jquery/jquery/blob/master/src/data.js#L4 Quand vous appelez,.data()
il le stocke en fait comme un objet in$.cache[elementUniqueID]
, qui est un identifiant attribué au besoin de manière incrémentale à chaque élément, par exemple 1, 2, 3, etc. Cet identifiant grimpant sera exposé dans jQuery 1.4.3 je crois, basé sur les commentaires de git l'autre jour. Je suppose que l'itinéraire HTML 5 serait plus rapide, cela dépend des optimisations de navigateur disponibles (je suis sûr que d'autres seront disponibles).Vous pouvez définir un
data-*
attribut sur un orme en utilisantattr()
, puis sélectionner en utilisant cet attribut:var elm = $('a').attr('data-test',123); //assign 123 using attr() elm = $("a[data-test=123]"); //select elm using attribute
et maintenant pour cet orme, les deux
attr()
etdata()
donneront 123 :console.log(elm.attr('data-test')); //123 console.log(elm.data('test')); //123
Cependant, si vous modifiez la valeur pour qu'elle soit 456 en utilisant
attr()
,data()
sera toujours 123 :elm.attr('data-test',456); //modify to 456 elm = $("a[data-test=456]"); //reselect elm using new 456 attribute console.log(elm.attr('data-test')); //456 console.log(elm.data('test')); //123
Donc, si je comprends bien, il semble que vous devriez probablement éviter les mélanges
attr()
et lesdata()
commandes dans votre code si vous n'êtes pas obligé. Carattr()
semble correspondre directement avec le DOM alors qu'ildata()
interagit avec la «mémoire», bien que sa valeur initiale puisse provenir du DOM. Mais le point clé est que les deux ne sont pas nécessairement synchronisés du tout.Alors faites attention.
En tout cas, si vous ne changez pas l'
data-*
attribut dans le DOM ou dans la mémoire, vous n'aurez pas de problème. Dès que vous commencez à modifier les valeurs, des problèmes potentiels peuvent survenir.Merci à @Clarence Liu pour la réponse de @ Ash, ainsi que pour ce post .
la source
$('a[data-category="music"]')
Ça marche. Voir Sélecteur d'attribut égal [nom = "valeur"] .
la source
Si vous utilisez également jQueryUI, vous obtenez une version (simple) du
:data
sélecteur qui vérifie la présence d'un élément de données, vous pouvez donc faire quelque chose comme$("div:data(view)")
, ou$( this ).closest(":data(view)")
.Voir http://api.jqueryui.com/data-selector/ . Je ne sais pas depuis combien de temps ils l'ont, mais c'est là maintenant!
la source
Voici un plugin qui simplifie la vie https://github.com/rootical/jQueryDataSelector
Utilisez-le comme ça:
data selector jQuery selector $$('name') $('[data-name]') $$('name', 10) $('[data-name=10]') $$('name', false) $('[data-name=false]') $$('name', null) $('[data-name]') $$('name', {}) Syntax error
la source