Commit 083ba9fe authored by Kevin Malakoff's avatar Kevin Malakoff Committed by Sam Saccone

Update Knockback to 1.0.0 and simplified.

parent 24f9d0df
node_modules/knockback/* node_modules/backbone/*
!node_modules/knockback/knockback.js !node_modules/backbone/backbone.js
!node_modules/knockback/node_modules
node_modules/knockback/node_modules/backbone/*
!node_modules/knockback/node_modules/backbone/backbone.js
node_modules/knockback/node_modules/underscore/* node_modules/backbone.localStorage/*
!node_modules/knockback/node_modules/underscore/underscore.js !node_modules/backbone.localStorage/backbone.localStorage.js
node_modules/knockback/node_modules/knockout/*
!node_modules/knockback/node_modules/knockout/build
node_modules/knockback/node_modules/knockout/build/*
!node_modules/knockback/node_modules/knockout/build/output
node_modules/knockback/node_modules/knockout/build/output/*
!node_modules/knockback/node_modules/knockout/build/output/knockout-latest.debug.js
node_modules/jquery/* node_modules/jquery/*
!node_modules/jquery/dist !node_modules/jquery/dist
node_modules/jquery/dist/* node_modules/jquery/dist/*
!node_modules/jquery/dist/jquery.js !node_modules/jquery/dist/jquery.js
node_modules/knockback/*
!node_modules/knockback/knockback.js
node_modules/knockout/*
!node_modules/knockout/build
node_modules/knockout/build/*
!node_modules/knockout/build/output
node_modules/knockout/build/output/*
!node_modules/knockout/build/output/knockout-latest.debug.js
node_modules/todomvc-app-css/* node_modules/todomvc-app-css/*
!node_modules/todomvc-app-css/index.css !node_modules/todomvc-app-css/index.css
node_modules/todomvc-common/* node_modules/todomvc-common/*
!node_modules/todomvc-common/base.css !node_modules/todomvc-common/base.css
!node_modules/todomvc-common/base.js !node_modules/todomvc-common/base.js
node_modules/underscore/*
!node_modules/underscore/underscore.js
...@@ -7,28 +7,28 @@ ...@@ -7,28 +7,28 @@
<link rel="stylesheet" href="node_modules/todomvc-app-css/index.css"> <link rel="stylesheet" href="node_modules/todomvc-app-css/index.css">
</head> </head>
<body> <body>
<section id="todoapp" kb-inject="AppViewModel"> <section class="todoapp" kb-inject="AppViewModel">
<header id="header"> <header class="header">
<h1>todos</h1> <h1>todos</h1>
<input id="new-todo" type="text" data-bind="value: title, valueUpdate: 'afterkeydown', event: {keyup: onAddTodo}" placeholder="What needs to be done?" autofocus> <input class="new-todo" type="text" data-bind="value: title, valueUpdate: 'afterkeydown', event: {keyup: onAddTodo}" placeholder="What needs to be done?" autofocus>
</header> </header>
<section id="main" data-bind="block: tasks_exist"> <section class="main" data-bind="visible: tasks_exist">
<input id="toggle-all" type="checkbox" data-bind="checked: all_completed"> <input class="toggle-all" type="checkbox" data-bind="checked: all_completed">
<label for="toggle-all">Mark all as complete</label> <label for="toggle-all">Mark all as complete</label>
<ul id="todo-list" data-bind="foreach: todos"> <ul class="todo-list" data-bind="foreach: todos">
<li data-bind="css: {completed: completed, editing: editing}"> <li data-bind="css: {completed: completed, editing: editing}">
<div class="view" data-bind="event: {dblclick: onCheckEditBegin}"> <div class="view" data-bind="event: {dblclick: onCheckEditBegin}">
<input class="toggle" type="checkbox" data-bind="checked: completed" checked> <input class="toggle" type="checkbox" data-bind="checked: completed" checked>
<label data-bind="text: title"></label> <label data-bind="text: title"></label>
<button class="destroy" data-bind="click: onDestroyTodo"></button> <button class="destroy" data-bind="click: onDestroy"></button>
</div> </div>
<input class="edit" type="text" data-bind="value: title, selectAndFocus: editing, event: {blur: onCheckEditEnd, keyup: onCheckEditEnd}"> <input class="edit" type="text" data-bind="value: edit_title, event: {blur: onCheckEditEnd, keyup: onCheckEditEnd}">
</li> </li>
</ul> </ul>
</section> </section>
<footer id="footer" data-bind="block: tasks_exist"> <footer class="footer" data-bind="visible: tasks_exist">
<span id="todo-count" data-bind="html: loc.remaining_message"></span> <span class="todo-count" data-bind="html: loc.remaining_message"></span>
<ul id="filters"> <ul class="filters">
<li> <li>
<a href="#/" data-bind="css: {selected: list_filter_mode()==''}">All</a> <a href="#/" data-bind="css: {selected: list_filter_mode()==''}">All</a>
</li> </li>
...@@ -39,10 +39,10 @@ ...@@ -39,10 +39,10 @@
<a href="#/completed" data-bind="css: {selected: list_filter_mode()=='completed'}">Completed</a> <a href="#/completed" data-bind="css: {selected: list_filter_mode()=='completed'}">Completed</a>
</li> </li>
</ul> </ul>
<button id="clear-completed" data-bind="text: loc.clear_message, block: loc.clear_message, click: onDestroyCompleted"></button> <button class="clear-completed" data-bind="text: loc.clear_message, visible: loc.clear_message, click: onClearCompleted"></button>
</footer> </footer>
</section> </section>
<footer id="info"> <footer class="info">
<p>Double-click to edit a todo</p> <p>Double-click to edit a todo</p>
<p>Created by <a href="https://github.com/kmalakoff">Kevin Malakoff</a>. <br/> <p>Created by <a href="https://github.com/kmalakoff">Kevin Malakoff</a>. <br/>
Please try out the <a href="http://kmalakoff.github.com/knockback-todos-app/">enhanced version</a> <br/> Please try out the <a href="http://kmalakoff.github.com/knockback-todos-app/">enhanced version</a> <br/>
...@@ -54,15 +54,13 @@ ...@@ -54,15 +54,13 @@
<!-- App Dependencies --> <!-- App Dependencies -->
<script src="node_modules/todomvc-common/base.js"></script> <script src="node_modules/todomvc-common/base.js"></script>
<script src="node_modules/jquery/dist/jquery.js"></script> <script src="node_modules/jquery/dist/jquery.js"></script>
<script src="node_modules/knockback/node_modules/underscore/underscore.js"></script> <script src="node_modules/underscore/underscore.js"></script>
<script src="node_modules/knockback/node_modules/backbone/backbone.js"></script> <script src="node_modules/backbone/backbone.js"></script>
<script src="node_modules/knockback/node_modules/knockout/build/output/knockout-latest.debug.js"></script> <script src="node_modules/knockout/build/output/knockout-latest.debug.js"></script>
<script src="node_modules/knockback/knockback.js"></script> <script src="node_modules/knockback/knockback.js"></script>
<script src="node_modules/backbone.localStorage/backbone.localStorage.js"></script> <script src="node_modules/backbone.localstorage/backbone.localStorage.js"></script>
<!-- App and Components --> <!-- App and Components -->
<script src="js/lib/knockout-extended-bindings.js"></script>
<script src="js/models/todo.js"></script>
<script src="js/models/todo_collection.js"></script> <script src="js/models/todo_collection.js"></script>
<script src="js/viewmodels/todo.js"></script> <script src="js/viewmodels/todo.js"></script>
<script src="js/viewmodels/app.js"></script> <script src="js/viewmodels/app.js"></script>
......
// Generated by CoffeeScript 1.8.0
(function() {
ko.bindingHandlers.dblclick = {
init: function(element, value_accessor) {
return $(element).dblclick(ko.utils.unwrapObservable(value_accessor()));
}
};
ko.bindingHandlers.block = {
update: function(element, value_accessor) {
return element.style.display = ko.utils.unwrapObservable(value_accessor()) ? 'block' : 'none';
}
};
ko.bindingHandlers.selectAndFocus = {
init: function(element, value_accessor, all_bindings_accessor) {
ko.bindingHandlers.hasfocus.init(element, value_accessor, all_bindings_accessor);
return ko.utils.registerEventHandler(element, 'focus', function() {
return element.select();
});
},
update: function(element, value_accessor) {
ko.utils.unwrapObservable(value_accessor());
return _.defer(function() {
return ko.bindingHandlers.hasfocus.update(element, value_accessor);
});
}
};
}).call(this);
// Generated by CoffeeScript 1.8.0
(function() {
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
window.Todo = (function(_super) {
__extends(Todo, _super);
function Todo() {
return Todo.__super__.constructor.apply(this, arguments);
}
Todo.prototype.completed = function(completed) {
if (arguments.length === 0) {
return !!this.get('completed');
}
return this.save({
completed: completed ? new Date() : null
});
};
return Todo;
})(Backbone.Model);
}).call(this);
// Generated by CoffeeScript 1.8.0 // Generated by CoffeeScript 1.10.0
(function() { (function() {
var __hasProp = {}.hasOwnProperty, var extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; hasProp = {}.hasOwnProperty;
window.TodoCollection = (function(_super) { window.TodoCollection = (function(superClass) {
__extends(TodoCollection, _super); extend(TodoCollection, superClass);
function TodoCollection() { function TodoCollection() {
return TodoCollection.__super__.constructor.apply(this, arguments); return TodoCollection.__super__.constructor.apply(this, arguments);
...@@ -12,35 +12,6 @@ ...@@ -12,35 +12,6 @@
TodoCollection.prototype.localStorage = new Store('todos-knockback'); TodoCollection.prototype.localStorage = new Store('todos-knockback');
TodoCollection.prototype.model = Todo;
TodoCollection.prototype.completedCount = function() {
return this.models.reduce((function(prev, cur) {
return prev + (cur.completed() ? 1 : 0);
}), 0);
};
TodoCollection.prototype.remainingCount = function() {
return this.models.length - this.completedCount();
};
TodoCollection.prototype.completeAll = function(completed) {
return this.each(function(todo) {
return todo.completed(completed);
});
};
TodoCollection.prototype.destroyCompleted = function() {
var completed_tasks, model, _i, _len;
completed_tasks = this.filter(function(todo) {
return todo.completed();
});
for (_i = 0, _len = completed_tasks.length; _i < _len; _i++) {
model = completed_tasks[_i];
model.destroy();
}
};
return TodoCollection; return TodoCollection;
})(Backbone.Collection); })(Backbone.Collection);
......
// Generated by CoffeeScript 1.8.0 // Generated by CoffeeScript 1.10.0
(function() { (function() {
var ENTER_KEY; var ENTER_KEY,
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
ENTER_KEY = 13; ENTER_KEY = 13;
window.AppViewModel = function() { window.AppViewModel = (function() {
var filter_fn, router; function AppViewModel() {
this.collections = { this.onClearCompleted = bind(this.onClearCompleted, this);
todos: new TodoCollection() this.onAddTodo = bind(this.onAddTodo, this);
}; var filter_fn, fn, i, len, ref, route, router;
this.collections.todos.fetch();
this.list_filter_mode = ko.observable(''); this.list_filter_mode = ko.observable('');
filter_fn = ko.computed((function(_this) { filter_fn = ko.computed((function(_this) {
return function() { return function() {
switch (_this.list_filter_mode()) { switch (_this.list_filter_mode()) {
case 'active': case 'active':
return function(model) { return (function(model) {
return !model.completed(); return !model.get('completed');
}; });
case 'completed': case 'completed':
return function(model) { return (function(model) {
return model.completed(); return model.get('completed');
}; });
default: default:
return function() { return (function() {
return true; return true;
}; });
} }
}; };
})(this)); })(this));
this.todos = kb.collectionObservable(this.collections.todos, { this.todos = kb.collectionObservable(new TodoCollection(), TodoViewModel, {
view_model: TodoViewModel,
filters: filter_fn filters: filter_fn
}); });
this.todos_changed = kb.triggeredObservable(this.collections.todos, 'change add remove'); this.todos.collection().fetch();
this._todos_changed = kb.triggeredObservable(this.todos.collection(), 'change add remove');
this.tasks_exist = ko.computed((function(_this) { this.tasks_exist = ko.computed((function(_this) {
return function() { return function() {
_this.todos_changed(); _this._todos_changed();
return !!_this.collections.todos.length; return !!_this.todos.collection().models.length;
}; };
})(this)); })(this));
this.title = ko.observable(''); this.title = ko.observable('');
this.onAddTodo = (function(_this) { this.completed_count = ko.computed((function(_this) {
return function(view_model, event) {
if (!$.trim(_this.title()) || (event.keyCode !== ENTER_KEY)) {
return true;
}
_this.collections.todos.create({
title: $.trim(_this.title())
});
return _this.title('');
};
})(this);
this.remaining_count = ko.computed((function(_this) {
return function() { return function() {
_this.todos_changed(); _this._todos_changed();
return _this.collections.todos.remainingCount(); return _this.todos.collection().filter(function(model) {
return model.get('completed');
}).length;
}; };
})(this)); })(this));
this.completed_count = ko.computed((function(_this) { this.remaining_count = ko.computed((function(_this) {
return function() { return function() {
_this.todos_changed(); _this._todos_changed();
return _this.collections.todos.completedCount(); return _this.todos.collection().length - _this.completed_count();
}; };
})(this)); })(this));
this.all_completed = ko.computed({ this.all_completed = ko.computed({
...@@ -72,15 +63,14 @@ ...@@ -72,15 +63,14 @@
})(this), })(this),
write: (function(_this) { write: (function(_this) {
return function(completed) { return function(completed) {
return _this.collections.todos.completeAll(completed); return _this.todos.collection().each(function(model) {
return model.save({
completed: completed
});
});
}; };
})(this) })(this)
}); });
this.onDestroyCompleted = (function(_this) {
return function() {
return _this.collections.todos.destroyCompleted();
};
})(this);
this.loc = { this.loc = {
remaining_message: ko.computed((function(_this) { remaining_message: ko.computed((function(_this) {
return function() { return function() {
...@@ -89,9 +79,8 @@ ...@@ -89,9 +79,8 @@
})(this)), })(this)),
clear_message: ko.computed((function(_this) { clear_message: ko.computed((function(_this) {
return function() { return function() {
var count; if (_this.completed_count()) {
if ((count = _this.completed_count())) { return 'Clear completed';
return "Clear completed";
} else { } else {
return ''; return '';
} }
...@@ -99,22 +88,46 @@ ...@@ -99,22 +88,46 @@
})(this)) })(this))
}; };
router = new Backbone.Router; router = new Backbone.Router;
router.route('', null, (function(_this) { ref = ['', 'active', 'completed'];
return function() { fn = (function(_this) {
return _this.list_filter_mode(''); return function(route) {
}; return router.route(route, null, function() {
})(this)); return _this.list_filter_mode(route);
router.route('active', null, (function(_this) { });
return function() {
return _this.list_filter_mode('active');
};
})(this));
router.route('completed', null, (function(_this) {
return function() {
return _this.list_filter_mode('completed');
}; };
})(this)); })(this);
for (i = 0, len = ref.length; i < len; i++) {
route = ref[i];
fn(route);
}
Backbone.history.start(); Backbone.history.start();
}
AppViewModel.prototype.onAddTodo = function(vm, event) {
if (!$.trim(this.title()) || (event.keyCode !== ENTER_KEY)) {
return;
}
this.todos.collection().create({
title: $.trim(this.title())
});
return this.title('');
};
AppViewModel.prototype.onClearCompleted = function() {
var i, len, model, ref, results;
ref = this.todos.collection().filter(function(model) {
return model.get('completed');
});
results = [];
for (i = 0, len = ref.length; i < len; i++) {
model = ref[i];
results.push(model.destroy());
}
return results;
}; };
return AppViewModel;
})();
}).call(this); }).call(this);
// Generated by CoffeeScript 1.8.0 // Generated by CoffeeScript 1.10.0
(function() { (function() {
window.TodoViewModel = function(model) { var ENTER_KEY, ESCAPE_KEY,
var ENTER_KEY, ESCAPE_KEY; bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
hasProp = {}.hasOwnProperty;
ENTER_KEY = 13; ENTER_KEY = 13;
ESCAPE_KEY = 27; ESCAPE_KEY = 27;
this.editing = ko.observable(false);
this.completed = kb.observable(model, { window.TodoViewModel = (function(superClass) {
key: 'completed', extend(TodoViewModel, superClass);
read: (function() {
return model.completed(); function TodoViewModel(model, options) {
}), this.onCheckEditEnd = bind(this.onCheckEditEnd, this);
write: (function(completed) { this.onCheckEditBegin = bind(this.onCheckEditBegin, this);
return model.completed(completed); this.onDestroy = bind(this.onDestroy, this);
}) TodoViewModel.__super__.constructor.call(this, model, {
}, this); requires: ['title', 'completed']
this.title = kb.observable(model, { }, options);
key: 'title', this.completed.subscribe((function(_this) {
write: ((function(_this) { return function(completed) {
return function(title) { return _this.model().save({
if ($.trim(title)) { completed: completed
model.save({
title: $.trim(title)
});
} else {
_.defer(function() {
return model.destroy();
}); });
}
return _this.editing(false);
}; };
})(this)) })(this));
}, this); this.edit_title = ko.observable();
this.onDestroyTodo = (function(_this) { this.editing = ko.observable(false);
return function() { }
return model.destroy();
TodoViewModel.prototype.onDestroy = function() {
return this.model().destroy();
}; };
})(this);
this.onCheckEditBegin = (function(_this) { TodoViewModel.prototype.onCheckEditBegin = function() {
return function() { if (this.editing()) {
if (!_this.editing()) { return;
_this.editing(true);
return $('.todo-input').focus();
} }
this.edit_title(this.title());
this.editing(true);
return $('.todo-input').focus();
}; };
})(this);
this.onCheckEditEnd = (function(_this) { TodoViewModel.prototype.onCheckEditEnd = function(vm, event) {
return function(view_model, event) { var title;
if (!this.editing()) {
return;
}
if (event.keyCode === ESCAPE_KEY) { if (event.keyCode === ESCAPE_KEY) {
_this.editing(false); this.editing(false);
} }
if ((event.keyCode === ENTER_KEY) || (event.type === 'blur')) { if ((event.keyCode === ENTER_KEY) || (event.type === 'blur')) {
$('.todo-input').blur(); $('.todo-input').blur();
return _this.editing(false); title = this.edit_title();
} if ($.trim(title)) {
this.model().set({
title: title
}).save({
title: $.trim(title)
});
} else {
_.defer((function(_this) {
return function() {
return _this.model().destroy();
}; };
})(this); })(this));
}
return this.editing(false);
}
}; };
return TodoViewModel;
})(kb.ViewModel);
}).call(this); }).call(this);
/*! /*!
* jQuery JavaScript Library v2.1.3 * jQuery JavaScript Library v2.1.4
* http://jquery.com/ * http://jquery.com/
* *
* Includes Sizzle.js * Includes Sizzle.js
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Released under the MIT license * Released under the MIT license
* http://jquery.org/license * http://jquery.org/license
* *
* Date: 2014-12-18T15:11Z * Date: 2015-04-28T16:01Z
*/ */
(function( global, factory ) { (function( global, factory ) {
...@@ -67,7 +67,7 @@ var ...@@ -67,7 +67,7 @@ var
// Use the correct document accordingly with window argument (sandbox) // Use the correct document accordingly with window argument (sandbox)
document = window.document, document = window.document,
version = "2.1.3", version = "2.1.4",
// Define a local copy of jQuery // Define a local copy of jQuery
jQuery = function( selector, context ) { jQuery = function( selector, context ) {
...@@ -531,7 +531,12 @@ jQuery.each("Boolean Number String Function Array Date RegExp Object Error".spli ...@@ -531,7 +531,12 @@ jQuery.each("Boolean Number String Function Array Date RegExp Object Error".spli
}); });
function isArraylike( obj ) { function isArraylike( obj ) {
var length = obj.length,
// Support: iOS 8.2 (not reproducible in simulator)
// `in` check used to prevent JIT error (gh-2145)
// hasOwn isn't used here due to false negatives
// regarding Nodelist length in IE
var length = "length" in obj && obj.length,
type = jQuery.type( obj ); type = jQuery.type( obj );
if ( type === "function" || jQuery.isWindow( obj ) ) { if ( type === "function" || jQuery.isWindow( obj ) ) {
......
...@@ -114,7 +114,12 @@ ...@@ -114,7 +114,12 @@
})({}); })({});
if (location.hostname === 'todomvc.com') { if (location.hostname === 'todomvc.com') {
window._gaq = [['_setAccount','UA-31081062-1'],['_trackPageview']];(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];g.src='//www.google-analytics.com/ga.js';s.parentNode.insertBefore(g,s)}(document,'script')); (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-31081062-1', 'auto');
ga('send', 'pageview');
} }
/* jshint ignore:end */ /* jshint ignore:end */
...@@ -228,7 +233,7 @@ ...@@ -228,7 +233,7 @@
xhr.onload = function (e) { xhr.onload = function (e) {
var parsedResponse = JSON.parse(e.target.responseText); var parsedResponse = JSON.parse(e.target.responseText);
if (parsedResponse instanceof Array) { if (parsedResponse instanceof Array) {
var count = parsedResponse.length var count = parsedResponse.length;
if (count !== 0) { if (count !== 0) {
issueLink.innerHTML = 'This app has ' + count + ' open issues'; issueLink.innerHTML = 'This app has ' + count + ' open issues';
document.getElementById('issue-count').style.display = 'inline'; document.getElementById('issue-count').style.display = 'inline';
......
{ {
"private": true, "private": true,
"dependencies": { "dependencies": {
"backbone.localStorage": "^1.1.3", "backbone": "^1.2.3",
"jquery": "^2.0.0", "backbone.localstorage": "^1.1.16",
"knockback": "^0.20.5", "jquery": "^2.1.4",
"todomvc-app-css": "^1.0.0", "knockback": "^1.0.0",
"todomvc-common": "^1.0.1" "knockout": "^3.3.0",
"todomvc-app-css": "^2.0.1",
"todomvc-common": "^1.0.2",
"underscore": "^1.8.3"
} }
} }
# Add custom handlers to Knockout.js - adapted from Knockout.js Todos app: https://github.com/ashish01/knockoutjs-todos
ko.bindingHandlers.dblclick =
init: (element, value_accessor) -> $(element).dblclick(ko.utils.unwrapObservable(value_accessor()))
ko.bindingHandlers.block =
update: (element, value_accessor) -> element.style.display = if ko.utils.unwrapObservable(value_accessor()) then 'block' else 'none'
ko.bindingHandlers.selectAndFocus =
init: (element, value_accessor, all_bindings_accessor) ->
ko.bindingHandlers.hasfocus.init(element, value_accessor, all_bindings_accessor)
ko.utils.registerEventHandler(element, 'focus', -> element.select())
update: (element, value_accessor) ->
ko.utils.unwrapObservable(value_accessor()) # create dependency
_.defer -> ko.bindingHandlers.hasfocus.update(element, value_accessor)
\ No newline at end of file
class window.Todo extends Backbone.Model
completed: (completed) ->
return !!@get('completed') if arguments.length is 0 # getter
@save({completed: if completed then new Date() else null}) # setter
\ No newline at end of file
class window.TodoCollection extends Backbone.Collection class window.TodoCollection extends Backbone.Collection
localStorage: new Store('todos-knockback') # Save all of the todos under the "todos-knockback" namespace. localStorage: new Store('todos-knockback') # Save all of the todos under the "todos-knockback" namespace.
model: Todo
completedCount: -> @models.reduce(((prev,cur)-> return prev + if cur.completed() then 1 else 0), 0)
remainingCount: -> @models.length - @completedCount()
completeAll: (completed) -> @each((todo) -> todo.completed(completed))
destroyCompleted: ->
completed_tasks = @filter((todo) -> return todo.completed())
model.destroy() for model in completed_tasks
return
\ No newline at end of file
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