Writing your first application using Backbone.js


Getting Started

As we know, writing a Single Page application using just jQuery is not quite a good idea especially when our application grows bigger and we need to modularize our codebase. To resolve this problem, there are many MV* frameworks available for us.

What is Backbone.js

Backbone.js is one of the many Javascript frameworks for creating MVC-like web applications which comes with a default template engine Underscore.js. Backbone.js lets us split our code into Model, Collection and View. The general idea is to organize an interface into logical views, backed by models, each of which can be updated independently when the model changes, without having to redraw the page.

On the front-end, it’s my architectural framework of choice as it’s both mature, relatively lightweight and can be easily tested using third-party toolkits such as Jasmine or QUnit.
– Developing Backbone.js Applications by Addy Osmani.

What is MVC

In this case, each contact is our Model, all the contacts group together by Collection and View renders the contacts details. We are going to use contacts mysql table for this application so contacts table is our Collection and each row exists in the table is our Model.

Let us begin

Let’s start by writing our first Backbone.js app – Addressbook in Backbone.js. Here is our 2-column layout, one for side links on the left and another to load forms/grid.

addressbookMVC/index.html – Main Layout

<div class='table abWrapper'>
  <div class='row'>
    <div class='cell abLinks'>
      <a href='#add_new_contact'>Add New Contact</a><br />
      <a href='#list_contacts'>List all Contacts</a><br />
      <a href='#search_contacts'>Search any Contact</a><br />
    </div>
    <div class='cell abPanel'>Loading... Please Wait.</div>
  </div>
</div>

Add New Contact – Backbone.View and Backbone.Model

We’ll write our first view addView and load it inside div.abPanel. We can write our custom view by extending Backbone.View.extend() method and can keep our templates either into a same page or can load it from a separate html file. In this case, we’ll simply wrap our template in <script> tag by giving it a special type and an id:

addressbookMVC/index.html – addNewContact Template


  <h2> Add New Contact</h2>
  
    <div>Full Name:</div>  <span class='false full_name_error'></span><br />
    <div>Email Id:</div>  <span class='false email_error'></span><br />
    <div>Phone:</div>  <span class='false phone_error'></span><br />
    <div>Address:</div> 
    
    <span class='success'></span>
    
  

Backbone View allows us to specify custom methods and properties but there are some predefined attributes you should use to simplify the flow and maintain the unity between all backbone apps.
el – specify the DOM element selector where you want to load your template within a page. In our case its div.abPanel.
template – The _.template method in Underscore compiles JavaScript template into function which can be evaluated for rendering.
initialize – The constructor to keep a piece of code to be executed while creating an instance of a view.

Below is our AB.addView backbone view which compiles the template mentioned above  and load it into el. 

addressbookMVC/js/script.js – addNewContact View

AB.addView = Backbone.View.extend({
  el: 'div.abPanel',
  template: _.template($('#addContactTemplate').html()),
  initialize: function () {
    _.bindAll(this, 'addContactPage');
  },
  addContactPage: function () {
    this.$el.html(this.template());
  }
});

In above code, we have used the _.bindAll method in Underscore which fixes the loss of context for this within methods. So we have to specify all those method names wherein we’ll use this.any_method or this.any_property i.e. this.$el, this.template etc.

In backbone.js, there is no need to grab elements the jquery way and attach some events to them. There is a special attribute events which allows us to attach event listeners to either custom selectors or directly to el if no selector is provided. It takes the form {‘eventName selector’ : ‘callbackMethod’}, So we can attach the submit event to our <form> in order to prevent the default form submission and fetch the form data. And once we get the data, we can simply call model.save() method to save the record into the DB which invokes Backbone.sync function every time we attempt to read or save a model to the server by making a RESTful JSON request.

Lets write our contactModel first. Notice that if a passed JSON data to model.save() contains an id key then a method name will be update in model.sync() else it will be create.

addressbookMVC/js/script.js – Contact Model

AB.contactModel = Backbone.Model.extend({
  sync: function (method, model, options) {
    if (method === 'create' || method === 'update') {
      return $.ajax({
        dataType: 'json',
        url: '../php/addNewContact.php',
        data: {
          id: (this.get('id') || ''),
          full_name: (this.get('full_name') || ''),
          email: (this.get('email') || ''),
          phone: (this.get('phone') || ''),
          address: (this.get('address') || '')
        },
        success: function (data) {
          // put your code after the contact is saved/updated.
        }
      });
    }
  }
});

Now we’ll create an instance of above model in our view and call the save() method.

addressbookMVC/js/script.js – addNewContact View

AB.addView = Backbone.View.extend({
  events: {
    'submit form#frmAddContact': 'addContact'
  },
  addContact: function (event) {
    var full_name = $('#full_name').val(),
        email = $('#email').val(),
        phone = $('#phone').val(),
        address = $('#address').val(),
        id = $('#id').val();
        
    if (id === '') {
      var contactmodel = new AB.contactModel({
        full_name: full_name,
        email: email,
        phone: phone,
        address: address
      });
    } else {
      var contactmodel = new AB.contactModel({
        id: id,
        full_name: full_name,
        email: email,
        phone: phone,
        address: address
      });
    }
    contactmodel.save();
    return false;
  }
});

List contacts – Backbone.View & Backbone.Collection

Usually we make an AJAX request to fetch all the data in JSON format but there is a special method collection.fetch() available to fetch the default set of models for the collection from the server based on the url defined in the collection. We’ll write our collection by specifying the model and the url:

# addressbookMVC/js/script.js – Contacts Collection

AB.contactsCollection = Backbone.Collection.extend({
  model: AB.contactModel,
  url: '../php/listContacts.php'
});

And we’ll put the templates in index.html:

addressbookMVC/index.html – listContacts Template


  <h2>List Contacts</h2>
  <table id='contactsGrid' width='100%' border='1' cellspacing='1' cellpadding='5'>
    <tr>
      <td width='25%'><b>Full Name</b></td>
      <td width='25%'><b>Email ID</b></td>
      <td width='15%'><b>Phone</b></td>
      <td width='25%'><b>Address</b></td>
      <td width='10%' align='center'><b>Action</b></td>
    </tr>
    
      <tr><td colspan='5'>No Record Found</td></tr>
    
          &lt;tr data-id=&gt;
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td align='center'><a>Edit</a> | <a>Delete</a></td>
          </tr>
    
  </table>

And then call the fetch() within its View:

addressbookMVC/js/script.js – listAllContacts View

AB.listView = Backbone.View.extend({
  el: 'div.abPanel',

  template: _.template($('#listContactsTemplate').html()),

  initialize: function () {
    _.bindAll(this, 'listContactsPage', 'render');
  },

  render: function (response) {
    var self = this;

    this.$el.html(this.template({contacts: response}));
  },

  listContactsPage: function (querystring) {
    var self = this;

    AB.contactscollection.fetch({
      data: querystring,
      success: function (collection, response) {
        self.render(response);
      }
    });
  }
});

Search contacts – Backbone.View and Backbone.Collection

I will not explain this section in detail because it is pretty much similar when it comes to load a searchContacts template into a page and to show all the contacts based on the search criteria, we can reuse the same method listContactsPage({full_name: ‘alice’}) from AB.listView class. We’ll get it once we go through the codebase. Lets move on to Backbone.Router.

Backbone.Router

In Backbone, routers are used to help manage application state and for connecting URLs to application events. This is achieved using hash-tags with URL fragments, or using the browser’s pushState and History API. Some examples of routes may be seen below:
http://addressbook.com/#addNewContact
http://addressbook.com/#editContact/6
When all of our routers have been created, and all of the routes are set up properly, call Backbone.history.start() to begin monitoring hashchange events, and dispatching routes. Inside run method, we are updating the hash to #add_new_contact and triggering it immediately so that renderAddNewContactPage will be called immediately once the page is loaded.

# addressbookMVC/js/script.js – Backbone.Router

var AB = {
  run: function () {
    this.addview = new this.addView();
    this.listview = new this.listView();
    this.searchview = new this.searchView();
    this.contactscollection = new AB.contactsCollection();
    this.router = new this.Router();
    Backbone.history.start();
    this.router.navigate('add_new_contact', {trigger: true});   
  }
};

AB.Router = Backbone.Router.extend({
  routes: {
    'list_contacts': 'renderListContactsPage',
    'add_new_contact': 'renderAddNewContactPage',
    'search_contacts': 'renderSearchContactsPage',
    'edit_contact/:id': 'renderEditContactPage'
  },

  renderAddNewContactPage: function () {
    AB.addview.addContactPage();
  },

  renderListContactsPage: function () {
    AB.listview.setElement('div.abPanel');
    AB.listview.listContactsPage();
  },

  renderSearchContactsPage: function () {
    AB.searchview.searchContactsPage();
  },  

  renderEditContactPage: function (id) {
    AB.addview.addContactPage(id);
  }
});

Summary

I simply love to use Backbone.js in my projects, its amazing.

Download the source code from github

And do share your thoughts in the comment section below.

Updates:

Since a very long time, I wanted to try out Require.js in my projects and what could be the best way than to rewrite the addressBook in backbone.js and require.js again.
So here it is: addressBook in Backbone.js and Require.js

Happy Hacking 🙂

If you found this article useful in anyway, feel free to donate me and receive my dilettante painting as a token of appreciation for your donation.

Pedigree/Family Tree using HTML table


For my recent project, i wanted to create a family tree structure for parent-child relationships. After a lot searches, i decided to build it using HTML table.

Lets begin…

First of all, we are going to write a render function which has an array of data to be shown.

$arrPedigree = array(
array(
'name' => 'Parent',
'children' => array(
array(
'name' => 'Child 1',
'children' => array(
array(
'name' => 'Sub Child 11',
'children' => array(
array(
'name' => 'Sub Sub Child 111',
),
array(
'name' => 'Sub Sub Child 112',
),
)
),
array(
'name' => 'Sub Child 12'
)
)
),
array(
'name' => 'Child 2',
'children' => array(
array(
'name' => 'Sub Child 21'
),
array(
'name' => 'Sub Child 22'
)
)
)
)
)
);
view raw pedigree.php hosted with ❤ by GitHub

Finally we need to loop through the array to create the structure and we’ll use some CSS classes to draw some lines for connecting parent to its children.

Pedigree/Family Tree
Pedigree/Family Tree

Download Code Here

The conventions to be followed for OOP in PHP


Hi guys,

I always give preference to the conventions over configurations. If somebody wants to be a professional programmer then must follow the conventions.

Here are some conventions i came up with based on PEAR Coding Standards which are good.

1. ClassName – Emailer, Logger, ErrorHandler, PEAR(this is a package name, that is why, it is in CAPS)

2. Public Methods – log, logError, PEAR_init (to avoid method name collisions between packages)

3. Protected Methods – _log, _logError, _PEAR_initMe

4. Private Methods – __log, __logError, __PEAR_initMe

5. Constant/Static Variables – MY_FIRST_CONSTANT, PEAR_MY_FIRST_CONSTANT(to var name collisions between packages)

6. Global Variables – $_MY_FIRST_GLOBAL, $_PEAR_MY_FIRST_GLOBAL(to avoid var name collisions between packages)

I hope this will help to improve us. And this way, we can remember conventions easily, that is why i did not give the full description.

Url Rewriting using php, smarty and mod_rewrite


Let’s learn to rewrite the website url today.

According to me, before learning something new, we should take a look at why we need to do it and what’s the use of it.

Use of URL rewriting:
1. Making website URLs more user and search engine friendly.
2. Preventing undesired “inline linking”.
3. Not exposing the inner workings of a web site’s address to visitors

So let’s begin…

Project Name: url_rewriting
Dir. Structure: url_rewriting
– cache
– configs
– libs
– templates
– templates_c
– .htaccess
– other php files

What we want to achieve:
here we want to convert the following url
from,
http://www.orkut.com/UniversalSearch.php?origin=box&exp=1&q=php
to
http://www.orkut.com/box/1/php/UniversalSearch.html

How we can achieve:
we need to first create a file “function.seo_optimise.php” in “smarty/lib/plugins/”, so that smarty will treat it as its own function without any hassal.

function smarty_function_seo_optimise($params, &$smarty)
{
// we will add code here later...
}

Done… 50%

Now secondly, we have to create a .htaccess file in the directory structure as shown above. And add following…


php_value error_reporting 7
Options +FollowSymLinks
RewriteEngine on
RewriteRule ^(.*)/([0-9]+)/(.*)/UniversalSearch.html$ UniversalSearch.php?origin=$1&exp=$2&q=$3


Please note that, (.*) suggest the type of text we are sending to perticular querystring. Like for origin querystring, we are going to send anything including characters & numbers, or in case of exp querystring, we are going to send only numbers thats why we have used ([0-9]+) in order to restrict the querystring value to the numbers only.

Done... 70%

I know, you are confused now, because you are thinking that how smarty will know, (.*) for origin, ([0-9]+) for exp and (.*) for q. Do not worry, thats we have created "function.seo_optimise.php" file above. Now, open this file, and write the following code... please note that here we are going to send three querystrings to the page thats why we have to pass three parameters to the function also. These are the three parameters..

function smarty_function_seo_optimise($params, &$smarty)
{
    /* This is for three querystrings */
        $origin =  $params[origin];
        $exp     =  $params[exp];
        $q         =  $params[q];
   /* This is to recognise the page to which we are going to rewrite */
   if($params[type] == 'universal_page')
   {
       if($params[urls] == 'Enable')
           return $origin."/".$exp."/".$q."/UniversalSearch.html";
       else
           return "UniversalSearch.php?origin=".$origin."&exp=".$exp."&q=".$q
   }
}


Done... 80%

Now let me explain you, this smarty function will transform our old url to new like this... http://www.orkut.com/box/1/php/UniversalSearch.html Ok then, time to spell the beans... to convert that url we have to write following in .tpl file.

{seo_optimise urls=$seo_urls origin=box exp=1 q=php type=universal_page}

<a href="http://www.blogger.com/%7Bseo_optimise%20urls=$seo_urls%20origin=box%20exp=1%20q=php%20type=universal_page%7D">
Click me
</a>

here is a explaination...

$seo_urls => Enable/Disable

when the page get loaded, that seo_optimise will pass the supplied parameters to the function of a same name created in smarty/lib/plugins/function.seo_optimise.php.

1. First, it will add the passed value to appropriete variables as mentioned above in this php file.
2. secondly, it will check which page you want to rewrite using "type" variable.
3. If it is "universal_page" and $seo_urls is "Enable" then it will return the url like http://www.orkut.com/box/1/php/UniversalSearch.html or if $seo_urls is "Disable" then it will return the url like http://www.orkut.com/UniversalSearch.php?origin=box&exp=1&q=php
Done... 100%

Using this way we can rewrite any url in any ways you want, just do not forget to enter the old url & new url in .htaccess file.