Unobtrusive JavaScript

JavaScript. Yes, it does happen sometimes. Someone asks you to add some client side functionality in your webapp, and you start vomiting js code straight into your (x)html templates. That is very very bad, and you should stop immediately. Since it’s 2007, and given that you want to evolve and keep enjoying what you are doing, here is how you should start thinking about client side code.

Separation of concerns. Years ago, we used to do our presentation inside our (x)html templates. Then we figured our how to do it using CSS. Years ago, we used to do all our persisted data (from database) to Objects translation, inside our POJOs. Then we started using DAOs. Separation is what makes software scale. Unless you are only “engineering” basic contact forms and guestbooks, you should try to embrace separation of concerns and layering, which will make your life easier.

So, back to JavaScript. The idea is to apply your behaviors in an unobtrusive way. Add a class, if necessary, to the elements you want to enhance, and apply the new functionality when the document loads.

Example:

You want to apply duplication functionality in some paragraphs. Clicking on those paragraphs, which have a class “duplicate”, will make them duplicate themselves.

HTML:

<p class="duplicate">Click me!</p>

You’ve got a little piece of nice (x)html. Google does not care what you are going to do on the client side. Screen readers and most mobiles won’t care as well. Why feed them anything more than pure accessible semantic markup? All client side code goes on a separate file, which on load will apply the behavior.

JavaScript:

// when window has loaded
window.onload=init;

  function init() {

  // if browser is capable
  if(document.getElementById) {

    // get all <p>
    var ps = document.getElementsByTagName('p');
    for(var i=0,length=ps.length; i<length; i++) {
    
      // if paragraph element has class 'duplicate'
      if (p[i].className.indexOf('duplicate')>=0) {
    
        // apply behavior
        ps[i].onclick=function() {
          this.parentNode.appendChild(this.cloneNode(true));
        };
      }
    }
  }
}

Live Demo
The first disadvantage here is that we have to write tedious DOM manipulation code. The second is that we have to do browser detection. In this simple example this is not so painful, but when you want to do complex stuff (possibly with asynchronous calls) there will be lots of code for browser compatibility. The third (and most important) problem is that this code will start executing only when the window has finished rendering. In complex documents and slow connections this will be seen.
The answer to all those problems comes with lightweight JavaScript libraries. Have a look at the same code, written in jQuery:

// when window has loaded
$(function(){

  // for all p with class duplicate which will be clicked
  $('p.duplicate').click(function() {

    // apply behavior
    $(this).parent().append($(this).clone());
  })
})

The best advice of course is to avoid use of JavaScript at any cost. IE6, a very popular browser, memory leaks very badly, which is another reason to try and keep JavaScript code to the absolute minimum.
Good luck.

Comments are closed.