[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