Models

Models represent state in your application. Think of a user in your system, you would create a model that contains attributes about your user. We provide a basic model to assist in storing data.

Basics

Here we will start with a class called "car" and store attributes about it. When you think of a car, there are four properties everyone is familiar with.

Make

Model

Year

Color

By creating a car model, we can store multiple cars and then search/filter based on the properties.

Defaults

Each model has two default properties, id and modelName. The id is set by the storage adadpter. modelName is used for the storage adapter. With that, there are five functions implemented that are based on the storage adapters.
All callbacks are asynchronous, as storage adapters can be remote data stores

get(id,callback)

getAll(callback)

remove(callback)

save(callback)

set(properties)

get(id,callback)

This takes in an id and loads the object, then passes it as a parameter to the callback function.

getAll(callback)

This loads all items of the given model and executes the callback.

remove(callback)

This removes an item from the storage adapter and executes the callback.

save(id,callback)

This saves an item from the storage adapter and executes the callback. This implements the insert/update commands.

set(properties)

This takes in a hash map of keys/values to set on the selected item.

Models Overview

Creating a model is simple. You simply call $.mvc.model.extend(name,properties,storageAdapter) and it will setup everything for you. The name parameter is name of the model, properties are a hash table, and storageAdapter is the adapter you want to use.

var Car=$.mvc.model.extend("car",{});

The above would create a car model accessed by the variable Car. It would not have any properties and only have the default functions. IT would use the default local storage adapter.

Storage Adapters

Storage adapters are the backend of the models that handle the data store. By default, we use the HTML5 local storage for data, but you can extend your own with any technology you write. Each adapter must implement four functions. When you create your model, there is a third parameter that is the storage adapter

Below is the default local storage adapter with comments/description. We do not store everything in a single entry. Instead, we have a linker record and each is stored as it's own entry then.
We use the modelName property to help us look up and keep track in the linkerCache object.

Please see the sample in the github repo for the server side component.

Other model libraries

You are free to use any model library you would like in your app. The only coupling between MVC and the built in models is auto loading. You are responsible for autoloading your own models.

Welcome to the

MVC Guide.

MVC is a lightweight MVC framework. You may ask "why another framework?". The target of MVC is to be lightweight and fast. We do not provide all the features of advanced
frameworks, like Backbone.js, CanJS, Knockout.js and Ember.js. Instead, the goal is to help with separating the content out from your app, provide routing, basic models and views.

MVC was built to work alongside UI but can also be used as a standlone library. The main goal is to provide controllers and views to help segment out your application.

Controllers - logic that runs in your application. These can be accessed by URL's like server side MVC frameworks do.

Views - the html you render for your application

Models - these handle data storage and relation

MVC Overview

MVC helps you segment out your application and manage your code. Controllers handle the logic side of your app, and are grouped by common functionality. Say you are writing a TODO
app, you're controller may look something like

todo
add
edit
save
delete

You would then be able to call them by URL's that route to the "todo" controller like the following.

Next, open up the app.js file and let's create an instance of the MVC app.

var app = new $.mvc.app();

So our app this there, but it won't do anything. Let's create a controller and two views. Inside your controller folder create the file "hello.js".
Inside the views folder create the files "hello.js" and "world.js"

./
controllers/
hello.js
views/
hello.js
world.js
index.html
app.js

"hello.js" controller

Open up the file with your favorite editor and let's set up a basic controller.

$.mvc.controller.create("hello", {
views:["views/hello.js","views/world.js"], //These are the views we will use with the controller
world:function(){
//This is the action "world". We will load the "world.js" view.
//When loading views, you must reference the folder path and file name.
$("#main").html($.template('views/world.js'));
},
init:function(){
//Here we can run any initializing code for this controller/
},
default:function(){
//Let's load the "hello.js" view as th default.
$("#main").html($.template('views/hello.js'));
},
});

Next, we will edit the two view files. First, we will edit "views/hello.js" and then "views/world.js"

Hello <br>
<a href="hello/world">Hello World</a>

Hello World <br>
<a href="hello/">Go Back</a>

app.js

Let's open up app.js again and edit it. We'll add an entry to load the hello.js controller and add a ready function to load the hello default action.

var app = new $.mvc.app();
app.loadControllers(["hello"]); //You can pass in array or a string. You do not need to reference the .js extension.
//Now let's run code on app.ready and load the default action for the hello controller.
app.ready(function(){
$.mvc.route("hello/");
});

Want to get involved?

First, head over to Github and fork the code. You can start playing around with the core, break things, fix things, and make enhancements. When you are ready, submit a pull request with the following

Overview of the pull request

Bugs fixed/Features added

Test cases for the above

Does this change affect current installs (will it break them)?

We will then review the pull request and either auto merge it or offer back feedback. If you are proposing something drastic, it's best to get in touch with us first to discuss the overall impact and go from there. If we find it diverts from our core goals or will affect users, we will deny it.

Controllers

Controllers drive the logic of your application. Routes are dispatched to functions in the controller to handle actions and execute code. This allows you to separate your logic and group functions into common areas.

Basics

The controller is an object that has functions attached to it. Using "routes", they will be dispatched to the controller, and then execute the function on that object.

Clicking the above link would look at the "foo" controller and then execute the "bar" function if it exists. Anything passed after the "action" part of the URL comes through as parameters. You can specify exactly what parameters are available in your function,
or you can access them via the "arguments" array.

With the above, we would have three parameters available in the function. They would be

1

2

3

Controller Overview

Creating a controller is simple. You call $.mvc.controller.create(name,{functions}) and it will setup everything for you. The name parameter is the name of your controller and the first part of the URL that gets routed.

$.mvc.controller.create("foo",{});

The above would create an empty controller called "foo", which would be accessible via routes to /foo/*. Next let's create the basic controller.

We now have two routes that can be called, views that will be loaded by default, and the init function that gets created when the controller is loaded. Continue on to our sample to see a controller for a simple todo app.

Sample Controller

Below you will find a sample controller for a "Todo" app. It is basic and will only have a few routes, but you will get to see how a controller is registered and actions are handled.

Skeleton Controller

Here is the skeleton of the controller. We will declare the needed functions and views.

Next is the default function. This is called when the app is loaded. We get all the previous items and save them.

default:function(){
//todo_model is an instace of the Todo model. We will get all of them and then list them
var items=todo_model.getAll(function(items){
//Filter active items
var active=items.filter(function(obj){return obj.archive!==true;});
//Filter archived items
var archived=items.filter(function(obj){return obj.archive==true;});
//Loop through the active items and put them in the DOM
active.forEach(function(theItem){
$("#active").append($.template("item_tpl",{item:theItem}));
});
//Loop through the archived items and put them in the DOM
archived.forEach(function(theItem){
$("#archived").append($.template("item_tpl",{item:theItem}));
});
});
}

Now we will handle saving a new todo.

save:function(){
//create a new object
var item = new Todo();
//set active to true
todo.active=true;
//Call save. it is asynchronous, so we execute a callback after it's finished. We will add it to the dom
todo.save(function(theItem){
$("#active").append($.template("item_tpl",{item:theItem}));
});
}

Put it all together

$.mvc.controller.create("foo",
{
views:{"main_tpl","views/main.tpl","item_tpl","views/item.tpl"},
init:function(){
$("#main").html($.template("main_tpl")); //Load the main template
//Now we will wire events for save cancel
$("#save_btn").bind("click",function(evt){
$.mvc.route("/todo/save");
});
$("#cancel_btn").bind("click",function(evt){
$("#todo_text").val("");
});
},
default:function(){
//todo_model is an instace of the Todo model. We will get all of them and then list them
var items=todo_model.getAll(function(items){
//Filter active items
var active=items.filter(function(obj){return obj.archive!==true;});
//Filter archived items
var archived=items.filter(function(obj){return obj.archive==true;});
//Loop through the active items and put them in the DOM
active.forEach(function(theItem){
$("#active").append($.template("item_tpl",{item:theItem}));
});
//Loop through the archived items and put them in the DOM
archived.forEach(function(theItem){
$("#archived").append($.template("item_tpl",{item:theItem}));
});
});
},
save:function(){
//create a new object
var item = new Todo();
//set active to true
todo.active=true;
//Call save. it is asynchronous, so we execute a callback after it's finished. We will add it to the dom
todo.save(function(theItem){
$("#active").append($.template("item_tpl",{item:theItem}));
});
},
finish:function(id,active){
var todo=todo_model.get(id,function(item){
item.active=active;
item.save(function(){
//Let's move it to the correct list
if(active)
$("#active").append("#"+id+"_item");
else
$("#archived").append("#"+id+"_item");
});
});
},
delete:function(id){
var todo=todo_model.remove(id,function(item){
//Let's remove the item from the DOM now
$("#"+id+"_item").remove();
});
}
}
);

Views

Views render the UI for your client. MVC uses the Dot.js plugin to assist in rendering views, but you can use any library you want. Views help with simplifying the code of your application and displays any elements to the user.

Invoking templates

To invoke a template, you call the javascript function and pass in the template name. When including them using an object, the key is the name. When including them in an array, the path is the name of the template.

var content=$.template("index_tpl");

You can pass in data to the template with a second parameter that is an object with all the values. Each property on the data object is accessed in the template by name then. You do NOT act on the object that is passed in.

var content=$.template("index_tpl",{name:'MVC'});

$.template returns an HTML string that you can then set $.html() on.

$("#myDiv").html($.template("index_tpl",{name:'MVC'}));

You can also call the $.tmpl function, which is similar to $.template but returns a App Framework object with the result. The function parameters are the same between the two.

$("#myDiv").append($.tmpl("index_tpl",{name:'MVC'}));

Sample Views

Below are some sample views. We will show how the contents of the view and expected result.

Count 1 to 5

Counter =

The expected output is

Counter = 1
Counter = 2
Counter = 3
Counter = 4
Counter = 5

Basic data

Here is a view that will display basic information about a person. We will create the person object and pass it in as a parameter, then render the data in the template.

Advanced table list (loop)

Below is an advanced use where we will construct a table based off an array in two ways. The first is to pass in the full array and do a loop. The second we will loop outside and use $.tmpl and append the content as we build it.

Other Template Libraries

You are free to use any other template library in MVC. You do need to register the special type attribute for your template system on the app object.

//Set the type for handlebars template system
app.setViewType("text/x-handlebars-template");

Please refer to the documentation for your selected template library on how to use them. There are numerous out there, so make sure it's lightweight and fast!

Hash Change Routes

You can listen for routing changes based off the hash change event by registering the listener on your app.

app.listenHashChange(); //Listen for hash change events

This will dispatch routes based off the URI structure of the hash. Take for example the hash you see above

docmvc.php#routes/cnt_hash //Full page
#routes/cnt_hash //hash

What we do is replace the hash symbol (#) with a forward slash to create our route

/routes/cnt_hash //Replace the # with a / to create the route

We now have the route being dispatched to the "routes" controller with actino of "cnt_hash"

Routes

You can setup functions based off routes instead of controllers. They look similar to REST routes, but you can not specify the type (GET/POST/DELETE). They work in the same pattern as the controllers, in that you have.

With the above, we have three routes registered that can be called. Here are five calls and what the expected output would be from the console.log functions

/foo/bar
"Foo bar"

/foo/foo
"Foo foo"

/foo
"Foo"

/foo/bar/adsf/123
"Foo bar" , ["asdf","123]

/foo/
"Foo"

MVC configuration

MVC a few configuration properties. We will go over those below, along with what they do. The configuration properties are set off the $.mvc.app object you create.

var app = new $.mvc.app();
app.controllersDir("path"); //Set the directory to your controllers folder if it is not named "controllers".
app.modelsDir("path"); //Set the directory to your models folder if it is not named "models";
app.ready(function); //Function that executes as soon as the MVC app has completed loading, or right away if it
// has already loaded.