So, you're too lazy for the Getting Started Guide and want something even quicker. Here's a cheat sheet of 'how-tos' with JavaScriptMVC.
Download it or pull it from Git. JavaScriptMVC is a collection of 4 projects. Once you have JavaScriptMVC, you should have a folder with:
documentjs - documentation engine
funcunit - testing app
jquery - jquery and jQueryMX plugins
steal - dependency management
js - JS command line for Linux/Mac
js.bat - JS command line for Windows
Notice: This folder, the one that has all the JMVC sub projects is called the ROOT FOLDER.
Well, typically, the first thing you'd do is use the Generators to create an application folder, complete with testing, build scripts, and documentation scripts. But, we're doing things the no-magic way!
JavaScriptMVC uses steal/steal.js for dependency management. It allows you to load scripts that might load other scripts and so forth. To use JavaScriptMVC's features like jQuery.Controller and jQuery.View, you 'steal' them like:
steal.plugins('jquery/controller','jquery/view').then(function(){
//code that uses controller and view goes here
})
To start 'stealing' JMVC, you need to add the steal script to your page.
Lets say you have a folder in the root folder called helloworld that looks like:
ROOT\
documentjs\
jquery\
funcunit\
steal\
helloworld\
helloworld.js
helloworld.html
To load steal.js and helloworld.js, put a script tag in helloworld.html like:
<script type='text/javascript'
src='../steal/steal.js?helloworld.js'>
</script>
This loads the steal script and your helloworld script. Now you can use steal to load whatever you want!
jQuery.Controller is used to make perfect widget plugins.
The following makes a tab plugin:
steal.plugins('jquery/controller').then(function(){
$.Controller("Tabs",{
// initialize widget
init : function(el){
// activate the first tab
$(el).children("li:first").addClass('active')
// hide the other tabs
var tab = this.tab;
this.element.children("li:gt(0)").each(function(){
tab($(this)).hide()
})
},
// helper function finds the tab for a given li
tab : function(li){
return $(li.find("a").attr("href"))
},
// hides old active tab, shows new one
"li click" : function(el, ev){
ev.preventDefault();
this.tab(this.find('.active').removeClass('active')).hide()
this.tab(el.addClass('active')).show();
}
})
});
You can see this in action here. There are a few things to notice about controller:
It creates a jQuery plugin for you. In this case, you can make a tabs like:
$('#myTabsElement').tabs() // ==> new Tabs( $("#myTabsElement") )
The element you add the controller to (#myTabsElement), becomes this.element in the controller.
It automatically delegates event handlers named like: "li click" on
this.element.
Lets say you have an jQuery.EJS template in the root folder named mytemplate.ejs that looks like:
<ul>
<% for( var i =0; i < items.length; i++ ){ %>
<li><%= item[i] %>
<% } %>
</ul>
And you wanted to draw a list of items in an element with id itemslist. You do it like:
steal.plugins('jquery/view/ejs').then(function(){
$('#itemslist').html('//mytemplate.ejs', {items:["apple","orange"]});
})
Your server is producing a list of pizza topings at GET /toppings. The data that comes back
looks like:
[{'id' : 1, 'name': 'cheese'},
{'id' : 2, 'name': 'mushrooms'}]
You want to be able to get a list of topings and know if they are tasty (ie, is not mushrooms). To do this, create a Model like:
steal.plugins('jquery/model').then(function(){
$.Model('Topping',
{
findAll : '/toppings'
},
{
isTasty : function(){
return this.name != 'mushroom'
}
});
});
Now you can get a list of toppings wrapped with additional
helper functions like isTasty:
Topping.findAll({},function(toppings){
alert('the first is ' +
toppings[0].isTasty() ? 'tasty' : 'gross' )
});
JavaScriptMVC uses FuncUnit for testing. FuncUnit supports two types of testing:
But you start creating these tests in the same way - by making a test page
and a test script. Lets say you wanted to
test helloworld.js and helloworld.html. Without code generators,
you add 4 files to make helloworld look like:
helloworld\
helloworld.html
helloworld.js
funcunit.html
funcunit.js
qunit.html
qunit.js
Put the following in qunit.html:
<html>
<head>
<link rel="stylesheet" type="text/css" href="../funcunit/qunit/qunit.css" />
<script type='text/javascript' src='../steal/steal.js?helloworld\qunit.js'></script>
</head>
<body>
<h1 id="qunit-header">Hello World Unit Test Suite</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<div id="test-content"></div>
<ol id="qunit-tests"></ol>
<div id="qunit-test-area"></div>
</body>
</html>
funcunit.html will look the same except change qunit.js to funcunit.js.
qunit.js might look like:
steal.plugins('funcunit/qunit').then('//helloworld/helloworld', function(){
module('helloworld')
test('something is there', function(){
ok(helloworld, "there's an object called helloworld");
})
})
funcunit.js might look like:
steal.plugins('funcunit').then( function(){
module('helloworld',{
setup : function(){
S.open('//helloworld/helloworld.html');
}
})
test('The page says hello world', function(){
ok(S(':contains(hello world)').size(), "The page says hello world");
})
})
To run these tests, you can either open the test page with your browser, or with envjs:
funcunit\envjs helloworld\funcunit.html
funcunit\envjs helloworld\qunit.html