Files
backbone/index.html
Jeremy Ashkenas e2cc030799 through render
2010-10-12 15:27:54 -04:00

968 lines
34 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<title>Backbone: ...</title>
<style>
body {
font-size: 14px;
line-height: 22px;
font-family: Helvetica Neue, Helvetica, Arial;
background: #f4f4f4 url(docs/images/background.png);
}
.interface {
font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important;
}
div#sidebar {
background: #fff;
position: fixed;
top: 0; left: 0; bottom: 0;
width: 180px;
overflow-y: auto;
overflow-x: hidden;
padding: 15px 0 0 30px;
border-right: 1px solid #ddd;
box-shadow: 0 0 20px #ccc; -webkit-box-shadow: 0 0 20px #ccc; -moz-box-shadow: 0 0 20px #ccc;
}
a.toc_title, a.toc_title:visited {
display: block;
color: black;
font-weight: bold;
margin-top: 15px;
}
div.toc_title:hover {
text-decoration: underline;
}
ul.toc_section {
font-size: 11px;
line-height: 14px;
margin: 5px 0 0 0;
padding-left: 0px;
list-style-type: none;
font-family: Lucida Grande;
}
.toc_section li {
cursor: pointer;
margin: 0 0 3px 0;
}
.toc_section li a {
color: black;
}
div.container {
position: relative;
width: 550px;
margin: 40px 0 50px 240px;
}
div.run {
position: absolute;
right: 15px;
width: 26px; height: 18px;
background: url('docs/images/arrows.png') no-repeat -26px 0;
}
div.run:active {
background-position: -51px 0;
}
p, div.container ul {
margin: 20px 0;
width: 550px;
}
div.container ul {
list-style: circle;
font-size: 12px;
padding-left: 15px;
}
a, a:visited {
color: #444;
text-decoration: none;
}
a:active, a:hover {
color: #000;
text-decoration: underline;
}
h1, h2, h3, h4, h5, h6 {
padding-top: 20px;
}
h2 {
font-size: 20px;
}
b.header {
font-size: 16px;
line-height: 30px;
}
span.alias {
font-size: 14px;
font-style: italic;
margin-left: 20px;
}
table {
margin: 15px 0 0; padding: 0;
}
tr, td {
margin: 0; padding: 0;
}
td {
padding: 0px 15px 5px 0;
}
code, pre, tt {
font-family: Monaco, Consolas, "Lucida Console", monospace;
font-size: 12px;
line-height: 18px;
}
tt {
padding: 0px 3px;
background: #fff;
border: 1px solid #ddd;
}
code {
margin-left: 20px;
}
pre {
font-size: 12px;
padding: 2px 0 2px 15px;
border: 4px solid #bbb; border-top: 0; border-bottom: 0;
margin: 0px 0 30px;
}
</style>
</head>
<body>
<div id="sidebar" class="interface">
<a class="toc_title" href="#">
Backbone.js
</a>
<a class="toc_title" href="#Introduction">
Introduction
</a>
<a class="toc_title" href="#Events">
Events
</a>
<ul class="toc_section">
<li> <a href="#Events-bind">bind</a></li>
<li> <a href="#Events-unbind">unbind</a></li>
<li> <a href="#Events-trigger">trigger</a></li>
</ul>
<a class="toc_title" href="#Model">
Model
</a>
<ul class="toc_section">
<li> <a href="#Model-extend">extend</a></li>
<li> <a href="#Model-get">get</a></li>
<li> <a href="#Model-set">set</a></li>
<li> <a href="#Model-unset">unset</a></li>
<li> <a href="#Model-attributes">attributes</a></li>
<li> <a href="#Model-save">save</a></li>
<li> <a href="#Model-destroy">destroy</a></li>
<li> <a href="#Model-validate">validate</a></li>
<li> <a href="#Model-url">url</a></li>
<li> <a href="#Model-clone">clone</a></li>
<li> <a href="#Model-toString">toString</a></li>
<li> <a href="#Model-isNew">isNew</a></li>
<li> <a href="#Model-change">change</a></li>
<li> <a href="#Model-hasChanged">hasChanged</a></li>
<li> <a href="#Model-changedAttributes">changedAttributes</a></li>
<li> <a href="#Model-previous">previous</a></li>
<li> <a href="#Model-previousAttributes">previousAttributes</a></li>
</ul>
<a class="toc_title" href="#Collection">
Collection
</a>
<ul class="toc_section">
<li> <a href="#Collection-extend">extend</a></li>
<li> <a href="#Collection-Underscore-Methods">Underscore Methods (24)</a></li>
<li> <a href="#Collection-add">add</a></li>
<li> <a href="#Collection-remove">remove</a></li>
<li> <a href="#Collection-get">get</a></li>
<li> <a href="#Collection-getByCid">getByCid</a></li>
<li> <a href="#Collection-at">at</a></li>
<li> <a href="#Collection-sort">sort</a></li>
<li> <a href="#Model-url">url</a></li>
<li> <a href="#Collection-refresh">refresh</a></li>
<li> <a href="#Collection-fetch">fetch</a></li>
<li> <a href="#Collection-create">create</a></li>
<li> <a href="#Collection-toString">toString</a></li>
<li> <a href="#Collection-pluck">pluck</a></li>
</ul>
<a class="toc_title" href="#Sync">
Sync
</a>
<ul class="toc_section">
<li> <a href="#Sync">Backbone.sync</a></li>
</ul>
<a class="toc_title" href="#View">
View
</a>
<ul class="toc_section">
<li> <a href="View-el">el</a></li>
<li> <a href="View-jQuery">$ (jQuery)</a></li>
<li> <a href="View-render">render</a></li>
<li> <a href="View-make">make</a></li>
<li> <a href="View-setMode">setMode</a></li>
<li> <a href="View-setCallbacks">setCallbacks</a></li>
</ul>
</div>
<div class="container">
<p>
<img style="width: 385px; height: 126px;" src="docs/images/backbone.png" alt="Backbone.js" />
</p>
<p>
<a href="http://github.com/documentcloud/backbone/">Backbone</a> gives
structure to JavaScript applications by providing models with
key-value binding, collections with rich enumerable functions,
views with declarative callbacks, and connects to your existing webapp
over a RESTful JSON interface.
</p>
<p>
The project is <a href="http://github.com/documentcloud/backbone/">hosted on GitHub</a>,
and the <a href="docs/backbone.html">annotated source code</a> is available,
as well as an online <a href="test/test.html">test suite</a>.
</p>
<p>
<i>
Backbone is an open-source component of
<a href="http://documentcloud.org/">DocumentCloud</a>.
</i>
</p>
<h2 id="downloads">
Downloads &amp; Dependencies
<span style="padding-left: 7px; font-size:11px; font-weight: normal;" class="interface">(Right-click, and use "Save As")</span>
</h2>
<table>
<tr>
<td><a href="underscore.js">Development Version (0.1.0)</a></td>
<td><i>22kb, Uncompressed with Comments</i></td>
</tr>
<tr>
<td><a href="underscore-min.js">Production Version (0.1.0)</a></td>
<td><i>2kb, Packed and Gzipped</i></td>
</tr>
</table>
<p>
Backbone's only hard dependency is
<a href="http://documentcloud.github.com/underscore/">Underscore.js</a>.
For RESTful persistence, and DOM manipulation with
<a href="#View">Backbone.View</a>,
it's highly recommended to include <a href="http://jquery.com">jQuery</a>,
and <a href="http://www.json.org/json2.js">json2.js</a>
(which you probably already have).
</p>
<h2 id="Introduction">Introduction</h2>
<p>
The core idea behind Backbone is to avoid tying your data to the DOM. It's
too easy to create JavaScript applications that end up as tangled piles of
jQuery selectors and callbacks, all trying frantically to keep data in
sync between the UI, your JavaScript logic, and the database on your
server. For rich client-side applications, a more structured approach
is helpful.
</p>
<p>
With Backbone, you represent your data as
<a href="#Model">Models</a>, which can be created, validated, destroyed,
and saved to the server. Whenever a UI action causes an attribute of
a model to change, the model triggers a <i>change</i> event, and all
the <a href="#View">Views</a> that are displaying the model's data are
notified, causing them to re-render. You don't have to write the glue
code that looks into the DOM to find an element with a specific <i>id</i>,
and update the HTML contents
&mdash; when the model changes, the views simply update themselves.
</p>
<p>
<i>How is this different than
<a href="http://www.sproutcore.com/">SproutCore</a> or
<a href="http://cappuccino.org/">Cappuccino</a>?
</i>
</p>
<p>
This question is frequently asked, and all three projects apply general
<a href="http://en.wikipedia.org/wiki/ModelViewController">Model-View-Controller</a>
principles to JavaScript applications. However, there isn't much basis
for comparsion. SproutCore and Cappuccino provide rich UI widgets, vast
core libraries, and determine the structure of your HTML for you.
Loading the "Hello World" of SproutCore includes <i>2.5 megabytes</i> of JavaScript on the
page; the "Hello World" of Cappuccino includes <i>1.7 megabytes</i> of JS and images.
Backbone is a <i>2 kilobyte</i> include that provides the core concepts of
models, events (key-value observing), collections, views, and persistence.
</p>
<h2 id="Events">Backbone.Events</h2>
<p>
<b>Events</b> is a module that can be mixed in to any object, giving the
object the ability to bind and trigger custom named events. Events do not
have to be declared before they are bound, and may take passed arguments.
For example:
</p>
<pre class="runnable">
var obj = {};
_.extend(obj, Backbone.Events);
obj.bind("alert", function(msg) {
alert("Triggered " + msg);
});
obj.trigger("alert", "an event");
</pre>
<p id="Events-bind">
<b class="header">bind</b><code>object.bind(event, callback)</code>
<br />
Bind a <b>callback</b> function to an object. The callback will be invoked
whenever the <b>event</b> (specified by a string identifier) is fired.
If you have many events on a page, the convention is to use colons to
namespace them: <tt>"poll:start"</tt>. Callbacks bound to the special
<tt>"all"</tt> event will be triggered when any event occurs, and are passed
the name of the event as the first argument.
</p>
<p id="Events-unbind">
<b class="header">unbind</b><code>object.unbind([event], [callback])</code>
<br />
Remove a previously-bound <b>callback</b> function from an object. If no
callback is specified, all callbacks for the <b>event</b> will be
removed. If no event is specified, all bound callbacks on the object
will be removed.
</p>
<p id="Events-trigger">
<b class="header">trigger</b><code>object.trigger(event, [*args])</code>
<br />
Trigger all callbacks for the given <b>event</b>. All subsequent arguments to
<b>trigger</b> will be passed along.
</p>
<h2 id="Model">Backbone.Model</h2>
<p>
<b>Models</b> are the heart of any JavaScript application, containing
the interactive data as well as a large part of the logic surrounding it:
conversions, validations, computed properties, and access control. You
extend <tt>Backbone.Model</tt> with your domain-specific methods, and
<b>Model</b> provides a basic set of functionality for managing changes.
</p>
<p>
The following is a contrived example, but it demonstrates defining a model
with a custom method, setting an attribute, and firing an event when the
model changes. After running this code once, <tt>sidebar</tt> will be
available in your browser's console, so you can play around with it.
</p>
<pre class="runnable">
var Sidebar = Backbone.Model.extend({
promptColor: function() {
var cssColor = prompt("Please enter a CSS color:");
this.set({color: cssColor});
}
});
window.sidebar = new Sidebar;
sidebar.bind('change:color', function(model, color) {
$('#sidebar').css({background: color});
});
sidebar.set({color: 'white'});
sidebar.promptColor();
</pre>
<p id="Model-extend">
<b class="header">extend</b><code>Backbone.Model.extend(properties, [staticProperties])</code>
<br />
To create a <b>Model</b> class of your own, you extend <b>Backbone.Model</b>
and provide instance <b>properties</b>, as well as optional properties to be attached
directly to the constructor function.
</p>
<p id="Model-get">
<b class="header">get</b><code>model.get(attribute)</code>
<br />
Get the current value of an attribute from the model. For example:
<tt>note.get("title")</tt>
</p>
<p id="Model-set">
<b class="header">set</b><code>model.set(attributes, [options])</code>
<br />
Set a hash of attributes (one or many) on the model. If any of the attributes
change the models state, a <tt>"change"</tt> event will be fired, unless
<tt>silent</tt> is passed as an option.
</p>
<p>
If the model has a <tt>validate</tt> method, it will be validated before
the attributes are set, and no changes will occur if the validation fails.
</p>
<pre>
note.set({title: "October 12", content: "Lorem Ipsum Dolor Sit Amet..."});
note.set({title: "October 31"}, {silent: true});
</pre>
<p id="Model-unset">
<b class="header">unset</b><code>model.unset(attribute, [options])</code>
<br />
Remove an attribute by deleting it from the internal attributes hash.
Fires a <tt>"change"</tt> event unless <tt>silent</tt> is passed as an option.
</p>
<p id="Model-attributes">
<b class="header">attributes</b><code>model.attributes()</code>
<br />
Return a copy of the model's <b>attributes</b>. This can be used for persistence,
serialization, or for augmentation before being handed off to a view.
</p>
<pre class="runnable">
var artist = new Backbone.Model({
firstName: "Wassily",
lastName: "Kandinsky"
});
artist.set({birthday: "December 16, 1866"});
alert(JSON.stringify(artist.attributes()));
</pre>
<p id="Model-save">
<b class="header">save</b><code>model.save(attributes, [options])</code>
<br />
Save a model to your database (or alternative persistence layer),
by delegating to <tt>Backbone.sync</tt>. If the model has a <tt>validate</tt>
method, and validation fails, the model will not be saved. If the model
<tt>isNew()</tt>, the save will be an HTTP <tt>POST</tt>, if the model already
exists on the server, the save will be a <tt>PUT</tt>. Accepts
<tt>success</tt> and <tt>error</tt> callbacks in the options hash.
</p>
<pre class="runnable">
Backbone.sync = function(type, model) {
alert(type + " " + JSON.stringify(model));
};
var book = new Backbone.Model({
title: "The Rough Riders",
author: "Theodore Roosevelt"
});
book.save();
</pre>
<p id="Model-destroy">
<b class="header">destroy</b><code>model.destroy([options])</code>
<br />
Destroys the model on the server by delegating an HTTP <tt>DELETE</tt>
request to <tt>Backbone.sync</tt>. Accepts
<tt>success</tt> and <tt>error</tt> callbacks in the options hash.
</p>
<pre>
book.destroy({
success: function(model, response) {
...
}
});
</pre>
<p id="Model-validate">
<b class="header">validate</b><code>model.validate(attributes)</code>
<br />
This method is left undefined, and you're encouraged to override it with
your custom validation logic, if you have any that can be performed
in JavaScript. <b>validate</b> is called before <tt>set</tt> and
<tt>save</tt>, and is passed the attributes that are about to be updated.
If the model and attributes are valid, don't return anything from <b>validate</b>;
if the attributes are invalid, return an error of your choosing. It
can be as simple as a string error message to be displayed, or a complete
error object that describes the error programmatically. <tt>set</tt> and
<tt>save</tt> will not continue if <b>validate</b> returns an error.
Failed validations trigger an <tt>"error"</tt> event.
</p>
<pre class="runnable">
var Chapter = Backbone.Model.extend({
validate: function(attrs) {
if (attrs.end < attrs.start) {
return "can't end before it starts";
}
}
});
var one = new Chapter({
title : "Chapter One: The Beginning"
});
one.bind("error", function(model, error) {
alert(model.get("title") + " " + error);
});
one.set({
start: 15,
end: 10
});
</pre>
<p id="Model-url">
<b class="header">url</b><code>model.url()</code>
<br />
Returns the relative URL where the model's resource would be located on
the server. If your models are located somewhere else, override this method
with the correct logic. Generates URLs of the form: <tt>"/[collection]/[id]"</tt>.
</p>
<p>
A model with an id of <tt>101</tt>, stored in a
<tt>Bindable.Collection</tt> with a <tt>url</tt> of <tt>"/notes"</tt>,
would have this URL: <tt>"/notes/101"</tt>
</p>
<p id="Model-clone">
<b class="header">clone</b><code>model.clone()</code>
<br />
Create a new instance of a model with identical attributes.
</p>
<p id="Model-toString">
<b class="header">toString</b><code>model.toString()</code>
<br />
By default, just returns <tt>"Model [id]"</tt> &mdash; Override <b>toString</b>
to get convenient logging in the console for your models.
</p>
<p id="Model-isNew">
<b class="header">isNew</b><code>model.isNew()</code>
<br />
Has this model been saved to the server yet? If the model does not yet have
an <tt>id</tt>, it is considered to be new.
</p>
<p id="Model-change">
<b class="header">change</b><code>model.change()</code>
<br />
If you've been passing <tt>{silent: true}</tt> to <tt>set</tt> in order to
aggregate rapid changes to a model, you'll want to fire the <tt>"change"</tt>
event when you're finished. Call <tt>model.change()</tt> to trigger it.
</p>
<p id="Model-hasChanged">
<b class="header">hasChanged</b><code>model.hasChanged([attribute])</code>
<br />
Has the model changed since the last <tt>"change"</tt> event? If an <b>attribute</b>
is passed, returns <tt>true</tt> if that specific attribute has changed.
</p>
<pre>
book.bind("change", function() {
if (book.hasChanged("title")) {
...
}
});
</pre>
<p id="Model-changedAttributes">
<b class="header">changedAttributes</b><code>model.changedAttributes([attributes])</code>
<br />
Retrieve a hash of only the model's attributes that have changed. Optionally,
an external <b>attributes</b> hash can be passed in, returning
the attributes in that hash which differ from the model. This can be used
to figure out which portions of a view should be updated, or what calls
need to be made to sync the changes to the server.
</p>
<p id="Model-previous">
<b class="header">previous</b><code>model.previous(attribute)</code>
<br />
During a <tt>"change"</tt> event, this method can be used to get the
previous value of a changed attribute.
</p>
<pre class="runnable">
var bill = new Backbone.Model({
name: "Bill Smith"
});
bill.bind("change:name", function(model, name) {
alert("Changed name from " + bill.previous("name") + " to " + name);
});
bill.set({name : "Bill Jones"});
</pre>
<p id="Model-previousAttributes">
<b class="header">previousAttributes</b><code>model.previousAttributes()</code>
<br />
Return a copy of the model's previous attributes. Useful for getting a
diff between versions of a model, or getting back to a valid state after
an error occurs.
</p>
<h2 id="Collection">Backbone.Collection</h2>
<p>
Collections are ordered sets of models. You can bind callbacks to be notified
when any model in the collection is changed, listen for <tt>"add"</tt> and
<tt>"remove"</tt> events, <tt>fetch</tt> the collection from the server,
and use a full suite of
<a href="http://documentcloud.github.com/underscore">Underscore.js</a>
functions.
</p>
<p id="Collection-extend">
<b class="header">extend</b><code>Backbone.Collection.extend(properties, [staticProperties])</code>
<br />
To create a <b>Collection</b> class of your own, extend <b>Backbone.Collection</b>,
providing instance <b>properties</b>, as well as optional properties to be attached
directly to the collection constructor function.
</p>
<p id="Collection-Underscore-Methods">
<b class="header">Underscore Methods (24)</b>
<br />
Backbone proxies to <b>Underscore.js</b> to provide 24 iteration functions
on <b>Backbone.Collection</b>. They aren't all documented here, but
you can take a look at the Underscore documentation for the full details&hellip;
</p>
<ul>
<li><a href="http://documentcloud.github.com/underscore/#each">forEach (each)</a></li>
<li><a href="http://documentcloud.github.com/underscore/#map">map</a></li>
<li><a href="http://documentcloud.github.com/underscore/#reduce">reduce (foldl, inject)</a></li>
<li><a href="http://documentcloud.github.com/underscore/#reduceRight">reduceRight (foldr)</a></li>
<li><a href="http://documentcloud.github.com/underscore/#detect">find (detect)</a></li>
<li><a href="http://documentcloud.github.com/underscore/#select">filter (select)</a></li>
<li><a href="http://documentcloud.github.com/underscore/#reject">reject</a></li>
<li><a href="http://documentcloud.github.com/underscore/#all">every (all)</a></li>
<li><a href="http://documentcloud.github.com/underscore/#any">some (any)</a></li>
<li><a href="http://documentcloud.github.com/underscore/#include">include</a></li>
<li><a href="http://documentcloud.github.com/underscore/#invoke">invoke</a></li>
<li><a href="http://documentcloud.github.com/underscore/#max">max</a></li>
<li><a href="http://documentcloud.github.com/underscore/#min">min</a></li>
<li><a href="http://documentcloud.github.com/underscore/#sortBy">sortBy</a></li>
<li><a href="http://documentcloud.github.com/underscore/#sortedIndex">sortedIndex</a></li>
<li><a href="http://documentcloud.github.com/underscore/#toArray">toArray</a></li>
<li><a href="http://documentcloud.github.com/underscore/#size">size</a></li>
<li><a href="http://documentcloud.github.com/underscore/#first">first</a></li>
<li><a href="http://documentcloud.github.com/underscore/#rest">rest</a></li>
<li><a href="http://documentcloud.github.com/underscore/#last">last</a></li>
<li><a href="http://documentcloud.github.com/underscore/#without">without</a></li>
<li><a href="http://documentcloud.github.com/underscore/#indexOf">indexOf</a></li>
<li><a href="http://documentcloud.github.com/underscore/#lastIndexOf">lastIndexOf</a></li>
<li><a href="http://documentcloud.github.com/underscore/#isEmpty">isEmpty</a></li>
</ul>
<pre>
Books.each(function(book) {
book.publish();
});
var titles = Books.map(function(book) {
return book.get("title");
});
var publishedBooks = Books.filter(function(book) {
return book.get("published") === true;
});
var alphabetical = Books.sortBy(function(book) {
return book.author.get("name").toLowerCase();
});
</pre>
<p id="Collection-add">
<b class="header">add</b><code>collection.add(models, [options])</code>
<br />
Add a model (or an array of models) to the collection. Fires an <tt>"add"</tt>
event, which you can pass <tt>{silent: true}</tt> to suppress.
</p>
<pre class="runnable">
var ships = new Backbone.Collection();
ships.bind("add", function(ship) {
alert("Ahoy " + ship.get("name") + "!");
});
var Ship = Backbone.Model.extend({});
ships.add([
new Ship({name: "Flying Dutchman"}),
new Ship({name: "Black Pearl"})
]);
</pre>
<p id="Collection-remove">
<b class="header">remove</b><code>collection.remove(models, [options])</code>
<br />
Remove a model (or an array of models) from the collection. Fires a
<tt>"remove"</tt> event, which you can pass <tt>{silent: true}</tt>
to suppress.
</p>
<p id="Collection-get">
<b class="header">get</b><code>collection.get(id)</code>
<br />
Get a model from a collection, specified by <b>id</b>.
</p>
<p id="Collection-getByCid">
<b class="header">getByCid</b><code>collection.getByCid(cid)</code>
<br />
Get a model from a collection, specified by client id. The client id
is the <tt>.cid</tt> property of the model, automatically assigned whenever
a model is created. Useful for models which have not yet been saved to
the server, and do not yet have true ids.
</p>
<p id="Collection-at">
<b class="header">at</b><code>collection.at(index)</code>
<br />
Get a model from a collection, specified by index. Useful if your collection
is sorted, and if your collection isn't sorted, <b>at</b> will still
retrieve models in insertion order.
</p>
<p id="Collection-sort">
<b class="header">sort</b><code>collection.sort([options])</code>
<br />
Force a collection to re-sort itself. You don't need to call this under
normal circumstances, as a collection with a <tt>comparator</tt> function
will maintain itself in proper sort order at all times. Triggers the
collection's <tt>"refresh"</tt> event, unless silenced by passing
<tt>{silent: true}</tt>
</p>
<p id="Collection-url">
<b class="header">url</b><code>collection.url or collection.url()</code>
<br />
Set the <b>url</b> property (or function) on a collection to reference
its location on the server. Models within the collection will use <b>url</b>
to construct URLs of their own.
</p>
<pre>
var Notes = Backbone.Collection.extend({
url: '/notes'
});
// Or, something more sophisticated:
var Notes = Backbone.Collection.extend({
url: function() {
return this.document.url() + '/notes';
}
});
</pre>
<p id="Collection-refresh">
<b class="header">refresh</b><code>collection.refresh(models, [options])</code>
<br />
Adding and removing models one at a time is all well and good, but sometimes
you have so many models to change that you'd rather just update the collection
in bulk. Use <b>refresh</b> to replace a collection with a new list
of models (or attribute hashes), triggering a single <tt>"refresh"</tt> event
at the end. Pass <tt>{silent: true}</tt> to suppress the <tt>"refresh"</tt> event.
</p>
<p id="Collection-fetch">
<b class="header">fetch</b><code>collection.fetch([options])</code>
<br />
Fetch the default set of models for this collection from the server,
refreshing the collection when they arrive. The <b>options</b> hash takes
<tt>success(collection, response)</tt> and <tt>error(collection, response)</tt>
callbacks. Delegates to <tt>Backbone.sync</tt>
under the covers, for custom persistence strategies.
</p>
<p>
The server handler for <b>fetch</b> requests should return a JSON list of
models, namespaced under "models": <tt>{"models": [...]}</tt> &mdash; and
additional information can be returned under different keys.
</p>
<p>
Note that <b>fetch</b> should not be used to populate collections on
page load &mdash; all models needed at load time should already be
bootstrapped in to place. <b>fetch</b> is intended for lazily-loading models
for interfaces that are not needed immediately: for example, documents
with collections of notes that may be toggled open and closed.
</p>
<p id="Collection-create">
<b class="header">create</b><code>collection.create(attributes, [options])</code>
<br />
Convenience to create a new instance of a model within a collection.
Equivalent to instantiating a model with a hash of attributes,
saving the model to the server, and adding the model to the set after being
successfully created. Returns
the model, or <tt>false</tt> if a validation error prevented the
model from being created. In order for this to work, your collection
must have a <tt>model</tt> property, referencing the type of model that
the collection contains.
</p>
<p id="Collection-toString">
<b class="header">toString</b><code>collection.toString()</code>
<br />
By default, just returns <tt>"Collection ([size] models)"</tt> &mdash;
Override <b>toString</b> to get convenient logging in the console for the collection.
</p>
<p id="Collection-pluck">
<b class="header">pluck</b><code>collection.pluck(attribute)</code>
<br />
Pluck an attribute from each model in the collection. Equivalent to calling
<tt>map</tt>, and returning a single attribute from the iterator.
</p>
<pre class="runnable">
var stooges = new Backbone.Collection([
new Backbone.Model({name: "Curly"}),
new Backbone.Model({name: "Larry"}),
new Backbone.Model({name: "Moe"})
]);
var names = stooges.pluck("name");
alert(JSON.stringify(names));
</pre>
<h2 id="Sync">Backbone.sync</h2>
<p>
<b>Backbone.sync</b> is the function the Backbone calls every time it
attempts to read or save a model to the server. By default, it uses
<tt>jQuery.ajax</tt> to make a RESTful JSON request. You can override
it in order to use a different persistence strategy, such as WebSockets,
XML transport, or Local Storage.
</p>
<p>
The method signature of <b>Backbone.sync</b> is <tt>sync(method, model, success, error)</tt>
</p>
<ul>
<li><b>method</b> the CRUD method (<tt>"create"</tt>, <tt>"read"</tt>, <tt>"update"</tt>, or <tt>"delete"</tt>)</li>
<li><b>model</b> the model to be saved (or collection to be read)</li>
<li><b>success({model: ...})</b> a callback that should be fired if the request works</li>
<li><b>error({model: ...})</b> a callback that should be fired if the request fails</li>
</ul>
<h2 id="View">Backbone.View</h2>
<p>
Backbone views are almost more convention than they are code.
The general idea is to organize your interface into logical sections,
backed by models, each of which can be updated independently when the
model changes. Instead of digging into a JSON object and looking up an
element in the DOM, and updating the HTML by hand, it should look more like:
<tt>model.bind('change', view.render)</tt> &mdash; and now everywhere that
model data is displayed in the UI, it is always immediately up to date.
</p>
<p id="View-el">
<b class="header">el</b><code>view.el</code>
<br />
All views have a DOM element at all times (the <b>el</b> property),
whether they've already been inserted into the page or not. In this
fashion, views can be rendered at any time, and inserted into the DOM all
at once, in order to get high-performance UI rendering with as few
reflows and repaints as possible.
</p>
<p id="View-jQuery">
<b class="header">$ (jQuery)</b><code>view.$(selector)</code>
<br />
If jQuery is included on the page, each view has a <b>$</b> or <b>jQuery</b>
function that runs queries scoped within the view's element. If you use this
scoped jQuery function, you don't have to use model ids as part of your query
to pull out specific elements in a list, and can rely much more on HTML class
attributes. It's equivalent to running: <tt>$(selector, this.el)</tt>
</p>
<pre>
ui.Chapter = Backbone.View.extend({
serialize : function() {
return {
title: this.$(".title").text(),
start: this.$(".start-page").text(),
end: this.$(".end-page").text()
};
}s
});
</pre>
<p id="View-render">
<b class="header">render</b><code>view.render()</code>
<br />
The default implementation of <b>render</b> is a no-op. Override this
function with your code that renders the view template from model data,
and updates <tt>this.el</tt> with the new HTML. You can use any flavor of
JavaScript templating or DOM-building you prefer. Because <b>Underscore.js</b>
is already on the page, <tt>_.template</tt> is available. The convention is to
<tt>return this</tt> at the end of <b>render</b> to enable chaining.
</p>
<pre>
ui.Chapter = Backbone.View.extend({
render : function() {
var data = this.model.attributes();
$(this.el).html(this.template.render(data));
return this;
}
});
</pre>
<h2 id="changes">Change Log</h2>
<p>
<b class="header">0.1.0</b><br />
Initial Backbone release.
</p>
<p>
<br />
<a href="http://documentcloud.org/" title="A DocumentCloud Project" style="background:none;">
<img src="http://jashkenas.s3.amazonaws.com/images/a_documentcloud_project.png" alt="A DocumentCloud Project" style="position:relative;left:-10px;" />
</a>
</p>
</div>
<script src="test/vendor/underscore-1.1.0.js"></script>
<script src="test/vendor/jquery-1.4.2.js"></script>
<script src="test/vendor/json2.js"></script>
<script src="backbone.js"></script>
<script>
$(function() {
$('.runnable').each(function() {
var code = this;
var button = $('<div class="run" title="Run"></div>');
$(button).insertBefore(code).bind('click', function(){
eval($(code).text());
});
});
});
</script>
</body>
</html>