Merge branch 'master' of github.com:documentcloud/backbone

This commit is contained in:
Jeff Larson
2010-10-13 10:52:28 -04:00
5 changed files with 384 additions and 181 deletions

44
README
View File

@@ -1,10 +1,3 @@
____ _ _ _
| __ ) __ _ ___| | _| |__ ___ _ __ ___ (_)___
| _ \ / _` |/ __| |/ / '_ \ / _ \| '_ \ / _ \ | / __|
| |_) | (_| | (__| <| |_) | (_) | | | | __/_ | \__ \
|____/ \__,_|\___|_|\_\_.__/ \___/|_| |_|\___(_)/ |___/
|__/
____ _ _ _
| _ \ | | | | (_)
| |_) | __ _ ___| | __| |__ ___ _ __ ___ _ ___
@@ -12,32 +5,21 @@
| |_) | (_| | (__| < | |_) | (_) | | | | __/_| \__ \
|____/ \__,_|\___|_|\_\|_.__/ \___/|_| |_|\___(_) |___/
_/ |
|__/
|__/
(_'___________________________________________________'_)
(_.———————————————————————————————————————————————————._)
___ _ _ _
/ __\ __ _ ___| | __| |__ ___ _ __ ___ (_)___
/__\/// _` |/ __| |/ /| '_ \ / _ \| '_ \ / _ \ | / __|
/ \/ \ (_| | (__| < | |_) | (_) | | | | __/_ | \__ \
\_____/\__,_|\___|_|\_\|_.__/ \___/|_| |_|\___(_)_/ |___/
|__/
______ _ _ _
(____ \ | | | | (_)
____) )_____ ____| | _| |__ ___ ____ _____ _ ___
| __ ((____ |/ ___) |_/ ) _ \ / _ \| _ \| ___ | | |/___)
| |__) ) ___ ( (___| _ (| |_) ) |_| | | | | ____|_ | |___ |
|______/\_____|\____)_| \_)____/ \___/|_| |_|_____|_)_| (___/
(__/
,-----. ,--. ,--. ,--.
| |) /_ ,--,--. ,---.| |,-.| |-. ,---. ,--,--, ,---. `--' ,---.
| .-. \' ,-. || .--'| /| .-. '| .-. || \| .-. : ,--.( .-'
| '--' /\ '-' |\ `--.| \ \| `-' |' '-' '| || |\ --..--. | |.-' `)
`------' `--`--' `---'`--'`--'`---' `---' `--''--' `----''--'.-' /`----'
'---'
Backbone is a ....
Backbone supplies structure to JavaScript-heavy applications by providing models key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing application over a RESTful JSON interface.
For Docs, License, Tests, and pre-packed downloads, see:
http://documentcloud.github.com/backbone/
To suggest a feature, report a bug, or general discussion:
http://github.com/documentcloud/backbone/issues/
All contributors are listed here:
http://github.com/documentcloud/backbone/contributors
Special thanks to Robert Kieffer for the original philosophy behind Backbone.
http://github.com/broofa

View File

@@ -11,15 +11,19 @@
// The top-level namespace.
var Backbone = {};
// Keep the version in sync with `package.json`.
// Keep the version here in sync with `package.json`.
Backbone.VERSION = '0.1.0';
// Export for both CommonJS and the Browser.
// Export for both CommonJS and the browser.
(typeof exports !== 'undefined' ? exports : this).Backbone = Backbone;
// Require Underscore, if we're on the server, and it's not already present.
var _ = this._;
if (!_ && (typeof require !== 'undefined')) _ = require("underscore")._;
// Helper function to correctly set up the prototype chain, for subclasses.
// Similar to `goog.inherits`, but uses a hash of prototype properties and
// static properties to be extended.
// class properties to be extended.
var inherits = function(parent, protoProps, classProps) {
var child = protoProps.hasOwnProperty('constructor') ? protoProps.constructor :
function(){ return parent.apply(this, arguments); };
@@ -32,7 +36,8 @@
return child;
};
// Get a url as a property or as a function.
// Helper function to get a URL from a Model or Collection as a property
// or as a function.
var getUrl = function(object) {
return _.isFunction(object.url) ? object.url() : object.url;
};
@@ -109,18 +114,13 @@
// Backbone.Model
// --------------
// Create a new model, with defined attributes.
// If you do not specify the id, a negative id will be assigned for you.
// Create a new model, with defined attributes. A client id (`cid`)
// is automatically generated and assigned for you.
Backbone.Model = function(attributes) {
this._attributes = {};
this.attributes = {};
this.cid = _.uniqueId('c');
this.set(attributes || {}, {silent : true});
this._previousAttributes = this.attributes();
};
// `attributes` is aliased as `toJSON`, for use with `JSON.stringify`.
var toJSON = function() {
return _.clone(this._attributes);
this._previousAttributes = _.clone(this.attributes);
};
// Attach all inheritable methods to the Model prototype.
@@ -134,12 +134,13 @@
_changed : false,
// Return a copy of the model's `attributes` object.
toJSON : toJSON,
attributes : toJSON,
toJSON : function() {
return _.clone(this.attributes);
},
// Get the value of an attribute.
get : function(attr) {
return this._attributes[attr];
return this.attributes[attr];
},
// Set a hash of model attributes on the object, firing `changed` unless you
@@ -149,8 +150,8 @@
// Extract attributes and options.
options || (options = {});
if (!attrs) return this;
attrs = attrs._attributes || attrs;
var now = this._attributes;
attrs = attrs.attributes || attrs;
var now = this.attributes;
// Run validation if `validate` is defined.
if (this.validate) {
@@ -186,8 +187,8 @@
// silence it.
unset : function(attr, options) {
options || (options = {});
var value = this._attributes[attr];
delete this._attributes[attr];
var value = this.attributes[attr];
delete this.attributes[attr];
if (!options.silent) {
this._changed = true;
this.trigger('change:' + attr, this);
@@ -197,6 +198,8 @@
},
// Set a hash of model attributes, and sync the model to the server.
// If the server returns an attributes hash that differs, the model's
// state will be `set` again.
save : function(attrs, options) {
attrs || (attrs = {});
options || (options = {});
@@ -211,7 +214,8 @@
return this;
},
// Destroy this model on the server.
// Destroy this model on the server. Upon success, the model is removed
// from its collection, if it has one.
destroy : function(options) {
options || (options = {});
var model = this;
@@ -234,7 +238,7 @@
// Create a new model with identical attributes to this one.
clone : function() {
return new (this.constructor)(this.attributes());
return new this.constructor(this);
},
// A model is new if it has never been saved to the server, and has a negative
@@ -247,14 +251,14 @@
// Calling this will cause all objects observing the model to update.
change : function() {
this.trigger('change', this);
this._previousAttributes = this.attributes();
this._previousAttributes = _.clone(this.attributes);
this._changed = false;
},
// Determine if the model has changed since the last `changed` event.
// If you specify an attribute name, determine if that attribute has changed.
hasChanged : function(attr) {
if (attr) return this._previousAttributes[attr] != this._attributes[attr];
if (attr) return this._previousAttributes[attr] != this.attributes[attr];
return this._changed;
},
@@ -263,7 +267,7 @@
// view need to be updated and/or what attributes need to be persisted to
// the server.
changedAttributes : function(now) {
var old = this._previousAttributes, now = now || this.attributes(), changed = false;
var old = this._previousAttributes, now = now || this.attributes, changed = false;
for (var attr in now) {
if (!_.isEqual(old[attr], now[attr])) {
changed = changed || {};
@@ -364,7 +368,7 @@
// When you have more items than you want to add or remove individually,
// you can refresh the entire set with a new list of models, without firing
// any `added` or `removed` events. Fires `refreshed` when finished.
// any `added` or `removed` events. Fires `refresh` when finished.
refresh : function(models, options) {
options || (options = {});
models = models || [];
@@ -381,7 +385,7 @@
},
// Fetch the default set of models for this collection, refreshing the
// collection.
// collection when they arrive.
fetch : function(options) {
options || (options = {});
var collection = this;
@@ -393,7 +397,8 @@
return this;
},
// Create a new instance of a model in this collection.
// Create a new instance of a model in this collection. After the model
// has been created on the server, it will be added to the collection.
create : function(model, options) {
options || (options = {});
if (!(model instanceof Backbone.Model)) model = new this.model(model);
@@ -420,7 +425,8 @@
this._byCid = {};
},
// Internal implementation of adding a single model to the set.
// Internal implementation of adding a single model to the set, updating
// hash indexes for `id` and `cid` lookups.
_add : function(model, options) {
options || (options = {});
var already = this.get(model);
@@ -436,7 +442,8 @@
return model;
},
// Internal implementation of removing a single model from the set.
// Internal implementation of removing a single model from the set, updating
// hash indexes for `id` and `cid` lookups.
_remove : function(model, options) {
options || (options = {});
model = this.get(model);
@@ -508,12 +515,12 @@
};
// Cached regex to split keys for `handleEvents`.
var eventSplitter = /^(\w+)\s+(.*)$/;
var eventSplitter = /^(\w+)\s*(.*)$/;
// Set up all inheritable **Backbone.View** properties and methods.
_.extend(Backbone.View.prototype, {
// The default tagName of a View's element is "div".
// The default `tagName` of a View's element is `"div"`.
tagName : 'div',
// Attach the jQuery function as the `$` and `jQuery` properties.
@@ -550,8 +557,8 @@
//
// pairs. Callbacks will be bound to the view, with `this` set properly.
// Uses jQuery event delegation for efficiency.
// Passing a selector of `el` binds to the view's root element.
// Change events are not delegated through the view because IE does not
// Omitting the selector binds the event to `this.el`.
// `"change"` events are not delegated through the view because IE does not
// bubble change events at all.
handleEvents : function(events) {
$(this.el).unbind();

View File

@@ -2,9 +2,10 @@
Backbone may be freely distributed under the MIT license.
For all details and documentation:
http://documentcloud.github.com/backbone
</code></pre> </td> <td class="code"> <div class="highlight"><pre><span class="p">(</span><span class="kd">function</span><span class="p">(){</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <h2>Initial Setup</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>The top-level namespace.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">Backbone</span> <span class="o">=</span> <span class="p">{};</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>Keep the version in sync with <code>package.json</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">VERSION</span> <span class="o">=</span> <span class="s1">&#39;0.1.0&#39;</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Export for both CommonJS and the Browser.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="p">(</span><span class="k">typeof</span> <span class="nx">exports</span> <span class="o">!==</span> <span class="s1">&#39;undefined&#39;</span> <span class="o">?</span> <span class="nx">exports</span> <span class="o">:</span> <span class="k">this</span><span class="p">).</span><span class="nx">Backbone</span> <span class="o">=</span> <span class="nx">Backbone</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>Helper function to correctly set up the prototype chain, for subclasses.
</code></pre> </td> <td class="code"> <div class="highlight"><pre><span class="p">(</span><span class="kd">function</span><span class="p">(){</span></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">&#182;</a> </div> <h2>Initial Setup</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">&#182;</a> </div> <p>The top-level namespace.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">Backbone</span> <span class="o">=</span> <span class="p">{};</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">&#182;</a> </div> <p>Keep the version here in sync with <code>package.json</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">VERSION</span> <span class="o">=</span> <span class="s1">&#39;0.1.0&#39;</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">&#182;</a> </div> <p>Export for both CommonJS and the browser.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="p">(</span><span class="k">typeof</span> <span class="nx">exports</span> <span class="o">!==</span> <span class="s1">&#39;undefined&#39;</span> <span class="o">?</span> <span class="nx">exports</span> <span class="o">:</span> <span class="k">this</span><span class="p">).</span><span class="nx">Backbone</span> <span class="o">=</span> <span class="nx">Backbone</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">&#182;</a> </div> <p>Require Underscore, if we're on the server, and it's not already present.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">_</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">_</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">_</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">require</span> <span class="o">!==</span> <span class="s1">&#39;undefined&#39;</span><span class="p">))</span> <span class="nx">_</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s2">&quot;underscore&quot;</span><span class="p">).</span><span class="nx">_</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>Helper function to correctly set up the prototype chain, for subclasses.
Similar to <code>goog.inherits</code>, but uses a hash of prototype properties and
static properties to be extended.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">inherits</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">parent</span><span class="p">,</span> <span class="nx">protoProps</span><span class="p">,</span> <span class="nx">classProps</span><span class="p">)</span> <span class="p">{</span>
class properties to be extended.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">inherits</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">parent</span><span class="p">,</span> <span class="nx">protoProps</span><span class="p">,</span> <span class="nx">classProps</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">child</span> <span class="o">=</span> <span class="nx">protoProps</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">(</span><span class="s1">&#39;constructor&#39;</span><span class="p">)</span> <span class="o">?</span> <span class="nx">protoProps</span><span class="p">.</span><span class="nx">constructor</span> <span class="o">:</span>
<span class="kd">function</span><span class="p">(){</span> <span class="k">return</span> <span class="nx">parent</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">arguments</span><span class="p">);</span> <span class="p">};</span>
<span class="kd">var</span> <span class="nx">ctor</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){};</span>
@@ -14,9 +15,10 @@ static properties to be extended.</p> </td> <td class="c
<span class="k">if</span> <span class="p">(</span><span class="nx">classProps</span><span class="p">)</span> <span class="nx">_</span><span class="p">.</span><span class="nx">extend</span><span class="p">(</span><span class="nx">child</span><span class="p">,</span> <span class="nx">classProps</span><span class="p">);</span>
<span class="nx">child</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">constructor</span> <span class="o">=</span> <span class="nx">child</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">child</span><span class="p">;</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">&#182;</a> </div> <p>Get a url as a property or as a function.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">getUrl</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">object</span><span class="p">)</span> <span class="p">{</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <p>Helper function to get a URL from a Model or Collection as a property
or as a function.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">getUrl</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">object</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">_</span><span class="p">.</span><span class="nx">isFunction</span><span class="p">(</span><span class="nx">object</span><span class="p">.</span><span class="nx">url</span><span class="p">)</span> <span class="o">?</span> <span class="nx">object</span><span class="p">.</span><span class="nx">url</span><span class="p">()</span> <span class="o">:</span> <span class="nx">object</span><span class="p">.</span><span class="nx">url</span><span class="p">;</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">&#182;</a> </div> <h2>Backbone.Events</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <p>A module that can be mixed in to <em>any object</em> in order to provide it with
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">&#182;</a> </div> <h2>Backbone.Events</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>A module that can be mixed in to <em>any object</em> in order to provide it with
custom events. You may <code>bind</code> or <code>unbind</code> a callback function to an event;
<code>trigger</code>-ing an event fires all callbacks in succession.</p>
@@ -24,13 +26,13 @@ custom events. You may <code>bind</code> or <code>unbind</code> a callback funct
_.extend(object, Backbone.Events);
object.bind('expand', function(){ alert('expanded'); });
object.trigger('expand');
</code></pre> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">Events</span> <span class="o">=</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>Bind an event, specified by a string name, <code>ev</code>, to a <code>callback</code> function.
</code></pre> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">Events</span> <span class="o">=</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>Bind an event, specified by a string name, <code>ev</code>, to a <code>callback</code> function.
Passing <code>"all"</code> will bind the callback to all events fired.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">bind</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">ev</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">calls</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">_callbacks</span> <span class="o">||</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">_callbacks</span> <span class="o">=</span> <span class="p">{});</span>
<span class="kd">var</span> <span class="nx">list</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">_callbacks</span><span class="p">[</span><span class="nx">ev</span><span class="p">]</span> <span class="o">||</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">_callbacks</span><span class="p">[</span><span class="nx">ev</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]);</span>
<span class="nx">list</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">callback</span><span class="p">);</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</a> </div> <p>Remove one or many callbacks. If <code>callback</code> is null, removes all
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>Remove one or many callbacks. If <code>callback</code> is null, removes all
callbacks for the event. If <code>ev</code> is null, removes all bound callbacks
for all events.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">unbind</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">ev</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">calls</span><span class="p">;</span>
@@ -51,7 +53,7 @@ for all events.</p> </td> <td class="code">
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">&#182;</a> </div> <p>Trigger an event, firing all bound callbacks. Callbacks are passed the
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</a> </div> <p>Trigger an event, firing all bound callbacks. Callbacks are passed the
same arguments as <code>trigger</code> is, apart from the event name.
Listening for <code>"all"</code> passes the true event name as the first argument.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">trigger</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">ev</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">list</span><span class="p">,</span> <span class="nx">calls</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">l</span><span class="p">;</span>
@@ -70,23 +72,22 @@ Listening for <code>"all"</code> passes the true event name as the first argumen
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">&#182;</a> </div> <h2>Backbone.Model</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <p>Create a new model, with defined attributes.
If you do not specify the id, a negative id will be assigned for you.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">Model</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">attributes</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_attributes</span> <span class="o">=</span> <span class="p">{};</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">&#182;</a> </div> <h2>Backbone.Model</h2> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>Create a new model, with defined attributes. A client id (<code>cid</code>)
is automatically generated and assigned for you.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">Model</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">attributes</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">attributes</span> <span class="o">=</span> <span class="p">{};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">cid</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">uniqueId</span><span class="p">(</span><span class="s1">&#39;c&#39;</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">attributes</span> <span class="o">||</span> <span class="p">{},</span> <span class="p">{</span><span class="nx">silent</span> <span class="o">:</span> <span class="kc">true</span><span class="p">});</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_previousAttributes</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">attributes</span><span class="p">();</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p><code>attributes</code> is aliased as <code>toJSON</code>, for use with <code>JSON.stringify</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">toJSON</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">_</span><span class="p">.</span><span class="nx">clone</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">_attributes</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_previousAttributes</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">clone</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">attributes</span><span class="p">);</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">&#182;</a> </div> <p>Attach all inheritable methods to the Model prototype.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_</span><span class="p">.</span><span class="nx">extend</span><span class="p">(</span><span class="nx">Backbone</span><span class="p">.</span><span class="nx">Model</span><span class="p">.</span><span class="nx">prototype</span><span class="p">,</span> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">Events</span><span class="p">,</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">&#182;</a> </div> <p>A snapshot of the model's previous attributes, taken immediately
after the last <code>changed</code> event was fired.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_previousAttributes</span> <span class="o">:</span> <span class="kc">null</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>Has the item been changed since the last <code>changed</code> event?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_changed</span> <span class="o">:</span> <span class="kc">false</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">&#182;</a> </div> <p>Return a copy of the model's <code>attributes</code> object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">toJSON</span> <span class="o">:</span> <span class="nx">toJSON</span><span class="p">,</span>
<span class="nx">attributes</span> <span class="o">:</span> <span class="nx">toJSON</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">&#182;</a> </div> <p>Get the value of an attribute.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">get</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">attr</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">_attributes</span><span class="p">[</span><span class="nx">attr</span><span class="p">];</span>
after the last <code>changed</code> event was fired.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_previousAttributes</span> <span class="o">:</span> <span class="kc">null</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">&#182;</a> </div> <p>Has the item been changed since the last <code>changed</code> event?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_changed</span> <span class="o">:</span> <span class="kc">false</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">&#182;</a> </div> <p>Return a copy of the model's <code>attributes</code> object.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">toJSON</span> <span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">_</span><span class="p">.</span><span class="nx">clone</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">attributes</span><span class="p">);</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">&#182;</a> </div> <p>Get the value of an attribute.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">get</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">attr</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">attributes</span><span class="p">[</span><span class="nx">attr</span><span class="p">];</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">&#182;</a> </div> <p>Set a hash of model attributes on the object, firing <code>changed</code> unless you
choose to silence it.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">set</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">attrs</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">&#182;</a> </div> <p>Extract attributes and options.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">options</span> <span class="o">||</span> <span class="p">(</span><span class="nx">options</span> <span class="o">=</span> <span class="p">{});</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">attrs</span><span class="p">)</span> <span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="nx">attrs</span> <span class="o">=</span> <span class="nx">attrs</span><span class="p">.</span><span class="nx">_attributes</span> <span class="o">||</span> <span class="nx">attrs</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">now</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">_attributes</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">&#182;</a> </div> <p>Run validation if <code>validate</code> is defined.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">validate</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">attrs</span> <span class="o">=</span> <span class="nx">attrs</span><span class="p">.</span><span class="nx">attributes</span> <span class="o">||</span> <span class="nx">attrs</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">now</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">attributes</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">&#182;</a> </div> <p>Run validation if <code>validate</code> is defined.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">validate</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">error</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">validate</span><span class="p">(</span><span class="nx">attrs</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">trigger</span><span class="p">(</span><span class="s1">&#39;error&#39;</span><span class="p">,</span> <span class="k">this</span><span class="p">,</span> <span class="nx">error</span><span class="p">);</span>
@@ -107,15 +108,17 @@ choose to silence it.</p> </td> <td class="code">
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">&#182;</a> </div> <p>Remove an attribute from the model, firing <code>changed</code> unless you choose to
silence it.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">unset</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">attr</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">options</span> <span class="o">||</span> <span class="p">(</span><span class="nx">options</span> <span class="o">=</span> <span class="p">{});</span>
<span class="kd">var</span> <span class="nx">value</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">_attributes</span><span class="p">[</span><span class="nx">attr</span><span class="p">];</span>
<span class="k">delete</span> <span class="k">this</span><span class="p">.</span><span class="nx">_attributes</span><span class="p">[</span><span class="nx">attr</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">value</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">attributes</span><span class="p">[</span><span class="nx">attr</span><span class="p">];</span>
<span class="k">delete</span> <span class="k">this</span><span class="p">.</span><span class="nx">attributes</span><span class="p">[</span><span class="nx">attr</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">options</span><span class="p">.</span><span class="nx">silent</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_changed</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">trigger</span><span class="p">(</span><span class="s1">&#39;change:&#39;</span> <span class="o">+</span> <span class="nx">attr</span><span class="p">,</span> <span class="k">this</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">change</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">value</span><span class="p">;</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">&#182;</a> </div> <p>Set a hash of model attributes, and sync the model to the server.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">save</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">attrs</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">&#182;</a> </div> <p>Set a hash of model attributes, and sync the model to the server.
If the server returns an attributes hash that differs, the model's
state will be <code>set</code> again.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">save</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">attrs</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">attrs</span> <span class="o">||</span> <span class="p">(</span><span class="nx">attrs</span> <span class="o">=</span> <span class="p">{});</span>
<span class="nx">options</span> <span class="o">||</span> <span class="p">(</span><span class="nx">options</span> <span class="o">=</span> <span class="p">{});</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">attrs</span><span class="p">,</span> <span class="nx">options</span><span class="p">))</span> <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
@@ -127,7 +130,8 @@ silence it.</p> </td> <td class="code"> <d
<span class="kd">var</span> <span class="nx">method</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">isNew</span><span class="p">()</span> <span class="o">?</span> <span class="s1">&#39;create&#39;</span> <span class="o">:</span> <span class="s1">&#39;update&#39;</span><span class="p">;</span>
<span class="nx">Backbone</span><span class="p">.</span><span class="nx">sync</span><span class="p">(</span><span class="nx">method</span><span class="p">,</span> <span class="k">this</span><span class="p">,</span> <span class="nx">success</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">error</span><span class="p">);</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">&#182;</a> </div> <p>Destroy this model on the server.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">destroy</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">&#182;</a> </div> <p>Destroy this model on the server. Upon success, the model is removed
from its collection, if it has one.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">destroy</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">options</span> <span class="o">||</span> <span class="p">(</span><span class="nx">options</span> <span class="o">=</span> <span class="p">{});</span>
<span class="kd">var</span> <span class="nx">model</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">success</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">resp</span><span class="p">)</span> <span class="p">{</span>
@@ -143,24 +147,24 @@ that will be called.</p> </td> <td class="code">
<span class="k">if</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">isNew</span><span class="p">())</span> <span class="k">return</span> <span class="nx">base</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">base</span> <span class="o">+</span> <span class="s1">&#39;/&#39;</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">id</span><span class="p">;</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">&#182;</a> </div> <p>Create a new model with identical attributes to this one.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">clone</span> <span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">new</span> <span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">constructor</span><span class="p">)(</span><span class="k">this</span><span class="p">.</span><span class="nx">attributes</span><span class="p">());</span>
<span class="k">return</span> <span class="k">new</span> <span class="k">this</span><span class="p">.</span><span class="nx">constructor</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-32"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-32">&#182;</a> </div> <p>A model is new if it has never been saved to the server, and has a negative
ID.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">isNew</span> <span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">id</span><span class="p">;</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-33"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-33">&#182;</a> </div> <p>Call this method to fire manually fire a <code>change</code> event for this model.
Calling this will cause all objects observing the model to update.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">change</span> <span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">trigger</span><span class="p">(</span><span class="s1">&#39;change&#39;</span><span class="p">,</span> <span class="k">this</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_previousAttributes</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">attributes</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_previousAttributes</span> <span class="o">=</span> <span class="nx">_</span><span class="p">.</span><span class="nx">clone</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">attributes</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_changed</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-34"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-34">&#182;</a> </div> <p>Determine if the model has changed since the last <code>changed</code> event.
If you specify an attribute name, determine if that attribute has changed.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">hasChanged</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">attr</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">attr</span><span class="p">)</span> <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">_previousAttributes</span><span class="p">[</span><span class="nx">attr</span><span class="p">]</span> <span class="o">!=</span> <span class="k">this</span><span class="p">.</span><span class="nx">_attributes</span><span class="p">[</span><span class="nx">attr</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">attr</span><span class="p">)</span> <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">_previousAttributes</span><span class="p">[</span><span class="nx">attr</span><span class="p">]</span> <span class="o">!=</span> <span class="k">this</span><span class="p">.</span><span class="nx">attributes</span><span class="p">[</span><span class="nx">attr</span><span class="p">];</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">_changed</span><span class="p">;</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-35"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-35">&#182;</a> </div> <p>Return an object containing all the attributes that have changed, or false
if there are no changed attributes. Useful for determining what parts of a
view need to be updated and/or what attributes need to be persisted to
the server.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">changedAttributes</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">now</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">old</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">_previousAttributes</span><span class="p">,</span> <span class="nx">now</span> <span class="o">=</span> <span class="nx">now</span> <span class="o">||</span> <span class="k">this</span><span class="p">.</span><span class="nx">attributes</span><span class="p">(),</span> <span class="nx">changed</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">old</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">_previousAttributes</span><span class="p">,</span> <span class="nx">now</span> <span class="o">=</span> <span class="nx">now</span> <span class="o">||</span> <span class="k">this</span><span class="p">.</span><span class="nx">attributes</span><span class="p">,</span> <span class="nx">changed</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">attr</span> <span class="k">in</span> <span class="nx">now</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">_</span><span class="p">.</span><span class="nx">isEqual</span><span class="p">(</span><span class="nx">old</span><span class="p">[</span><span class="nx">attr</span><span class="p">],</span> <span class="nx">now</span><span class="p">[</span><span class="nx">attr</span><span class="p">]))</span> <span class="p">{</span>
<span class="nx">changed</span> <span class="o">=</span> <span class="nx">changed</span> <span class="o">||</span> <span class="p">{};</span>
@@ -220,7 +224,7 @@ circumstances, as the set will maintain sort order as each item is added.</p>
<span class="k">return</span> <span class="nx">_</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">models</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">model</span><span class="p">){</span> <span class="k">return</span> <span class="nx">model</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">attr</span><span class="p">);</span> <span class="p">});</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-49"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-49">&#182;</a> </div> <p>When you have more items than you want to add or remove individually,
you can refresh the entire set with a new list of models, without firing
any <code>added</code> or <code>removed</code> events. Fires <code>refreshed</code> when finished.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">refresh</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">models</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
any <code>added</code> or <code>removed</code> events. Fires <code>refresh</code> when finished.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">refresh</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">models</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">options</span> <span class="o">||</span> <span class="p">(</span><span class="nx">options</span> <span class="o">=</span> <span class="p">{});</span>
<span class="nx">models</span> <span class="o">=</span> <span class="nx">models</span> <span class="o">||</span> <span class="p">[];</span>
<span class="kd">var</span> <span class="nx">collection</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
@@ -234,7 +238,7 @@ any <code>added</code> or <code>removed</code> events. Fires <code>refreshed</co
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">options</span><span class="p">.</span><span class="nx">silent</span><span class="p">)</span> <span class="k">this</span><span class="p">.</span><span class="nx">trigger</span><span class="p">(</span><span class="s1">&#39;refresh&#39;</span><span class="p">,</span> <span class="k">this</span><span class="p">);</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-50"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-50">&#182;</a> </div> <p>Fetch the default set of models for this collection, refreshing the
collection.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">fetch</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
collection when they arrive.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">fetch</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">options</span> <span class="o">||</span> <span class="p">(</span><span class="nx">options</span> <span class="o">=</span> <span class="p">{});</span>
<span class="kd">var</span> <span class="nx">collection</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">success</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">resp</span><span class="p">)</span> <span class="p">{</span>
@@ -243,7 +247,8 @@ collection.</p> </td> <td class="code"> <d
<span class="p">};</span>
<span class="nx">Backbone</span><span class="p">.</span><span class="nx">sync</span><span class="p">(</span><span class="s1">&#39;read&#39;</span><span class="p">,</span> <span class="k">this</span><span class="p">,</span> <span class="nx">success</span><span class="p">,</span> <span class="nx">options</span><span class="p">.</span><span class="nx">error</span><span class="p">);</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">&#182;</a> </div> <p>Create a new instance of a model in this collection.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">create</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">model</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-51"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-51">&#182;</a> </div> <p>Create a new instance of a model in this collection. After the model
has been created on the server, it will be added to the collection.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">create</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">model</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">options</span> <span class="o">||</span> <span class="p">(</span><span class="nx">options</span> <span class="o">=</span> <span class="p">{});</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="nx">model</span> <span class="k">instanceof</span> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">Model</span><span class="p">))</span> <span class="nx">model</span> <span class="o">=</span> <span class="k">new</span> <span class="k">this</span><span class="p">.</span><span class="nx">model</span><span class="p">(</span><span class="nx">model</span><span class="p">);</span>
<span class="nx">model</span><span class="p">.</span><span class="nx">collection</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
@@ -261,7 +266,8 @@ collection is refreshed.</p> </td> <td class="code">
<span class="k">this</span><span class="p">.</span><span class="nx">models</span> <span class="o">=</span> <span class="p">[];</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_byId</span> <span class="o">=</span> <span class="p">{};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_byCid</span> <span class="o">=</span> <span class="p">{};</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">&#182;</a> </div> <p>Internal implementation of adding a single model to the set.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_add</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">model</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-54"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-54">&#182;</a> </div> <p>Internal implementation of adding a single model to the set, updating
hash indexes for <code>id</code> and <code>cid</code> lookups.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_add</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">model</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">options</span> <span class="o">||</span> <span class="p">(</span><span class="nx">options</span> <span class="o">=</span> <span class="p">{});</span>
<span class="kd">var</span> <span class="nx">already</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">model</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">already</span><span class="p">)</span> <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">([</span><span class="s2">&quot;Can&#39;t add the same model to a set twice&quot;</span><span class="p">,</span> <span class="nx">already</span><span class="p">.</span><span class="nx">id</span><span class="p">]);</span>
@@ -274,7 +280,8 @@ collection is refreshed.</p> </td> <td class="code">
<span class="k">this</span><span class="p">.</span><span class="nx">length</span><span class="o">++</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">options</span><span class="p">.</span><span class="nx">silent</span><span class="p">)</span> <span class="k">this</span><span class="p">.</span><span class="nx">trigger</span><span class="p">(</span><span class="s1">&#39;add&#39;</span><span class="p">,</span> <span class="nx">model</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">model</span><span class="p">;</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-55">&#182;</a> </div> <p>Internal implementation of removing a single model from the set.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_remove</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">model</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="p">},</span></pre></div> </td> </tr> <tr id="section-55"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-55">&#182;</a> </div> <p>Internal implementation of removing a single model from the set, updating
hash indexes for <code>id</code> and <code>cid</code> lookups.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_remove</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">model</span><span class="p">,</span> <span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">options</span> <span class="o">||</span> <span class="p">(</span><span class="nx">options</span> <span class="o">=</span> <span class="p">{});</span>
<span class="nx">model</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">model</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">model</span><span class="p">)</span> <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
@@ -324,7 +331,7 @@ if an existing element is not provided...</p> </td> <td
This should be prefered to global jQuery lookups, if you're dealing with
a specific view.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">jQueryDelegate</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">selector</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">$</span><span class="p">(</span><span class="nx">selector</span><span class="p">,</span> <span class="k">this</span><span class="p">.</span><span class="nx">el</span><span class="p">);</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-62">&#182;</a> </div> <p>Cached regex to split keys for <code>handleEvents</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">eventSplitter</span> <span class="o">=</span> <span class="sr">/^(\w+)\s+(.*)$/</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-63">&#182;</a> </div> <p>Set up all inheritable <strong>Backbone.View</strong> properties and methods.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_</span><span class="p">.</span><span class="nx">extend</span><span class="p">(</span><span class="nx">Backbone</span><span class="p">.</span><span class="nx">View</span><span class="p">.</span><span class="nx">prototype</span><span class="p">,</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-64">&#182;</a> </div> <p>The default tagName of a View's element is "div".</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">tagName</span> <span class="o">:</span> <span class="s1">&#39;div&#39;</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-65">&#182;</a> </div> <p>Attach the jQuery function as the <code>$</code> and <code>jQuery</code> properties.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">$</span> <span class="o">:</span> <span class="nx">jQueryDelegate</span><span class="p">,</span>
<span class="p">};</span></pre></div> </td> </tr> <tr id="section-62"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-62">&#182;</a> </div> <p>Cached regex to split keys for <code>handleEvents</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="kd">var</span> <span class="nx">eventSplitter</span> <span class="o">=</span> <span class="sr">/^(\w+)\s*(.*)$/</span><span class="p">;</span></pre></div> </td> </tr> <tr id="section-63"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-63">&#182;</a> </div> <p>Set up all inheritable <strong>Backbone.View</strong> properties and methods.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">_</span><span class="p">.</span><span class="nx">extend</span><span class="p">(</span><span class="nx">Backbone</span><span class="p">.</span><span class="nx">View</span><span class="p">.</span><span class="nx">prototype</span><span class="p">,</span> <span class="p">{</span></pre></div> </td> </tr> <tr id="section-64"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-64">&#182;</a> </div> <p>The default <code>tagName</code> of a View's element is <code>"div"</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">tagName</span> <span class="o">:</span> <span class="s1">&#39;div&#39;</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-65"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-65">&#182;</a> </div> <p>Attach the jQuery function as the <code>$</code> and <code>jQuery</code> properties.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">$</span> <span class="o">:</span> <span class="nx">jQueryDelegate</span><span class="p">,</span>
<span class="nx">jQuery</span> <span class="o">:</span> <span class="nx">jQueryDelegate</span><span class="p">,</span></pre></div> </td> </tr> <tr id="section-66"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-66">&#182;</a> </div> <p><strong>render</strong> is the core function that your view should override, in order
to populate its element (<code>this.el</code>), with the appropriate HTML. The
convention is for <strong>render</strong> to always return <code>this</code>.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">render</span> <span class="o">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
@@ -350,8 +357,8 @@ needed, use <strong>make</strong> to manufacture elements, one at a time.</p>
<p>pairs. Callbacks will be bound to the view, with <code>this</code> set properly.
Uses jQuery event delegation for efficiency.
Passing a selector of <code>el</code> binds to the view's root element.
Change events are not delegated through the view because IE does not
Omitting the selector binds the event to <code>this.el</code>.
<code>"change"</code> events are not delegated through the view because IE does not
bubble change events at all.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">handleEvents</span> <span class="o">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">events</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">el</span><span class="p">).</span><span class="nx">unbind</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="nx">events</span> <span class="o">||</span> <span class="p">(</span><span class="nx">events</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">events</span><span class="p">)))</span> <span class="k">return</span> <span class="k">this</span><span class="p">;</span>

View File

@@ -150,7 +150,10 @@
<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-id">id</a></li>
<li> <a href="#Model-cid">cid</a></li>
<li> <a href="#Model-attributes">attributes</a></li>
<li>- <a href="#Model-toJSON">toJSON</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>
@@ -169,12 +172,15 @@
</a>
<ul class="toc_section">
<li> <a href="#Collection-extend">extend</a></li>
<li> <a href="#Collection-models">models</a></li>
<li> <a href="#Collection-Underscore-Methods"><b>Underscore Methods (24)</b></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-length">length</a></li>
<li> <a href="#Collection-comparator">comparator</a></li>
<li> <a href="#Collection-sort">sort</a></li>
<li> <a href="#Collection-pluck">pluck</a></li>
<li> <a href="#Model-url">url</a></li>
@@ -199,6 +205,9 @@
<li> <a href="#View-make">make</a></li>
<li> <a href="#View-handleEvents">handleEvents</a></li>
</ul>
<a class="toc_title" href="#changelog">
Change Log
</a>
</div>
<div class="container">
@@ -236,7 +245,7 @@
<table>
<tr>
<td><a href="backbone.js">Development Version (0.1.0)</a></td>
<td><i>22kb, Uncompressed with Comments</i></td>
<td><i>21kb, Uncompressed with Comments</i></td>
</tr>
<tr>
<td><a href="backbone-min.js">Production Version (0.1.0)</a></td>
@@ -257,8 +266,8 @@
<h2 id="Introduction">Introduction</h2>
<p>
When working on a heavy-duty JavaScript application, one of the first things
you learn is to stop tying your data to the DOM. It's all
When working on a web application that involved a lot of JavaScript, one
of the first things you learn is to stop tying your data to the DOM. It's all
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 HTML UI, your JavaScript logic, and the database on your
@@ -270,11 +279,11 @@
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
a model to change, the model triggers a <i>"change"</i> event; all
the <a href="#View">Views</a> that display the model's data receive the
event, 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
and update the HTML manually
&mdash; when the model changes, the views simply update themselves.
</p>
@@ -292,9 +301,17 @@
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 just the core concepts of
models, events (key-value binding), collections, views, and persistence.
page; the "Hello World" of Cappuccino includes <i>1.7 megabytes</i> of JS and images,
as measured with the Webkit inspector.
Backbone is a <i>2 kilobyte</i> include (packed, gzipped) that provides
just the core concepts of models, events (key-value binding), collections,
views, and persistence. A much closer relative to Backbone is
<a href="http://benpickles.github.com/js-model/">js-model</a>.
</p>
<p>
Many of the examples that follow are runnable. Click the <i>play</i> button
to execute them.
</p>
<h2 id="Events">Backbone.Events</h2>
@@ -307,27 +324,38 @@
</p>
<pre class="runnable">
var obj = {};
var object = {};
_.extend(obj, Backbone.Events);
_.extend(object, Backbone.Events);
obj.bind("alert", function(msg) {
object.bind("alert", function(msg) {
alert("Triggered " + msg);
});
obj.trigger("alert", "an event");
object.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.
whenever the <b>event</b> (specified by an arbitrary 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.
namespace them: <tt>"poll:start"</tt>.
</p>
<p>
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. For example, to proxy all events
from one object to another:
</p>
<pre>
proxy.bind("all", function(eventName) {
object.trigger(eventName);
});
</pre>
<p id="Events-unbind">
<b class="header">unbind</b><code>object.unbind([event], [callback])</code>
@@ -337,12 +365,20 @@ obj.trigger("alert", "an event");
removed. If no event is specified, all bound callbacks on the object
will be removed.
</p>
<pre>
object.unbind("change", onChange); // Removes just the onChange callback.
object.unbind("change"); // Removes all "change" callbacks.
object.unbind(); // Removes all callbacks on object.
</pre>
<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.
<b>trigger</b> will be passed along to the event callbacks.
</p>
<h2 id="Model">Backbone.Model</h2>
@@ -357,8 +393,9 @@ obj.trigger("alert", "an event");
<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
with a custom method, setting an attribute, and firing an event keyed
to changes in that specific attribute.
After running this code once, <tt>sidebar</tt> will be
available in your browser's console, so you can play around with it.
</p>
@@ -382,12 +419,29 @@ sidebar.promptColor();
</pre>
<p id="Model-extend">
<b class="header">extend</b><code>Backbone.Model.extend(properties, [staticProperties])</code>
<b class="header">extend</b><code>Backbone.Model.extend(properties, [classProperties])</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.
and provide instance <b>properties</b>, as well as optional
<b>classProperties</b> to be attached directly to the constructor function.
</p>
<p>
<b>extend</b> correctly sets up the prototype chain, so subclasses created
with <b>extend</b> can be further extended and subclassed as far as you like.
</p>
<pre>
var Note = Backbone.Model.extend({
author: function() { ... },
allowedToEdit: function(account) { ... },
coordinates: function() { ... }
});
</pre>
<p id="Model-get">
<b class="header">get</b><code>model.get(attribute)</code>
@@ -401,18 +455,17 @@ sidebar.promptColor();
<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.
<tt>{silent: true}</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.
If the model has a <a href="#Model-validate">validate</a> 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">
@@ -421,12 +474,42 @@ note.set({title: "October 31"}, {silent: true});
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-id">
<b class="header">id</b><code>model.id</code>
<br />
A special property of models, the <b>id</b> is an arbitrary string
(integer id or UUID). If you set the <b>id</b> in the
attributes hash, it will be copied onto the model as a direct property.
Models can be retrieved by id from collections, and the id is used to generate
model URLs by default.
</p>
<p id="Model-cid">
<b class="header">cid</b><code>model.cid</code>
<br />
A special property of models, the <b>cid</b> or client id is a unique identifier
automatically assigned to all models when they're first created. Client ids
are handy when the model has not yet been saved to the server, and does not
yet have its eventual true <b>id</b>, but already needs to be visible in the UI.
Client ids take the form: <tt>c1, c2, c3 ...</tt>
</p>
<p id="Model-attributes">
<b class="header">attributes</b><code>model.attributes()</code>
<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.
The <b>attributes</b> property is the internal hash containing the model's
state. Please use <a href="#Model-set">set</a> to update the attributes instead of modifying
them directly. If you'd like to retrieve and munge a copy of the model's
attributes, use <a href="#Model-toJSON">toJSON</a> instead.
</p>
<p id="Model-toJSON">
<b class="header">toJSON</b><code>model.toJSON</code>
<br />
Return a copy of the model's <a href="#Model-attributes">attributes</a> for JSON stringification.
This can be used for persistence, serialization, or for augmentation before
being handed off to a view.
</p>
<pre class="runnable">
@@ -437,18 +520,25 @@ var artist = new Backbone.Model({
artist.set({birthday: "December 16, 1866"});
alert(JSON.stringify(artist.attributes()));
alert(JSON.stringify(artist));
</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>
by delegating to <a href="#Sync">Backbone.sync</a>. If the model has a <a href="#Model-validate">validate</a>
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.
<a href="#Model-isNew">isNew</a>, the save will be a <tt>"create"</tt>
(HTTP <tt>POST</tt>), if the model already
exists on the server, the save will be an <tt>"update"</tt> (HTTP <tt>PUT</tt>). Accepts
<tt>success</tt> and <tt>error</tt> callbacks in the options hash, which
are passed <tt>(model, response)</tt> as arguments.
</p>
<p>
In the following example, notice how because the model has never been
saved previously, our overridden version of <tt>Backbone.sync</tt> receives a <tt>"create"</tt> request.
</p>
<pre class="runnable">
@@ -468,16 +558,14 @@ book.save();
<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
request to <a href="#Sync">Backbone.sync</a>. Accepts
<tt>success</tt> and <tt>error</tt> callbacks in the options hash.
</p>
<pre>
book.destroy({
success: function(model, response) {
...
}
});
book.destroy({success: function(model, response) {
...
}});
</pre>
<p id="Model-validate">
@@ -528,14 +616,14 @@ one.set({
<p>
A model with an id of <tt>101</tt>, stored in a
<b>Backbone.Collection</b> with a <tt>url</tt> of <tt>"/notes"</tt>,
<a href="#Collection">Backbone.Collection</a> 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.
Returns a new instance of the model with identical attributes.
</p>
<p id="Model-isNew">
@@ -548,9 +636,10 @@ one.set({
<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.
Manually trigger the <tt>"change"</tt> event.
If you've been passing <tt>{silent: true}</tt> to the <a href="#Model-set">set</a> function in order to
aggregate rapid changes to a model, you'll want to call <tt>model.change()</tt>
when you're all finished.
</p>
<p id="Model-hasChanged">
@@ -619,16 +708,24 @@ bill.set({name : "Bill Jones"});
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.
<a href="#Collection-Underscore-Methods">Underscore.js methods</a>.
</p>
<p id="Collection-extend">
<b class="header">extend</b><code>Backbone.Collection.extend(properties, [staticProperties])</code>
<b class="header">extend</b><code>Backbone.Collection.extend(properties, [classProperties])</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.
providing instance <b>properties</b>, as well as optional <b>classProperties</b> to be attached
directly to the collection's constructor function.
</p>
<p id="Collection-models">
<b class="header">models</b><code>collection.models</code>
<br />
Raw access to the JavaScript array of models inside of the collection. Usually you'll
want to use <tt>get</tt>, <tt>at</tt>, or the <b>Underscore methods</b>
to access model objects, but occasionally a direct reference to the array
is desired.
</p>
<p id="Collection-Underscore-Methods">
@@ -692,14 +789,13 @@ var alphabetical = Books.sortBy(function(book) {
</p>
<pre class="runnable">
var ships = new Backbone.Collection();
var Ship = Backbone.Model;
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"})
@@ -710,7 +806,7 @@ ships.add([
<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>
<tt>"remove"</tt> event, which you can use <tt>silent</tt>
to suppress.
</p>
@@ -719,6 +815,10 @@ ships.add([
<br />
Get a model from a collection, specified by <b>id</b>.
</p>
<pre>
var book = Library.get(110);
</pre>
<p id="Collection-getByCid">
<b class="header">getByCid</b><code>collection.getByCid(cid)</code>
@@ -736,12 +836,50 @@ ships.add([
is sorted, and if your collection isn't sorted, <b>at</b> will still
retrieve models in insertion order.
</p>
<p id="Collection-length">
<b class="header">length</b><code>collection.length</code>
<br />
Like an array, a Collection maintains a <tt>length</tt> property, counting
the number of models it contains.
</p>
<p id="Collection-comparator">
<b class="header">comparator</b><code>collection.comparator</code>
<br />
By default there is no <b>comparator</b> function on a collection.
If you define a comparator, it will be used to maintain
the collection in sorted order. This means that as models are added,
they are inserted at the correct index in <tt>collection.models</tt>.
Comparator functions take a model and return a numeric or string value
by which the model should be ordered relative to others.
</p>
<p>
Note how even though all of the chapters in this example are added backwards,
they come out in the proper order:
</p>
<pre class="runnable">
var Chapter = Backbone.Model;
var chapters = new Backbone.Collection;
chapters.comparator = function(chapter) {
return chapter.get("page");
};
chapters.add(new Chapter({page: 9, title: "The End"}));
chapters.add(new Chapter({page: 5, title: "The Middle"}));
chapters.add(new Chapter({page: 1, title: "The Beginning"}));
alert(chapters.pluck('title'));
</pre>
<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
normal circumstances, as a collection with a <a href="#Collection-comparator">comparator</a> 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>
@@ -803,16 +941,28 @@ var Notes = Backbone.Collection.extend({
<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>
<tt>success</tt> and <tt>error</tt>
callbacks which will be passed <tt>(collection, response)</tt> as arguments.
Delegates to <a href="#Sync">Backbone.sync</a>
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.
models, namespaced under "models": <tt>{"models": [...]}</tt> &mdash;
additional information can be returned with the response under different keys.
</p>
<pre class="runnable">
Backbone.sync = function(method, model) {
alert(method + ": " + model.url);
};
var accounts = new Backbone.Collection;
accounts.url = '/accounts';
accounts.fetch();
</pre>
<p>
Note that <b>fetch</b> should not be used to populate collections on
@@ -834,6 +984,19 @@ var Notes = Backbone.Collection.extend({
must have a <tt>model</tt> property, referencing the type of model that
the collection contains.
</p>
<pre>
var Library = Backbone.Collection.extend({
model: Book
});
var NYPL = new Library;
var othello = NYPL.create({
title: "Othello",
author: "William Shakespeare"
});
</pre>
<p id="Collection-toString">
<b class="header">toString</b><code>collection.toString()</code>
@@ -862,15 +1025,42 @@ var Notes = Backbone.Collection.extend({
<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>
<p>
When formulating server responses for <b>Backbone.sync</b> requests,
model attributes will be sent up, serialized as JSON, under the <tt>model</tt>
parameter. When returning a JSON response, send down the model's representation
under the <tt>model</tt> key, and other keys can be used for additional out-of-band
information. When responding to a <tt>"read"</tt> request from a collection,
send down the array of model attribute hashes under the <tt>models</tt> key.
</p>
<p>
For example, a Rails handler responding to an <tt>"update"</tt> call from
<b>Backbone.sync</b> would look like this: <i>(In real code, never use
</i><tt>update_attributes</tt><i> blindly, and always whitelist the attributes
you allow to be changed.)</i>
</p>
<pre>
def update
account = Account.find(params[:id])
account.update_attributes JSON.parse params[:model]
render :json => {:model => account}
end
</pre>
<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,
Backbone views are almost more convention than they are code &mdash; they
don't determine anything about your HTML or CSS for you, and can be used
with any JavaScript templating library.
The general idea is to organize your interface into logical views,
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:
model changes, without having to redraw the page. Instead of digging into
a JSON object, 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>
@@ -914,16 +1104,17 @@ ui.Chapter = Backbone.View.extend({
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 already available. A good
is already on the page,
<a href="http://documentcloud.github.com/underscore/#template">_.template</a>
is already available. A good
convention is to <tt>return this</tt> at the end of <b>render</b> to
enable chained calls.
</p>
<pre>
ui.Chapter = Backbone.View.extend({
var Bookmark = Backbone.View.extend({
render: function() {
var data = this.model.attributes();
$(this.el).html(this.template.render(data));
$(this.el).html(this.template.render(this.model.toJSON()));
return this;
}
});
@@ -936,6 +1127,16 @@ ui.Chapter = Backbone.View.extend({
with optional attributes and HTML content. Used internally to create the
initial <tt>view.el</tt>.
</p>
<pre class="runnable">
var view = new Backbone.View;
var el = view.make("b", {className: "bold"}, "Bold! ");
$("#make-demo").append(el);
</pre>
<div id="make-demo"></div>
<p id="View-handleEvents">
<b class="header">handleEvents</b><code>handleEvents([events])</code>
@@ -944,11 +1145,13 @@ ui.Chapter = Backbone.View.extend({
for DOM events within a view.
If an <b>events</b> hash is not passed directly, uses <tt>this.events</tt>
as the source. Events are written in the format <tt>{"event selector": "callback"}</tt>.
Omitting the <tt>selector</tt> causes the event to be bound to the view's
root element (<tt>this.el</tt>).
</p>
<p>
Using <b>handleEvents</b> provides a number of advantages over manually
binding events to child elements within <tt>render</tt>. All attached
using jQuery to bind events to child elements during <a href="#View-render">render</a>. All attached
callbacks are bound to the view before being handed off to jQuery, so when
the callbacks are invoked, <tt>this</tt> continues to refer to the view object. When
<b>handleEvents</b> is run again, perhaps with a different <tt>events</tt>
@@ -965,8 +1168,8 @@ ui.Chapter = Backbone.View.extend({
var DocumentView = Backbone.View.extend({
events: {
"click .title" : "select",
"dblclick .title" : "open",
"dblclick" : "open",
"click .icon.doc" : "select",
"contextmenu .icon.doc" : "showMenu",
"click .show_notes" : "toggleNotes",
"click .title .lock" : "editAccessLevel",
@@ -974,11 +1177,20 @@ var DocumentView = Backbone.View.extend({
},
render: {
var data = this.document.attributes();
this.el.html(this.template.render(data));
$(this.el).html(this.template.render(this.model.toJSON()));
this.handleEvents();
return this;
}
},
open: function() {
window.open(this.model.get("viewer_url"));
},
select: function() {
this.model.set({selected: true});
},
...
});
</pre>
@@ -988,7 +1200,7 @@ var DocumentView = Backbone.View.extend({
<h2 id="changes">Change Log</h2>
<h2 id="changelog">Change Log</h2>
<p>
<b class="header">0.1.0</b><br />

View File

@@ -26,11 +26,6 @@ $(document).ready(function() {
var collection = new klass();
collection.add(doc);
test("model: attributes", function() {
ok(doc.attributes() !== attrs, "Attributes are different objects.");
ok(_.isEqual(doc.attributes(), attrs), "but with identical contents.");
});
test("model: url", function() {
equals(doc.url(), '/collection/1-the-tempest');
});