Tech Tuesday: Backbone and I

May 7th, 2013 by Sarah

In the development of our mobile application, we decided to use PhoneGap so we could easily distribute the application to as many platforms as possible. When we were first designing the application, we knew we would need a robust JavaScript framework to give us a solid code structure, but we needed something very light weight inside of a mobile space. With all of that in mind, we decided on BackboneJS. It gives you a solid start on building a JavaScript site with a great code structure. The structure comes from its four major classes: Models, Views, Collections, and a Router. Each of them help keep data where it should be, allowing you to focus on interactions and building the best experience.

So, what do each of these classes do? Let’s talk.

Models

A model is where you store data about a specific item, one of our most commonly used Models is a Comment. This model will contain data about a comment, id, the id of the gallery item it’s attached to, and the comment text itself. What is so great about Backbone Models are that we just have to point them to the API endpoint, and it will automatically sync the data for us. Since both Backbone and the Imgur API follow REST standards, they can easily communicate with each other, and you don’t have to spend time tweaking things to make them work together. Here’s an example of how you can create a comment with the Imgur API and a BackboneJS model:

By calling .save() we not only create an object with the given data to manipulate in JavaScript, but also send a POST request to the Imgur API to create it in the Database. That allows us to worry about other things, rather than when to save the data to the API. In a similar vein, you can call myComment.destroy() and it not only deletes the JavaScript object, but also deletes it from the server and triggers a destroy event. There are a number of methods and events that allow models to communicate with an API behind the scenes so you can worry about other things.

Views

Backbone views is probably where we save the most code, simply because we are reusing the data every chance we can. When you hit a gallery view in the app then click an image, we don’t actually fetch any data for that image. We already have the data from our first request, so we simply show you a different view of the image. By doing this we can keep everything, sync across the app and greatly reduce the number of requests we need to make to the server. Here’s a quick example of how you might render an Image:

Now we can use the view with a Backbone Model. For the sake of simplicity, let’s say we have an Image Model, myImage, with all the data we need.

var imageView = new ImageView({
'model' : myImage
});
//this is simply taking the html rendered in
//the image view, and using jQuery to insert into the DOM for us
$("#comments").html(imageView.render().el);

The output for imageView.render().el is going to look something like this:

<div class="image">
<h1 class="title">
Went running yesterday for the first time in a long time.
</h1>
<img src="http://i.imgur.com/j17loBb.jpg" />
</div>

We are also using the _.template method in the example since it comes with Backbone, but you can use any JavaScript templating system that you want. By using a template, we can say that we want all of the objects rendered with this view to look the same. We also have some protection against people trying to inject html into our website by calling _.escape to the title, which is user input.

Now a user wants to delete that image, normally you’d have to setup code to make a delete request to the server, delete the object, and remove it from the HTML as well. However with BackboneJS, we can simplify that to :

myImage.destroy();

In the initialize function in the ImageView, we have a call to this.listenTo. This adds an event listener for the model on the ‘destroy’ event, and will call the remove function associated with the view. There is a default remove function in all BackboneJS views that removes them from the DOM, and all of the handlers associated with them. As we mentioned earlier, the destroy function also makes a DELETE request to the URL in the model. By simply destroying the model, we have removed it from the screen, memory, and the database. Pretty sweet, right?

Collections

A collection is, at its simplest, an array of models. The great thing about collections is we can simply hook it up to a URL like we did with models before, so you can just say “fetch” this data, and you’ll get all of the data your heart desires. Let’s take a look at how the Imgur Gallery works:

Now we have a Collection of models, with all the image data for the front page of Imgur. What can we do with all of this new found data? Well, we have already defined a view for images, ImageView. Now, let’s use that to render all of the images in the gallery.

First of all, we need to create a collection view. This is the same as a normal view, but you’ll be passing a collection to it. The render function will know how to deal with an array rather than single model.

Router

The last of the major Classes of Backbone is the Router class. This class is where we define when we want to use the views and collection data. It’s basically the glue that brings everything together. The routes are url paths that you intercept and want to display. Basically, they use regular expressions to make everything in your life easier. Let’s take a look at how we might render a gallery then move on to a single image with the classes we used before.

Let’s say your website is http://imgur.com. When you visit that link it will go to the showGallery function, render the gallery collection, and insert it into the body tag on the page. If you go to http://imgur.com/j17loBb it will call showImage, and take you to a page where it shows that image. We also did a really quick improvement to reduce the number of ajax requests in the router. We are simply selecting all of the images in the gallery on load, then using that data to navigate through the application. It’s important to note that if the ajax request isn’t finished by the time you try to load the pages, you’ll see nothing. To fix that, we can add some wait times and do all sorts of checks in the router, or we can simply modify the view. If we add the ‘add’ event handler to the gallery view, we can render them as data comes back from the server.

The biggest advantages to using backbone are code clarity, organization, simplicity, and reduction of AJAX requests. The way Backbone breaks down code into chunks allows us to easily organize the codebase. Also, by maintaining data in collections and models we can keep track of them to re-render later and in different ways depending on the view.

While these are some watered down examples of how you might use BackboneJS to build your own application with the Imgur API, I hope it helps you start off with some awesome apps. There is a lot more information on BackboneJS at http://backbonejs.org, http://backbonetutorials.com, and http://codeschool.com. Hope to see some awesome apps built with the Imgur API and BackboneJS! Brace yourself; the Imgur Mobile Application is coming.

Backbone is quite robust and lightweight, and you guys did a pretty damn good job with the tutorial. However, you could have done the same thing with Angular, with gives you much more customization options on the front end. The backend work is slightly tricky, but the frontend work would be so much simpler.

Yeah, the problem with Angular for us, was just how big it is… 80kb for the minified Angular vs 6.3kb for minified Backbone. While it doesn’t seem like a lot, we want to try and reduce as much as we can when sending to a mobile device. Since Backbone is more than an order of magnitude savings in size, and still gives us what we want it, it was the best choice for us.

Really glad to see Imgur going the Backbone route! One thing I would suggest to you guys is check out Marionette JS – it’s an application framework for Backbone that reduces the boilerplate associated with it. It’s still really lightweight since that’s very important to you guys. A Backbone/Marionette combination is on par with any of the other MVC frameworks, but since it’s Backbone, you know it’ll fit like a glove.

I’ve been producing screencasts and tutorials focusing on large/scalable Backbone Apps at http://www.backbonerails.com — definitely on par with the other links you posted. I think the material can definitely be helpful!