Happy Bear Software

Field Notes on Client-Side Javascript

A random bunch of ideas for developing complex javascript UIs on the client, using libraries like Backbone.

The Golden Rule:

1. All State Shall Live in the Model

Why? Because by putting it in the model, all of this state is something that can be listened to by one or more views.

This rule was taught to me by a certain Mark Evans at New Bamboo. There is deep wisdom in this rule. Abide by it, and your UI code will magically begin to organize itself. Think fractal patterns, cherry blossoms and haiku. Let state creep in elsewhere, and watch as it turns into an unmaintainable mess.

2. Your views have precious few responsibilities

They are:

And that's it.

They might:

Other random bits of useful:

3. 'Handlers' listen to views or models and do stuff

4. An Example Interaction

  1. User clicks on an image
  2. An instance of ImageView eats the click (nom), fires an image:select event, passing the image model along with it.
  3. An instance of SelectionHandler catches the image:select event on the view, calls session.select(image) passing in the image it got from the image:select event trigger.
  4. session which is a model object representing the state of the workspace, fires a selection:changed event with the image as an argument.
  5. Our original instance of ImageView which was listening to session gets the selection:changed event, figures out that it's displaying the same image as the one that just got selected, and responds by running a method that adds a .selected class to it's element.

5. Stitch all of these components together in 'Apps'

You normally write a bunch of initializiation code for your single page app. This code almost always ends up:

  1. Getting state from somewhere. This could be via an AJAX call to an endpoint or (I know, it's gross, but we all do it) loading it out of JSON rendered into the page and stuffed in a global.
  2. Initializing model objects we need with that data.
  3. Initializing your view, and injecting models into it.

What I tend to do is create an App object, who's job it is to do step 2 onwards. That way, your top-level javascript ends up being something along the lines of

//pageData contains our model info
app = new MyApp(pageData);
app.initialize();

Apps could in theory compose and delegate to each other, stitched together in any way you see fit.

The first step is to have a place for all this messy initialization code, then you can start cutting it up into logically separate pieces.

Other random tidbits

Further Reading

It's a bit dated but Martin Fowlers article on GUI architectures shows that they figured most of this stuff out in the nineties.