todomvc
Version:
> Helping you select an MV\* framework
139 lines (120 loc) • 5.2 kB
JavaScript
define([
"dojo/_base/array",
"dojo/_base/lang",
"dojox/mvc/getStateful"
], function(array, lang, getStateful){
var defaultData = {
// summary:
// Data used when there is no saved data.
// The same structure is used to save data to localStrage (when the page is unloaded).
// id: String
// The ID of saved data, used in Dojo Object Store as well as in localStorage that the Dojo Object Store uses.
id: "todos-dojo",
// todos: Object[]
// The todo items.
todos : [],
// incomplete: Number
// The count of incomplete todo items.
incomplete: 0,
// complete: Number
// The count of complete todo items.
complete: 0
};
var seq = 0; // The sequence number to generate unique IDs of todo items
return function(/*Object*/ data){
// summary:
// The data model for TodoMVC.
// description:
// This data model does:
//
// - Keep complete/incomplete properties up to date
// - Add unique ID to new todo items
//
// data: Object
// The plain data, coming from Dojo Object Store.
function assignPropertiesToNewItem(/*dojo/Stateful*/ item){
// summary:
// Add additional properties to a todo item.
// description:
// This function does:
//
// - Add unique ID to the given todo item
// - Add setter function for completed property to the given todo item
// item: dojo/Stateful
// The todo item.
lang.mixin(item, {
_completedSetter: function(/*Boolean*/ value){
// summary
// The setter function for completed property, which keeps complete/incomplete properties of the data model up to date.
// value: Boolean
// True means this todo item is completed. Otherwise means this todo item is incomplete.
if(this.completed ^ value){ // Update is done only if there is a flip in value
// If the todo item is turned to completed state, increase the count of completed items.
// If the todo item is turned to incomplete state, decrease the count of completed items.
statefulData.set("complete", statefulData.get("complete") + (value ? 1 : -1));
}
this.completed = value; // Assign the new value
},
// uniqueId: String
// The unique ID of the todo item.
uniqueId: "TODO-" + seq++
});
}
var statefulData = getStateful(data || defaultData); // Convert a plain object to dojo/Stateful, hierarchically. Use the default data if (lastly saved) data is not there
array.forEach(statefulData.todos, assignPropertiesToNewItem); // Add additional properties to todo items
return lang.mixin(statefulData, {
_elementWatchHandle: statefulData.todos.watchElements(function(/*Number*/ idx, /*dojo/Stateful[]*/ removals, /*dojo/Stateful[]*/adds){
// summary:
// The dojox/mvc/StatefulArray watch callback for adds/removals of todo items.
// description:
// This callback does:
//
// - Keep complete/incomplete properties up to date, upon adds/removals of todo items
// - Add unique ID to new todo items
// - Add setter function for completed property to new todo items
//
// idx: Number
// The array index where adds/removals happened at.
// removals: dojo/Stateful[]
// The removed todo items.
// adds: dojo/Stateful[]
// The added todo items.
var complete = statefulData.get("complete");
array.forEach(removals, function(item){ complete -= !!item.completed; }); // If completed items are removed, decrease the count of completed items
array.forEach(adds, function(item){ complete += !!item.completed; }); // If completed items are added, increase the count of completed items
statefulData.set("complete", complete);
statefulData.set("incomplete", statefulData.todos.get("length") - complete);
array.forEach(adds, assignPropertiesToNewItem); // Add additional properties to newly added todo items
}),
_incompleteSetter: function(/*Number*/ value){
// summary:
// dojo/Stateful setter function for incomplete property.
// description:
// This setter function keeps complete property up to date.
// value: Number
// The new count of incomplete todo items.
var changed = this.incomplete != value;
this.incomplete = value; // Assign the new value
if(changed){ // Update is done only if there is a change in value
this.set("complete", this.todos.get("length") - value); // Make the count of complete items reflect the new count of incomplete items
}
},
_completeSetter: function(/*Number*/ value){
// summary:
// dojo/Stateful setter function for complete property.
// description:
// This setter function keeps incomplete property up to date.
// value: Number
// The new count of complete todo items.
var changed = this.complete != value;
this.complete = value; // Assign the new value
if(changed){ // Update is done only if there is a change in value
this.set("incomplete", this.todos.get("length") - value); // Make the count of incomplete items reflect the new count of complete items
}
},
destroy: function(){
this._elementWatchHandle.remove(); // Stop watching for adds/removals of todo items
}
});
};
});