Commit 2cb3d139 authored by Aaron Boushley's avatar Aaron Boushley

Merge pull request #52 from rniemeyer/knockout-updates

KnockoutJS: add "Mark all as complete" checkbox and "Press Enter" tooltip.
parents 071564bd 78ed736a
......@@ -12,9 +12,13 @@
<div class="content">
<div id="create-todo">
<input id="new-todo" data-bind="value: current, valueUpdate: 'afterkeydown', enterKey: add" placeholder="What needs to be done?" />
<span class="ui-tooltip-top" style="display: none;">Press Enter to save this task</span>
<span class="ui-tooltip-top" data-bind="visible: showTooltip" style="display: none;">Press Enter to save this task</span>
</div>
<div id="todos">
<div data-bind="visible: todos().length">
<input id="check-all" class="check" type="checkbox" data-bind="checked: allCompleted" />
<label for="check-all">Mark all as complete</label>
</div>
<ul id="todo-list" data-bind="foreach: todos">
<li data-bind="css: { editing: editing }">
<div class="todo" data-bind="css: { done : done }">
......
......@@ -40,51 +40,86 @@
var ViewModel = function(todos) {
var self = this;
//map array of passed in todos to an observableArray of Todo objects
this.todos = ko.observableArray(ko.utils.arrayMap(todos, function(todo) {
self.todos = ko.observableArray(ko.utils.arrayMap(todos, function(todo) {
return new Todo(todo.content, todo.done);
}));
//store the new todo value being entered
this.current = ko.observable();
self.current = ko.observable();
//add a new todo, when enter key is pressed
this.add = function (data, event) {
self.add = function (data, event) {
var newTodo = new Todo(self.current());
self.todos.push(newTodo);
self.current("");
};
//remove a single todo
this.remove = function (todo) {
self.remove = function (todo) {
self.todos.remove(todo);
};
//remove all completed todos
this.removeCompleted = function () {
self.removeCompleted = function () {
self.todos.remove(function(todo) {
return todo.done();
});
};
//count of all completed todos
this.completedCount = ko.computed(function () {
self.completedCount = ko.computed(function () {
return ko.utils.arrayFilter(self.todos(), function(todo) {
return todo.done();
}).length;
});
//count of todos that are not complete
this.remainingCount = ko.computed(function () {
self.remainingCount = ko.computed(function () {
return self.todos().length - self.completedCount();
});
//writeable computed observable to handle marking all complete/incomplete
self.allCompleted = ko.computed({
//always return true/false based on the done flag of all todos
read: function() {
return !self.remainingCount();
},
//set all todos to the written value (true/false)
write: function(newValue) {
ko.utils.arrayForEach(self.todos(), function(todo) {
//set even if value is the same, as subscribers are not notified in that case
todo.done(newValue);
});
}
});
//track whether the tooltip should be shown
self.showTooltip = ko.observable(false);
self.showTooltip.setTrue = function() { self.showTooltip(true); }; //avoid an anonymous function each time
//watch the current value
self.current.subscribe(function(newValue) {
//if the value was just updated, then the tooltip should not be shown
self.showTooltip(false);
//clear the current timer, as it is actively being updated
if (self.showTooltip.timer) {
clearTimeout(self.showTooltip.timer);
}
//if there is a value and then show the tooltip after 1 second
if (newValue) {
self.showTooltip.timer = setTimeout(self.showTooltip.setTrue, 1000);
}
});
//helper function to keep expressions out of markup
this.getLabel = function(count) {
self.getLabel = function(count) {
return ko.utils.unwrapObservable(count) === 1 ? "item" : "items";
};
//computed observable that fires whenever anything changes in our todos
this.isDirty = ko.computed(function() {
//internal computed observable that fires whenever anything changes in our todos
ko.computed(function() {
//get a clean copy of the todos, which also creates a dependency on the observableArray and all observables in each item
var todos = ko.toJS(self.todos);
......
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