Introducing ElementalJS and the Behaviour Pattern

We’ll come to ElementalJS a little later but first I wanted to describe the problem it’s trying to solve.

The problem with current Javascript design patterns

There seems to be two mainstream ways of building Javascript applications: DOM event listeners with callback spaghetti or full blown object oriented MVC architecture.

The listeners and callbacks pattern works well for small applications where the entire file fits on your screen. After that it can be difficult to track down where the handlers are for certain events. It can be even more difficult when trying to debug in a browser console when you’re trying to find the handler for that interaction in question.

Object oriented Javascript has been gaining ground but with so many options of which framework to choose from it can feel like an application is putting it’s eggs in one basket by using one of those frameworks. Each has it’s own pro and con list, but sometimes you just need a little bit of whiz bang without managing an application within an application.

There are other tools to help like CommonJS and Asynchronous Module Definitions (AMD) but they don’t answer how to structure an applications Javascript code.

An alternative

An alternative, spaghetti-leaning pattern has emerged on several projects here in the New York office. The pattern has been dubbed ‘data presents’ or ‘behaviours’, depending on the project. This pattern couples a function to an element in the DOM by adding a data attribute to the element itself. This is not having Javascript in a href attribute within an anchor or onchange attribute of a select element, but it does highlight which functions are related to any given element.

This approach tries to embrace the simplicity of binding listeners to DOM events but tries to organise it in such a way to make it scalable and maintainable as the client side code grows.

Here instead of the script looking and binding to events across the whole DOM, an element is passed to a function where it can work on a local scale. There will still be listeners, but with the scope of the parent element the functions will be more tightly focused.

By adding a behaviour through the markup, this means that when looking at some HTML, you can see the behaviours that have been loaded for a particular element and it’s children. This can be useful when attempting to find a callback from a DOM action as typically there will be behaviours wrapped around the HTML.

Typically behaviours are small, focused functions. They are just javascript so can create objects, call functions and trigger or listen to events. Given they are small, this makes them easy to test. We use Jasmine heavily on our projects at Pivotal when testing Javascript, and these small functions are breakfast for Jasmine.

In a Rails project, or something which supports an asset pipeline, these behaviours are best suited to single files per behaviour. Naming a file the same as the behaviour name also increases discoverability in a codebase. For example, the Foo.Bar behaviour is located in foo/bar.js.

Spaghetti code perhaps, but sort of like finding a message within your alphabetti spaghetti.

What about unobtrusive javascript?

While three of the four components don’t really affect this pattern as they are in the domain of the application itself, separation of concern between the presentation layer and the Javascript, does.

The section on separation of concerns on Wikipedia covers this concern well. This pattern is quite clearly encouraging the use of putting behaviour into the presentation which is shown to reduce maintainability. So what’s different this time around?

Using this pattern we are not expressively stating what events to fire upon (e.g. onclick or onchange), we are just defining a behaviour that wraps this element. One of the concerns addressed in the separation of concerns section in the Wikipedia article is ease of development but by defining small behaviours they can be easily separated into their own files, have more of a single responsibility and therefore should be easier to test.
What about unobtrusive HTML?

Many Javascript applications will be loaded when the DOM has finished loading and will generally search the entire DOM for elements to attach events to. Using this pattern the element gets passed into the function that contains the behaviour. This enables that function to search the DOM locally and reduce the chance of any changes to the DOM affecting the applications javascript as changes can be localised.

When can I start using ElementalJS?

You can use this right now by using ElementalJS. You can either download the source, or if you’re using Rails theres a handy gem which wraps the file and puts it straight into your asset pipeline. Check out more over at the ElementalJS repository.