Backbone.js at a glance

Introduction:

In the recent years web-technology has revolutionized in many ways, made our life much easier. As we all know websites mean a lot of pages containing specific information in each page. But nowadays this concept is changing. As the time moving forward we are able to access internet via many devices except pc. Many of them has smaller resources to begin with. So, to meet these new requirements, developers made single page applications. Achieving single page applications with jquery will get very complicated because of its complex API. So, we have a new technology to accomplish the single page applications.

What is backbone.js ?

We all have used different kind of frameworks like Model-View-Controller(MVC), Model-View-Presenter(MVP),Model-View-View Model(MVVM) for creating single page applications(SPAs). Backbone.js (or simply Backbone) is a front-end JavaScript framework for building data-heavy Single Page Applications (SPAs).Backbone follows its own special paradigm. Backbone doesn’t require files to be structured in file system. Backbone also helps us providing necessary advises about code structure in projects. Backbone is most useful when an application uses a database in the back-end to persist user data, and the front-end application will need to mirror a lot of this data.

Why should we use Backbone.js ?

Backbone is a type of MVC that lies in the client.In order to have fast interaction and experience.Using a client MVC supplies a RESTful set of resource from the server.So, using backbone can benefit us in different aspect of creating a website.

How to get started with backbone.js?

Backbone is a MV* framework. So, before we begin working with backbone, we need to have the appropriate library. As for our first we can get backbone from
1>> http://backbonejs.org/

2>> The next we are in need of jquery, which we can get from
http://jquery.com/

3>> finally we are going to need underscore from
http://underscorejs.org/

It is my personal opinion to install the development versions. But any version will do. After saving these libraries we are good to go with the backbone.

backbone.js as a MV* framework:

Javascript frameworks take the ideas of template to the next level. With these frameworks, you can run your entire web application without ever reloading the page. The most prolific MV* library for JavaScript, lightweight and un-opinionated. Provides a great starting point for little cost.
A router is not a controller. It’s a router. A view is not a controller. It’s a view. Yes, both routers and views share some of what a modern web-server MVC framework, such as Ruby on Rails, would call a controller. But neither of these is a controller.So, we can say that backbone has no controller. If there is no controller we definitely can not call it MVC framework. For better understanding let us walk through a diagram.

At first let us look at a diagram of MVC framework:

MVC framework

Now let us look at a MV* framework to understand the difference more thoroughly.

MV- framework

A few positive and negative sides of backbone.js:

A few pros of backbone:

• BackboneJS is simple and flexible and requires only a few minutes to get started, even when using higher level additional libraries like MarionetteJS or Chaplin.
• The BackboneJS community and ecosystem is huge and there are tons of plug-ins and extensions. Documentation is also good and solutions to almost any problem exists,      making finding help or support easy.
• It’s simple yet powerful inheritance model, based on the useful extend method. The extend method is actually defining the prototype for the newly created objects.
• There is no doubt that BackboneJS deserves a lot of credit in bringing MV* to mainstream client-side JavaScript development.

A few disadvantages of backbone:

•BackboneJS is really easy to make many small updates to the DOM for a single user interaction. For large data structures, this can lead to a poor user experience.
•BackboneJS is opinionated about is the RESTful API, working with non RESTful API back-end, or supporting different URI schemes, can sometimes be difficult with            BackboneJS.
•BackboneJS Models are reasonably straightforward to unit test. Unit-testing Backbone Views on the other hand, is very hard.
•BackboneJS creates an empty div element for each Backbone view. This can lead to a lot of redundant DIVs in the generated HTML
•The lack of a controller building block is also a disadvantage to the BackboneJS.

Architecture diagram of backbone:

Now let us look through a certain diagram for understanding the workflow of backbone.js.
backbone workflow

Model in Backbone.js:

Models are the heart of any JavaScript application, containing the interactive data as well as a large part of the logic surrounding it: conversions, validations, computed properties, and access control. There are two types of models, Thread and Message. Thread being able to contain multiple Messages.
1> Message Model:The Message model is the most simple model structure.

 $.forum.Message = Backbone.RelationalModel.extend({
    urlRoot: '/api/message',
    idAttribute: '_id',
   });

2>Thread Model:

$.forum.Thread = Backbone.RelationalModel.extend({
    urlRoot: '/api/thread',
    idAttribute: '_id',
    relations: [{
        type: Backbone.HasMany,
        key: 'messages',
        relatedModel: '$.forum.Message',
        reverseRelation: {
            key: 'thread',
            includeInJSON: '_id',
        },
    }]
});

The relations option we are using comes from Backbone-relational. It allows to specify how the Thread objects relate to the Message objects:
type: Backbone.HasMany: Each Thread can contain references to multiple Messages.
key: ‘messages’: The name of the attribute of Thread objects containing the external references. Thread.messages will contain an array of Messages.
relatedModel: ‘$.forum.Message’: The model being referenced.
reverseRelation.key = ‘thread’: The reverse reference to the Thread object, from each of the Message objects contained.
reverseRelation.includeInJSON = ‘_id’: Tells Backbone-relational to store the value of one of the Thread attributes in message.thread, rather than a reference to the object itself.
Creating a model:

As we have mentioned earlier, that we represent our data as models in backbone. So, at first we will discuss the creation process of the models. If we wish to create a new user on the server then we will instantiate a new User and call save.

var reg_name,reg_pass;
    var Client = Backbone.Model.extend({
        defaults : {
             name : null,
            pwd : null
        },

        initialize : function() {
            console.log("initialize client");

Updating a model:
As we update any data according to our needs in a web application. In backbone we are allowed to do so with the models too. Now that we have a model that exist on the server we can perform an update using a PUT request. We will use the save api call which is intelligent and will send a PUT request instead of a POST request if an id is present.

Deleting a model:
In the above we have created a model, updated the name attribute of that model. Now we are going to see the process of deleting the same model. We know our model has an id that exists on the server, so if we wish to remove it from the server we can call destroy ().

Setting attributes in model:
We have created model. Now we want to pass some parameters when we create an instance of our model. In this code snippet we can see that we are passing values as parameter in time of initialization. passing a JavaScript object to our constructor is the same as calling model.set().

User = Backbone.Model.extend({
        initialize: function(){
            alert("Hello!");
        }
    });
        var user= newUser({ name: "name", age: 24});

Getting attributes of model:
There will be many times where we want to try retrieve the values of models. There is an easy process to it, we are going to discuss this method now. Using the model.get() method we can access model properties at anytime.

Retrieving a model:
We can retrieve the model from the server. If we instantiate a model with an parameter, Backbone.js will automatically perform a get request to the urlRoot + ‘/parameter’.

Interacting with the server:

Models are used to represent data from your server and actions you perform on them will be translated to RESTful operations.
The id attribute of a model identifies how to find it on the database usually mapping to the surrogate key.The server has implemented a RESTful URL /user which allows us to interact with it.

var UserModel = Backbone.Model.extend({
 urlRoot: '/user',
 defaults: {
----values----
 }
What is a view?

Backbone views are used to reflect what your applications’ data models look like. They are also used to listen to events and react accordingly.

var UserView = Backbone.View.extend({
        el : $("#divUser"),
        initialize : function() {
            var that = this;

            this.listeUsers = new UsersCollection();
			 this.listUsers = new UsersCollection();
            this.listeUsers.bind("add", function(model){

		        that.addUserToList(model);

The “el” property
The “el” property references the DOM object created in the browser. Every Backbone.js view has an “el” property, and if it not defined, Backbone.js will construct its own, which is an empty div element.

 el : $("#divUser"),

Constructor / initialize:
We can initialize a view using new View ([options]) .if we pass properties like model, collection, el, id, className, tagName, attributes and events through the view.those properties will be attached directly to the view. If the view defines an initialize function, it will be called when the view is first created.

What is collection in backbone?

Backbone collections are simply an ordered set of models. By using Models and Collections we can avoid putting data manipulation logic into our Views. Plus, Models and Collections provide convenience methods for working with a back-end, and can automatically signal Backbone Views when the data changes.

 var UsersCollection = Backbone.Collection.extend({
        model : User,
        initialize : function() {
            console.log("initialize users collection");

            this.bind("add", function(model){ console.log("Add", model.get('id'), model); });

            this.bind("remove", function(el){ console.log("Remove", el.get('id'), el); });

Add models to a collection:

As we know collections are a collection of models.So,we can add models to a collection. To add models to a collection we can use the “add” method.we can also add a model to the beginning of a collection by using the unshift method.

 this.bind("add", function(model){ console.log("Add", model.get('id'), model); });

Remove models from a collection:
Many times we will feel the need to remove some specific data from a collection.To remove a model from a collection, we can provide the id of the model that we want to remove.If we want to replace a collection with a completely new set of data.We can use the reset method. We’ve made a bunch of changes to our current collection. Let’s start over by passing the original array back in.

this.bind("remove", function(el){ console.log("Remove", el.get('id'), el); });

Get & Set:
When we need to get a value from a collection from somewhere else in code, using the get method is fairly straightforward. We can pass in the id value to retrieve the model that we want to get…

The set method for a collection has an interesting implementation.The set method performs a “smart” update of the collection with the passed list of models. If a model in the list isn’t yet in the collection it will be added. If the model is already in the collection its attributes will be merged. And if the collection contains any models that aren’t present in the list, they’ll be removed.

constructor / initialize:

When creating a Collection,we can pass in the initial array of models. The collection’s comparator may be included as an option. Passing false as the comparator option will prevent sorting. If we define an initialize function, it will be invoked when the collection is created. There are a couple of options that, if provided, are attached to the collection
directly: model and comparator.

comparator:

By default there is no comparator for a collection. If we are to define a comparator, it will be used to maintain the collection in sorted order. This means that as models are added, they are inserted at the correct index in collection.models. A comparator can be defined as a sortBy , as a sort , or as a string indicating the attribute to sort by.
“sortBy” comparator functions take a model and return a numeric or string value by which the model should be ordered relative to others.
“sort” comparator functions take two models, and return -1 if the first model should come before the second, 0 if they are of the same rank and 1 if the first model should come after.

url:

Sets the url property on a collection to reference its location on the server. Models within the collection will use url to construct URLs of their own.

parse:

parse is called by Backbone whenever a collection’s models are returned by the server, in fetch. The function is passed the raw response object.it should return the array of model attributes to be added to the collection. The default implementation is a no-op. simply passing through the JSON response. Override this to work with a preexisting API, or better namespace responses.

fetch:

Fetches the default set of models for this collection from the server, setting them on the collection when they arrive. The options hash takes success and error callbacks which will both be passed (collection, response, options) as arguments. Then the model data returns from the server.It uses set to merge the fetched models. Delegates to Backbone.sync under the covers for custom persistence strategies and returns a jqXHR. The server handler for fetch requests should return a JSON array of models.

How to use templates in backbone?

One of the more important components of Backbone.js is templates. Templates are essentially pieces of markup that can be used to create a bunch of different reusable copies of that same markup. But populating each component with different data. Used in combination with views, they are great for doing such as iterating over a collection of models to display a list of data for some purpose. Backbone.js uses the template engine of Underscore.js which makes sense because Backbone has a hard dependency on Underscore. Backbone allows for different multiple template engine. The possibilities are limitless. But let’s first take a look at an Underscore.js template because that will work out of the box with Backbone.js.

window.EventView = Backbone.View.extend({
      template: _.template($('#calendar-event-template').html()),
      render: function() {
        $(this.el).html(this.template(this.model.toJSON()));
        return this;
      }
    });

As we can see in the above code snippet, we have used underscore template. The _.template() Underscore method takes as its argument the “html” extracted from the type=”text/template” tag. The result of the _.template() call is a function that will return a string with the things inside replaced with key-values passed into the function. Since the template only requires that title and description values be defined .in case we have the local variables, we can invoke the function as event_html({title: title, description: description}). To append that to the existing table cell we should convert the resulting HTML string into a jQuery object and append it to the cell element.
In the above code snippet we have created an individual view that corresponds to single calendar event. The results are much simpler conceptually. All that I need implement in the view class is a template attribute and a render method. As we can see the render method just extracts the attributes from the model and passes them to the template function.

Events in Backbone:

Events is a module that can be mixed in to any object, giving the object the ability to bind and trigger custom named events. Events do not have to be declared before they are bound, and may take passed arguments.

on:
This event also known as bind.Binds a callback function to an object. The callback will be invoked whenever the event is fired. If we have different events on a page, the convention is to use colons to namespace them: “poll:start”, or “change:selection”. The event string may also be a space-delimited list of several events.

off:
Also known as unbind.Removes a previously bound callback function from an object. If no context is specified, all of the versions of the callback with different contexts will be removed. If no callback is specified, all callbacks for the event will be removed. If no event is specified, callbacks for all events will be removed.

trigger:
Trigger callbacks for the given event, or space-delimited list of events. Subsequent arguments to trigger will be passed along to the event callbacks.

object.trigger("alert", "an event");

listenTo:
listenTo Tells an object to listen to a particular event on an other object. The advantage of using this form, instead of other.on, is that listenTo allows the object to keep track of the events, and they can be removed all at once later on. The callback will always be called with object as context.

What is a router?

As backbone being a platform which supports the client side. We also in need for a traditional Request/Response website. We fully expect the back and forward history navigation to work. With the stateless nature of the traditional website, this was very easy to implement. The browser needed only to keep track of the previously requested URLs and request them again when the user asks for them Single Page Applications built using JavaScript are stateful and will require programmer intervention to allow this appearance of functioning history. Luckily for us, Backbone provides mechanisms to make this process easier. The URL of the application should change when the content on the screen changes. We also like to share URLs with other people, as well as bookmark these URLs for later browsing. Typically, traditional web apps have a URL that points to a resource on the server, beginning with a forward slash. Every time a new page is requested, the server responds with an entirely new page based on that URL.

Backbone routers are used for routing applications URL’s when using hash tags(#). In the traditional MVC sense they don’t necessarily fit the semantics. Though a Backbone “router” is still very useful for any application/feature that needs URL routing/history capabilities. Defined routers should always contain at least one route and a function to map the particular route to.

Also note that routes interpret anything after “#” tag in the URL. All links in your application should target “#/action” or “#action”. (Appending a forward slash after the hashtag looks a bit nicer.

var AppRouter = Backbone.Router.extend({
        routes: {
            "*actions": "defaultRoute" 
        }
    });
    // Initiate the router
    var app_router = new AppRouter;
    app_router.on('route:defaultRoute', function(actions) {
        alert(actions);
    })

    // Start Backbone history a necessary step for bookmarkable URL's
    Backbone.history.start();

extend:

Now create a custom router class. Define actions that are triggered when certain URL fragments are matched, and provide a routes hash that pairs routes to actions.

var myrouter = Backbone.Router.extend({
  routes: {
    "help":                 "help",    
    "search/:query":        "search" 
  },
  help: function() {
    ...
  },
  search: function(query) {
    ...
  }
});

routes:

The routes hash maps URLs with parameters to functions on router, similar to the View’s events hash. Routes can contain parameter parts, :param, which match a single URL component between slashes; and splat parts *splat, which can match any number of URL components. Part of a route can be made optional by surrounding it in parentheses (/:optional).

When the visitor presses the back button, or enters a URL, and a particular route is matched, the name of the action will be fired as an event, so that other objects can listen to the router, and be notified. In the following example, visiting #help/uploading will fire a route:help event from the router.

route:

Manually creates a route for the router, The route argument may be a routing string or regular expression. Each matching capture from the route or regular expression will be passed as an argument to the callback. The name argument will be triggered as a “route:name” event whenever the route is matched. If the callback argument is omitted router[name] will be used instead.

navigate:

Whenever an application has to be save as a URL, call navigate in order to update the URL. If we want to also call the route function, set the trigger option to true. To update the URL without creating an entry in the browser’s history, set the replace option to true.

user_details: function(userid) {
  this.document.pages.at(userid).open();
  this.navigate("user/" + userid);

History:

History serves as a global router (per frame) to handle hash-change events or push State, match the appropriate route, and trigger callbacks. we shouldn’t ever have to create one of these our self since Backbone.history already contains one.
push-state support exists on a purely opt-in basis in Backbone. Older browsers that don’t support push-state will continue to use hash-based URL fragments, and if a hash URL is visited by a push-state-capable browser, it will be transparently upgraded to the true URL.using real URLs requires web server to be able to correctly render those pages, so back-end changes are required as well. For full search-engine crawl ability, it’s best to have the server generate the complete HTML for the page. but if it’s a web application, just rendering the same content would have for the root URL, and filling in the rest with Backbone Views and JavaScript works fine.

start:

When all of Routers have been created, and all of the routes are set up properly, call Backbone.history.start() to begin monitoring hash-change events, and dispatching routes.to use HTML5 push-state support in application, use Backbone.history.start({push-state: true}). If you’d like to use push-state, instead, we also can add {hash-change: false} to the options.

 Backbone.history.start({pushState: true, root: "/public/search/"})
creating a single page application:

Architectural Diagram:

Let us see the basic diagram of the project we are going to do.
SPA Project

Coding:

HTML code:


  <head>
    <title>Backbone</title>
    <script data-require="underscore.js@*" data-semver="1.5.2" src="//cdn.jsdelivr.net/underscorejs/1.5.2/underscore-min.js"></script>
    <script data-require="jquery@*" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
    <script data-require="backbone.js@*" data-semver="1.0.0" src="//cdn.jsdelivr.net/backbonejs/1.0.0/backbone-min.js"></script>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  </head>

  <body>
    <div id="divUser">
        username:         <input type="text" id="txtIdUser" placeholder="username" />
        <br/>

          password :       <input type="text" id="txtNomUser" placeholder="paas" />

     <br/>              
          <button id="login">Login</button>     

     <button id="Retry">Retry</button>
     <br/>
     To Register Please <button id="cmdAddUser">Click Here</button>
      <br />
      <ul id="listeUser"></ul>
    </div>

JavaScript code:

var reg_name,reg_pass;
    var User = Backbone.Model.extend({
        defaults : {
             name : null,
            pwd : null
        },

        initialize : function() {
            console.log("initialize user");

		}
    });

    var UsersCollection = Backbone.Collection.extend({
        model : User,
        initialize : function() {
            console.log("initialize users collection");

            this.bind("add", function(model){ console.log("Add", model.get('id'), model); });

            this.bind("remove", function(el){ console.log("Remove", el.get('id'), el); });
        }
    });

    var UserView = Backbone.View.extend({
        el : $("#divUser"), /* Utilisation de zepto pour lier UserView au DOM */
        initialize : function() {
            var that = this;
                       this.listeUsers = new UsersCollection();
			 this.listUsers = new UsersCollection();
            this.listeUsers.bind("add", function(model){
        		        that.addUserToList(model);

		    });
			this.listUsers.bind("add", function(model){

		        that.addLoginToList(model);

		    });
        },
                events : {
            'click #cmdAddUser' : 'cmdAddUser_Click' ,
			'click #login' : 'login'

        },

        cmdAddUser_Click : function(){
            var tmpUser = new User({
               name : $("#txtIdUser").val(),
                pwd : $("#txtNomUser").val(),

             });

            this.listeUsers.add(tmpUser);
        },
		login : function(){

            var tmplogin = new User({
             name : $("#txtIdUser").val(),
                pwd : $("#txtNomUser").val(),

             });
        this.listUsers.add(tmplogin);
        },

    addUserToList : function(model) {
	reg_name=model.get('name');
	reg_pass=model.get('pwd');

            $("#listeUser").html("Sucessfully Registred, login now");
        },

    addLoginToList : function(model) {
;
	if(model.get('name')==reg_name && model.get('pwd')==reg_pass)
	{

            $("#divUser").html("Login sucessfull");

        }
		else
		{
	       $("#listeUser").html("Failed Logged in, Retry");

		}
		}

    });

    //var userView = new UserView();

   var userView = new UserView();

  Backbone.history.start();
Useful links

1) Backbone :
http://backbonejs.org/
2) Jquery:
http://jquery.com/
3) Underscore:
http://underscorejs.org/
4) Sources:
http://backbonetutorials.com/
http://stackoverflow.com/

Some related articles :

1>Introduction to Backbone.js

2>Models in Backbone.js

3>Underscore Methods in Backbone.js

4>Backbone Routes and History

5>Collections in Backbone.js

6>Understanding view in Backbone.js

7>Templates In Backbone.js

8>WHY SHOULD WE USE SERVER SIDE IN BACKBONE.JS?

If you find this article helpful, you can connect us in Google+ and Twitter.

1 thought on “Backbone.js at a glance

Leave a Reply

Your email address will not be published. Required fields are marked *