Получить список атрибутов data- * с помощью javascript/jQuery

Учитывая произвольный элемент HTML с нулевыми или более атрибутами data-*, как можно получить список пар ключ-значение для данных.

например. учитывая это:

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

Я хотел бы иметь возможность программно получить это:

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

Использование jQuery (v1.4.3), доступ к отдельным битам данных с помощью $.data() прост, если ключи известны заранее, но не очевидно, как это можно сделать с произвольными наборами данных.

Я ищу "простое" решение jQuery, если оно существует, но не обращает внимания на подход более низкого уровня. Я попытался разобрать $('#prod').attributes, но моя нехватка javascript-fu меня подвела.

Обновление

customdata делает то, что мне нужно. Однако включение плагина jQuery только для части его функциональности показалось излишним.

Наблюдение за источником помогло мне исправить мой собственный код (и улучшил мой javascript-fu).

В этом решении я придумал:

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

Как показано в принятом ответе, решение тривиально с jQuery ( >= 1.4.4). $('#prod').data() вернет требуемые данные dict.

Ответ 1

На самом деле, если вы работаете с jQuery, с версии 1.4.3 <1.4 > 1.4.4 (из-за ошибки, указанной в комментариях ниже), атрибуты data-* поддерживаются через .data():

Как в jQuery 1.4.3 HTML 5 data-атрибуты будут автоматически втянутый в объект данных jQuery.

Обратите внимание, что строки остаются нетронутыми а значения JavaScript преобразуются к их связанной стоимости (это включает в себя булевы, числа, объекты, массивы и null). data-атрибуты вытягиваются в первом доступ к ресурсу данных и затем больше не доступны или не мутируются (тогда сохраняются все значения данных внутри jQuery).

Функция jQuery.fn.data возвращает весь атрибут data- внутри объекта как пары ключ-значение, причем ключ был частью имени атрибута после data-, а значение было значением этого атрибута после были преобразованы в соответствии с указанными выше правилами.

Я также создал простую демонстрацию, если это вас не убедит: http://jsfiddle.net/yijiang/WVfSg/

Ответ 2

Также должно быть предложено чистое решение JavaScript, так как решение не сложно:

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

Это дает массив объектов атрибутов, которые имеют свойства name и value:

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

Изменить: Чтобы сделать это еще дальше, вы можете получить словарь, итерации атрибутов и заполнения объекта данных:

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

Затем вы можете получить доступ к значению, например, data-my-value="2" как data.myValue;

jsfiddle.net/3KFYf/33

Изменить: Если вы хотите программно установить атрибуты данных в своем элементе из объекта, вы можете:

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: Если вы используете babel или TypeScript или кодируете только для браузеров es6, это хорошее место для использования функций стрелок es6 и немного сокращает код:

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

Ответ 3

Посмотрите здесь:

Если браузер также поддерживает JavaScript API HTML5, вы можете получить данные с помощью:

var attributes = element.dataset

или

var cat = element.dataset.cat

О, но я также читал:

К сожалению, новое свойство набора данных еще не реализовано ни в одном браузере, так что пока лучше использовать getAttribute и setAttribute, как показано ранее.

Это с мая 2010 года.


Если вы все равно используете jQuery, вам может понадобиться посмотреть плагин customdata​​strong > . Однако у меня нет опыта в этом.

Ответ 4

Как упоминалось выше современные браузеры имеют HTMLElement.dataset API.
Этот API дает вам DOMStringMap, и вы можете получить список атрибутов data-*, просто выполнив:

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

вы также можете получить массив с именами ключей свойств data-, например

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

или сопоставить его значения на

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

и т.д., вы можете повторять эти действия и использовать их без необходимости фильтрации между всеми атрибутами элемента как это было необходимо перед.

Ответ 5

Вы должны получить данные через атрибуты набора данных

var data = element.dataset;

dataset - полезный инструмент для получения атрибута данных

Ответ 6

или конвертировать gilly3 отличный ответ на метод 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;
}

Использование: $('.foo').info();