Last Updated Apr 02, 2013 — Enterprise Agile Planning expert
Sip a cup of Backbarstrap: Backbone, Handlebars, and Bootstrap with CoffeeScript and RequireJS
Enterprise Agile Planning
I've been working with other VersionOne developers and managers on what will become our App Catalog. We intend to make the application itself open source. With it, you'll be able to easily showcase the add/ons, plugins, or just plain old resources you have related to your own applications. We're all familiar with this kind of interface. You see it in your phones, and in places like Mozilla Addons, or the Visual Studio Gallery. In upcoming posts we will focus on our design and development process related to this, but for now I just want to cover some of the technical aspects of the front/end HTML, JavaScript, and CSS.
App Catalog Prototype done with Twitter Bootstrap
I came across Adobe Technical Evangelist Christophe Coenraets' very illustrative Sample App with Backbone.js and Twitter Bootstrap a couple of days ago and used it as a baseline for building this early prototype of an entry detail page for our App Catalog. This shows it rendering the data for our Clarity PPM integration.Standing up straight with Backbone
For some time now, the VersionOne team has been using Backbone.js in new features. Maybe that is because we've found new use for our own backbones with the awesome sit/stand GeekDesks we have in the VersionOne offices? I digress. Anyway, it's very easy to use Backbone to consume and manipulate RESTful resources by extendingBackbone.Model
and overriding one or more of its functions. In this post, we'll examine that and a few other highlights. I encourage you to see the README.md for the code on GitHub for an in/depth, sequential explanation.Consuming a cloud/hosted resource with Backbone
We are hosting a Node.js based RESTful app on Windows Azure to store our catalog data. Internally, the app uses the awesome Mongoose JS library to connect to MongoDB // itself hosted within MongoLabs. To expose our data as a Backbone model, all we have to do is extend it this way:EntryModel model extending Backbone.Model in CoffeeScript
[gist id=5300295 file=EntryModel.coffee]Painless AJAX with Backbone.Model
Now that we have a model that is easily consumable, we can use thefetch
function to initiate an HTTP GET on that resource. Backbone will delegate to jQuery or zepto for AJAX support, and when finished will callback the function we pass as the second argument:Using Backbone.Model.fetch function to get HTTP resource
Within the route handler forentryDetails
, we instantiate the model with an id, and then simply call fetch
, passing it a success callback function. By the time that function gets called, the entry
instance has been populated with all the attributes that came back from the JSON document returned by the remote HTTP response.
[gist id=5300295 file=Router.coffee]Handlebars template with Bootstrap goodness
Another thing we've adopted at VersionOne is the elegant, simple, and extensible Handlebars.js templating engine. As you saw above, in the callback passed tofetch
, we instantiate an EntryDetailsView
, passing it the model instance.
You should view my in/depth explanation of the code at GitHub in the README.md file for the repository to understand the flow of execution in detail.
Here's a snippet from a sub/view, EntryDetailsInfoView.html
, with Handlebars variable/interpolation syntax, {{variable}}
, and some of Bootstrap's CSS classes to make a stack of navigation button tabs painless and easy:Replacing placeholders with model properties and tabbifying links with Bootstrap classes
Notice theclass='textLinks nav nav/tabs nav/stacked'
. The nav
classes there are part of Bootstrap, and they enable the links to look as the screenshot above depicts.
[gist id=5300295 file=EntryDetailsInfoView.html]Rooting our Boots with RequireJS
In Christophe's original version of the Employee Directory app, he loads all the JavaScript files directly in the index.html file. For mine, I used RequireJS. This library supports the Asynchronous Module Definition pattern, which makes it a snap to load scripts entirely from another script, and to ensure that each script can declare its own dependencies and get those injected to a configuration function. It's kind of like constructor/injection based Inversion of Control in that respect. Here's the gist:HTML template contains only shell structure and one single script reference
The reference torequire.js
and the data/main
attribute tell RequireJS to load main.js
as the entry point for the application.
[gist id=5300295 file=index.html]The main.coffee file configures RequireJS and asks it to load dependencies
First note that when we compile the app with coffee/script,main.coffee
becomes main.js
. What happens in this file is that we first configure RequireJS to treat a handful of libraries with some shim, to make them behave as if they natively supported the AMD pattern. This lets the rest of our script modules import them without pain. The actual function call to require
passes in an array of module names, and then a callback function. We only declare variables for four of those modules, because those are the ones we need to use in the initialization of the app within the callback.
[gist id=5300295 file=main.coffee]