Getting started with deploying SPA, Node and Mongo Apps on Heroku - Developer Focused

Overview

First of all this blog is developer focused, hence I avoid going into details like Heroku for production. The purpose is to help developers quickly deploy apps on heroku for testing

What is Heroku?

Heroku is a Cloud Application Platform. It enables you to quickly and painlessly deploy your Applications on the cloud.

[singlepic id=59 w=800 h=600 float=]

Heroku supports following languages

[singlepic id=63 w=600 h=400 float=]

Why use Heroku?

In today's world a developer's Resume is really the following

Linkedin Profile Pointing to the following

    1. Your Opinions - e.g Blog
    2. Your Ideas - e.g Twitter
    3. Your Skills and Accomplishments as Ployglot programmer- Series of Hosted Applications on the cloud
    4. Online Source Code e.g github.com
    5. Online Forum Activity and Scores e.g StackOverflow
    6. Online Presentations e.g Slide share
    7. Online Videos e.g Youtube

Now lets focus on the part in Red - Series of Hosted Applications on the cloud

A Developer writing, testing and showcasing application on the cloud has to as easy as he/she does this on his/her laptop. And Developers love

  1. Free Quotas on Servers, Database and Hosting
  2. Command line tools to work on cloud as they are working locally
  3. Popular AddOns e.g for Node easy and ready addons like Mongo, Redis, etc makes lot of sense
  4. Use known tools to deploy the app

Well Heroku is built thinking about all these things.

Getting Started Guide Available for Popular Languages

[singlepic id=62 w=600 h=400 float=]

Command Line Tool Available to deploy apps and check logs and status

[singlepic id=60 w=600 h=400 float=]

Easy to Add Free Quota based Addons

[singlepic id=61 w=600 h=400 float=]

How to use Heroku?

Enough of Bluff, now lets move to Stuff

Steps

  1. Create Heruko Account & Install Command Line Tool
  2. Clone existing Node, SPA (Single Page Application - HTML/JS), MongoDB locally
  3. Run the existing Node, SPA, MongoDB Application locally
  4. Run the existing Node, SPA, MongoDB Application locally using Heroku
  5. Run the existing Node, SPA, MongoDB Application on cloud using Heroku

Lets get Started

Create Heruko Account & Install Command Line Tool

Step 1

Goto https://id.heroku.com/signup/devcenter and sign up

Step 2

Install Heroku Toolbet from https://toolbelt.heroku.com/

Step 3

Ensure Heroku is properly installed by trying heroku tool on command prompt

$> heroku

Clone existing Node, SPA, MongoDB locally

SPA stands for Single Page Application typically built using HTML5, JavaScript and CSS3

We will refer to an already existing Todo MVC from this source - https://github.com/Stackato-Apps/node-backbone-mongo

* Todo MVC - An App which demonstrates how to create a simple Todo App, in various technology stacks. This is the new Hello World

Prerequistes

  1. git command line client is installed
  2. node and npm are installed
  3. mongodb 2.4.x downloaded, unzipped and in path
  4. configure git and npm to work around any firewall restrictions you have

Step 1

Clone the example from github

$>git clone https://github.com/Stackato-Apps/node-backbone-mongo.git

Run the existing Node, SPA, MongoDB Application locally

Step 1

Start your mongodb database

$>mongod

Verify whether mongodb is running by trying following command on a different command prompt

$>mongo

* mongod is the mongo daemon/server and mongo is the client to connect to the server to try few mongo commands. Do not close the command prompt running mongod

 Step 2

Fetch all the dependencies

$>cd node-backbone-mongo

Download all dependencies

$>npm install

Step 3

Start the application

$>node app.js

Open Browser - http://localhost:3000

[singlepic id=64 w=800 h=600 float=]

 

Run the existing Node, SPA, MongoDB Application locally using Heroku

Step 1

Login into Heroku using command prompt tool

$>cd node-backbone-mongo

$>heroku login

Step 2

Create Application on Heroku Cloud using command prompt Tool

$>cd node-backbone-mongo

$>heroku apps:create todomvc-trial

* the app name is unique across heroku, try some other unique name

Step 3

Create a Procfile

$>cd node-backbone-mongo

$>echo "web: node app.js" > Procfile

* Basically use any text editor and create a Procfile with following text

web: node app.js

Step 4

Run App locally using Heroku

The tool heroku uses to run the app locally is called as foreman and the it reads the Procfile to find out what it needs to run

$>cd node-backbone-mongo

$>foreman start

Start browser - http://localhost:5000/

[singlepic id=65 w=800 h=600 float=]

Run the existing Node, SPA, MongoDB Application on cloud using Heroku

Lets first of all foresee what problems we will face if we run this application as it is on Cloud

  1. It assumes there is a MongoDB server running on localhost at predefined port
  2. It assumes it will run on port 5000 - Not to a good port to run web app on

For here onwards there are 3 steps

  1. Add a Mongo DB add on to your Heroku App
  2. Make Code Changes to get correct MongoDB Url and Port Name while running App on the Cloud
  3. Push the App to Heroku (we are running it locally so far)

Add a Mongo DB add on to your Heroku App

Heroku has concept of add ons, which you can add to your existing apps. We will see how to add these from Command Prompt

Step 1

Find the Addon and Command for it

[singlepic id=72 w=800 h=600 float=]

[singlepic id=71 w=800 h=600 float=]

[singlepic id=70 w=800 h=600 float=]

Step 2

Run the Command

$> heroku addons: add mongolab

[singlepic id=69 w=800 h=600 float=]

Step 3

Verify the effects of the Command

[singlepic id=68 w=800 h=600 float=]

Optional

You can proceed and look at the database if you want

[singlepic id=67 w=800 h=600 float=]

 

Make Code Changes

We need to make code changes so our Application use the correct information for the following

  1. Which MongoDB to connect when on cloud and when running locally
  2. Which Port to run the Web Server on when on cloud and when running locally

Lets Open app.js and see what code we need to change

[singlepic id=73 w=800 h=600 float=] Orignal Code

var port = process.env.VCAP_APP_PORT || 3000;

if(process.env.VCAP_SERVICES){
  var services = JSON.parse(process.env.VCAP_SERVICES);
  var dbcreds = services['mongodb'][0].credentials;
}

if(dbcreds){
  console.log(dbcreds);
  mongoose.connect(dbcreds.host, dbcreds.db, dbcreds.port, {user: dbcreds.username, pass: dbcreds.password});
}else{
  mongoose.connect("127.0.0.1", "todomvc", 27017);
}

Modified Code

Heroku has concept of Environment Variables. You need to see things as follows

  1. When you are running app locally using foreman, your code will have access to locally declared environment variables. e,g Port and Mongo DB Urls can come from environment variables or can be hard coded (as we have done)
  2. When you are running app in the cloud using heroku, its running on a server which has its own set of Environment variables. When we added the Mongo DB AddOn, heroku added an Environment variable named "MONGOLAB_URI"

JavaScript has a very easy way of doing if else (for fallback scenarios)

var port = process.env.PORT || 5000; really means if you can find process.env.PORT value (in short read PORT environment variable) then use if , if you don't find it then fallback to 5000

So on the cloud port is 80 and on your local machine it is 5000

Same thing applies to uristring, locally it falls to a locally running mongodb, on the cloud it uses one of the Add On Mongo DB (provided you have added them)

var port = process.env.PORT || 5000;

var uristring =
    process.env.MONGOLAB_URI ||
        process.env.MONGOHQ_URL ||
        'mongodb://localhost/todomvc';

mongoose.connect(uristring, function (err, res) {
    if (err) {
        console.log ('ERROR connecting to: ' + uristring + '. ' + err);
    } else {
        console.log ('Succeeded connected to: ' + uristring);
    }
});

* MONGOLAB_URI and MONGOHQ_URL - Well Heroku provides two addons for Mongo DB, depending on which one you choose heruko will declare one of the above Environment variable on the server/cloud machine where it runs your code

 

Push the App to Heroku

Now the final Step make this app run on the cloud. Well this part can not get any simpler

Heroku pushes code from local machine to its cloud using git mechanims. Its like checking in your code and the server checks it out and runs it (like Continuos build cycles)

Got thing with source code versioning tools like git is that it is a 2 step process

  1. Local Commit for tracking
  2. Push Changes to Remote Repository

Now we said Heroku uses git for pushing code to the cloud, this means your code has to be in a git repository

  1. Either Locally declared git repository
  2. OR cloned git repository as we are doing

 

First step carefully read the following part

 

Recall We did git clone from github

Unlike SVN or CVS, in git, we clone the entire repository on client machine and all the code, history is available. These cloned repository know where they can push changes, in this case the original github repository

Further Recall we did $>heroku apps:create

When we did $>heroku apps:create, it added a remote repository entry in our local git repository (to be precise with the name heroku)

Now when you commit changes locally and the local git repository goes out of sync (or advances) we have an option of pushing those changes to not only the

  1. Original github repository where we cloned from
  2. But also to Heroku cloud

Actual Steps to push code to Heroku

We have made code changes in app.js

Step 1

Commit changes to local repository

$>git commit -a -m "Code changes to make code run on Heroku"

Step 2

Push changes to Heroku

$>git push heroku master

You will see a long log here, which will show you what Heroku is doing on the server when it receives the latest code

Step 3

Access the App running on the cloud

$>heroku open

[singlepic id=74 w=800 h=600 float=]

 

Quick Recap

Following are the commands we used

$>git clone https://github.com/Stackato-Apps/node-backbone-mongo.git

$>heroku login

$>heroku apps:create todomvc-trial

$> heroku addons: add mongolab

$>git commit -a -m "Code changes to make code run on Heroku"

$>git push heroku master

Special Notes

In case you want to link an existing code (which is part of some git repo) with already existing heroku app, you can do the following

 

$ heroku git:remote -a todomvc-trial

 

 

 

Theory - Enabling AR Drone to Track and Follow Objects

Goal

Make AR Drone Follow Objects it sees keeping a constant distance.

[singlepic id=58 w=800 h=600 float=]

Image Reference - http://blog.parrot.com/2012/06/07/ar-drone-give-you-personal-training/

* No Copyright violation intended - References are provided to source of the images

Sub Goals

  1. Enable AR Drone to Track Objects it sees
  2. Enable AR Drone to Measure Depth (Distance)
  3. Control AR Drone's flight to ensure that the Object in field of view

Enable AR Drone to Track Objects

The idea is to use OpenCV and one of its many techniques to Track Object. Simplest of them being Track Objects by color.

Theory

  1. Provide the Camera feed to OpenCV
  2. Select a color to track
  3. Convert that Color to 1 and everything else to 0
  4. Now the Program can see following
  5. Track the moment of the white part on the black background

This is just one of the ways, there are many other ways to do so. To keep things simple in the first attempt, this method is preferred

 

Reference - http://opencv-srf.blogspot.ro/2010/09/object-detection-using-color-seperation.html

Enable AR Drone to Measure Depth (Distance)

Before we talk about using OpenCV to measure Depth, we need to understand more about Computer Vision.

Human Beings have 2 Eyes to give them a Perception of Depth. We focus on an Object and that Object is in center for both of our eyes. Rest of the objects which we do not focus on either move left or right. Our Brain uses this information to figure out the depth/distance.

 

Theory of Stereopsis (How Humans Perceive Depth)

Here is an example taken from http://en.wikipedia.org/wiki/Stereopsis

Human Eye focusing on the Whale. Note, it is not focusing on the Cube infront of the Whale

Left Eye

Note the Cube appears on the Right

Right Eye

Note the Cube appears on the Left

Depth

Human brain uses this disparity of position of Cube to compute Depth

If same has to be applied to Computer Vision (CV), then in the above picture the Light Objects are closer and Darker Objects are farther.

Problem - AR Drone only has one Eye

The biggest problem to apply the above theory to AR Drone to track object and especially its Depth is that AR Drone has only one Camera (One Eye).

Now We can bring in 2 cameras into picture as follows

and this setup works well, but for Computer Vision if you are experimenting in a Lab

What we need is a light weight solution which gives our AR Drone Camera a Stereoscopic Vision.

Here comes another theory and believe me there is no claim from myside on getting the following scientific concept of prisms right. (Probably more reading, buying prisms and working with it would help me ascertain the theory right, but for now its a concept, so don't yell if I got it wrong)

[singlepic id=57 w=800 h=600 float=center]

The idea is to use some light weight prisms and mirrors to make the AR Drone see things as follows

Then use Open CV to create a Depth Map and then AR Drone Program will see Objects as follows

The Lighter parts are closer than the darker part

References -

  1. http://en.wikipedia.org/wiki/Stereopsis
  2. https://sites.google.com/site/elsamuko/c-cpp/opencv-depthmap

Control AR Drone's flight to keep Object in field of view

The Idea is to use

  1. Input from Track Object Program (see above), to control AR Drones Flight Left and Right
  2. Input from Depth Tracking Program (see above), to control AR Drones Flight to Forward and Backwards

Conclusion

While all this is theory at the present moment, I hope you enjoyed reading it. The next steps for me are to play with Open CV on Node Js and do the following things

  1. Write a JavaScript Program to track Objects by Color (for now) and come up with Algorithm to measure how much the camera should be moved to keep the object at center
  2. Build a Stereoscopic Vision set for Laptop Camera and use Open CV to take 2 feeds from same Image and measure depth
  3. Build a Stereoscopic Vision set light enough to be mounted on AR Drone and give the Node JS program Stereoscopic feed
  4. Wire all these together and make AR Drone to see more like we do and make it follow objects

AR Drone - Node JS Controller and Camera Feed

Introduction to AR Drone Parrot 2.0

 

AR Drone Parrot is a QuadCopter which comes with a front facing hd camera and a bottom facing camera. The AR Drone is controlled by sending commands over Wifi thus inherently it is programmable

Browser Based Controller and Camera Feed Receiver

Following is the first of the series of Apps I plan to build.

It is a Browser based Command and Control Dashboard for the AR Drone which also show us the AR Drone Camera Feed. There are buttons available in the toolbar to make the AR Drone Take Off, Spin, Stop and Land.

[singlepic id=54 w=800 h=600 float=]

Usage

Setup

  1. Start AR Drone Parrot 2.0
  2. Connect the Laptop to the ar drone wifi
  3. Clone the project from git hub
  4. run $> npm install
  5. run $> node server.js
  6. Open http://locahost:3000 in Chrome browser

Directions

  1. There are two videos shown here
    1. One from Laptop Camera
      1. You will be prompted to allow access to the Laptop Camera
      2. This is based on WebRTC
    2. One from AR Drone Parrot 2.0
      1. If the Video feed shows, than video feed connection to AR Drone is working fine
  2. The AR Drone can be controlled using the buttons on the Toolbar
    1. Take Off - Click the Take Off button to make the AR Drone Take Off
    2. Spin - Click on the Spin button to make the AR Drone Start Spinning
    3. Stop - Click on the Stop button to stop Spinning
    4. Land - Click on the Land Button to Land the Craft
  3. The Dashboard also shows how much of battery is left on AR Drone

Source Code

The source code be found at https://github.com/rohitghatol/ardrone-nodejs-browser-control

[singlepic id=55 w=600 h=480  float=]

[singlepic id=56 w=600 h=480  float=]

Video Demo

http://www.youtube.com/watch?v=js-V--Qen-Q

 

References

This project uses following

  1. NodeJS Express Server
  2. NodeJS Module - ar-drone
  3. NodeJS Module - dronestream
  4. Socket IO to get the feed from backend server to the Browser

 

 

Learning Jasmine @ Houston.js

@ Houston.js - Learned Jasmine real quick Overview

Jasmine is a Testing Tool for JavaScript

Classes Under Test

Classes under test as follows

var CrewMember = function (name) {
    this.name = name;
}

var Ship = function (name) {
    this.name = name;
    this.crew = [];
    this.goWarp = function () {
        console.log("Going Wrap");
    }

    this.notifyWhenOutofWarp = function(callback){
        setTimeout(callback, 1000);
    }
}

Simplest Test

describe("Crew Member", function () {
    var crew = null;

    beforeEach(function () {
        crew = new CrewMember("Kirk");
    });

    it("should have a name", function () {
        expect(crew.name).toEqual("Kirk");
    });

});

Spy, Run, Wait Feature of Jasmine

describe("Ship", function () {
    var crew = null;
    var ship = null;

    beforeEach(function () {
        crew = new CrewMember("Kirk");
        ship = new Ship("Enterprise");
        spyOn(ship, 'goWarp');
        ship.crew.push(crew);
    });

    it("should have a crew", function () {
        expect(ship.crew.length).toEqual(1);
    });
    it("should go to Warp", function () {
        ship.goWarp();
        expect(ship.goWarp).toHaveBeenCalled();
    });

    it("should call callback when notifyWhenOutofWarp is done", function(){
       var flag = false;
       runs(function() {
           ship.notifyWhenOutofWarp(function() {
               flag = true;        
           });
       });
       waitsFor(function() {
           return flag;
       }, "The notifyWhenOutofWarp(callback) call succeeded", 2000);

       runs(function() {
           expect(flag).toEqual(true);
       });

    });

});

Running Example

[iajsfiddle fiddle="NxgqB" height="500px" width="100%" show="result,js,html" skin="default"]

Single Page Application Ecosystem

Single Page Application aka SPA are the norms of the day for building HTML5 Web or Mobile Applications. They have been around for a while and lot of development is happening in various aspects of SPA. In order to begin understanding the SPA Ecosystem, we need to first understand how SPA can be broken down into various categories. The following diagram depicts that

SPA Ecosystem Categories

[singlepic id=53 w=800 h=600 float=]

The next step is to go through each block of the above diagram, explain each aspect and what Libraries exist today to support them. We will list either most popular libraries only

Build Tool, Dependency Management & Scaffolding

Every Software stack needs set of Build Tools. And as the Software Stack matures, Dependency and Scaffolding tools are added.

Yeoman

Yeoman is a combination of all the above and it has capability to Automate Tasks, pull dependencies and Scaffolds to generate code

Home Page - http://yeoman.io/

three tools for improving your productivity and satisfaction when building a web app: yo (the scaffolding tool), grunt (the build tool) and bower (for package management).

  • Yo scaffolds out a new application, writing your Grunt configuration and pulling in relevant Grunt tasks that you might need for your build.
  • Grunt is used to build, preview and test your project, thanks to help from tasks curated by the Yeoman team and grunt-contrib.
  • Bower is used for dependency management, so that you no longer have to manually download and manage your scripts.

Usage of Yeoman

npm install -g yo grunt-cli bower

Usage of Yo

Install Angular Scaffolding

npm install -g generator-angular

Running Angular Scaffolding

yo angular  

GruntJS Concept

GruntJS in most layman terms is Ant for JavaScript

GruntFile.js - Think of it like build.xml

// Project configuration.
grunt.initConfig({
  uglify: {
    my_target: {
      files: {
        'dest/output.min.js': ['src/input1.js', 'src/input2.js']
      }
    }
  }
});

Running uglify - Think about running ant task

grunt uglify

Bower Concept

Bower is a dependency management tool for JavaScript. It is similar to npm (package.json) of node. Just that Bower is for client side JavaScript

Install bower

npm install -g bower

Define Dependencies

{
  "name": "Bower Starter",
  "version": "1.0.0",
  "dependencies": {
    "requirejs": "latest",
    "jquery": "latest",
    "backbone-amd": "latest",
    "underscore-amd": "latest"
  }
}

Run bower to download dependency

bower install

Mobile Native Packaging

Mobile Native Packaging enables 2 things

  1. Allows HTML5 Apps to be packaged as Native Mobile Applications to be pushed on the app stores
  2. Enriches the HTML5 Apps by providing them native mobile features to use e.g Camera, GPS,  Contacts, Accelerometer etc

The few contenters in the top players for HTML5 Apps for Mobile Packaging are

PhoneGap

PhoneGap aka Cordova is one of the first HTML5 Cross Platform Mobile development framework. PhoneGap supports iOS, Android, Windows Mobile, Black Berry, Bada mobile platforms

PhoneGap can be extended by adding plugins to it.

In terms of Mobile Platform support and Plugin Support PhoneGap is leading

 

Trigger IO

Trigger IO is the newer kid on block when it comes to HTML5 Cross Platform Mobile Framework.

Trigger IO currently only supports Android and iOS, and has lesser support for its Plugins (in terms of number of plugins available). However, Trigger.io claims its JavaScript to native bridge is upto 5 times faster than PhoneGap. Also its builds are faster and easier for developers to manage.

Trigger.io also supports building iOS Apps on Windows platform, since it builds on the cloud.

 

 

StyleSheet Languages

CSS is an key aspect of SPA Space. Even with advancement with CSS3, coding in CSS has been a pain. With no features like inheritances, variables, mix ins creating themes or Responsive UI in basic CSS is a big pain.

That is where new age StyleSheet Languages come into Picture. These Languages provides things like

  1. Nested CSS Declaration - Hierarchical declaration of CSS classes
  2. Variables - Which are great of creating themes
  3. Mix ins - Reusable Snippets of CSS
  4. and more

There are tools available which can convert the Stylesheet written in these languages to CSS understood by the browser

Top Contenders in this space are

SaSS

Sass allows developers to write CSS in different and more power syntax (SCSS/SASS) and provides tools to convert CSS

sample.scss

$blue: #3bbfce;
$margin: 16px;

.content-navigation {
  border-color: $blue;
  color:
    darken($blue, 9%);
}

.border {
  padding: $margin / 2;
  margin: $margin / 2;
  border-color: $blue;
}

converts to following css after sass compilation

/* CSS */

.content-navigation {
  border-color: #3bbfce;
  color: #2b9eab;
}

.border {
  padding: 8px;
  margin: 8px;
  border-color: #3bbfce;
}

Less

On the same lines as SASS, Less is another library to write CSS in a more powerful syntax and compile it to CSS

Less Syntax

.transition(@transition) {
  -webkit-transition: @transition;
     -moz-transition: @transition;
       -o-transition: @transition;
          transition: @transition;
}
.opacity(@opacity) {
  opacity: @opacity / 100;
  filter: ~"alpha(opacity=@{opacity})";
}

a {
  .transition(all 0.4s);
  &:hover {
    .opacity(70);
  }
}

// Selector interpolation only works in 1.3.1+. Try it!
@theGoodThings: ~".food, .beer, .sleep, .javascript";

@{theGoodThings} {
  font-weight: bold;
}

Generated CSS

a {
  -webkit-transition: all 0.4s;
  -moz-transition: all 0.4s;
  -o-transition: all 0.4s;
  transition: all 0.4s;
}
a:hover {
  opacity: 0.7;
  filter: alpha(opacity=70);
}
.food, .beer, .sleep, .javascript {
  font-weight: bold;
}

 

Production Optimization

Product Optimization refers to anything which helps HTML based apps to run faster in the production environment. These refers to tools which can help us minify or obfuscate javascript, css and even HTML files. There are other tools which can concatenate images into large images and modify the css accordingly.

Popular tools here are

  1. jsmin
  2. uglify
  3. yui compressors
  4. etc many others

Typically most of these tools are now available as plugin to Grunt

Class System

JavaScript is a flexible language. Infact it is so flexible it allows you to write class in many manners. The main reason being there is nothing like a class in javascript, its a prototype based language. In this blog we will not go deep into javascript prototype (its a topic for another blog itself)

The most basic class definition can be as follows

var Employee = function(firstName, lastName){
   this.firstName = firstName;
   this.lastName = lastName;

   this.getFullName = function(){
       return this.firstName +" "+this.lastName;
   }
}

var employee = new Employee('Rohit','Ghatol');
console.log(employee.getFullName());

Another way of defining the same class could be

var Employee = function(firstName, lastName){
   this.firstName = firstName;
   this.lastName = lastName;
}
Employee.prototype.getFullName = function(){
   return this.firstName +" "+this.lastName;
}

var employee = new Employee('Rohit','Ghatol');
console.log(employee.getFullName());

The idea to behind talking about Class System is that you should be aware when you choose a profound JavaScript Library (profound meaning large enough), it is bound to have its own Class System

Backbone Class System Backbone would define its own class as follows

    Person = Backbone.Model.extend(
    { 
        defaults: { 
            name: 'Fetus', 
            age: 0, 
            child: '' 
        }, 
        initialize: function(){ 
            alert("Welcome to this world"); 
        } 
    }); 

    var person = new Person({ name: "Thomas", age: 67, child: 'Ryan'}); 
    var age = person.get("age"); // 67 
    var name = person.get("name"); // "Thomas" 
    var child = person.get("child"); // 'Ryan'

Sencha/ExtJs Class System Sencha Touch defines its classes differently

Ext.define('User', {
    extend: 'Ext.data.Model',
    config: {
        fields: [
            { name: 'id', type: 'int' },
            { name: 'name', type: 'string' }
        ]
    }
});

AMD - Asynchronous Module Definition

(Asynchronous Module Definitions)
  1. Allows creation of Modules
  2. Typically each Module has its own JS file
  3. One Module can load another, asynchronously
  4. Modules can be replaced by Mocks for Unit Testing
  5. Modules can be concatenated and Obfuscated
  6. Examples
    • RequireJS
    • CommonJS
    • ExtJS
    • etc

Lets go over AMD by looking at a  example, we will use require.js pseudo code for this

Understanding AMD by an Example

WITHOUT AMD

<head> <script src=“model.js”></script> <script src=“store.js”></script> <script src=“view.js”></script> <script src=“controller.js”></script> <script src=“app.js”></script> </head>

WITH AMD <head> <script src=“require.js” data-main=“app.js”></script> </head>

DEFINE MODEL JS

//Model.js
define(
    [],
    function(){
        return {
            "name":"Todo Model"
        };
    }
);

DEFINE STORE JS

//Store.js - with CRUD Operation
define(
    [‘Model’],
    function(model){
        return {
            “create”:function(){..},
            “retrieve”:function(){..},
            “update”:function(){..},
            “delete”:function(){..},
       };
    }
);

DEFINE VIEW JS

//View.js
define(
    [’jQuery’,’Model’,’Store'], 
    function($,model, store){
		store.update(model);

        //render 
		$(“.view”).html(…);

        return ..;
    }
) ;

DEFINE CONTROLLER JS

//Controller.js
define(
    [’jQuery’,’View’,’Store'],
    function($,view, store){
        view.setStore(store);
        $(“#placeholder”).html(view.el());
        return ..;
    }
) ;

DEFINE APP JS

//app.js
require(
    [‘jQuery’,’Controller’],
    function($,controller){
        $(“#loading”).html(“”); 	   	   
        controller.initialize();
    }
);

Writing JavaScript frameworks/libraries targeted for AMD

When Writing JS Libraries following care should be taken

  1. Your Library can be consumed by Any one
  2. That person may be using
    1. RequireJS
    2. CommonJS
    3. Directly including JS Library in HTML Page
  3. Your Library needs to be UMD
    1. It should load in all possible environments
      1. With RequireJS Module
      2. With CommonJS Module
      3. Without any Module (just by embedding javascript in page)

 Example of UMD

!function (name, definition) {
    if (typeof define == 'function' && define.amd) {
        //define module in Require JS
        define(definition);
    } else if (typeof module != 'undefined') {
        //define module in Common JS
        module.exports = definition();
    } else {
        //define module when JavaScript file is directly embedded in page
        this[name] = definition();
    }
}('MessageBus', function() {

    var MessageBus = function () {
        .......
    };

    MessageBus.prototype = {
        publish : function (channel,message){
            ......
        },
        subscribe : function (channels,callbacks){
            .....
        }
    };

    return MessageBus;
});

Router & History

Routers and History frameworks in JavaScript allow Single Page Applications to behave like any other Web Application and obey ground rules like following

  1. Obey Browser Back and Forward Buttons
  2. Allow Deep link/Book marking of state in SPA
  3. Programmatically allow manipulation of history

Example of How Routers & History Works Step 1 - User is at Ext.data.Store page in Sencha Documentation

Step 2 - User clicks the StoreManager link

Step 3 - This changes the Browser address to http://docs.sencha.com/touch/2-0/#!/api/Ext.data.StoreManager

Step 4 - The Router framework is listening to any change in URL and triggers creation of an addition Tab to show Ext.data.StoreManager's apis

Examples of Pure Router Frameworks are

  1. Sammy JS
  2. Pager
  3. Dave JS
  4. Cross Roads
  5. Path JS

Other profound frameworks like Sencha, EXTJS & Backbone have their own Routers built in

DOM Manipulation

DOM Manipulation is all about manipulating HTML DOM at runtime.

  1. Most Popular Framework - jQuery
  2. Other Frameworks
    1. ZeptoUI
    2. XUI

Apparently jQuery also provides other api apart from DOM Manipulation like Ajax API etc

MicroTemplates

A good design pattern when building UI in javascript is to keep the markup code out side the JavaScript View logic.

The idea is to have a clear separation of Concern

JavaScript View

  1. Access Model 
  2. Address UI Events

Markup Code aka Micro Template

  1. Map the Model attributes to the Markup
  2. Provide Markup with looping, conditional blocks capability

Example of Underscore Micro Template

<div id="placeholder"></div> <script type="text/javascript">

// Compile the template using underscore var tmplTxt = $("#search_template").html();

//_ stands for underscroe var template = _.template(tmplTxt, {label:"Hello World"} );

$("placeholder").html( template );

</script>

//Template put in the script tag

<script id="search_template" type="text/template"> <label><%=label%></label> <input type="text" id="search_input" /> <input type="button" id="search_button" value="Search" /> </script>

Once the MicroTemplate has run the div (placeholder) looks as follows

<div id="placeholder"> <label>Hello World</label> <input id="search_input" type="text" /> <input id="search_button" type="button" value="Search" /> </div>

Following examples of standalone Micro Template libraries

  1. underscore
  2. handlerbar
  3. moustache
  4. etc

MV * Frameworks

By MV * frameworks we mean any frameworks which approximates to any of the following design patterns

  1. Model View Controller
  2. Model View View-Model
  3. Model View Presenter (rarely seen in JavaScript but main framework for GWT)

MVC Design Pattern

 

 

Backbone is one of the popular MVC Framework, also one of the most flexible frameworks which can work with other frameworks. Backbone is really a MV* framework and not really a pure MVC framework. In Backbone the View and Controller boundaries are blurred and the View represents both. Apart from this, Backbone has Model, Collection and Routers.

Backbone MVC Code Snippets

Model

Person = Backbone.Model.extend({ 
    initialize: function(){ 
        alert("Welcome to this world"); 
    } 
}); 
var person = new Person({ name: "Thomas", age: 67});

View & Controller in View itself

SearchView = Backbone.View.extend({ 

    initialize: function(){       
        this.render();
    },
    render:function(){
        this.$el.html("<button id="button">Click Me</button>");
    }
    events: { 
        "click #button": "clickMe" 
    }, 
    clickMe: function( event ){ 
         alert("You clicked me"); 
    } 
}); 

// The initialize function is always called when instantiating a Backbone View. 
// Consider it the constructor of the class. 

var search_view = new SearchView($("#placeholder"));

In Backbone the View and Controller are combined into One. In the above code initialize() and render() method are View concept, and event object and clickMe() method are Controller concept.

Other Popular JavaScript MVC Frameworks are

  1. Angular Js
  2. ExtJS, Sencha Touch
  3. Ember JS
  4. Kendo UI
  5. etc

MV VM Design Pattern

 

 

MV VM framework is about View and View Model living in pair and View Model adapting the Model (Domain Model) for the View

HTML Markup aka View

<p>First name: <strong >todo</strong data-bind="text:firstName" ></p> <p>Last name: <strong>todo</strong data-bind="text:lastName" ></p>

JavaScript Code

function AppViewModel() {
    this.firstName = ko.observable("Rohit");
    this.lastName = ko.observable("Ghatol");
}

// Activates knockout.js
ko.applyBindings(new AppViewModel());

Output HTML Markup <p>First name: <strong >todo</strong data-bind="text:firstName" >Rohit</p> <p>Last name: <strong>todo</strong data-bind="text:lastName" >Ghatol</p>

 


MVP Design Pattern

 

 

 

Like I mentioned before MVP is Design Pattern worth knowing, but it is not popular in JavaScript world. However it is the official Design pattern for GWT (Google Web Toolkit)

.

.

.

Data bound Views

Data bound Views are views which take their data from a predefined data source. e.g GridView which talk to a Data Store which in turn reads out data from either a AJAX Source or Local Storage etc.

Following is how Sencha's Data Bound Views work

Following Libraries have Data Bound Views and Widgets (Views) in them

  1. ExtJs or Sencha Touch
  2. Backbone Js

 

Large Scale Application Frameworks

Design Patterns get us only so far when building Large Scale Applications. To really work on a Large Scale Application, we need an Architecture for it.

Aura Js is an upcoming popular Large Scale Application framework. It is based on the following design

[singlepic id=45 w=320 h=240 float=]

Aura Provides following

  1. A Framework to abstract out 
    1. DOM Manipulation Frameworks
    2. MV* Frameworks
    3. Any framework your application depends on
  2. Aura Core is an extensible Core, User Extensions can be added to it to expand its capability
  3. Out of the box Aura Core comes with
    1. DOM Manipulation APIs under the hood calling jQuery. This can be switch to Zepto or any other
    2. MVC APIs which under the hood call BackBone
  4. Anything like a Logging or Authentication or Ajax APIs which the product needs should be added to Aura as Extensions
  5. Widgets are Views (out of box uses BackBone) which are running in Aura Sandbox
  6. Extensions can be used to provide Widgets additional APIs vai the Sandbox
  7. Widgets communicate to other Widgets only through the Sandbox
  8. Widgets do not access DOM, Ajax or anything directly but uses Sandbox for everything

Code Snippet

Aura BootStrap Code

require(['aura/aura'], function (Aura) {
    var app = new Aura();

    app.use('extensions/storage');
    app.start({ widgets: 'body' });
});

Extension

define(['underscore'], function (_) {
    var app;
    var todos = [];

    function createNewTask(data) {
        var task = _.extend(data, {id: _.uniqueId('task')});
        todos.push(task);

        app.sandbox.emit('storage/newTaskCreated', task);
    }

    function toggleTask(data) {
        var task = _.find(todos, function(task) {
            return task.id === data.id;
        })
        var completed = task.completed || false;
        task.completed = !completed;

        app.sandbox.emit('storage/taskToggled', task);
    }

    function deleteTask(data) {
        todos = _.reject(todos, function (task) {
            return task.id === data.id;
        });

        app.sandbox.emit('storage/taskDeleted');
    }

    function editTask(data) {
        var task = _.find(todos, function(task) {
            return task.id === data.id;
        })
        task.description = data.description;

        app.sandbox.emit('storage/taskEdited');
    }

    return {
        initialize: function (application) {
            app = application;
            app.sandbox.on('ui/createNewTask', createNewTask);
            app.sandbox.on('ui/toggleTask', toggleTask);
            app.sandbox.on('ui/deleteTask', deleteTask);
            app.sandbox.on('ui/editTask', editTask);
        }
    };

});

Widet Code

define(['underscore'], function (_) {

    return {
        template: 
            '<header id="header">\
                <h1>todos</h1>\
                <input id="new-todo" placeholder="What needs to be done?" autofocus>\
            </header>',

        initialize: function () {
            _.bindAll(this);

            this.render();
            this.cacheElements();
            this.attachEvents();
        },

        render: function () {
            this.$el.html(this.template);
        },

        cacheElements: function () {
            this.$newTodo = this.$el.find('#new-todo');
        },

        attachEvents: function () {
            this.$el.find('#new-todo').on('keyup', this.createNewTask);
        },

        createNewTask: function(e) {
            if (e.which === 13) {
                var val = this.$newTodo.val();
                this.sandbox.emit('ui/createNewTask', {description: val});
                this.$newTodo.val('');
            }
        }
    };

});

Refer to Aura Todo MVC Example

Responsive UI

Response UI can mean number of things. However in the HTML5 world it means following

  1. SPA are responsive to any form factor and device
  2. Pages adapt to different Screen Sizes

This is best explained as an example

Look at the Screen shot below. This is how a responsive website looks on Desktop

[singlepic id=46 w=320 h=240 float=]

The same site adopts to the mobile browser as below. Notice the change in how menus are shown

[singlepic id=47 w=320 h=240 float=]

Further more see how Menus are loaded on mobile browser

[singlepic id=48 w=320 h=240 float=]

The two most popular Responsive UI framework out there are

  1. Twitter Bootstrap
  2. Zurb Foundation

Responsive UI frameworks are hard to define. They are really mix of

  1. Elaborate Grid System and CSS which make heavy use of Media Queries.
  2. Grid System is a way of saying that we will put the UI components across say 12 Columns in a Grid. Depending in the Screen size the Columns will stay intact or convert to Row as part of Responsive UI
  3. Media Queries are CSS snippets which apply themselves or remove themselves depending on Screen size. This how the above example worked. 
  4. CSS Styling for Tabs, Buttons, Section, Bread Crumbs etc
  5. JavaScript APIs for Tabs, Buttons, Sections etc
  6. Ready to use Conversional Look and Feel, so you don't need a Designer to launch your work

The best part of Responsive UI is that they can be applied independently of MV* Framework. Also Responsive UI are tools for doing Quick Mockups.

 

Widget Set

Widget Sets are referred to as Framework which provide Richer Widgets. There are pure widget set frameworks and other more profound javascript framework where widget set is one of the many part

One of the popular Pure Widget Set framework is jQuery UI.

[singlepic id=49 w=320 h=240 float=]

Other more popular and profound Frameworks with Richer Widget Sets are

  1. Sencha Touch/ExtJs
  2. Kendo UI
  3. etc

[singlepic id=51 w=320 h=240 float=]

[singlepic id=50 w=320 h=240 float=]

HTML5 Features

HTML5 Features are provided by the browser. However there are issues with cross browser compatibility.  Some browsers are better than others in supporting HTML5 Features.

A SPA Product needs to work on all sorts of Browsers. It needs to leverage features where they are available out of the box, and it needs to either simulate features or do a graceful fallback when the features are not available out of the box.

HTML5 SPA Product development needs two things

  1. Design Time Information to make critical decisions. What features to incorporate and what to let go.
  2. Runtime Libraries to detect HTML 5 Features, Simulate or do graceful fallback

Design Time Tools

Design time tools are for making decisions on which HTML 5 Feature to go with depending on the browser support available.

One of my favorite tool for this is http://html5please.com. Only only does it tell whether a feature is safe to use on all modern available browser, but it also recommends polyfills if required. It also cautions about a feature if polyfills are missing or major browser (e.g IE 10) is not supporting the feature

[singlepic id=52 w=500 h=350 float=]

Apart from this one there are the following

  1. http://caniuse.com
  2. http://html5test.com

Run Time Tools

Runtime tools in HTML5 are of 2 types

  1. Feature Detection and Fallback Mechanims
  2. Polyfills

Feature Detection and Fallback Mechanism

Modernizr is a popular JavaScript library which can provide details like which HTML5 Features are supported by the browser running it.

Modernizr.load({
  test: Modernizr.geolocation,
  yep : 'geo.js',
  nope: 'geo-polyfill.js'
});

In the above code we are testing if geolocation feature is available on the browser, if so use the geo.js javascript file, and if not then fallback using geo-polyfill.js. PolyFills

Polyfills are mechanisms to provide to a missing HTML5 Feature. e.g In IE6, there is no support for Canvas, we can add this support by using the ExCanvas Polyfill, which uses flash internally to do rendering, but adheres to the same canvas apis.

There are many polyfills out there. However using Polyfills can degrade performance (as these are not provided by browsers, but are software simulated). Here are few examples

  1. SVG Web - http://code.google.com/p/svgweb/
  2. ExCanvas - http://code.google.com/p/explorercanvas/
  3. Storage Polyfill - http://www.calormen.com/polyfill/#storage
  4. HTML5 Shiv - http://github.com/afarkas/html5shiv
  5. HTML5 Media - http://github.com/etianen/html5media
  6. Event Source - https://github.com/remy/polyfills/blob/master/EventSource.js

Visit this github repository to find all popular polyfills.

 

3D/2D Graphics/Visualization

3D and 2D Visualization even though part of HTML5 feature set , require special attention.

WebGL forms the basis for 3D Visualization and Canvas/SVG form the basic for 2D Visualization/Charts and Graphs

WebGL

Programming in WebGL is tough and unproductive. Abstraction level frameworks are required to ease programming effort when working with WebGL.

Popular 3D Libraries are

  1. Three.js
  2. X3DOM
  3. Scene.js
  4. etc

Three.js Demo

X3DOM Demo

 

Charts/Graphs

Charts and Graphs can be created in HTML5 using any of the following technologies

  1. Canvas
  2. SVG
  3. VML
  4. Divs

Charts and Visualizations libraries can be categorized roughly into two

  1. Actual Charts/Graphs Libraries
    1. High Charts
    2. JS Charts
    3. Plot Kits
    4. Google Visualizations
  2. Advanced more Generic Visualization Libraries
    1. D3JS

The key difference is D3JS is more generic and more power visualization framework. It should be used when more complex visualizations are required which are not available out of the box.

Like the following Back to Back Bar Chart.

 

[iajsfiddle fiddle="DWJ35" height="500px" width="100%" show="result,js" skin="default"]