Skip to content

Instantly share code, notes, and snippets.

@dcporter
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dcporter/89e86a12075a4d45c014 to your computer and use it in GitHub Desktop.
Save dcporter/89e86a12075a4d45c014 to your computer and use it in GitHub Desktop.
An ArrayController which exposes each content item wrapped in a proxy class.
// ==========================================================================
// Project: SC.ProxiedArrayController
// Copyright: ©2014 My Company, Inc.
// ==========================================================================
/*globals SC */
/** @class
This controller implements an experimental ArrayController pattern which wraps each item in a
controller object when retrieved.
TO ADD: Selection support.
@extends SC.ArrayController
*/
SC.ProxiedArrayController = SC.ArrayController.extend({
/**
The proxy class, usually a subclass of SC.ObjectController.
If specified, each item in this controller's content array will be wrapped in an instance
of this class and exposed via the standard objectAt and arrangedObjects properties. The
content object will be set to the proxy object's `content` property, and this array
controller will be set to its `source` property. Its `isArrayContentProxy` property will
be set to YES.
If not specified, SC.ProxiedArrayController behaves as a standard ArrayController.
If you need to provide different proxy classes depending on the content object, you
should override proxyClassForContentObject instead.
@type class
*/
Proxy: null,
/**
Returns a proxy class for the specified content object. The default implementation returns
this controller's `Proxy` property. You may override it to provide a more granular approach,
for example returning different proxy classes depending on the content object's record type.
@param {SC.Object} contentObject
@returns class
*/
proxyClassForContentObject: function(contentObject) {
return this.get('Proxy');
},
/** @private */
indexOf: function (object, startAt) {
var content = this._scac_observableContent();
// If this is a wrapped object, compare its content.
if (object.isArrayContentProxy) object = object.get('content');
return content ? content.indexOf(object, startAt) : -1;
},
/** @private Override objectAt to return items wrapped in an instance of our Proxy class. */
objectAt: function (index) {
var content = this._scac_observableContent(),
ret = null,
cache, Proxy, contentObject, guid;
// FAST PATH: No content.
if (!content) { return ret; }
contentObject = content.objectAt(index);
// FAST PATH: No contentObject.
if (!contentObject) { return ret; }
guid = SC.guidFor(contentObject);
cache = (this._scac_proxyCache ? this._scac_proxyCache : (this._scac_proxyCache = {}));
// Check cache.
if (cache[guid]) {
ret = cache[guid];
}
// Otherwise, create and cache the wrapper.
else {
Proxy = this.proxyClassForContentObject(contentObject);
//@if(debug)
// Provide some developer support for non-class Proxies.
if (!Proxy.isClass) SC.error("SC.ProxiedArrayController proxy class must be a class.");
//@endif
// TODO: Pool proxy objects (per proxy class of course).
ret = cache[guid] = Proxy.create({
isArrayContentProxy: YES,
content: contentObject,
source: this
});
}
return ret;
},
/** @private Invalidate the cache whenever the content array object swaps out. */
_scac_contentDidChange: function() {
// TODO: Transfer any proxy objects found in the new content array over to the new cache.
// Snag the previous list's cached proxy items, if any.
var cache = this._scac_proxyCache;
this._scac_proxyCache = null;
// Run the standard ArrayController changeover. This helps clear the proxy items out of the
// controller graph and the view layer before we destroy them.
sc_super();
if (cache) {
var key, proxyObject;
for (key in cache) {
proxyObject = cache[key];
if (!proxyObject || !proxyObject.isArrayContentProxy) continue;
proxyObject.set('content', null);
proxyObject.destroy();
}
}
}.observes('content')
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment