Unobtrusive javascript with lowpro

Jan 03, 2008

Dan Webb's lowpro library has been around for quite a while now, but if the sites I frequent are anything to go by it's adoption is far from widespread. Why? Frankly, I don't know. It's a brilliant library and if you're already using things like prototype and scriptaculous but you're not all over lowpro then there is a good chance you need to be seriously smacked around a bit.

Rails comes with a heap of built-in helpers for doing useful things like autocomplete boxes and inline editing. But at the end of the day, while the implementation from the developers perspective is relatively clean the actual code they generate sucks major ass. If you view source on the output, you'll find that there is lots of javascript now embedded within the HTML document. Not only is the HTML no longer just describing the structure of the page, but in many cases you've created a dependency on the end user to have javascript to be able to use your site. It also means to test your site properly, you have to be using something like selenium as the standard rails test framework(s) won't execute your javascript.

How does lowpro help?

It means you focus on developing a site that works for everyone to begin with. No stinking javascript, no silly business or aesthetic logic being inserted into your HTML. Instead, you have a traditional HTML (and CSS) only site that works for all browsers, all users, all of the time. Then you go about having lowpro add in the logic you require at run-time to improve the user experience for those that support it.

Installing and setting up lowpro

Firstly grab the 0.2.0 release from here and unzip the files into your project. Now this library is dependent on prototype, so if you're using jquery or something else that'll be the topic of a later discussion. Next you have to include prototype and lowpro in your HTML. None of this is rails specific, and none of it is going to involve ruby. It's back to old-skool javascript skills. Here's what you need to include:

<script src="/js/prototype.js" type="text/javascipt"></script>
<script src="/js/lowpro.js" type="text/javascipt"></script>

Using lowpro

So this is obviously the most important bit. Forget everything you used to know about onload, onmouseover, onclick, etc. Now you create a javascript file to contain all the logic you need and who needs to respond to what. Replace `<body onload="alert('hello!')">` with:

Event.onReady(function() {
  alert('hello!');
});

The brilliant things about attaching the event in this fashion is that rather than executing after the entire document has finished loading (which can include images and everything), it will fire as soon as the browser has parsed the HTML and knows the document layout (or once the DOM had loaded for those up with the lingo). That means you can have the actions fire as soon as the document has loaded, but before the user sees anything.

But what about those mouse over and mouse click events? You've got a button called 'foo' that you want to say boo when you click on it, likewise you've got all of links with the class of 'bar' that you want to highlight whenever the mouse passes over them. It's as simple as:

Event.observe($('foo'), 'click', function(e) {
    alert('boo!');
});

Event.addBehavior({
    'a.bar:mouseover' : function(e) {
      this.visualEffect('highlight');
    }
});

And there we go, #foo now has an onclick event applied to it. Meanwhile every link with a class of bar has had a mouseover event applied. You can of course nest and stack these events until your heart is content. Kudos once again to Dan for such an awesome library

Hi, I'm Glenn! 👋 I've spent most of my career working with or at startups. I'm currently the Director of Product @ Ockam where I'm helping developers build applications and systems that are secure-by-design. It's time we started securely connecting apps, not networks.

Previously I led the Terraform product team @ HashiCorp, where we launched Terraform Cloud and set the stage for a successful IPO. Prior to that I was part of the Startup Team @ AWS, and earlier still an early employee @ Heroku. I've also invested in a couple of dozen early stage startups.