MVC Patterns, Frameworks & Templates

What we will be covering

Design Patterns, What are they?

a design pattern is a general reusable solution to a commonly occurring problem within a given context in software design.
source: Wikipedia :: Software design pattern

The Benefits

The MVC Design Pattern

Model-View-Controller is an architectural Design Pattern.

MVC isolates domain logic from the user interface, promoting

The MVC Design Pattern

The Model

Sample Model

The model is any of the logic or the database or any of the data itself. -Terence Parr

Source: Wikipedia :: Model-view-controller

The MVC Design Pattern

The View

Sample View

Source: Wikipedia :: Model-view-controller

The MVC Design Pattern

The Controller

Sample Controller

The controller decides what the user's input was, how the model needs to change as a result of that input, and which resulting view should be used. - Jeff Atwood

source: Wikipedia :: Model-view-controller
Source: Understanding Model-View-Controller

MVC on the Backend

MVC has traditionally been implemented in many backend languages; including:

MVC on the Frontend

JavaScript MVC Frameworks

MVC on the Frontend

Project and Companies using MVC Frameworks

MVC on the Frontend

The Reasons for MVC on the Frontend

An MVC Application - Filmstrip

Goals / Features

We would like to be able to do the following:

Built in Bacbone.js 0.5.3 and Ruby on Rails 3.1.1. So what is Backbone.js?

Backbone.js Basics

Backbone supplies structure to JavaScript-heavy applications ...

Dependancies

Source: http://documentcloud.github.com/backbone/
Source: http://documentcloud.github.com/underscore/
Source: http://jquery.com/
Source: http://zeptojs.com/

Backbone.js Basics

The Model

You extend Backbone.Model with your domain-specific methods, and Model provides a basic set of functionality for managing changes; conversions, validations, computed properties and access control.


/**
    @description An example of a Model in Backbone.js
    @url http://documentcloud.github.com/backbone/#Model
*/
var Model = Backbone.Model.extend({
    // Restful URL of the Model e.g. "/[urlRoot]/id"
    'urlRoot': '/model'
    // Default attribute values
    'defaults': {
        'length': 0,
        'width': 0,
        'height': 0
    },
/**
    @constructor
*/
    'initialize': function () {

    },
/**
    @function
    @description Validates your attributes before a set or save
*/
    'validate': function () {
        // do not return anything if attributes are valid
    }
});			
		

Initializing the Model


var model = new Model({
    'length': 0,
    'width': 0,
    'height': 0
});
		

Setting and Retrieving a Models Attribute


model.set('length', 1);
----
model.get('length');
		

Source: http://documentcloud.github.com/backbone/#Model

Backbone.js Basics

The View / Controller

The general idea is to organize your interface into logical views, backed by models, each of which can be updated independently when the model changes, without having to redraw the page.


/**
    @description An example of a View in Backbone.js
    @url http://documentcloud.github.com/backbone/#View
*/
var View = Backbone.View.extend({
    'events': {
        'click a': 'clickHandler'
    },
/**
    @constructor
*/
    'initialize': function () {

    },
/**
    @function
    @description Override this function with your code that renders the view template from model data, and updates this.el with the new HTML.
    @returns {View}
*/
    'render': function () {
        // Allows for chained calls
        return this;
    },
/**
    @event
    @description Handles the click even on all anchor tags.
    @param e Click Event
*/
    'clickHandler': function (e) {
        e.preventDefault();
        e.stopPropagation();
    }
});
	
Backbone views are almost more convention than they are code — they don't determine anything about your HTML or CSS for you, and can be used with any JavaScript templating library.

The View class can also be thought of as a kind of controller, dispatching events that originate from the UI, with the HTML template serving as the true view.

Initializing the View

Already Rendered


new View({
    'el': document.getElementById('item')
});		
	

Not Rendered


var view = new View();
----
'initialize': function () {
    this.render();
},
----
view.render();
	

Source: http://documentcloud.github.com/backbone/#View

Backbone.js Basics

The Collection (not controller)

Collections are ordered sets of models.


/**
    @description An example of a Collection in Backbone.js
    @url http://documentcloud.github.com/backbone/#Collection
*/
var Collection = Backbone.Collection.extend({
    //Override this property to specify the model class that the collection contains
    'model': Model,
/**
    @constructor
*/
    'initialize': function () {

    }
});
	

Adding a Model


//initialize your model
var model = new Model({
    'length': 0,
    'width': 0,
    'height': 0
});

//create a new collection
var coll = new Collection();

//add model to collection
coll.add(model);
	

Source: http://documentcloud.github.com/backbone/#Collection

Backbone.js based App Structure

Let's See Some Code!

Filmstrip - Organizing our App

Loading our App with LABjs


<script src="libs/LAB.min.js">
<script>
    $LAB
    //libs
    .script('libs/jquery-1.6.4.min.js" %>').wait()
    .script('libs/underscore-min.js" %>').wait()
    .script('libs/backbone.js" %>').wait()
    //models
    .script('flmstrp/model/FilmModel.js" %>').wait()
    //collections
    .script('flmstrp/collection/FilmCollection.js" %>').wait()
    //views
    .script('flmstrp/view/FilmView.js" %>').wait()
    .script('flmstrp/view/ModalView.js" %>').wait()
    .script('flmstrp/film.config.js" %>').wait()
    .script('flmstrp/film.js" %>').wait()
    .script('flmstrp/film.personalfilms.js" %>').wait()
    .script('flmstrp/film.modal.js" %>').wait( function () {
        Film.PersonalFilms.init();
        Film.Modal.create();
    });
</script>
	

Namespacing our App (film.config.js)


var Film = {}; //Global utils, attributes here
Film.views = {}; //personalView
Film.models = {}; //personalFilmModels
Film.collections = {}; //personalFilmCollection
		

Filmstrip - Initializing Our App

Filmstrip - Creating our App

The Setup of our Backbone App is Complete!

Filmstrip - The Details

Filmstrip - Task

Removing a Film

JavaScript Templating

How does templating work?

Simple: It calls a JavaScript function for injecting html contents on the client side. It can also interpolate and/or evaluate expressions using regex.

Templating Best Practices

Javascript Templating Examples

Underscore.js

Template


<script type="text/template" id="myscript">
<ul>
    <% _.each(models, function (model) {
        <li>
            <h2><%= model.name %></h2>
            <p><%= model.description %></p>
        </li>
    })%>
</ul>
</script>
		

Template Processing


var models, results;
models = [model1, model2, model3];
results = _.template($('#myscript').html(), models);

$('#container').append(results);

Tips

You can change your interpolation settings like so:


_.templateSettings = {
  interpolate : /\{\{(.+?)\}\}/g,
  evaluate : /\{\{\=(.+?)\}\}/g,
};
		

This allows you to use {{ }} instead of <% %>

Javascript Templating Examples

Mustache.js

Template


<script type="text/template" id="myscript">
<ul>
    {{#models}}
    <li>
        <h2>{{name}}</h2>
        <p>{{description}}</p>
    </li>
    {{#models}}
</ul>
</script>
	

Template Processing


var results, html;

html = $('#myscript').html();
results = Mustache.to_html(html, { 'models': [model1, model2, model3] });

$('#container')
    .append(results);

	

Tips

To disable escaping in your template - use triple mustaches like so:


{{{unescaped_variable}}}
	

The following characters are escaped int he curly braces:


    & \ " ' < >

Javascript Templating Examples

Handlebars.js

Template


<script type="text/x-handlebars-template" id="myscript">
<ul>
    {{#each models}}
    <li>
        <h2>{{this.name}}</h2>
        <p>{{this.description}}</p>
    </li>
    {{/each}}
</ul>
</script>
	

Template Processing


var template, results;

template = Handlebars.compile($('#myscrip').html());

results = template( {'models': [model1, model2, model3]} );

$('#container')
    .append(results);

	

Tips

Use helpers to process your information, helping you keep your logic outside the template:


Handlebars.registerHelper('calculate_total', function() {
  return "" + this.price * this.order_amount + "";
});
	

You would then use this help, like so:


<ul>
  {{#each items}}
  <li>Total: {{calculate_total}}</li>
  {{/each}}
</ul>	
	

References / Resources

Source Code / Slides

Thank You

/

#