In this series I'm going to build a very simple but broad single-page app (SPA), to connect to the IMDB public API and retrieve things, using backbone. If you ever get lost, it means I'm not doing a good job, so I would love to hear any feedback.

What is backbone.js?

Backbone.js is a lightweight strictly front-end framework, that makes the fear of working with frameworks go away. Even though it's quite simple and straight forward, especially when comparing with other frameworks like AngularJS or Ember.js, it's always an awesome choice even when working on complex single-page applications.

Why backbone.js?

Lightweight

Like said earlier, it's very lightweight. It only truly depends on Underscore.js.
If you add jQuery to it, it gets bigger indeed, but still, it's not a heavy framework.

Unopinionated

The guys over at backbone said it best:

(..) while very deliberately avoiding painting you into a corner by making any decisions that you're better equipped to make yourself.

Which basically means that there is less to learn. It also means that the pressure to make it work properly is on you, the developer.

Small

Due to it's lack of opinion, there are less and less things to "automate", making backbone very small in feature. I say this in a good way. Again, backbone said it best:

The focus is on supplying you with helpful methods to manipulate and query your data, not on HTML widgets or reinventing the JavaScript object model.

Just going through the documentation gives the feeling of how small and not overwhelming it is.

Flexible

The size and lightweightness doesn't cramp backbone.js's capabilities. For very complex projects it might take a little bit more of manual code writing, but in the end you'll still end up with a perfectly functional, maintainable and scalable platform.

MVC?

Backbone doesn't really have a Model-View-Controller, per se. It actually has a Model-View-Collection, and the View here plays most of the part of the controller.
The navigation is controlled through backbone's Router, and the user interaction through triggers and events. Very jQuery.

To create new Models, Views or Collections, just extend from backbone's Model, Collection or View object.
Create a basic index.html file to test these components. Include jQuery, Underscore and Backbone CDNs. You can add the actual files or simply copy paste this:

<!doctype html>
<html lang="en">
	<head>
		<meta charset="UTF8">
		<title>Workshop Backbonejs</title>
		<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
		<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
		<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.1/backbone-min.js"></script>
	</head>
	<body>
		<div id="main"></div>
		<script type="text/javascript"></script>
	</body>
</html>

I'll be adding the javascript code inside the <script></script> tags.

Models

Keep in mind the purpose of Backbone:

(..) supplying you with helpful methods to manipulate and query your data

Models are the basic data containers. Think of OOP. That's it.
A Model can be a person, a movie etc. Here is a movie Model:

// Create the Model
var Movie = Backbone.Model.extend({

	initialize: function(options) {
		console.log(options);
	}
});

// Instantiate the Model
var m1 = new Movie({
    name: "Monty Python and the Holy Grail",
    year: 1975
});

// Show the model
console.log(m1);

The initialize function is inherited from backbone itself. It's just something that runs every time a Model (or anything else) is instantiated. The options argument is the object that is given to the Model once it's instantiated. This can perfectly be empty.
Open this file in the browser, check the console, and you should see:

The first line is the options object, the second one the actual Model object. Notice the attributes you added to it inside the attributes property. Fiddle with it, be one with the model, become the model.

Collections

Collections are, well, collections of models. Yup, an array, but on steroids. This basically means you can have a Collection of person Models called "Persons". But what is the point in having a collections of models? Since manipulating and querying data is what backbone is all about, having a Collection as an array on steroids with some added functionality, makes a whole lot of sense.
This comes especially handy and fun when it comes to integrate backbone with an external API.

Create a Movies collection, under the Movie Model:

var Movie = Backbone.Model.extend({

		initialize: function(options) {
		    console.log(options);
		}
});

var Movies = Backbone.Collection.extend({

		initialize: function(options) {}
});					
				

Create one more movie, after m1:

var m2 = new Movie({
	name: "The Meaning of Life",
    year: 1983
});

Instantiate the Collection with the two movies, m1 & m2, and log it:

var mymovies = new Movies([m1, m2]);
console.log(mymovies);

Should pop:

As you can see, the Collection is just an array with a handy length property, and an array with objects. Each of those objects is an actual backbone Model. Expand it, and see for yourself.

Views

Views are a mix between a controller, DOM manipulation and templating. In a simpler way, they are what encapsulates everything from reading the data on your Models or Collections, and showing it on your browser.
A View says something like: "Get the name of the first Person in the Collection Persons, and show it on that div called 'person-name'".
Views are also where you will write all of your DOM manipulation, user interaction, awesome Javascript code.

Let's create a view to show a movie, after the Collection:

var MovieView = Backbone.View.extend({

	initialize: function(options) {}
});

and instantiate it:

var movieView = new MovieView();	
console.log(movieView);

You'll see the View object generated:

You'll see all sorts of confusing things. Rule of thumb: Don't panic. It's actually extremely basic.
When a view is instantiated it generates actual html with whatever you want to put inside it. If you just instantiate a view without doing anything (like we just did), it will generate:

  • cid: It's just an ID. Backbone's way of identifying it.
  • el: It's the DOM element it's generating. Since it's an empty view, it's just creating a DOM element that is a <div></div>. This DOM element is not yet in the actual DOM though. Expand it and you should recognize it's structure.
  • $el: It's as simple as a jQuery selector containing the newly generated DOM element. Same as doing $(el).

The whole logic behind Views is to create it's own block of HTML that you can put anywhere in the DOM. Think of a view as a reusable container where you can show anything, a list of items, an item, a property of an item. Doesn't matter.

Add something to the view, like a simple text string:

var MovieView = Backbone.View.extend({

	initialize: function(options) {},

	render: function() {
        this.$el.html("T'is a string!");
        return this;
	}
});

Notice the render() function. It's where you should populate the view's DOM. Next, just run the render.

var movieView = new MovieView();
movieView.render();    // <-- added this
console.log(movieView);

If you re-log this view, expand the el property, and look for the innerHTML:

There it is. At this point the view's el has an actual HTML string generated, but, your DOM still doesn't have this view's content. Just add it to the DOM with this:

$('#main').append(movieView.el);

Refresh the browser, and voilá.
Now for something actually useful, adding a movie info to the screen:

(...)

var MovieView = Backbone.View.extend({

	initialize: function(options) {
        this.movie = options.movie;
    },

	render: function() {
		this.$el.html("<div class='name'>"+ this.movie.attributes.name +"</div><div class='year'>"+ this.movie.attributes.year +"</div>");

    return this
	}
});

(...)

// add m1 as an attribute to the view
var movieView = new MovieView({movie: m1});			    

movieView.render();
$('#main').append(movieView.el);

If all went well, you've just created a view that renders a movie's info. The way we are creating the html in the render() is far from optimal. There are many ways for us to template things, but those are out of this article's scope.

If you want to create a View representing a list of movies, for example:

(...)

var MoviesList = Backbone.View.extend({

	initialize: function(options) {
        this.list = options.list;
    },

	render: function() {

        for(var n in this.list.models) {
            this.$el.append("<div class='name'>"+ this.list.models[n].attributes.name +"</div><div class='year'>"+ this.list.models[n].attributes.year +"</div>");
         }  
    
    return this;
    }
});

(...)

// Inject the collection to the view
var movieList = new MovieList({list: mymovies});			    

movieView.render();
$('#main').append(movieList.el);

Remember that mymovies is a Collection containing two movies.

If during the whole process something goes wrong and you are lost and have no idea why, just start console.logging objects to see the actual structure. This is plain Javascript.

Now that the base is set, let's create an actual application with this.