The library for web and native user interfaces.
Fix backbone todomvc example
petehunt committed
May 30, 2013 at 03:35 UTC
56dbec46db99d5ba764714a585fe9ce17ec8dcd8
1 file changed
+36
-52
examples/todomvc-backbone/js/app.js
+36
-52
@@ -66,29 +66,6 @@ var TodoList = Backbone.Collection.extend({
66
}
67
});
68
69
-// Create our global collection of **Todos**.
70
-var Todos = new TodoList();
71
-
72
-var TodoFilter;
73
-
74
-var Workspace = Backbone.Router.extend({
75
- routes:{
76
- '*filter': 'setFilter'
77
- },
78
-
79
- setFilter: function( param ) {
80
- // Set the current filter to be used
81
- TodoFilter = param.trim() || '';
82
-
83
- // Trigger a collection filter event, causing hiding/unhiding
84
- // of Todo view items
85
- Todos.trigger('filter');
86
- }
87
-});
88
-
89
-var TodoRouter = new Workspace();
90
-Backbone.history.start();
91
-
69
var Utils = {
70
// https://gist.github.com/1308368
71
uuid: function(a,b){for(b=a='';a++<36;b+=a*51&52?(a^15?8^Math.random()*(a^20?16:4):4).toString(16):'-');return b},
@@ -111,7 +88,7 @@ var ENTER_KEY = 13;
88
89
var TodoItem = React.createClass({
90
getInitialState: function() {
114
- return {editValue: this.props.todo.title};
91
+ return {editValue: this.props.todo.get('title')};
92
},
93
onKeyUp: React.autoBind(function(event) {
94
this.setState({editValue: event.target.value});
@@ -127,16 +104,16 @@ var TodoItem = React.createClass({
104
}),
105
render: function() {
106
return (
130
- <li class={cx({completed: this.props.todo.completed, editing: this.props.editing})}>
107
+ <li class={cx({completed: this.props.todo.get('completed'), editing: this.props.editing})}>
108
<div class="view">
109
<input
110
class="toggle"
111
type="checkbox"
135
- checked={this.props.todo.completed ? 'checked' : null}
112
+ checked={this.props.todo.get('completed') ? 'checked' : null}
113
onChange={this.props.onToggle}
114
/>
138
- <label onDoubleClick={this.onEdit}>{this.props.todo.title}</label>
139
- <button class="destroy" onClick={this.props.onDestroy} />
115
+ <label onDoubleClick={this.onEdit}>{this.props.todo.get('title')}</label>
116
+ <button class="destroy" onClick={this.props.onDestroy} />
117
</div>
118
<input ref="editField" class="edit" value={this.state.editValue} onKeyUp={this.onKeyUp} />
119
</li>
@@ -166,7 +143,15 @@ var TodoFooter = React.createClass({
143
144
var TodoApp = React.createClass({
145
getInitialState: function() {
169
- return {todos: Utils.store('todos-react'), newTodoValue: '', editing: {}};
146
+ return {newTodoValue: '', editing: {}};
147
+ },
148
+ // Here is "the backbone integration." Just tell React whenever there *might* be a change
149
+ // and we'll reconcile.
150
+ componentWillMount: function() {
151
+ this.props.todos.on('add change remove', this.forceUpdate, this);
152
+ },
153
+ componentWillUnmount: function() {
154
+ this.props.todos.off(null, null, this);
155
},
156
handleKeyUp: React.autoBind(function(event) {
157
this.setState({newTodoValue: event.target.value});
@@ -174,48 +159,48 @@ var TodoApp = React.createClass({
159
if (event.nativeEvent.keyCode !== ENTER_KEY || !val) {
160
return;
161
}
177
- var todos = this.state.todos;
178
- todos.push({id: Utils.uuid(), title: val, completed: false});
179
- this.setState({todos: todos, newTodoValue: ''});
162
+ this.props.todos.add(new Todo({id: Utils.uuid(), title: val, completed: false}));
163
+ this.setState({newTodoValue: ''});
164
}),
165
toggleAll: function(event) {
166
var checked = event.nativeEvent.target.checked;
183
- this.state.todos.map(function(todo) {
184
- todo.completed = checked;
167
+ this.props.todos.map(function(todo) {
168
+ todo.set('completed', checked);
169
});
186
- this.setState({todos: this.state.todos});
170
},
171
toggle: function(todo) {
189
- todo.completed = !todo.completed;
190
- this.setState({todos: this.state.todos});
172
+ todo.set('completed', !todo.get('completed'));
173
},
174
destroy: function(todo) {
193
- this.setState({todos: this.state.todos.filter(function(candidate) { return candidate.id !== todo.id; })});
175
+ this.props.todos.remove(todo);
176
},
177
edit: function(todo) {
196
- this.state.todos.map(function(todo) { this.state.editing[todo.id] = false; }.bind(this));
197
- this.state.editing[todo.id] = true;
198
- this.setState({editing: this.state.editing});
178
+ var editing = {};
179
+ editing[todo.get('id')] = true;
180
+ this.setState({editing: editing});
181
},
182
save: function(todo, text) {
201
- todo.title = text;
202
- this.state.editing[todo.id] = false;
203
- this.setState({todos: this.state.todos, editing: this.state.editing});
183
+ todo.set('title', text);
184
+ this.setState({editing: {}});
185
},
186
clearCompleted: function() {
206
- this.setState({todos: this.state.todos.filter(function(todo) { return !todo.completed })});
187
+ this.props.todos.filter(function(todo) {
188
+ return todo.get('completed');
189
+ }).map(this.props.todos.remove.bind(this.props.todos));
190
+ },
191
+ componentDidUpdate: function() {
192
+ Utils.store('todos-react', this.props.todos);
193
},
194
render: function() {
209
- Utils.store(this.props.localStorageKey || 'todos-react', this.state.todos);
195
var footer = null;
196
var main = null;
212
- var todoItems = this.state.todos.map(function(todo) {
213
- return <TodoItem todo={todo} onToggle={this.toggle.bind(this, todo)} onDestroy={this.destroy.bind(this, todo)} onEdit={this.edit.bind(this, todo)} editing={this.state.editing[todo.id]} onSave={this.save.bind(this, todo)} />;
197
+ var todoItems = this.props.todos.map(function(todo) {
198
+ return <TodoItem todo={todo} onToggle={this.toggle.bind(this, todo)} onDestroy={this.destroy.bind(this, todo)} onEdit={this.edit.bind(this, todo)} editing={this.state.editing[todo.get('id')]} onSave={this.save.bind(this, todo)} />;
199
}.bind(this));
200
216
- var activeTodoCount = this.state.todos.filter(function(todo) { return !todo.completed }).length;
201
+ var activeTodoCount = this.props.todos.filter(function(todo) { return !todo.get('completed') }).length;
202
var completedCount = todoItems.length - activeTodoCount;
218
- if (activeTodoCount || completedCount) {
203
+ if (activeTodoCount || completedCount) {
204
footer = <TodoFooter count={activeTodoCount} completedCount={completedCount} onClearCompleted={this.clearCompleted.bind(this)} />;
205
}
206
@@ -250,5 +235,4 @@ var TodoApp = React.createClass({
235
);
236
}
237
});
253
-
254
-React.renderComponent(<TodoApp />, document.getElementById('todoapp'));
238
+React.renderComponent(<TodoApp todos={new TodoList(Utils.store('todos-react'))} />, document.getElementById('todoapp'));