/
script.js
147 lines (128 loc) · 3.74 KB
/
script.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
var app = {}; // create namespace
//--------------
// Models
//--------------
app.Todo = Backbone.Model.extend({ // class Todo extends backbone model. could also use: var Todo = Backbone.Model.extend({});
defaults: {
title: '',
author: 'anon'
}
});
// Create a Firebase collection and set the 'firebase' property to the URL of your Firebase
//--------------
// Collections
//--------------
//Collection: ordered set of models
app.TodoList = Backbone.Firebase.Collection.extend({
model: app.Todo,
url: "https://boiling-inferno-6812.firebaseio.com/"
});
// instance of the Collection
app.todoList = new app.TodoList();
//--------------
// Views
//--------------
// View for he individual todo item
app.TodoView = Backbone.View.extend({
tagName: 'p', // el will be wrapped in <p>
template: _.template($('#item-template').html()),
render: function(){
this.$el.html(this.template(this.model.toJSON()));
this.input = this.$('.edit');
return this; // enable chained calls
},
initialize: function() {
this.model.on('change', this.render, this); // listen for edit
this.model.on('destroy', this.remove, this); // listen for destroy
},
events: { // bind functions to events
'dblclick .bubble' : 'edit',
'keypress .edit' : 'updateOnEnter',
'blur .edit' : 'close',
'click .destroy': 'destroy'
},
edit: function(){
this.$el.addClass('editing');
this.input.focus();
},
close: function(){
var value = this.input.val().trim();
if(value){
this.model.save({title: value});
}
this.$el.removeClass('editing');
},
updateOnEnter: function(e){
if(e.which == 13){
this.close();
}
},
destroy: function(){
this.model.destroy();
}
});
// View for the collection
app.AppView = Backbone.View.extend({
el: '#todoapp', // from the HTML
initialize: function () {
this.input = this.$('#new-todo'); // input is a jQuery object from the form
// when new elements are added to the collection render then with addOne
this.author = this.$('#new-author');
app.todoList.on('add', this.addOne, this); // bind the object 'this' to the event add and the callback function addOne. The callback addOne will be executed on this when add event is triggered.
app.todoList.on('reset', this.addAll, this);
app.todoList.fetch(); // Loads list from local storage
},
events: {
'keypress #new-todo': 'createTodoOnEnter' // when keypress event runs on #new-todo run function createTodoOnEnter
},
createTodoOnEnter: function(e){
if ( e.which !== 13 || !this.input.val().trim() ) { // ENTER_KEY = 13
return; // if it's not enter, do nothing
}
app.todoList.create(this.newAttributes());
this.input.val(''); // clean input box
e.preventDefault();
},
addOne: function(todo){ // add todo to list
var view = new app.TodoView({model: todo});
$('#todo-list').append(view.render().el);
},
addAll: function(){
this.$('#todo-list').html(''); // clean the todo list
// filter todo item list
switch(window.filter){
default:
app.todoList.each(this.addOne, this);
break;
}
},
newAttributes: function(){
return {
title: this.input.val().trim(),
author: this.author.val().trim()
}
}
});
//--------------
// Routers
//--------------
app.Router = Backbone.Router.extend({
routes: {
'*filter' : 'setFilter'
},
setFilter: function(params) {
console.log('app.router.params = ' + params);
if(params) {
window.filter = params.trim() || '';
} else {
window.filter = '';
}
app.todoList.trigger('reset');
}
});
//--------------
// Initializers
//--------------
app.router = new app.Router();
Backbone.history.start();
app.appView = new app.AppView();