Ivano Malavolta
Handlebars
& Require JS
How you structure your applications
MVC framework for
giving structure
File and module loader
for code modularization
Templating engine for
separation of concerns
How you structure your applications
Roadmap
• Require JS
• Handlebars
• Conclusions
Require JS
• Why Require JS
• Using modules
• Defining modules
• Configuring Require JS
Why Require JS
We are buildingapps, not websites
We need well-specified and isolated JS files/modules
Code complexity grows as the app gets bigger
à we need some sort of #include/import/require
à ability to load nested dependencies
What we want to avoid
uncontrolled scripts
poor control flow understanding
RequireJS
RequireJS is a JavaScript file and moduleloader
Using a modular script loader like RequireJS will improve the modularity of your code
à speed in implementing changes
à better understanding of the code
Require JS allows modules to be loaded as fast as possible, even out of order, but evaluated in the
correct dependency order
Builton the Module Pattern
JavaScript file and module loader
The module pattern
A JavaScript code moduleis some JavaScript code located in a function
All of the code that runs inside the function lives in a closure, which provides:
• privacy
• state
throughoutthe lifetime of the module
Module example
Technically, it is simply a function that executes immediately
Module VS script files
A moduleis different from a traditional script file in that it defines a well-scoped object that avoids
pollutingthe global namespace à its retained objects can be deleted by the GC
VS
Require JS
• Why Require JS
• Using modules
• Defining modules
• Configuring Require JS
Using modules
main.js is the entry point of the app
The main HTML:
The main JS file:
Using modules
This function is called when all dependencies are loaded
If a required module calls define(), then this function is not
fired until its dependencies have been loaded
Required modules
References to
required modules
Require JS
• Why Require JS
• Using modules
• Defining modules
• Configuring Require JS
Module without dependencies Always one module per file
Public variables
Setup code
the simplest module can be a plain
collection of name/value pairs
module with initialization
The returned element can be any valid JS element
By convention I always return an object representing the
module
Module with dependencies
Dependency
definition
Dependent module reference
Dependent module
usage
This function is called when
zepto.js is loaded.
If zepto.js calls define(), then
this function is not fired until
also zepto’s dependencies
have loaded
Require JS under the hoods...
1. loads each dependency as a script tag, using head.appendChild() and waits for all dependencies to
load
2. computes the right order in which to call the functionsthat define the modules
3. calls the module definitionfunctions of each dependency in the right order
main.js
jQuery Backbone
SpinJS
MoviesCollection
MovieModel
MoviesView
1
2
3 4
5
67
Require JS
• Why Require JS
• Using modules
• Defining modules
• Configuring Require JS
Configuring Require JS
Require refers to a global configuration options
It allows developers to:
• set the paths to all used frameworks in one place
• use older frameworks as modules (shim)
• define configurationparams for the modules
• etc.
Configuring Require JS
Shims for older
frameworks
paths to used frameworks
Dependent module
usage
Roadmap
• Require JS
• Handlebars
• Conclusions
Handlebars
• Why Handlebars
• Handlebars basics
• Usage with Backbone and Require JS
Why Handlebars
We want to separate presentation from logic
TRANSLATE TO: we don’t want to put any HTML element into JavaScript code
separate logic from presentation
Imagine yourself trying to change how a movie should be rendered in
your app...
Handlebars
• Why Handlebars
• Handlebars basics
• Usage with Backbone and Require JS
Example of template
A Handlebars expression is
{{ something }}
Escape values
Handlebars HTML-escapes all the values returned by an {{expression}}
If you don't want Handlebars to escape a value, use the "triple-stash“ à {{{ expression }}}
Populate your template
The recurrent process of obtaining a populated template is the following:
1. create the template T with its placeholders {{ - }}
2. compile the template into a JavaScript function t
3. create a context CT containing the actual values for placeholders
4. run the compiled template t(CT) to obtain the final HTML fragment
1. create the template
Templates are defined within a <script> tag or in external files
2. compile the template
Handlebars.compile is used to compile a template
Compiling = obtaining a JS function representing the template
3. create a context for the template
A context is a JavaScript object used to populate a template
Here the keys of the object must match with the name of the placeholders to be populated
4. obtain the final HTML fragment
You have to execute a template with a context in order to get its corresponding HTML code
Expressions
The simplest expression is a simple identifier
This expression means "look up the username property in the current context"
Expressions with paths
Handlebars expressions can also be dot-separated paths
This expression means
"look up the user property in the current context,
then look up the username property of the user"
Helpers
Helpers are JavaScript functions that return HTML code
You should return a Handlebars SafeString if you don't want it to be escaped by default
Calling helpers
An Handlebars helper call is a simple identifier, followed by zero or more parameters
Each parameter is a Handlebars expression
es.
{{ test user }}
In this case, test is the name of the Handlebars helper, and user is a parameter to the helper
Built-in helpers
To iterate over a list
each
Inside the block, you can use
this
to reference the element being iterated
<ul class="people_list">
{{#each people}}
<li>{{this}}</li>
{{/each}}
</ul>
{ people: [ “Ivano", “Andrea", “Paolo" ] }
<ul class="people_list">
<li>Ivano</li>
<li>Andrea</li>
<li>Paolo</li>
</ul>
Built-in helpers
It renders the block if its argument is not equal to false, undefined, null, []
If / Else
The unless helper is the inverse of if
<div class="entry“>
<h1>{{title}}</h1>
{{#if author}}
<h2>By {{firstName}} {{lastName}}</h2>
{{#else}}
<h2>Unknown author</h1>
{{/if}}
{ title: "My first post!",
author: undefined }
}
<div class="entry“>
<h1>My first post!</h1>
<h2>Unknown author</h2>
</div>
Built-in helpers
It shifts the context for a section of a template
with
<div class="entry“>
<h1>{{title}}</h1>
{{#with author}}
<h2>By {{firstName}} {{lastName}}</h2>
{{/with}}
</div>
{ title: "My first post!",
author: { firstName: “Ivano", lastName: “Malavolta" }
}
<div class="entry“>
<h1>My first post!</h1>
<h2>By Ivano Malavolta</h2>
</div>
handlebars summary
Each Template can contain Expressions and Helpers operating on them
The main helpers are:
• each
• if / else /unless
• with
You can define your own Helpers that operate on expressions, they return HTML code
A template can be (pre)-compiled and must be executed with a context in order to return the
final HTML fragment
Handlebars
• Why Handlebars
• Handlebars basics
• Usage with Backbone and Require JS
Usage with Backbone and Require JS
Templates can be seen as special modules
So we can have the following:
1. a separate HTML file for each template
2. a Backbone view can have a dependency to each template
3. the template can be executed by using a JSON object of the Backbone model as context
Example
Dependency to template HTML file
It contains a string
Compiled template
Execution of the template
References
http://backbonejs.org
http://requirejs.org
http://handlebarsjs.com
https://github.com/iivanoo/cordovaboilerplate
LAB
1. Integrate everything with the Cordova Boilerplate
• http://github.com/iivanoo/cordovaboilerplate
2. Define all Backbone’s objects as Require modules with dependencies
3. Move out all the HTML code you had in the JavaScript code into Handlebars
templates
Contact
Ivano Malavolta
iivanoo
ivano.malavolta@gssi.infn.it
www.ivanomalavolta.com

[2015/2016] Require JS and Handlebars JS

  • 1.
  • 2.
    How you structureyour applications MVC framework for giving structure File and module loader for code modularization Templating engine for separation of concerns
  • 3.
    How you structureyour applications
  • 4.
    Roadmap • Require JS •Handlebars • Conclusions
  • 5.
    Require JS • WhyRequire JS • Using modules • Defining modules • Configuring Require JS
  • 6.
    Why Require JS Weare buildingapps, not websites We need well-specified and isolated JS files/modules Code complexity grows as the app gets bigger à we need some sort of #include/import/require à ability to load nested dependencies
  • 7.
    What we wantto avoid uncontrolled scripts poor control flow understanding
  • 8.
    RequireJS RequireJS is aJavaScript file and moduleloader Using a modular script loader like RequireJS will improve the modularity of your code à speed in implementing changes à better understanding of the code Require JS allows modules to be loaded as fast as possible, even out of order, but evaluated in the correct dependency order Builton the Module Pattern JavaScript file and module loader
  • 9.
    The module pattern AJavaScript code moduleis some JavaScript code located in a function All of the code that runs inside the function lives in a closure, which provides: • privacy • state throughoutthe lifetime of the module
  • 10.
    Module example Technically, itis simply a function that executes immediately
  • 11.
    Module VS scriptfiles A moduleis different from a traditional script file in that it defines a well-scoped object that avoids pollutingthe global namespace à its retained objects can be deleted by the GC VS
  • 12.
    Require JS • WhyRequire JS • Using modules • Defining modules • Configuring Require JS
  • 13.
    Using modules main.js isthe entry point of the app The main HTML:
  • 14.
    The main JSfile: Using modules This function is called when all dependencies are loaded If a required module calls define(), then this function is not fired until its dependencies have been loaded Required modules References to required modules
  • 15.
    Require JS • WhyRequire JS • Using modules • Defining modules • Configuring Require JS
  • 16.
    Module without dependenciesAlways one module per file Public variables Setup code the simplest module can be a plain collection of name/value pairs module with initialization The returned element can be any valid JS element By convention I always return an object representing the module
  • 17.
    Module with dependencies Dependency definition Dependentmodule reference Dependent module usage This function is called when zepto.js is loaded. If zepto.js calls define(), then this function is not fired until also zepto’s dependencies have loaded
  • 18.
    Require JS underthe hoods... 1. loads each dependency as a script tag, using head.appendChild() and waits for all dependencies to load 2. computes the right order in which to call the functionsthat define the modules 3. calls the module definitionfunctions of each dependency in the right order main.js jQuery Backbone SpinJS MoviesCollection MovieModel MoviesView 1 2 3 4 5 67
  • 19.
    Require JS • WhyRequire JS • Using modules • Defining modules • Configuring Require JS
  • 20.
    Configuring Require JS Requirerefers to a global configuration options It allows developers to: • set the paths to all used frameworks in one place • use older frameworks as modules (shim) • define configurationparams for the modules • etc.
  • 21.
    Configuring Require JS Shimsfor older frameworks paths to used frameworks Dependent module usage
  • 22.
    Roadmap • Require JS •Handlebars • Conclusions
  • 23.
    Handlebars • Why Handlebars •Handlebars basics • Usage with Backbone and Require JS
  • 24.
    Why Handlebars We wantto separate presentation from logic TRANSLATE TO: we don’t want to put any HTML element into JavaScript code separate logic from presentation Imagine yourself trying to change how a movie should be rendered in your app...
  • 25.
    Handlebars • Why Handlebars •Handlebars basics • Usage with Backbone and Require JS
  • 26.
    Example of template AHandlebars expression is {{ something }}
  • 27.
    Escape values Handlebars HTML-escapesall the values returned by an {{expression}} If you don't want Handlebars to escape a value, use the "triple-stash“ à {{{ expression }}}
  • 28.
    Populate your template Therecurrent process of obtaining a populated template is the following: 1. create the template T with its placeholders {{ - }} 2. compile the template into a JavaScript function t 3. create a context CT containing the actual values for placeholders 4. run the compiled template t(CT) to obtain the final HTML fragment
  • 29.
    1. create thetemplate Templates are defined within a <script> tag or in external files
  • 30.
    2. compile thetemplate Handlebars.compile is used to compile a template Compiling = obtaining a JS function representing the template
  • 31.
    3. create acontext for the template A context is a JavaScript object used to populate a template Here the keys of the object must match with the name of the placeholders to be populated
  • 32.
    4. obtain thefinal HTML fragment You have to execute a template with a context in order to get its corresponding HTML code
  • 33.
    Expressions The simplest expressionis a simple identifier This expression means "look up the username property in the current context"
  • 34.
    Expressions with paths Handlebarsexpressions can also be dot-separated paths This expression means "look up the user property in the current context, then look up the username property of the user"
  • 35.
    Helpers Helpers are JavaScriptfunctions that return HTML code You should return a Handlebars SafeString if you don't want it to be escaped by default
  • 36.
    Calling helpers An Handlebarshelper call is a simple identifier, followed by zero or more parameters Each parameter is a Handlebars expression es. {{ test user }} In this case, test is the name of the Handlebars helper, and user is a parameter to the helper
  • 37.
    Built-in helpers To iterateover a list each Inside the block, you can use this to reference the element being iterated <ul class="people_list"> {{#each people}} <li>{{this}}</li> {{/each}} </ul> { people: [ “Ivano", “Andrea", “Paolo" ] } <ul class="people_list"> <li>Ivano</li> <li>Andrea</li> <li>Paolo</li> </ul>
  • 38.
    Built-in helpers It rendersthe block if its argument is not equal to false, undefined, null, [] If / Else The unless helper is the inverse of if <div class="entry“> <h1>{{title}}</h1> {{#if author}} <h2>By {{firstName}} {{lastName}}</h2> {{#else}} <h2>Unknown author</h1> {{/if}} { title: "My first post!", author: undefined } } <div class="entry“> <h1>My first post!</h1> <h2>Unknown author</h2> </div>
  • 39.
    Built-in helpers It shiftsthe context for a section of a template with <div class="entry“> <h1>{{title}}</h1> {{#with author}} <h2>By {{firstName}} {{lastName}}</h2> {{/with}} </div> { title: "My first post!", author: { firstName: “Ivano", lastName: “Malavolta" } } <div class="entry“> <h1>My first post!</h1> <h2>By Ivano Malavolta</h2> </div>
  • 40.
    handlebars summary Each Templatecan contain Expressions and Helpers operating on them The main helpers are: • each • if / else /unless • with You can define your own Helpers that operate on expressions, they return HTML code A template can be (pre)-compiled and must be executed with a context in order to return the final HTML fragment
  • 41.
    Handlebars • Why Handlebars •Handlebars basics • Usage with Backbone and Require JS
  • 42.
    Usage with Backboneand Require JS Templates can be seen as special modules So we can have the following: 1. a separate HTML file for each template 2. a Backbone view can have a dependency to each template 3. the template can be executed by using a JSON object of the Backbone model as context
  • 43.
    Example Dependency to templateHTML file It contains a string Compiled template Execution of the template
  • 44.
  • 45.
    LAB 1. Integrate everythingwith the Cordova Boilerplate • http://github.com/iivanoo/cordovaboilerplate 2. Define all Backbone’s objects as Require modules with dependencies 3. Move out all the HTML code you had in the JavaScript code into Handlebars templates
  • 46.