Obter lista de atributos data- * usando javascript / jQuery

Dado um elemento HTML arbitrário com zero ou mais atributos data-* , como é possível recuperar uma lista de pares de valores-chave para os dados.

Por exemplo, dado isto:

 
blah

Eu gostaria de poder recuperar programaticamente isso:

 { "id":10, "cat":"toy", "cid":42 } 

Usando jQuery (v1.4.3), acessar os bits individuais de dados usando $.data() é simples se as chaves são conhecidas antecipadamente, mas não é óbvio como se pode fazer isso com conjuntos arbitrários de dados.

Estou procurando uma solução jQuery “simples”, se existir, mas não me importaria com uma abordagem de baixo nível. Eu tive que tentar analisar os $('#prod').attributes Mas minha falta de javascript-fu está me deixando pra baixo.

atualizar

customdata faz o que eu preciso. No entanto, include um plugin jQuery apenas por uma fração de sua funcionalidade parecia um exagero.

Orientar a fonte me ajudou a corrigir meu próprio código (e melhorou meu javascript-fu).

Aqui está a solução que eu criei:

 function getDataAttributes(node) { var d = {}, re_dataAttr = /^data\-(.+)$/; $.each(node.get(0).attributes, function(index, attr) { if (re_dataAttr.test(attr.nodeName)) { var key = attr.nodeName.match(re_dataAttr)[1]; d[key] = attr.nodeValue; } }); return d; } 

atualização 2

Como demonstrado na resposta aceita, a solução é trivial com jQuery (> = 1.4.4). $('#prod').data() retornaria o dit de dados requerido.

Na verdade, se você está trabalhando com jQuery, a partir da versão 1.4.3 1.4.4 (por causa do bug como mencionado nos comentários abaixo), os atributos data-* são suportados através de .data() :

A partir do jQuery 1.4.3, os atributos de data- HTML 5 serão automaticamente inseridos no object de dados do jQuery.

Observe que as seqüências de caracteres são deixadas intactas enquanto os valores JavaScript são convertidos em seu valor associado (isso inclui booleanos, números, objects, matrizes e nulos). Os atributos de data- são extraídos na primeira vez que a propriedade de dados é acessada e, em seguida, não são mais acessados ​​ou mutados (todos os valores de dados são armazenados internamente em jQuery).

A function jQuery.fn.data retornará todos os atributos de data- dentro de um object como pares de valor-chave, com a chave sendo a parte do nome do atributo após data- e o valor sendo o valor desse atributo após ser convertido após as regras mencionadas acima.

Eu também criei uma demonstração simples se isso não te convencer: http://jsfiddle.net/yijiang/WVfSg/

Uma solução JavaScript pura deve ser oferecida também, pois a solução não é difícil:

 var a = [].filter.call(el.attributes, function(at) { return /^data-/.test(at.name); }); 

Isso fornece uma matriz de objects de atributo, que possuem propriedades de name e value :

 if (a.length) { var firstAttributeName = a[0].name; var firstAttributeValue = a[0].value; } 

Edit: Para dar um passo adiante, você pode obter um dictionary, iterando os atributos e preenchendo um object de dados:

 var data = {}; [].forEach.call(el.attributes, function(attr) { if (/^data-/.test(attr.name)) { var camelCaseName = attr.name.substr(5).replace(/-(.)/g, function ($0, $1) { return $1.toUpperCase(); }); data[camelCaseName] = attr.value; } }); 

Você poderia então acessar o valor de, por exemplo, data-my-value="2" como data.myValue ;

jsfiddle.net/3KFYf/33

Edit: Se você quisesse definir atributos de dados em seu elemento de forma programática a partir de um object, você poderia:

 Object.keys(data).forEach(function(key) { var attrName = "data-" + key.replace(/[AZ]/g, function($0) { return "-" + $0.toLowerCase(); }); el.setAttribute(attrName, data[key]); }); 

jsfiddle.net/3KFYf/34

EDIT: Se você estiver usando o babel ou o TypeScript, ou codificando somente para navegadores es6, este é um bom lugar para usar as funções de seta es6 e encurtar o código um pouco:

 var a = [].filter.call(el.attributes, at => /^data-/.test(at.name)); 

Dê uma olhada aqui :

Se o navegador também suportar a API JavaScript do HTML5, você poderá obter os dados com:

 var attributes = element.dataset 

ou

 var cat = element.dataset.cat 

Ah, mas eu também li:

Infelizmente, a nova propriedade de dataset ainda não foi implementada em nenhum navegador, portanto, é melhor usar getAttribute e setAttribute como demonstrado anteriormente.

É de maio de 2010.


Se você usar o jQuery de qualquer maneira, talvez queira dar uma olhada no plug- in customdata . Eu não tenho experiência com isso.

Como mencionado acima, os navegadores modernos têm a API The HTMLElement.dataset .
Essa API fornece um DOMStringMap e você pode recuperar a lista de atributos data-* simplesmente faz:

 var dataset = el.dataset; // as you asked in the question 

você também pode recuperar uma matriz com os nomes das chaves da propriedade de data- como

 var data = Object.keys(el.dataset); 

ou mapear seus valores por

 Object.keys(el.dataset).map(function(key){ return el.dataset[key];}); // or the ES6 way: Object.keys(el.dataset).map(key=>{ return el.dataset[key];}); 

e assim você pode iterar e usá-los sem a necessidade de filtrar entre todos os atributos do elemento como precisávamos fazer antes .

ou converta a excelente resposta de gilly3 para um método jQuery:

 $.fn.info = function () { var data = {}; [].forEach.call(this.get(0).attributes, function (attr) { if (/^data-/.test(attr.name)) { var camelCaseName = attr.name.substr(5).replace(/-(.)/g, function ($0, $1) { return $1.toUpperCase(); }); data[camelCaseName] = attr.value; } }); return data; } 

Usando: $('.foo').info() ;

Você deve obter os dados através dos atributos do dataset

 var data = element.dataset; 

dataset é uma ferramenta útil para obter o atributo de dados