29 November 2010

Javascript MVC Framework for Rich Web Applications

Planbox is a complex UI beast. Notably the Plan page which handles tons of different user interactions. Take for example when you complete a task (1).  The holding item gets updated (2) and the user and initiative progress as well (3 & 4). Oh, by the way Planbox is an Agile Project Management Tool, for those who are just coming to this blog.

To perform this magic, we rely heavily on John Resig's jQuery and AJAX calls to the Planbox Engine. However as our code grows, we find ourselves struggling to maintain a growing number of Javascript functions to handle all of this. So we head out searching for a Javascript framework which could solve my problem. My requirements were simple:
  1. Must be minimalist. No bloated Javascript framework with 90% of stuff we won't use.
  2. Must implement MVC. We want to keep presentation and data decoupled.
  3. Must be easy to understand and extend. Clean and easy to read code please.
Not long ago I was brought to look at Jeremy Ashkenas' Backbone JS. It's brand new on the block (released October 13th) and fits most of my requirements. Here's how Jeremy describes Backbone:

Backbone supplies structure to JavaScript-heavy applications by providing models with key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing application over a RESTful JSON interface.

At that point, my mouth was watering. But then I also read this sentence:

Backbone is a 2 kilobyte include that provides just the core concepts of models, events, collections, views, and persistence.

I was sold. My quest was over.

Binding Events on Data

I've been prototyping with Backbone for a few weeks now. And I really like it. The core power comes in binding events to data. In Backbone Models represent data. You can bind events on a Model and trigger a handler when the Model changes. That is powerful. Views on the other hand listen to the Model and update DOM. Here's a little code snippet of a View:
ItemView = Backbone.View.extend({
  tagName: "li",
  template: _.template($('#item_template').html()),
  initialize: function(options) {
    _.bindAll(this, 'render');
    this.model.bind('change', this.render);
  render: function() {
Backbone also integrates a template engine to facilitate with the presentation layer (you can choose to plug in your own if you prefer). For example here is the item template from the above example. It simply outputs the item name and status inside the div element (specified in the View's tagName property):

Things to Improve

A couple caveats though:
  1. Server interaction is too restrictive. The Sync function and Controllers assume a near one-to-one object mapping between the client and server. And Backbone assumes that mapping is to be shown in the URL hash tag.
  2. Events are too primitive and don't behave as expected in some situations. For example, it is not yet possible to unbind an event in the bound event handler itself.
Fortunately Backbone is extensible. You can easily overwrite any method using the Underscore extend function. And as I said, Backbone is still young and evolving. So existing limitations will surely be overcome over time.

Underscore - A Pleasant Discovery

In working with Backbone I also discovered another powerful library: Underscore by Jeremy Ashkenas. It includes tons of useful Javascript functions. It has become an integral part of my Javascript toolkit along with jQuery and json2.js. I encourage you to have a look. So for those of you looking for an elegant way to decouple business data and presentation in Javascript, have a look at Backbone JS. It may be the thing you're looking for. P.S. Thanks to Mathieu for the discovery of Backbone JS (http://www.mathieusavard.info).
comments powered by Disqus