Skip to content

Instantly share code, notes, and snippets.

@radist2s
Created October 9, 2014 14:12
Show Gist options
  • Save radist2s/3568002b79dacbf708ab to your computer and use it in GitHub Desktop.
Save radist2s/3568002b79dacbf708ab to your computer and use it in GitHub Desktop.
Backbone Model previousAttributes() delta
Backbone.Model.prototype.set = function(key, val, options) {
var attr, attrs, unset, changes, silent, changing, prev, current;
if (key == null) return this;
// Handle both `"key", value` and `{key: value}` -style arguments.
if (typeof key === 'object') {
attrs = key;
options = val;
} else {
(attrs = {})[key] = val;
}
options || (options = {});
// Run validation.
if (!this._validate(attrs, options)) return false;
// Extract attributes and options.
unset = options.unset;
silent = options.silent;
changes = [];
changing = this._changing;
this._changing = true;
if (!changing) {
var attributesCopy = _.clone(this.attributes),
changedAttributesKeys = _.keys(attrs);
this._previousAttributes = this._previousAttributes || {};
_.each(changedAttributesKeys, function (key) {
if (_.has(attributesCopy, key) && !_.isEqual(attributesCopy[key], attrs[key])) {
this._previousAttributes[key] = attributesCopy[key]
}
}, this)
//this._previousAttributes = _.clone(this.attributes); // default bb funct
this.changed = {};
}
current = this.attributes, prev = this._previousAttributes;
// Check for changes of `id`.
if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
// For each `set` attribute, update or delete the current value.
for (attr in attrs) {
val = attrs[attr];
if (!_.isEqual(current[attr], val)) changes.push(attr);
if (!_.isEqual(prev[attr], val)) {
this.changed[attr] = val;
} else {
delete this.changed[attr];
}
unset ? delete current[attr] : current[attr] = val;
}
// Trigger all relevant attribute changes.
if (!silent) {
if (changes.length) this._pending = options;
for (var i = 0, l = changes.length; i < l; i++) {
this.trigger('change:' + changes[i], this, current[changes[i]], options);
}
}
// You might be wondering why there's a `while` loop here. Changes can
// be recursively nested within `"change"` events.
if (changing) return this;
if (!silent) {
while (this._pending) {
options = this._pending;
this._pending = false;
this.trigger('change', this, options);
}
}
this._pending = false;
this._changing = false;
return this;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment