Wednesday, January 4, 2017

backbone.js first steps

1. Intro

Official web-page: http://backbonejs.org/

From wiki:
Backbone.js is a JavaScript framework with a RESTful JSON interface and is based on the model–view–presenter (MVP) application design paradigm. Backbone is known for being lightweight, as its only hard dependency is on one JavaScript library,[2] Underscore.js, plus jQuery for use of the full library.[3] It is designed for developing single-page web applications,[4] and for keeping various parts of web applications (e.g. multiple clients and the server) synchronized.[5] Backbone was created by Jeremy Ashkenas,[6] who is also known for CoffeeScript and Underscore.js.[7]


I don't know why but most popalar application for first BackBone project is Todo list. So lets's create it. For storing entered data we will be using "local storage".

2. Test application structure

BackBone application contains next parts:
1. Models - structure for entity-data. In our application we have only one model - for Todo entity with properties "title" and "completed".

2. Collections - structures for operating lists(arrays) of  Models. We will have only one collection: Todo collection.

3. Views - structures responsible for user interface and user interaction. We will have 2 views: TodoView - for just Todo itself and AppView - for combining all TodoViews into one list.



Also, we need some common for all web application stuff like:
4. html file
5. css file

3. Model

Our model is very simple, just 2 properties and one function:

app.Todo = Backbone.Model.extend({
  defaults: {
    title: '',
    completed: false  },
  toggle: function(){
    this.save({ completed: !this.get('completed')});
  }
});


4. Collection

we are using local storage for our collection, and it will use our model: 

app.TodoList = Backbone.Collection.extend({
  model: app.Todo,
  localStorage: new Store("backbone-todo")
});


5. TodoView

Views are much more complicated structures:) This view is responsible for displaying just one Todo item - one Todo model.

In this view we are defining:
- TagName - element which will be create "outside" view: view will be inside "<li>" element
- template - we can "hardcode" creation of all html elements needed for view in render function, but of course it's better to use template.
- render  - function which will be called to display view
- initialize - function which will be called once at the beginning for initialization
- events - we can subscribe for some event which can triggered by user. Format is "EVENT ELEMENT:FUNCTION_TO_CALL". For example for 'click .save-btn' : 'close'  : when user clicked element with css class ".save-btn" - we have to execute function "close".
- model events - also we can subscribe on some events from our model. By "this.model.on('change', this.render, this);" - we are subscribing to run "render()" function every time our model change.
- other functions - of course if we need we can add additional functions to view, like in this example  we defined edit, cancel, close, toggleCompleted, destroy functions

app.TodoView = Backbone.View.extend({
  tagName: 'tr',
  template: _.template($('#item-template').html()),
  render: function(){
    this.$el.html(this.template(this.model.toJSON()));
    this.input = this.$('.edit');
    return this; // enable chained calls  },
  initialize: function(){
    this.model.on('change', this.render, this);
    this.model.on('destroy', this.remove, this);
  },      
  events: {
    'click .save-btn' : 'close',
    'click .cancel-btn' : 'cancel',
    'click .toggle': 'toggleCompleted',
    'click .remove-btn': 'destroy',
    'click .edit-btn': 'edit'  },
  edit: function(){
    this.$el.addClass('editing');
    this.input.focus();
  },
  cancel: function(){
    this.$el.removeClass('editing');
  },
  close: function(){
    var value = this.input.val().trim();
    if(value) {
      this.model.save({title: value});
    }
    this.$el.removeClass('editing');
  },
  toggleCompleted: function(){
    this.model.toggle();
  },
  destroy: function(){
    this.model.destroy();
  }      
});

6. AppView

This view is responsible for combining all TodoViews into one list.
Instead of "tagName" we use another property "el" - that mean our view will be showed inside this element. In this example - inside "#todoapp" element. Other elements are similar to previous view.

app.AppView = Backbone.View.extend({
  el: '#todoapp',
  initialize: function () {
    this.input = this.$('#new-todo');
    app.todoList.on('add', this.addAll, this);
    app.todoList.on('reset', this.addAll, this);
    app.todoList.fetch(); // Loads list from local storage  },
  events: {
    'click #add-btn': 'btnAddClick',
  },
  btnAddClick: function(e){
    app.todoList.create(
        {
          title: this.input.val().trim(),
          completed: false        }
    );
    this.input.val(''); // clean input box  },
  addOne: function(todo){
    var view = new app.TodoView({model: todo});
    $('#todo-list').append(view.render().el);
  },
  addAll: function(){
    this.$('#todo-list').html(''); // clean the todo list    app.todoList.each(this.addOne, this);
  }
});

7. Main js file

All our logic are in views, so main application file is very short:
app.todoList = new app.TodoList();
appView = new app.AppView(); 


8. Main css file 

We need to hide and show elements depending on current mode:
- in "view" mode buttons "save" and "cancel" have to hidden. In contrary, buttons "edit" and "remove" have to be visible
-  and visewersa, in "edit" mode buttons "edit" and "remove" have to hidden. But, buttons "save" and "cancel" have to be visible.

   #todoapp ul {
     list-style-type: none;
   }
   #todo-list input.edit {
     display: none;
   }

   #todo-list button.edit-btn {
       display: inline;
   }


   #todo-list button.save-btn {
       display: none;
   }

   #todo-list button.cancel-btn {
       display: none;
   }


/* editing  */
   #todo-list .editing label {
       display: none;
   }
   #todo-list .editing input.edit {
       display: inline;
   }

   #todo-list .editing button.save-btn {
       display: inline;
   }

   #todo-list .editing button.edit-btn {
       display: none;
   }

   #todo-list .editing button.cancel-btn {
       display: inline;
   }

   #todo-list .editing button.remove-btn {
       display: none; 
   }

9. Main Html file. 

In main HTML file we have to define:
- placeholder for our main view: table with id "todo-list".
- template for todo view
- all needed libraries

<!DOCTYPE html>
<html>
<head>
    <title>Simple Backbone example</title>
    <link rel="stylesheet" type="text/css" href="css/main.css"/>
</head>
<body>
<section id="todoapp">
    <header id="header">
        <h1>New TODO</h1>
        <input id="new-todo" placeholder="Enter new TODO here" autofocus>
        <button id="add-btn">add</button>
    </header>
    <section id="main">
        <h1>List of TODOs:</h1>
        <table id="todo-list" border="1"></table>
    </section>
</section>

<!-- Templates --><script type="text/template" id="item-template">
    <div class="view">
        <td>
            <input class="toggle" type="checkbox" <%= completed ? 'checked' : '' %>>
        </td>
        <td>
            <label><%- title %></label>
            <input class="edit" value="<%- title %>">
        </td>
        <td>
            <button class="edit-btn">edit</button>
            <button class="save-btn">save</button>
        </td>
        <td>
            <button class="remove-btn">remove</button>
            <button class="cancel-btn">cancel</button>
        </td>
    </div>
</script>

<!-- ========= --><!-- Libraries --><!-- ========= --><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min.js"        type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js" type="text/javascript"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone-localstorage.js/1.0/backbone.localStorage-min.js"        type="text/javascript"></script>

<!-- =============== --><!-- Javascript code --><!-- =============== --><script type="text/javascript">
    'use strict';

    var app = {}; // create namespace for our app</script>

<script src="js/models/Todo.js" type="text/javascript"></script>
<script src="js/collections/TodoList.js" type="text/javascript"></script>
<script src="js/views/TodoView.js" type="text/javascript"></script>
<script src="js/views/AppView.js" type="text/javascript"></script>

<script src="js/app.js" type="text/javascript"></script>


</body>
</html>



10. How it works

Everything works pretty good. We can add new todos, edit existing or delete them:



Thursday, November 3, 2016

require.js first steps

Very often, we have to split a solid application to the set of simple modules. And of course, such modules can have dependencies. In such situations we have to manage dependencies somehow. For example we can have module A which is using modules B and C. And module B use modules D and E. So we have to load this modules in order:
  <script src="js/E.js"></script>
  <script src="js/D.js"></script>
  <script src="js/B.js"></script>
  <script src="js/C.js"></script>
  <script src="js/A.js"></script>

RequireJS - one of the tools for managing such situations. Using is we will have just to load main file and requirejs itself:
<script data-main="js/A"  src="http://requirejs.org/docs/release/2.3.2/comments/require.js"></script>


Let's create a simple application without require.js and after that let's re-write it with it.
In our application we will have 2 entities: User and Department. 2 tools: Validator and Logger. And main file which is using them all.

1. Without require.js. 

We are just creating separate js files and after all w will have to list them in proper order in html file.

1.1 User object 

function User(id, name) {
  this.id=id;
  this.name=name;
  this.toString = function() {
     return name;
  }
}


1.2 Department object

function Department(id, name) {
 this.users=[];
 this.id=id;
 this.name=name;

 this.addUser = function(user) {
   this.users.push(user);
 };

 this.getUsers = function() {
   return this.users;
 };
 
}


1.3 Validator object 

function hasAttribute(object, attribute) {
   return object.hasOwnProperty(attribute);
}

function isValid(object) {
  return hasAttribute(object, "name") && hasAttribute(object, "id");
}



1.4 Logger

function idNameFormat(object) {
  return "["+object.id+"]"+object.name;
}

function logUser(user) {
  console.log("user:"+idNameFormat(user));
}

function logDepartment(department) {
  console.log("department:"+idNameFormat(department)+" users:"+department.getUsers().toString());
}


1.5. Main script

We are just creating several objects, validating them and printing them using logger. 

function run() {
   var user1=new User(1, "Joe");
   var user2=new User(2, "Black");

   var dep1=new Department(1, "IT");
   dep1.addUser(user1);
   dep1.addUser(user2);

   if (isValid(user1) && isValid(user2) && isValid(dep1)) {
      logUser(user1);
      logUser(user2);
      logDepartment(dep1);
   } else {
      console.log("errors in validation");
   }
   
}

1.6 HTML file 

All our modules has to be listed in a proper order otherwise our application will not work.

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
</head>

<body>

  <script src="js/validator.js"></script>
  <script src="js/user.js"></script>
  <script src="js/department.js"></script>
  <script src="js/logger.js"></script>
  <script src="js/main.js"></script>
  
  <script>
    run();
  </script>
</body>

</html>


2. Now let's rewrite application using require.js

2.1. User

We are defining User function and returning it.

define(function () {

    function User(id, name) {
        this.id = id;
        this.name = name;

        this.toString = function () {
            return this.name;
        };
    }

    return User;
});


2.2. Department

The same as with User.

define(function () {

    function Department(id, name) {
        this.users = [];
        this.id = id;
        this.name = name;

        this.addUser = function (user) {
            this.users.push(user);
        };

        this.getUsers = function () {
            return this.users;
        };
    }

    return Department;

});

2.3 Validator

Here we have private method "hasAttribute" and public method "isValid".

define(function () {

    function hasAttribute(object, attribute) {
        return object.hasOwnProperty(attribute);
    }

    return {
        isValid: function (object) {
            return hasAttribute(object, "name") && hasAttribute(object, "id");
        }
    }

});


2.4 Logger

Here we also have private method and 2 public methods.

define(function () {
        function idNameFormat(object) {
            return "[" + object.id + "]" + object.name;
        }

        return {
            logUser: function (user) {
                console.log("user:" + idNameFormat(user));

            },
            logDepartment: function (department) {
                console.log("department:" + idNameFormat(department) + ". users:" + department.getUsers().toString());
            }
        }
    }
);


2.5 Main

Here we have most interesting thing: we are getting dependencies using require.js

require(["user", "department", "logger", "validator"], function (User, Department, Logger, Validator) {
    console.log("Hello world!");

    var user1 = new User(1, "Joe");
    var user2 = new User(2, "Black");

    var dep1 = new Department(1, "IT");
    dep1.addUser(user1);
    dep1.addUser(user2);

    if (Validator.isValid(user1) && Validator.isValid(user2) && Validator.isValid(dep1)) {
        Logger.logUser(user1);
        Logger.logUser(user2);
        Logger.logDepartment(dep1);
    } else {
        console.log("errors in validation");
    }


});


2.6. HTML file

Here we just have to point to our main file ("js/main.js"  - file ending ".js" can be omitted) and path to require.js(url).


<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
</head>

<body>

  <script data-main="js/main"  src="http://requirejs.org/docs/release/2.3.2/comments/require.js"></script>

</body>

</html>

3.  Execution.


logger.js:8 user:[1]Joe
logger.js:8 user:[2]Black
logger.js:12 department:[1]IT. users:Joe,Black

4. The end. 

Development with  RequireJS makes part of application modular and reusable.

Tuesday, September 13, 2016

JavaScript functional and prototype inheritance

In JavaScript there are 2 options for class  inheritance: functional(regular - well known by other OO languages) and prototype(own style based on "cloning").

1. Preparation 


First of all we need several files:- html file for displaying test results: test.html- our script file with algorythm implementation: MyScript.js- file with test scripts for previous step: MyScriptTest.js- libraries mocha.js and chai.js - they will be used as external scripts.All this files I put to one directory. Here is the content of test result file: test.html:



<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">

  <!-- Mocha css -->  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.1.0/mocha.css">
  <!-- Mocha dependency -->  <script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.1.0/mocha.js"></script>
  <!-- Mocha: setup BDD -->  <script> mocha.setup('bdd'); </script>
  <!-- chai dependency -->  <script src="https://cdnjs.cloudflare.com/ajax/libs/chai/2.0.0/chai.js"></script>
  <!-- export assert -->  <script>  var assert = chai.assert;  </script>
</head>

<body>
  <!-- script which should be tested -->  <script src="MyScript.js"></script>
  <!-- test itself -->  <script src="MyScriptTest.js"></script>
  <!-- element with id="mocha" for test results -->  <div id="mocha"></div>
  <!-- run tests! -->  <script>
    mocha.run();
  </script>
</body>
</html>

As you can see, mocha and chai libraries will be downloaded by SRIPT tag. Also we set up mocha for using BDD, exported "assert" for simple usage and executed mocha test running.
In addition, we need just 2 files:
<!-- script which should be tested --><script src="MyScript.js"></script>
<!-- test itself --><script src="MyScriptTest.js"></script>

- we will be creating them step-by-step during implementation. First - function for MyScript, next - testblock for that function in MyScriptTest.js.

2. Functional inheritance

Let's create a regular class:

function FuncPoint(x, y) {
    var _x = x, _y = y, self = this;

    self.getX = function () {
        return _x;
    };
    self.getY = function () {
        return _y;
    };
    self.toString = function () {
        return "[" + _x + "," + _y + "]";
    };
    return self;
}

- it has 2 private variables: _x and _y, we also created just "getters"(getX and getY) for this variables - so our class in "immutable": we can not change it after creation. Beside the we added "toString" method for printing our object in "user friendly" style.

Let's test it:
it("should be getX, getY, toString functions in FuncPoint class", function () {
    var p = new FuncPoint(1, 2);
    assert.equal(p.getX(), 1);
    assert.equal(p.getY(), 2);
    assert.equal(p.toString(), "[1,2]");
});


2.1 Child class in functional inheritance style. 

Now let's imagine, we have to extend our class for adding more(we want to add information about color to our point) functionality:

function FuncColoredPoint(x, y, color) {
    FuncPoint.call(this, x, y);
    var _color = color, self = this;

    self.getColor = function () {
        return _color;
    };

    var parentToString = self.toString;
    self.toString = function () {
        return parentToString() + "#" + _color;
    };

    return self;
}

Everything looks more or less similar to what we have in other OO languages:
- we can  to call "parent" constructor : FuncPoint.call(this, x, y);
so, no needs to create own variables _x and _y - the will be "inherited" from parent(FuncPoint) class.
- we can add additional properties(color) and methods(getColor)
- we can "override" methods by just defining the method with the same name:  self.toString = function () {....} and if we want to use "parent" function in "overriding" we can "copy" it to another variable(var parentToString = self.toString;) and use from it:  return parentToString() + "#" + _color;

Test:
it("should inherited getX and getY functions beside own function getColor and overriden function toString in FuncColoredPoint class", function () {
    var p = new FuncColoredPoint(2, 3, "RED");
    assert.equal(p.getX(), 2);
    assert.equal(p.getY(), 3);
    assert.equal(p.getColor(), "RED");
    assert.equal(p.toString(), "[2,3]#RED");
});

Everything is working, functional inheritance is clear and simple for understanding.

3. Prototype inheritance

Every JavaScript object has a prototype. The prototype is also an object.
All JavaScript objects inherit their properties and methods from their prototype. 
All JavaScript objects inherit the properties and methods from their prototype.
Objects created using an object literal, or with new Object(), inherit from a prototype called Object.prototype.

Concept of "class" is absent in JavaScript, there are just "objects" which are created by functions. So when we are creating object by new.... operator we are creating object by "prototype".

For example, we have regular function which creates object:
function ProtoPoint(x, y) {
    this.x = x;
    this.y = y;
}

When we creating object "p = new ProtoPoint" - we are creating object with property "__proto__" which is our case was inherited from Object.prototype property:
  1. ProtoPoint {x1y2}
    1. x:1
    2. y:2
    3. __proto__:Object

there are a lot of interesting things inside it:
  1. ProtoPoint {x1y2}
    1. x:1
    2. y:2
    3. __proto__:Object
      1. constructor:ProtoPoint(x, y)

      2. __proto__:Object
        1. __defineGetter__:__defineGetter__()
        2. __defineSetter__:__defineSetter__()
        3. __lookupGetter__:__lookupGetter__()
        4. __lookupSetter__:__lookupSetter__()
        5. constructor:Object()
        6. hasOwnProperty:hasOwnProperty()
        7. isPrototypeOf:isPrototypeOf()
        8. propertyIsEnumerable:propertyIsEnumerable()
        9. toLocaleString:toLocaleString()
        10. toString:toString()
        11. valueOf:valueOf()
        12. get __proto__:__proto__()
        13. set __proto__:__proto__()

For example we have a methods which were inherited from Object class like "hasOwnProperty" "toString" and others.

3.1 Adding methods to prototype.

"__proto__" is just a property, so we can add to it methods:
ProtoPoint.prototype.getX = function () {
    return this.x;
};

ProtoPoint.prototype.getY = function () {
    return this.y;
};

ProtoPoint.prototype.toString = function () {
    return "[" + this.x + "," + this.y + "]";
};

- it's just another option of defining object methods.

Test:
it("should getX, getY, toString functions added to PROTOTYPE", function () {
    var p = new ProtoPoint(4, 5);
    assert.equal(p.getX(), 4);
    assert.equal(p.getY(), 5);
    assert.equal(p.toString(), "[4,5]");
});

Everything is working just like methods were defined inside function "ProtoPoint". But where is one not very good thing here: our variables x and y are visible outside and we can't make them private:

it("should be visible outside local variable - we can't make them private :(", function () {
    var p = new ProtoPoint(6, 7);
    assert.equal(p.x, 6);
    assert.equal(p.y, 7);
});


3.2 Prototype inheritance. 

For prototype inheritance we can just create independent standalone class, and ones we decided to make it "inherited" from another - we can just change it __proto__ object:

function ProtoColoredPoint(x, y, color) {
    ProtoPoint.call(this, x, y);
    this.color = color;
}

ProtoColoredPoint.prototype = Object.create(ProtoPoint.prototype);

ProtoColoredPoint.prototype.getColor = function () {
    return this.color;
};

ProtoColoredPoint.prototype.toString = function () {
    return ProtoPoint.prototype.toString.call(this) + "#" + this.color;
};

For calling "parent" functions on overriding we can use ProtoPoint.prototype.PARENT_FUNCTION.call


Let's test it:
it("should be class ProtoColoredPoint with inherited methods form ProtoPoint", function () {
    var p = new ProtoColoredPoint(8, 9, "BLACK");
    assert.equal(p.getX(), 8);
    assert.equal(p.getY(), 9);
    assert.equal(p.getColor(), "BLACK");
    assert.equal(p.toString(), "[8,9]#BLACK");
});

4. The end.

Source code can be downloaded from here