forked from tastejs/todomvc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
RYan Eastridge
committed
Sep 19, 2012
1 parent
83cf863
commit 466307f
Showing
12 changed files
with
2,816 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | ||
<title>Thorax • TodoMVC</title> | ||
<link rel="stylesheet" href="../../../assets/base.css"> | ||
<!--[if IE]> | ||
<script src="../../../assets/ie.js"></script> | ||
<![endif]--> | ||
</head> | ||
<body> | ||
<script type="text/template" data-template-name="app"> | ||
<section id="todoapp"> | ||
<header id="header"> | ||
<h1>todos</h1> | ||
<input id="new-todo" placeholder="What needs to be done?" autofocus> | ||
</header> | ||
{{^empty todosCollection}} | ||
<section id="main"> | ||
<input id="toggle-all" type="checkbox"> | ||
<label for="toggle-all">Mark all as complete</label> | ||
{{#collection todosCollection item-view="todo-item" tag="ul" id="todo-list"}} | ||
<div class="view"> | ||
<input class="toggle" type="checkbox" {{#if completed}}checked{{/if}}> | ||
<label>{{title}}</label> | ||
<button class="destroy"></button> | ||
</div> | ||
<input class="edit" value="{{title}}"> | ||
{{/collection}} | ||
</section> | ||
{{view "stats" tag="footer" id="footer"}} | ||
{{/empty}} | ||
</section> | ||
<div id="info"> | ||
<p>Double-click to edit a todo</p> | ||
<p>Written by <a href="https://github.com/addyosmani">Addy Osmani</a> & <a href="https://github.com/beastridge">Ryan Eastridge</a></p> | ||
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p> | ||
</div> | ||
</script> | ||
<script type="text/template" data-template-name="stats"> | ||
<span id="todo-count"><strong>{{remaining}}</strong> {{itemText}} left</span> | ||
<ul id="filters"> | ||
<li> | ||
{{#link "/" class="selected"}}All{{/link}} | ||
</li> | ||
<li> | ||
{{#link "/active"}}Active{{/link}} | ||
</li> | ||
<li> | ||
{{#link "/completed"}}Completed{{/link}} | ||
</li> | ||
</ul> | ||
{{#if completed}} | ||
<button id="clear-completed">Clear completed ({{completed}})</button> | ||
{{/if}} | ||
</script> | ||
<script src="../../../assets/base.js"></script> | ||
<script src="../../../assets/jquery.min.js"></script> | ||
<script src="../../../assets/lodash.min.js"></script> | ||
<script src="../../../assets/handlebars.min.js"></script> | ||
<script src="js/lib/backbone-min.js"></script> | ||
<script src="js/lib/backbone-localstorage.js"></script> | ||
<script src="js/lib/thorax.js"></script> | ||
<script> | ||
// Grab the text from the templates we created above | ||
Thorax.templates = { | ||
app: Handlebars.compile($('script[data-template-name="app"]').html()), | ||
stats: Handlebars.compile($('script[data-template-name="stats"]').html()) | ||
}; | ||
</script> | ||
<script src="js/models/todo.js"></script> | ||
<script src="js/collections/todos.js"></script> | ||
<script src="js/views/todo-item.js"></script> | ||
<script src="js/views/stats.js"></script> | ||
<script src="js/views/app.js"></script> | ||
<script src="js/routers/router.js"></script> | ||
<script src="js/app.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
var app = app || {}; | ||
var ENTER_KEY = 13; | ||
|
||
$(function() { | ||
|
||
// Kick things off by creating the **App**. | ||
var view = new Thorax.Views['app'](); | ||
$('body').append(view.el); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
var app = app || {}; | ||
|
||
(function() { | ||
'use strict'; | ||
|
||
// Todo Collection | ||
// --------------- | ||
|
||
// The collection of todos is backed by *localStorage* instead of a remote | ||
// server. | ||
var TodoList = Backbone.Collection.extend({ | ||
|
||
// Reference to this collection's model. | ||
model: app.Todo, | ||
|
||
// Save all of the todo items under the `"todos"` namespace. | ||
localStorage: new Store('todos-backbone'), | ||
|
||
// Filter down the list of all todo items that are finished. | ||
completed: function() { | ||
return this.filter(function( todo ) { | ||
return todo.get('completed'); | ||
}); | ||
}, | ||
|
||
// Filter down the list to only todo items that are still not finished. | ||
remaining: function() { | ||
return this.without.apply( this, this.completed() ); | ||
}, | ||
|
||
// 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**. | ||
app.Todos = new TodoList(); | ||
|
||
}()); |
84 changes: 84 additions & 0 deletions
84
labs/architecture-examples/thorax/js/lib/backbone-localstorage.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// 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"); | ||
} | ||
}; |
Oops, something went wrong.