Created
April 18, 2012 12:49
-
-
Save yurtaev/2413383 to your computer and use it in GitHub Desktop.
Support nested id's for backbone.js Model
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(Backbone){ | |
// Helper function to accessing nested JavaScript objects with string key | |
// via. http://stackoverflow.com/a/6491621 | |
var byString = function(object, stringKey) { | |
stringKey = stringKey.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties | |
stringKey = stringKey.replace(/^\./, ''); // strip a leading dot | |
var a = stringKey.split('.'); | |
while (a.length) { | |
var n = a.shift(); | |
if (n in object) { | |
object = object[n]; | |
} else { | |
return; | |
} | |
} | |
return object; | |
}; | |
// Helper function to test the existence of multiple levels | |
// via. http://stackoverflow.com/a/2631198 | |
var checkNested = function(obj, args) { | |
for (var i = 0; i < args.length; i++) { | |
if (!obj.hasOwnProperty(args[i])) { | |
return false; | |
} | |
obj = obj[args[i]]; | |
} | |
return true; | |
}; | |
ModelNestedID = Backbone.Model.extend({ | |
set: function(key, value, options) { | |
var attrs, attr, val; | |
// Handle both `"key", value` and `{key: value}` -style arguments. | |
if (_.isObject(key) || key == null) { | |
attrs = key; | |
options = value; | |
} else { | |
attrs = {}; | |
attrs[key] = value; | |
} | |
// Extract attributes and options. | |
options || (options = {}); | |
if (!attrs) return this; | |
if (attrs instanceof Backbone.Model) attrs = attrs.attributes; | |
if (options.unset) for (attr in attrs) attrs[attr] = void 0; | |
// Run validation. | |
if (!this._validate(attrs, options)) return false; | |
// Check for changes of `id`. | |
if (checkNested(attrs, this.idAttribute.split('.'))) this.id = byString(attrs, this.idAttribute); | |
var changes = options.changes = {}; | |
var now = this.attributes; | |
var escaped = this._escapedAttributes; | |
var prev = this._previousAttributes || {}; | |
// For each `set` attribute... | |
for (attr in attrs) { | |
val = attrs[attr]; | |
// If the new and current value differ, record the change. | |
if (!_.isEqual(now[attr], val) || (options.unset && _.has(now, attr))) { | |
delete escaped[attr]; | |
(options.silent ? this._silent : changes)[attr] = true; | |
} | |
// Update or delete the current value. | |
options.unset ? delete now[attr] : now[attr] = val; | |
// 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] = val; | |
if (!options.silent) this._pending[attr] = true; | |
} else { | |
delete this.changed[attr]; | |
delete this._pending[attr]; | |
} | |
} | |
// Fire the `"change"` events. | |
if (!options.silent) this.change(options); | |
return this; | |
} | |
}); | |
Backbone.Model = ModelNestedID; | |
})(Backbone); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment