Get list of data-* attributes using javascript / j

2019-01-02 22:35发布

Given an arbitrary HTML element with zero or more data-* attributes, how can one retrieve a list of key-value pairs for the data.

E.g. given this:

<div id='prod' data-id='10' data-cat='toy' data-cid='42'>blah</div>

I would like to be able to programmatically retrieve this:

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

Using jQuery (v1.4.3), accessing the individual bits of data using $.data() is simple if the keys are known in advance, but it is not obvious how one can do so with arbitrary sets of data.

I'm looking for a 'simple' jQuery solution if one exists, but would not mind a lower level approach otherwise. I had a go at trying to to parse $('#prod').attributes but my lack of javascript-fu is letting me down.

update

customdata does what I need. However, including a jQuery plugin just for a fraction of its functionality seemed like an overkill.

Eyeballing the source helped me fix my own code (and improved my javascript-fu).

Here's the solution I came up with:

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

update 2

As demonstrated in the accepted answer, the solution is trivial with jQuery (>=1.4.4). $('#prod').data() would return the required data dict.

8条回答
对你真心纯属浪费
2楼-- · 2019-01-02 23:11

You should be get the data through the dataset attributes

var data = element.dataset;

dataset is useful tool for get data-attribute

查看更多
小情绪 Triste *
3楼-- · 2019-01-02 23:16

Have a look here:

If the browser also supports the HTML5 JavaScript API, you should be able to get the data with:

var attributes = element.dataset

or

var cat = element.dataset.cat

Oh, but I also read:

Unfortunately, the new dataset property has not yet been implemented in any browser, so in the meantime it’s best to use getAttribute and setAttribute as demonstrated earlier.

It is from May 2010.


If you use jQuery anyway, you might want to have a look at the customdata plugin. I have no experience with it though.

查看更多
ら.Afraid
4楼-- · 2019-01-02 23:17

You can just iterate over the data attributes like any other object to get keys and values, here's how to do it with $.each:

    $.each($('#myEl').data(), function(key, value) {
        console.log(key);
        console.log(value);
    });
查看更多
\"骚年 ilove
5楼-- · 2019-01-02 23:23

One way of finding all data attributes is using element.attributes. Using .attributes, you can loop through all of the element attributes, filtering out the items which include the string "data-".

let element = document.getElementById("element");

function getDataAttributes(element){
    let elementAttributes = {},
        i = 0;

    while(i < element.attributes.length){
        if(element.attributes[i].name.includes("data-")){
            elementAttributes[element.attributes[i].name] = element.attributes[i].value
        }
        i++;
    }

    return elementAttributes;

}
查看更多
Explosion°爆炸
6楼-- · 2019-01-02 23:25

A pure JavaScript solution ought to be offered as well, as the solution is not difficult:

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

This gives an array of attribute objects, which have name and value properties:

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

Edit: To take it a step further, you can get a dictionary by iterating the attributes and populating a data object:

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

You could then access the value of, for example, data-my-value="2" as data.myValue;

jsfiddle.net/3KFYf/33

Edit: If you wanted to set data attributes on your element programmatically from an object, you could:

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

jsfiddle.net/3KFYf/34

EDIT: If you are using babel or TypeScript, or coding only for es6 browsers, this is a nice place to use es6 arrow functions, and shorten the code a bit:

var a = [].filter.call(el.attributes, at => /^data-/.test(at.name));
查看更多
\"骚年 ilove
7楼-- · 2019-01-02 23:28

As mentioned above modern browsers have the The HTMLElement.dataset API.
That API gives you a DOMStringMap, and you can retrieve the list of data-* attributes simply doing:

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

you can also retrieve a array with the data- property's key names like

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

or map its values by

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

and like this you can iterate those and use them without the need of filtering between all attributes of the element like we needed to do before.

查看更多
登录 后发表回答