Create a gist now

Instantly share code, notes, and snippets.

data-* support
(function () {
var forEach = [].forEach,
regex = /^data-(.+)/,
dashChar = /\-([a-z])/ig,
el = document.createElement('div'),
mutationSupported = false,
function detectMutation() {
mutationSupported = true;
this.removeEventListener('DOMAttrModified', detectMutation, false);
function toCamelCase(s) {
return s.replace(dashChar, function (m,l) { return l.toUpperCase(); });
function updateDataset() {
var dataset = {};, function(attr) {
if (match =
dataset[toCamelCase(match[1])] = attr.value;
return dataset;
// only add support if the browser doesn't support data-* natively
if (el.dataset != undefined) return;
el.addEventListener('DOMAttrModified', detectMutation, false);
el.setAttribute('foo', 'bar');
Element.prototype.__defineGetter__('dataset', mutationSupported
? function () {
if (!this._datasetCache) {
this._datasetCache =;
return this._datasetCache;
: updateDataset
document.addEventListener('DOMAttrModified', function (event) {
}, false);
<!DOCTYPE html>
<meta charset=utf-8 />
<title>test data-*</title>
<script src="data.js"></script>
<p data-id="ok" data-name="remy" data-screen-name="rem" id="hello">Hello World</p>
var el = document.getElementById('hello'), dl = el.dataset, a = [], key;
for (key in dl) a.push(key + ': ' + dl[key]);
a.length = 0;
el.setAttribute('data-foo', 'bar');
if (el._datasetCache) alert('Houston: we have a problem!');
dl = el.dataset;
for (key in dl) a.push(key + ': ' + dl[key]);
remy commented Apr 29, 2010

Note that setting doesn't work - you have to set this manually on the element via setAttribute. I've not found a way yet that I can define a setter on an unknown property on an object. When the el.dataset object has a property change or updated, it should create a new attribute on the element, but we can't catch that particular update, so it's a no go.


Is there any reason not to just use setAttribute and getAttribute (or $.attr through jQuery) ?

remy commented Jul 12, 2010

There's no reason not to, I was just coding a proof of concept to show how the final implementation would feel - though in retrospect I realised it's not a complete implementation because I don't handle = 'bar', which would then execute el.setAttribute('data-foo', 'bar').


hmm, okay, well, for now I'll stick with just using setAttribute / $.attr, as that works. Not to mention
I don't see any benefit from using el.dataset.*, are there any benefits?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment