Crashlytics Labs is proud to announce the release of Backbone.StateManager

Backbone.js is a highly extensible framework that provides an MV* paradigm for Javascript applications that we use here at Crashlytics. Its lightweight architecture provides us a great foundation for building modular thick web clients. Backbone’s adaptability allows for the creation of addons and plugins to help tackle many of the problems faced when building a large scale JS application.

However, one of the problems we ran into while using Backbone at Crashlytics was the difficulty of managing the state of our application and its child components in a modular, scalable fashion. Whether it is choosing how to render a view on the DOM or conditionalizing the functionality of a model, the persistent nature of a web application requires a way to manage state-related logic.

Enter Backbone.StateManager

Backbone.StateManager is a module for Backbone.js that adds the ability to manage and utilize states in any size JavaScript application. It can be used as a stand alone object or in conjunction with a target object. Built on top of Underscore.js and Backbone.js, StateManager allows for modular state definitions, sub/pub architecture support with Backbone.Events, transition events between states, and regular expression matching.

Continuing our commitment to open source software, we’re happy to announce that Backbone.StateManager is available today on Github.

Getting Started

The core functionality of StateManager is comprised of 3 simple methods: addStatetriggerState, and removeState. Because StateManager extends Backbone.Events, it is also possible to subscribe to the object and listen as it sends out signals when moving between states.

Backbone.StateManager constructor takes two arguments, a state object and an options object, but neither is required. Passed in states will be automatically added and the options are set as an instance property.

 1 var stateManager;
 2
 3 stateManager = new Backbone.StateManager();
 4 // or
 5 stateManager = new Backbone.StateManager({
 6   foo: {
 7     enter: function() {
 8       return console.log('enter bar');
 9     },
10     exit: function() {
11       return console.log('exit foo');
12     }
13   },
14   bar: {
15     enter: function() {
16       return console.log('enter bar');
17     },
18     exit: function() {
19       return console.log('exit bar');
20     }
21   }
22 });

State Definitions

A state is intended to be as modular as possible, so each state definition is expected to contain enter and exit methods that are used when entering or leaving that state. A state definition can also have a transitions property that contains several methods to be used when moving between specified states. There are 4 types of transitions that Backbone.StateManager will defaultly look for: onBeforeExitTo, onExitTo, onBeforeEnterFrom, and onEnterFrom. Each transition is a key value pair, where the value is a method and the key defines the transition type and the specified state (eg onEnterFrom:specifiedState).

 1 {
 2   enter: function() {
 3     return console.log('enter');
 4   },
 5   exit: function() {
 6     return console.log('exit');
 7   },
 8   transitions: {
 9     'onBeforeExitTo:anotherState': function() {},
10     'onExitTo:anotherState': function() {},
11     'onBeforeEnterFrom:anotherState': function() {},
12     'onEnterFrom:anotherState': function() {}
13   }
14 }

Integration

A benefit of StateManager is that it provides an easy method to painlessly add itself to any object. Through the use of the addStateManager, which takes a target object parameter, it reads in any states defined on the target, binds state methods to the target, and creates a new Backbone.StateManager. It also sets a number of convenience methods on the target, including triggerState, getCurrentState, and a reference to the StateManager at target.stateManager.

 1 var View;
 2
 3 View = Backbone.View.extend({
 4   states: {
 5     foo: {
 6       enter: function() {
 7         return console.log('enter bar');
 8       },
 9       exit: function() {
10         return console.log('exit foo');
11       },
12       transitions: {
13         'onExitTo:bar': function() {
14           return 'just exited and bar is about to be entered';
15         }
16       }
17     },
18     bar: {
19       enter: function() {
20         return console.log('enter bar');
21       },
22       exit: function() {
23         return console.log('exit bar');
24       }
25     }
26   },
27   initialize: function() {
28     return Backbone.StateManager.addStateManager(this);
29   }
30 });

Get It

Feedback Welcome

Our goal is to make Backbone.StateManager as useful as possible for you to make writing powerful Backbone.js apps painless. We’re just getting started, and the feedback you provide is critical in achieving this. Please report bugs and discuss features on our Github issues page https://github.com/crashlytics/backbone.statemanager/issues.

Join the Team

Interested in diving-deep into these and other workflow-enhancing challenges?  We’re hiring!  Give us a shout at jobs@crashlytics.com. You can stay up to date with all our progress on TwitterFacebook, and Google+.