[Pkg-javascript-commits] [backbone] 261/281: cache changed attributes

Jonas Smedegaard js at moszumanska.debian.org
Sat May 3 17:02:20 UTC 2014


This is an automated email from the git hooks/post-receive script.

js pushed a commit to tag 0.9.0
in repository backbone.

commit 2f654d2676ef6e44150ba4a10b90be53567d9e8d
Author: Brad Dunbar <dunbarb2 at gmail.com>
Date:   Mon Jan 30 05:00:41 2012 -0500

    cache changed attributes
---
 backbone.js   | 42 +++++++++++++++++-------------------------
 test/model.js |  9 +++++++++
 2 files changed, 26 insertions(+), 25 deletions(-)

diff --git a/backbone.js b/backbone.js
index e7702b4..ee6ef0c 100644
--- a/backbone.js
+++ b/backbone.js
@@ -163,10 +163,11 @@
     this.attributes = {};
     this._escapedAttributes = {};
     this.cid = _.uniqueId('c');
+    this._changed = {};
     if (!this.set(attributes, {silent: true})) {
       throw new Error("Can't create an invalid model");
     }
-    this._changed = false;
+    this._changed = {};
     this._previousAttributes = _.clone(this.attributes);
     this.initialize.apply(this, arguments);
   };
@@ -174,9 +175,6 @@
   // Attach all inheritable methods to the Model prototype.
   _.extend(Backbone.Model.prototype, Backbone.Events, {
 
-    // Has the item been changed since the last `"change"` event?
-    _changed: false,
-
     // The default name for the JSON `id` attribute is `"id"`. MongoDB and
     // CouchDB users may want to set this to `"_id"`.
     idAttribute: 'id',
@@ -226,7 +224,6 @@
       if (!attrs) return this;
       if (attrs instanceof Backbone.Model) attrs = attrs.attributes;
       if (options.unset) for (var attr in attrs) attrs[attr] = void 0;
-      var now = this.attributes, escaped = this._escapedAttributes;
 
       // Run validation.
       if (this.validate && !this._performValidation(attrs, options)) return false;
@@ -234,7 +231,9 @@
       // Check for changes of `id`.
       if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
 
-      // We're about to start triggering change events.
+      var now = this.attributes;
+      var escaped = this._escapedAttributes;
+      var prev = this._previousAttributes || {};
       var alreadyChanging = this._changing;
       this._changing = true;
 
@@ -243,14 +242,17 @@
         val = attrs[attr];
         if (!_.isEqual(now[attr], val) || (options.unset && (attr in now))) {
           delete escaped[attr];
-          this._changed = true;
+        }
+        delete this._changed[attr];
+        if (!_.isEqual(prev[attr], val) || (options.unset && (attr in prev))) {
+          this._changed[attr] = val;
         }
         options.unset ? delete now[attr] : now[attr] = val;
       }
 
       // Fire the `"change"` events, if the model has been changed.
       if (!alreadyChanging) {
-        if (!options.silent && this._changed) this.change(options);
+        if (!options.silent && this.hasChanged()) this.change(options);
         this._changing = false;
       }
       return this;
@@ -373,20 +375,19 @@
     // a `"change:attribute"` event for each changed attribute.
     // Calling this will cause all objects observing the model to update.
     change: function(options) {
-      var changes = this.changedAttributes();
-      for (var attr in changes) {
-        this.trigger('change:' + attr, this, changes[attr], options);
+      for (var attr in this._changed) {
+        this.trigger('change:' + attr, this, this._changed[attr], options);
       }
       this.trigger('change', this, options);
       this._previousAttributes = _.clone(this.attributes);
-      this._changed = false;
+      this._changed = {};
     },
 
     // Determine if the model has changed since the last `"change"` event.
     // If you specify an attribute name, determine if that attribute has changed.
     hasChanged: function(attr) {
-      if (attr) return !_.isEqual(this._previousAttributes[attr], this.attributes[attr]);
-      return this._changed;
+      if (attr) return attr in this._changed;
+      return !_.isEmpty(this._changed);
     },
 
     // Return an object containing all the attributes that have changed, or
@@ -394,17 +395,8 @@
     // parts of a view need to be updated and/or what attributes need to be
     // persisted to the server. Unset attributes will be set to undefined.
     changedAttributes: function(now) {
-      if (!this._changed) return false;
-      now || (now = this.attributes);
-      var changed = false, old = this._previousAttributes;
-      for (var attr in now) {
-        if (_.isEqual(old[attr], now[attr])) continue;
-        (changed || (changed = {}))[attr] = now[attr];
-      }
-      for (var attr in old) {
-        if (!(attr in now)) (changed || (changed = {}))[attr] = void 0;
-      }
-      return changed;
+      if (!this.hasChanged()) return false;
+      return _.clone(this._changed);
     },
 
     // Get the previous value of an attribute, recorded at the time the last
diff --git a/test/model.js b/test/model.js
index 861ec61..225b21e 100644
--- a/test/model.js
+++ b/test/model.js
@@ -559,4 +559,13 @@ $(document).ready(function() {
     model.change();
   });
 
+  test("hasChanged is false after original values are set", function() {
+    var model = new Backbone.Model({x: 1});
+    model.on('change:x', function(){ ok(false); });
+    model.set({x: 2}, {silent: true});
+    ok(model.hasChanged());
+    model.set({x: 1}, {silent: true});
+    ok(!model.hasChanged());
+  });
+
 });

-- 
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