UNPKG

todomvc

Version:

> Helping you select an MV\* framework

111 lines (91 loc) 3.1 kB
/*global define, window */ define([ 'knockout', 'config/global', 'models/Todo' ], function (ko, g, Todo) { 'use strict'; // our main view model var ViewModel = function (todos) { var self = this; // map array of passed in todos to an observableArray of Todo objects self.todos = ko.observableArray(ko.utils.arrayMap(todos, function (todo) { return new Todo(todo.title, todo.completed); })); // store the new todo value being entered self.current = ko.observable(); // add a new todo, when enter key is pressed self.add = function () { var current = self.current().trim(); if (current) { self.todos.push(new Todo(current)); self.current(''); } }; // remove a single todo self.remove = function (todo) { self.todos.remove(todo); }; // remove all completed todos self.removeCompleted = function () { self.todos.remove(function (todo) { return todo.completed(); }); }; // edit an item self.editItem = function (item) { item.editing(true); }; // stop editing an item. Remove the item, if it is now empty self.stopEditing = function (item) { item.editing(false); var title = item.title(); var trimmedTitle = title.trim(); // Observable value changes are not triggered if they're consisting of whitespaces only // Therefore we've to compare untrimmed version with a trimmed one to chech whether anything changed // And if yes, we've to set the new value manually if (title !== trimmedTitle) { item.title(trimmedTitle); } if (!trimmedTitle) { self.remove(item); } }; // count of all completed todos self.completedCount = ko.computed(function () { return ko.utils.arrayFilter(self.todos(), function (todo) { return todo.completed(); }).length; }); // count of todos that are not complete 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.completed(newValue); }); } }); // helper function to keep expressions out of markup self.getLabel = function (count) { return ko.utils.unwrapObservable(count) === 1 ? 'item' : 'items'; }; // internal computed observable that fires whenever anything changes in our todos ko.computed(function () { // store a clean copy to local storage, which also creates a dependency on the observableArray and all observables in each item window.localStorage.setItem(g.localStorageItem, ko.toJSON(self.todos)); }).extend({ rateLimit: { timeout: 500, method: 'notifyWhenChangesStop' } }); // save at most twice per second }; return ViewModel; });