/ch12/index.html
HTML | 2277 lines | 1955 code | 322 blank | 0 comment | 0 complexity | 3caa4075b2c7b6ef13c2f511e0159302 MD5 | raw file
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 30px; 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.3.3)</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-refresh">refresh</a></li> 224 <li>– <a href="#Collection-create">create</a></li> 225 </ul> 226 227 <a class="toc_title" href="#Controller"> 228 Controller 229 </a> 230 <ul class="toc_section"> 231 <li>– <a href="#Controller-extend">extend</a></li> 232 <li>– <a href="#Controller-routes">routes</a></li> 233 <li>– <a href="#Controller-constructor">constructor / initialize</a></li> 234 <li>– <a href="#Controller-route">route</a></li> 235 <li>– <a href="#Controller-saveLocation">saveLocation</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="#examples"> 269 Examples 270 </a> 271 272 <a class="toc_title" href="#faq"> 273 F.A.Q. 274 </a> 275 <ul class="toc_section"> 276 <li>– <a href="#FAQ-events">Catalog of Events</a></li> 277 <li>– <a href="#FAQ-nested">Nested Models & Collections</a></li> 278 <li>– <a href="#FAQ-bootstrap">Loading Bootstrapped Models</a></li> 279 <li>– <a href="#FAQ-mvc">Traditional MVC</a></li> 280 <li>– <a href="#FAQ-this">Binding "this"</a></li> 281 <li>- <a href="#FAQ-rias">Other RIA Frameworks</a></li> 282 </ul> 283 284 <a class="toc_title" href="#changelog"> 285 Change Log 286 </a> 287 288 </div> 289 290 <div class="container"> 291 292 <p> 293 <img style="width: 385px; height: 126px;" src="docs/images/backbone.png" alt="Backbone.js" /> 294 </p> 295 296 <p> 297 <a href="http://github.com/documentcloud/backbone/">Backbone</a> 298 supplies structure to JavaScript-heavy applications by providing <b>models</b> with 299 key-value binding and custom events, <b>collections</b> with a rich API of enumerable functions, 300 <b>views</b> with declarative event handling, and connects it all to your 301 existing application over a RESTful JSON interface. 302 </p> 303 304 <p> 305 The project is <a href="http://github.com/documentcloud/backbone/">hosted on GitHub</a>, 306 and the <a href="docs/backbone.html">annotated source code</a> is available, 307 as well as an online <a href="test/test.html">test suite</a>, and 308 <a href="examples/todos/index.html">example application</a>. 309 </p> 310 311 <p> 312 You can report bugs and discuss features on the 313 <a href="http://github.com/documentcloud/backbone/issues">issues page</a>, 314 on Freenode in the <tt>#documentcloud</tt> channel, 315 or send tweets to <a href="http://twitter.com/documentcloud">@documentcloud</a>. 316 </p> 317 318 <p> 319 <i> 320 Backbone is an open-source component of 321 <a href="http://documentcloud.org/">DocumentCloud</a>. 322 </i> 323 </p> 324 325 <h2 id="downloads"> 326 Downloads & Dependencies 327 <span style="padding-left: 7px; font-size:11px; font-weight: normal;" class="interface">(Right-click, and use "Save As")</span> 328 </h2> 329 330 <table> 331 <tr> 332 <td><a href="backbone.js">Development Version (0.3.3)</a></td> 333 <td><i>35kb, Uncompressed with Comments</i></td> 334 </tr> 335 <tr> 336 <td><a href="backbone-min.js">Production Version (0.3.3)</a></td> 337 <td><i>3.9kb, Packed and Gzipped</i></td> 338 </tr> 339 </table> 340 341 <p> 342 Backbone's only hard dependency is 343 <a href="http://documentcloud.github.com/underscore/">Underscore.js</a>. 344 For RESTful persistence, and DOM manipulation with 345 <a href="#View">Backbone.View</a>, 346 it's highly recommended to include 347 <a href="https://github.com/douglascrockford/JSON-js">json2.js</a>, and either 348 <a href="http://jquery.com">jQuery</a> or <a href="http://zeptojs.com/">Zepto</a>. 349 </p> 350 351 <h2 id="Introduction">Introduction</h2> 352 353 <p> 354 When working on a web application that involves a lot of JavaScript, one 355 of the first things you learn is to stop tying your data to the DOM. It's all 356 too easy to create JavaScript applications that end up as tangled piles of 357 jQuery selectors and callbacks, all trying frantically to keep data in 358 sync between the HTML UI, your JavaScript logic, and the database on your 359 server. For rich client-side applications, a more structured approach 360 is helpful. 361 </p> 362 363 <p> 364 With Backbone, you represent your data as 365 <a href="#Model">Models</a>, which can be created, validated, destroyed, 366 and saved to the server. Whenever a UI action causes an attribute of 367 a model to change, the model triggers a <i>"change"</i> event; all 368 the <a href="#View">Views</a> that display the model's data are notified of the 369 event, causing them to re-render. You don't have to write the glue 370 code that looks into the DOM to find an element with a specific <i>id</i>, 371 and update the HTML manually 372 — when the model changes, the views simply update themselves. 373 </p> 374 375 <p> 376 Many of the examples that follow are runnable. Click the <i>play</i> button 377 to execute them. 378 </p> 379 380 <h2 id="Events">Backbone.Events</h2> 381 382 <p> 383 <b>Events</b> is a module that can be mixed in to any object, giving the 384 object the ability to bind and trigger custom named events. Events do not 385 have to be declared before they are bound, and may take passed arguments. 386 For example: 387 </p> 388 389<pre class="runnable"> 390var object = {}; 391 392_.extend(object, Backbone.Events); 393 394object.bind("alert", function(msg) { 395 alert("Triggered " + msg); 396}); 397 398object.trigger("alert", "an event"); 399</pre> 400 401 <p id="Events-bind"> 402 <b class="header">bind</b><code>object.bind(event, callback)</code> 403 <br /> 404 Bind a <b>callback</b> function to an object. The callback will be invoked 405 whenever the <b>event</b> (specified by an arbitrary string identifier) is fired. 406 If you have a large number of different events on a page, the convention is to use colons to 407 namespace them: <tt>"poll:start"</tt>, or <tt>"change:selection"</tt> 408 </p> 409 410 <p> 411 Callbacks bound to the special 412 <tt>"all"</tt> event will be triggered when any event occurs, and are passed 413 the name of the event as the first argument. For example, to proxy all events 414 from one object to another: 415 </p> 416 417<pre> 418proxy.bind("all", function(eventName) { 419 object.trigger(eventName); 420}); 421</pre> 422 423 <p id="Events-unbind"> 424 <b class="header">unbind</b><code>object.unbind([event], [callback])</code> 425 <br /> 426 Remove a previously-bound <b>callback</b> function from an object. If no 427 callback is specified, all callbacks for the <b>event</b> will be 428 removed. If no event is specified, <i>all</i> event callbacks on the object 429 will be removed. 430 </p> 431 432<pre> 433object.unbind("change", onChange); // Removes just the onChange callback. 434 435object.unbind("change"); // Removes all "change" callbacks. 436 437object.unbind(); // Removes all callbacks on object. 438</pre> 439 440 <p id="Events-trigger"> 441 <b class="header">trigger</b><code>object.trigger(event, [*args])</code> 442 <br /> 443 Trigger callbacks for the given <b>event</b>. Subsequent arguments to 444 <b>trigger</b> will be passed along to the event callbacks. 445 </p> 446 447 <h2 id="Model">Backbone.Model</h2> 448 449 <p> 450 <b>Models</b> are the heart of any JavaScript application, containing 451 the interactive data as well as a large part of the logic surrounding it: 452 conversions, validations, computed properties, and access control. You 453 extend <b>Backbone.Model</b> with your domain-specific methods, and 454 <b>Model</b> provides a basic set of functionality for managing changes. 455 </p> 456 457 <p> 458 The following is a contrived example, but it demonstrates defining a model 459 with a custom method, setting an attribute, and firing an event keyed 460 to changes in that specific attribute. 461 After running this code once, <tt>sidebar</tt> will be 462 available in your browser's console, so you can play around with it. 463 </p> 464 465<pre class="runnable"> 466var Sidebar = Backbone.Model.extend({ 467 promptColor: function() { 468 var cssColor = prompt("Please enter a CSS color:"); 469 this.set({color: cssColor}); 470 } 471}); 472 473window.sidebar = new Sidebar; 474 475sidebar.bind('change:color', function(model, color) { 476 $('#sidebar').css({background: color}); 477}); 478 479sidebar.set({color: 'white'}); 480 481sidebar.promptColor(); 482</pre> 483 484 <p id="Model-extend"> 485 <b class="header">extend</b><code>Backbone.Model.extend(properties, [classProperties])</code> 486 <br /> 487 To create a <b>Model</b> class of your own, you extend <b>Backbone.Model</b> 488 and provide instance <b>properties</b>, as well as optional 489 <b>classProperties</b> to be attached directly to the constructor function. 490 </p> 491 492 <p> 493 <b>extend</b> correctly sets up the prototype chain, so subclasses created 494 with <b>extend</b> can be further extended and subclassed as far as you like. 495 </p> 496 497<pre> 498var Note = Backbone.Model.extend({ 499 500 initialize: function() { ... }, 501 502 author: function() { ... }, 503 504 coordinates: function() { ... }, 505 506 allowedToEdit: function(account) { 507 return true; 508 } 509 510}); 511 512var PrivateNote = Note.extend({ 513 514 allowedToEdit: function(account) { 515 return account.owns(this); 516 } 517 518}); 519</pre> 520 521 <p class="warning"> 522 Brief aside on <tt>super</tt>: JavaScript does not provide 523 a simple way to call super — the function of the same name defined 524 higher on the prototype chain. If you override a core function like 525 <tt>set</tt>, or <tt>save</tt>, and you want to invoke the 526 parent object's implementation, you'll have to explicitly call it, along these lines: 527 </p> 528 529<pre> 530var Note = Backbone.Model.extend({ 531 set: function(attributes, options) { 532 Backbone.Model.prototype.set.call(this, attributes, options); 533 ... 534 } 535}); 536</pre> 537 538 <p id="Model-constructor"> 539 <b class="header">constructor / initialize</b><code>new Model([attributes])</code> 540 <br /> 541 When creating an instance of a model, you can pass in the initial values 542 of the <b>attributes</b>, which will be <a href="#Model-set">set</a> on the 543 model. If you define an <b>initialize</b> function, it will be invoked when 544 the model is created. 545 </p> 546 547<pre> 548new Book({ 549 title: "One Thousand and One Nights", 550 author: "Scheherazade" 551}); 552</pre> 553 554 <p id="Model-get"> 555 <b class="header">get</b><code>model.get(attribute)</code> 556 <br /> 557 Get the current value of an attribute from the model. For example: 558 <tt>note.get("title")</tt> 559 </p> 560 561 <p id="Model-escape"> 562 <b class="header">escape</b><code>model.escape(attribute)</code> 563 <br /> 564 Similar to <a href="#Model-get">get</a>, but returns the HTML-escaped version 565 of a model's attribute. If you're interpolating data from the model into 566 HTML, using <b>escape</b> to retrieve attributes will prevent 567 <a href="http://en.wikipedia.org/wiki/Cross-site_scripting">XSS</a> attacks. 568 </p> 569 570<pre class="runnable"> 571var hacker = new Backbone.Model({ 572 name: "<script>alert('xss')</script>" 573}); 574 575alert(hacker.escape('name')); 576</pre> 577 578 <p id="Model-set"> 579 <b class="header">set</b><code>model.set(attributes, [options])</code> 580 <br /> 581 Set a hash of attributes (one or many) on the model. If any of the attributes 582 change the models state, a <tt>"change"</tt> event will be triggered, unless 583 <tt>{silent: true}</tt> is passed as an option. Change events for specific 584 attributes are also triggered, and you can bind to those as well, for example: 585 <tt>change:title</tt>, and <tt>change:content</tt>. 586 </p> 587 588<pre> 589note.set({title: "October 12", content: "Lorem Ipsum Dolor Sit Amet..."}); 590</pre> 591 592 <p> 593 If the model has a <a href="#Model-validate">validate</a> method, 594 it will be validated before the attributes are set, no changes will 595 occur if the validation fails, and <b>set</b> will return <tt>false</tt>. 596 You may also pass an <tt>error</tt> 597 callback in the options, which will be invoked instead of triggering an 598 <tt>"error"</tt> event, should validation fail. 599 </p> 600 601 <p id="Model-escape"> 602 <b class="header">escape</b><code>model.escape(attribute)</code> 603 <br /> 604 Similar to <a href="#Model-get">get</a>, but returns the HTML-escaped version 605 of a model's attribute. If you're interpolating data from the model into 606 HTML, using <b>escape</b> to retrieve attributes will prevent 607 <a href="http://en.wikipedia.org/wiki/Cross-site_scripting">XSS</a> attacks. 608 </p> 609 610<pre class="runnable"> 611var hacker = new Backbone.Model({ 612 name: "<script>alert('xss')</script>" 613}); 614 615alert(hacker.escape('name')); 616</pre> 617 618 <p id="Model-has"> 619 <b class="header">has</b><code>model.has(attribute)</code> 620 <br /> 621 Returns <tt>true</tt> if the attribute is set to a non-null or non-undefined 622 value. 623 </p> 624 625<pre> 626if (note.has("title")) { 627 ... 628} 629</pre> 630 631 <p id="Model-unset"> 632 <b class="header">unset</b><code>model.unset(attribute, [options])</code> 633 <br /> 634 Remove an attribute by deleting it from the internal attributes hash. 635 Fires a <tt>"change"</tt> event unless <tt>silent</tt> is passed as an option. 636 </p> 637 638 <p id="Model-clear"> 639 <b class="header">clear</b><code>model.clear([options])</code> 640 <br /> 641 Removes all attributes from the model. Fires a <tt>"change"</tt> event unless 642 <tt>silent</tt> is passed as an option. 643 </p> 644 645 <p id="Model-id"> 646 <b class="header">id</b><code>model.id</code> 647 <br /> 648 A special property of models, the <b>id</b> is an arbitrary string 649 (integer id or UUID). If you set the <b>id</b> in the 650 attributes hash, it will be copied onto the model as a direct property. 651 Models can be retrieved by id from collections, and the id is used to generate 652 model URLs by default. 653 </p> 654 655 <p id="Model-cid"> 656 <b class="header">cid</b><code>model.cid</code> 657 <br /> 658 A special property of models, the <b>cid</b> or client id is a unique identifier 659 automatically assigned to all models when they're first created. Client ids 660 are handy when the model has not yet been saved to the server, and does not 661 yet have its eventual true <b>id</b>, but already needs to be visible in the UI. 662 Client ids take the form: <tt>c1, c2, c3 ...</tt> 663 </p> 664 665 <p id="Model-attributes"> 666 <b class="header">attributes</b><code>model.attributes</code> 667 <br /> 668 The <b>attributes</b> property is the internal hash containing the model's 669 state. Please use <a href="#Model-set">set</a> to update the attributes instead of modifying 670 them directly. If you'd like to retrieve and munge a copy of the model's 671 attributes, use <a href="#Model-toJSON">toJSON</a> instead. 672 </p> 673 674 <p id="Model-defaults"> 675 <b class="header">defaults</b><code>model.defaults or model.defaults()</code> 676 <br /> 677 The <b>defaults</b> hash (or function) can be used to specify the default 678 attributes for your model. When creating an instance of the model, 679 any unspecified attributes will be set to their default value. 680 </p> 681 682<pre class="runnable"> 683var Meal = Backbone.Model.extend({ 684 defaults: { 685 "appetizer": "caesar salad", 686 "entree": "ravioli", 687 "dessert": "cheesecake" 688 } 689}); 690 691alert("Dessert will be " + (new Meal).get('dessert')); 692</pre> 693 694 <p id="Model-toJSON"> 695 <b class="header">toJSON</b><code>model.toJSON()</code> 696 <br /> 697 Return a copy of the model's <a href="#Model-attributes">attributes</a> for JSON stringification. 698 This can be used for persistence, serialization, or for augmentation before 699 being handed off to a view. The name of this method is a bit confusing, as 700 it doesn't actually return a JSON string — but I'm afraid that it's 701 the way that the <a href="https://developer.mozilla.org/en/JSON#toJSON()_method">JavaScript API for <b>JSON.stringify</b> works</a>. 702 </p> 703 704<pre class="runnable"> 705var artist = new Backbone.Model({ 706 firstName: "Wassily", 707 lastName: "Kandinsky" 708}); 709 710artist.set({birthday: "December 16, 1866"}); 711 712alert(JSON.stringify(artist)); 713</pre> 714 715 <p id="Model-fetch"> 716 <b class="header">fetch</b><code>model.fetch([options])</code> 717 <br /> 718 Refreshes the model's state from the server. Useful if the model has never 719 been populated with data, or if you'd like to ensure that you have the 720 latest server state. A <tt>"change"</tt> event will be triggered if the 721 server's state differs from the current attributes. Accepts 722 <tt>success</tt> and <tt>error</tt> callbacks in the options hash, which 723 are passed <tt>(model, response)</tt> as arguments. 724 </p> 725 726<pre> 727// Poll every 10 seconds to keep the channel model up-to-date. 728setInterval(function() { 729 channel.fetch(); 730}, 10000); 731</pre> 732 733 <p id="Model-save"> 734 <b class="header">save</b><code>model.save([attributes], [options])</code> 735 <br /> 736 Save a model to your database (or alternative persistence layer), 737 by delegating to <a href="#Sync">Backbone.sync</a>. The <b>attributes</b> 738 hash (as in <a href="#Model-set">set</a>) should contain the attributes 739 you'd like to change -- keys that aren't mentioned won't be altered. 740 If the model has a <a href="#Model-validate">validate</a> 741 method, and validation fails, the model will not be saved. If the model 742 <a href="#Model-isNew">isNew</a>, the save will be a <tt>"create"</tt> 743 (HTTP <tt>POST</tt>), if the model already 744 exists on the server, the save will be an <tt>"update"</tt> (HTTP <tt>PUT</tt>). 745 </p> 746 747 <p> 748 In the following example, notice how because the model has never been 749 saved previously, our overridden version of <tt>Backbone.sync</tt> receives a <tt>"create"</tt> request. 750 </p> 751 752<pre class="runnable"> 753Backbone.sync = function(method, model) { 754 alert(method + ": " + JSON.stringify(model)); 755}; 756 757var book = new Backbone.Model({ 758 title: "The Rough Riders", 759 author: "Theodore Roosevelt" 760}); 761 762book.save(); 763</pre> 764 765 <p> 766 <b>save</b> accepts <tt>success</tt> and <tt>error</tt> callbacks in the 767 options hash, which are passed <tt>(model, response)</tt> as arguments. 768 The <tt>error</tt> callback will also be invoked if the model has a 769 <tt>validate</tt> method, and validation fails. If a server-side 770 validation fails, return a non-<tt>200</tt> HTTP response code, along with 771 an error response in text or JSON. 772 </p> 773 774<pre> 775book.save({author: "F.D.R."}, {error: function(){ ... }}); 776</pre> 777 778 <p id="Model-destroy"> 779 <b class="header">destroy</b><code>model.destroy([options])</code> 780 <br /> 781 Destroys the model on the server by delegating an HTTP <tt>DELETE</tt> 782 request to <a href="#Sync">Backbone.sync</a>. Accepts 783 <tt>success</tt> and <tt>error</tt> callbacks in the options hash. 784 Triggers a <tt>"destroy"</tt> event on the model, which will bubble up 785 through any collections that contain it. 786 </p> 787 788<pre> 789book.destroy({success: function(model, response) { 790 ... 791}}); 792</pre> 793 794 <p id="Model-validate"> 795 <b class="header">validate</b><code>model.validate(attributes)</code> 796 <br /> 797 This method is left undefined, and you're encouraged to override it with 798 your custom validation logic, if you have any that can be performed 799 in JavaScript. <b>validate</b> is called before <tt>set</tt> and 800 <tt>save</tt>, and is passed the attributes that are about to be updated. 801 If the model and attributes are valid, don't return anything from <b>validate</b>; 802 if the attributes are invalid, return an error of your choosing. It 803 can be as simple as a string error message to be displayed, or a complete 804 error object that describes the error programmatically. <tt>set</tt> and 805 <tt>save</tt> will not continue if <b>validate</b> returns an error. 806 Failed validations trigger an <tt>"error"</tt> event. 807 </p> 808 809<pre class="runnable"> 810var Chapter = Backbone.Model.extend({ 811 validate: function(attrs) { 812 if (attrs.end < attrs.start) { 813 return "can't end before it starts"; 814 } 815 } 816}); 817 818var one = new Chapter({ 819 title : "Chapter One: The Beginning" 820}); 821 822one.bind("error", function(model, error) { 823 alert(model.get("title") + " " + error); 824}); 825 826one.set({ 827 start: 15, 828 end: 10 829}); 830</pre> 831 832 <p> 833 <tt>"error"</tt> events are useful for providing coarse-grained error 834 messages at the model or collection level, but if you have a specific view 835 that can better handle the error, you may override and suppress the event 836 by passing an <tt>error</tt> callback directly: 837 </p> 838 839<pre> 840account.set({access: "unlimited"}, { 841 error: function(model, error) { 842 alert(error); 843 } 844}); 845</pre> 846 847 <p id="Model-url"> 848 <b class="header">url</b><code>model.url()</code> 849 <br /> 850 Returns the relative URL where the model's resource would be located on 851 the server. If your models are located somewhere else, override this method 852 with the correct logic. Generates URLs of the form: <tt>"/[collection.url]/[id]"</tt>, 853 falling back to <tt>"/[urlRoot]/id"</tt> if the model is not part of a collection. 854 </p> 855 856 <p> 857 Delegates to <a href="#Collection-url">Collection#url</a> to generate the 858 URL, so make sure that you have it defined, or a <a href="#Model-urlRoot">urlRoot</a> 859 property, if all models of this class share a common root URL. 860 A model with an id of <tt>101</tt>, stored in a 861 <a href="#Collection">Backbone.Collection</a> with a <tt>url</tt> of <tt>"/documents/7/notes"</tt>, 862 would have this URL: <tt>"/documents/7/notes/101"</tt> 863 </p> 864 865 <p id="Model-urlRoot"> 866 <b class="header">urlRoot</b><code>model.urlRoot</code> 867 <br /> 868 Specify a <tt>urlRoot</tt> if you're using a model outside of a collection, 869 to enable the default <a href="#Model-url">url</a> function to generate 870 URLs based on the model id. <tt>"/[urlRoot]/id"</tt> 871 </p> 872 873<pre class="runnable"> 874var Book = Backbone.Model.extend({urlRoot : '/books'}); 875 876var solaris = new Book({id: "1083-lem-solaris"}); 877 878alert(solaris.url()); 879</pre> 880 881 <p id="Model-parse"> 882 <b class="header">parse</b><code>model.parse(response)</code> 883 <br /> 884 <b>parse</b> is called whenever a model's data is returned by the 885 server, in <a href="#Model-fetch">fetch</a>, and <a href="#Model-save">save</a>. 886 The function is passed the raw <tt>response</tt> object, and should return 887 the attributes hash to be <a href="#Model-set">set</a> on the model. The 888 default implementation is a no-op, simply passing through the JSON response. 889 Override this if you need to work with a preexisting API, or better namespace 890 your responses. 891 </p> 892 893 <p> 894 If you're working with a Rails backend, you'll notice that Rails' default 895 <tt>to_json</tt> implementation includes a model's attributes under a 896 namespace. To disable this behavior for seamless Backbone integration, set: 897 </p> 898 899<pre> 900ActiveRecord::Base.include_root_in_json = false 901</pre> 902 903 <p id="Model-clone"> 904 <b class="header">clone</b><code>model.clone()</code> 905 <br /> 906 Returns a new instance of the model with identical attributes. 907 </p> 908 909 <p id="Model-isNew"> 910 <b class="header">isNew</b><code>model.isNew()</code> 911 <br /> 912 Has this model been saved to the server yet? If the model does not yet have 913 an <tt>id</tt>, it is considered to be new. 914 </p> 915 916 <p id="Model-change"> 917 <b class="header">change</b><code>model.change()</code> 918 <br /> 919 Manually trigger the <tt>"change"</tt> event. 920 If you've been passing <tt>{silent: true}</tt> to the <a href="#Model-set">set</a> function in order to 921 aggregate rapid changes to a model, you'll want to call <tt>model.change()</tt> 922 when you're all finished. 923 </p> 924 925 <p id="Model-hasChanged"> 926 <b class="header">hasChanged</b><code>model.hasChanged([attribute])</code> 927 <br /> 928 Has the model changed since the last <tt>"change"</tt> event? If an <b>attribute</b> 929 is passed, returns <tt>true</tt> if that specific attribute has changed. 930 </p> 931 932<pre> 933book.bind("change", function() { 934 if (book.hasChanged("title")) { 935 ... 936 } 937}); 938</pre> 939 940 <p id="Model-changedAttributes"> 941 <b class="header">changedAttributes</b><code>model.changedAttributes([attributes])</code> 942 <br /> 943 Retrieve a hash of only the model's attributes that have changed. Optionally, 944 an external <b>attributes</b> hash can be passed in, returning 945 the attributes in that hash which differ from the model. This can be used 946 to figure out which portions of a view should be updated, or what calls 947 need to be made to sync the changes to the server. 948 </p> 949 950 <p id="Model-previous"> 951 <b class="header">previous</b><code>model.previous(attribute)</code> 952 <br /> 953 During a <tt>"change"</tt> event, this method can be used to get the 954 previous value of a changed attribute. 955 </p> 956 957<pre class="runnable"> 958var bill = new Backbone.Model({ 959 name: "Bill Smith" 960}); 961 962bill.bind("change:name", function(model, name) { 963 alert("Changed name from " + bill.previous("name") + " to " + name); 964}); 965 966bill.set({name : "Bill Jones"}); 967</pre> 968 969 <p id="Model-previousAttributes"> 970 <b class="header">previousAttributes</b><code>model.previousAttributes()</code> 971 <br /> 972 Return a copy of the model's previous attributes. Useful for getting a 973 diff between versions of a model, or getting back to a valid state after 974 an error occurs. 975 </p> 976 977 <h2 id="Collection">Backbone.Collection</h2> 978 979 <p> 980 Collections are ordered sets of models. You can to bind <tt>"change"</tt> events 981 to be notified when any model in the collection has been modified, 982 listen for <tt>"add"</tt> and <tt>"remove"</tt> events, <tt>fetch</tt> 983 the collection from the server, and use a full suite of 984 <a href="#Collection-Underscore-Methods">Underscore.js methods</a>. 985 </p> 986 987 <p> 988 Any event that is triggered on a model in a collection will also be 989 triggered on the collection directly, for convenience. 990 This allows you to listen for changes to specific attributes in any 991 model in a collection, for example: 992 <tt>Documents.bind("change:selected", ...)</tt> 993 </p> 994 995 <p id="Collection-extend"> 996 <b class="header">extend</b><code>Backbone.Collection.extend(properties, [classProperties])</code> 997 <br /> 998 To create a <b>Collection</b> class of your own, extend <b>Backbone.Collection</b>, 999 providing instance <b>properties</b>, as well as optional <b>classProperties</b> to be attached 1000 directly to the collection's constructor function. 1001 </p> 1002 1003 <p id="Collection-model"> 1004 <b class="header">model</b><code>collection.model</code> 1005 <br /> 1006 Override this property to specify the model class that the collection 1007 contains. If defined, you can pass raw attributes objects (and arrays) to 1008 <a href="#Collection-add">add</a>, <a href="#Collection-create">create</a>, 1009 and <a href="#Collection-refresh">refresh</a>, and the attributes will be 1010 converted into a model of the proper type. 1011 </p> 1012 1013<pre> 1014var Library = Backbone.Collection.extend({ 1015 model: Book 1016}); 1017</pre> 1018 1019 <p id="Collection-constructor"> 1020 <b class="header">constructor / initialize</b><code>new Collection([models], [options])</code> 1021 <br /> 1022 When creating a Collection, you may choose to pass in the initial array of <b>models</b>. 1023 The collection's <a href="#Collection-comparator">comparator</a> function 1024 may be included as an option. If you define an <b>initialize</b> function, it will be 1025 invoked when the collection is created. 1026 </p> 1027 1028<pre> 1029var tabs = new TabSet([tab1, tab2, tab3]); 1030</pre> 1031 1032 <p id="Collection-models"> 1033 <b class="header">models</b><code>collection.models</code> 1034 <br /> 1035 Raw access to the JavaScript array of models inside of the collection. Usually you'll 1036 want to use <tt>get</tt>, <tt>at</tt>, or the <b>Underscore methods</b> 1037 to access model objects, but occasionally a direct reference to the array 1038 is desired. 1039 </p> 1040 1041 <p id="Collection-toJSON"> 1042 <b class="header">toJSON</b><code>collection.toJSON()</code> 1043 <br /> 1044 Return an array containing the attributes hash of each model in the 1045 collection. This can be used to serialize and persist the 1046 collection as a whole. The name of this method is a bit confusing, because 1047 it conforms to 1048 <a href="https://developer.mozilla.org/en/JSON#toJSON()_method">JavaScript's JSON API</a>. 1049 </p> 1050 1051<pre class="runnable"> 1052var collection = new Backbone.Collection([ 1053 {name: "Tim", age: 5}, 1054 {name: "Ida", age: 26}, 1055 {name: "Rob", age: 55} 1056]); 1057 1058alert(JSON.stringify(collection)); 1059</pre> 1060 1061 <p id="Collection-Underscore-Methods"> 1062 <b class="header">Underscore Methods (25)</b> 1063 <br /> 1064 Backbone proxies to <b>Underscore.js</b> to provide 25 iteration functions 1065 on <b>Backbone.Collection</b>. They aren't all documented here, but 1066 you can take a look at the Underscore documentation for the full details… 1067 </p> 1068 1069 <ul> 1070 <li><a href="http://documentcloud.github.com/underscore/#each">forEach (each)</a></li> 1071 <li><a href="http://documentcloud.github.com/underscore/#map">map</a></li> 1072 <li><a href="http://documentcloud.github.com/underscore/#reduce">reduce (foldl, inject)</a></li> 1073 <li><a href="http://documentcloud.github.com/underscore/#reduceRight">reduceRight (foldr)</a></li> 1074 <li><a href="http://documentcloud.github.com/underscore/#detect">find (detect)</a></li> 1075 <li><a href="http://documentcloud.github.com/underscore/#select">filter (select)</a></li> 1076 <li><a href="http://documentcloud.github.com/underscore/#reject">reject</a></li> 1077 <li><a href="http://documentcloud.github.com/underscore/#all">every (all)</a></li> 1078 <li><a href="http://documentcloud.github.com/underscore/#any">some (any)</a></li> 1079 <li><a href="http://documentcloud.github.com/underscore/#include">include</a></li> 1080 <li><a href="http://documentcloud.github.com/underscore/#invoke">invoke</a></li> 1081 <li><a href="http://documentcloud.github.com/underscore/#max">max</a></li> 1082 <li><a href="http://documentcloud.github.com/underscore/#min">min</a></li> 1083 <li><a href="http://documentcloud.github.com/underscore/#sortBy">sortBy</a></li> 1084 <li><a href="http://documentcloud.github.com/underscore/#sortedIndex">sortedIndex</a></li> 1085 <li><a href="http://documentcloud.github.com/underscore/#toArray">toArray</a></li> 1086 <li><a href="http://documentcloud.github.com/underscore/#size">size</a></li> 1087 <li><a href="http://documentcloud.github.com/underscore/#first">first</a></li> 1088 <li><a href="http://documentcloud.github.com/underscore/#rest">rest</a></li> 1089 <li><a href="http://documentcloud.github.com/underscore/#last">last</a></li> 1090 <li><a href="http://documentcloud.github.com/underscore/#without">without</a></li> 1091 <li><a href="http://documentcloud.github.com/underscore/#indexOf">indexOf</a></li> 1092 <li><a href="http://documentcloud.github.com/underscore/#lastIndexOf">lastIndexOf</a></li> 1093 <li><a href="http://documentcloud.github.com/underscore/#isEmpty">isEmpty</a></li> 1094 <li><a href="http://documentcloud.github.com/underscore/#chain">chain</a></li> 1095 </ul> 1096 1097<pre> 1098Books.each(function(book) { 1099 book.publish(); 1100}); 1101 1102var titles = Books.map(function(book) { 1103 return book.get("title"); 1104}); 1105 1106var publishedBooks = Books.filter(function(book) { 1107 return book.get("published") === true; 1108}); 1109 1110var alphabetical = Books.sortBy(function(book) { 1111 return book.author.get("name").toLowerCase(); 1112}); 1113</pre> 1114 1115 <p id="Collection-add"> 1116 <b class="header">add</b><code>collection.add(models, [options])</code> 1117 <br /> 1118 Add a model (or an array of models) to the collection. Fires an <tt>"add"</tt> 1119 event, which you can pass <tt>{silent: true}</tt> to suppress. If a 1120 <a href="#Collection-model">model</a> property is defined, you may also pass 1121 raw attributes objects, and have them be vivified as instances of the model. 1122 </p> 1123 1124<pre class="runnable"> 1125var ships = new Backbone.Collection; 1126 1127ships.bind("add", function(ship) { 1128 alert("Ahoy " + ship.get("name") + "!"); 1129}); 1130 1131ships.add([ 1132 {name: "Flying Dutchman"}, 1133 {name: "Black Pearl"} 1134]); 1135</pre> 1136 1137 <p id="Collection-remove"> 1138 <b class="header">remove</b><code>collection.remove(models, [options])</code> 1139 <br /> 1140 Remove a model (or an array of models) from the collection. Fires a 1141 <tt>"remove"</tt> event, which you can use <tt>silent</tt> 1142 to suppress. 1143 </p> 1144 1145 <p id="Collection-get"> 1146 <b class="header">get</b><code>collection.get(id)</code> 1147 <br /> 1148 Get a model from a collection, specified by <b>id</b>. 1149 </p> 1150 1151<pre> 1152var book = Library.get(110); 1153</pre> 1154 1155 <p id="Collection-getByCid"> 1156 <b class="header">getByCid</b><code>collection.getByCid(cid)</code> 1157 <br /> 1158 Get a model from a collection, specified by client id. The client id 1159 is the <tt>.cid</tt> property of the model, automatically assigned whenever 1160 a model is created. Useful for models which have not yet been saved to 1161 the server, and do not yet have true ids. 1162 </p> 1163 1164 <p id="Collection-at"> 1165 <b class="header">at</b><code>collection.at(index)</code> 1166 <br /> 1167 Get a model from a collection, specified by index. Useful if your collection 1168 is sorted, and if your collection isn't sorted, <b>at</b> will still 1169 retrieve models in insertion order. 1170 </p> 1171 1172 <p id="Collection-length"> 1173 <b class="header">length</b><code>collection.length</code> 1174 <br /> 1175 Like an array, a Collection maintains a <tt>length</tt> property, counting 1176 the number of models it contains. 1177 </p> 1178 1179 <p id="Collection-comparator"> 1180 <b class="header">comparator</b><code>collection.comparator</code> 1181 <br /> 1182 By default there is no <b>comparator</b> function on a collection. 1183 If you define a comparator, it will be used to maintain 1184 the collection in sorted order. This means that as models are added, 1185 they are inserted at the correct index in <tt>collection.models</tt>. 1186 Comparator functions take a model and return a numeric or string value 1187 by which the model should be ordered relative to others. 1188 </p> 1189 1190 <p> 1191 Note how even though all of the chapters in this example are added backwards, 1192 they come out in the proper order: 1193 </p> 1194 1195<pre class="runnable"> 1196var Chapter = Backbone.Model; 1197var chapters = new Backbone.Collection; 1198 1199chapters.comparator = function(chapter) { 1200 return chapter.get("page"); 1201}; 1202 1203chapters.add(new Chapter({page: 9, title: "The End"})); 1204chapters.add(new Chapter({page: 5, title: "The Middle"})); 1205chapters.add(new Chapter({page: 1, title: "The Beginning"})); 1206 1207alert(chapters.pluck('title')); 1208</pre> 1209 1210 <p class="warning"> 1211 Brief aside: This comparator function is different than JavaScript's regular 1212 "sort", which must return <tt>0</tt>, <tt>1</tt>, or <tt>-1</tt>, 1213 and is more similar to a <tt>sortBy</tt> — a much nicer API. 1214 </p> 1215 1216 <p id="Collection-sort"> 1217 <b class="header">sort</b><code>collection.sort([options])</code> 1218 <br /> 1219 Force a collection to re-sort itself. You don't need to call this under 1220 normal circumstances, as a collection with a <a href="#Collection-comparator">comparator</a> function 1221 will maintain itself in proper sort order at all times. Calling <b>sort</b> 1222 triggers the collection's <tt>"refresh"</tt> event, unless silenced by passing 1223 <tt>{silent: true}</tt> 1224 </p> 1225 1226 <p id="Collection-pluck"> 1227 <b class="header">pluck</b><code>collection.pluck(attribute)</code> 1228 <br /> 1229 Pluck an attribute from each model in the collection. Equivalent to calling 1230 <tt>map</tt>, and returning a single attribute from the iterator. 1231 </p> 1232 1233<pre class="runnable"> 1234var stooges = new Backbone.Collection([ 1235 new Backbone.Model({name: "Curly"}), 1236 new Backbone.Model({name: "Larry"}), 1237 new Backbone.Model({name: "Moe"}) 1238]); 1239 1240var names = stooges.pluck("name"); 1241 1242alert(JSON.stringify(names)); 1243</pre> 1244 1245 <p id="Collection-url"> 1246 <b class="header">url</b><code>collection.url or collection.url()</code> 1247 <br /> 1248 Set the <b>url</b> property (or function) on a collection to reference 1249 its location on the server. Models within the collection will use <b>url</b> 1250 to construct URLs of their own. 1251 </p> 1252 1253<pre> 1254var Notes = Backbone.Collection.extend({ 1255 url: '/notes' 1256}); 1257 1258// Or, something more sophisticated: 1259 1260var Notes = Backbone.Collection.extend({ 1261 url: function() { 1262 return this.document.url() + '/notes'; 1263 } 1264}); 1265</pre> 1266 1267 <p id="Collection-parse"> 1268 <b class="header">parse</b><code>collection.parse(response)</code> 1269 <br /> 1270 <b>parse</b> is called by Backbone whenever a collection's models are 1271 returned by the server, in <a href="#Collection-fetch">fetch</a>. 1272 The function is passed the raw <tt>response</tt> object, and should return 1273 the array of model attributes to be <a href="#Collection-add">added</a> 1274 to the collection. The default implementation is a no-op, simply passing 1275 through the JSON response. Override this if you need to work with a 1276 preexisting API, or better namespace your responses. 1277 </p> 1278 1279<pre> 1280var Tweets = Backbone.Collection.extend({ 1281 // The Twitter Search API returns tweets under "results". 1282 parse: function(response) { 1283 return response.results; 1284 } 1285}); 1286</pre> 1287 1288 <p id="Collection-fetch"> 1289 <b class="header">fetch</b><code>collection.fetch([options])</code> 1290 <br /> 1291 Fetch the default set of models for this collection from the server, 1292 refreshing the collection when they arrive. The <b>options</b> hash takes 1293 <tt>success</tt> and <tt>error</tt> 1294 callbacks which will be passed <tt>(collection, response)</tt> as arguments. 1295 When the model data returns from the server, the collection will 1296 <a href="#Collection-refresh">refresh</a>. 1297 Delegates to <a href="#Sync">Backbone.sync</a> 1298 under the covers, for custom persistence strategies. 1299 The server handler for <b>fetch</b> requests should return a JSON array of 1300 models. 1301 </p> 1302 1303<pre class="runnable"> 1304Backbone.sync = function(method, model) { 1305 alert(method + ": " + model.url); 1306}; 1307 1308var Accounts = new Backbone.Collection; 1309Accounts.url = '/accounts'; 1310 1311Accounts.fetch(); 1312</pre> 1313 1314 <p> 1315 If you'd like to add the incoming models to the current collection, instead 1316 of replacing the collection's contents, pass <tt>{add: true}</tt> as an 1317 option to <b>fetch</b>. 1318 </p> 1319 1320 <p> 1321 Note that <b>fetch</b> should not be used to populate collections on 1322 page load — all models needed at load time should already be 1323 <a href="#FAQ-bootstrap">bootstrapped</a> in to place. <b>fetch</b> is 1324 intended for lazily-loading models for interfaces that are not needed 1325 immediately: for example, documents with collections of notes that may be 1326 toggled open and closed. 1327 </p> 1328 1329 <p id="Collection-refresh"> 1330 <b class="header">refresh</b><code>collection.refresh(models, [options])</code> 1331 <br /> 1332 Adding and removing models one at a time is all well and good, but sometimes 1333 you have so many models to change that you'd rather just update the collection 1334 in bulk. Use <b>refresh</b> to replace a collection with a new list 1335 of models (or attribute hashes), triggering a single <tt>"refresh"</tt> event 1336 at the end. Pass <tt>{silent: true}</tt> to suppress the <tt>"refresh"</tt> event. 1337 </p> 1338 1339 <p> 1340 Here's an example using <b>refresh</b> to bootstrap a collection during initial page load, 1341 in a Rails application. 1342 </p> 1343 1344<pre> 1345<script> 1346 Accounts.refresh(<%= @accounts.to_json %>); 1347</script> 1348</pre> 1349 1350 <p id="Collection-create"> 1351 <b class="header">create</b><code>collection.create(attributes, [options])</code> 1352 <br /> 1353 Convenience to create a new instance of a model within a collection. 1354 Equivalent to instantiating a model with a hash of attributes, 1355 saving the model to the server, and adding the model to the set after being 1356 successfully created. Returns 1357 the model, or <tt>false</tt> if a validation error prevented the 1358 model from being created. In order for this to work, your should set the 1359 <a href="#Collection-model">model</a> property of the collection. 1360 </p> 1361 1362<pre> 1363var Library = Backbone.Collection.extend({ 1364 model: Book 1365}); 1366 1367var NYPL = new Library; 1368 1369var othello = NYPL.create({ 1370 title: "Othello", 1371 author: "William Shakespeare" 1372}); 1373</pre> 1374 1375 <h2 id="Controller">Backbone.Controller</h2> 1376 1377 <p> 1378 Web applications often choose to change their URL fragment (<tt>#fragment</tt>) 1379 in order to provide shareable, bookmarkable URLs for an Ajax-heavy application. 1380 <b>Backbone.Controller</b> provides methods for routing client-side URL 1381 fragments, and connecting them to actions and events. 1382 </p> 1383 1384 <p class="warning"> 1385 Backbone controllers do not yet make use of HTML5 <b>pushState</b> and 1386 <b>replaceState</b>. Currently, <b>pushState</b> and <b>replaceState</b> 1387 need special handling on the server-side, cause you to mint duplicate URLs, 1388 and have an incomplete API. We may start supporting them in the future 1389 when these issues have been resolved. 1390 </p> 1391 1392 <p> 1393 During page load, after your application has finished creating all of its controllers, 1394 be sure to call <tt>Backbone.history.start()</tt> to route the initial URL. 1395 </p> 1396 1397 <p id="Controller-extend"> 1398 <b class="header">extend</b><code>Backbone.Controller.extend(properties, [classProperties])</code> 1399 <br /> 1400 Get started by creating a custom controller class. You'll 1401 want to define actions that are triggered when certain URL fragments are 1402 matched, and provide a <a href="#Controller-routes">routes</a> hash 1403 that pairs routes to actions. 1404 </p> 1405 1406<pre> 1407var Workspace = Backbone.Controller.extend({ 1408 1409 routes: { 1410 "help": "help", // #help 1411 "search/:query": "search", // #search/kiwis 1412 "search/:query/p:page": "search" // #search/kiwis/p7 1413 }, 1414 1415 help: function() { 1416 ... 1417 }, 1418 1419 search: function(query, page) { 1420 ... 1421 } 1422 1423}); 1424</pre> 1425 1426 <p id="Controller-routes"> 1427 <b class="header">routes</b><code>controller.routes</code> 1428 <br /> 1429 The routes hash maps URLs with parameters to functions on your controller, 1430 similar to the <a href="#View">View</a>'s <a href="#View-delegateEvents">events hash</a>. 1431 Routes can contain parameter parts, <tt>:param</tt>, which match a single URL 1432 component between slashes; and splat parts <tt>*splat</tt>, which can match 1433 any number of URL components. 1434 </p> 1435 1436 <p> 1437 For example, a route of <tt>"search/:query/p:page"</tt> will match 1438 a fragment of <tt>#search/obama/p2</tt>, passing <tt>"obama"</tt> 1439 and <tt>"2"</tt> to the action. A route of <tt>"file/*path"</tt> will 1440 match <tt>#file/nested/folder/file.txt</tt>, 1441 passing <tt>"nested/folder/file.txt"</tt> to the action. 1442 </p> 1443 1444 <p> 1445 When the visitor presses the back button, or enters a URL, and a particular 1446 route is matched, the name of the action will be fired as an 1447 <a href="#Events">event</a>, so that other objects can listen to the controller, 1448 and be notified. In the following example, visiting <tt>#help/uploading</tt> 1449 will fire a <tt>route:help</tt> event from the controller. 1450 </p> 1451 1452<pre> 1453routes: { 1454 "help/:page": "help", 1455 "download/*path": "download", 1456 "folder/:name": "openFolder", 1457 "folder/:name-:mode": "openFolder" 1458} 1459</pre> 1460 1461<pre> 1462controller.bind("route:help", function(page) { 1463 ... 1464}); 1465</pre> 1466 1467 <p id="Controller-constructor"> 1468 <b class="header">constructor / initialize</b><code>new Controller([options])</code> 1469 <br /> 1470 When creating a new controller, you may pass its 1471 <a href="#Controller-routes">routes</a> hash directly as an option, if you 1472 choose. All <tt>options</tt> will also be passed to your <tt>initialize</tt> 1473 function, if defined. 1474 </p> 1475 1476 <p id="Controller-route"> 1477 <b class="header">route</b><code>controller.route(route, name, callback)</code> 1478 <br /> 1479 Manually create a route for the controller, The <tt>route</tt> argument may 1480 be a <a href="#Controller-routes">routing string</a> or regular expression. 1481 Each matching capture from the route or regular expression will be passed as 1482 an argument to the callback. The <tt>name</tt> argument will be triggered as 1483 a <tt>"route:name"</tt> event whenever the route is matched. 1484 </p> 1485 1486<pre> 1487initialize: function(options) { 1488 1489 // Matches #page/10, passing "10" 1490 this.route("page/:number", "page", function(number){ ... }); 1491 1492 // Matches /117-a/b/c/open, passing "117-a/b/c" 1493 this.route(/^(.*?)\/open$/, "open", function(id){ ... }); 1494 1495} 1496</pre> 1497 1498 <p id="Controller-saveLocation"> 1499 <b class="header">saveLocation</b><code>controller.saveLocation(fragment)</code> 1500 <br /> 1501 Whenever you reach a point in your application that you'd like to save 1502 as a URL, call <b>saveLocation</b> in order to update the URL fragment 1503 without triggering a <tt>hashchange</tt> event. (If you would prefer to 1504 trigger the event and routing, you can just set the hash directly.) 1505 </p> 1506 1507<pre> 1508openPage: function(pageNumber) { 1509 this.document.pages.at(pageNumber).open(); 1510 this.saveLocation("page/" + pageNumber); 1511} 1512</pre> 1513 1514 <h2 id="History">Backbone.history</h2> 1515 1516 <p> 1517 <b>History</b> serves as a global router (per frame) to handle <tt>hashchange</tt> 1518 events, match the appropriate route, and trigger callbacks. You shouldn't 1519 ever have to create one of these yourself — you should use the reference 1520 to <tt>Backbone.history</tt> that will be created for you automatically if you make use 1521 of <a href="#Controller">Controllers</a> with <a href="#Controller-routes">routes</a>. 1522 </p> 1523 1524 <p id="History-start"> 1525 <b class="header">start</b><code>Backbone.history.start()</code> 1526 <br /> 1527 When all of your <a href="#Controller">Controllers</a> have been created, 1528 and all of the routes are set up properly, call <tt>Backbone.history.start()</tt> 1529 to begin monitoring <tt>hashchange</tt> events, and dispatching routes. 1530 </p> 1531 1532<pre> 1533$(function(){ 1534 new WorkspaceController(); 1535 new HelpPaneController(); 1536 Backbone.history.start(); 1537}); 1538</pre> 1539 1540 <h2 id="Sync">Backbone.sync</h2> 1541 1542 <p> 1543 <b>Backbone.sync</b> is the function the Backbone calls every time it 1544 attempts to read or save a model to the server. By default, it uses 1545 <tt>(jQuery/Zepto).ajax</tt> to make a RESTful JSON request. You can override 1546 it in order to use a different persistence strategy, such as WebSockets, 1547 XML transport, or Local Storage. 1548 </p> 1549 1550 <p> 1551 The method signature of <b>Backbone.sync</b> is <tt>sync(method, model, success, error)</tt> 1552 </p> 1553 1554 <ul> 1555 <li><b>method</b> – the CRUD method (<tt>"create"</tt>, <tt>"read"</tt>, <tt>"update"</tt>, or <tt>"delete"</tt>)</li> 1556 <li><b>model</b> – the model to be saved (or collection to be read)</li> 1557 <li><b>success({model: ...})</b> – a callback that should be fired if the request works</li> 1558 <li><b>error({model: ...})</b> – a callback that should be fired if the request fails</li> 1559 </ul> 1560 1561 <p> 1562 With the default implementation, when <b>Backbone.sync</b> sends up a request to save 1563 a model, its attributes will be passed, serialized as JSON, and sent in the HTTP body 1564 with content-type <tt>application/json</tt>. When returning a JSON response, 1565 send down the attributes of the model that have been changed by the server, and need 1566 to be updated on the client. When responding to a <tt>"read"</tt> request from a collection 1567 (<a href="#Collection#fetch">Collection#fetch</a>), send down an array 1568 of model attribute objects. 1569 </p> 1570 1571 <p> 1572 The default <b>sync</b> handler maps CRUD to REST like so: 1573 </p> 1574 1575 <ul> 1576 <li><b>create → POST </b><tt>/collection</tt></li> 1577 <li><b>read → GET </b><tt>/collection[/id]</tt></li> 1578 <li><b>update → PUT </b><tt>/collection/id</tt></li> 1579 <li><b>delete → DELETE </b><tt>/collection/id</tt></li> 1580 </ul> 1581 1582 <p> 1583 As an example, a Rails handler responding to an <tt>"update"</tt> call from 1584 <tt>Backbone</tt> might look like this: <i>(In real code, never use 1585 </i><tt>update_attributes</tt><i> blindly, and always whitelist the attributes 1586 you allow to be changed.)</i> 1587 </p> 1588 1589<pre> 1590def update 1591 account = Account.find params[:id] 1592 account.update_attributes params 1593 render :json => account 1594end 1595</pre> 1596 1597 <p> 1598 One more tip for Rails integration is to disable the default namespacing for 1599 <tt>to_json</tt> calls on models by setting <tt>ActiveRecord::Base.include_root_in_json = false</tt> 1600 </p> 1601 1602 <p id="Sync-emulateHTTP"> 1603 <b class="header">emulateHTTP</b><code>Backbone.emulateHTTP = true</code> 1604 <br /> 1605 If you want to work with a legacy web server that doesn't support Backbones's 1606 default REST/HTTP approach, you may choose to turn on <tt>Backbone.emulateHTTP</tt>. 1607 Setting this option will fake <tt>PUT</tt> and <tt>DELETE</tt> requests with 1608 a HTTP <tt>POST</tt>, and pass them under the <tt>_method</tt> parameter. Setting this option 1609 will also set an <tt>X-HTTP-Method-Override</tt> header with the true method. 1610 </p> 1611 1612<pre> 1613Backbone.emulateHTTP = true; 1614 1615model.save(); // POST to "/collection/id", with "_method=PUT" + header. 1616</pre> 1617 1618 <p id="Sync-emulateJSON"> 1619 <b class="header">emulateJSON</b><code>Backbone.emulateJSON = true</code> 1620 <br /> 1621 If you're working with a legacy web server that can't handle requests 1622 encoded as <tt>application/json</tt>, setting <tt>Backbone.emulateJSON = true;</tt> 1623 will cause the JSON to be serialized under a <tt>model</tt> parameter, and 1624 the request to be made with a <tt>application/x-www-form-urlencoded</tt> 1625 mime type, as if from an HTML form. 1626 </p> 1627 1628 <h2 id="View">Backbone.View</h2> 1629 1630 <p> 1631 Backbone views are almost more convention than they are code — they 1632 don't determine anything about your HTML or CSS for you, and can be used 1633 with any JavaScript templating library. 1634 The general idea is to organize your interface into logical views, 1635 backed by models, each of which can be updated independently when the 1636 model changes, without having to redraw the page. Instead of digging into 1637 a JSON object, looking up an element in the DOM, and updating the HTML by hand, 1638 you can bind your view's <tt>render</tt> function to the model's <tt>"change"</tt> 1639 event — and now everywhere that 1640 model data is displayed in the UI, it is always immediately up to date. 1641 </p> 1642 1643 <p id="View-extend"> 1644 <b class="header">extend</b><code>Backbone.View.extend(properties, [classProperties])</code> 1645 <br /> 1646 Get started with views by creating a custom view class. You'll want to 1647 override the <a href="#View-render">render</a> function, specify your 1648 declarative <a href="#View-delegateEvents">events</a>, and perhaps the 1649 <tt>tagName</tt>, <tt>className</tt>, or <tt>id</tt> of the View's root 1650 element. 1651 </p> 1652 1653<pre> 1654var DocumentRow = Backbone.View.extend({ 1655 1656 tagName: "li", 1657 1658 className: "document-row", 1659 1660 events: { 1661 "click .icon": "open", 1662 "click .button.edit": "openEditDialog", 1663 "click .button.delete": "destroy" 1664 }, 1665 1666 initialize: function() { 1667 _.bindAll(this, "render"); 1668 }, 1669 1670 render: function() { 1671 ... 1672 } 1673 1674}); 1675</pre> 1676 1677 <p id="View-constructor"> 1678 <b class="header">constructor / initialize</b><code>new View([options])</code> 1679 <br /> 1680 When creating a new View, the options you pass are attached to the view 1681 as <tt>this.options</tt>, for future reference. There are several special 1682 options that, if passed, will be attached directly to the view: 1683 <tt>model</tt>, <tt>collection</tt>, 1684 <tt>el</tt>, <tt>id</tt>, <tt>className</tt>, and <tt>tagName</tt>. 1685 If the view defines an <b>initialize</b> function, it will be called when 1686 the view is first created. If you'd like to create a view that references 1687 an element <i>already</i> in the DOM, pass in the element as an option: 1688 <tt>new View({el: existingElement})</tt> 1689 </p> 1690 1691<pre> 1692var doc = Documents.first(); 1693 1694new DocumentRow({ 1695 model: doc, 1696 id: "document-row-" + doc.id 1697}); 1698</pre> 1699 1700 <p id="View-el"> 1701 <b class="header">el</b><code>view.el</code> 1702 <br /> 1703 All views have a DOM element at all times (the <b>el</b> property), 1704 whether they've already been inserted into the page or not. In this 1705 fashion, views can be rendered at any time, and inserted into the DOM all 1706 at once, in order to get high-performance UI rendering with as few 1707 reflows and repaints as possible. <tt>this.el</tt> is created from the 1708 view's <tt>tagName</tt>, <tt>className</tt>, and <tt>id</tt> properties, 1709 if specified. If not, <b>el</b> is an empty <tt>div</tt>. 1710 </p> 1711 1712 <p> 1713 You may assign <b>el</b> directly if the view is being 1714 created for an element that already exists in the DOM. Use either a 1715 reference to a real DOM element, or a css selector string. 1716 </p> 1717 1718<pre class="runnable"> 1719var ItemView = Backbone.View.extend({ 1720 tagName: 'li' 1721}); 1722 1723var BodyView = Backbone.View.extend({ 1724 el: 'body' 1725}); 1726 1727var item = new ItemView(); 1728var body = new BodyView(); 1729 1730alert(item.el + ' ' + body.el); 1731</pre> 1732 1733 <p id="View-dollar"> 1734 <b class="header">$ (jQuery or Zepto)</b><code>view.$(selector)</code> 1735 <br /> 1736 If jQuery or Zepto is included on the page, each view has a 1737 <b>$</b> function that runs queries scoped within the view's element. If you use this 1738 scoped jQuery function, you don't have to use model ids as part of your query 1739 to pull out specific elements in a list, and can rely much more on HTML class 1740 attributes. It's equivalent to running: <tt>$(selector, this.el)</tt> 1741 </p> 1742 1743<pre> 1744ui.Chapter = Backbone.View.extend({ 1745 serialize : function() { 1746 return { 1747 title: this.$(".title").text(), 1748 start: this.$(".start-page").text(), 1749 end: this.$(".end-page").text() 1750 }; 1751 } 1752}); 1753</pre> 1754 1755 <p id="View-render"> 1756 <b class="header">render</b><code>view.render()</code> 1757 <br /> 1758 The default implementation of <b>render</b> is a no-op. Override this 1759 function with your code that renders the view template from model data, 1760 and updates <tt>this.el</tt> with the new HTML. A good 1761 convention is to <tt>return this</tt> at the end of <b>render</b> to 1762 enable chained calls. 1763 </p> 1764 1765<pre> 1766var Bookmark = Backbone.View.extend({ 1767 render: function() { 1768 $(this.el).html(this.template(this.model.toJSON())); 1769 return this; 1770 } 1771}); 1772</pre> 1773 1774 <p> 1775 Backbone is agnostic with respect to your preferred method of HTML templating. 1776 Your <b>render</b> function could even munge together an HTML string, or use 1777 <tt>document.createElement</tt> to generate a DOM tree. However, we suggest 1778 choosing a nice JavaScript templating library. 1779 <a href="http://github.com/janl/mustache.js">Mustache.js</a>, 1780 <a href="http://github.com/creationix/haml-js">Haml-js</a>, and 1781 <a href="http://github.com/sstephenson/eco">Eco</a> are all fine alternatives. 1782 Because <a href="http://documentcloud.github.com/underscore/">Underscore.js</a> is already on the page, 1783 <a href="http://documentcloud.github.com/underscore/#template">_.template</a> 1784 is available, and is an excellent choice if you've already XSS-sanitized 1785 your interpolated data. 1786 </p> 1787 1788 <p> 1789 Whatever templating strategy you end up with, it's nice if you <i>never</i> 1790 have to put strings of HTML in your JavaScript. At DocumentCloud, we 1791 use <a href="http://documentcloud.github.com/jammit/">Jammit</a> in order 1792 to package up JavaScript templates stored in <tt>/app/views</tt> as part 1793 of our main <tt>core.js</tt> asset package. 1794 </p> 1795 1796 <p id="View-remove"> 1797 <b class="header">remove</b><code>view.remove()</code> 1798 <br /> 1799 Convenience function for removing the view from the DOM. Equivalent to calling 1800 <tt>$(view.el).remove();</tt> 1801 </p> 1802 1803 <p id="View-make"> 1804 <b class="header">make</b><code>view.make(tagName, [attributes], [content])</code> 1805 <br /> 1806 Convenience function for creating a DOM element of the given type (<b>tagName</b>), 1807 with optional attributes and HTML content. Used internally to create the 1808 initial <tt>view.el</tt>. 1809 </p> 1810 1811<pre class="runnable"> 1812var view = new Backbone.View; 1813 1814var el = view.make("b", {className: "bold"}, "Bold! "); 1815 1816$("#make-demo").append(el); 1817</pre> 1818 1819<div id="make-demo"></div> 1820 1821 <p id="View-delegateEvents"> 1822 <b class="header">delegateEvents</b><code>delegateEvents([events])</code> 1823 <br /> 1824 Uses jQuery's <tt>delegate</tt> function to provide declarative callbacks 1825 for DOM events within a view. 1826 If an <b>events</b> hash is not passed directly, uses <tt>this.events</tt> 1827 as the source. Events are written in the format <tt>{"event selector": "callback"}</tt>. 1828 Omitting the <tt>selector</tt> causes the event to be bound to the view's 1829 root element (<tt>this.el</tt>). By default, <tt>delegateEvents</tt> is called 1830 within the View's constructor for you, so if you have a simple <tt>events</tt> 1831 hash, all of your DOM events will always already be connected, and you will 1832 never have to call this function yourself. 1833 </p> 1834 1835 <p> 1836 Using <b>delegateEvents</b> provides a number of advantages over manually 1837 using jQuery to bind events to child elements during <a href="#View-render">render</a>. All attached 1838 callbacks are bound to the view before being handed off to jQuery, so when 1839 the callbacks are invoked, <tt>this</tt> continues to refer to the view object. When 1840 <b>delegateEvents</b> is run again, perhaps with a different <tt>events</tt> 1841 hash, all callbacks are removed and delegated afresh — useful for 1842 views which need to behave differently when in different modes. 1843 </p> 1844 1845 <p> 1846 A view that displays a document in a search result might look 1847 something like this: 1848 </p> 1849 1850<pre> 1851var DocumentView = Backbone.View.extend({ 1852 1853 events: { 1854 "dblclick" : "open", 1855 "click .icon.doc" : "select", 1856 "contextmenu .icon.doc" : "showMenu", 1857 "click .show_notes" : "toggleNotes", 1858 "click .title .lock" : "editAccessLevel", 1859 "mouseover .title .date" : "showTooltip" 1860 }, 1861 1862 render: function() { 1863 $(this.el).html(this.template(this.model.toJSON())); 1864 return this; 1865 }, 1866 1867 open: function() { 1868 window.open(this.model.get("viewer_url")); 1869 }, 1870 1871 select: function() { 1872 this.model.set({selected: true}); 1873 }, 1874 1875 ... 1876 1877}); 1878</pre> 1879 1880 <h2 id="examples">Examples</h2> 1881 1882 <p> 1883 <a href="http://jgn.me/">Jérôme Gravel-Niquet</a> has contributed a 1884 <a href="examples/todos/index.html">Todo List application</a> 1885 that is bundled in the repository as Backbone example. If you're wondering 1886 where to get started with Backbone in general, take a moment to 1887 <a href="docs/todos.html">read through the annotated source</a>. The app uses a 1888 <a href="docs/backbone-localstorage.html">LocalStorage adapter</a> 1889 to transparently save all of your todos within your browser, instead of 1890 sending them to a server. Jérôme also has a version hosted at 1891 <a href="http://localtodos.com/">localtodos.com</a> that uses a 1892 <a href="http://github.com/jeromegn/backbone-mootools">MooTools-backed version of Backbone</a> 1893 instead of jQuery. 1894 </p> 1895 1896 <div style="text-align: center;"> 1897 <a href="examples/todos/index.html"> 1898 <img src="docs/images/todos.png" alt="Todos" class="example_image" /> 1899 </a> 1900 </div> 1901 1902 <p> 1903 The <a href="http://www.documentcloud.org/public/#search/">DocumentCloud workspace</a> 1904 is built on Backbone.js, with <i>Documents</i>, <i>Projects</i>, 1905 <i>Notes</i>, and <i>Accounts</i> all as Backbone models and collections. 1906 </p> 1907 1908 <div style="text-align: center;"> 1909 <a href="http://www.documentcloud.org/public/#search/"> 1910 <img src="docs/images/dc-workspace.png" alt="DocumentCloud Workspace" class="example_image" /> 1911 </a> 1912 </div> 1913 1914 <p> 1915 <a href="http://37signals.com/">37Signals</a> used Backbone.js to create 1916 <a href="http://basecamphq.com/mobile">Basecamp Mobile</a>, the mobile version 1917 of their popular project management software. You can access all your Basecamp 1918 projects, post new messages, and comment on milestones (all represented 1919 internally as Backbone.js models). 1920 </p> 1921 1922 <div style="text-align: center;"> 1923 <a href="http://basecamphq.com/mobile"> 1924 <img src="docs/images/basecamp-mobile.png" alt="Basecamp Mobile" class="example_image" /> 1925 </a> 1926 </div> 1927 1928 <p> 1929 Our fellow 1930 <a href="http://www.newschallenge.org/">Knight Foundation News Challenge</a> 1931 winners, <a href="http://mapbox.com/">MapBox</a>, created an open-source 1932 map design studio with Backbone.js: 1933 <a href="http://mapbox.github.com/tilemill/">TileMill</a>. 1934 TileMill lets you manage map layers based on shapefiles and rasters, and 1935 edit their appearance directly in the browser with the 1936 <a href="https://github.com/mapbox/carto">Carto styling language</a>. 1937 </p> 1938 1939 <div style="text-align: center;"> 1940 <a href="http://mapbox.github.com/tilemill/"> 1941 <img src="docs/images/tilemill.png" alt="TileMill" class="example_image" /> 1942 </a> 1943 </div> 1944 1945 <p> 1946 <a href="http://twitter.com/elliottkember">Elliott Kember</a> and 1947 <a href="http://twitter.com/dizzyup">Hector Simpson</a> built 1948 <a href="http://instagre.at">Insta-great!</a> 1949 - a fun way to explore popular photos and interact with 1950 <a href="http://instagram.com/">Instagram</a> on the web. 1951 Elliott says, "Backbone.js and Coffeescript were insanely useful for 1952 writing clean, consistent UI code and keeping everything modular and 1953 readable, even through several code refactors. I'm in love." 1954 </p> 1955 1956 <div style="text-align: center;"> 1957 <a href="http://instagre.at"> 1958 <img src="docs/images/instagreat.png" alt="instagre.at" class="example_image" /> 1959 </a> 1960 </div> 1961 1962 <p> 1963 <a href="http://www.twitter.com/jamesjyu">James Yu</a> used Backbone.js to 1964 create <a href="http://www.quietwrite.com/">QuietWrite</a>, an app 1965 that gives writers a clean and quiet interface to concentrate on the text itself. 1966 The editor relies on Backbone to persist document data to the server. He 1967 followed up with a Backbone.js + Rails tutorial that describes how to implement 1968 <a href="http://www.jamesyu.org/2011/01/27/cloudedit-a-backbone-js-tutorial-by-example/">CloudEdit, a simple document editing app</a>. 1969 </p> 1970 1971 <div style="text-align: center;"> 1972 <a href="http://www.quietwrite.com/"> 1973 <img src="docs/images/quietwrite.png" alt="QuietWrite" class="example_image" /> 1974 </a> 1975 </div> 1976 1977 <p> 1978 <a href="http://twitter.com/evilchelu">Cristi Balan</a> and 1979 <a href="http://dira.ro">Irina Dumitrascu</a> created 1980 <a href="http://tzigla.com">Tzigla</a>, a collaborative drawing 1981 application where artists make tiles that connect to each other to 1982 create <a href="http://tzigla.com/boards/1">surreal drawings</a>. 1983 Backbone models help organize the code, controllers provide 1984 <a href="http://tzigla.com/boards/1#!/tiles/2-2">bookmarkable deep links</a>, 1985 and the views are rendered with 1986 <a href="https://github.com/creationix/haml-js">haml.js</a> and 1987 <a href="http://zeptojs.com/">Zepto</a>. 1988 Tzigla is written in Ruby (Rails) on the backend, and 1989 <a href="http://coffeescript.org">CoffeeScript</a> on the frontend, with 1990 <a href="http://documentcloud.github.com/jammit/">Jammit</a> 1991 prepackaging the static assets. 1992 </p> 1993 1994 <div style="text-align: center;"> 1995 <a href="http://www.tzigla.com/"> 1996 <img src="docs/images/tzigla.png" alt="Tzigla" class="example_image" /> 1997 </a> 1998 </div> 1999 2000 <p> 2001 Michael Aufreiter is building an open source document authoring and publishing engine: <a href="http://substance.io">Substance</a>. 2002 Substance makes use of Backbone.View and Backbone.Controller, while Backbone plays well together with <a href="http://github.com/michael/data">Data.js</a>, which is used for data persistence. 2003 </p> 2004 2005 <div style="text-align: center;"> 2006 <a href="http://substance.io/"> 2007 <img src="docs/images/substance.png" alt="Substance" class="example_image" /> 2008 </a> 2009 </div> 2010 2011 <p> 2012 <a href="http://bennolan.com/">Ben Nolan</a> created 2013 <a href="http://bennolan.com/2010/11/24/backbone-jquery-demo.html">an example "Backbone Mobile" application</a>, combining Backbone.js 2014 with <a href="http://jquerymobile.com/">jQuery Mobile</a>. You can 2015 <a href="http://bennolan.com/science/backbone-mobile/">try the app</a> 2016 in your browser, or view the 2017 <a href="https://github.com/bnolan/backbone-mobile">source code</a> on Github. 2018 </p> 2019 2020 <div style="text-align: center;"> 2021 <a href="http://bennolan.com/science/backbone-mobile/"> 2022 <img src="docs/images/backbone-mobile.png" alt="Backbone Mobile" class="example_image" /> 2023 </a> 2024 </div> 2025 2026 <h2 id="faq">F.A.Q.</h2> 2027 2028 <p id="FAQ-events"> 2029 <b class="header">Catalog of Events</b> 2030 <br /> 2031 Here's a list of all of the built-in events that Backbone.js can fire. 2032 You're also free to trigger your own events on Models and Views as you 2033 see fit. 2034 </p> 2035 2036 <ul> 2037 <li><b>"add"</b> (model, collection) — when a model is added to a collection. </li> 2038 <li><b>"remove"</b> (model, collection) — when a model is removed from a collection. </li> 2039 <li><b>"refresh"</b> (collection) — when the collection's entire contents have been replaced. </li> 2040 <li><b>"change"</b> (model, collection) — when a model's attributes have changed. </li> 2041 <li><b>"change:[attribute]"</b> (model, collection) — when a specific attribute has been updated. </li> 2042 <li><b>"destrooy"</b> (model, collection) — when a model is <a href="#Model-destroy">destroyed</a>. </li> 2043 <li><b>"error"</b> (model, collection) — when a model's validation fails, or a <a href="#Model-save">save</a> call fails on the server. </li> 2044 <li><b>"route:[name]"</b> (controller) — when one of a controller's routes has matched. </li> 2045 <li><b>"all"</b> — this special event fires for <i>any</i> triggered event, passing the event name as the first argument. </li> 2046 </ul> 2047 2048 <p id="FAQ-nested"> 2049 <b class="header">Nested Models & Collections</b> 2050 <br /> 2051 It's common to nest collections inside of models with Backbone. For example, 2052 consider a <tt>Mailbox</tt> model that contains many <tt>Message</tt> models. 2053 One nice pattern for handling this is have a <tt>this.messages</tt> collection 2054 for each mailbox, enabling the lazy-loading of messages, when the mailbox 2055 is first opened ... perhaps with <tt>MessageList</tt> views listening for 2056 <tt>"add"</tt> and <tt>"remove"</tt> events. 2057 </p> 2058 2059<pre> 2060var Mailbox = Backbone.Model.extend({ 2061 2062 initialize: function() { 2063 this.messages = new Messages; 2064 this.messages.url = '/mailbox/' + this.id + '/messages'; 2065 this.messages.bind("refresh", this.updateCounts); 2066 }, 2067 2068 ... 2069 2070}); 2071 2072var Inbox = new Mailbox; 2073 2074// And then, when the Inbox is opened: 2075 2076Inbox.messages.fetch(); 2077</pre> 2078 2079 <p id="FAQ-bootstrap"> 2080 <b class="header">Loading Bootstrapped Models</b> 2081 <br /> 2082 When your app first loads, it's common to have a set of initial models that 2083 you know you're going to need, in order to render the page. Instead of 2084 firing an extra AJAX request to <a href="#Collection-fetch">fetch</a> them, 2085 a nicer pattern is to have their data already bootstrapped into the page. 2086 You can then use <a href="#Collection-refresh">refresh</a> to populate your 2087 collections with the initial data. At DocumentCloud, in the 2088 <a href="http://en.wikipedia.org/wiki/ERuby">ERB</a> template for the 2089 workspace, we do something along these lines: 2090 </p> 2091 2092<pre> 2093<script> 2094 Accounts.refresh(<%= @accounts.to_json %>); 2095 Projects.refresh(<%= @projects.to_json(:collaborators => true) %>); 2096</script> 2097</pre> 2098 2099 <p id="FAQ-mvc"> 2100 <b class="header">How does Backbone relate to "traditional" MVC?</b> 2101 <br /> 2102 Different implementations of the 2103 <a href="http://en.wikipedia.org/wiki/Model–View–Controller">Model-View-Controller</a> 2104 pattern tend to disagree about the definition of a controller. If it helps any, in 2105 Backbone, the <a href="#View">View</a> class can also be thought of as a 2106 kind of controller, dispatching events that originate from the UI, with 2107 the HTML template serving as the true view. We call it a View because it 2108 represents a logical chunk of UI, responsible for the contents of a single 2109 DOM element. 2110 </p> 2111 2112 <p id="FAQ-this"> 2113 <b class="header">Binding "this"</b> 2114 <br /> 2115 Perhaps the single most common JavaScript "gotcha" is the fact that when 2116 you pass a function as a callback, it's value for <tt>this</tt> is lost. With 2117 Backbone, when dealing with <a href="#Events">events</a> and callbacks, 2118 you'll often find it useful to rely on 2119 <a href="http://documentcloud.github.com/underscore/#bind">_.bind</a> and 2120 <a href="http://documentcloud.github.com/underscore/#bindAll">_.bindAll</a> 2121 from Underscore.js. <tt>_.bind</tt> takes a function and an object to be 2122 used as <tt>this</tt>, any time the function is called in the future. 2123 <tt>_.bindAll</tt> takes an object and a list of method names: each method 2124 in the list will be bound to the object, so that it's <tt>this</tt> may 2125 not change. For example, in a <a href="#View">View</a> that listens for 2126 changes to a collection... 2127 </p> 2128 2129<pre> 2130var MessageList = Backbone.View.extend({ 2131 2132 initialize: function() { 2133 _.bindAll(this, "addMessage", "removeMessage", "render"); 2134 2135 var messages = this.collection; 2136 messages.bind("refresh", this.render); 2137 messages.bind("add", this.addMessage); 2138 messages.bind("remove", this.removeMessage); 2139 } 2140 2141}); 2142 2143// Later, in the app... 2144 2145Inbox.messages.add(newMessage); 2146</pre> 2147 2148 <p id="FAQ-rias"> 2149 <b class="header"> 2150 How is Backbone different than 2151 <a href="http://www.sproutcore.com/">SproutCore</a> or 2152 <a href="http://cappuccino.org/">Cappuccino</a>? 2153 </b> 2154 <br /> 2155 This question is frequently asked, and all three projects apply general 2156 <a href="http://en.wikipedia.org/wiki/Model–View–Controller">Model-View-Controller</a> 2157 principles to JavaScript applications. However, there isn't much basis 2158 for comparison. SproutCore and Cappuccino provide rich UI widgets, vast 2159 core libraries, and determine the structure of your HTML for you. 2160 Both frameworks measure in the hundreds of kilobytes when packed and 2161 gzipped, and megabytes of JavaScript, CSS, and images when loaded in the browser 2162 — there's a lot of room underneath for libraries of a more moderate scope. 2163 Backbone is a <i>4 kilobyte</i> include that provides 2164 just the core concepts of models, events, collections, views, controllers, 2165 and persistence. 2166 </p> 2167 2168 <h2 id="changelog">Change Log</h2> 2169 2170 <p> 2171 <b class="header">0.3.3</b> — <small><i>Dec 1, 2010</i></small><br /> 2172 Backbone.js now supports <a href="http://zeptojs.com">Zepto</a>, alongside 2173 jQuery, as a framework for DOM manipulation and Ajax support. 2174 Implemented <a href="#Model-escape">Model#escape</a>, to efficiently handle 2175 attributes intended for HTML interpolation. When trying to persist a model, 2176 failed requests will now trigger an <tt>"error"</tt> event. The 2177 ubiquitous <tt>options</tt> argument is now passed as the final argument 2178 to all <tt>"change"</tt> events. 2179 </p> 2180 2181 <p> 2182 <b class="header">0.3.2</b> — <small><i>Nov 23, 2010</i></small><br /> 2183 Bugfix for IE7 + iframe-based "hashchange" events. <tt>sync</tt> may now be 2184 overridden on a per-model, or per-collection basis. Fixed recursion error 2185 when calling <tt>save</tt> with no changed attributes, within a 2186 <tt>"change"</tt> event. 2187 </p> 2188 2189 <p> 2190 <b class="header">0.3.1</b> — <small><i>Nov 15, 2010</i></small><br /> 2191 All <tt>"add"</tt> and <tt>"remove"</tt> events are now sent through the 2192 model, so that views can listen for them without having to know about the 2193 collection. Added a <tt>remove</tt> method to <a href="#View">Backbone.View</a>. 2194 <tt>toJSON</tt> is no longer called at all for <tt>'read'</tt> and <tt>'delete'</tt> requests. 2195 Backbone routes are now able to load empty URL fragments. 2196 </p> 2197 2198 <p> 2199 <b class="header">0.3.0</b> — <small><i>Nov 9, 2010</i></small><br /> 2200 Backbone now has <a href="#Controller">Controllers</a> and 2201 <a href="#History">History</a>, for doing client-side routing based on 2202 URL fragments. 2203 Added <tt>emulateHTTP</tt> to provide support for legacy servers that don't 2204 do <tt>PUT</tt> and <tt>DELETE</tt>. 2205 Added <tt>emulateJSON</tt> for servers that can't accept <tt>application/json</tt> 2206 encoded requests. 2207 Added <a href="#Model-clear">Model#clear</a>, which removes all attributes 2208 from a model. 2209 All Backbone classes may now be seamlessly inherited by CoffeeScript classes. 2210 </p> 2211 2212 <p> 2213 <b class="header">0.2.0</b> — <small><i>Oct 25, 2010</i></small><br /> 2214 Instead of requiring server responses to be namespaced under a <tt>model</tt> 2215 key, now you can define your own <a href="#Model-parse">parse</a> method 2216 to convert responses into attributes for Models and Collections. 2217 The old <tt>handleEvents</tt> function is now named 2218 <a href="#View-delegateEvents">delegateEvents</a>, and is automatically 2219 called as part of the View's constructor. 2220 Added a <a href="#Collection-toJSON">toJSON</a> function to Collections. 2221 Added <a href="#Collection-chain">Underscore's chain</a> to Collections. 2222 </p> 2223 2224 <p> 2225 <b class="header">0.1.2</b> — <small><i>Oct 19, 2010</i></small><br /> 2226 Added a <a href="#Model-fetch">Model#fetch</a> method for refreshing the 2227 attributes of single model from the server. 2228 An <tt>error</tt> callback may now be passed to <tt>set</tt> and <tt>save</tt> 2229 as an option, which will be invoked if validation fails, overriding the 2230 <tt>"error"</tt> event. 2231 You can now tell backbone to use the <tt>_method</tt> hack instead of HTTP 2232 methods by setting <tt>Backbone.emulateHTTP = true</tt>. 2233 Existing Model and Collection data is no longer sent up unnecessarily with 2234 <tt>GET</tt> and <tt>DELETE</tt> requests. Added a <tt>rake lint</tt> task. 2235 Backbone is now published as an <a href="http://npmjs.org">NPM</a> module. 2236 </p> 2237 2238 <p> 2239 <b class="header">0.1.1</b> — <small><i>Oct 14, 2010</i></small><br /> 2240 Added a convention for <tt>initialize</tt> functions to be called 2241 upon instance construction, if defined. Documentation tweaks. 2242 </p> 2243 2244 <p> 2245 <b class="header">0.1.0</b> — <small><i>Oct 13, 2010</i></small><br /> 2246 Initial Backbone release. 2247 </p> 2248 2249 <p> 2250 <br /> 2251 <a href="http://documentcloud.org/" title="A DocumentCloud Project" style="background:none;"> 2252 <img src="http://jashkenas.s3.amazonaws.com/images/a_documentcloud_project.png" alt="A DocumentCloud Project" style="position:relative;left:-10px;" /> 2253 </a> 2254 </p> 2255 2256 </div> 2257 2258 <script src="test/vendor/underscore-1.1.4.js"></script> 2259 <script src="test/vendor/jquery-1.5.js"></script> 2260 <script src="test/vendor/json2.js"></script> 2261 <script src="backbone.js"></script> 2262 2263 <script> 2264 // Set up the "play" buttons for each runnable code example. 2265 $(function() { 2266 $('.runnable').each(function() { 2267 var code = this; 2268 var button = $('<div class="run" title="Run"></div>'); 2269 $(button).insertBefore(code).bind('click', function(){ 2270 eval($(code).text()); 2271 }); 2272 }); 2273 }); 2274 </script> 2275 2276</body> 2277</html>