0個以上のdata-*
属性を持つ任意のHTML要素が与えられた場合、データのキーと値のペアのリストをどのように取得できますか。
例えば。これを考えると:
<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;
}
受け入れられた答えで示されているように、このソリューションはjQuery(> = 1.4.4)で簡単です。 $('#prod').data()
は、必要なデータ辞書を返します。
実際、バージョンの時点でjQueryを使用している場合 1.4.3 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/
ソリューションは難しくないため、純粋な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;
}
Edit:さらに一歩進めるために、属性を繰り返してデータオブジェクトに入力することで辞書を取得できます:
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
としてアクセスできます。
Edit:オブジェクトからプログラムで要素にデータ属性を設定したい場合は、次のことができます。
Object.keys(data).forEach(function(key) {
var attrName = "data-" + key.replace(/[A-Z]/g, function($0) {
return "-" + $0.toLowerCase();
});
el.setAttribute(attrName, data[key]);
});
EDIT:babelまたはTypeScriptを使用している場合、またはes6ブラウザーのみをコーディングしている場合、これはes6矢印関数を使用してコードを短縮するのに最適な場所です少し:
var a = [].filter.call(el.attributes, at => /^data-/.test(at.name));
ブラウザがHTML5 JavaScript APIもサポートしている場合、次の方法でデータを取得できるはずです。
var attributes = element.dataset
または
var cat = element.dataset.cat
ああ、でも私は読んだ:
残念ながら、新しいデータセットプロパティはどのブラウザにもまだ実装されていないため、当面は、前述のように
getAttribute
およびsetAttribute
を使用するのが最善です。
2010年5月からです。
とにかくjQueryを使用する場合は、 customdata プラグインをご覧ください。私はそれで経験がありません。
上記のように 最新のブラウザ には The 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];});
このように、要素のすべての属性間でフィルタリングする必要なく、それらを反復して使用できます 前に行う必要があったように 。
または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()
;
すべてのデータ属性を見つける1つの方法は、 element.attributes
を使用することです。 .attributes
を使用すると、すべての要素属性をループして、文字列「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;
}
他のオブジェクトと同様にデータ属性を反復処理してキーと値を取得できます。以下に$.each
を使用してそれを行う方法を示します。
$.each($('#myEl').data(), function(key, value) {
console.log(key);
console.log(value);
});