Boilerplate that strengthens your backbone
JavaScript Ruby CoffeeScript CSS
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
app/js
config
dist
examples/some_rails_app
spec
tasks
vendor/js
.gitignore
.npmignore
.travis.yml
Gruntfile.js
LICENSE.txt
README.md
package.json

README.md

backbone-fixins

Build Status

downloads

Download backbone-fixins and include it after Backbone.js:

introduction

A common complaint directed at Backbone.js is that it's hard to get up-and-running without a significant amount of general boilerplate code. On one hand, Backbone's minimalism is its greatest strength. On the other hand, it doesn't make sense for our applications to solve problems that are outside of their domain, and it makes even less sense to solve the same problems in each new application we write.

This project doesn't aim to saddle users with a new Backbone meta-framework. But neither does it have the luxury of being so focused as to only tackle one feature or problem (like backbone-localstorage, backbone.layoutmanager, or backbone-relational do). Instead, backbone-fixins will only ever be a handful of little, easy-to-discard boilerplate utilities. The only motivation here is to help new applications get up-and-running a little more quickly.

components

Right now it's just the SuperView. I've got short-term plans to add a generic CollectionView and a mixin that aids in model validation.

Backbone.Fixins.SuperView

Most basic Backbone views do the following:

  1. Override the #render function
  2. Grab a compiled template
  3. Generate HTML by passing a context object to the template; usually by serializing the view's model property as JSON
  4. Render that HTML into the View's el element

And while this works fine, I'm sick of writing code to do it. First, none of this is a domain concern... it's a concern shared by nearly every view—why not DRY this up and get it out of the way? Second, overridden render functions don't age gracefully, in my experience.

As most Views mature, "render-time" behavior is often just tacked on at the end of the render function. Because this violates SRP, it makes for complex unit tests and complicates performance optimizations that try to minimize calls to render. The Backbone.Fixins.SuperView intends to discourage users from coupling render behaviors from the start.

So here's an example Backbone view that extends from Backbone.Fixins.SuperView:

class MyView extends Backbone.Fixins.SuperView
  renderJQueryAccordion: ->

Invoking new MyView(model: new Backbone.Model).render() will do a lot for you:

  1. By default, it'll look for a template function at JST['templates/my_view']
  2. It will invoke the template by passing it the view's model.toJSON()
  3. It will render the resulting HTML into the view's el element
  4. It will invoke the view's renderJQueryAccordion function, because the function's name started with the word "render"
  5. It will trigger a "rendered" event on the view, so that any behavior can be triggered whenever the view is rendered (and without tempting the user to override the render function)

In case you missed it, that means that in addition to making some logical assumptions, two new conventions can help you avoid coupling behaviors that have only the concept of "rendering stuff" in common.

  • Any view may define any number of methods that start with the word "render", and they'll each be called immediately after the template is re-rendered. Because the methods are still available to be bound to other events or called discretely, small aspects of the view can easily be re-rendered without making a more-expensive call to the render function

  • After each render is completed, views will emit a "rendered" event that anyone with a reference to the view can bind to.

SuperView customization

Of course, not all views will fit this mold snugly. Any view can optionally define these attributes to alter the behavior of the SuperView:

  • template - function or string - the locator of the view (e.g. "templates/popups/panda_view")
  • templateContext - function or object - the object to be passed to the compiled template (e.g. { enabled: true, time: new Date() })

Note that if your application won't be locating its templates on a global JST object (as is the way of Jammit and Sprockets), you'll need to override the templateFunction configuration (see below for an example).

application-wide configuration

Backbone-fixins has a handful of global configuration options that can be set by passing a configuration object to Backbone.Fixins.configure(). Current application-wide options include:

  • defaultTemplateLocator - function(view) - given a view, find the locator of the template. (default: "templates/view_name_in_snake_case")
  • templateFunction - function(locator) - given a locator, return a compiled template function (default: the function at JST[locator])
  • defaultTemplateContext - function(view) - given a view, return whatever object should be handed to the compiled template function. (default: model.toJSON())

You can also reset the default configuration with Backbone.Fixins.resetConfiguration

example configuration

Suppose you want to grab your template functions from <script> elements on the DOM and compile them with underscore''s _.template(). You might override the configuration like this:

Backbone.Fixins.configure({
  templateFunction: function(name){
    templateSource = $('script[type="text/html"]#'+name).html();
    return _.template(templateSource);
  },
  defaultTemplateLocator: function(view){
    return Backbone.Fixins.helpers.constructorNameOf(view);
  }
});

(Fair warning: this is a contrived example as it will inefficiently re-compile the template on each render invocation).

building backbone-fixins

If you're interested in working on backbone-fixins, it'll be important for you to be able to run the tests and build a distribution. Luckily this is really easy thanks to lineman-lib!

  • clone this repo
  • npm install -g lineman
  • npm install
  • lineman run in 1 terminal session (leave it running while you test)
  • lineman spec in another terminal session

When you are ready to issue a build, simply run lineman build. The output minifed bundles will live in dist/.