In the beginning (well, beginning with jQuery 1.2.3 in early 2008) there was the
Most jQuery code sets data values using the higher-level
.data() API; for example,
$("div").data("imaDiv", true) sets a boolean value on every
div in the document. This API, in turn, calls down to
jQuery.data() with each element to set the value. For completeness, there are also
.removeData() to remove data elements, and
jQuery.hasData() to determine if any data is currently set for an element.
So to recap: At the inception of these APIs, they were only about getting and setting values associated with DOM elements in memory. Most importantly, the data was managed to ensure no memory would leak when the DOM elements were removed. Many internal jQuery features such as event handling and toggle state memory use these data APIs and their benefits.
A few years later, HTML5 became popular and associated another concept with the word "data" through its
data-*attributes and the associated DOM
.dataset property. This isn't quite the same as jQuery's original idea of data: It involves values being associated with HTML elements in markup and not DOM elements in memory. But they are logically close enough that we added the ability to read HTML5
data-* attributes into jQuery's data object starting with version 1.4.
It's not a perfect marriage, though. HTML5
data-* attribute names are more like CSS names; a name like
data-shrivel-up is turned into
shrivelUp to find a match. We know it's not ideal, but it's a consequence of trying to fit two concepts with differing semantics into a single API.
With that history in mind, there are a few important things you should know in order to use the
jQuery.data() APIs effectively. To give you a better sense of what's going on, the items are illustrated with some code. Assume that each code block runs independently of the others and that they all refer the following HTML:
Here are the rules of the road:
.data()API reads HTML5
data-*attributes, and it does so once.
The in-memory data object for an element is initialized from those
data-* attributes the first time you call
.data() for the element. Any subsequent changes to the attributes are ignored, since jQuery has already cached the data.
Rule: If HTML5
data-* attributes change during program execution, use jQuery's
.attr() method to get the current values.
.data()API converts HTML5
That means sequences of digits or exponential-looking values like
"true" becomes Boolean
Rule: To get HTML5
data-* attributes as strings without data conversion, use jQuery's
jQuery.data()API does not read HTML5
However, if the
.data() API has been called already on that DOM element,
jQuery.data() will "see" the values that it has already read from the
data-* attributes. Conversely, if
jQuery.data() sets a value with the same name as an HTML5
data-* attribute and
.data() later reads them, the HTML5 attribute is ignored.
Rule: To prevent confusion, do not use similar names for HTML5
data-* attributes and strictly internal data stored using
.data() on the same elements.
Most uses of
Rule: To update or remove HTML5
data-* attributes, use jQuery's
data-*names are stored in camelCase in the jQuery data object, using W3C rules.
data-caMEL-case becomes the
camelCase property in the data object and should be accessed using
.data("camelCase"). Because many people will use
.data("camel-case") instead, we convert that to
camelCase as well, but only if no data item named
camel-case is found so it's faster to use the first form. If you get the entire data object using code like
data = jQuery.data(elem), you must use
data.camelCase to access the data item.
Rule: When accessing data taken from
data-* attributes, and especially when accessing the data object directly, use the W3C camelCasing conventions.
Over time, jQuery's
.data() API has taken on more responsibilities than it originally had when it was just a way to associate in-memory data with DOM elements and prevent IE leakage. If you need only a simple way to read HTML5
data-* attributes as strings, then the
.attr() method may be the best choice, even though the siren-song-name
.data() may be telling you otherwise. Whether you use
.data(), they work consistently across browsers all the way back to IE6 — even if the browser doesn't support HTML5 — so just choose the API with the feature set that works best for your needs.