Commit ab4eb6b7 authored by addyosmani's avatar addyosmani

updating directory structure

parent c72bcab6
This diff is collapsed.
<!DOCTYPE html>
<html>
<head>
<title>Backbone Demo: Todos</title>
<link href="css/todos.css" media="all" rel="stylesheet" type="text/css"/>
<script src="js/json2.js"></script>
<script src="js/jquery-1.5.js"></script>
<script src="js/underscore-1.1.6.js"></script>
<script src="js/backbone.js"></script>
<script src="js/backbone-localstorage.js"></script>
<script src="js/todos.js"></script>
</head>
<body>
<!-- Todo App Interface -->
<div id="todoapp">
<div class="title">
<h1>Todos</h1>
</div>
<div class="content">
<div id="create-todo">
<input id="new-todo" placeholder="What needs to be done?" type="text" />
<span class="ui-tooltip-top" style="display:none;">Press Enter to save this task</span>
</div>
<div id="todos">
<ul id="todo-list"></ul>
</div>
<div id="todo-stats"></div>
</div>
</div>
<div id="credits">
Created by
<br />
<a href="http://jgn.me/">J&eacute;r&ocirc;me Gravel-Niquet</a>. <br />Cleanup, edits: <a href="http://addyosmani.com">Addy Osmani</a>.
</div>
<!-- Templates -->
<script type="text/template" id="item-template">
<div class="todo <%= done ? 'done' : '' %>">
<div class="display">
<input class="check" type="checkbox" <%= done ? 'checked="checked"' : '' %> />
<div class="todo-content"></div>
<span class="todo-destroy"></span>
</div>
<div class="edit">
<input class="todo-input" type="text" value="" />
</div>
</div>
</script>
<script type="text/template" id="stats-template">
<% if (total) { %>
<span class="todo-count">
<span class="number"><%= remaining %></span>
<span class="word"><%= remaining == 1 ? 'item' : 'items' %></span> left.
</span>
<% } %>
<% if (done) { %>
<span class="todo-clear">
<a href="#">
Clear <span class="number-done"><%= done %></span>
completed <span class="word-done"><%= done == 1 ? 'item' : 'items' %></span>
</a>
</span>
<% } %>
</script>
</body>
</html>
// A simple module to replace `Backbone.sync` with *localStorage*-based
// persistence. Models are given GUIDS, and saved into a JSON object. Simple
// as that.
// Generate four random hex digits.
function S4() {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
};
// Generate a pseudo-GUID by concatenating random hexadecimal.
function guid() {
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
};
// Our Store is represented by a single JS object in *localStorage*. Create it
// with a meaningful name, like the name you'd give a table.
var Store = function(name) {
this.name = name;
var store = localStorage.getItem(this.name);
this.data = (store && JSON.parse(store)) || {};
};
_.extend(Store.prototype, {
// Save the current state of the **Store** to *localStorage*.
save: function() {
localStorage.setItem(this.name, JSON.stringify(this.data));
},
// Add a model, giving it a (hopefully)-unique GUID, if it doesn't already
// have an id of it's own.
create: function(model) {
if (!model.id) model.id = model.attributes.id = guid();
this.data[model.id] = model;
this.save();
return model;
},
// Update a model by replacing its copy in `this.data`.
update: function(model) {
this.data[model.id] = model;
this.save();
return model;
},
// Retrieve a model from `this.data` by id.
find: function(model) {
return this.data[model.id];
},
// Return the array of all models currently in storage.
findAll: function() {
return _.values(this.data);
},
// Delete a model from `this.data`, returning it.
destroy: function(model) {
delete this.data[model.id];
this.save();
return model;
}
});
// Override `Backbone.sync` to use delegate to the model or collection's
// *localStorage* property, which should be an instance of `Store`.
Backbone.sync = function(method, model, options) {
var resp;
var store = model.localStorage || model.collection.localStorage;
switch (method) {
case "read": resp = model.id ? store.find(model) : store.findAll(); break;
case "create": resp = store.create(model); break;
case "update": resp = store.update(model); break;
case "delete": resp = store.destroy(model); break;
}
if (resp) {
options.success(resp);
} else {
options.error("Record not found");
}
};
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// An example Backbone application contributed by
// [Jérôme Gravel-Niquet](http://jgn.me/). This demo uses a simple
// [LocalStorage adapter](backbone-localstorage.html)
// to persist Backbone models within your browser.
// Load the application once the DOM is ready, using `jQuery.ready`:
$(function(){
// Todo Model
// ----------
// Our basic **Todo** model has `content`, `order`, and `done` attributes.
window.Todo = Backbone.Model.extend({
// Default attributes for the todo.
defaults: {
content: "empty todo...",
done: false
},
// Ensure that each todo created has `content`.
initialize: function() {
if (!this.get("content")) {
this.set({"content": this.defaults.content});
}
},
// Toggle the `done` state of this todo item.
toggle: function() {
this.save({done: !this.get("done")});
},
// Remove this Todo from *localStorage* and delete its view.
clear: function() {
this.destroy();
this.view.remove();
}
});
// Todo Collection
// ---------------
// The collection of todos is backed by *localStorage* instead of a remote
// server.
window.TodoList = Backbone.Collection.extend({
// Reference to this collection's model.
model: Todo,
// Save all of the todo items under the `"todos"` namespace.
localStorage: new Store("todos"),
// Filter down the list of all todo items that are finished.
done: function() {
return this.filter(function(todo){ return todo.get('done'); });
},
// Filter down the list to only todo items that are still not finished.
remaining: function() {
return this.without.apply(this, this.done());
},
// We keep the Todos in sequential order, despite being saved by unordered
// GUID in the database. This generates the next order number for new items.
nextOrder: function() {
if (!this.length) return 1;
return this.last().get('order') + 1;
},
// Todos are sorted by their original insertion order.
comparator: function(todo) {
return todo.get('order');
}
});
// Create our global collection of **Todos**.
window.Todos = new TodoList;
// Todo Item View
// --------------
// The DOM element for a todo item...
window.TodoView = Backbone.View.extend({
//... is a list tag.
tagName: "li",
// Cache the template function for a single item.
template: _.template($('#item-template').html()),
// The DOM events specific to an item.
events: {
"click .check" : "toggleDone",
"dblclick div.todo-content" : "edit",
"click span.todo-destroy" : "clear",
"keypress .todo-input" : "updateOnEnter"
},
// The TodoView listens for changes to its model, re-rendering. Since there's
// a one-to-one correspondence between a **Todo** and a **TodoView** in this
// app, we set a direct reference on the model for convenience.
initialize: function() {
_.bindAll(this, 'render', 'close');
this.model.bind('change', this.render);
this.model.view = this;
},
// Re-render the contents of the todo item.
render: function() {
$(this.el).html(this.template(this.model.toJSON()));
this.setContent();
return this;
},
// To avoid XSS (not that it would be harmful in this particular app),
// we use `jQuery.text` to set the contents of the todo item.
setContent: function() {
var content = this.model.get('content');
this.$('.todo-content').text(content);
this.input = this.$('.todo-input');
this.input.bind('blur', this.close);
this.input.val(content);
},
// Toggle the `"done"` state of the model.
toggleDone: function() {
this.model.toggle();
},
// Switch this view into `"editing"` mode, displaying the input field.
edit: function() {
$(this.el).addClass("editing");
this.input.focus();
},
// Close the `"editing"` mode, saving changes to the todo.
close: function() {
this.model.save({content: this.input.val()});
$(this.el).removeClass("editing");
},
// If you hit `enter`, we're through editing the item.
updateOnEnter: function(e) {
if (e.keyCode == 13) this.close();
},
// Remove this view from the DOM.
remove: function() {
$(this.el).remove();
},
// Remove the item, destroy the model.
clear: function() {
this.model.clear();
}
});
// The Application
// ---------------
// Our overall **AppView** is the top-level piece of UI.
window.AppView = Backbone.View.extend({
// Instead of generating a new element, bind to the existing skeleton of
// the App already present in the HTML.
el: $("#todoapp"),
// Our template for the line of statistics at the bottom of the app.
statsTemplate: _.template($('#stats-template').html()),
// Delegated events for creating new items, and clearing completed ones.
events: {
"keypress #new-todo": "createOnEnter",
"keyup #new-todo": "showTooltip",
"click .todo-clear a": "clearCompleted"
},
// At initialization we bind to the relevant events on the `Todos`
// collection, when items are added or changed. Kick things off by
// loading any preexisting todos that might be saved in *localStorage*.
initialize: function() {
_.bindAll(this, 'addOne', 'addAll', 'render');
this.input = this.$("#new-todo");
Todos.bind('add', this.addOne);
Todos.bind('reset', this.addAll);
Todos.bind('all', this.render);
Todos.fetch();
},
// Re-rendering the App just means refreshing the statistics -- the rest
// of the app doesn't change.
render: function() {
var done = Todos.done().length;
this.$('#todo-stats').html(this.statsTemplate({
total: Todos.length,
done: Todos.done().length,
remaining: Todos.remaining().length
}));
},
// Add a single todo item to the list by creating a view for it, and
// appending its element to the `<ul>`.
addOne: function(todo) {
var view = new TodoView({model: todo});
this.$("#todo-list").append(view.render().el);
},
// Add all items in the **Todos** collection at once.
addAll: function() {
Todos.each(this.addOne);
},
// Generate the attributes for a new Todo item.
newAttributes: function() {
return {
content: this.input.val(),
order: Todos.nextOrder(),
done: false
};
},
// If you hit return in the main input field, create new **Todo** model,
// persisting it to *localStorage*.
createOnEnter: function(e) {
if (e.keyCode != 13) return;
Todos.create(this.newAttributes());
this.input.val('');
},
// Clear all done todo items, destroying their models.
clearCompleted: function() {
_.each(Todos.done(), function(todo){ todo.clear(); });
return false;
},
// Lazily show the tooltip that tells you to press `enter` to save
// a new todo item, after one second.
showTooltip: function(e) {
var tooltip = this.$(".ui-tooltip-top");
var val = this.input.val();
tooltip.fadeOut();
if (this.tooltipTimeout) clearTimeout(this.tooltipTimeout);
if (val == '' || val == this.input.attr('placeholder')) return;
var show = function(){ tooltip.show().fadeIn(); };
this.tooltipTimeout = _.delay(show, 1000);
}
});
// Finally, we kick things off by creating the **App**.
window.App = new AppView;
});
This diff is collapsed.
# JavaScriptMVC Todo Application
###Why this fork?
I began this fork of the useful JMVC Todo application as I felt it was missing a number of things including:
<ul>
<li>Setup documentation (which I've written up below)</li>
<li>A directory structure that matches what the build files originally defined require</li>
<li>Minor changes to help it fall in line with the Backbone and Spine todo apps including UI features and stylistic changes.</li>
<li>Pre-built production.js and production.css files so users could test the app right out of the box (as long as steal etc. are available)</li>
</ul>
##Getting Started
JavaScriptMVC is a jQuery-based JavaScript framework that's excellent as a comprehensive front-end solution for structuring applications using the MVC architecture pattern.
It's broken down into 4 separate projects that can be used independently of each other. These are:
<ul>
<li><b>jQueryMVC</b> - MVC extensions for jQuery</li>
<li><b>StealJS</b> - Dependency management, build process, code generators</li>
<li><b>FuncUnit</b> - A web testing framework</li>
<li><b>DocumentJS</b> - A JavaScript documentation framework</li>
</ul>
For more information on getting started with the framework as a whole, you may find Justin Meyer's documentation on it here https://gist.github.com/989117 quite helpful. It discusses classes, models, views and controllers and is an overall good read for any developers wishing to begin using JMVC.
###Setup
To get started with the Todo application, you'll first need to clone the repository to a local directory. You have a few options of how to approach this.
###Cloning with submodules automatically synched
The repository also contains git submodules for jQueryMVC, StealJS, FuncUnit and DocumentJS out of the box. If you would like to check-out the code for the application including all submodules you can do so as follows:
<pre>
git clone --recursive git://github.com/addyosmani/todo
</pre>
Git 1.6.5 supports this however if you're using an older version of Git you can achieve the same effect using <pre>git submodule update --init</pre>
###Cloning with submodules manually
Alternatively, you can checkout the main application files and clone the dependancies manually. To checkout the app simply execute:
<pre>
git clone git@github.com:addyosmani/todo.git
</pre>
You can then either use *submodules* to checkout the submodules as their own repositories (eg. if you forked them from JMVC and wished to keep track of your own versions) or alternatively by cloning their repos locally.
###Submodules
<pre>
git submodule add git://github.com/jupiterjs/steal.git steal
git submodule add git://github.com/jupiterjs/jquerymx.git jquery
git submodule add git://github.com/jupiterjs/funcunit.git funcunit
git submodule add git://github.com/jupiterjs/documentjs.git documentjs
</pre>
Note that as per JupiterIT's original Todo application, jquerymx is actually stored in the directory called jquery in case we decide to sync up any changes made without worrying about path differences.
###Cloning
Cloning repositories using GitHub is a fairly straight-forward process and the todo application just requires the following commands to be executed to get you setup:
<pre>
git clone git://github.com/jupiterjs/steal.git
git clone git://github.com/jupiterjs/jquerymx.git
git clone git://github.com/jupiterjs/funcunit.git
git clone git://github.com/jupiterjs/documentjs.git
</pre>
###Structure
In order to correctly build the todo application, you'll need to ensure that you have the following directory structure, unless you decide to change the build files in the todo/scripts directory:
<pre>
funcunit
jquery
steal
todo
todo
index.html, todo.js etc.
scripts
test
</pre>
###Building
Within todo/todo, you'll find the main application (todo.js) as well as two additional folders. The *scripts* folder contains the build files needed to build the final production files required for the app to run, whilst the *test* folder contains the FuncUnit and QUnit files required for testing. Let's take a look at todo/todo/scripts/build.js:
<pre>
load("steal/rhino/steal.js");
steal.plugins('steal/build','steal/build/scripts','steal/build/styles',function(){
steal.build('todo/todo/scripts/build.html',{to: 'todo/todo'});
});
</pre>
In this simple build file, we're telling out build process to load steal.js from the rhino directory (for more on Rhino, see here: http://www.mozilla.org/rhino/doc.html) and then *steal* (ie. load within the context of a script loader) the steal plugins we'll be using for our build.
We finally define the build actions required, which essentially allows us to specify the build source (todo/todo/scripts/build.html) and the build target (todo/todo). In case you're wondering what build.html does, it effectively tells steal.js to build the application within the folder todo/todo as follows:
<pre>
&lt;script type=&#39;text/javascript&#39; src=&#39;../../../steal/steal.js?todo/todo&#39;&gt;
</pre>
You of course don't have to output your build files to the same directory as your application source, however as both our outputs have names which are different to the source files, I think this works fine for our example.
Finally, to perform the application build so that JMVC outputs the production-ready version of your code, execute the following command where we pass our build.js file as an argument to steal's builder.
<pre>
./steal/js todo/todo/scripts/build.js
</pre>
TOC:
A. How to get (and contribute) to JMVC
A. How to get (and contribute) JMVC
1. Start a new project in git.
2. Fork ....
http://github.com/jupiterjs/steal and
http://github.com/jupiterjs/jquerymx
3. Add steal and javascriptmvc as submodules of your project...
git submodule add git@github.com:_YOU_/steal.git steal
git submodule add git@github.com:_YOU_/jquerymx.git jquery
* Notice javascriptmvc is under the jquery folder
4. Learn a little more about submodules ...
http://johnleach.co.uk/words/archives/2008/10/12/323/git-submodules-in-n-easy-steps
5. Make changes in steal or jmvc, and push them back to your fork.
6. Make a pull request to your fork.
// load('jquery/build.js')
load('steal/rhino/steal.js')
var i, fileName, cmd,
plugins = [
"class" ,
"controller",
{
plugin: "controller/subscribe",
exclude: ["jquery/controller/controller.js",
"jquery/class/class.js",
"jquery/lang/lang.js",
"jquery/event/destroyed/destroyed.js",
"jquery/controller/controller.js"]},
"event/default",
"event/destroyed",
"event/drag",
"event/pause",
"event/resize",
{
plugin: "event/drag/limit",
exclude: ["jquery/lang/vector/vector.js", "jquery/event/livehack/livehack.js", "jquery/event/drag/drag.js"]},
{
plugin: "event/drag/scroll",
exclude: ["jquery/dom/within/within.js", "jquery/dom/compare/compare.js", "jquery/event/drop/drop.js","jquery/lang/vector/vector.js", "jquery/event/livehack/livehack.js", "jquery/event/drag/drag.js"]},
{
plugin: "event/drop",
exclude: ["jquery/lang/vector/vector.js", "jquery/event/livehack/livehack.js", "jquery/event/drag/drag.js"]},
"event/hover",
"view/ejs",
"dom/closest",
"dom/compare",
{
plugin: "dom/dimensions",
fileName: "jquery.dimensions.etc.js"
},
"dom/fixture",
"dom/form_params",
"dom/within",
"dom/cur_styles",
"model",
{
plugin: "model/associations",
exclude: ["jquery/class/class.js",
"jquery/lang/lang.js",
"jquery/event/destroyed/destroyed.js",
"jquery/lang/openajax/openajax.js",
"jquery/model/model.js"]
},
{
plugin: "model/backup",
exclude: ["jquery/class/class.js",
"jquery/lang/lang.js",
"jquery/event/destroyed/destroyed.js",
"jquery/lang/openajax/openajax.js",
"jquery/model/model.js"]
},
{
plugin: "model/list",
exclude: ["jquery/class/class.js",
"jquery/lang/lang.js",
"jquery/event/destroyed/destroyed.js",
"jquery/lang/openajax/openajax.js",
"jquery/model/model.js"]
},
{
plugin: "model/list/cookie",
exclude: ["jquery/class/class.js",
"jquery/lang/lang.js",
"jquery/event/destroyed/destroyed.js",
"jquery/lang/openajax/openajax.js",
"jquery/model/model.js",
"jquery/model/list/list.js"]
},
{
plugin: "model/list/local",
exclude: ["jquery/class/class.js",
"jquery/lang/lang.js",
"jquery/event/destroyed/destroyed.js",
"jquery/lang/openajax/openajax.js",
"jquery/model/model.js",
"jquery/model/list/list.js"]
},
{
plugin: "model/validations",
exclude: ["jquery/class/class.js",
"jquery/lang/lang.js",
"jquery/event/destroyed/destroyed.js",
"jquery/lang/openajax/openajax.js",
"jquery/model/model.js"]
},
"view",
"view/ejs",
"view/jaml",
"view/micro",
"view/tmpl"
]
steal.plugins('steal/build/pluginify').then( function(s){
var plugin, exclude, fileDest, fileName;
for(i=0; i<plugins.length; i++){
plugin = plugins[i];
exclude = [];
fileName = null;
if (typeof plugin != "string") {
fileName = plugin.fileName;
exclude = plugin.exclude || [];
plugin = plugin.plugin;
}
fileName = fileName || "jquery."+plugin.replace(/\//g, ".").replace(/dom\./, "").replace(/\_/, "")+".js";
fileDest = "jquery/dist/"+fileName
s.build.pluginify("jquery/"+plugin,{
nojquery: true,
destination: fileDest,
exclude: exclude.length? exclude: false
})
var outBaos = new java.io.ByteArrayOutputStream();
var output = new java.io.PrintStream(outBaos);
runCommand("java", "-jar", "steal/build/scripts/compiler.jar", "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--js", fileDest, {
output: output
});
var minFileDest = fileDest.replace(".js", ".min.js")
new steal.File(minFileDest).save(outBaos.toString());
}
})
/*
for (i = 0; i < plugins.length; i++) {
plugin = plugins[i];
exclude = [];
fileName = null;
if (typeof plugin != "string") {
fileName = plugin.fileName;
exclude = plugin.exclude || [];
plugin = plugin.plugin;
}
fileName = fileName || "jquery." + plugin.replace(/\//g, ".").replace(/dom\./, "").replace(/\_/, "") + ".js";
fileDest = "jquery/dist/" + fileName
// compress
var outBaos = new java.io.ByteArrayOutputStream();
var output = new java.io.PrintStream(outBaos);
runCommand("java", "-jar", "steal/build/scripts/compiler.jar", "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--warning_level", "QUIET", "--js", fileDest, {
output: output
});
var minFileDest = fileDest.replace(".js", ".min.js")
new steal.File(minFileDest).save(outBaos.toString());
print("***" + fileName + " pluginified and compressed")
}*/
// load('jquery/build.js')
load('steal/rhino/steal.js')
// load every plugin in a single app
// get dependency graph
// generate single script
steal.plugins('steal/build/pluginify','steal/build/apps','steal/build/scripts').then( function(s){
var ignore = /\.\w+|test|generate|dist|qunit|fixtures|pages/
var plugins = [];
s.File('jquery').contents(function( name, type, current ) {
if (type !== 'file' && !ignore.test(name)) {
var folder = current+"/"+name;
print(folder);
plugins.push(folder);
steal.File(folder).contents(arguments.callee, folder)
//steal.File(path + "/" + (current ? current + "/" : "") + name).contents(arguments.callee, (current ? current + "/" : "") + name);
}
},"jquery");
// tell it to load all plugins into this page
rhinoLoader = {
callback: function( s ) {
s.plugins.apply(s,plugins);
}
};
steal.win().build_in_progress = true;
print(" LOADING APP ")
var pageSteal = steal.build.open("steal/rhino/empty.html").steal,
steals = pageSteal.total,
//hash of names to steals
files = {},
depends = function(stl, steals){
if(stl.dependencies){
for (var d = 0; d < stl.dependencies.length; d++) {
var depend = stl.dependencies[d];
if(!steals[depend.path]){
steals[depend.path] = true;
print("123 " + depend.path);
//depends(depend, steals);
}
}
}
},
all = function(c){
for(var i =0; i < steals.length; i++){
var pSteal =steals[i];
if(!pSteal.func){
c(pSteal)
}
}
};
print(" LOADED, GETTING DEPENDS");
all(function(stl){
files[stl.path] = stl;
})
all(function(stl){
print(stl.path)
var dependencies = files[stl.path] = [];
if(stl.dependencies){
for (var d = 0; d < stl.dependencies.length; d++) {
var depend = stl.dependencies[d];
if (depend.path !== "jquery/jquery.js") {
dependencies.push(depend.path);
}
}
}
})
steal.File("jquery/dist/standalone").mkdir();
steal.File("jquery/dist/standalone/dependencies.json").save($.toJSON(files));
//get each file ...
print("Creating jquery/dist/standalone/")
var compressor = steal.build.builders.scripts.compressors[ "localClosure"]()
for(var path in files){
if(path == "jquery/jquery.js"){
continue;
}
var content = readFile(path);
var funcContent = s.build.pluginify.getFunction(content);
if(typeof funcContent == "undefined"){
content = "";
} else {
content = "("+s.build.pluginify.getFunction(content)+")(jQuery);";
}
var out = path.replace(/\/\w+\.js/,"").replace(/\//g,".");
content = steal.build.builders.scripts.clean(content);
print(" "+out+"");
content = steal.build.builders.scripts.clean(content);
s.File("jquery/dist/standalone/"+out+".js").save(content);
s.File("jquery/dist/standalone/"+out+".min.js").save(compressor(content));
}
})
\ No newline at end of file
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>jQuery.Class Demo</title>
<style type='text/css'>
body {font-family: verdana}
.tabs, .history_tabs {
padding: 0px; margin: 20px 0 0 0;
}
li {
float: left;
padding: 10px;
background-color: #F6F6F6;
list-style: none;
margin-left: 10px;
}
li a {
color: #1C94C4;
font-weight: bold;
text-decoration: none;
}
li.active a {
color: #F6A828;
cursor: default;
}
.tab {
border: solid 1px #F6A828;
}
/* clearfix from jQueryUI */
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.ui-helper-clearfix { display: inline-block; }
/* required comment for clearfix to work in Opera \*/
* html .ui-helper-clearfix { height:1%; }
.ui-helper-clearfix { display:block; }
/* end clearfix */
</style>
</head>
<body>
<p>jQuery.Class Demo shows a tabs controller extended to work with history.</p>
<div id="demo-html">
<h2>Basic Tabs</h2>
<ul id='tabs1' class='ui-helper-clearfix''>
<li><a href='#tab1'>Tab 1</a></li>
<li><a href='#tab2'>Tab 2</a></li>
<li><a href='#tab3'>Tab 3</a></li>
</ul>
<div id='tab1' class='tab'>Tab 1 Content</div>
<div id='tab2' class='tab'>Tab 2 Content</div>
<div id='tab3' class='tab'>Tab 3 Content</div>
<h2>History Tabs</h2>
<ul id='tabs2' class='ui-helper-clearfix''>
<li><a href='#tab4'>Tab 4</a></li>
<li><a href='#tab5'>Tab 5</a></li>
<li><a href='#tab6'>Tab 6</a></li>
</ul>
<div id='tab4' class='tab'>Tab 4 Content</div>
<div id='tab5' class='tab'>Tab 5 Content</div>
<div id='tab6' class='tab'>Tab 6 Content</div>
</div>
<script type='text/javascript'>DEMO_HTML = document.getElementById('demo-html').innerHTML</script>
<script type='text/javascript' src='../../steal/steal.js'></script>
<script type='text/javascript'>
steal.plugins('jquery/controller/history').start();
</script>
<script type='text/javascript' id="demo-source">
$.Controller.extend("Tabs",{
init : function(){
this.element.children("li:first").addClass('active')
var tab = this.tab;
this.element.children("li:gt(0)").each(function(){
tab($(this)).hide()
})
},
tab : function(li){
return $(li.find("a").attr("href"))
},
"li click" : function(el, ev){
ev.preventDefault();
this.activate(el)
},
activate : function(el){
this.tab(this.find('.active').removeClass('active')).hide()
this.tab(el.addClass('active')).show();
}
})
//inherit from tabs
Tabs.extend("HistoryTabs",{
// ignore clicks
"li click" : function(){},
// listen for history changes
"history.** subscribe" : function(called){
var hash = window.location.hash;
this.activate(hash === '' || hash === '#' ?
this.element.find("li:first") :
this.element.find("a[href="+hash+"]").parent()
)
}
})
//adds the controller to the element
$("#tabs1").tabs();
$("#tabs2").history_tabs();
</script>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
steal
.plugins("jquery/class") //load your app
.plugins('funcunit/qunit').then(function(){
module("jquery/class");
test("Creating", function(){
jQuery.Class.extend("Animal",
{
count: 0,
test: function() {
return this.match ? true : false
}
},
{
init: function() {
this.Class.count++;
this.eyes = false;
}
}
);
Animal.extend("Dog",
{
match : /abc/
},
{
init: function() {
this._super();
},
talk: function() {
return "Woof";
}
});
Dog.extend("Ajax",
{
count : 0
},
{
init: function( hairs ) {
this._super();
this.hairs = hairs;
this.setEyes();
},
setEyes: function() {
this.eyes = true;
}
});
new Dog();
new Animal();
new Animal();
var ajax = new Ajax(1000);
equals(2, Animal.count, "right number of animals");
equals(1, Dog.count, "right number of animals")
ok(Dog.match, "right number of animals")
ok(!Animal.match, "right number of animals")
ok(Dog.test(), "right number of animals")
ok(!Animal.test(), "right number of animals")
equals(1, Ajax.count, "right number of animals")
equals(2, Animal.count, "right number of animals");
equals(true, ajax.eyes, "right number of animals");
equals(1000, ajax.hairs, "right number of animals");
})
test("new instance",function(){
var d = Ajax.newInstance(6);
equals(6, d.hairs);
})
test("namespaces",function(){
var fb = $.Class.extend("Foo.Bar")
ok(Foo.Bar === fb, "returns class")
equals(fb.shortName, "Bar", "short name is right");
equals(fb.fullName, "Foo.Bar","fullName is right")
})
test("setups", function(){
var order = 0,
staticSetup,
staticSetupArgs,
staticInit,
staticInitArgs,
protoSetup,
protoInitArgs,
protoInit,
staticProps = {
setup: function() {
staticSetup = ++order;
staticSetupArgs = arguments;
return ["something"]
},
init: function() {
staticInit = ++order;
staticInitArgs = arguments;
}
},
protoProps = {
setup: function( name ) {
protoSetup = ++order;
return ["Ford: "+name];
},
init: function() {
protoInit = ++order;
protoInitArgs = arguments;
}
}
$.Class.extend("Car",staticProps,protoProps);
var geo = new Car("geo");
equals(staticSetup, 1);
equals(staticInit, 2);
equals(protoSetup, 3);
equals(protoInit, 4);
same($.makeArray(staticInitArgs), ["something"] )
same($.makeArray(protoInitArgs),["Ford: geo"] )
same($.makeArray(staticSetupArgs),[$.Class, "Car",staticProps, protoProps] ,"static construct");
//now see if staticSetup gets called again ...
Car.extend("Truck");
equals(staticSetup, 5, "Static setup is called if overwriting");
});
test("callback", function(){
var curVal = 0;
$.Class.extend("Car",{
show: function( value ) {
equals(curVal, value)
}
},{
show: function( value ) {
}
})
var cb = Car.callback('show');
curVal = 1;
cb(1)
curVal = 2;
var cb2 = Car.callback('show',2)
cb2();
});
test("callback error", 1,function(){
$.Class.extend("Car",{
show: function( value ) {
equals(curVal, value)
}
},{
show: function( value ) {
}
})
try{
Car.callback('huh');
ok(false, "I should have errored")
}catch(e){
ok(true, "Error was thrown")
}
})
test("Creating without extend", function(){
$.Class("Bar",{
ok : function(){
ok(true, "ok called")
}
});
new Bar().ok();
Bar("Foo",{
dude : function(){
ok(true, "dude called")
}
});
new Foo().dude(true);
})
/* Not sure I want to fix this yet.
test("Super in derived when parent doesn't have init", function(){
$.Class("Parent",{
});
Parent("Derived",{
init : function(){
this._super();
}
});
try {
new Derived();
ok(true, "Can call super in init safely")
} catch (e) {
ok(false, "Failed to call super in init with error: " + e)
}
})*/
});
\ No newline at end of file
<html>
<head>
<link rel="stylesheet" type="text/css" href="../../funcunit/qunit/qunit.css" />
</head>
<body>
<h1 id="qunit-header">Class Test Suite</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-test-area"></div>
<script type='text/javascript' src='../../steal/steal.js?jquery/class/class_test.js'></script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>Controller Example</title>
<style type='text/css'>
body {font-family: verdana}
.tabs {
padding: 0px; margin: 0px;
}
.tabs li {
float: left;
padding: 10px;
background-color: #F6F6F6;
list-style: none;
margin-left: 10px;
}
.tabs li a {
color: #1C94C4;
font-weight: bold;
text-decoration: none;
}
.tabs li.active a {
color: #F6A828;
cursor: default;
}
.tab {
border: solid 1px #F6A828;
}
/* clearfix from jQueryUI */
.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
.ui-helper-clearfix { display: inline-block; }
/* required comment for clearfix to work in Opera \*/
* html .ui-helper-clearfix { height:1%; }
.ui-helper-clearfix { display:block; }
/* end clearfix */
</style>
</head>
<body>
<div id="demo-html">
<ul id='tabs' class='ui-helper-clearfix''>
<li><a href='#tab1'>Tab 1</a></li>
<li><a href='#tab2'>Tab 2</a></li>
<li><a href='#tab3'>Tab 3</a></li>
</ul>
<div id='tab1' class='tab'>Tab 1 Content</div>
<div id='tab2' class='tab'>Tab 2 Content</div>
<div id='tab3' class='tab'>Tab 3 Content</div>
</div>
<script type='text/javascript' src='../../steal/steal.js'></script>
<script type='text/javascript'>
steal.plugins("jquery/controller").start();
</script>
<script type='text/javascript' id="demo-source">
// create a new Tabs class
$.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();
}
})
// adds the controller to the element
$("#tabs").tabs();
</script>
</body>
</html>
\ No newline at end of file
This diff is collapsed.
steal.plugins('jquery/controller/subscribe').then(function($){
var hasHistoryManagementSupport = !!(window.history && history.pushState);
if (hasHistoryManagementSupport) {
steal.dev.log("WARNING: The current browser does not support HTML5 History Management.");
} else {
window.onpopstate = function(event) {
OpenAjax.hub.publish("history."+location.href, (event && event.state) || {});
};
setTimeout(function(){
window.onpopstate();
}, 1); // immediately after ready
$.extend($.Controller.prototype, {
redirectTo: function(url, data, title) {
data = data || {};
window.history.pushState(data, title, url);
this.publish("history." + url, data);
}
});
$.Controller.processors["windowpopstate"] = function(el, event, selector, cb) {
$(window).bind("popstate", cb);
return function(){
$(window).unbind("popstate", cb);
}
};
}
})
<html>
<head>
<link rel="stylesheet" type="text/css" href="../../../../funcunit/qunit/qunit.css" />
<style>
body {
margin: 0px; padding: 0px;
}
</style>
<script type='text/javascript' src='../../../../steal/steal.js?steal[app]=jquery/controller/history/html5/qunit'></script>
</head>
<body>
<h1 id="qunit-header">HTML5 History 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>
<html>
<head>
<link rel="stylesheet" type="text/css" href="../../../funcunit/qunit/qunit.css" />
<style>
body {
margin: 0px; padding: 0px;
}
</style>
<script type='text/javascript' src='../../../steal/steal.js?steal[app]=jquery/controller/history/qunit'></script>
</head>
<body>
<h1 id="qunit-header">Model Store Cookie 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>
\ No newline at end of file
steal.plugins('funcunit/qunit','jquery/controller/history').then(function($){
module("jquery/controller/history",{
setup: function(){
}
})
test("Basic getData",function(){
var data = $.Controller.History.getData("#foo/bar&a=b");
equals(data.a,"b")
var data = $.Controller.History.getData("#foo/bar&a=b&c=d");
equals(data.a,"b")
equals(data.c,"d")
})
test("Nested getData",function(){
var data = $.Controller.History.getData("#foo/bar&a[b]=1&a[c]=2");
equals(data.a.b,1)
equals(data.a.c,2)
var data = $.Controller.History.getData("#foo/bar&a[]=1&a[]=2");
equals(data.a[0],1)
equals(data.a[1],2)
var data = $.Controller.History.getData("#foo/bar&a[b][]=1&a[b][]=2");
equals(data.a.b[0],1)
equals(data.a.b[1],2)
var data = $.Controller.History.getData("#foo/bar&a[0]=1&a[1]=2");
equals(data.a[0],1)
equals(data.a[1],2)
})
})
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
//we probably have to have this only describing where the tests are
steal
.plugins('jquery/controller/view','jquery/view/micro') //load your app
.plugins('funcunit/qunit') //load qunit
.then("controller_view_test")
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<div style='margin-top: 10px; padding-left: 5px; position: relative; float: left; border: solid 2px black;' id='styled'>
Here is some content;
</div>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment