bpm 1.0.0.beta.4 → 1.0.0.beta.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +11 -0
- data/TODO.md +4 -10
- data/backbone/LICENSE +22 -0
- data/backbone/README +25 -0
- data/backbone/Rakefile +42 -0
- data/backbone/backbone-0.5.1.bpkg +0 -0
- data/backbone/examples/backbone-localstorage.js +84 -0
- data/backbone/examples/todos/destroy.png +0 -0
- data/backbone/examples/todos/index.html +87 -0
- data/backbone/examples/todos/todos.css +311 -0
- data/backbone/examples/todos/todos.js +258 -0
- data/backbone/index.html +2606 -0
- data/backbone/index.js +1 -0
- data/backbone/lib/backbone.js +1149 -0
- data/backbone/lib/index.js +1 -0
- data/backbone/package.json +14 -0
- data/backbone/test/collection.js +345 -0
- data/backbone/test/events.js +70 -0
- data/backbone/test/model.coffee +43 -0
- data/backbone/test/model.js +424 -0
- data/backbone/test/noconflict.js +12 -0
- data/backbone/test/router.js +116 -0
- data/backbone/test/speed.js +45 -0
- data/backbone/test/sync.js +133 -0
- data/backbone/test/test-zepto.html +30 -0
- data/backbone/test/test.html +31 -0
- data/backbone/test/vendor/jquery-1.5.js +8176 -0
- data/backbone/test/vendor/jslitmus.js +649 -0
- data/backbone/test/vendor/json2.js +481 -0
- data/backbone/test/vendor/qunit.css +196 -0
- data/backbone/test/vendor/qunit.js +1364 -0
- data/backbone/test/vendor/underscore-1.1.6.js +807 -0
- data/backbone/test/vendor/zepto-0.6.js +692 -0
- data/backbone/test/view.js +137 -0
- data/lib/bpm/cli/base.rb +22 -7
- data/lib/bpm/package.rb +17 -5
- data/lib/bpm/project.rb +49 -32
- data/lib/bpm/version.rb +1 -1
- data/spec/cli/add_spec.rb +22 -4
- data/spec/cli/fetch_spec.rb +0 -1
- data/spec/cli/init_spec.rb +25 -10
- data/spec/cli/list_spec.rb +103 -62
- data/spec/cli/pack_spec.rb +36 -4
- data/spec/fixtures/packages/backbone/LICENSE +22 -0
- data/spec/fixtures/packages/backbone/README +25 -0
- data/spec/fixtures/packages/backbone/Rakefile +42 -0
- data/spec/fixtures/packages/backbone/examples/backbone-localstorage.js +84 -0
- data/spec/fixtures/packages/backbone/examples/todos/destroy.png +0 -0
- data/spec/fixtures/packages/backbone/examples/todos/index.html +87 -0
- data/spec/fixtures/packages/backbone/examples/todos/todos.css +311 -0
- data/spec/fixtures/packages/backbone/examples/todos/todos.js +258 -0
- data/spec/fixtures/packages/backbone/index.html +2606 -0
- data/spec/fixtures/packages/backbone/lib/backbone.js +1149 -0
- data/spec/fixtures/packages/backbone/lib/index.js +1 -0
- data/spec/fixtures/packages/backbone/package.json +14 -0
- data/spec/fixtures/packages/backbone/test/collection.js +345 -0
- data/spec/fixtures/packages/backbone/test/events.js +70 -0
- data/spec/fixtures/packages/backbone/test/model.coffee +43 -0
- data/spec/fixtures/packages/backbone/test/model.js +424 -0
- data/spec/fixtures/packages/backbone/test/noconflict.js +12 -0
- data/spec/fixtures/packages/backbone/test/router.js +116 -0
- data/spec/fixtures/packages/backbone/test/speed.js +45 -0
- data/spec/fixtures/packages/backbone/test/sync.js +133 -0
- data/spec/fixtures/packages/backbone/test/test-zepto.html +30 -0
- data/spec/fixtures/packages/backbone/test/test.html +31 -0
- data/spec/fixtures/packages/backbone/test/vendor/jquery-1.5.js +8176 -0
- data/spec/fixtures/packages/backbone/test/vendor/jslitmus.js +649 -0
- data/spec/fixtures/packages/backbone/test/vendor/json2.js +481 -0
- data/spec/fixtures/packages/backbone/test/vendor/qunit.css +196 -0
- data/spec/fixtures/packages/backbone/test/vendor/qunit.js +1364 -0
- data/spec/fixtures/packages/backbone/test/vendor/underscore-1.1.6.js +807 -0
- data/spec/fixtures/packages/backbone/test/vendor/zepto-0.6.js +692 -0
- data/spec/fixtures/packages/backbone/test/view.js +137 -0
- data/spec/fixtures/projects/init_app/assets/bpm_libs.js +1 -1
- data/spec/fixtures/projects/init_app/assets/bpm_styles.css +1 -1
- data/spec/fixtures/projects/init_app/new_project.json +1 -10
- data/spec/pipeline_spec.rb +5 -5
- data/spec/plugins/minifier_spec.rb +1 -1
- data/spec/plugins/transport_spec.rb +1 -1
- metadata +116 -28
- data/spec/fixtures/projects/init_app/assets/new_project/bpm_libs.js +0 -6
- data/spec/fixtures/projects/init_app/assets/new_project/bpm_styles.css +0 -5
@@ -0,0 +1,311 @@
|
|
1
|
+
html, body, div, span, applet, object, iframe,
|
2
|
+
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
3
|
+
a, abbr, acronym, address, big, cite, code,
|
4
|
+
del, dfn, em, font, img, ins, kbd, q, s, samp,
|
5
|
+
small, strike, strong, sub, sup, tt, var,
|
6
|
+
dl, dt, dd, ol, ul, li,
|
7
|
+
fieldset, form, label, legend,
|
8
|
+
table, caption, tbody, tfoot, thead, tr, th, td {
|
9
|
+
margin: 0;
|
10
|
+
padding: 0;
|
11
|
+
border: 0;
|
12
|
+
outline: 0;
|
13
|
+
font-weight: inherit;
|
14
|
+
font-style: inherit;
|
15
|
+
font-size: 100%;
|
16
|
+
font-family: inherit;
|
17
|
+
vertical-align: baseline;
|
18
|
+
}
|
19
|
+
body {
|
20
|
+
line-height: 1;
|
21
|
+
color: black;
|
22
|
+
background: white;
|
23
|
+
}
|
24
|
+
ol, ul {
|
25
|
+
list-style: none;
|
26
|
+
}
|
27
|
+
a img {
|
28
|
+
border: none;
|
29
|
+
}
|
30
|
+
|
31
|
+
html {
|
32
|
+
background: #eeeeee;
|
33
|
+
}
|
34
|
+
body {
|
35
|
+
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
36
|
+
font-size: 14px;
|
37
|
+
line-height: 1.4em;
|
38
|
+
background: #eeeeee;
|
39
|
+
color: #333333;
|
40
|
+
}
|
41
|
+
|
42
|
+
#todoapp {
|
43
|
+
width: 480px;
|
44
|
+
margin: 0 auto 40px;
|
45
|
+
background: white;
|
46
|
+
padding: 20px;
|
47
|
+
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
|
48
|
+
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
|
49
|
+
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
|
50
|
+
box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
|
51
|
+
}
|
52
|
+
#todoapp h1 {
|
53
|
+
font-size: 36px;
|
54
|
+
font-weight: bold;
|
55
|
+
text-align: center;
|
56
|
+
padding: 20px 0 30px 0;
|
57
|
+
line-height: 1;
|
58
|
+
}
|
59
|
+
|
60
|
+
#create-todo {
|
61
|
+
position: relative;
|
62
|
+
}
|
63
|
+
#create-todo input {
|
64
|
+
width: 466px;
|
65
|
+
font-size: 24px;
|
66
|
+
font-family: inherit;
|
67
|
+
line-height: 1.4em;
|
68
|
+
border: 0;
|
69
|
+
outline: none;
|
70
|
+
padding: 6px;
|
71
|
+
border: 1px solid #999999;
|
72
|
+
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
|
73
|
+
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
|
74
|
+
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
|
75
|
+
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
|
76
|
+
}
|
77
|
+
#create-todo input::-webkit-input-placeholder {
|
78
|
+
font-style: italic;
|
79
|
+
}
|
80
|
+
#create-todo span {
|
81
|
+
position: absolute;
|
82
|
+
z-index: 999;
|
83
|
+
width: 170px;
|
84
|
+
left: 50%;
|
85
|
+
margin-left: -85px;
|
86
|
+
}
|
87
|
+
|
88
|
+
#todo-list {
|
89
|
+
margin-top: 10px;
|
90
|
+
}
|
91
|
+
#todo-list li {
|
92
|
+
padding: 12px 20px 11px 0;
|
93
|
+
position: relative;
|
94
|
+
font-size: 24px;
|
95
|
+
line-height: 1.1em;
|
96
|
+
border-bottom: 1px solid #cccccc;
|
97
|
+
}
|
98
|
+
#todo-list li:after {
|
99
|
+
content: "\0020";
|
100
|
+
display: block;
|
101
|
+
height: 0;
|
102
|
+
clear: both;
|
103
|
+
overflow: hidden;
|
104
|
+
visibility: hidden;
|
105
|
+
}
|
106
|
+
#todo-list li.editing {
|
107
|
+
padding: 0;
|
108
|
+
border-bottom: 0;
|
109
|
+
}
|
110
|
+
#todo-list .editing .display,
|
111
|
+
#todo-list .edit {
|
112
|
+
display: none;
|
113
|
+
}
|
114
|
+
#todo-list .editing .edit {
|
115
|
+
display: block;
|
116
|
+
}
|
117
|
+
#todo-list .editing input {
|
118
|
+
width: 444px;
|
119
|
+
font-size: 24px;
|
120
|
+
font-family: inherit;
|
121
|
+
margin: 0;
|
122
|
+
line-height: 1.6em;
|
123
|
+
border: 0;
|
124
|
+
outline: none;
|
125
|
+
padding: 10px 7px 0px 27px;
|
126
|
+
border: 1px solid #999999;
|
127
|
+
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
|
128
|
+
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
|
129
|
+
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
|
130
|
+
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
|
131
|
+
}
|
132
|
+
#todo-list .check {
|
133
|
+
position: relative;
|
134
|
+
top: 9px;
|
135
|
+
margin: 0 10px 0 7px;
|
136
|
+
float: left;
|
137
|
+
}
|
138
|
+
#todo-list .done .todo-content {
|
139
|
+
text-decoration: line-through;
|
140
|
+
color: #777777;
|
141
|
+
}
|
142
|
+
#todo-list .todo-destroy {
|
143
|
+
position: absolute;
|
144
|
+
right: 5px;
|
145
|
+
top: 14px;
|
146
|
+
display: none;
|
147
|
+
cursor: pointer;
|
148
|
+
width: 20px;
|
149
|
+
height: 20px;
|
150
|
+
background: url(destroy.png) no-repeat 0 0;
|
151
|
+
}
|
152
|
+
#todo-list li:hover .todo-destroy {
|
153
|
+
display: block;
|
154
|
+
}
|
155
|
+
#todo-list .todo-destroy:hover {
|
156
|
+
background-position: 0 -20px;
|
157
|
+
}
|
158
|
+
|
159
|
+
#todo-stats {
|
160
|
+
*zoom: 1;
|
161
|
+
margin-top: 10px;
|
162
|
+
color: #777777;
|
163
|
+
}
|
164
|
+
#todo-stats:after {
|
165
|
+
content: "\0020";
|
166
|
+
display: block;
|
167
|
+
height: 0;
|
168
|
+
clear: both;
|
169
|
+
overflow: hidden;
|
170
|
+
visibility: hidden;
|
171
|
+
}
|
172
|
+
#todo-stats .todo-count {
|
173
|
+
float: left;
|
174
|
+
}
|
175
|
+
#todo-stats .todo-count .number {
|
176
|
+
font-weight: bold;
|
177
|
+
color: #333333;
|
178
|
+
}
|
179
|
+
#todo-stats .todo-clear {
|
180
|
+
float: right;
|
181
|
+
}
|
182
|
+
#todo-stats .todo-clear a {
|
183
|
+
color: #777777;
|
184
|
+
font-size: 12px;
|
185
|
+
}
|
186
|
+
#todo-stats .todo-clear a:visited {
|
187
|
+
color: #777777;
|
188
|
+
}
|
189
|
+
#todo-stats .todo-clear a:hover {
|
190
|
+
color: #336699;
|
191
|
+
}
|
192
|
+
|
193
|
+
#instructions {
|
194
|
+
width: 520px;
|
195
|
+
margin: 10px auto;
|
196
|
+
color: #777777;
|
197
|
+
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
|
198
|
+
text-align: center;
|
199
|
+
}
|
200
|
+
#instructions a {
|
201
|
+
color: #336699;
|
202
|
+
}
|
203
|
+
|
204
|
+
#credits {
|
205
|
+
width: 520px;
|
206
|
+
margin: 30px auto;
|
207
|
+
color: #999;
|
208
|
+
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
|
209
|
+
text-align: center;
|
210
|
+
}
|
211
|
+
#credits a {
|
212
|
+
color: #888;
|
213
|
+
}
|
214
|
+
|
215
|
+
|
216
|
+
/*
|
217
|
+
* François 'cahnory' Germain
|
218
|
+
*/
|
219
|
+
.ui-tooltip, .ui-tooltip-top, .ui-tooltip-right, .ui-tooltip-bottom, .ui-tooltip-left {
|
220
|
+
color:#ffffff;
|
221
|
+
cursor:normal;
|
222
|
+
display:-moz-inline-stack;
|
223
|
+
display:inline-block;
|
224
|
+
font-size:12px;
|
225
|
+
font-family:arial;
|
226
|
+
padding:.5em 1em;
|
227
|
+
position:relative;
|
228
|
+
text-align:center;
|
229
|
+
text-shadow:0 -1px 1px #111111;
|
230
|
+
-webkit-border-top-left-radius:4px ;
|
231
|
+
-webkit-border-top-right-radius:4px ;
|
232
|
+
-webkit-border-bottom-right-radius:4px ;
|
233
|
+
-webkit-border-bottom-left-radius:4px ;
|
234
|
+
-khtml-border-top-left-radius:4px ;
|
235
|
+
-khtml-border-top-right-radius:4px ;
|
236
|
+
-khtml-border-bottom-right-radius:4px ;
|
237
|
+
-khtml-border-bottom-left-radius:4px ;
|
238
|
+
-moz-border-radius-topleft:4px ;
|
239
|
+
-moz-border-radius-topright:4px ;
|
240
|
+
-moz-border-radius-bottomright:4px ;
|
241
|
+
-moz-border-radius-bottomleft:4px ;
|
242
|
+
border-top-left-radius:4px ;
|
243
|
+
border-top-right-radius:4px ;
|
244
|
+
border-bottom-right-radius:4px ;
|
245
|
+
border-bottom-left-radius:4px ;
|
246
|
+
-o-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
|
247
|
+
-moz-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
|
248
|
+
-khtml-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
|
249
|
+
-webkit-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
|
250
|
+
box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
|
251
|
+
background-color:#3b3b3b;
|
252
|
+
background-image:-moz-linear-gradient(top,#555555,#222222);
|
253
|
+
background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#555555),color-stop(1,#222222));
|
254
|
+
filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#555555,EndColorStr=#222222);
|
255
|
+
-ms-filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#555555,EndColorStr=#222222);
|
256
|
+
}
|
257
|
+
.ui-tooltip:after, .ui-tooltip-top:after, .ui-tooltip-right:after, .ui-tooltip-bottom:after, .ui-tooltip-left:after {
|
258
|
+
content:"\25B8";
|
259
|
+
display:block;
|
260
|
+
font-size:2em;
|
261
|
+
height:0;
|
262
|
+
line-height:0;
|
263
|
+
position:absolute;
|
264
|
+
}
|
265
|
+
.ui-tooltip:after, .ui-tooltip-bottom:after {
|
266
|
+
color:#2a2a2a;
|
267
|
+
bottom:0;
|
268
|
+
left:1px;
|
269
|
+
text-align:center;
|
270
|
+
text-shadow:1px 0 2px #000000;
|
271
|
+
-o-transform:rotate(90deg);
|
272
|
+
-moz-transform:rotate(90deg);
|
273
|
+
-khtml-transform:rotate(90deg);
|
274
|
+
-webkit-transform:rotate(90deg);
|
275
|
+
width:100%;
|
276
|
+
}
|
277
|
+
.ui-tooltip-top:after {
|
278
|
+
bottom:auto;
|
279
|
+
color:#4f4f4f;
|
280
|
+
left:-2px;
|
281
|
+
top:0;
|
282
|
+
text-align:center;
|
283
|
+
text-shadow:none;
|
284
|
+
-o-transform:rotate(-90deg);
|
285
|
+
-moz-transform:rotate(-90deg);
|
286
|
+
-khtml-transform:rotate(-90deg);
|
287
|
+
-webkit-transform:rotate(-90deg);
|
288
|
+
width:100%;
|
289
|
+
}
|
290
|
+
.ui-tooltip-right:after {
|
291
|
+
color:#222222;
|
292
|
+
right:-0.375em;
|
293
|
+
top:50%;
|
294
|
+
margin-top:-.05em;
|
295
|
+
text-shadow:0 1px 2px #000000;
|
296
|
+
-o-transform:rotate(0);
|
297
|
+
-moz-transform:rotate(0);
|
298
|
+
-khtml-transform:rotate(0);
|
299
|
+
-webkit-transform:rotate(0);
|
300
|
+
}
|
301
|
+
.ui-tooltip-left:after {
|
302
|
+
color:#222222;
|
303
|
+
left:-0.375em;
|
304
|
+
top:50%;
|
305
|
+
margin-top:.1em;
|
306
|
+
text-shadow:0 -1px 2px #000000;
|
307
|
+
-o-transform:rotate(180deg);
|
308
|
+
-moz-transform:rotate(180deg);
|
309
|
+
-khtml-transform:rotate(180deg);
|
310
|
+
-webkit-transform:rotate(180deg);
|
311
|
+
}
|
@@ -0,0 +1,258 @@
|
|
1
|
+
// An example Backbone application contributed by
|
2
|
+
// [Jérôme Gravel-Niquet](http://jgn.me/). This demo uses a simple
|
3
|
+
// [LocalStorage adapter](backbone-localstorage.html)
|
4
|
+
// to persist Backbone models within your browser.
|
5
|
+
|
6
|
+
// Load the application once the DOM is ready, using `jQuery.ready`:
|
7
|
+
$(function(){
|
8
|
+
|
9
|
+
// Todo Model
|
10
|
+
// ----------
|
11
|
+
|
12
|
+
// Our basic **Todo** model has `content`, `order`, and `done` attributes.
|
13
|
+
window.Todo = Backbone.Model.extend({
|
14
|
+
|
15
|
+
// Default attributes for the todo.
|
16
|
+
defaults: {
|
17
|
+
content: "empty todo...",
|
18
|
+
done: false
|
19
|
+
},
|
20
|
+
|
21
|
+
// Ensure that each todo created has `content`.
|
22
|
+
initialize: function() {
|
23
|
+
if (!this.get("content")) {
|
24
|
+
this.set({"content": this.defaults.content});
|
25
|
+
}
|
26
|
+
},
|
27
|
+
|
28
|
+
// Toggle the `done` state of this todo item.
|
29
|
+
toggle: function() {
|
30
|
+
this.save({done: !this.get("done")});
|
31
|
+
},
|
32
|
+
|
33
|
+
// Remove this Todo from *localStorage* and delete its view.
|
34
|
+
clear: function() {
|
35
|
+
this.destroy();
|
36
|
+
this.view.remove();
|
37
|
+
}
|
38
|
+
|
39
|
+
});
|
40
|
+
|
41
|
+
// Todo Collection
|
42
|
+
// ---------------
|
43
|
+
|
44
|
+
// The collection of todos is backed by *localStorage* instead of a remote
|
45
|
+
// server.
|
46
|
+
window.TodoList = Backbone.Collection.extend({
|
47
|
+
|
48
|
+
// Reference to this collection's model.
|
49
|
+
model: Todo,
|
50
|
+
|
51
|
+
// Save all of the todo items under the `"todos"` namespace.
|
52
|
+
localStorage: new Store("todos"),
|
53
|
+
|
54
|
+
// Filter down the list of all todo items that are finished.
|
55
|
+
done: function() {
|
56
|
+
return this.filter(function(todo){ return todo.get('done'); });
|
57
|
+
},
|
58
|
+
|
59
|
+
// Filter down the list to only todo items that are still not finished.
|
60
|
+
remaining: function() {
|
61
|
+
return this.without.apply(this, this.done());
|
62
|
+
},
|
63
|
+
|
64
|
+
// We keep the Todos in sequential order, despite being saved by unordered
|
65
|
+
// GUID in the database. This generates the next order number for new items.
|
66
|
+
nextOrder: function() {
|
67
|
+
if (!this.length) return 1;
|
68
|
+
return this.last().get('order') + 1;
|
69
|
+
},
|
70
|
+
|
71
|
+
// Todos are sorted by their original insertion order.
|
72
|
+
comparator: function(todo) {
|
73
|
+
return todo.get('order');
|
74
|
+
}
|
75
|
+
|
76
|
+
});
|
77
|
+
|
78
|
+
// Create our global collection of **Todos**.
|
79
|
+
window.Todos = new TodoList;
|
80
|
+
|
81
|
+
// Todo Item View
|
82
|
+
// --------------
|
83
|
+
|
84
|
+
// The DOM element for a todo item...
|
85
|
+
window.TodoView = Backbone.View.extend({
|
86
|
+
|
87
|
+
//... is a list tag.
|
88
|
+
tagName: "li",
|
89
|
+
|
90
|
+
// Cache the template function for a single item.
|
91
|
+
template: _.template($('#item-template').html()),
|
92
|
+
|
93
|
+
// The DOM events specific to an item.
|
94
|
+
events: {
|
95
|
+
"click .check" : "toggleDone",
|
96
|
+
"dblclick div.todo-content" : "edit",
|
97
|
+
"click span.todo-destroy" : "clear",
|
98
|
+
"keypress .todo-input" : "updateOnEnter"
|
99
|
+
},
|
100
|
+
|
101
|
+
// The TodoView listens for changes to its model, re-rendering. Since there's
|
102
|
+
// a one-to-one correspondence between a **Todo** and a **TodoView** in this
|
103
|
+
// app, we set a direct reference on the model for convenience.
|
104
|
+
initialize: function() {
|
105
|
+
_.bindAll(this, 'render', 'close');
|
106
|
+
this.model.bind('change', this.render);
|
107
|
+
this.model.view = this;
|
108
|
+
},
|
109
|
+
|
110
|
+
// Re-render the contents of the todo item.
|
111
|
+
render: function() {
|
112
|
+
$(this.el).html(this.template(this.model.toJSON()));
|
113
|
+
this.setContent();
|
114
|
+
return this;
|
115
|
+
},
|
116
|
+
|
117
|
+
// To avoid XSS (not that it would be harmful in this particular app),
|
118
|
+
// we use `jQuery.text` to set the contents of the todo item.
|
119
|
+
setContent: function() {
|
120
|
+
var content = this.model.get('content');
|
121
|
+
this.$('.todo-content').text(content);
|
122
|
+
this.input = this.$('.todo-input');
|
123
|
+
this.input.bind('blur', this.close);
|
124
|
+
this.input.val(content);
|
125
|
+
},
|
126
|
+
|
127
|
+
// Toggle the `"done"` state of the model.
|
128
|
+
toggleDone: function() {
|
129
|
+
this.model.toggle();
|
130
|
+
},
|
131
|
+
|
132
|
+
// Switch this view into `"editing"` mode, displaying the input field.
|
133
|
+
edit: function() {
|
134
|
+
$(this.el).addClass("editing");
|
135
|
+
this.input.focus();
|
136
|
+
},
|
137
|
+
|
138
|
+
// Close the `"editing"` mode, saving changes to the todo.
|
139
|
+
close: function() {
|
140
|
+
this.model.save({content: this.input.val()});
|
141
|
+
$(this.el).removeClass("editing");
|
142
|
+
},
|
143
|
+
|
144
|
+
// If you hit `enter`, we're through editing the item.
|
145
|
+
updateOnEnter: function(e) {
|
146
|
+
if (e.keyCode == 13) this.close();
|
147
|
+
},
|
148
|
+
|
149
|
+
// Remove this view from the DOM.
|
150
|
+
remove: function() {
|
151
|
+
$(this.el).remove();
|
152
|
+
},
|
153
|
+
|
154
|
+
// Remove the item, destroy the model.
|
155
|
+
clear: function() {
|
156
|
+
this.model.clear();
|
157
|
+
}
|
158
|
+
|
159
|
+
});
|
160
|
+
|
161
|
+
// The Application
|
162
|
+
// ---------------
|
163
|
+
|
164
|
+
// Our overall **AppView** is the top-level piece of UI.
|
165
|
+
window.AppView = Backbone.View.extend({
|
166
|
+
|
167
|
+
// Instead of generating a new element, bind to the existing skeleton of
|
168
|
+
// the App already present in the HTML.
|
169
|
+
el: $("#todoapp"),
|
170
|
+
|
171
|
+
// Our template for the line of statistics at the bottom of the app.
|
172
|
+
statsTemplate: _.template($('#stats-template').html()),
|
173
|
+
|
174
|
+
// Delegated events for creating new items, and clearing completed ones.
|
175
|
+
events: {
|
176
|
+
"keypress #new-todo": "createOnEnter",
|
177
|
+
"keyup #new-todo": "showTooltip",
|
178
|
+
"click .todo-clear a": "clearCompleted"
|
179
|
+
},
|
180
|
+
|
181
|
+
// At initialization we bind to the relevant events on the `Todos`
|
182
|
+
// collection, when items are added or changed. Kick things off by
|
183
|
+
// loading any preexisting todos that might be saved in *localStorage*.
|
184
|
+
initialize: function() {
|
185
|
+
_.bindAll(this, 'addOne', 'addAll', 'render');
|
186
|
+
|
187
|
+
this.input = this.$("#new-todo");
|
188
|
+
|
189
|
+
Todos.bind('add', this.addOne);
|
190
|
+
Todos.bind('reset', this.addAll);
|
191
|
+
Todos.bind('all', this.render);
|
192
|
+
|
193
|
+
Todos.fetch();
|
194
|
+
},
|
195
|
+
|
196
|
+
// Re-rendering the App just means refreshing the statistics -- the rest
|
197
|
+
// of the app doesn't change.
|
198
|
+
render: function() {
|
199
|
+
this.$('#todo-stats').html(this.statsTemplate({
|
200
|
+
total: Todos.length,
|
201
|
+
done: Todos.done().length,
|
202
|
+
remaining: Todos.remaining().length
|
203
|
+
}));
|
204
|
+
},
|
205
|
+
|
206
|
+
// Add a single todo item to the list by creating a view for it, and
|
207
|
+
// appending its element to the `<ul>`.
|
208
|
+
addOne: function(todo) {
|
209
|
+
var view = new TodoView({model: todo});
|
210
|
+
this.$("#todo-list").append(view.render().el);
|
211
|
+
},
|
212
|
+
|
213
|
+
// Add all items in the **Todos** collection at once.
|
214
|
+
addAll: function() {
|
215
|
+
Todos.each(this.addOne);
|
216
|
+
},
|
217
|
+
|
218
|
+
// Generate the attributes for a new Todo item.
|
219
|
+
newAttributes: function() {
|
220
|
+
return {
|
221
|
+
content: this.input.val(),
|
222
|
+
order: Todos.nextOrder(),
|
223
|
+
done: false
|
224
|
+
};
|
225
|
+
},
|
226
|
+
|
227
|
+
// If you hit return in the main input field, create new **Todo** model,
|
228
|
+
// persisting it to *localStorage*.
|
229
|
+
createOnEnter: function(e) {
|
230
|
+
if (e.keyCode != 13) return;
|
231
|
+
Todos.create(this.newAttributes());
|
232
|
+
this.input.val('');
|
233
|
+
},
|
234
|
+
|
235
|
+
// Clear all done todo items, destroying their models.
|
236
|
+
clearCompleted: function() {
|
237
|
+
_.each(Todos.done(), function(todo){ todo.clear(); });
|
238
|
+
return false;
|
239
|
+
},
|
240
|
+
|
241
|
+
// Lazily show the tooltip that tells you to press `enter` to save
|
242
|
+
// a new todo item, after one second.
|
243
|
+
showTooltip: function(e) {
|
244
|
+
var tooltip = this.$(".ui-tooltip-top");
|
245
|
+
var val = this.input.val();
|
246
|
+
tooltip.fadeOut();
|
247
|
+
if (this.tooltipTimeout) clearTimeout(this.tooltipTimeout);
|
248
|
+
if (val == '' || val == this.input.attr('placeholder')) return;
|
249
|
+
var show = function(){ tooltip.show().fadeIn(); };
|
250
|
+
this.tooltipTimeout = _.delay(show, 1000);
|
251
|
+
}
|
252
|
+
|
253
|
+
});
|
254
|
+
|
255
|
+
// Finally, we kick things off by creating the **App**.
|
256
|
+
window.App = new AppView;
|
257
|
+
|
258
|
+
});
|