bpm 1.0.0.beta.5 → 1.0.0.beta.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/TODO.md +18 -17
  3. data/lib/bpm/pipeline/generated_asset.rb +64 -41
  4. data/lib/bpm/pipeline/plugin_context.rb +24 -0
  5. data/lib/bpm/pipeline/transport_processor.rb +3 -3
  6. data/lib/bpm/pipeline.rb +2 -1
  7. data/lib/bpm/project.rb +7 -1
  8. data/lib/bpm/version.rb +1 -1
  9. data/lib/bpm.rb +1 -0
  10. data/spec/fixtures/projects/minitest/minitest.json +4 -2
  11. data/spec/fixtures/projects/minitest/packages/uglyduck/minifier/main.js +3 -2
  12. data/spec/fixtures/projects/minitrans/lib/main.js +3 -0
  13. data/spec/fixtures/projects/minitrans/minitrans.json +25 -0
  14. data/spec/fixtures/projects/minitrans/packages/transport/lib/main.js +1 -0
  15. data/spec/fixtures/projects/minitrans/packages/transport/package.json +21 -0
  16. data/spec/fixtures/projects/minitrans/packages/transport/transports/wrapper.js +6 -0
  17. data/spec/fixtures/projects/minitrans/packages/uglyduck/lib/main.js +3 -0
  18. data/spec/fixtures/projects/minitrans/packages/uglyduck/minifier/main.js +6 -0
  19. data/spec/fixtures/projects/minitrans/packages/uglyduck/package.json +21 -0
  20. data/spec/fixtures/projects/transporter/packages/transport/transports/wrapper.js +2 -2
  21. data/spec/plugins/minifier_spec.rb +2 -2
  22. data/spec/plugins/transport_spec.rb +38 -0
  23. metadata +41 -56
  24. data/backbone/LICENSE +0 -22
  25. data/backbone/README +0 -25
  26. data/backbone/Rakefile +0 -42
  27. data/backbone/backbone-0.5.1.bpkg +0 -0
  28. data/backbone/examples/backbone-localstorage.js +0 -84
  29. data/backbone/examples/todos/destroy.png +0 -0
  30. data/backbone/examples/todos/index.html +0 -87
  31. data/backbone/examples/todos/todos.css +0 -311
  32. data/backbone/examples/todos/todos.js +0 -258
  33. data/backbone/index.html +0 -2606
  34. data/backbone/index.js +0 -1
  35. data/backbone/lib/backbone.js +0 -1149
  36. data/backbone/lib/index.js +0 -1
  37. data/backbone/package.json +0 -14
  38. data/backbone/test/collection.js +0 -345
  39. data/backbone/test/events.js +0 -70
  40. data/backbone/test/model.coffee +0 -43
  41. data/backbone/test/model.js +0 -424
  42. data/backbone/test/noconflict.js +0 -12
  43. data/backbone/test/router.js +0 -116
  44. data/backbone/test/speed.js +0 -45
  45. data/backbone/test/sync.js +0 -133
  46. data/backbone/test/test-zepto.html +0 -30
  47. data/backbone/test/test.html +0 -31
  48. data/backbone/test/vendor/jquery-1.5.js +0 -8176
  49. data/backbone/test/vendor/jslitmus.js +0 -649
  50. data/backbone/test/vendor/json2.js +0 -481
  51. data/backbone/test/vendor/qunit.css +0 -196
  52. data/backbone/test/vendor/qunit.js +0 -1364
  53. data/backbone/test/vendor/underscore-1.1.6.js +0 -807
  54. data/backbone/test/vendor/zepto-0.6.js +0 -692
  55. data/backbone/test/view.js +0 -137
data/backbone/index.html DELETED
@@ -1,2606 +0,0 @@
1
- <!DOCTYPE HTML>
2
- <html>
3
- <head>
4
- <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
5
- <meta http-equiv="X-UA-Compatible" content="chrome=1">
6
- <title>Backbone.js</title>
7
- <style>
8
- body {
9
- font-size: 14px;
10
- line-height: 22px;
11
- font-family: Helvetica Neue, Helvetica, Arial;
12
- background: #f4f4f4 url(docs/images/background.png);
13
- }
14
- .interface {
15
- font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important;
16
- }
17
- div#sidebar {
18
- background: #fff;
19
- position: fixed;
20
- top: 0; left: 0; bottom: 0;
21
- width: 200px;
22
- overflow-y: auto;
23
- overflow-x: hidden;
24
- padding: 15px 0 30px 30px;
25
- border-right: 1px solid #ddd;
26
- box-shadow: 0 0 20px #ccc; -webkit-box-shadow: 0 0 20px #ccc; -moz-box-shadow: 0 0 20px #ccc;
27
- }
28
- a.toc_title, a.toc_title:visited {
29
- display: block;
30
- color: black;
31
- font-weight: bold;
32
- margin-top: 15px;
33
- }
34
- a.toc_title:hover {
35
- text-decoration: underline;
36
- }
37
- #sidebar .version {
38
- font-size: 10px;
39
- font-weight: normal;
40
- }
41
- ul.toc_section {
42
- font-size: 11px;
43
- line-height: 14px;
44
- margin: 5px 0 0 0;
45
- padding-left: 0px;
46
- list-style-type: none;
47
- font-family: Lucida Grande;
48
- }
49
- .toc_section li {
50
- cursor: pointer;
51
- margin: 0 0 3px 0;
52
- }
53
- .toc_section li a {
54
- text-decoration: none;
55
- color: black;
56
- }
57
- .toc_section li a:hover {
58
- text-decoration: underline;
59
- }
60
- div.container {
61
- position: relative;
62
- width: 550px;
63
- margin: 40px 0 50px 260px;
64
- }
65
- div.run {
66
- position: absolute;
67
- right: 15px;
68
- width: 26px; height: 18px;
69
- background: url('docs/images/arrows.png') no-repeat -26px 0;
70
- }
71
- div.run:active {
72
- background-position: -51px 0;
73
- }
74
- p, div.container ul {
75
- margin: 20px 0;
76
- width: 550px;
77
- }
78
- p.warning {
79
- font-size: 12px;
80
- line-height: 18px;
81
- font-style: italic;
82
- }
83
- div.container ul {
84
- list-style: circle;
85
- font-size: 12px;
86
- padding-left: 15px;
87
- }
88
- a, a:visited {
89
- color: #444;
90
- }
91
- a:active, a:hover {
92
- color: #000;
93
- }
94
- a img {
95
- border: 0;
96
- }
97
- h1, h2, h3, h4, h5, h6 {
98
- padding-top: 20px;
99
- }
100
- h2 {
101
- font-size: 20px;
102
- }
103
- b.header {
104
- font-size: 16px;
105
- line-height: 30px;
106
- }
107
- span.alias {
108
- font-size: 14px;
109
- font-style: italic;
110
- margin-left: 20px;
111
- }
112
- table {
113
- margin: 15px 0 0; padding: 0;
114
- }
115
- tr, td {
116
- margin: 0; padding: 0;
117
- }
118
- td {
119
- padding: 0px 15px 5px 0;
120
- }
121
- code, pre, tt {
122
- font-family: Monaco, Consolas, "Lucida Console", monospace;
123
- font-size: 12px;
124
- line-height: 18px;
125
- font-style: normal;
126
- }
127
- tt {
128
- padding: 0px 3px;
129
- background: #fff;
130
- border: 1px solid #ddd;
131
- zoom: 1;
132
- }
133
- code {
134
- margin-left: 20px;
135
- }
136
- pre {
137
- font-size: 12px;
138
- padding: 2px 0 2px 15px;
139
- border: 4px solid #bbb; border-top: 0; border-bottom: 0;
140
- margin: 0px 0 30px;
141
- }
142
- img.example_image {
143
- margin: 0px auto;
144
- }
145
- </style>
146
- </head>
147
- <body>
148
-
149
- <div id="sidebar" class="interface">
150
-
151
- <a class="toc_title" href="#">
152
- Backbone.js <span class="version">(0.5.1)</span>
153
- </a>
154
-
155
- <a class="toc_title" href="#Introduction">
156
- Introduction
157
- </a>
158
-
159
- <a class="toc_title" href="#Events">
160
- Events
161
- </a>
162
- <ul class="toc_section">
163
- <li>– <a href="#Events-bind">bind</a></li>
164
- <li>– <a href="#Events-unbind">unbind</a></li>
165
- <li>– <a href="#Events-trigger">trigger</a></li>
166
- </ul>
167
-
168
- <a class="toc_title" href="#Model">
169
- Model
170
- </a>
171
- <ul class="toc_section">
172
- <li>– <a href="#Model-extend">extend</a></li>
173
- <li>– <a href="#Model-constructor">constructor / initialize</a></li>
174
- <li>– <a href="#Model-get">get</a></li>
175
- <li>– <a href="#Model-set">set</a></li>
176
- <li>– <a href="#Model-escape">escape</a></li>
177
- <li>– <a href="#Model-has">has</a></li>
178
- <li>– <a href="#Model-unset">unset</a></li>
179
- <li>– <a href="#Model-clear">clear</a></li>
180
- <li>– <a href="#Model-id">id</a></li>
181
- <li>– <a href="#Model-cid">cid</a></li>
182
- <li>– <a href="#Model-attributes">attributes</a></li>
183
- <li>– <a href="#Model-defaults">defaults</a></li>
184
- <li>- <a href="#Model-toJSON">toJSON</a></li>
185
- <li>– <a href="#Model-fetch">fetch</a></li>
186
- <li>– <a href="#Model-save">save</a></li>
187
- <li>– <a href="#Model-destroy">destroy</a></li>
188
- <li>– <a href="#Model-validate">validate</a></li>
189
- <li>– <a href="#Model-url">url</a></li>
190
- <li>– <a href="#Model-urlRoot">urlRoot</a></li>
191
- <li>– <a href="#Model-parse">parse</a></li>
192
- <li>– <a href="#Model-clone">clone</a></li>
193
- <li>– <a href="#Model-isNew">isNew</a></li>
194
- <li>– <a href="#Model-change">change</a></li>
195
- <li>– <a href="#Model-hasChanged">hasChanged</a></li>
196
- <li>– <a href="#Model-changedAttributes">changedAttributes</a></li>
197
- <li>– <a href="#Model-previous">previous</a></li>
198
- <li>– <a href="#Model-previousAttributes">previousAttributes</a></li>
199
- </ul>
200
-
201
- <a class="toc_title" href="#Collection">
202
- Collection
203
- </a>
204
- <ul class="toc_section">
205
- <li>– <a href="#Collection-extend">extend</a></li>
206
- <li>– <a href="#Collection-model">model</a></li>
207
- <li>– <a href="#Collection-constructor">constructor / initialize</a></li>
208
- <li>– <a href="#Collection-models">models</a></li>
209
- <li>– <a href="#Collection-toJSON">toJSON</a></li>
210
- <li>– <a href="#Collection-Underscore-Methods"><b>Underscore Methods (25)</b></a></li>
211
- <li>– <a href="#Collection-add">add</a></li>
212
- <li>– <a href="#Collection-remove">remove</a></li>
213
- <li>– <a href="#Collection-get">get</a></li>
214
- <li>– <a href="#Collection-getByCid">getByCid</a></li>
215
- <li>– <a href="#Collection-at">at</a></li>
216
- <li>– <a href="#Collection-length">length</a></li>
217
- <li>– <a href="#Collection-comparator">comparator</a></li>
218
- <li>– <a href="#Collection-sort">sort</a></li>
219
- <li>– <a href="#Collection-pluck">pluck</a></li>
220
- <li>– <a href="#Collection-url">url</a></li>
221
- <li>– <a href="#Collection-parse">parse</a></li>
222
- <li>– <a href="#Collection-fetch">fetch</a></li>
223
- <li>– <a href="#Collection-reset">reset</a></li>
224
- <li>– <a href="#Collection-create">create</a></li>
225
- </ul>
226
-
227
- <a class="toc_title" href="#Router">
228
- Router
229
- </a>
230
- <ul class="toc_section">
231
- <li>– <a href="#Router-extend">extend</a></li>
232
- <li>– <a href="#Router-routes">routes</a></li>
233
- <li>– <a href="#Router-constructor">constructor / initialize</a></li>
234
- <li>– <a href="#Router-route">route</a></li>
235
- <li>– <a href="#Router-navigate">navigate</a></li>
236
- </ul>
237
-
238
- <a class="toc_title" href="#History">
239
- History
240
- </a>
241
- <ul class="toc_section">
242
- <li>– <a href="#History-start">start</a></li>
243
- </ul>
244
-
245
- <a class="toc_title" href="#Sync">
246
- Sync
247
- </a>
248
- <ul class="toc_section">
249
- <li>– <a href="#Sync">Backbone.sync</a></li>
250
- <li>– <a href="#Sync-emulateHTTP">Backbone.emulateHTTP</a></li>
251
- <li>– <a href="#Sync-emulateJSON">Backbone.emulateJSON</a></li>
252
- </ul>
253
-
254
- <a class="toc_title" href="#View">
255
- View
256
- </a>
257
- <ul class="toc_section">
258
- <li>– <a href="#View-extend">extend</a></li>
259
- <li>– <a href="#View-constructor">constructor / initialize</a></li>
260
- <li>– <a href="#View-el">el</a></li>
261
- <li>– <a href="#View-dollar">$ (jQuery or Zepto)</a></li>
262
- <li>– <a href="#View-render">render</a></li>
263
- <li>– <a href="#View-remove">remove</a></li>
264
- <li>– <a href="#View-make">make</a></li>
265
- <li>– <a href="#View-delegateEvents">delegateEvents</a></li>
266
- </ul>
267
-
268
- <a class="toc_title" href="#Utility">
269
- Utility
270
- </a>
271
- <ul class="toc_section">
272
- <li>– <a href="#Utility-noConflict">noConflict</a></li>
273
- </ul>
274
-
275
- <a class="toc_title" href="#examples">
276
- Examples
277
- </a>
278
- <ul class="toc_section">
279
- <li>– <a href="#examples-todos">Todos</a></li>
280
- <li>– <a href="#examples-documentcloud">DocumentCloud</a></li>
281
- <li>– <a href="#examples-basecamp">Basecamp Mobile</a></li>
282
- <li>– <a href="#examples-flow">Flow</a></li>
283
- <li>– <a href="#examples-cloudapp">CloudApp</a></li>
284
- <li>– <a href="#examples-soundcloud">Mobile SoundCloud</a></li>
285
- <li>– <a href="#examples-quoteroller">Quote Roller</a></li>
286
- <li>– <a href="#examples-tilemill">TileMill</a></li>
287
- <li>– <a href="#examples-menagerievet">Menagerie Whiteboard</a></li>
288
- <li>- <a href="#examples-instagreat">Insta-great!</a></li>
289
- <li>- <a href="#examples-decide">Decide</a></li>
290
- <li>- <a href="#examples-bittorrent">BitTorrent</a></li>
291
- <li>- <a href="#examples-fluxiom">Fluxiom</a></li>
292
- <li>- <a href="#examples-chop">Chop</a></li>
293
- <li>- <a href="#examples-quietwrite">QuietWrite</a></li>
294
- <li>- <a href="#examples-tzigla">Tzigla</a></li>
295
- <li>- <a href="#examples-substance">Substance</a></li>
296
- </ul>
297
-
298
- <a class="toc_title" href="#faq">
299
- F.A.Q.
300
- </a>
301
- <ul class="toc_section">
302
- <li>– <a href="#FAQ-events">Catalog of Events</a></li>
303
- <li>– <a href="#FAQ-nested">Nested Models &amp; Collections</a></li>
304
- <li>– <a href="#FAQ-bootstrap">Loading Bootstrapped Models</a></li>
305
- <li>– <a href="#FAQ-mvc">Traditional MVC</a></li>
306
- <li>– <a href="#FAQ-this">Binding "this"</a></li>
307
- </ul>
308
-
309
- <a class="toc_title" href="#changelog">
310
- Change Log
311
- </a>
312
-
313
- </div>
314
-
315
- <div class="container">
316
-
317
- <p>
318
- <img style="width: 385px; height: 126px;" src="docs/images/backbone.png" alt="Backbone.js" />
319
- </p>
320
-
321
- <p>
322
- <a href="http://github.com/documentcloud/backbone/">Backbone</a>
323
- supplies structure to JavaScript-heavy applications by providing <b>models</b> with
324
- key-value binding and custom events, <b>collections</b> with a rich API of enumerable functions,
325
- <b>views</b> with declarative event handling, and connects it all to your
326
- existing application over a RESTful JSON interface.
327
- </p>
328
-
329
- <p>
330
- The project is <a href="http://github.com/documentcloud/backbone/">hosted on GitHub</a>,
331
- and the <a href="docs/backbone.html">annotated source code</a> is available,
332
- as well as an online <a href="test/test.html">test suite</a>, an
333
- <a href="examples/todos/index.html">example application</a> and a
334
- <a href="https://github.com/documentcloud/backbone/wiki/Tutorials%2C-blog-posts-and-example-sites">list of tutorials</a>.
335
- </p>
336
-
337
- <p>
338
- You can report bugs and discuss features on the
339
- <a href="http://github.com/documentcloud/backbone/issues">GitHub issues page</a>,
340
- on Freenode IRC in the <tt>#documentcloud</tt> channel, post questions to the
341
- <a href="https://groups.google.com/forum/#!forum/backbonejs">Google Group</a>,
342
- or send tweets to <a href="http://twitter.com/documentcloud">@documentcloud</a>.
343
- </p>
344
-
345
- <p>
346
- <i>
347
- Backbone is an open-source component of
348
- <a href="http://documentcloud.org/">DocumentCloud</a>.
349
- </i>
350
- </p>
351
-
352
- <h2 id="downloads">
353
- Downloads &amp; Dependencies
354
- <span style="padding-left: 7px; font-size:11px; font-weight: normal;" class="interface">(Right-click, and use "Save As")</span>
355
- </h2>
356
-
357
- <table>
358
- <tr>
359
- <td><a href="backbone.js">Development Version (0.5.1)</a></td>
360
- <td><i>41kb, Full Source with Comments</i></td>
361
- </tr>
362
- <tr>
363
- <td><a href="backbone-min.js">Production Version (0.5.1)</a></td>
364
- <td><i>4.6kb, Packed and Gzipped</i></td>
365
- </tr>
366
- </table>
367
-
368
- <p>
369
- Backbone's only hard dependency is
370
- <a href="http://documentcloud.github.com/underscore/">Underscore.js</a>.
371
- For RESTful persistence, history support via <a href="#Router">Backbone.Router</a>
372
- and DOM manipulation with <a href="#View">Backbone.View</a>, include
373
- <a href="https://github.com/douglascrockford/JSON-js">json2.js</a>, and either
374
- <a href="http://jquery.com">jQuery</a> <small>( > 1.4.2)</small> or
375
- <a href="http://zeptojs.com/">Zepto</a>.
376
- </p>
377
-
378
- <h2 id="Upgrading">Upgrading to 0.5.0+</h2>
379
-
380
- <p>
381
- We've taken the opportunity to clarify some naming with the <b>0.5.0</b>
382
- release. <tt>Controller</tt> is now <a href="#Router">Router</a>, and
383
- <tt>refresh</tt> is now <a href="#Collection-reset">reset</a>.
384
- The previous <tt>saveLocation</tt> and <tt>setLocation</tt>
385
- functions have been replaced by <a href="#Router-navigate">navigate</a>.
386
- <tt>Backbone.sync</tt>'s method signature has changed to allow the passing
387
- of arbitrary options to <tt>jQuery.ajax</tt>.
388
- Be sure to <a href="#History-start">opt-in</a> to <tt>pushState</tt> support,
389
- if you want to use it.
390
- </p>
391
-
392
- <h2 id="Introduction">Introduction</h2>
393
-
394
- <p>
395
- When working on a web application that involves a lot of JavaScript, one
396
- of the first things you learn is to stop tying your data to the DOM. It's all
397
- too easy to create JavaScript applications that end up as tangled piles of
398
- jQuery selectors and callbacks, all trying frantically to keep data in
399
- sync between the HTML UI, your JavaScript logic, and the database on your
400
- server. For rich client-side applications, a more structured approach
401
- is often helpful.
402
- </p>
403
-
404
- <p>
405
- With Backbone, you represent your data as
406
- <a href="#Model">Models</a>, which can be created, validated, destroyed,
407
- and saved to the server. Whenever a UI action causes an attribute of
408
- a model to change, the model triggers a <i>"change"</i> event; all
409
- the <a href="#View">Views</a> that display the model's data are notified of the
410
- event, causing them to re-render. You don't have to write the glue
411
- code that looks into the DOM to find an element with a specific <i>id</i>,
412
- and update the HTML manually
413
- &mdash; when the model changes, the views simply update themselves.
414
- </p>
415
-
416
- <p>
417
- Many of the examples that follow are runnable. Click the <i>play</i> button
418
- to execute them.
419
- </p>
420
-
421
- <h2 id="Events">Backbone.Events</h2>
422
-
423
- <p>
424
- <b>Events</b> is a module that can be mixed in to any object, giving the
425
- object the ability to bind and trigger custom named events. Events do not
426
- have to be declared before they are bound, and may take passed arguments.
427
- For example:
428
- </p>
429
-
430
- <pre class="runnable">
431
- var object = {};
432
-
433
- _.extend(object, Backbone.Events);
434
-
435
- object.bind("alert", function(msg) {
436
- alert("Triggered " + msg);
437
- });
438
-
439
- object.trigger("alert", "an event");
440
- </pre>
441
-
442
- <p id="Events-bind">
443
- <b class="header">bind</b><code>object.bind(event, callback)</code>
444
- <br />
445
- Bind a <b>callback</b> function to an object. The callback will be invoked
446
- whenever the <b>event</b> (specified by an arbitrary string identifier) is fired.
447
- If you have a large number of different events on a page, the convention is to use colons to
448
- namespace them: <tt>"poll:start"</tt>, or <tt>"change:selection"</tt>
449
- </p>
450
-
451
- <p>
452
- Callbacks bound to the special
453
- <tt>"all"</tt> event will be triggered when any event occurs, and are passed
454
- the name of the event as the first argument. For example, to proxy all events
455
- from one object to another:
456
- </p>
457
-
458
- <pre>
459
- proxy.bind("all", function(eventName) {
460
- object.trigger(eventName);
461
- });
462
- </pre>
463
-
464
- <p id="Events-unbind">
465
- <b class="header">unbind</b><code>object.unbind([event], [callback])</code>
466
- <br />
467
- Remove a previously-bound <b>callback</b> function from an object. If no
468
- callback is specified, all callbacks for the <b>event</b> will be
469
- removed. If no event is specified, <i>all</i> event callbacks on the object
470
- will be removed.
471
- </p>
472
-
473
- <pre>
474
- object.unbind("change", onChange); // Removes just the onChange callback.
475
-
476
- object.unbind("change"); // Removes all "change" callbacks.
477
-
478
- object.unbind(); // Removes all callbacks on object.
479
- </pre>
480
-
481
- <p id="Events-trigger">
482
- <b class="header">trigger</b><code>object.trigger(event, [*args])</code>
483
- <br />
484
- Trigger callbacks for the given <b>event</b>. Subsequent arguments to
485
- <b>trigger</b> will be passed along to the event callbacks.
486
- </p>
487
-
488
- <h2 id="Model">Backbone.Model</h2>
489
-
490
- <p>
491
- <b>Models</b> are the heart of any JavaScript application, containing
492
- the interactive data as well as a large part of the logic surrounding it:
493
- conversions, validations, computed properties, and access control. You
494
- extend <b>Backbone.Model</b> with your domain-specific methods, and
495
- <b>Model</b> provides a basic set of functionality for managing changes.
496
- </p>
497
-
498
- <p>
499
- The following is a contrived example, but it demonstrates defining a model
500
- with a custom method, setting an attribute, and firing an event keyed
501
- to changes in that specific attribute.
502
- After running this code once, <tt>sidebar</tt> will be
503
- available in your browser's console, so you can play around with it.
504
- </p>
505
-
506
- <pre class="runnable">
507
- var Sidebar = Backbone.Model.extend({
508
- promptColor: function() {
509
- var cssColor = prompt("Please enter a CSS color:");
510
- this.set({color: cssColor});
511
- }
512
- });
513
-
514
- window.sidebar = new Sidebar;
515
-
516
- sidebar.bind('change:color', function(model, color) {
517
- $('#sidebar').css({background: color});
518
- });
519
-
520
- sidebar.set({color: 'white'});
521
-
522
- sidebar.promptColor();
523
- </pre>
524
-
525
- <p id="Model-extend">
526
- <b class="header">extend</b><code>Backbone.Model.extend(properties, [classProperties])</code>
527
- <br />
528
- To create a <b>Model</b> class of your own, you extend <b>Backbone.Model</b>
529
- and provide instance <b>properties</b>, as well as optional
530
- <b>classProperties</b> to be attached directly to the constructor function.
531
- </p>
532
-
533
- <p>
534
- <b>extend</b> correctly sets up the prototype chain, so subclasses created
535
- with <b>extend</b> can be further extended and subclassed as far as you like.
536
- </p>
537
-
538
- <pre>
539
- var Note = Backbone.Model.extend({
540
-
541
- initialize: function() { ... },
542
-
543
- author: function() { ... },
544
-
545
- coordinates: function() { ... },
546
-
547
- allowedToEdit: function(account) {
548
- return true;
549
- }
550
-
551
- });
552
-
553
- var PrivateNote = Note.extend({
554
-
555
- allowedToEdit: function(account) {
556
- return account.owns(this);
557
- }
558
-
559
- });
560
- </pre>
561
-
562
- <p class="warning">
563
- Brief aside on <tt>super</tt>: JavaScript does not provide
564
- a simple way to call super &mdash; the function of the same name defined
565
- higher on the prototype chain. If you override a core function like
566
- <tt>set</tt>, or <tt>save</tt>, and you want to invoke the
567
- parent object's implementation, you'll have to explicitly call it, along these lines:
568
- </p>
569
-
570
- <pre>
571
- var Note = Backbone.Model.extend({
572
- set: function(attributes, options) {
573
- Backbone.Model.prototype.set.call(this, attributes, options);
574
- ...
575
- }
576
- });
577
- </pre>
578
-
579
- <p id="Model-constructor">
580
- <b class="header">constructor / initialize</b><code>new Model([attributes])</code>
581
- <br />
582
- When creating an instance of a model, you can pass in the initial values
583
- of the <b>attributes</b>, which will be <a href="#Model-set">set</a> on the
584
- model. If you define an <b>initialize</b> function, it will be invoked when
585
- the model is created.
586
- </p>
587
-
588
- <pre>
589
- new Book({
590
- title: "One Thousand and One Nights",
591
- author: "Scheherazade"
592
- });
593
- </pre>
594
-
595
- <p id="Model-get">
596
- <b class="header">get</b><code>model.get(attribute)</code>
597
- <br />
598
- Get the current value of an attribute from the model. For example:
599
- <tt>note.get("title")</tt>
600
- </p>
601
-
602
- <p id="Model-set">
603
- <b class="header">set</b><code>model.set(attributes, [options])</code>
604
- <br />
605
- Set a hash of attributes (one or many) on the model. If any of the attributes
606
- change the models state, a <tt>"change"</tt> event will be triggered, unless
607
- <tt>{silent: true}</tt> is passed as an option. Change events for specific
608
- attributes are also triggered, and you can bind to those as well, for example:
609
- <tt>change:title</tt>, and <tt>change:content</tt>.
610
- </p>
611
-
612
- <pre>
613
- note.set({title: "October 12", content: "Lorem Ipsum Dolor Sit Amet..."});
614
- </pre>
615
-
616
- <p>
617
- If the model has a <a href="#Model-validate">validate</a> method,
618
- it will be validated before the attributes are set, no changes will
619
- occur if the validation fails, and <b>set</b> will return <tt>false</tt>.
620
- You may also pass an <tt>error</tt>
621
- callback in the options, which will be invoked instead of triggering an
622
- <tt>"error"</tt> event, should validation fail.
623
- </p>
624
-
625
- <p id="Model-escape">
626
- <b class="header">escape</b><code>model.escape(attribute)</code>
627
- <br />
628
- Similar to <a href="#Model-get">get</a>, but returns the HTML-escaped version
629
- of a model's attribute. If you're interpolating data from the model into
630
- HTML, using <b>escape</b> to retrieve attributes will prevent
631
- <a href="http://en.wikipedia.org/wiki/Cross-site_scripting">XSS</a> attacks.
632
- </p>
633
-
634
- <pre class="runnable">
635
- var hacker = new Backbone.Model({
636
- name: "&lt;script&gt;alert('xss')&lt;/script&gt;"
637
- });
638
-
639
- alert(hacker.escape('name'));
640
- </pre>
641
-
642
- <p id="Model-has">
643
- <b class="header">has</b><code>model.has(attribute)</code>
644
- <br />
645
- Returns <tt>true</tt> if the attribute is set to a non-null or non-undefined
646
- value.
647
- </p>
648
-
649
- <pre>
650
- if (note.has("title")) {
651
- ...
652
- }
653
- </pre>
654
-
655
- <p id="Model-unset">
656
- <b class="header">unset</b><code>model.unset(attribute, [options])</code>
657
- <br />
658
- Remove an attribute by deleting it from the internal attributes hash.
659
- Fires a <tt>"change"</tt> event unless <tt>silent</tt> is passed as an option.
660
- </p>
661
-
662
- <p id="Model-clear">
663
- <b class="header">clear</b><code>model.clear([options])</code>
664
- <br />
665
- Removes all attributes from the model. Fires a <tt>"change"</tt> event unless
666
- <tt>silent</tt> is passed as an option.
667
- </p>
668
-
669
- <p id="Model-id">
670
- <b class="header">id</b><code>model.id</code>
671
- <br />
672
- A special property of models, the <b>id</b> is an arbitrary string
673
- (integer id or UUID). If you set the <b>id</b> in the
674
- attributes hash, it will be copied onto the model as a direct property.
675
- Models can be retrieved by id from collections, and the id is used to generate
676
- model URLs by default.
677
- </p>
678
-
679
- <p id="Model-cid">
680
- <b class="header">cid</b><code>model.cid</code>
681
- <br />
682
- A special property of models, the <b>cid</b> or client id is a unique identifier
683
- automatically assigned to all models when they're first created. Client ids
684
- are handy when the model has not yet been saved to the server, and does not
685
- yet have its eventual true <b>id</b>, but already needs to be visible in the UI.
686
- Client ids take the form: <tt>c1, c2, c3 ...</tt>
687
- </p>
688
-
689
- <p id="Model-attributes">
690
- <b class="header">attributes</b><code>model.attributes</code>
691
- <br />
692
- The <b>attributes</b> property is the internal hash containing the model's
693
- state. Please use <a href="#Model-set">set</a> to update the attributes instead of modifying
694
- them directly. If you'd like to retrieve and munge a copy of the model's
695
- attributes, use <a href="#Model-toJSON">toJSON</a> instead.
696
- </p>
697
-
698
- <p id="Model-defaults">
699
- <b class="header">defaults</b><code>model.defaults or model.defaults()</code>
700
- <br />
701
- The <b>defaults</b> hash (or function) can be used to specify the default
702
- attributes for your model. When creating an instance of the model,
703
- any unspecified attributes will be set to their default value.
704
- </p>
705
-
706
- <pre class="runnable">
707
- var Meal = Backbone.Model.extend({
708
- defaults: {
709
- "appetizer": "caesar salad",
710
- "entree": "ravioli",
711
- "dessert": "cheesecake"
712
- }
713
- });
714
-
715
- alert("Dessert will be " + (new Meal).get('dessert'));
716
- </pre>
717
-
718
- <p class="warning">
719
- Remember that in JavaScript, objects are passed by reference, so if you
720
- include an object as a default value, it will be shared among all instances.
721
- </p>
722
-
723
- <p id="Model-toJSON">
724
- <b class="header">toJSON</b><code>model.toJSON()</code>
725
- <br />
726
- Return a copy of the model's <a href="#Model-attributes">attributes</a> for JSON stringification.
727
- This can be used for persistence, serialization, or for augmentation before
728
- being handed off to a view. The name of this method is a bit confusing, as
729
- it doesn't actually return a JSON string &mdash; but I'm afraid that it's
730
- the way that the <a href="https://developer.mozilla.org/en/JSON#toJSON()_method">JavaScript API for <b>JSON.stringify</b> works</a>.
731
- </p>
732
-
733
- <pre class="runnable">
734
- var artist = new Backbone.Model({
735
- firstName: "Wassily",
736
- lastName: "Kandinsky"
737
- });
738
-
739
- artist.set({birthday: "December 16, 1866"});
740
-
741
- alert(JSON.stringify(artist));
742
- </pre>
743
-
744
- <p id="Model-fetch">
745
- <b class="header">fetch</b><code>model.fetch([options])</code>
746
- <br />
747
- Resets the model's state from the server. Useful if the model has never
748
- been populated with data, or if you'd like to ensure that you have the
749
- latest server state. A <tt>"change"</tt> event will be triggered if the
750
- server's state differs from the current attributes. Accepts
751
- <tt>success</tt> and <tt>error</tt> callbacks in the options hash, which
752
- are passed <tt>(model, response)</tt> as arguments.
753
- </p>
754
-
755
- <pre>
756
- // Poll every 10 seconds to keep the channel model up-to-date.
757
- setInterval(function() {
758
- channel.fetch();
759
- }, 10000);
760
- </pre>
761
-
762
- <p id="Model-save">
763
- <b class="header">save</b><code>model.save([attributes], [options])</code>
764
- <br />
765
- Save a model to your database (or alternative persistence layer),
766
- by delegating to <a href="#Sync">Backbone.sync</a>. The <b>attributes</b>
767
- hash (as in <a href="#Model-set">set</a>) should contain the attributes
768
- you'd like to change -- keys that aren't mentioned won't be altered.
769
- If the model has a <a href="#Model-validate">validate</a>
770
- method, and validation fails, the model will not be saved. If the model
771
- <a href="#Model-isNew">isNew</a>, the save will be a <tt>"create"</tt>
772
- (HTTP <tt>POST</tt>), if the model already
773
- exists on the server, the save will be an <tt>"update"</tt> (HTTP <tt>PUT</tt>).
774
- </p>
775
-
776
- <p>
777
- In the following example, notice how our overridden version
778
- of <tt>Backbone.sync</tt> receives a <tt>"create"</tt> request
779
- the first time the model is saved and an <tt>"update"</tt>
780
- request the second time.
781
- </p>
782
-
783
- <pre class="runnable">
784
- Backbone.sync = function(method, model) {
785
- alert(method + ": " + JSON.stringify(model));
786
- model.id = 1;
787
- };
788
-
789
- var book = new Backbone.Model({
790
- title: "The Rough Riders",
791
- author: "Theodore Roosevelt"
792
- });
793
-
794
- book.save();
795
-
796
- book.save({author: "Teddy"});
797
- </pre>
798
-
799
- <p>
800
- <b>save</b> accepts <tt>success</tt> and <tt>error</tt> callbacks in the
801
- options hash, which are passed <tt>(model, response)</tt> as arguments.
802
- The <tt>error</tt> callback will also be invoked if the model has a
803
- <tt>validate</tt> method, and validation fails. If a server-side
804
- validation fails, return a non-<tt>200</tt> HTTP response code, along with
805
- an error response in text or JSON.
806
- </p>
807
-
808
- <pre>
809
- book.save({author: "F.D.R."}, {error: function(){ ... }});
810
- </pre>
811
-
812
- <p id="Model-destroy">
813
- <b class="header">destroy</b><code>model.destroy([options])</code>
814
- <br />
815
- Destroys the model on the server by delegating an HTTP <tt>DELETE</tt>
816
- request to <a href="#Sync">Backbone.sync</a>. Accepts
817
- <tt>success</tt> and <tt>error</tt> callbacks in the options hash.
818
- Triggers a <tt>"destroy"</tt> event on the model, which will bubble up
819
- through any collections that contain it.
820
- </p>
821
-
822
- <pre>
823
- book.destroy({success: function(model, response) {
824
- ...
825
- }});
826
- </pre>
827
-
828
- <p id="Model-validate">
829
- <b class="header">validate</b><code>model.validate(attributes)</code>
830
- <br />
831
- This method is left undefined, and you're encouraged to override it with
832
- your custom validation logic, if you have any that can be performed
833
- in JavaScript. <b>validate</b> is called before <tt>set</tt> and
834
- <tt>save</tt>, and is passed the attributes that are about to be updated.
835
- If the model and attributes are valid, don't return anything from <b>validate</b>;
836
- if the attributes are invalid, return an error of your choosing. It
837
- can be as simple as a string error message to be displayed, or a complete
838
- error object that describes the error programmatically. <tt>set</tt> and
839
- <tt>save</tt> will not continue if <b>validate</b> returns an error.
840
- Failed validations trigger an <tt>"error"</tt> event.
841
- </p>
842
-
843
- <pre class="runnable">
844
- var Chapter = Backbone.Model.extend({
845
- validate: function(attrs) {
846
- if (attrs.end < attrs.start) {
847
- return "can't end before it starts";
848
- }
849
- }
850
- });
851
-
852
- var one = new Chapter({
853
- title : "Chapter One: The Beginning"
854
- });
855
-
856
- one.bind("error", function(model, error) {
857
- alert(model.get("title") + " " + error);
858
- });
859
-
860
- one.set({
861
- start: 15,
862
- end: 10
863
- });
864
- </pre>
865
-
866
- <p>
867
- <tt>"error"</tt> events are useful for providing coarse-grained error
868
- messages at the model or collection level, but if you have a specific view
869
- that can better handle the error, you may override and suppress the event
870
- by passing an <tt>error</tt> callback directly:
871
- </p>
872
-
873
- <pre>
874
- account.set({access: "unlimited"}, {
875
- error: function(model, error) {
876
- alert(error);
877
- }
878
- });
879
- </pre>
880
-
881
- <p id="Model-url">
882
- <b class="header">url</b><code>model.url()</code>
883
- <br />
884
- Returns the relative URL where the model's resource would be located on
885
- the server. If your models are located somewhere else, override this method
886
- with the correct logic. Generates URLs of the form: <tt>"/[collection.url]/[id]"</tt>,
887
- falling back to <tt>"/[urlRoot]/id"</tt> if the model is not part of a collection.
888
- </p>
889
-
890
- <p>
891
- Delegates to <a href="#Collection-url">Collection#url</a> to generate the
892
- URL, so make sure that you have it defined, or a <a href="#Model-urlRoot">urlRoot</a>
893
- property, if all models of this class share a common root URL.
894
- A model with an id of <tt>101</tt>, stored in a
895
- <a href="#Collection">Backbone.Collection</a> with a <tt>url</tt> of <tt>"/documents/7/notes"</tt>,
896
- would have this URL: <tt>"/documents/7/notes/101"</tt>
897
- </p>
898
-
899
- <p id="Model-urlRoot">
900
- <b class="header">urlRoot</b><code>model.urlRoot</code>
901
- <br />
902
- Specify a <tt>urlRoot</tt> if you're using a model outside of a collection,
903
- to enable the default <a href="#Model-url">url</a> function to generate
904
- URLs based on the model id. <tt>"/[urlRoot]/id"</tt>
905
- </p>
906
-
907
- <pre class="runnable">
908
- var Book = Backbone.Model.extend({urlRoot : '/books'});
909
-
910
- var solaris = new Book({id: "1083-lem-solaris"});
911
-
912
- alert(solaris.url());
913
- </pre>
914
-
915
- <p id="Model-parse">
916
- <b class="header">parse</b><code>model.parse(response)</code>
917
- <br />
918
- <b>parse</b> is called whenever a model's data is returned by the
919
- server, in <a href="#Model-fetch">fetch</a>, and <a href="#Model-save">save</a>.
920
- The function is passed the raw <tt>response</tt> object, and should return
921
- the attributes hash to be <a href="#Model-set">set</a> on the model. The
922
- default implementation is a no-op, simply passing through the JSON response.
923
- Override this if you need to work with a preexisting API, or better namespace
924
- your responses.
925
- </p>
926
-
927
- <p>
928
- If you're working with a Rails backend, you'll notice that Rails' default
929
- <tt>to_json</tt> implementation includes a model's attributes under a
930
- namespace. To disable this behavior for seamless Backbone integration, set:
931
- </p>
932
-
933
- <pre>
934
- ActiveRecord::Base.include_root_in_json = false
935
- </pre>
936
-
937
- <p id="Model-clone">
938
- <b class="header">clone</b><code>model.clone()</code>
939
- <br />
940
- Returns a new instance of the model with identical attributes.
941
- </p>
942
-
943
- <p id="Model-isNew">
944
- <b class="header">isNew</b><code>model.isNew()</code>
945
- <br />
946
- Has this model been saved to the server yet? If the model does not yet have
947
- an <tt>id</tt>, it is considered to be new.
948
- </p>
949
-
950
- <p id="Model-change">
951
- <b class="header">change</b><code>model.change()</code>
952
- <br />
953
- Manually trigger the <tt>"change"</tt> event.
954
- If you've been passing <tt>{silent: true}</tt> to the <a href="#Model-set">set</a> function in order to
955
- aggregate rapid changes to a model, you'll want to call <tt>model.change()</tt>
956
- when you're all finished.
957
- </p>
958
-
959
- <p id="Model-hasChanged">
960
- <b class="header">hasChanged</b><code>model.hasChanged([attribute])</code>
961
- <br />
962
- Has the model changed since the last <tt>"change"</tt> event? If an <b>attribute</b>
963
- is passed, returns <tt>true</tt> if that specific attribute has changed.
964
- </p>
965
-
966
- <p class="warning">
967
- Note that this method, and the following change-related ones,
968
- are only useful during the course of a <tt>"change"</tt> event.
969
- </p>
970
-
971
- <pre>
972
- book.bind("change", function() {
973
- if (book.hasChanged("title")) {
974
- ...
975
- }
976
- });
977
- </pre>
978
-
979
- <p id="Model-changedAttributes">
980
- <b class="header">changedAttributes</b><code>model.changedAttributes([attributes])</code>
981
- <br />
982
- Retrieve a hash of only the model's attributes that have changed. Optionally,
983
- an external <b>attributes</b> hash can be passed in, returning
984
- the attributes in that hash which differ from the model. This can be used
985
- to figure out which portions of a view should be updated, or what calls
986
- need to be made to sync the changes to the server.
987
- </p>
988
-
989
- <p id="Model-previous">
990
- <b class="header">previous</b><code>model.previous(attribute)</code>
991
- <br />
992
- During a <tt>"change"</tt> event, this method can be used to get the
993
- previous value of a changed attribute.
994
- </p>
995
-
996
- <pre class="runnable">
997
- var bill = new Backbone.Model({
998
- name: "Bill Smith"
999
- });
1000
-
1001
- bill.bind("change:name", function(model, name) {
1002
- alert("Changed name from " + bill.previous("name") + " to " + name);
1003
- });
1004
-
1005
- bill.set({name : "Bill Jones"});
1006
- </pre>
1007
-
1008
- <p id="Model-previousAttributes">
1009
- <b class="header">previousAttributes</b><code>model.previousAttributes()</code>
1010
- <br />
1011
- Return a copy of the model's previous attributes. Useful for getting a
1012
- diff between versions of a model, or getting back to a valid state after
1013
- an error occurs.
1014
- </p>
1015
-
1016
- <h2 id="Collection">Backbone.Collection</h2>
1017
-
1018
- <p>
1019
- Collections are ordered sets of models. You can to bind <tt>"change"</tt> events
1020
- to be notified when any model in the collection has been modified,
1021
- listen for <tt>"add"</tt> and <tt>"remove"</tt> events, <tt>fetch</tt>
1022
- the collection from the server, and use a full suite of
1023
- <a href="#Collection-Underscore-Methods">Underscore.js methods</a>.
1024
- </p>
1025
-
1026
- <p>
1027
- Any event that is triggered on a model in a collection will also be
1028
- triggered on the collection directly, for convenience.
1029
- This allows you to listen for changes to specific attributes in any
1030
- model in a collection, for example:
1031
- <tt>Documents.bind("change:selected", ...)</tt>
1032
- </p>
1033
-
1034
- <p id="Collection-extend">
1035
- <b class="header">extend</b><code>Backbone.Collection.extend(properties, [classProperties])</code>
1036
- <br />
1037
- To create a <b>Collection</b> class of your own, extend <b>Backbone.Collection</b>,
1038
- providing instance <b>properties</b>, as well as optional <b>classProperties</b> to be attached
1039
- directly to the collection's constructor function.
1040
- </p>
1041
-
1042
- <p id="Collection-model">
1043
- <b class="header">model</b><code>collection.model</code>
1044
- <br />
1045
- Override this property to specify the model class that the collection
1046
- contains. If defined, you can pass raw attributes objects (and arrays) to
1047
- <a href="#Collection-add">add</a>, <a href="#Collection-create">create</a>,
1048
- and <a href="#Collection-reset">reset</a>, and the attributes will be
1049
- converted into a model of the proper type.
1050
- </p>
1051
-
1052
- <pre>
1053
- var Library = Backbone.Collection.extend({
1054
- model: Book
1055
- });
1056
- </pre>
1057
-
1058
- <p id="Collection-constructor">
1059
- <b class="header">constructor / initialize</b><code>new Collection([models], [options])</code>
1060
- <br />
1061
- When creating a Collection, you may choose to pass in the initial array of <b>models</b>.
1062
- The collection's <a href="#Collection-comparator">comparator</a> function
1063
- may be included as an option. If you define an <b>initialize</b> function, it will be
1064
- invoked when the collection is created.
1065
- </p>
1066
-
1067
- <pre>
1068
- var tabs = new TabSet([tab1, tab2, tab3]);
1069
- </pre>
1070
-
1071
- <p id="Collection-models">
1072
- <b class="header">models</b><code>collection.models</code>
1073
- <br />
1074
- Raw access to the JavaScript array of models inside of the collection. Usually you'll
1075
- want to use <tt>get</tt>, <tt>at</tt>, or the <b>Underscore methods</b>
1076
- to access model objects, but occasionally a direct reference to the array
1077
- is desired.
1078
- </p>
1079
-
1080
- <p id="Collection-toJSON">
1081
- <b class="header">toJSON</b><code>collection.toJSON()</code>
1082
- <br />
1083
- Return an array containing the attributes hash of each model in the
1084
- collection. This can be used to serialize and persist the
1085
- collection as a whole. The name of this method is a bit confusing, because
1086
- it conforms to
1087
- <a href="https://developer.mozilla.org/en/JSON#toJSON()_method">JavaScript's JSON API</a>.
1088
- </p>
1089
-
1090
- <pre class="runnable">
1091
- var collection = new Backbone.Collection([
1092
- {name: "Tim", age: 5},
1093
- {name: "Ida", age: 26},
1094
- {name: "Rob", age: 55}
1095
- ]);
1096
-
1097
- alert(JSON.stringify(collection));
1098
- </pre>
1099
-
1100
- <p id="Collection-Underscore-Methods">
1101
- <b class="header">Underscore Methods (25)</b>
1102
- <br />
1103
- Backbone proxies to <b>Underscore.js</b> to provide 25 iteration functions
1104
- on <b>Backbone.Collection</b>. They aren't all documented here, but
1105
- you can take a look at the Underscore documentation for the full details&hellip;
1106
- </p>
1107
-
1108
- <ul>
1109
- <li><a href="http://documentcloud.github.com/underscore/#each">forEach (each)</a></li>
1110
- <li><a href="http://documentcloud.github.com/underscore/#map">map</a></li>
1111
- <li><a href="http://documentcloud.github.com/underscore/#reduce">reduce (foldl, inject)</a></li>
1112
- <li><a href="http://documentcloud.github.com/underscore/#reduceRight">reduceRight (foldr)</a></li>
1113
- <li><a href="http://documentcloud.github.com/underscore/#detect">find (detect)</a></li>
1114
- <li><a href="http://documentcloud.github.com/underscore/#select">filter (select)</a></li>
1115
- <li><a href="http://documentcloud.github.com/underscore/#reject">reject</a></li>
1116
- <li><a href="http://documentcloud.github.com/underscore/#all">every (all)</a></li>
1117
- <li><a href="http://documentcloud.github.com/underscore/#any">some (any)</a></li>
1118
- <li><a href="http://documentcloud.github.com/underscore/#include">include</a></li>
1119
- <li><a href="http://documentcloud.github.com/underscore/#invoke">invoke</a></li>
1120
- <li><a href="http://documentcloud.github.com/underscore/#max">max</a></li>
1121
- <li><a href="http://documentcloud.github.com/underscore/#min">min</a></li>
1122
- <li><a href="http://documentcloud.github.com/underscore/#sortBy">sortBy</a></li>
1123
- <li><a href="http://documentcloud.github.com/underscore/#sortedIndex">sortedIndex</a></li>
1124
- <li><a href="http://documentcloud.github.com/underscore/#toArray">toArray</a></li>
1125
- <li><a href="http://documentcloud.github.com/underscore/#size">size</a></li>
1126
- <li><a href="http://documentcloud.github.com/underscore/#first">first</a></li>
1127
- <li><a href="http://documentcloud.github.com/underscore/#rest">rest</a></li>
1128
- <li><a href="http://documentcloud.github.com/underscore/#last">last</a></li>
1129
- <li><a href="http://documentcloud.github.com/underscore/#without">without</a></li>
1130
- <li><a href="http://documentcloud.github.com/underscore/#indexOf">indexOf</a></li>
1131
- <li><a href="http://documentcloud.github.com/underscore/#lastIndexOf">lastIndexOf</a></li>
1132
- <li><a href="http://documentcloud.github.com/underscore/#isEmpty">isEmpty</a></li>
1133
- <li><a href="http://documentcloud.github.com/underscore/#chain">chain</a></li>
1134
- </ul>
1135
-
1136
- <pre>
1137
- Books.each(function(book) {
1138
- book.publish();
1139
- });
1140
-
1141
- var titles = Books.map(function(book) {
1142
- return book.get("title");
1143
- });
1144
-
1145
- var publishedBooks = Books.filter(function(book) {
1146
- return book.get("published") === true;
1147
- });
1148
-
1149
- var alphabetical = Books.sortBy(function(book) {
1150
- return book.author.get("name").toLowerCase();
1151
- });
1152
- </pre>
1153
-
1154
- <p id="Collection-add">
1155
- <b class="header">add</b><code>collection.add(models, [options])</code>
1156
- <br />
1157
- Add a model (or an array of models) to the collection. Fires an <tt>"add"</tt>
1158
- event, which you can pass <tt>{silent: true}</tt> to suppress. If a
1159
- <a href="#Collection-model">model</a> property is defined, you may also pass
1160
- raw attributes objects, and have them be vivified as instances of the model.
1161
- Pass <tt>{at: index}</tt> to splice the model into the collection at the
1162
- specified <tt>index</tt>.
1163
- </p>
1164
-
1165
- <pre class="runnable">
1166
- var ships = new Backbone.Collection;
1167
-
1168
- ships.bind("add", function(ship) {
1169
- alert("Ahoy " + ship.get("name") + "!");
1170
- });
1171
-
1172
- ships.add([
1173
- {name: "Flying Dutchman"},
1174
- {name: "Black Pearl"}
1175
- ]);
1176
- </pre>
1177
-
1178
- <p id="Collection-remove">
1179
- <b class="header">remove</b><code>collection.remove(models, [options])</code>
1180
- <br />
1181
- Remove a model (or an array of models) from the collection. Fires a
1182
- <tt>"remove"</tt> event, which you can use <tt>silent</tt>
1183
- to suppress.
1184
- </p>
1185
-
1186
- <p id="Collection-get">
1187
- <b class="header">get</b><code>collection.get(id)</code>
1188
- <br />
1189
- Get a model from a collection, specified by <b>id</b>.
1190
- </p>
1191
-
1192
- <pre>
1193
- var book = Library.get(110);
1194
- </pre>
1195
-
1196
- <p id="Collection-getByCid">
1197
- <b class="header">getByCid</b><code>collection.getByCid(cid)</code>
1198
- <br />
1199
- Get a model from a collection, specified by client id. The client id
1200
- is the <tt>.cid</tt> property of the model, automatically assigned whenever
1201
- a model is created. Useful for models which have not yet been saved to
1202
- the server, and do not yet have true ids.
1203
- </p>
1204
-
1205
- <p id="Collection-at">
1206
- <b class="header">at</b><code>collection.at(index)</code>
1207
- <br />
1208
- Get a model from a collection, specified by index. Useful if your collection
1209
- is sorted, and if your collection isn't sorted, <b>at</b> will still
1210
- retrieve models in insertion order.
1211
- </p>
1212
-
1213
- <p id="Collection-length">
1214
- <b class="header">length</b><code>collection.length</code>
1215
- <br />
1216
- Like an array, a Collection maintains a <tt>length</tt> property, counting
1217
- the number of models it contains.
1218
- </p>
1219
-
1220
- <p id="Collection-comparator">
1221
- <b class="header">comparator</b><code>collection.comparator</code>
1222
- <br />
1223
- By default there is no <b>comparator</b> function on a collection.
1224
- If you define a comparator, it will be used to maintain
1225
- the collection in sorted order. This means that as models are added,
1226
- they are inserted at the correct index in <tt>collection.models</tt>.
1227
- Comparator functions take a model and return a numeric or string value
1228
- by which the model should be ordered relative to others.
1229
- </p>
1230
-
1231
- <p>
1232
- Note how even though all of the chapters in this example are added backwards,
1233
- they come out in the proper order:
1234
- </p>
1235
-
1236
- <pre class="runnable">
1237
- var Chapter = Backbone.Model;
1238
- var chapters = new Backbone.Collection;
1239
-
1240
- chapters.comparator = function(chapter) {
1241
- return chapter.get("page");
1242
- };
1243
-
1244
- chapters.add(new Chapter({page: 9, title: "The End"}));
1245
- chapters.add(new Chapter({page: 5, title: "The Middle"}));
1246
- chapters.add(new Chapter({page: 1, title: "The Beginning"}));
1247
-
1248
- alert(chapters.pluck('title'));
1249
- </pre>
1250
-
1251
- <p class="warning">
1252
- Brief aside: This comparator function is different than JavaScript's regular
1253
- "sort", which must return <tt>0</tt>, <tt>1</tt>, or <tt>-1</tt>,
1254
- and is more similar to a <tt>sortBy</tt> &mdash; a much nicer API.
1255
- </p>
1256
-
1257
- <p id="Collection-sort">
1258
- <b class="header">sort</b><code>collection.sort([options])</code>
1259
- <br />
1260
- Force a collection to re-sort itself. You don't need to call this under
1261
- normal circumstances, as a collection with a <a href="#Collection-comparator">comparator</a> function
1262
- will maintain itself in proper sort order at all times. Calling <b>sort</b>
1263
- triggers the collection's <tt>"reset"</tt> event, unless silenced by passing
1264
- <tt>{silent: true}</tt>
1265
- </p>
1266
-
1267
- <p id="Collection-pluck">
1268
- <b class="header">pluck</b><code>collection.pluck(attribute)</code>
1269
- <br />
1270
- Pluck an attribute from each model in the collection. Equivalent to calling
1271
- <tt>map</tt>, and returning a single attribute from the iterator.
1272
- </p>
1273
-
1274
- <pre class="runnable">
1275
- var stooges = new Backbone.Collection([
1276
- new Backbone.Model({name: "Curly"}),
1277
- new Backbone.Model({name: "Larry"}),
1278
- new Backbone.Model({name: "Moe"})
1279
- ]);
1280
-
1281
- var names = stooges.pluck("name");
1282
-
1283
- alert(JSON.stringify(names));
1284
- </pre>
1285
-
1286
- <p id="Collection-url">
1287
- <b class="header">url</b><code>collection.url or collection.url()</code>
1288
- <br />
1289
- Set the <b>url</b> property (or function) on a collection to reference
1290
- its location on the server. Models within the collection will use <b>url</b>
1291
- to construct URLs of their own.
1292
- </p>
1293
-
1294
- <pre>
1295
- var Notes = Backbone.Collection.extend({
1296
- url: '/notes'
1297
- });
1298
-
1299
- // Or, something more sophisticated:
1300
-
1301
- var Notes = Backbone.Collection.extend({
1302
- url: function() {
1303
- return this.document.url() + '/notes';
1304
- }
1305
- });
1306
- </pre>
1307
-
1308
- <p id="Collection-parse">
1309
- <b class="header">parse</b><code>collection.parse(response)</code>
1310
- <br />
1311
- <b>parse</b> is called by Backbone whenever a collection's models are
1312
- returned by the server, in <a href="#Collection-fetch">fetch</a>.
1313
- The function is passed the raw <tt>response</tt> object, and should return
1314
- the array of model attributes to be <a href="#Collection-add">added</a>
1315
- to the collection. The default implementation is a no-op, simply passing
1316
- through the JSON response. Override this if you need to work with a
1317
- preexisting API, or better namespace your responses.
1318
- </p>
1319
-
1320
- <pre>
1321
- var Tweets = Backbone.Collection.extend({
1322
- // The Twitter Search API returns tweets under "results".
1323
- parse: function(response) {
1324
- return response.results;
1325
- }
1326
- });
1327
- </pre>
1328
-
1329
- <p id="Collection-fetch">
1330
- <b class="header">fetch</b><code>collection.fetch([options])</code>
1331
- <br />
1332
- Fetch the default set of models for this collection from the server,
1333
- resetting the collection when they arrive. The <b>options</b> hash takes
1334
- <tt>success</tt> and <tt>error</tt>
1335
- callbacks which will be passed <tt>(collection, response)</tt> as arguments.
1336
- When the model data returns from the server, the collection will
1337
- <a href="#Collection-reset">reset</a>.
1338
- Delegates to <a href="#Sync">Backbone.sync</a>
1339
- under the covers, for custom persistence strategies.
1340
- The server handler for <b>fetch</b> requests should return a JSON array of
1341
- models.
1342
- </p>
1343
-
1344
- <pre class="runnable">
1345
- Backbone.sync = function(method, model) {
1346
- alert(method + ": " + model.url);
1347
- };
1348
-
1349
- var Accounts = new Backbone.Collection;
1350
- Accounts.url = '/accounts';
1351
-
1352
- Accounts.fetch();
1353
- </pre>
1354
-
1355
- <p>
1356
- If you'd like to add the incoming models to the current collection, instead
1357
- of replacing the collection's contents, pass <tt>{add: true}</tt> as an
1358
- option to <b>fetch</b>.
1359
- </p>
1360
-
1361
- <p>
1362
- <b>jQuery.ajax</b> options can also be passed directly as <b>fetch</b> options,
1363
- so to fetch a specific page of a paginated collection:
1364
- <tt>Documents.fetch({data: {page: 3}})</tt>
1365
- </p>
1366
-
1367
- <p>
1368
- Note that <b>fetch</b> should not be used to populate collections on
1369
- page load &mdash; all models needed at load time should already be
1370
- <a href="#FAQ-bootstrap">bootstrapped</a> in to place. <b>fetch</b> is
1371
- intended for lazily-loading models for interfaces that are not needed
1372
- immediately: for example, documents with collections of notes that may be
1373
- toggled open and closed.
1374
- </p>
1375
-
1376
- <p id="Collection-reset">
1377
- <b class="header">reset</b><code>collection.reset(models, [options])</code>
1378
- <br />
1379
- Adding and removing models one at a time is all well and good, but sometimes
1380
- you have so many models to change that you'd rather just update the collection
1381
- in bulk. Use <b>reset</b> to replace a collection with a new list
1382
- of models (or attribute hashes), triggering a single <tt>"reset"</tt> event
1383
- at the end. Pass <tt>{silent: true}</tt> to suppress the <tt>"reset"</tt> event.
1384
- Using reset with no arguments is useful as a way to empty the collection.
1385
- </p>
1386
-
1387
- <p>
1388
- Here's an example using <b>reset</b> to bootstrap a collection during initial page load,
1389
- in a Rails application.
1390
- </p>
1391
-
1392
- <pre>
1393
- &lt;script&gt;
1394
- Accounts.reset(&lt;%= @accounts.to_json %&gt;);
1395
- &lt;/script&gt;
1396
- </pre>
1397
-
1398
- <p>
1399
- Calling <tt>collection.reset()</tt> without passing any models as arguments
1400
- will empty the entire collection.
1401
- </p>
1402
-
1403
- <p id="Collection-create">
1404
- <b class="header">create</b><code>collection.create(attributes, [options])</code>
1405
- <br />
1406
- Convenience to create a new instance of a model within a collection.
1407
- Equivalent to instantiating a model with a hash of attributes,
1408
- saving the model to the server, and adding the model to the set after being
1409
- successfully created. Returns
1410
- the model, or <tt>false</tt> if a validation error prevented the
1411
- model from being created. In order for this to work, you should set the
1412
- <a href="#Collection-model">model</a> property of the collection.
1413
- The <b>create</b> method can accept either an attributes hash or an
1414
- existing, unsaved model object.
1415
- </p>
1416
-
1417
- <pre>
1418
- var Library = Backbone.Collection.extend({
1419
- model: Book
1420
- });
1421
-
1422
- var NYPL = new Library;
1423
-
1424
- var othello = NYPL.create({
1425
- title: "Othello",
1426
- author: "William Shakespeare"
1427
- });
1428
- </pre>
1429
-
1430
- <h2 id="Router">Backbone.Router</h2>
1431
-
1432
- <p>
1433
- Web applications often choose to change their URL fragment (<tt>#fragment</tt>)
1434
- in order to provide shareable, bookmarkable URLs for an Ajax-heavy application.
1435
- <b>Backbone.Router</b> provides methods for routing client-side URL
1436
- fragments, and connecting them to actions and events.
1437
- </p>
1438
-
1439
- <p>
1440
- During page load, after your application has finished creating all of its routers,
1441
- be sure to call <tt>Backbone.history.start()</tt>, or
1442
- <tt>Backbone.history.start({pushState: true})</tt> to route the initial URL.
1443
- </p>
1444
-
1445
- <p id="Router-extend">
1446
- <b class="header">extend</b><code>Backbone.Router.extend(properties, [classProperties])</code>
1447
- <br />
1448
- Get started by creating a custom router class. You'll
1449
- want to define actions that are triggered when certain URL fragments are
1450
- matched, and provide a <a href="#Router-routes">routes</a> hash
1451
- that pairs routes to actions.
1452
- </p>
1453
-
1454
- <pre>
1455
- var Workspace = Backbone.Router.extend({
1456
-
1457
- routes: {
1458
- "help": "help", // #help
1459
- "search/:query": "search", // #search/kiwis
1460
- "search/:query/p:page": "search" // #search/kiwis/p7
1461
- },
1462
-
1463
- help: function() {
1464
- ...
1465
- },
1466
-
1467
- search: function(query, page) {
1468
- ...
1469
- }
1470
-
1471
- });
1472
- </pre>
1473
-
1474
- <p id="Router-routes">
1475
- <b class="header">routes</b><code>router.routes</code>
1476
- <br />
1477
- The routes hash maps URLs with parameters to functions on your router,
1478
- similar to the <a href="#View">View</a>'s <a href="#View-delegateEvents">events hash</a>.
1479
- Routes can contain parameter parts, <tt>:param</tt>, which match a single URL
1480
- component between slashes; and splat parts <tt>*splat</tt>, which can match
1481
- any number of URL components.
1482
- </p>
1483
-
1484
- <p>
1485
- For example, a route of <tt>"search/:query/p:page"</tt> will match
1486
- a fragment of <tt>#search/obama/p2</tt>, passing <tt>"obama"</tt>
1487
- and <tt>"2"</tt> to the action. A route of <tt>"file/*path"</tt> will
1488
- match <tt>#file/nested/folder/file.txt</tt>,
1489
- passing <tt>"nested/folder/file.txt"</tt> to the action.
1490
- </p>
1491
-
1492
- <p>
1493
- When the visitor presses the back button, or enters a URL, and a particular
1494
- route is matched, the name of the action will be fired as an
1495
- <a href="#Events">event</a>, so that other objects can listen to the router,
1496
- and be notified. In the following example, visiting <tt>#help/uploading</tt>
1497
- will fire a <tt>route:help</tt> event from the router.
1498
- </p>
1499
-
1500
- <pre>
1501
- routes: {
1502
- "help/:page": "help",
1503
- "download/*path": "download",
1504
- "folder/:name": "openFolder",
1505
- "folder/:name-:mode": "openFolder"
1506
- }
1507
- </pre>
1508
-
1509
- <pre>
1510
- router.bind("route:help", function(page) {
1511
- ...
1512
- });
1513
- </pre>
1514
-
1515
- <p id="Router-constructor">
1516
- <b class="header">constructor / initialize</b><code>new Router([options])</code>
1517
- <br />
1518
- When creating a new router, you may pass its
1519
- <a href="#Router-routes">routes</a> hash directly as an option, if you
1520
- choose. All <tt>options</tt> will also be passed to your <tt>initialize</tt>
1521
- function, if defined.
1522
- </p>
1523
-
1524
- <p id="Router-route">
1525
- <b class="header">route</b><code>router.route(route, name, callback)</code>
1526
- <br />
1527
- Manually create a route for the router, The <tt>route</tt> argument may
1528
- be a <a href="#Router-routes">routing string</a> or regular expression.
1529
- Each matching capture from the route or regular expression will be passed as
1530
- an argument to the callback. The <tt>name</tt> argument will be triggered as
1531
- a <tt>"route:name"</tt> event whenever the route is matched.
1532
- </p>
1533
-
1534
- <pre>
1535
- initialize: function(options) {
1536
-
1537
- // Matches #page/10, passing "10"
1538
- this.route("page/:number", "page", function(number){ ... });
1539
-
1540
- // Matches /117-a/b/c/open, passing "117-a/b/c"
1541
- this.route(/^(.*?)\/open$/, "open", function(id){ ... });
1542
-
1543
- }
1544
- </pre>
1545
-
1546
- <p id="Router-navigate">
1547
- <b class="header">navigate</b><code>router.navigate(fragment, [triggerRoute])</code>
1548
- <br />
1549
- Whenever you reach a point in your application that you'd like to save
1550
- as a URL, call <b>navigate</b> in order to update the URL.
1551
- If you wish to also call the route function, pass <b>triggerRoute</b>.
1552
- </p>
1553
-
1554
- <pre>
1555
- openPage: function(pageNumber) {
1556
- this.document.pages.at(pageNumber).open();
1557
- this.navigate("page/" + pageNumber);
1558
- }
1559
-
1560
- # Or ...
1561
-
1562
- app.navigate("help/troubleshooting", true);
1563
- </pre>
1564
-
1565
- <h2 id="History">Backbone.history</h2>
1566
-
1567
- <p>
1568
- <b>History</b> serves as a global router (per frame) to handle <tt>hashchange</tt>
1569
- events or <tt>pushState</tt>, match the appropriate route, and trigger callbacks. You shouldn't
1570
- ever have to create one of these yourself &mdash; you should use the reference
1571
- to <tt>Backbone.history</tt> that will be created for you automatically if you make use
1572
- of <a href="#Router">Routers</a> with <a href="#Router-routes">routes</a>.
1573
- </p>
1574
-
1575
- <p>
1576
- <b>pushState</b> support exists on a purely opt-in basis in Backbone.
1577
- Older browsers that don't support <tt>pushState</tt> will continue to use
1578
- hash-based URL fragments, and if a hash URL is visited by a
1579
- <tt>pushState</tt>-capable browser, it will be transparently upgraded to
1580
- the true URL. Note that using real URLs requires your web server to be
1581
- able to correctly render those pages, so back-end changes are required
1582
- as well. For example, if you have a route of <tt>/documents/100</tt>,
1583
- your web server must be able to serve that page, if the browser
1584
- visits that URL directly. For full search-engine crawlability, it's best to
1585
- have the server generate the complete HTML for the page ... but if it's a web
1586
- application, just rendering the same content you would have for the root URL,
1587
- and filling in the rest with Backbone Views and JavaScript works fine.
1588
- </p>
1589
-
1590
- <p id="History-start">
1591
- <b class="header">start</b><code>Backbone.history.start([options])</code>
1592
- <br />
1593
- When all of your <a href="#Router">Routers</a> have been created,
1594
- and all of the routes are set up properly, call <tt>Backbone.history.start()</tt>
1595
- to begin monitoring <tt>hashchange</tt> events, and dispatching routes.
1596
- </p>
1597
-
1598
- <p>
1599
- To indicate that you'd like to use HTML5 <tt>pushState</tt> support in
1600
- your application, use <tt>Backbone.history.start({pushState: true})</tt>.
1601
- </p>
1602
-
1603
- <p>
1604
- If your application is not being served from the root url <tt>/</tt> of your
1605
- domain, be sure to tell History where the root really is, as an option:
1606
- <tt>Backbone.history.start({pushState: true, root: "/public/search/"})</tt>
1607
- <p>
1608
- When called, if a route succeeds with a match for the current URL,
1609
- <tt>Backbone.history.start()</tt> returns <tt>true</tt>. If no defined
1610
- route matches the current URL, it returns <tt>false</tt>.
1611
- </p>
1612
-
1613
- <pre>
1614
- $(function(){
1615
- new WorkspaceRouter();
1616
- new HelpPaneRouter();
1617
- Backbone.history.start({pushState: true});
1618
- });
1619
- </pre>
1620
-
1621
- <h2 id="Sync">Backbone.sync</h2>
1622
-
1623
- <p>
1624
- <b>Backbone.sync</b> is the function that Backbone calls every time it
1625
- attempts to read or save a model to the server. By default, it uses
1626
- <tt>(jQuery/Zepto).ajax</tt> to make a RESTful JSON request. You can override
1627
- it in order to use a different persistence strategy, such as WebSockets,
1628
- XML transport, or Local Storage.
1629
- </p>
1630
-
1631
- <p>
1632
- The method signature of <b>Backbone.sync</b> is <tt>sync(method, model, [options])</tt>
1633
- </p>
1634
-
1635
- <ul>
1636
- <li><b>method</b> – the CRUD method (<tt>"create"</tt>, <tt>"read"</tt>, <tt>"update"</tt>, or <tt>"delete"</tt>)</li>
1637
- <li><b>model</b> – the model to be saved (or collection to be read)</li>
1638
- <li><b>options</b> – success and error callbacks, and all other jQuery request options</li>
1639
- </ul>
1640
-
1641
- <p>
1642
- With the default implementation, when <b>Backbone.sync</b> sends up a request to save
1643
- a model, its attributes will be passed, serialized as JSON, and sent in the HTTP body
1644
- with content-type <tt>application/json</tt>. When returning a JSON response,
1645
- send down the attributes of the model that have been changed by the server, and need
1646
- to be updated on the client. When responding to a <tt>"read"</tt> request from a collection
1647
- (<a href="#Collection#fetch">Collection#fetch</a>), send down an array
1648
- of model attribute objects.
1649
- </p>
1650
-
1651
- <p>
1652
- The default <b>sync</b> handler maps CRUD to REST like so:
1653
- </p>
1654
-
1655
- <ul>
1656
- <li><b>create &rarr; POST &nbsp; </b><tt>/collection</tt></li>
1657
- <li><b>read &rarr; GET &nbsp; </b><tt>/collection[/id]</tt></li>
1658
- <li><b>update &rarr; PUT &nbsp; </b><tt>/collection/id</tt></li>
1659
- <li><b>delete &rarr; DELETE &nbsp; </b><tt>/collection/id</tt></li>
1660
- </ul>
1661
-
1662
- <p>
1663
- As an example, a Rails handler responding to an <tt>"update"</tt> call from
1664
- <tt>Backbone</tt> might look like this: <i>(In real code, never use
1665
- </i><tt>update_attributes</tt><i> blindly, and always whitelist the attributes
1666
- you allow to be changed.)</i>
1667
- </p>
1668
-
1669
- <pre>
1670
- def update
1671
- account = Account.find params[:id]
1672
- account.update_attributes params
1673
- render :json => account
1674
- end
1675
- </pre>
1676
-
1677
- <p>
1678
- One more tip for Rails integration is to disable the default namespacing for
1679
- <tt>to_json</tt> calls on models by setting <tt>ActiveRecord::Base.include_root_in_json = false</tt>
1680
- </p>
1681
-
1682
- <p id="Sync-emulateHTTP">
1683
- <b class="header">emulateHTTP</b><code>Backbone.emulateHTTP = true</code>
1684
- <br />
1685
- If you want to work with a legacy web server that doesn't support Backbones's
1686
- default REST/HTTP approach, you may choose to turn on <tt>Backbone.emulateHTTP</tt>.
1687
- Setting this option will fake <tt>PUT</tt> and <tt>DELETE</tt> requests with
1688
- a HTTP <tt>POST</tt>, and pass them under the <tt>_method</tt> parameter. Setting this option
1689
- will also set an <tt>X-HTTP-Method-Override</tt> header with the true method.
1690
- </p>
1691
-
1692
- <pre>
1693
- Backbone.emulateHTTP = true;
1694
-
1695
- model.save(); // POST to "/collection/id", with "_method=PUT" + header.
1696
- </pre>
1697
-
1698
- <p id="Sync-emulateJSON">
1699
- <b class="header">emulateJSON</b><code>Backbone.emulateJSON = true</code>
1700
- <br />
1701
- If you're working with a legacy web server that can't handle requests
1702
- encoded as <tt>application/json</tt>, setting <tt>Backbone.emulateJSON = true;</tt>
1703
- will cause the JSON to be serialized under a <tt>model</tt> parameter, and
1704
- the request to be made with a <tt>application/x-www-form-urlencoded</tt>
1705
- mime type, as if from an HTML form.
1706
- </p>
1707
-
1708
- <h2 id="View">Backbone.View</h2>
1709
-
1710
- <p>
1711
- Backbone views are almost more convention than they are code &mdash; they
1712
- don't determine anything about your HTML or CSS for you, and can be used
1713
- with any JavaScript templating library.
1714
- The general idea is to organize your interface into logical views,
1715
- backed by models, each of which can be updated independently when the
1716
- model changes, without having to redraw the page. Instead of digging into
1717
- a JSON object, looking up an element in the DOM, and updating the HTML by hand,
1718
- you can bind your view's <tt>render</tt> function to the model's <tt>"change"</tt>
1719
- event &mdash; and now everywhere that
1720
- model data is displayed in the UI, it is always immediately up to date.
1721
- </p>
1722
-
1723
- <p id="View-extend">
1724
- <b class="header">extend</b><code>Backbone.View.extend(properties, [classProperties])</code>
1725
- <br />
1726
- Get started with views by creating a custom view class. You'll want to
1727
- override the <a href="#View-render">render</a> function, specify your
1728
- declarative <a href="#View-delegateEvents">events</a>, and perhaps the
1729
- <tt>tagName</tt>, <tt>className</tt>, or <tt>id</tt> of the View's root
1730
- element.
1731
- </p>
1732
-
1733
- <pre>
1734
- var DocumentRow = Backbone.View.extend({
1735
-
1736
- tagName: "li",
1737
-
1738
- className: "document-row",
1739
-
1740
- events: {
1741
- "click .icon": "open",
1742
- "click .button.edit": "openEditDialog",
1743
- "click .button.delete": "destroy"
1744
- },
1745
-
1746
- initialize: function() {
1747
- _.bindAll(this, "render");
1748
- },
1749
-
1750
- render: function() {
1751
- ...
1752
- }
1753
-
1754
- });
1755
- </pre>
1756
-
1757
- <p id="View-constructor">
1758
- <b class="header">constructor / initialize</b><code>new View([options])</code>
1759
- <br />
1760
- When creating a new View, the options you pass are attached to the view
1761
- as <tt>this.options</tt>, for future reference. There are several special
1762
- options that, if passed, will be attached directly to the view:
1763
- <tt>model</tt>, <tt>collection</tt>,
1764
- <tt>el</tt>, <tt>id</tt>, <tt>className</tt>, and <tt>tagName</tt>.
1765
- If the view defines an <b>initialize</b> function, it will be called when
1766
- the view is first created. If you'd like to create a view that references
1767
- an element <i>already</i> in the DOM, pass in the element as an option:
1768
- <tt>new View({el: existingElement})</tt>
1769
- </p>
1770
-
1771
- <pre>
1772
- var doc = Documents.first();
1773
-
1774
- new DocumentRow({
1775
- model: doc,
1776
- id: "document-row-" + doc.id
1777
- });
1778
- </pre>
1779
-
1780
- <p id="View-el">
1781
- <b class="header">el</b><code>view.el</code>
1782
- <br />
1783
- All views have a DOM element at all times (the <b>el</b> property),
1784
- whether they've already been inserted into the page or not. In this
1785
- fashion, views can be rendered at any time, and inserted into the DOM all
1786
- at once, in order to get high-performance UI rendering with as few
1787
- reflows and repaints as possible. <tt>this.el</tt> is created from the
1788
- view's <tt>tagName</tt>, <tt>className</tt>, and <tt>id</tt> properties,
1789
- if specified. If not, <b>el</b> is an empty <tt>div</tt>.
1790
- </p>
1791
-
1792
- <p>
1793
- You may assign <b>el</b> directly if the view is being
1794
- created for an element that already exists in the DOM. Use either a
1795
- reference to a real DOM element, or a css selector string.
1796
- </p>
1797
-
1798
- <pre class="runnable">
1799
- var ItemView = Backbone.View.extend({
1800
- tagName: 'li'
1801
- });
1802
-
1803
- var BodyView = Backbone.View.extend({
1804
- el: 'body'
1805
- });
1806
-
1807
- var item = new ItemView();
1808
- var body = new BodyView();
1809
-
1810
- alert(item.el + ' ' + body.el);
1811
- </pre>
1812
-
1813
- <p id="View-dollar">
1814
- <b class="header">$ (jQuery or Zepto)</b><code>view.$(selector)</code>
1815
- <br />
1816
- If jQuery or Zepto is included on the page, each view has a
1817
- <b>$</b> function that runs queries scoped within the view's element. If you use this
1818
- scoped jQuery function, you don't have to use model ids as part of your query
1819
- to pull out specific elements in a list, and can rely much more on HTML class
1820
- attributes. It's equivalent to running: <tt>$(selector, this.el)</tt>
1821
- </p>
1822
-
1823
- <pre>
1824
- ui.Chapter = Backbone.View.extend({
1825
- serialize : function() {
1826
- return {
1827
- title: this.$(".title").text(),
1828
- start: this.$(".start-page").text(),
1829
- end: this.$(".end-page").text()
1830
- };
1831
- }
1832
- });
1833
- </pre>
1834
-
1835
- <p id="View-render">
1836
- <b class="header">render</b><code>view.render()</code>
1837
- <br />
1838
- The default implementation of <b>render</b> is a no-op. Override this
1839
- function with your code that renders the view template from model data,
1840
- and updates <tt>this.el</tt> with the new HTML. A good
1841
- convention is to <tt>return this</tt> at the end of <b>render</b> to
1842
- enable chained calls.
1843
- </p>
1844
-
1845
- <pre>
1846
- var Bookmark = Backbone.View.extend({
1847
- render: function() {
1848
- $(this.el).html(this.template(this.model.toJSON()));
1849
- return this;
1850
- }
1851
- });
1852
- </pre>
1853
-
1854
- <p>
1855
- Backbone is agnostic with respect to your preferred method of HTML templating.
1856
- Your <b>render</b> function could even munge together an HTML string, or use
1857
- <tt>document.createElement</tt> to generate a DOM tree. However, we suggest
1858
- choosing a nice JavaScript templating library.
1859
- <a href="http://github.com/janl/mustache.js">Mustache.js</a>,
1860
- <a href="http://github.com/creationix/haml-js">Haml-js</a>, and
1861
- <a href="http://github.com/sstephenson/eco">Eco</a> are all fine alternatives.
1862
- Because <a href="http://documentcloud.github.com/underscore/">Underscore.js</a> is already on the page,
1863
- <a href="http://documentcloud.github.com/underscore/#template">_.template</a>
1864
- is available, and is an excellent choice if you've already XSS-sanitized
1865
- your interpolated data.
1866
- </p>
1867
-
1868
- <p>
1869
- Whatever templating strategy you end up with, it's nice if you <i>never</i>
1870
- have to put strings of HTML in your JavaScript. At DocumentCloud, we
1871
- use <a href="http://documentcloud.github.com/jammit/">Jammit</a> in order
1872
- to package up JavaScript templates stored in <tt>/app/views</tt> as part
1873
- of our main <tt>core.js</tt> asset package.
1874
- </p>
1875
-
1876
- <p id="View-remove">
1877
- <b class="header">remove</b><code>view.remove()</code>
1878
- <br />
1879
- Convenience function for removing the view from the DOM. Equivalent to calling
1880
- <tt>$(view.el).remove();</tt>
1881
- </p>
1882
-
1883
- <p id="View-make">
1884
- <b class="header">make</b><code>view.make(tagName, [attributes], [content])</code>
1885
- <br />
1886
- Convenience function for creating a DOM element of the given type (<b>tagName</b>),
1887
- with optional attributes and HTML content. Used internally to create the
1888
- initial <tt>view.el</tt>.
1889
- </p>
1890
-
1891
- <pre class="runnable">
1892
- var view = new Backbone.View;
1893
-
1894
- var el = view.make("b", {className: "bold"}, "Bold! ");
1895
-
1896
- $("#make-demo").append(el);
1897
- </pre>
1898
-
1899
- <div id="make-demo"></div>
1900
-
1901
- <p id="View-delegateEvents">
1902
- <b class="header">delegateEvents</b><code>delegateEvents([events])</code>
1903
- <br />
1904
- Uses jQuery's <tt>delegate</tt> function to provide declarative callbacks
1905
- for DOM events within a view.
1906
- If an <b>events</b> hash is not passed directly, uses <tt>this.events</tt>
1907
- as the source. Events are written in the format <tt>{"event selector": "callback"}</tt>.
1908
- Omitting the <tt>selector</tt> causes the event to be bound to the view's
1909
- root element (<tt>this.el</tt>). By default, <tt>delegateEvents</tt> is called
1910
- within the View's constructor for you, so if you have a simple <tt>events</tt>
1911
- hash, all of your DOM events will always already be connected, and you will
1912
- never have to call this function yourself.
1913
- </p>
1914
-
1915
- <p>
1916
- Using <b>delegateEvents</b> provides a number of advantages over manually
1917
- using jQuery to bind events to child elements during <a href="#View-render">render</a>. All attached
1918
- callbacks are bound to the view before being handed off to jQuery, so when
1919
- the callbacks are invoked, <tt>this</tt> continues to refer to the view object. When
1920
- <b>delegateEvents</b> is run again, perhaps with a different <tt>events</tt>
1921
- hash, all callbacks are removed and delegated afresh &mdash; useful for
1922
- views which need to behave differently when in different modes.
1923
- </p>
1924
-
1925
- <p>
1926
- A view that displays a document in a search result might look
1927
- something like this:
1928
- </p>
1929
-
1930
- <pre>
1931
- var DocumentView = Backbone.View.extend({
1932
-
1933
- events: {
1934
- "dblclick" : "open",
1935
- "click .icon.doc" : "select",
1936
- "contextmenu .icon.doc" : "showMenu",
1937
- "click .show_notes" : "toggleNotes",
1938
- "click .title .lock" : "editAccessLevel",
1939
- "mouseover .title .date" : "showTooltip"
1940
- },
1941
-
1942
- render: function() {
1943
- $(this.el).html(this.template(this.model.toJSON()));
1944
- return this;
1945
- },
1946
-
1947
- open: function() {
1948
- window.open(this.model.get("viewer_url"));
1949
- },
1950
-
1951
- select: function() {
1952
- this.model.set({selected: true});
1953
- },
1954
-
1955
- ...
1956
-
1957
- });
1958
- </pre>
1959
-
1960
- <h2 id="Utility">Utility Functions</h2>
1961
-
1962
- <p>
1963
-
1964
- </p>
1965
-
1966
- <p id="Utility-noConflict">
1967
- <b class="header">noConflict</b><code>var backbone = Backbone.noConflict();</code>
1968
- <br />
1969
- Returns the <tt>Backbone</tt> object back to its original value. You can
1970
- use the return value of <tt>Backbone.noConflict()</tt> to keep a local
1971
- reference to Backbone. Useful for embedding Backbone on third-party
1972
- websites, where you don't want to clobber the existing Backbone.
1973
- </p>
1974
-
1975
- <pre>
1976
- var localBackbone = Backbone.noConflict();
1977
- var model = localBackbone.Model.extend(...);
1978
- </pre>
1979
-
1980
- <h2 id="examples">Examples</h2>
1981
-
1982
- <p id="examples-todos">
1983
- <a href="http://jgn.me/">Jérôme Gravel-Niquet</a> has contributed a
1984
- <a href="examples/todos/index.html">Todo List application</a>
1985
- that is bundled in the repository as Backbone example. If you're wondering
1986
- where to get started with Backbone in general, take a moment to
1987
- <a href="docs/todos.html">read through the annotated source</a>. The app uses a
1988
- <a href="docs/backbone-localstorage.html">LocalStorage adapter</a>
1989
- to transparently save all of your todos within your browser, instead of
1990
- sending them to a server. Jérôme also has a version hosted at
1991
- <a href="http://localtodos.com/">localtodos.com</a> that uses a
1992
- <a href="http://github.com/jeromegn/backbone-mootools">MooTools-backed version of Backbone</a>
1993
- instead of jQuery.
1994
- </p>
1995
-
1996
- <div style="text-align: center;">
1997
- <a href="examples/todos/index.html">
1998
- <img src="docs/images/todos.png" alt="Todos" class="example_image" />
1999
- </a>
2000
- </div>
2001
-
2002
- <h2 id="examples-documentcloud">DocumentCloud</h2>
2003
-
2004
- <p>
2005
- The <a href="http://www.documentcloud.org/public/#search/">DocumentCloud workspace</a>
2006
- is built on Backbone.js, with <i>Documents</i>, <i>Projects</i>,
2007
- <i>Notes</i>, and <i>Accounts</i> all as Backbone models and collections.
2008
- If you're interested in history &mdash; both Underscore.js and Backbone.js
2009
- were originally extracted from the DocumentCloud codebase, and packaged
2010
- into standalone JS libraries.
2011
- </p>
2012
-
2013
- <div style="text-align: center;">
2014
- <a href="http://www.documentcloud.org/public/#search/">
2015
- <img src="docs/images/dc-workspace.png" alt="DocumentCloud Workspace" class="example_image" />
2016
- </a>
2017
- </div>
2018
-
2019
- <h2 id="examples-basecamp">Basecamp Mobile</h2>
2020
-
2021
- <p>
2022
- <a href="http://37signals.com/">37Signals</a> used Backbone.js to create
2023
- <a href="http://basecamphq.com/mobile">Basecamp Mobile</a>, the mobile version
2024
- of their popular project management software. You can access all your Basecamp
2025
- projects, post new messages, and comment on milestones (all represented
2026
- internally as Backbone.js models).
2027
- </p>
2028
-
2029
- <div style="text-align: center;">
2030
- <a href="http://basecamphq.com/mobile">
2031
- <img src="docs/images/basecamp-mobile.png" alt="Basecamp Mobile" class="example_image" />
2032
- </a>
2033
- </div>
2034
-
2035
- <h2 id="examples-flow">Flow</h2>
2036
-
2037
- <p>
2038
- <a href="http://www.metalabdesign.com/">MetaLab</a> used Backbone.js to create
2039
- <a href="http://www.getflow.com/">Flow</a>, a task management app for teams. The
2040
- workspace relies on Backbone.js to construct task views, activities, accounts,
2041
- folders, projects, and tags. You can see the internals under <tt>window.Flow</tt>.
2042
- </p>
2043
-
2044
- <div style="text-align: center;">
2045
- <a href="http://www.getflow.com/">
2046
- <img src="docs/images/flow.png" alt="Flow" class="example_image" />
2047
- </a>
2048
- </div>
2049
-
2050
- <h2 id="examples-cloudapp">CloudApp</h2>
2051
-
2052
- <p>
2053
- <a href="http://getcloudapp.com">CloudApp</a> is simple file and link
2054
- sharing for the Mac. Backbone.js powers the web tools
2055
- which consume the <a href="http://developer.getcloudapp.com">documented API</a>
2056
- to manage Drops. Data is either pulled manually or pushed by
2057
- <a href="http://pusher.com">Pusher</a> and fed to
2058
- <a href="http://github.com/janl/mustache.js">Mustache</a> templates for
2059
- rendering. Check out the <a href="http://cloudapp.github.com/engine">annotated source code</a>
2060
- to see the magic.
2061
- </p>
2062
-
2063
- <div style="text-align: center;">
2064
- <a href="http://getcloudapp.com">
2065
- <img src="docs/images/cloudapp.png" alt="CloudApp" class="example_image" />
2066
- </a>
2067
- </div>
2068
-
2069
- <h2 id="examples-soundcloud">SoundCloud</h2>
2070
-
2071
- <p>
2072
- <a href="http://soundcloud.com">SoundCloud</a> is the leading sound sharing
2073
- platform on the internet, and Backbone.js provides the foundation for
2074
- <a href="http://m.soundcloud.com">Mobile SoundCloud</a>. The project uses
2075
- the public SoundCloud <a href="http://soundcloud.com/developers">API</a>
2076
- as a data source (channeled through a nginx proxy),
2077
- <a href="http://api.jquery.com/category/plugins/templates/">jQuery templates</a>
2078
- for the rendering, <a href="http://docs.jquery.com/Qunit">Qunit
2079
- </a> and <a href="http://code.google.com/p/phantomjs/">PhantomJS</a> for
2080
- the testing suite. The JS code, templates and CSS are built for the
2081
- production deployment with various Node.js tools like
2082
- <a href="https://github.com/dsimard/ready.js">ready.js</a>,
2083
- <a href="https://github.com/mde/node-jake">Jake</a>,
2084
- <a href="https://github.com/tmpvar/jsdom">jsdom</a>.
2085
- The <b>Backbone.History</b> was modified to support the HTML5 <tt>history.pushState</tt>.
2086
- <b>Backbone.sync</b> was extended with an additional SessionStorage based cache
2087
- layer.
2088
- </p>
2089
-
2090
- <div style="text-align: center;">
2091
- <a href="http://m.soundcloud.com">
2092
- <img src="docs/images/soundcloud.png" alt="SoundCloud" class="example_image" />
2093
- </a>
2094
- </div>
2095
-
2096
- <h2 id="examples-quoteroller">Quote Roller</h2>
2097
-
2098
- <p>
2099
- <a href="http://www.codingstaff.com">Coding Staff</a> used Backbone.js to
2100
- create <a href="http://www.quoteroller.com">Quote Roller</a>, an application
2101
- that helps to create, send, organize and track business proposals with ease.
2102
- Backbone.js has been used to implement interactive parts of the
2103
- application like template builder, pricing table, file attachments manager.
2104
- </p>
2105
-
2106
- <div style="text-align: center;">
2107
- <a href="http://www.quoteroller.com">
2108
- <img src="docs/images/quoteroller.png" alt="Quote Roller" class="example_image" />
2109
- </a>
2110
- </div>
2111
-
2112
- <h2 id="examples-tilemill">TileMill</h2>
2113
-
2114
- <p>
2115
- Our fellow
2116
- <a href="http://www.newschallenge.org/">Knight Foundation News Challenge</a>
2117
- winners, <a href="http://mapbox.com/">MapBox</a>, created an open-source
2118
- map design studio with Backbone.js:
2119
- <a href="http://mapbox.github.com/tilemill/">TileMill</a>.
2120
- TileMill lets you manage map layers based on shapefiles and rasters, and
2121
- edit their appearance directly in the browser with the
2122
- <a href="https://github.com/mapbox/carto">Carto styling language</a>.
2123
- Note that the gorgeous <a href="http://mapbox.com/">MapBox</a> homepage
2124
- is also a Backbone.js app.
2125
- </p>
2126
-
2127
- <div style="text-align: center;">
2128
- <a href="http://mapbox.github.com/tilemill/">
2129
- <img src="docs/images/tilemill.png" alt="TileMill" class="example_image" />
2130
- </a>
2131
- </div>
2132
-
2133
- <h2 id="examples-menagerievet">Menagerie Whiteboard</h2>
2134
-
2135
- <p>
2136
- <a href="http://twitter.com/_aaron_">Aaron Hamid</a> and
2137
- <a href="http://twitter.com/mkuklis">Michal Kuklis</a> from
2138
- <a href="http://incandescentsoftware.com">Incandescent Software</a>
2139
- used Backbone.js to create
2140
- <a href="http://menagerievet.com">Menagerie Whiteboard</a> a digital
2141
- "whiteboard" for veterinary practices. Backbone <b>Models</b> were used to
2142
- sync the data with CouchDB. A Backbone <b>Controller</b> was used for
2143
- routing and bookmarkable deep links. Backbone <b>Views</b> were used to
2144
- bind, listen and 'react' to changes coming from models.
2145
- <b>Backbone.sync</b> was extended to support connection to CouchDB
2146
- and deployment as a CouchApp.
2147
- </p>
2148
-
2149
- <div style="text-align: center;">
2150
- <a href="http://menagerievet.com/">
2151
- <img src="docs/images/menagerievet.png" alt="MenagerieVet" class="example_image" />
2152
- </a>
2153
- </div>
2154
-
2155
- <h2 id="examples-instagreat">Insta-great!</h2>
2156
-
2157
- <p>
2158
- <a href="http://twitter.com/elliottkember">Elliott Kember</a> and
2159
- <a href="http://twitter.com/dizzyup">Hector Simpson</a> built
2160
- <a href="http://instagre.at">Insta-great!</a>
2161
- - a fun way to explore popular photos and interact with
2162
- <a href="http://instagram.com/">Instagram</a> on the web.
2163
- Elliott says, "Backbone.js and Coffeescript were insanely useful for
2164
- writing clean, consistent UI code and keeping everything modular and
2165
- readable, even through several code refactors. I'm in love."
2166
- </p>
2167
-
2168
- <div style="text-align: center;">
2169
- <a href="http://instagre.at">
2170
- <img src="docs/images/instagreat.png" alt="instagre.at" class="example_image" />
2171
- </a>
2172
- </div>
2173
-
2174
- <h2 id="examples-decide">Decide</h2>
2175
-
2176
- <p>
2177
- <a href="http://decide.com">Decide.com</a> helps people decide when to buy
2178
- consumer electronics. It relies heavily on Backbone.js to render and
2179
- update its Search Results Page. An "infinite scroll" feature takes
2180
- advantage of a SearchResults model containing a collection of
2181
- Product models to fetch more results and render them on the fly
2182
- with Mustache. A SearchController keeps everything in sync and
2183
- maintains page state in the URL. Backbone also powers the user
2184
- accounts and settings management.
2185
- </p>
2186
-
2187
- <div style="text-align: center;">
2188
- <a href="http://decide.com">
2189
- <img src="docs/images/decide.png" alt="Decide" class="example_image" />
2190
- </a>
2191
- </div>
2192
-
2193
- <h2 id="examples-bittorrent">BitTorrent</h2>
2194
-
2195
- <p>
2196
- <a href="http://www.bittorrent.com">BitTorrent</a> used Backbone to
2197
- completely rework an existing Win32 UI. Models normalize access to the
2198
- client's data and views rely heavily on the <tt>change</tt> events to keep
2199
- the UI state current. Using Backbone and SCSS,
2200
- <a href="http://www.bittorrent.com/chrysalis/">our new design</a> and UX
2201
- prototypes are considerably easier to iterate, test and work with than
2202
- the original Win32 UI.
2203
- </p>
2204
-
2205
- <div style="text-align: center;">
2206
- <a href="http://www.bittorrent.com/chrysalis/">
2207
- <img src="docs/images/bittorrent.jpg" alt="BitTorrent" class="example_image" />
2208
- </a>
2209
- </div>
2210
-
2211
- <h2 id="examples-fluxiom">Fluxiom</h2>
2212
-
2213
- <p>
2214
- <a href="http://fluxiom.com">Fluxiom</a> uses Backbone.js and HTML5 to
2215
- deliver a seamless upload experience from the desktop to the cloud,
2216
- including drag and drop, live previews, partial uploads, and one-click sharing.
2217
- <p>
2218
-
2219
- <p>
2220
- The upload queue is a single collection and each file is it’s own model.
2221
- The UI is divided into several views for efficient event handling, and
2222
- uses <a href="http://documentcloud.github.com/underscore/">Underscore.js</a>
2223
- templates for fast rendering, even when handling hundreds of uploads.
2224
- </p>
2225
-
2226
- <div style="text-align: center;">
2227
- <a href="http://fluxiom.com/">
2228
- <img src="docs/images/fluxiom.png" alt="Fluxiom" class="example_image" />
2229
- </a>
2230
- </div>
2231
-
2232
- <h2 id="examples-chop">Chop</h2>
2233
-
2234
- <p>
2235
- <a href="http://chopapp.com/">Chop</a> is a little app from
2236
- <a href="http://www.zurb.com/">ZURB</a> that lets people slice up bad code
2237
- and share their feedback to help put it back together.
2238
- Chop was built to demonstrate how easy it is to build pageless apps
2239
- using Backbone.js and Rails. Chop makes extensive use of Backbone <b>Views</b>,
2240
- <b>Controllers</b>, and <b>Models</b>.
2241
- </p>
2242
-
2243
- <div style="text-align: center;">
2244
- <a href="http://chopapp.com/">
2245
- <img src="docs/images/chop.png" alt="Chop" class="example_image" />
2246
- </a>
2247
- </div>
2248
-
2249
- <h2 id="examples-quietwrite">QuietWrite</h2>
2250
-
2251
- <p>
2252
- <a href="http://www.twitter.com/jamesjyu">James Yu</a> used Backbone.js to
2253
- create <a href="http://www.quietwrite.com/">QuietWrite</a>, an app
2254
- that gives writers a clean and quiet interface to concentrate on the text itself.
2255
- The editor relies on Backbone to persist document data to the server. He
2256
- followed up with a Backbone.js + Rails tutorial that describes how to implement
2257
- <a href="http://www.jamesyu.org/2011/01/27/cloudedit-a-backbone-js-tutorial-by-example/">CloudEdit, a simple document editing app</a>.
2258
- </p>
2259
-
2260
- <div style="text-align: center;">
2261
- <a href="http://www.quietwrite.com/">
2262
- <img src="docs/images/quietwrite.png" alt="QuietWrite" class="example_image" />
2263
- </a>
2264
- </div>
2265
-
2266
- <h2 id="examples-tzigla">Tzigla</h2>
2267
-
2268
- <p>
2269
- <a href="http://twitter.com/evilchelu">Cristi Balan</a> and
2270
- <a href="http://dira.ro">Irina Dumitrascu</a> created
2271
- <a href="http://tzigla.com">Tzigla</a>, a collaborative drawing
2272
- application where artists make tiles that connect to each other to
2273
- create <a href="http://tzigla.com/boards/1">surreal drawings</a>.
2274
- Backbone models help organize the code, routers provide
2275
- <a href="http://tzigla.com/boards/1#!/tiles/2-2">bookmarkable deep links</a>,
2276
- and the views are rendered with
2277
- <a href="https://github.com/creationix/haml-js">haml.js</a> and
2278
- <a href="http://zeptojs.com/">Zepto</a>.
2279
- Tzigla is written in Ruby (Rails) on the backend, and
2280
- <a href="http://coffeescript.org">CoffeeScript</a> on the frontend, with
2281
- <a href="http://documentcloud.github.com/jammit/">Jammit</a>
2282
- prepackaging the static assets.
2283
- </p>
2284
-
2285
- <div style="text-align: center;">
2286
- <a href="http://www.tzigla.com/">
2287
- <img src="docs/images/tzigla.png" alt="Tzigla" class="example_image" />
2288
- </a>
2289
- </div>
2290
-
2291
- <h2 id="examples-substance">Substance</h2>
2292
-
2293
- <p>
2294
- Michael Aufreiter is building an open source document authoring and
2295
- publishing engine: <a href="http://substance.io">Substance</a>.
2296
- Substance makes use of Backbone.View and Backbone.Router, while
2297
- Backbone plays well together with
2298
- <a href="http://github.com/michael/data">Data.js</a>, which is used for
2299
- data persistence.
2300
- </p>
2301
-
2302
- <div style="text-align: center;">
2303
- <a href="http://substance.io/">
2304
- <img src="docs/images/substance.png" alt="Substance" class="example_image" />
2305
- </a>
2306
- </div>
2307
-
2308
- <h2 id="faq">F.A.Q.</h2>
2309
-
2310
- <p id="FAQ-events">
2311
- <b class="header">Catalog of Events</b>
2312
- <br />
2313
- Here's a list of all of the built-in events that Backbone.js can fire.
2314
- You're also free to trigger your own events on Models and Views as you
2315
- see fit.
2316
- </p>
2317
-
2318
- <ul>
2319
- <li><b>"add"</b> (model, collection) &mdash; when a model is added to a collection. </li>
2320
- <li><b>"remove"</b> (model, collection) &mdash; when a model is removed from a collection. </li>
2321
- <li><b>"reset"</b> (collection) &mdash; when the collection's entire contents have been replaced. </li>
2322
- <li><b>"change"</b> (model, collection) &mdash; when a model's attributes have changed. </li>
2323
- <li><b>"change:[attribute]"</b> (model, collection) &mdash; when a specific attribute has been updated. </li>
2324
- <li><b>"destroy"</b> (model, collection) &mdash; when a model is <a href="#Model-destroy">destroyed</a>. </li>
2325
- <li><b>"error"</b> (model, collection) &mdash; when a model's validation fails, or a <a href="#Model-save">save</a> call fails on the server. </li>
2326
- <li><b>"route:[name]"</b> (router) &mdash; when one of a router's routes has matched. </li>
2327
- <li><b>"all"</b> &mdash; this special event fires for <i>any</i> triggered event, passing the event name as the first argument. </li>
2328
- </ul>
2329
-
2330
- <p id="FAQ-nested">
2331
- <b class="header">Nested Models &amp; Collections</b>
2332
- <br />
2333
- It's common to nest collections inside of models with Backbone. For example,
2334
- consider a <tt>Mailbox</tt> model that contains many <tt>Message</tt> models.
2335
- One nice pattern for handling this is have a <tt>this.messages</tt> collection
2336
- for each mailbox, enabling the lazy-loading of messages, when the mailbox
2337
- is first opened ... perhaps with <tt>MessageList</tt> views listening for
2338
- <tt>"add"</tt> and <tt>"remove"</tt> events.
2339
- </p>
2340
-
2341
- <pre>
2342
- var Mailbox = Backbone.Model.extend({
2343
-
2344
- initialize: function() {
2345
- this.messages = new Messages;
2346
- this.messages.url = '/mailbox/' + this.id + '/messages';
2347
- this.messages.bind("reset", this.updateCounts);
2348
- },
2349
-
2350
- ...
2351
-
2352
- });
2353
-
2354
- var Inbox = new Mailbox;
2355
-
2356
- // And then, when the Inbox is opened:
2357
-
2358
- Inbox.messages.fetch();
2359
- </pre>
2360
-
2361
- <p>
2362
- If you're looking for something more opinionated, there are a number of
2363
- Backbone plugins that add sophisticated associations among models,
2364
- <a href="https://github.com/documentcloud/backbone/wiki/Extensions%2C-Plugins%2C-Resources">available on the wiki</a>.
2365
- </p>
2366
-
2367
- <p id="FAQ-bootstrap">
2368
- <b class="header">Loading Bootstrapped Models</b>
2369
- <br />
2370
- When your app first loads, it's common to have a set of initial models that
2371
- you know you're going to need, in order to render the page. Instead of
2372
- firing an extra AJAX request to <a href="#Collection-fetch">fetch</a> them,
2373
- a nicer pattern is to have their data already bootstrapped into the page.
2374
- You can then use <a href="#Collection-reset">reset</a> to populate your
2375
- collections with the initial data. At DocumentCloud, in the
2376
- <a href="http://en.wikipedia.org/wiki/ERuby">ERB</a> template for the
2377
- workspace, we do something along these lines:
2378
- </p>
2379
-
2380
- <pre>
2381
- &lt;script&gt;
2382
- Accounts.reset(&lt;%= @accounts.to_json %&gt;);
2383
- Projects.reset(&lt;%= @projects.to_json(:collaborators => true) %&gt;);
2384
- &lt;/script&gt;
2385
- </pre>
2386
-
2387
- <p id="FAQ-mvc">
2388
- <b class="header">How does Backbone relate to "traditional" MVC?</b>
2389
- <br />
2390
- Different implementations of the
2391
- <a href="http://en.wikipedia.org/wiki/Model–View–Controller">Model-View-Controller</a>
2392
- pattern tend to disagree about the definition of a controller. If it helps any, in
2393
- Backbone, the <a href="#View">View</a> class can also be thought of as a
2394
- kind of controller, dispatching events that originate from the UI, with
2395
- the HTML template serving as the true view. We call it a View because it
2396
- represents a logical chunk of UI, responsible for the contents of a single
2397
- DOM element.
2398
- </p>
2399
-
2400
- <p>
2401
- Comparing the overall structure of Backbone to a server-side MVC framework
2402
- like <b>Rails</b>, the pieces line up like so:
2403
- </p>
2404
-
2405
- <ul>
2406
- <li>
2407
- <b>Backbone.Model</b> &ndash; Like a Rails model minus the class
2408
- methods. Wraps a row of data in business logic.
2409
- </li>
2410
- <li>
2411
- <b>Backbone.Collection</b> &ndash; A group of models on the client-side,
2412
- with sorting/filtering/aggregation logic.
2413
- </li>
2414
- <li>
2415
- <b>Backbone.Router</b> &ndash; Rails <tt>routes.rb</tt> + Rails controller
2416
- actions. Maps URLs to functions.
2417
- </li>
2418
- <li>
2419
- <b>Backbone.View</b> &ndash; A logical, re-usable piece of UI. Often,
2420
- but not always, associated with a model.
2421
- </li>
2422
- <li>
2423
- <b>Client-side Templates</b> &ndash; Rails <tt>.html.erb</tt> views,
2424
- rendering a chunk of HTML.
2425
- </li>
2426
- </ul>
2427
-
2428
- <p id="FAQ-this">
2429
- <b class="header">Binding "this"</b>
2430
- <br />
2431
- Perhaps the single most common JavaScript "gotcha" is the fact that when
2432
- you pass a function as a callback, its value for <tt>this</tt> is lost. With
2433
- Backbone, when dealing with <a href="#Events">events</a> and callbacks,
2434
- you'll often find it useful to rely on
2435
- <a href="http://documentcloud.github.com/underscore/#bind">_.bind</a> and
2436
- <a href="http://documentcloud.github.com/underscore/#bindAll">_.bindAll</a>
2437
- from Underscore.js. <tt>_.bind</tt> takes a function and an object to be
2438
- used as <tt>this</tt>, any time the function is called in the future.
2439
- <tt>_.bindAll</tt> takes an object and a list of method names: each method
2440
- in the list will be bound to the object, so that its <tt>this</tt> may
2441
- not change. For example, in a <a href="#View">View</a> that listens for
2442
- changes to a collection...
2443
- </p>
2444
-
2445
- <pre>
2446
- var MessageList = Backbone.View.extend({
2447
-
2448
- initialize: function() {
2449
- _.bindAll(this, "addMessage", "removeMessage", "render");
2450
-
2451
- var messages = this.collection;
2452
- messages.bind("reset", this.render);
2453
- messages.bind("add", this.addMessage);
2454
- messages.bind("remove", this.removeMessage);
2455
- }
2456
-
2457
- });
2458
-
2459
- // Later, in the app...
2460
-
2461
- Inbox.messages.add(newMessage);
2462
- </pre>
2463
-
2464
- <h2 id="changelog">Change Log</h2>
2465
-
2466
- <p>
2467
- <b class="header">0.5.1</b> &mdash; <small><i>July 5, 2011</i></small><br />
2468
- Cleanups from the 0.5.0 release, to wit: improved transparent upgrades from
2469
- hash-based URLs to pushState, and vice-versa. Fixed inconsistency with
2470
- non-modified attributes being passed to <tt>Model#initialize</tt>. Reverted
2471
- a <b>0.5.0</b> change that would strip leading hashbangs from routes.
2472
- Added <tt>contains</tt> as an alias for <tt>includes</tt>.
2473
- </p>
2474
-
2475
- <p>
2476
- <b class="header">0.5.0</b> &mdash; <small><i>July 1, 2011</i></small><br />
2477
- A large number of tiny tweaks and micro bugfixes, best viewed by looking
2478
- at <a href="https://github.com/documentcloud/backbone/compare/0.3.3...0.5.0">the commit diff</a>.
2479
- HTML5 <tt>pushState</tt> support, enabled by opting-in with:
2480
- <tt>Backbone.history.start({pushState: true})</tt>.
2481
- <tt>Controller</tt> was renamed to <tt>Router</tt>, for clarity.
2482
- <tt>Collection#refresh</tt> was renamed to <tt>Collection#reset</tt> to emphasize
2483
- its ability to both reset the collection with new models, as well as empty
2484
- out the collection when used with no parameters.
2485
- <tt>saveLocation</tt> was replaced with <tt>navigate</tt>.
2486
- RESTful persistence methods (save, fetch, etc.) now return the jQuery deferred
2487
- object for further success/error chaining and general convenience.
2488
- Improved XSS escaping for <tt>Model#escape</tt>.
2489
- Added a <tt>urlRoot</tt> option to allow specifying RESTful urls without
2490
- the use of a collection.
2491
- An error is thrown if <tt>Backbone.history.start</tt> is called multiple times.
2492
- <tt>Collection#create</tt> now validates before initializing the new model.
2493
- <tt>view.el</tt> can now be a jQuery string lookup.
2494
- Backbone Views can now also take an <tt>attributes</tt> parameter.
2495
- <tt>Model#defaults</tt> can now be a function as well as a literal attributes
2496
- object.
2497
- </p>
2498
-
2499
- <p>
2500
- <b class="header">0.3.3</b> &mdash; <small><i>Dec 1, 2010</i></small><br />
2501
- Backbone.js now supports <a href="http://zeptojs.com">Zepto</a>, alongside
2502
- jQuery, as a framework for DOM manipulation and Ajax support.
2503
- Implemented <a href="#Model-escape">Model#escape</a>, to efficiently handle
2504
- attributes intended for HTML interpolation. When trying to persist a model,
2505
- failed requests will now trigger an <tt>"error"</tt> event. The
2506
- ubiquitous <tt>options</tt> argument is now passed as the final argument
2507
- to all <tt>"change"</tt> events.
2508
- </p>
2509
-
2510
- <p>
2511
- <b class="header">0.3.2</b> &mdash; <small><i>Nov 23, 2010</i></small><br />
2512
- Bugfix for IE7 + iframe-based "hashchange" events. <tt>sync</tt> may now be
2513
- overridden on a per-model, or per-collection basis. Fixed recursion error
2514
- when calling <tt>save</tt> with no changed attributes, within a
2515
- <tt>"change"</tt> event.
2516
- </p>
2517
-
2518
- <p>
2519
- <b class="header">0.3.1</b> &mdash; <small><i>Nov 15, 2010</i></small><br />
2520
- All <tt>"add"</tt> and <tt>"remove"</tt> events are now sent through the
2521
- model, so that views can listen for them without having to know about the
2522
- collection. Added a <tt>remove</tt> method to <a href="#View">Backbone.View</a>.
2523
- <tt>toJSON</tt> is no longer called at all for <tt>'read'</tt> and <tt>'delete'</tt> requests.
2524
- Backbone routes are now able to load empty URL fragments.
2525
- </p>
2526
-
2527
- <p>
2528
- <b class="header">0.3.0</b> &mdash; <small><i>Nov 9, 2010</i></small><br />
2529
- Backbone now has <a href="#Controller">Controllers</a> and
2530
- <a href="#History">History</a>, for doing client-side routing based on
2531
- URL fragments.
2532
- Added <tt>emulateHTTP</tt> to provide support for legacy servers that don't
2533
- do <tt>PUT</tt> and <tt>DELETE</tt>.
2534
- Added <tt>emulateJSON</tt> for servers that can't accept <tt>application/json</tt>
2535
- encoded requests.
2536
- Added <a href="#Model-clear">Model#clear</a>, which removes all attributes
2537
- from a model.
2538
- All Backbone classes may now be seamlessly inherited by CoffeeScript classes.
2539
- </p>
2540
-
2541
- <p>
2542
- <b class="header">0.2.0</b> &mdash; <small><i>Oct 25, 2010</i></small><br />
2543
- Instead of requiring server responses to be namespaced under a <tt>model</tt>
2544
- key, now you can define your own <a href="#Model-parse">parse</a> method
2545
- to convert responses into attributes for Models and Collections.
2546
- The old <tt>handleEvents</tt> function is now named
2547
- <a href="#View-delegateEvents">delegateEvents</a>, and is automatically
2548
- called as part of the View's constructor.
2549
- Added a <a href="#Collection-toJSON">toJSON</a> function to Collections.
2550
- Added <a href="#Collection-chain">Underscore's chain</a> to Collections.
2551
- </p>
2552
-
2553
- <p>
2554
- <b class="header">0.1.2</b> &mdash; <small><i>Oct 19, 2010</i></small><br />
2555
- Added a <a href="#Model-fetch">Model#fetch</a> method for refreshing the
2556
- attributes of single model from the server.
2557
- An <tt>error</tt> callback may now be passed to <tt>set</tt> and <tt>save</tt>
2558
- as an option, which will be invoked if validation fails, overriding the
2559
- <tt>"error"</tt> event.
2560
- You can now tell backbone to use the <tt>_method</tt> hack instead of HTTP
2561
- methods by setting <tt>Backbone.emulateHTTP = true</tt>.
2562
- Existing Model and Collection data is no longer sent up unnecessarily with
2563
- <tt>GET</tt> and <tt>DELETE</tt> requests. Added a <tt>rake lint</tt> task.
2564
- Backbone is now published as an <a href="http://npmjs.org">NPM</a> module.
2565
- </p>
2566
-
2567
- <p>
2568
- <b class="header">0.1.1</b> &mdash; <small><i>Oct 14, 2010</i></small><br />
2569
- Added a convention for <tt>initialize</tt> functions to be called
2570
- upon instance construction, if defined. Documentation tweaks.
2571
- </p>
2572
-
2573
- <p>
2574
- <b class="header">0.1.0</b> &mdash; <small><i>Oct 13, 2010</i></small><br />
2575
- Initial Backbone release.
2576
- </p>
2577
-
2578
- <p>
2579
- <br />
2580
- <a href="http://documentcloud.org/" title="A DocumentCloud Project" style="background:none;">
2581
- <img src="http://jashkenas.s3.amazonaws.com/images/a_documentcloud_project.png" alt="A DocumentCloud Project" style="position:relative;left:-10px;" />
2582
- </a>
2583
- </p>
2584
-
2585
- </div>
2586
-
2587
- <script src="test/vendor/underscore-1.1.6.js"></script>
2588
- <script src="test/vendor/jquery-1.5.js"></script>
2589
- <script src="test/vendor/json2.js"></script>
2590
- <script src="backbone.js"></script>
2591
-
2592
- <script>
2593
- // Set up the "play" buttons for each runnable code example.
2594
- $(function() {
2595
- $('.runnable').each(function() {
2596
- var code = this;
2597
- var button = $('<div class="run" title="Run"></div>');
2598
- $(button).insertBefore(code).bind('click', function(){
2599
- eval($(code).text());
2600
- });
2601
- });
2602
- });
2603
- </script>
2604
-
2605
- </body>
2606
- </html>