bpm 1.0.0.beta.4 → 1.0.0.beta.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/CHANGELOG.md +11 -0
  2. data/TODO.md +4 -10
  3. data/backbone/LICENSE +22 -0
  4. data/backbone/README +25 -0
  5. data/backbone/Rakefile +42 -0
  6. data/backbone/backbone-0.5.1.bpkg +0 -0
  7. data/backbone/examples/backbone-localstorage.js +84 -0
  8. data/backbone/examples/todos/destroy.png +0 -0
  9. data/backbone/examples/todos/index.html +87 -0
  10. data/backbone/examples/todos/todos.css +311 -0
  11. data/backbone/examples/todos/todos.js +258 -0
  12. data/backbone/index.html +2606 -0
  13. data/backbone/index.js +1 -0
  14. data/backbone/lib/backbone.js +1149 -0
  15. data/backbone/lib/index.js +1 -0
  16. data/backbone/package.json +14 -0
  17. data/backbone/test/collection.js +345 -0
  18. data/backbone/test/events.js +70 -0
  19. data/backbone/test/model.coffee +43 -0
  20. data/backbone/test/model.js +424 -0
  21. data/backbone/test/noconflict.js +12 -0
  22. data/backbone/test/router.js +116 -0
  23. data/backbone/test/speed.js +45 -0
  24. data/backbone/test/sync.js +133 -0
  25. data/backbone/test/test-zepto.html +30 -0
  26. data/backbone/test/test.html +31 -0
  27. data/backbone/test/vendor/jquery-1.5.js +8176 -0
  28. data/backbone/test/vendor/jslitmus.js +649 -0
  29. data/backbone/test/vendor/json2.js +481 -0
  30. data/backbone/test/vendor/qunit.css +196 -0
  31. data/backbone/test/vendor/qunit.js +1364 -0
  32. data/backbone/test/vendor/underscore-1.1.6.js +807 -0
  33. data/backbone/test/vendor/zepto-0.6.js +692 -0
  34. data/backbone/test/view.js +137 -0
  35. data/lib/bpm/cli/base.rb +22 -7
  36. data/lib/bpm/package.rb +17 -5
  37. data/lib/bpm/project.rb +49 -32
  38. data/lib/bpm/version.rb +1 -1
  39. data/spec/cli/add_spec.rb +22 -4
  40. data/spec/cli/fetch_spec.rb +0 -1
  41. data/spec/cli/init_spec.rb +25 -10
  42. data/spec/cli/list_spec.rb +103 -62
  43. data/spec/cli/pack_spec.rb +36 -4
  44. data/spec/fixtures/packages/backbone/LICENSE +22 -0
  45. data/spec/fixtures/packages/backbone/README +25 -0
  46. data/spec/fixtures/packages/backbone/Rakefile +42 -0
  47. data/spec/fixtures/packages/backbone/examples/backbone-localstorage.js +84 -0
  48. data/spec/fixtures/packages/backbone/examples/todos/destroy.png +0 -0
  49. data/spec/fixtures/packages/backbone/examples/todos/index.html +87 -0
  50. data/spec/fixtures/packages/backbone/examples/todos/todos.css +311 -0
  51. data/spec/fixtures/packages/backbone/examples/todos/todos.js +258 -0
  52. data/spec/fixtures/packages/backbone/index.html +2606 -0
  53. data/spec/fixtures/packages/backbone/lib/backbone.js +1149 -0
  54. data/spec/fixtures/packages/backbone/lib/index.js +1 -0
  55. data/spec/fixtures/packages/backbone/package.json +14 -0
  56. data/spec/fixtures/packages/backbone/test/collection.js +345 -0
  57. data/spec/fixtures/packages/backbone/test/events.js +70 -0
  58. data/spec/fixtures/packages/backbone/test/model.coffee +43 -0
  59. data/spec/fixtures/packages/backbone/test/model.js +424 -0
  60. data/spec/fixtures/packages/backbone/test/noconflict.js +12 -0
  61. data/spec/fixtures/packages/backbone/test/router.js +116 -0
  62. data/spec/fixtures/packages/backbone/test/speed.js +45 -0
  63. data/spec/fixtures/packages/backbone/test/sync.js +133 -0
  64. data/spec/fixtures/packages/backbone/test/test-zepto.html +30 -0
  65. data/spec/fixtures/packages/backbone/test/test.html +31 -0
  66. data/spec/fixtures/packages/backbone/test/vendor/jquery-1.5.js +8176 -0
  67. data/spec/fixtures/packages/backbone/test/vendor/jslitmus.js +649 -0
  68. data/spec/fixtures/packages/backbone/test/vendor/json2.js +481 -0
  69. data/spec/fixtures/packages/backbone/test/vendor/qunit.css +196 -0
  70. data/spec/fixtures/packages/backbone/test/vendor/qunit.js +1364 -0
  71. data/spec/fixtures/packages/backbone/test/vendor/underscore-1.1.6.js +807 -0
  72. data/spec/fixtures/packages/backbone/test/vendor/zepto-0.6.js +692 -0
  73. data/spec/fixtures/packages/backbone/test/view.js +137 -0
  74. data/spec/fixtures/projects/init_app/assets/bpm_libs.js +1 -1
  75. data/spec/fixtures/projects/init_app/assets/bpm_styles.css +1 -1
  76. data/spec/fixtures/projects/init_app/new_project.json +1 -10
  77. data/spec/pipeline_spec.rb +5 -5
  78. data/spec/plugins/minifier_spec.rb +1 -1
  79. data/spec/plugins/transport_spec.rb +1 -1
  80. metadata +116 -28
  81. data/spec/fixtures/projects/init_app/assets/new_project/bpm_libs.js +0 -6
  82. data/spec/fixtures/projects/init_app/assets/new_project/bpm_styles.css +0 -5
@@ -0,0 +1,2606 @@
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>