forked from tastejs/todomvc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.js
152 lines (122 loc) · 3.34 KB
/
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*global blocks */
(function () {
'use strict';
var ENTER_KEY = 13;
var ESCAPE_KEY = 27;
var App = blocks.Application();
var Todo = App.Model({
title: App.Property(),
completed: App.Property(),
editing: blocks.observable(),
init: function () {
var collection = this.collection();
// collection is undefined when a Todo is still not part of the Todos collection
if (collection) {
// save to Local Storage on each attribute change
this.title.on('change', collection.save);
this.completed.on('change', collection.save);
}
this.title.on('change', function (newValue) {
this.title((newValue || '').trim());
});
},
toggleComplete: function () {
this.completed(!this.completed());
},
edit: function () {
this.lastValue = this.title();
this.editing(true);
},
closeEdit: function () {
if (this.title()) {
this.editing(false);
} else {
this.destroy();
}
},
handleAction: function (e) {
if (e.which === ENTER_KEY) {
this.closeEdit();
} else if (e.which === ESCAPE_KEY) {
this.title(this.lastValue);
this.editing(false);
}
}
});
var Todos = App.Collection(Todo, {
remaining: blocks.observable(),
init: function () {
this
// load the data from the Local Storage
.reset(JSON.parse(localStorage.getItem('todos-jsblocks')) || [])
// save to Local Storage on each item add or remove
.on('add remove', this.save)
.updateRemaining();
},
// set all todos as completed
toggleAll: function () {
var complete = this.remaining() === 0 ? false : true;
this.each(function (todo) {
todo.completed(complete);
});
},
// remove all completed todos
clearCompleted: function () {
this.removeAll(function (todo) {
return todo.completed();
});
},
// saves all data back to the Local Storage
save: function () {
var result = [];
blocks.each(this(), function (model) {
result.push(model.dataItem());
});
localStorage.setItem('todos-jsblocks', JSON.stringify(result));
this.updateRemaining();
},
// updates the observable
updateRemaining: function () {
this.remaining(this.reduce(function (memo, todo) {
return todo.completed() ? memo : memo + 1;
}, 0));
}
});
App.View('Todos', {
options: {
// creates a route for the View in order to handle
// /all, /active, /completed filters
route: blocks.route('{{filter}}').optional('filter')
},
filter: blocks.observable(),
newTodo: new Todo(),
// holds all todos for the current view
// todos are filtered if "Active" or "Completed" is clicked
todos: new Todos().extend('filter', function (value) {
var mode = this.filter();
var completed = value.completed();
var include = true;
if (mode === 'active') {
include = !completed;
} else if (mode === 'completed') {
include = completed;
}
return include;
}),
// filter the data when the route have changed
// the callback is fired when "All", "Active" or "Completed" have been clicked
routed: function (params) {
if (params.filter !== 'active' && params.filter !== 'completed') {
params.filter = 'all';
}
this.filter(params.filter);
},
addTodo: function (e) {
if (e.which === ENTER_KEY && this.newTodo.title()) {
this.todos.push(this.newTodo);
// return all Todo values to their defaults
this.newTodo.reset();
}
}
});
})();