[Pkg-javascript-commits] [backbone] 32/34: Streamlined event delegation from models through collections. Added documentation for 0.2.0 enhancements.
Jonas Smedegaard
js at moszumanska.debian.org
Sat May 3 16:58:55 UTC 2014
This is an automated email from the git hooks/post-receive script.
js pushed a commit to tag 0.2.0
in repository backbone.
commit 6e7894d8fad10bae0c73dcdf8ee7b1954ecf428c
Author: Jeremy Ashkenas <jashkenas at gmail.com>
Date: Mon Oct 25 11:23:04 2010 -0400
Streamlined event delegation from models through collections. Added documentation for 0.2.0 enhancements.
---
backbone.js | 20 +++++--------
index.html | 84 ++++++++++++++++++++++++++++++++++++++----------------
test/collection.js | 13 +++++++++
3 files changed, 80 insertions(+), 37 deletions(-)
diff --git a/backbone.js b/backbone.js
index 8e48b32..4e42722 100644
--- a/backbone.js
+++ b/backbone.js
@@ -495,20 +495,14 @@
},
// Internal method called every time a model in the set fires an event.
- // Sets need to update their indexes when models change ids.
- _onModelEvent : function(ev, model, error) {
- switch (ev) {
- case 'change':
- if (model.hasChanged('id')) {
- delete this._byId[model.previous('id')];
- this._byId[model.id] = model;
- }
- this.trigger('change', model);
- break;
- case 'error':
- this.trigger('error', model, error);
- break;
+ // Sets need to update their indexes when models change ids. All other
+ // events simply proxy through.
+ _onModelEvent : function(ev, model) {
+ if (ev === 'change:id') {
+ delete this._byId[model.previous('id')];
+ this._byId[model.id] = model;
}
+ this.trigger.apply(this, arguments);
}
});
diff --git a/index.html b/index.html
index 5dae9f4..5d2d6d2 100644
--- a/index.html
+++ b/index.html
@@ -164,6 +164,7 @@
<li>– <a href="#Model-destroy">destroy</a></li>
<li>– <a href="#Model-validate">validate</a></li>
<li>– <a href="#Model-url">url</a></li>
+ <li>– <a href="#Model-parse">parse</a></li>
<li>– <a href="#Model-clone">clone</a></li>
<li>– <a href="#Model-isNew">isNew</a></li>
<li>– <a href="#Model-change">change</a></li>
@@ -192,6 +193,7 @@
<li>– <a href="#Collection-sort">sort</a></li>
<li>– <a href="#Collection-pluck">pluck</a></li>
<li>– <a href="#Collection-url">url</a></li>
+ <li>– <a href="#Collection-parse">parse</a></li>
<li>– <a href="#Collection-fetch">fetch</a></li>
<li>– <a href="#Collection-refresh">refresh</a></li>
<li>– <a href="#Collection-create">create</a></li>
@@ -212,7 +214,7 @@
<li>– <a href="#View-jQuery">$ (jQuery)</a></li>
<li>– <a href="#View-render">render</a></li>
<li>– <a href="#View-make">make</a></li>
- <li>– <a href="#View-handleEvents">handleEvents</a></li>
+ <li>– <a href="#View-delegateEvents">delegateEvents</a></li>
</ul>
<a class="toc_title" href="#examples">
Examples
@@ -508,8 +510,10 @@ new Book({
<b class="header">set</b><code>model.set(attributes, [options])</code>
<br />
Set a hash of attributes (one or many) on the model. If any of the attributes
- change the models state, a <tt>"change"</tt> event will be fired, unless
- <tt>{silent: true}</tt> is passed as an option.
+ change the models state, a <tt>"change"</tt> event will be triggered, unless
+ <tt>{silent: true}</tt> is passed as an option. Change events for specific
+ attributes are also triggered, and you can bind to those as well, for example:
+ <tt>change:title</tt>, and <tt>change:content</tt>.
</p>
<pre>
@@ -715,7 +719,7 @@ account.set({access: "unlimited"}, {
the server. If your models are located somewhere else, override this method
with the correct logic. Generates URLs of the form: <tt>"/[collection]/[id]"</tt>.
</p>
-
+
<p>
Delegates to <a href="#Collection-url">Collection#url</a> to generate the
URL, so make sure that you have it defined.
@@ -723,6 +727,18 @@ account.set({access: "unlimited"}, {
<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-parse">
+ <b class="header">parse</b><code>model.parse(response)</code>
+ <br />
+ <b>parse</b> is called whenever a model's data is returned by the
+ server, in <a href="#Model-fetch">fetch</a>, and <a href="#Model-save">save</a>.
+ The function is passed the raw <tt>response</tt> object, and should return
+ the attributes hash to be <a href="#Model-set">set</a> on the model. The
+ default implementation is a no-op, simply passing through the JSON response.
+ Override this if you need to work with a preexisting API, or better namespace
+ your responses.
+ </p>
<p id="Model-clone">
<b class="header">clone</b><code>model.clone()</code>
@@ -801,12 +817,17 @@ bill.set({name : "Bill Jones"});
<h2 id="Collection">Backbone.Collection</h2>
<p>
- Collections are ordered sets of models. You can bind callbacks to be notified
- when any model in the collection is changed, listen for <tt>"add"</tt> and
- <tt>"remove"</tt> events, <tt>fetch</tt> the collection from the server,
- and use a full suite of
+ Collections are ordered sets of models. You can to bind <tt>"change"</tt> events
+ to be notified when any model in the collection has been modified,
+ 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="#Collection-Underscore-Methods">Underscore.js methods</a>.
</p>
+
+ <p>
+ Collections may also listen for changes to specific attributes in their
+ models, for example: <tt>Documents.bind("change:selected", ...)</tt>
+ </p>
<p id="Collection-extend">
<b class="header">extend</b><code>Backbone.Collection.extend(properties, [classProperties])</code>
@@ -1082,6 +1103,27 @@ var Notes = Backbone.Collection.extend({
});
</pre>
+ <p id="Collection-parse">
+ <b class="header">parse</b><code>collection.parse(response)</code>
+ <br />
+ <b>parse</b> is called by Backbone whenever a collection's models are
+ returned by the server, in <a href="#Collection-fetch">fetch</a>.
+ The function is passed the raw <tt>response</tt> object, and should return
+ the array of model attributes to be <a href="#Collection-add">added</a>
+ to the collection. The default implementation is a no-op, simply passing
+ through the JSON response. Override this if you need to work with a
+ preexisting API, or better namespace your responses.
+ </p>
+
+<pre>
+var Tweets = Backbone.Collection.extend({
+ // The Twitter Search API returns tweets under "results".
+ parse: function(response) {
+ return response.results;
+ }
+});
+</pre>
+
<p id="Collection-fetch">
<b class="header">fetch</b><code>collection.fetch([options])</code>
<br />
@@ -1093,15 +1135,8 @@ var Notes = Backbone.Collection.extend({
<a href="#Collection-refresh">refresh</a>.
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> —
- instead of returning the
- array directly, we ask you to namespace your models like this by default,
- so that it's possible to send down out-of-band information
- for things like pagination or error states.
+ The server handler for <b>fetch</b> requests should return a JSON array of
+ models.
</p>
<pre class="runnable">
@@ -1258,7 +1293,7 @@ end
<br />
Get started with views by creating a custom view class. You'll want to
override the <a href="#View-render">render</a> function, specify your
- declarative <a href="#View-handleEvents">events</a>, and perhaps the
+ declarative <a href="#View-delegateEvents">events</a>, and perhaps the
<tt>tagName</tt>, <tt>className</tt>, or <tt>id</tt> of the View's root
element.
</p>
@@ -1406,23 +1441,25 @@ $("#make-demo").append(el);
<div id="make-demo"></div>
- <p id="View-handleEvents">
- <b class="header">handleEvents</b><code>handleEvents([events])</code>
+ <p id="View-delegateEvents">
+ <b class="header">delegateEvents</b><code>delegateEvents([events])</code>
<br />
Uses jQuery's <tt>delegate</tt> function to provide declarative callbacks
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>).
+ root element (<tt>this.el</tt>). By default <tt>delegateEvents</tt> is called
+ within the View's constructor for you, so if you have a simple <tt>events</tt>
+ hash, all of your DOM events will always already be connected.
</p>
<p>
- Using <b>handleEvents</b> provides a number of advantages over manually
+ Using <b>delegateEvents</b> provides a number of advantages over manually
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>
+ <b>delegateEvents</b> is run again, perhaps with a different <tt>events</tt>
hash, all callbacks are removed and delegated afresh — useful for
views which need to behave differently when in different modes.
</p>
@@ -1446,7 +1483,6 @@ var DocumentView = Backbone.View.extend({
render: function() {
$(this.el).html(this.template(this.model.toJSON()));
- this.handleEvents();
return this;
},
diff --git a/test/collection.js b/test/collection.js
index 46dd0f5..59d0f22 100644
--- a/test/collection.js
+++ b/test/collection.js
@@ -31,6 +31,19 @@ $(document).ready(function() {
equals(col.getByCid(col.first().cid), col.first());
});
+ test("Collection: update index when id changes", function() {
+ var col = new Backbone.Collection();
+ col.add([
+ {id : 1, name : 'one'},
+ {id : 2, name : 'two'}
+ ]);
+ var one = col.get(1);
+ equals(one.get('name'), 'one');
+ one.set({id : 101});
+ equals(col.get(1), null);
+ equals(col.get(101).get('name'), 'one');
+ });
+
test("Collection: at", function() {
equals(col.at(2), b);
});
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/backbone.git
More information about the Pkg-javascript-commits
mailing list