Since I’m working with a server-side programming language (PHP), JavaScript and HTML I’ve been dealing with a way to separate logic, structure and presentation layer. Especially when you work on projects that have a lot of frontend logic. There’s always a need for change late in the project in either one of them. When you have to change the structure or the representation layer you will mess up your logic when there’s no clean separation and the other way around. With the html data-*-attribute things get much easier. It solves the problem of how to pass data from your server to the frontend, helps avoiding mixing up style definitions and frontend logic (class-attributes) and gives your frontend data a home.There have been a lot of discussions since 2008 how and when to use the data-*-attributes, as you can read in the blog posts below. I tried some of their advises and have found my personal best practice.
In the HTML5 spec the custom data attributes are clearly defined for use for in your own application.
These attributes are not intended for use by software that is independent of the site that uses the attributes.
Passing data to JavaScript
There has always been the problem of how to get data out of your database through your server logic to the fron end. I’ve tried and used those endless long JavaScript arrays/objects. One problem was the mapping between the array/object and the corresponding element. There was always the need of passing an identifier in the id like:
<div id="post_7">foo</div>
When you want to show a sequence of entries you have to loop through your data twice (in the header section and the body) or you build up PHP-arrays or strings of doom. No matter which solution you chose it won’t have anything to do with clean templating.
Another problem is, the markup is spoiled with tons of JavaScript and senseless ids.
There’s also the possibility to load your data with AJAX, which is absolutely valid when you render your templates in the frontend. But as soon as you use AJAX your application is stateful and you have to deal with the impacts like loading and waiting.
There’s also the possibility to save the data in other attributes and there are also some that fit semantically like title or href, but most of your data won’t fit in a standard attribute.
A clean representation might look like this:
<a title="John Doe" href="#john-doe" data-id="7" data-eye-color="blue">John Doe</a>
Selecting elements in JavaScript
When you implement a dynamic web application you always need to select elements. Modern Browsers support query selectors like jQuery or other frameworks do. Usually you use ids for selecting certain elements and classes for a set of them. Using classes is a really bad habit as they should be used for styling the elements only. It is possible to separate classes for logic and style but it is very very likely you mess them up.
Bad:
<style>
.itm {
color: blue;
}
</style>
<script>
var $itms = $('.itm');
</script>
<ul><li class="itm">A</li><li class="itm">B</li></ul>
Good:
<style>
.blue {
color: blue;
}
</style>
<script>
var $itms = $('.itm');
</script>
<ul><li class="blue itm">A</li><li class="blue itm">B</li></ul>
Better:
<style>
.itm {
color: blue;
}
</style>
<script>
var $itms = $('[data-itm]');
</script>
<ul><li class="blue" data-itm>A</li><li class="blue" data-itm>B</li></ul>
You need to be aware that those selectors are slower than class names and you may return to class names when your application gets slow, but this solution may fit most of your needs. It may also help to save your elements in vars as long as you work with a reference of them.
Storing data in JavaScript
There is always the question where the data should be saved. There is data that could be saved in your DOM-element, like position, but others may be saved in an array or object.
By using data-*-attributes your data is where it belongs, on your element, also the transition is seemless. As you could pass your initial data from your server to the frontend.
<div data-box data-x="5" data-y="7"></div>
<script>
$('[data-box]').data('x', 10);
</script>
Upshot
Since I use these patterns my code looks cleaner then ever. Now there is absolutely no need to write any JavaScript code in the HTML-Document. I put the data where it belongs to its logical place. The concern of the elements is also clear.
Use those attributes now! Your coding style will improve and the result will be much better.
What i need now is syntax highlighting that distinguishes between attributes for representation and logic.
- http://ejohn.org/blog/html-5-data-attributes/
- http://danwebb.net/2010/1/27/put-that-data-attribute-away-son-you-might-hurt-someone
- http://dev.w3.org/html5/spec/global-attributes.html#embedding-custom-non-visible-data-with-the-data-*-attributes
- http://roytomeij.com/2012/dont-use-class-names-to-find-HTML-elements-with-JS.html
- http://chriseppstein.github.com/blog/2010/09/01/blurring-the-line-between-content-and-presentation-with-data-attributes/
UPDATE 8.10.2012
Also read this article, which gives further information on the speed of the selectors, also by @roy (thx @jayeff) http://roytomeij.com/2012/follow-up-don-t-use-class-names-to-find-html-elements-with-js.html