selettore dati jQuery

Devo selezionare gli elementi in base ai valori memorizzati .data() un elemento. Come minimo, vorrei selezionare le proprietà dei dati di livello superiore usando selettori, forse in questo modo:

 $('a').data("category","music"); $('a:data(category=music)'); 

O forse il selettore dovrebbe essere nel normale formato di selettore degli attributi:

 $('a[category=music]'); 

Oppure in formato attributo, ma con un .data() per indicare che è in .data() :

 $('a[:category=music]'); 

Ho trovato l’implementazione di James Padolsey per sembrare semplice, ma buona. Il selettore formatta sopra i metodi mirror mostrati in quella pagina. C’è anche questa patch Sizzle .

Per qualche ragione, ricordo di aver letto un po ‘indietro che jQuery 1.4 avrebbe incluso il supporto per i selettori sui valori .data() jquery .data() . Tuttavia, ora che lo sto cercando, non riesco a trovarlo. Forse era solo una richiesta di funzionalità che ho visto. C’è supporto per questo e io non lo vedo?

Idealmente, mi piacerebbe supportare le sotto-proprietà in data () usando la notazione dot. Come questo:

 $('a').data("user",{name: {first:"Tom",last:"Smith"},username: "tomsmith"}); $('a[:user.name.first=Tom]'); 

Vorrei anche supportare più selettori di dati, in cui vengono trovati solo gli elementi con TUTTI i selettori di dati specificati. Il normale selettore multiplo jQuery esegue un’operazione OR. Ad esempio, $('a.big, a.small') seleziona a tag con una class big o small ). Sto cercando un AND, forse in questo modo:

 $('a').data("artist",{id: 3281, name: "Madonna"}); $('a').data("category","music"); $('a[:category=music && :artist.name=Madonna]'); 

Infine, sarebbe bello se gli operatori di confronto e le caratteristiche di regex fossero disponibili sui selettori di dati. Quindi $(a[:artist.id>5000]) sarebbe ansible. Mi rendo conto che probabilmente potrei fare molto di questo usando filter() , ma sarebbe bello avere un semplice formato di selezione.

Quali soluzioni sono disponibili per fare questo? Jame’s Padolsey è la soluzione migliore in questo momento? La mia preoccupazione riguarda principalmente le prestazioni, ma anche le funzionalità extra come la notazione puntiforms sotto la proprietà e più selettori di dati. Esistono altre implementazioni che supportano queste cose o sono in qualche modo migliori?

Ho creato un nuovo selettore di data che dovrebbe consentire di eseguire query nidificate e condizioni AND. Uso:

 $('a:data(category==music,artist.name==Madonna)'); 

Il modello è:

 :data( {namespace} [{operator} {check}] ) 

“operator” e “check” sono opzionali. Quindi, se hai solo :data(abc) controllerà semplicemente la veridicità di abc .

Puoi vedere gli operatori disponibili nel codice qui sotto. Tra di loro è ~= che consente il test regex:

 $('a:data(category~=^mus..$,artist.name~=^M.+a$)'); 

L’ho provato con alcune varianti e sembra funzionare abbastanza bene. Probabilmente lo aggiungerò presto come repo Github (con una suite di test completa), quindi tieni d’occhio!

Il codice:

 (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; }; }()); 

Al momento sto selezionando in questo modo:

 $('a[data-attribute=true]') 

Che sembra funzionare bene, ma sarebbe bello se jQuery fosse in grado di selezionare quell’attributo senza il prefisso ‘data-‘.

Non ho provato questo con i dati aggiunti agli elementi via jQuery in modo dinamico, in modo che potrebbe essere la rovina di questo metodo.

Puoi anche utilizzare una semplice funzione di filtro senza plugin. Questo non è esattamente quello che vuoi ma il risultato è lo stesso:

 $('a').data("user", {name: {first:"Tom",last:"Smith"},username: "tomsmith"}); $('a').filter(function() { return $(this).data('user') && $(this).data('user').name.first === "Tom"; }); 

Voglio avvisarti che $('a[data-attribute=true]') non funziona, come da risposta di Ashley, se hai collegato i dati a un elemento DOM tramite la funzione data ().

Funziona come ci si aspetterebbe se aggiungessi un dato effettivo-attr nel tuo HTML, ma jQuery memorizza i dati in memoria, quindi i risultati che otterresti da $('a[data-attribute=true]') non sarebbero sii corretto

Dovrai utilizzare il plug-in dei dati http://code.google.com/p/jquerypluginsblog/ , utilizzare la soluzione di filter di Dmitri o eseguire un $ .each su tutti gli elementi e controllare .data () in modo iterativo

C’è un plug-in del filtro :data() che fa proprio questo 🙂

Alcuni esempi basati sulla tua domanda:

 $('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 

La performance non sarà molto grande rispetto a ciò che è ansible , selezionando da $._cache e afferrando gli elementi corrispondenti è di gran lunga il più veloce, ma molto più round-about e non molto “jQuery-ey” in termini di come ottieni cose (di solito entri dal lato dell’elemento). In cima alla mia testa, non sono sicuro che questo sia il più veloce in ogni caso, dal momento che il processo di passare da un ID univoco a un elemento è contorto di per sé, in termini di prestazioni.

Il selettore di confronto che hai menzionato sarà il migliore da fare in un file .filter() , non c’è un supporto integrato per questo nel plugin, sebbene tu possa aggiungerlo senza molti problemi.

Puoi impostare un attributo data-* su un elm usando attr() , e quindi selezionare usando quell’attributo:

 var elm = $('a').attr('data-test',123); //assign 123 using attr() elm = $("a[data-test=123]"); //select elm using attribute 

e ora per quell’olm, sia attr() che data() arriveranno a 123 :

 console.log(elm.attr('data-test')); //123 console.log(elm.data('test')); //123 

Tuttavia, se si modifica il valore per essere 456 utilizzando attr() , data() sarà ancora 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 

Quindi, come ho capito, sembra che probabilmente dovresti evitare di mescolare i comandi attr() e data() nel tuo codice se non dovessi farlo. Poiché attr() sembra corrispondere direttamente al DOM mentre data() interagisce con la ‘memoria’, sebbene il suo valore iniziale possa provenire dal DOM. Ma il punto chiave è che i due non sono necessariamente sincronizzati.

Quindi stai attento.

In ogni caso, se non si modifica l’attributo data-* nel DOM o nella memoria, non si avrà alcun problema. Non appena inizi a modificare i valori, si possono verificare potenziali problemi.

Grazie a @Clarence Liu alla @ risposta di Ash, così come questo post .

 $('a[data-category="music"]') 

Funziona. Vedi Attributo Uguale al selettore [nome = “valore”] .

Se usi anche jQueryUI, ottieni una (semplice) versione di :data selettore di :data con esso che controlla la presenza di un elemento di dati, quindi puoi fare qualcosa come $("div:data(view)") , o $( this ).closest(":data(view)") .

Vedi http://api.jqueryui.com/data-selector/ . Non so per quanto tempo l’hanno avuto, ma è lì ora!

Ecco un plugin che semplifica la vita https://github.com/rootical/jQueryDataSelector

Usalo così:

 data selector jQuery selector $$('name') $('[data-name]') $$('name', 10) $('[data-name=10]') $$('name', false) $('[data-name=false]') $$('name', null) $('[data-name]') $$('name', {}) Syntax error