HTML5 Data Attribute Example

This post is more than 2 years old.

My readers are probably sick and tired of me gushing over data attributes, and for that, I apologize. I'm just a huge fan of practical, useful solutions, and no, I'm not going to use this as opportunity to complain about how silly Canvas is again. Rather, I thought I'd whip up another simple example of how you can make use of data attributes in your shiny Ajax-enabled web sites.

If you don't remember what data attributes are, here's a quick reminder. Data attributes are a way to add ad hoc data to your DOM. By prefixing an attribute with data- in front of your name/value pair, your have HTML that is still valid no matter what name you use. So for example:

<img src="something" data-nsfw="true">

There is no data-nsfw attribute for the image tag, but because I began the attribute with data-, it's valid. Another example:

<img src="something" data-nsfw="true" data-hires="someurl">

In both examples, the browser blissfully ignores the custom attributes, but you can write your own code to do whatever you want with it. This comes in handy in numerous situations, but here's one simple example. Imagine I'm selecting data from a table that includes price information. To make it pretty, I'll wrap the output of the price in a function to render it as a currency. Here's an example in ColdFusion:

Price: #dollarFormat(price)#<br/>

For the hell of it, here's the PHP version of it:

echo money_format('%i', $price) . "\n";

This outputs something like : $12,3900.11. What if you wanted to work with this price in JavaScript but treat it as a number? You would need to strip out the currency, possibly even the commas first. Instead of worrying about that, what if we used data attributes to store the "naked" price as a simple number? This will be hidden from the end user (technically not hidden - it will be available in view source) but will be available for our code. Here's an example. The code below loops over a query of art work. (I'll show the entire template in a bit.)

<cfoutput query="getArt"> <div class="artPiece" data-id="#artid#" data-price="#price#">

	&lt;h2&gt;#artname#&lt;/h2&gt;
	Price: #dollarFormat(price)#&lt;br/&gt;
	Media: #mediatype#&lt;br/&gt;
	Artist: #firstname# #lastname#&lt;br/&gt;
	#description#&lt;br/&gt;
	&lt;img src="/cfdocs/images/artgallery/#largeimage#"&gt;
&lt;/div&gt;

</cfoutput>

As you can see, I've included two data attributes in my div tag. One of the primary key of the record and one for the price. To be clear, I could have used other methods. I could have used a hidden form field for example. But this is much cleaner. Grabbing the values is a matter of simple JavaScript, but jQuery makes it even easier. Here's the complete template:

<!--- get art work ---> <cfquery name="getArt" datasource="cfartgallery"> select art.artid, art.artname, art.description, art.price, art.largeimage, artists.firstname, artists.lastname, media.mediatype from art join artists on art.artistid = artists.artistid join media on art.mediaid = media.mediaid </cfquery>

<html>

&lt;head&gt;
	&lt;title&gt;Data Example&lt;/title&gt;
	&lt;link rel="stylesheet" href="http://twitter.github.com/bootstrap/1.3.0/bootstrap.min.css" /&gt;
	&lt;script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"&gt;&lt;/script&gt;

	&lt;style&gt;
	.artPiece {
		margin: 12px;	
		border-style:solid;            
       	border-width:thin;
		width: 230px;   
		padding: 5px;
		float: left;
	}
	
	&lt;/style&gt;
	&lt;script type="text/javascript"&gt;
	$(function() {
		$(".artPiece").click(function() {
			var selectedId = $(this).data("id");
			var selectedPrice = $(this).data("price");
			console.log(selectedId+" "+selectedPrice);
		});			
	});	
	&lt;/script&gt;
&lt;/head&gt;

&lt;body&gt;
	
	&lt;div class="container"&gt;
		
	&lt;h1&gt;Art Work&lt;/h1&gt;
	
	&lt;cfoutput query="getArt"&gt;
		&lt;div class="artPiece" data-id="#artid#" data-price="#price#"&gt;
			
			&lt;h2&gt;#artname#&lt;/h2&gt;
			Price: #dollarFormat(price)#&lt;br/&gt;
			Media: #mediatype#&lt;br/&gt;
			Artist: #firstname# #lastname#&lt;br/&gt;
			#description#&lt;br/&gt;
			&lt;img src="/cfdocs/images/artgallery/#largeimage#"&gt;
		&lt;/div&gt;
	&lt;/cfoutput&gt;
	
	&lt;/div&gt;
	
&lt;/body&gt;

</html>

You can ignore the SQL and most of the formatting. Focus on the fact that I've got a click handler on my div. Grabbing my two values is as simple as using jQuery's data method. You can demo this below.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Phillip Senn posted on 11/3/2011 at 7:00 PM

Nice. The way ColdFusion talks to JavaScript is through the DOM. ColdFusion populates data- attributes and input values before the page is loaded. JavaScript can examine them after the page is loaded. JavaScript can then call a .cfc via AJAX to talk back to ColdFusion.

Comment 2 by Matt Williams posted on 11/3/2011 at 9:12 PM

I have often doing things like <td id="id_1234"> and then used javascript's split(tmpid,'_') function to parse that.

This example makes that much cleaner:
$(this).data("price"); <-- Like It!

Comment 3 by John Varady posted on 11/7/2011 at 5:51 PM

Ray - I have been doing this technique for a while now, but I have not been prefixing the attributes with "data-". For example:

<tr id="id#region_id#" pkid="#region_id#" rowid="#CurrentRow-1#">

Then when a user clicks a button in the row, I use this script:

var $tr = $(btn).closest("tr");
var pkid = $tr.attr("pkid");
var rowid = $tr.attr("rowid");
var ROW = qryRows.DATA[rowid];

Where "qryRows" is a JSON serialized query. Is there any downside to this method over the "data-" prefix? I haven't seen any yet, but your comment " you have HTML that is still valid" caused me to blink.

Comment 4 by Raymond Camden posted on 11/7/2011 at 6:54 PM

It may work, but is not considered valid HTML since those attributes are not in the HTML spec.

Now - I've been known to say practicality should trump spec - but in this case we have an easy way to be in spec - hence my recommendation to use data-* instead.