Created
December 12, 2017 16:10
-
-
Save markerikson/33353b696418dce9fba5cf570e51f0ec to your computer and use it in GitHub Desktop.
Backbone / Ampersand compatibility shims
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
// Ampersand-State doesn't mix in Underscore methods the way Backbone.Model does. | |
// Technically it could also be done as a standalone mixin, but we'll do that here. | |
var modelMethods = ['keys', 'values', 'pairs', 'invert', 'pick', 'omit']; | |
// Mix in each Underscore method as a proxy to `Model#attributes`. | |
_.each(modelMethods, function(method) { | |
State.prototype[method] = function() { | |
var args = [].slice.call(arguments); | |
args.unshift(this.attributes); | |
return _[method].apply(_, args); | |
}; | |
}); | |
// State doesn't include has() like BB.Model - add it in | |
State.prototype.has = function(attr) { | |
return this.get(attr) != null; | |
}; | |
// Override the default toJSON() implementation to allow compatibility with BB.Epoxy | |
State.prototype.toJSON = function(options) { | |
var originalData = this.serialize(); | |
// Epoxy passes in "{computed : true}" when it tries to determine what attributes | |
// are available on a Model instance, since that's what Epoxy.Model uses. | |
// State, however, uses "derived" instead of "computed", and also has "session" fields. | |
// This fix allows Epoxy binding to work with State instances that have derived/session attributes. | |
if(options && options.computed) | |
{ | |
_.extend(originalData, this.getAttributes({derived: true, session: true})); | |
} | |
return originalData; | |
}; | |
// Add a string to State that we can use to help identify this as a valid Model instance | |
// when adding to a BB.Collection | |
State.prototype.modelType = "model"; | |
// State has built-in support for fields containing JS primitives, JS objects, and other State | |
// instances, but not BB.Collections. Add a new "collection" datatype so that a State containing a | |
// nested Collection instance will properly bubble up events to the parent State. | |
State = State.extend({ | |
dataTypes : { | |
collection : { | |
"set": function (newVal) { | |
var isInstance = _.result(newVal, "getType") == "collection"; | |
if (isInstance) { | |
return { | |
val: newVal, | |
type: 'collection' | |
}; | |
} else { | |
return { | |
val: newVal, | |
type: typeof newVal | |
}; | |
} | |
}, | |
compare: function (currentVal, newVal, attributeName) { | |
var isSame = currentVal === newVal; | |
// if this has changed we want to also handle | |
// event propagation | |
if (!isSame) { | |
if (currentVal) { | |
this.stopListening(currentVal); | |
} | |
if (newVal != null) { | |
this.listenTo(newVal, 'all', this._getEventBubblingHandler(attributeName)); | |
} | |
} | |
return isSame; | |
} | |
} | |
} | |
}); | |
return { | |
State : State | |
}; |
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
// Add hooks for compatibility between Backbone and Ampersand | |
Backbone.Model.prototype.getType = function() { | |
return "model"; | |
}; | |
Backbone.Model.prototype.isState = true; | |
Backbone.Collection.prototype.getType = function() { | |
return "collection"; | |
}; | |
// Override the default _isModel() function to determine if an item is a valid model | |
// based on our custom "getType" values rather than the normal "instanceof Model" check. | |
// This will allow us to store both BB.Models and amp.States with no issues. | |
Backbone.Collection.prototype._isModel = function(model) { | |
return _.result(model, "getType") == "model"; | |
}; | |
// amp.State tries to call serialize() on its nested "children" and "collections", so | |
// add these for compatibility. | |
Backbone.Model.prototype.serialize = function() { | |
return this.toJSON(); | |
}; | |
Backbone.Collection.prototype.serialize = function() { | |
return this.toJSON(); | |
}; | |
Backbone.Model.prototype.getId = function () { | |
return this[this.idAttribute]; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment