[Pkg-javascript-commits] [backbone] 22/37: fixes #915 - nested `'change:attr'` events
Jonas Smedegaard
js at moszumanska.debian.org
Sat May 3 17:02:48 UTC 2014
This is an automated email from the git hooks/post-receive script.
js pushed a commit to tag 0.9.1
in repository backbone.
commit 29a4359ff7d49611cc46cbb9af41815ae18a2646
Author: Brad Dunbar <dunbarb2 at gmail.com>
Date: Thu Feb 2 10:32:34 2012 -0500
fixes #915 - nested `'change:attr'` events
* `'change'` does not fire without changes
* nested `'change:attr'` events are fired
* `'change'` is only fired once for nested calls
* nested `'change'` events are fired
---
backbone.js | 21 ++++++++++++++++-----
test/model.js | 60 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 65 insertions(+), 16 deletions(-)
diff --git a/backbone.js b/backbone.js
index 3dcf369..257e3b7 100644
--- a/backbone.js
+++ b/backbone.js
@@ -233,15 +233,19 @@
var now = this.attributes;
var escaped = this._escapedAttributes;
var prev = this._previousAttributes || {};
- var alreadyChanging = this._changing;
+ var alreadySetting = this._setting;
this._changed || (this._changed = {});
- this._changing = true;
+ this._setting = true;
// Update attributes.
for (attr in attrs) {
val = attrs[attr];
if (!_.isEqual(now[attr], val)) delete escaped[attr];
options.unset ? delete now[attr] : now[attr] = val;
+ if (this._changing && !_.isEqual(this._changed[attr], val)) {
+ this.trigger('change:' + attr, this, val, options);
+ this._moreChanges = true;
+ }
delete this._changed[attr];
if (!_.isEqual(prev[attr], val) || (_.has(now, attr) != _.has(prev, attr))) {
this._changed[attr] = val;
@@ -249,9 +253,9 @@
}
// Fire the `"change"` events, if the model has been changed.
- if (!alreadyChanging) {
+ if (!alreadySetting) {
if (!options.silent && this.hasChanged()) this.change(options);
- this._changing = false;
+ this._setting = false;
}
return this;
},
@@ -379,12 +383,19 @@
// a `"change:attribute"` event for each changed attribute.
// Calling this will cause all objects observing the model to update.
change: function(options) {
+ if (this._changing || !this.hasChanged()) return this;
+ this._changing = true;
for (var attr in this._changed) {
this.trigger('change:' + attr, this, this._changed[attr], options);
}
- this.trigger('change', this, options);
+ do {
+ this._moreChanges = false;
+ this.trigger('change', this, options);
+ } while (this._moreChanges);
this._previousAttributes = _.clone(this.attributes);
delete this._changed;
+ this._changing = false;
+ return this;
},
// Determine if the model has changed since the last `"change"` event.
diff --git a/test/model.js b/test/model.js
index 3ee2942..346f2f0 100644
--- a/test/model.js
+++ b/test/model.js
@@ -506,17 +506,6 @@ $(document).ready(function() {
a.set({state: 'hello'});
});
- test("Model: Multiple nested calls to set", function() {
- var counter = 0, model = new Backbone.Model({});
- model.on('change', function() {
- counter++;
- model.set({b: 1});
- model.set({a: 1});
- })
- .set({a: 1});
- equal(counter, 1, 'change is only triggered once');
- });
-
test("hasChanged/set should use same comparison", function() {
expect(2);
var changed = 0, model = new Backbone.Model({a: null});
@@ -627,4 +616,53 @@ $(document).ready(function() {
equal(changed, 1);
});
+ test("nested `set` during `'change:attr'`", 1, function() {
+ var model = new Backbone.Model();
+ model.on('change:x', function() { ok(true); });
+ model.on('change:y', function() {
+ model.set({x: true});
+ // only fires once
+ model.set({x: true});
+ });
+ model.set({y: true});
+ });
+
+ test("nested `change` only fires once", 1, function() {
+ var model = new Backbone.Model();
+ model.on('change', function() {
+ ok(true);
+ model.change();
+ });
+ model.set({x: true});
+ });
+
+ test("no `'change'` event if no changes", function() {
+ var model = new Backbone.Model();
+ model.on('change', function() { ok(false); });
+ model.change();
+ });
+
+ test("nested `set` suring `'change'`", 3, function() {
+ var count = 0;
+ var model = new Backbone.Model();
+ model.on('change', function() {
+ switch(count++) {
+ case 0:
+ deepEqual(this.changedAttributes(), {x: true});
+ model.set({y: true});
+ break;
+ case 1:
+ deepEqual(this.changedAttributes(), {x: true, y: true});
+ model.set({z: true});
+ break;
+ case 2:
+ deepEqual(this.changedAttributes(), {x: true, y: true, z: true});
+ break;
+ default:
+ ok(false);
+ }
+ });
+ model.set({x: true});
+ });
+
});
--
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