mirror of
https://github.com/jashkenas/backbone.git
synced 2026-04-30 03:00:06 -04:00
Fixes #1016 - Expose changed.
* Expose `changed` as a public hash of changes. * Initialize `changed`, `_pending`, and `_silent` in the constructor instead of checking in `set`. * Ensure `changed` matches `attributes`.
This commit is contained in:
45
backbone.js
45
backbone.js
@@ -174,10 +174,14 @@
|
||||
this.attributes = {};
|
||||
this._escapedAttributes = {};
|
||||
this.cid = _.uniqueId('c');
|
||||
this.changed = {};
|
||||
this._silent = {};
|
||||
this._pending = {};
|
||||
this.set(attributes, {silent: true});
|
||||
delete this._changed;
|
||||
delete this._silent;
|
||||
delete this._pending;
|
||||
// Reset change tracking.
|
||||
this.changed = {};
|
||||
this._silent = {};
|
||||
this._pending = {};
|
||||
this._previousAttributes = _.clone(this.attributes);
|
||||
this.initialize.apply(this, arguments);
|
||||
};
|
||||
@@ -186,7 +190,7 @@
|
||||
_.extend(Backbone.Model.prototype, Backbone.Events, {
|
||||
|
||||
// A hash of attributes whose current and previous value differ.
|
||||
_changed: null,
|
||||
changed: null,
|
||||
|
||||
// A hash of attributes that have silently changed since the last time
|
||||
// `change` was called. Will become pending attributes on the next call.
|
||||
@@ -252,13 +256,10 @@
|
||||
// Check for changes of `id`.
|
||||
if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
|
||||
|
||||
var changes = {};
|
||||
var changes = options.changes = {};
|
||||
var now = this.attributes;
|
||||
var escaped = this._escapedAttributes;
|
||||
var prev = this._previousAttributes || {};
|
||||
this._changed || (this._changed = {});
|
||||
this._silent || (this._silent = {});
|
||||
this._pending || (this._pending = {});
|
||||
|
||||
for (attr in attrs) {
|
||||
val = attrs[attr];
|
||||
@@ -272,16 +273,16 @@
|
||||
// If the new and previous value differ, record the change. If not,
|
||||
// then remove changes for this attribute.
|
||||
if (!_.isEqual(prev[attr], val) || (_.has(now, attr) != _.has(prev, attr))) {
|
||||
this._changed[attr] = true;
|
||||
this.changed[attr] = val;
|
||||
if (!options.silent) this._pending[attr] = true;
|
||||
} else {
|
||||
delete this._changed[attr];
|
||||
delete this.changed[attr];
|
||||
delete this._pending[attr];
|
||||
}
|
||||
}
|
||||
|
||||
// Fire the `"change"` events.
|
||||
if (!options.silent) this.change(_.extend({changes: changes}, options));
|
||||
if (!options.silent) this.change(options);
|
||||
return this;
|
||||
},
|
||||
|
||||
@@ -412,20 +413,23 @@
|
||||
var changing = this._changing;
|
||||
this._changing = true;
|
||||
// Silent changes become pending changes.
|
||||
this._pending = _.extend(this._pending || {}, this._silent);
|
||||
for (var attr in this._silent) this._pending[attr] = true;
|
||||
// Silent changes are triggered.
|
||||
var changes = _.extend({}, options.changes, this._silent);
|
||||
delete this._silent;
|
||||
this._silent = {};
|
||||
for (var attr in changes) {
|
||||
this.trigger('change:' + attr, this, this.attributes[attr], options);
|
||||
}
|
||||
if (changing) return this;
|
||||
// Continue firing `"change"` events while there are pending changes.
|
||||
while (!_.isEmpty(this._pending)) {
|
||||
delete this._pending;
|
||||
this._pending = {};
|
||||
this.trigger('change', this, options);
|
||||
// Pending and silent changes still remain.
|
||||
this._changed = _.extend({}, this._pending, this._silent);
|
||||
for (var attr in this.changed) {
|
||||
if (this._pending[attr] || this._silent[attr]) continue;
|
||||
delete this.changed[attr];
|
||||
}
|
||||
this._previousAttributes = _.clone(this.attributes);
|
||||
}
|
||||
this._changing = false;
|
||||
@@ -435,8 +439,8 @@
|
||||
// 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 (!arguments.length) return !_.isEmpty(this._changed);
|
||||
return this._changed && _.has(this._changed, attr);
|
||||
if (!arguments.length) return !_.isEmpty(this.changed);
|
||||
return _.has(this.changed, attr);
|
||||
},
|
||||
|
||||
// Return an object containing all the attributes that have changed, or
|
||||
@@ -446,12 +450,7 @@
|
||||
// You can also pass an attributes object to diff against the model,
|
||||
// determining if there *would be* a change.
|
||||
changedAttributes: function(diff) {
|
||||
if (!diff) {
|
||||
if (!this.hasChanged()) return false;
|
||||
var changes = {};
|
||||
for (var attr in this._changed) changes[attr] = this.attributes[attr];
|
||||
return changes;
|
||||
}
|
||||
if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
|
||||
var val, changed = false, old = this._previousAttributes;
|
||||
for (var attr in diff) {
|
||||
if (_.isEqual(old[attr], (val = diff[attr]))) continue;
|
||||
|
||||
Reference in New Issue
Block a user