Unobtrusive JavaScript — Use It!
October 22nd, 2007 in web development | 31 Comments
I’m sure you’ve heard of unobtrusive JavaScript before. But do you use it? I admit that in my early days I hadn’t and only started to once I began using Mootools.
Update: Some people aren’t reading the link about unobtrusive JS so I’ll summarize the benefits. Its main goal is not to make JS shorter but easier to maintain, very much like CSS makes styling easier to maintain (and I really hope you’re using CSS). It separates the behavior from the structure like CSS separates style from structure. If you’ve only got one or two things that use JS on your page, then yes, inline JS would be the simplest. But if you’re making something more complex, then unobtrusive JS will make your life easier in the long run.
It is possible to create unobtrusive JavaScript without a library, but you’re better off using something like DOM Assistant if you’re not already using a library. Even with all the modules, it’s only 10 kb compressed. That should allow you to easily do all the things you could with a full-fledged library.
It the examples below, I’ll be using Mootools. Look for equivalents for your library.
Link Actions
Don’t
<a href="#" onClick="doSomething(); return false;">Some link</a> <a href="javascript: doSomething();">Some other link</a>
A benefit of separating behavior and structure is that it degrades gracefully. The two links above don’t. They’re broken if the user doesn’t have JavaScript. If you don’t want non-JavaScript users to see something, create it in JavaScript.
Do
function doSomething(e) { // some stuff new Event(e).stop(); } window.addEvent('load', function(){ $$('.linkClass', '#linkID').addEvent('click', doSomething); // or if you don't want non-javascript users seeing it new Element('div', { 'class': 'button', 'events': { 'click': doSomething } }).injectInside('some_elemet_id'); });
The function doSomething() receives the event object which is extended by Mootools and then stopped. This prevents links from going anywhere in Mootools (in version 1.2 events will be extended automatically, and you can just return false like you’re used to). In the first example, I grab any links with a certain class or id, and attach a click event to them. In the second example, I create a new element and give it a click event, then inject it inside whatever existing element I want.
From here, you can do a lot of interesting things. Something I like to do to maintain the same functionality with or without JavaScript is to use GET requests and AJAX. You can have a normal link that performs just fine without JavaScript, but with JavaScript, it’ll be asynchronous. Here’s the HTML:
<a id="action1" href="action1.php?key1=value1&key2=value2">Perform Action1</a>
And the JavaScript:
var xhrReq = new XHR('method': 'get', 'onSuccess': function(){/* handle the response */}); window.addEvent('load', function(){ $('action1').addEvent('click', function(){ xhrReq.send(this.getProperty('href'), '_ajax=true'); }) });
With just that little bit of code, I can attach an AJAX call to a link. It’s up to the server-side script to determine what to return based on the presence of _ajax or not, but other than that, it’s the same functionality with or without JavaScript.
Form Actions
Capturing form submissions is pretty similar to capturing link clicks.
Don’t
<form id="form1" action="action2.php" method="post" onSubmit="doSomething()"> ... </form>
Do
function doSomething(e) { // some stuff new Event(e).stop(); } window.addEvent('load', function(){ $('form1').addEvent('submit', doSomething); });
Again, your function for form submission has to stop the default event actions, otherwise it’ll submit the form to action2.php. And similar to the tweak above to get the same functionality with or without JavaScript, you can send your form data using AJAX and just grab the path to send it to from the form’s action property. In fact, with Mootools, all you have to do is $('form1').send().
Styling
It’s also important to keep style out of behavior.
Don’t
function error(id) { $(id).addStyles({ 'color': '#f00', 'font-size': 24 }); }
Here, the styles are located within the JavaScript. Why do this when it’s a lot easier to do the following?
Do
/* in your css file */ .error { color: #f00; font-size: 24px; }
function error(id) { $(id).addClass('error'); }
Conclusion
That’s it! Now your JavaScript should be a lot more maintainable and readable, and I won’t puke when I see it!

Hi, I'm Chris, a passionate freelance web developer. My languages of choice are PHP and JavaScript, and that's what you'll mostly find in my blog. You'll also find updates about 