☕ 5 min read
jQuery makes elements-related data manipulation easy.
The HTML5 data-*
attribute is linked in some way to the jQuery data object for DOM elements.
$.data(element, key[, value])
deals with DOM elements related data.
$.fn.data(key[, value])
deals with jQuery elements related data.
$.data
is low-level and executes faster while $.fn.data
is much more convenient and flexible. Futhermore, the second one can access to the data-*
attributes.
<!-- HTML -->
<div id="main-content"></div>
// Javascript
var $el = $('#main-content')
$el.data('key', 'plop') // fast
$.data($el, 'key', 'plop') // 10 times faster
Finally, unlike $.fn.attr
, both of these methods don’t modify the DOM.
$el.data('key', 'plop')
// <div id="main-content"></div>
$.data($el, 'key', 'plop')
// <div id="main-content"></div>
$el.attr('data-key', 'plop')
// <div id="main-content" data-key="plop"></div>
To attach an information to an element and manipulate it over script execution is dead easy with jQuery. Indeed, the library has methods to store, modify and delete data which are related to an element.
Futhermore, it’s good to know that the data-*
attributes introduced with HTML5 are automatically pulled as a jQuery data object. Doing so, they are accessible through some of its methods.
The most popular method is $.fn.data
which is used as below:
// Affects the "plop" string to the "key" key
elem.data('key', 'plop')
// Reads the data with the "key" key
elem.data('key')
<!-- Valid HTML5 code -->
<div id="elem" data-my-key="hey"></div>
$('#elem').data('myKey') // Outputs "hey"
You’ll notice that we remove data-
and the HTML hyphens to specify the key the CamelCase way, accordingly to the W3C specification.
The documentation is very simple to get in and gives a good overview of the concept.
But wait there’s more… use the $.fn.removeData
method to clean all that mess:
elem.removeData('key') // Bye!
The library also comes with a more low-level and less known method, $.data
. It plays the same role excepted the syntax and the fact that you need to provide a DOM element associated to the data as a parameter.
// Affects the "plop" string to the "key" key
$.data(elem, 'key', 'plop')
// Reads the data with the "key" key
$.data(elem, 'key')
Here again, please have a look to the official documentation.
We also get the $.removeData
method to remove data and the $.hasData
one to check if an element does or doesn’t have data attached:
$.hasData(elem) // Outputs "true"
$.removeData(elem, 'key') // Bye!
$.hasData(elem) // Outputs "false"
Why should I use $.data
when $.fn.data
is much more sexy to write?
Well, as the method is low-level, it goes way faster!
el.data('key', 'plop') // fast
$.data(el, 'key', 'plop') // up to 10 times faster
I invite you to test performances by yourself.
The other side of the coin is that it should attach data to a DOM element while $.fn.data
can handle any sort of jQuery object, events included:
// Affects each link index as a data for the "click" event
// When you click on a link, it shows its index
$('a').each(function(i) {
$(this).on('click', { index: i }, function(e) {
alert('My index is ' + e.data.index)
})
})
Finally, $.data
doesn’t manage HTML5 data-*
attributes while $.fn.data
does.
Concretely:
$.fn.data
data-*
attribute, use $.fn.data
$.data
because of performanceIt’s also good to know that both of the $.data
and $.fn.data
methods do not modify the DOM.
More precisely, although the $.fn.data
methods can access to data-*
attributes, it wouldn’t modify them in the DOM. You shouldn’t get tricked because of the function abstraction: it’s not the attribute you are manipulating but an automatically created jQuery object.
In return, the $.fn.attr
method is an alternative to reach DOM attributes and to modify them.
<div id="main-content" data-my-key="hey"></div>
$('#main-content').data('myKey', 'plop')
// Change the jQuery object, not the DOM
// <div id="main-content" data-my-key="hey"></div>
// Note: $('#main-content').data('myKey') outputs "plop"
$('#main-content').attr('data-my-key', 'plop')
// Change effectively the DOM
// <div id="main-content" data-key="plop"></div>
In the first code, we modified the jQuery object but nothing happen on the HTML.
In the second code however, we concretely modified the HTML.
Concerning performance, you might note that the second is way faster than the first one. A reason for that would probably be that $.fn.data
does more than just “reach” the element: it performs some casting regarding to the type of the element.
Thus, it could be very helpful for plugins or widgets initialization:
<div class="widget" data-row="2" data-responsive="true"></div>
$('.widget').each(function() {
$(this).myWidget($(this).data('rows'), $(this).data('responsive'))
})
On the other hand, $.fn.attr
will always output a string, which could be necessary sometimes.
That’s it for my short (but intense!) presentation of existing jQuery methods to manipulate data.
I thought that notes about performance would have been interesting, but it shouldn’t be a concern: this is not what would make you script significantly faster. Still, it’s good to know about it!
If I’m lucky enough, that may have been one of your “Aha moment” with JS (as some people would call that) =)
Plop!