D a m o . j s     User Guide

Howto
Syntax & Coding
Basics
Get Started
The damo object
The datamodel
Routing
Page controllers
Damo config
Two-way data binding
Display the datamodel
Conditions
Loop
Trigger
Filters
Directives
Languages
Script :
Html Templates :

Howto

Basics

The idea of Damo is : the properties of a json data model shall have a direct conterpart into the HTML template, both related by a two-way data binding. Consequently all the data used inside the application shall be defined as a part of the application json datamodel.

For instance the following datamodel

//JSON applicative data model
{
  "books" : [
    {
      "buyers" : [
        {
          "name" : "Albert"
        },
      ]
    }
  ]
}

will instanciate the object damo.dm, and will relate to the DOM tag :

    <tagName damo-id="books[0].buyer[0].name">...</tagName>
In this last tag, the attribute damo-id explains to damo that the value of the tag shall be related to the value of the datamodel element books[0].buyer[0].name, in a two-way data binding fashion. A change of the value of books[0].buyer[0].name on the DOM will automatically change its value in the datamodel of the javascript code.

For those who are familiar with Angular.js, and its way to tag the DOM, the way Damo does things is pretty similar, but simpler. For instance the tag attributes will be damo-if, damo-filter, damo-loop, damo-trigger, .... Damo is designed to be much simpler and open than Angular, the integration of external libraries being very easy.

Damo is thought for faster and simpler development, this is its aim.

Get started

Here is the simplest code that displays "Hello World" :

<!DOCTYPE html>
<html>
  <head>
    <title>Damo Hello World</title>
    <meta charset="utf-8">    
    <script src="http://code.jquery.com/jquery-1.10.2.js"></script>
    <script src="damo.min.js"></script>
    <script>
      damo.dm.myText = "Hello World !";
    </script>    
  </head>
  <body>
    <div damo-id="myText"></div>
  </body>
</html>

However this example does not display all the possibilities of Damo, so we propose to explain Damo by using the elementary application damoSeed (that you can download here). This is a good idea to start any Damo development from this seed.
Here is the content of the seed :

The damo object

damo is an object with different properties :

var damo = {
  dm        : {},
  fn        : {},
  routing   : {},
  directive : {},
  filter    : {},
  method    : {},
  config    : {}
};

The datamodel

The datamodel is a JSON file located in data/datamodel.json. Here is a typical datamodel :

{
  "user" : {
    "firstName" : "John",
    "lastName"  : "Doe",
    "email"     : "john@doe.com",
    "tel"       : "0123456789",
    "address"   : "36 Baker Street, NY, USA",
    "avis"      : "",
    "shoppingCart" : {
      "list" : [
        {
          "name"  : "Bread",
          "price" : 1.49
        },
        {
          "name"  : "Fruits",
          "price" : 3.30
        },
        {
          "name"  : "Salad",
          "price" : 0.95
        },
        {
          "name"  : "Rice",
          "price" : 2.18
        }
      ],
      "total" : 0.0
    }
  }
}

A datamodel is a JSON tree that shall describe the entire hierachy of the informations used by the application. There is only one datamodel, and every data must have a precise place in the json tree. At start the object damo.dm is loaded with the data found in the file data/datamodel.json. So with the above example, the variable damo.dm.user.shoppingCart[2].name for instance has the value "salad" and is available in all the controllers of the application.

Routing

The routing is described in the file js/routing.js. Here is a typical routing file :

damo.routing = {
  home : {
    url        : 'home',
    template   : 'index.html',
    controller : 'controller_home',
    needLogin  : false
  },
  page1 : {
    url        : 'page1',
    template   : 'templates/page1.html',
    controller : 'controller_page1',
    needLogin  : false
  },
  page2 : {
    url        : 'page2',
    template   : 'templates/page2.html',
    controller : 'controller_page2',
    needLogin  : false
  }
}

A routing item has 4 properties :

Page controllers

The controller of each page is usually described in the file js/controller.js, but it could be any other file. Here is a typical file :

function controller_home() {
	console.log('in controller_home');
	damo.dm.captainAge = calculateAgeOfCaptain();
}
function controller_page1() {
	console.log('in controller_page1');
}
function controller_page2() {
	console.log('in controller_page2');	
}
function controller_shopCart() {
	console.log('in controller_shopCart');	
	var total = 0.0;
	var arr   = damo.dm.user.shoppingCart.list;
	for(var i=0;i<arr.length;i++) {
		total += arr[i].price;
	}
	damo.dm.user.shoppingCart.total=total+' €';
}

All damo is accessible in all the the controllers, so damo.dm, damo.fn, damo.filters, damo.routing, .... If a value is changed inside damo.dm, it is automatically changed for the whole application, so all the controllers.

Damo config

here is the definition of the config property of damo :

config    : {
    /**
     * @property {integer} securityBreak
     * @type integer
     * @extends damo.config
     * @description
     * Damo uses some "while true" loops. This property ensures that
     * these loops can not get out of control. All these kind of
     * loops will break after securityBreak iteretions, if not
     * broken before.
     * 
     */
    securityBreak   : 10,
    /**
     * @property {integer} switchPageDelay
     * @type milliseconds
     * @extends damo.config
     * @description
     * This parameter set the delay that damo will apply to animate
     * a page change.
     * 
     */
    switchPageDelay : 300,
    /**
     * @property {integer} showHideDelay
     * @type milliseconds
     * @extends damo.config
     * @description
     * This parameter set the delay that damo will apply to animate
     * the show/hide of an HTML element.
     * 
     */
    showHideDelay   : 200
}

damo.config.switchPageDelay and damo.config.showHideDelay can be setup to animate more or less smoothly the application behavior.

Two-way data binding

The elements of the DOM are related to the datamodel damo.dm by the tag attribute damo-id. For instance the following input will display the value of damo.dm.user.firstName :

	<input type="text" damo-id="user.firstName">

If the value of this input is changed by the user, it is automatically changed also in the datamodel damo.dm.

However if a value of the datamodel is changed inside a javascript controller, the coder shall use damoRefresh(); to propagate the change to the DOM.

Display the data model

The tags of the html template are connected to the applicative data model, and the variables of the scope, by their attribute damo-id. All tags having this attribute will be watch for the two-way data binding, others will be ignored.

<tagName damo-id="dataModelPropertyName">

In these expressions dataModelPropertyName is of type : books[4].buyer[6].price and is the counterpart of the property damo.dm.books[4].buyer[6].price of the datamodel.

Conditions

The display of an HTML element might be conditional, depending on a scope variable, function or a data model variable. The syntax to use is the following :

<tagName damo-if="condition">...</tagName>

The evaluation is made on the truth of the condition. This last may be the result of a function, an expression using ! == != < <= > >= ==, or the simple presence of a datamodel variable damo.dm.myVariable. Some examples :

//corresponding to what the function damo.fn.myFunction() returns
<tagName damo-if="myFunction()">...</tagName>
//corresponding to $scp.myVar
<tagName damo-if="myVar">...</tagName>
<tagName damo-if="myVar >= 26">...</tagName>
<tagName damo-if="myVar != myOtherVar">...</tagName>
//corresponding to $scp.$dm.books[4].buyer[6].name
<tagName damo-if="books[4].buyer[6].name.length>20">...</tagName>
Loop

You might have lists to display, and furthermore lists with a changing length along the application, and that could be fastidious to code. Damo provides a tag attribute that will handle this kind of problem. Here is an example :

<ul>
  <li damo-loop="book in books"><span damo-id="book.name"></span></li>
</ul>

In this example the span tag will be fed with damo.dm.books[i].name. Any sort of html tag can be repeated this way.

Note that the string $index in a loop will be replaced by the current index of the loop.

Trigger

This is an equivalent of the click() function of Jquery, except that only the name of the function is needed (no parenthesis). Here is an example :

<div damo-trigger="myTriggerFunction"></div>

This syntax will trigger the function when the html tag is clicked. The function must be a property of damo.fn, i.e. damo.fn.myTriggerFunction = function() {...}

Filters

The values of the data model, and the variables of the scope, can be first filtered before being displayed. This is made this ways :

<tagName id="dataModelPropertyName" damo-filter="filterName">

However this is not possible inside an option tag, which requires only text as content, therefore in this unique case the filter must be specified like this :

<option value="whatever">{{dataModelPropertyName | filterName}}</option>

In these expressions filterName is the name of the function that will be used to filter the value, i.e. damo.filter.filterName().
The filters can only be a method of the object damo.filter, it is prferable to described it in the file js/filters.js. Here is an example of the content of such a file :

damo.filter = {
  boldify : function(str) {
    return '<b>'+str+'</b>';
  },
  setPriceInEuro : function(price) {
    return parseFloat(price).toFixed(2)+' €';
  }
}

Directives

A directive is a non standard html tag that stands for an entire template. The file js/directives.js contains the directive definitions. Here is an example of this file :

damo.directive = {
  shoppingList : {
    templateUrl : 'templates/shoppingList.html',
    controller   : 'controller_shopCart'
  },
  carousel: {
    templateUrl : 'templates/carousel.html',
  }
}

A directive is described by a template and optionnaly by a controller that controls the template's behavior. In the above example, the HTML tag <shoppingList></shoppingList> found in the DOM will be replaced by the content of the file templates/shoppingList.html.

Language

Damo comes with a language facility. The choosen language is define from the browser's language.A directive is a non standard html tag that stands for an entire template. The file js/directives.js contains the directive definitions. Here is an example of this file :

damo.directive = {
  shoppingList : {
    templateUrl : 'templates/shoppingList.html',
    controller   : 'controller_shopCart'
  },
  carousel: {
    templateUrl : 'templates/carousel.html',
  }
}

A directive is described by a template and optionnaly by a controller that controls the template's behavior. In the above example, the HTML tag <shoppingList></shoppingList> found in the DOM will be replaced by the content of the file templates/shoppingList.html.

Syntax

HTML template

Word Pattern Usage
<tagName damo-key="value">
...
</tagName>
or for option tags :
<option value="{{dataModelId}}">
  {{dataModelId}}
</option>
This is the reference format for all the Damo's Html tags. The words in italic have to be replaced by the significant words.
page
<div damo-page="page">
...
</div>
This tag is made to enclose a page of the application. The page is described in the file js/routing.html as damo.routing.page
id
<tagName damo-id="varId">
...
</tagName>
Each tag having the attribute damo-id will be watch for the two-way data binding.
filter
<tagName damo-id="varId" damo-filter="filterName">
...
</tagName>
or for option tags :
<option value="varId">
  {{varId | filterName}}
</option>
This pattern applies a filter to the concerned variable having the data model id varId, e.g. shop.books[2].promo.price.
loop
<tagName damo-loop="item in arrayName">
...
</tagName>
This pattern calls a loop based on the content of the array which name is arrayName. The tagName can be of varous type : div, td, tr, option, li, or anything else.
seed
<directiveName damo-seed="seedName">
...
</directiveName>
This pattern indicates which word will be considered as the root data of the directive (see Directives).
trigger
<tagName damo-trigger="functionName">
...
</tagName>
This pattern calls the function which name is functionName, when the concerned tagName is clicked. It is preferable to setup these functions inside the object damo.fn, i.e. damo.fn.functionName = function() {...}
lang
<tagName damo-lang="expression">
...
</tagName>
This pattern will fill the inner HTML of the tag with the value of the object damo.dm.lang.expression, defined in the file lang/browserslang.js.

Script

Pattern Usage
damoRefresh()
This function is called each time the javascript changes a value in the datamodel, and you want to display it on the DOM.
damoGo(routing.item)
This function is used to change the application page.