Last active
August 29, 2015 14:03
-
-
Save dcporter/89e86a12075a4d45c014 to your computer and use it in GitHub Desktop.
An ArrayController which exposes each content item wrapped in a proxy class.
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
// ========================================================================== | |
// 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