PDA

View Full Version : New Class: Ext.ux.icc -- "interclass communication channel"



willf1976
21 Sep 2009, 2:34 PM
Hi All

I recently ran into a problem where I was attempting to spawn multiple windows at once each one containing its own set of components that needed to be able to communicate with each other with in the window and be able to pass messages between windows. Further more some of the windows had to be instances of the same set of components so just using the component manager to find objects on the page wasn't an option and I didn't find relayEvents to be that convenient to use for these purposes.

The solution I came up with is something I am calling an: icc -- interclass communication channel. Its a very simple concept but I think it will make for a lot of convince in how I write my code.

The channels can be dynamically created and are stored in a manager system that is almost identical component manager -- use Ext.ux.getIcc to find channels the same way you would use Ext.getCmp to find components.

Each channel that is created has several features:

All components that share the same channel and have the Ext.ux.Component.SubcribeIcc plugin are stored on a component manager that is specific to the channel -- allowing the components with in the channel to keep tabs on each other.

Components may have more than one channel (in order to provide additional channels for between window communications).

Channels may have child channels (stored in a collection called: children,l), so you can nest them together if need be.

Channels have a collection called 'props' -- these properties are mean to be used in the same sort of way one would use global variables, except these properties are set directly on the channel so they won't be polluting the global name space.

Channels also have a simple observable object called: broadcast. This object is there to attach events and listeners to so multiple components can subscribe to events sent out across the channel.

Channels have several convenience functions to give you easy access to the collections they store (see the in class documentation for more details).

Please let me know any comments you have or bugs you might find.

Best Regards

Will Ferrer



/*
author: Will Ferrer
date: 09/21/09
history:
09/21/09 -- posted to extJs forums
10/06/09 -- added autoDestroyIcc functionality. This can be used to prevent potential memory leak problems by destroying the icc when it is no longer needed.
*/
/**
* @class Ext.ux.iccMgr
* @singleton
* @extends Object
* A stripped down version of the component manager in order to keep track of iccs (interclass communication channels)
* @constructor
* @param {Object} config The config object
*/
Ext.ns('Ext.ux');
Ext.ux.iccMgr = function(){
return {
/**
* Registers a icc.
* @param {Ext.icc} c The icc
*/
register : function(c){
this.all.add(c);
},

/**
* Unregisters a icc.
* @param {Ext.icc} c The icc
*/
unregister : function(c){
this.all.remove(c);
},

/**
* Returns a icc by {@link Ext.icc#id id}.
* For additional details see {@link Ext.util.MixedCollection#get}.
* @param {String} id The icc {@link Ext.icc#id id}
* @return Ext.icc The icc, <tt>undefined</tt> if not found, or <tt>null</tt> if a
* Class was found.
*/
get : function(id){
return this.all.get(id);
},

/**
* Registers a function that will be called when a specified icc is added to iccMgr
* @param {String} id The icc {@link Ext.icc#id id}
* @param {Function} fn The callback function
* @param {Object} scope The scope of the callback
*/
onAvailable : function(id, fn, scope){
this.all.on("add", function(index, o){
if(o.id == id){
fn.call(scope || o, o);
this.all.un("add", fn, scope);
}
});
},

/**
* The MixedCollection used internally for the icc cache. An example usage may be subscribing to
* events on the MixedCollection to monitor addition or removal. Read-only.
* @type {MixedCollection}
*/
all : new Ext.util.MixedCollection(),

/**
* Creates a new icc from the specified config object using the
* config object's {@link Ext.icc#xtype xtype} to determine the class to instantiate.
* @param {Object} config A configuration object for the icc you wish to create.
* @param {Constructor} defaultType The constructor to provide the default icc type if
* the config object does not contain a <tt>xtype</tt>. (Optional if the config contains a <tt>xtype</tt>).
* @return {Ext.icc} The newly instantiated icc.
*/
create : function(config, defaultType){
return new types[config.xtype || defaultType](config);
}
}
}();
Ext.ux.getIcc = Ext.ux.iccMgr.get;

/**
* @class Ext.ux.icc
* @extends Ext.util.Observable
* icc stands for: interclass communication channel.
* This is an observable class with 3 MixedColletions and 1 observable:
* cmps -- stores the components that are subscribed to this icc
* children -- child iccs for this object
* props -- properties to be stored and accessed by components that subcrive to this icc
* broadcast -- this is a simple observable object intended to have custom events and listeners applied to it
* Also contained is an observable object called broadcast. You may set what ever events and listeners you like on broadcast.
* @constructor
* @param {Object} config The config object
* @ptype ux-icc
*/
Ext.ux.icc = function(config){
Ext.apply(this, config);
Ext.ux.icc.superclass.constructor.call(this);

this.id = (this.id)?this.id:this.name + '-' + (Ext.Component.AUTO_ID++);

Ext.ux.iccMgr.register(this);

this.addEvents(
//Cmps:
/**
* @event beforegetcmp
* Fires before an item is retrieved from the collection. You may return false to return a value of null to the callingObj
* @param {String} key The key associated with the item to retrieve.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'beforegetcmp',
/**
* @event aftergetcmp
* Fires when an item is retrieved from the collection.
* @param {String} key The key associated with the added item retrieved.
* @param {Object} o The item retrieved.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'aftergetcmp',
/**
* @event beforeaddcmp
* Fires before an item is added to the collection. You may return an object to replace the object to be added or you may return false to cancel the operation.
* @param {String} key The key associated with the item to add.
* @param {Object} o The item to add.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'beforeaddcmp',
/**
* @event afteraddcmp
* Fires when an item is added to the collection -- same as [iccName].cmps.add event
* @param {Number} index The index at which the item was added.
* @param {String} key The key associated with the added item.
* @param {Object} o The item added.
* @param {Ext.ux.icc} this The icc
*/
'afteraddcmp',
/**
* @event beforeclearcmps
* Fires before the collection is cleared. You may return false to cancel the operation.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'beforeclearcmps',
/**
* @event afterclearcmps
* Fires when the collection is cleared -- same as [iccName].cmps.clear event
* @param {Boolean} cleared True or false
* @param {Ext.ux.icc} this The icc
*/
'afterclearcmps',
/**
* @event beforeremovecmp
* Fires before an item is removed from the collection. You may return another object to remove or you may return false to cancel the operation.
* @param {Object} o The item to remove.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'beforeremovecmp',
/**
* @event afterremovecmp
* Fires when an item is removed from the collection -- same as [iccName].cmps.remove event
* @param {String} key The key associated with the item to remove.
* @param {Object} o The item removed.
* @param {Ext.ux.icc} this The icc
*/
'afterremovecmp',
/**
* @event beforereplacecmp
* Fires before an item is replaced in the collection. You may return an object to replace or you may return false to cancel the operation.
* @param {String} key The key associated with the item to replace.
* @param {Object} o The item to replace.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'beforereplacecmp',
/**
* @event afterreplacecmp
* Fires when an item is replaced in the collection. -- same as [iccName].cmps.replace event
* @param {String} key The key associated with the newly added cmp.
* @param {Object} oldObj The item being replaced.
* @param {Object} newObj The new item.
* @param {Ext.ux.icc} this The icc
*/
'afterreplacecmp',
//Children:
/**
* @event beforegetchild
* Fires before an item is retrieved from the collection. You may return false to return a value of null to the callingObj
* @param {String} key The key associated with the item to retrieve.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'beforegetchild',
/**
* @event aftergetchild
* Fires when an item is retrieved from the collection.
* @param {String} key The key associated with the added item retrieved.
* @param {Object} o The item retrieved.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'aftergetchild',
/**
* @event beforeaddchild
* Fires before an item is added to the collection. You may return an object to replace the object to be added or you may return false to cancel the operation.
* @param {String} key The key associated with the item to add.
* @param {Object} o The item to add.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'beforeaddchild',
/**
* @event afteraddchild
* Fires when an item is added to the collection -- same as [iccName].children.add event
* @param {Number} index The index at which the item was added.
* @param {String} key The key associated with the added item.
* @param {Object} o The item added.
* @param {Ext.ux.icc} this The icc
*/
'afteraddchild',
/**
* @event beforeclearchildren
* Fires before the collection is cleared. You may return false to cancel the operation.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'beforeclearchildren',
/**
* @event afterclearchildren
* Fires when the collection is cleared -- same as [iccName].children.clear event
* @param {Boolean} cleared True or false
* @param {Ext.ux.icc} this The icc
*/
'afterclearchildren',
/**
* @event beforeremovechild
* Fires before an item is removed from the collection. You may return another object to remove or you may return false to cancel the operation.
* @param {Object} o The item to remove.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'beforeremovechild',
/**
* @event afterremovechild
* Fires when an item is removed from the collection -- same as [iccName].children.remove event
* @param {String} key The key associated with the item to remove.
* @param {Object} o The item removed.
* @param {Ext.ux.icc} this The icc
*/
'afterremovechild',
/**
* @event beforereplacechild
* Fires before an item is replaced in the collection. You may return an object to replace or you may return false to cancel the operation.
* @param {String} key The key associated with the item to replace.
* @param {Object} o The item to replace.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'beforereplacechild',
/**
* @event afterreplacechild
* Fires when an item is replaced in the collection. -- same as [iccName].children.replace event
* @param {String} key The key associated with the newly added child.
* @param {Object} oldObj The item being replaced.
* @param {Object} newObj The new item.
* @param {Ext.ux.icc} this The icc
*/
'afterreplacechild',
//Props:
/**
* @event beforegetprop
* Fires before an item is retrieved from the collection. You may return false to return a value of null to the callingObj
* @param {String} key The key associated with the item to retrieve.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'beforegetprop',
/**
* @event aftergetprop
* Fires when an item is retrieved from the collection.
* @param {String} key The key associated with the added item retrieved.
* @param {Object} o The item retrieved.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'aftergetprop',
/**
* @event beforeaddprop
* Fires before an item is added to the collection. You may return an object to replace the object to be added or you may return false to cancel the operation.
* @param {String} key The key associated with the item to add.
* @param {Object} o The item to add.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'beforeaddprop',
/**
* @event afteraddprop
* Fires when an item is added to the collection -- same as [iccName].props.add event
* @param {Number} index The index at which the item was added.
* @param {String} key The key associated with the added item.
* @param {Object} o The item added.
* @param {Ext.ux.icc} this The icc
*/
'afteraddprop',
/**
* @event beforeclearprops
* Fires before the collection is cleared. You may return false to cancel the operation.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'beforeclearprops',
/**
* @event afterclearprops
* Fires when the collection is cleared -- same as [iccName].props.clear event
* @param {Boolean} cleared True or false
* @param {Ext.ux.icc} this The icc
*/
'afterclearprops',
/**
* @event beforeremoveprop
* Fires before an item is removed from the collection. You may return another object to remove or you may return false to cancel the operation.
* @param {Object} o The item to remove.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'beforeremoveprop',
/**
* @event afterremoveprop
* Fires when an item is removed from the collection -- same as [iccName].props.remove event
* @param {String} key The key associated with the item to remove.
* @param {Object} o The item removed.
* @param {Ext.ux.icc} this The icc
*/
'afterremoveprop',
/**
* @event beforereplaceprop
* Fires before an item is replaced in the collection. You may return an object to replace or you may return false to cancel the operation.
* @param {String} key The key associated with the item to replace.
* @param {Object} o The item to replace.
* @param {Ext.ux.icc} this The icc
* @param {Object} callingObj The Object that made the request
*/
'beforereplaceprop',
/**
* @event afterreplaceprop
* Fires when an item is replaced in the collection. -- same as [iccName].props.replace event
* @param {String} key The key associated with the newly added prop.
* @param {Object} oldObj The item being replaced.
* @param {Object} newObj The new item.
* @param {Ext.ux.icc} this The icc
*/
'afterreplaceprop',
/**
* @event beforedestroy
* Fires before the icc is destroyed. Return false to cancel the operation.
* @param {Ext.ux.icc} this The icc
*/
'beforedestroy',
/**
* @event afterdestroy
* Fires before the icc is destroyed
* @param {Ext.ux.icc} this The icc
*/
'afterdestroy'
);

this.cmps.on('add', function(index, o, key){
this.fireEvent("afteraddcmp", index, key, o, this);
}, this);
this.cmps.on('clear', function(){
this.fireEvent("afterclearcmps", this);
}, this);
this.cmps.on('remove', function(o, key){
this.fireEvent("afterremovecmp", key, o, this);
}, this);
this.cmps.on('replace', function(key, oldObj, newObj){
this.fireEvent("afterreplacecmp", key, oldObj, newObj, this);
}, this);

this.children.on('add', function(index, o, key){
this.fireEvent("afteraddchild", index, key, o, this);
}, this);
this.children.on('clear', function(){
this.fireEvent("afterclearchildren", this);
}, this);
this.children.on('remove', function(o, key){
this.fireEvent("afterremovechild", key, o, this);
}, this);
this.children.on('replace', function(key, oldObj, newObj){
this.fireEvent("afterreplacechild", key, oldObj, newObj, this);
}, this);

this.props.on('add', function(index, o, key){
this.fireEvent("afteraddprop", index, key, o, this);
}, this);
this.props.on('clear', function(){
this.fireEvent("afterclearprops", this);
}, this);
this.props.on('remove', function(o, key){
this.fireEvent("afterremoveprop", key, o, this);
}, this);
this.props.on('replace', function(key, oldObj, newObj){
this.fireEvent("afterreplaceprop", key, oldObj, newObj, this);
}, this);

this.on('afterremovecmp', this.onAfterRemoveCmp, this);

if (this.broadcastEvents) {
this.broadcast.addEvents(this.broadcastEvents);
}
};
Ext.extend(Ext.ux.icc, Ext.util.Observable, {
//Public Properties:
/**
* @cfg {String} id
* The id of the icc -- If no id is set then a unique id will be created using name + a unique number. Defaults to null
*/
id : null,
/**
* @cfg {String} name
* The name of the icc -- If no id is set then a unique id will be created using name + a unique number. Defaults to 'ext-ux-icc'.
*/
name : 'ext-ux-icc',
/**
* @cfg {Array|Null} broadcastEvents
* Events to automatically add to broadcast -- include an array of Strings (name of each event). Defaults to null.
*/
broadcastEvents : null,
/**
* @cfg {Boolean} autoDestroyIcc
* Whether or not to destroy the icc when there no components left in its cmps collection. Defaults to false.
*/
autoDestroyIcc : false,
//Private Properties:
/**
* @private internal config {String} cmps
* MixedCollection used to store components that are on this icc. Defaults to new Ext.util.MixedCollection().
*/
cmps : new Ext.util.MixedCollection(),
/**
* @private internal config {String} children
* MixedCollection used to store child iccs. Defaults to new Ext.util.MixedCollection().
*/
children : new Ext.util.MixedCollection(),
/**
* @private internal config {String} props
* MixedCollection used to store properties on this icc. Defaults to new Ext.util.MixedCollection().
*/
props : new Ext.util.MixedCollection(),
/**
* @private internal config {String} broadcast
* A observable object used to store custom events for the icc. Defaults to new Ext.util.Observable().
*/
broadcast : new Ext.util.Observable(),
//Public Functions:
//Cmps:
/** Public Function: getCmp
* Gets an item from the cmps collection -- Relays request to getItem
* @param {String} key (Required) The key to associate with the item.
* @return {Object|Null} item The item retrieved or null if no item was retrieved
*/
getCmp : function (key, callingObj) {
return this.getItem('cmps', 'cmp', key, callingObj);
},
/** Public Function: addCmp
* Add an items to the cmps collection -- Relays request to addItem
* @param {String} key (Required) The key to associate with the item.
* @param {Object} o (Required) The item to add.
* @param {Object} callingObj (Optional) The object making the request -- passed to listeners
* @return {Object|Null} newItem The item added or null if no item was added
*/
addCmp : function (key, o, callingObj) {
return this.addItem('cmps', 'cmp', key, o, callingObj);
},
/** Public Function: clearCmps
* clears all items in cmps colletion -- relayed request to clearItems
* @param {Object} callingObj (Optional) The object making the request -- passed to listeners
* @return {Boolean} cleared True or false
*/
clearCmps : function (callingObj) {
return this.clearItems('cmps', callingObj);
},
/** Public Function: removeCmp
* Remove an item from the cmps collection -- relays request to removeItem
* @param {Object} o (Required) The item to remove.
* @param {Object} callingObj (Optional) The object making the request -- passed to listeners
* @return {Object|Null} removedItem The item removed or null if no item was removed
*/
removeCmp : function (o, callingObj) {
return this.removeItem('cmps', 'cmp', o, callingObj);
},
/** Public Function: replaceCmp
* Replace an item in the cmps collection -- relays request to replaceItem
* @param {String} key (Required) The key associated with the item to replace, or the replacement item.
* @param {Object} o (Optional) If the first parameter passed was a key, the item to associate with that key.
* @param {Object} callingObj (Optional) The object making the request -- passed to listeners
* @return {Object|Boolean} newItem The item created or false if no item was added
*/
replaceCmp : function (key, o, callingObj) {
return this.replaceItem('cmps', 'cmp', key, o, callingObj);
},
//Children:
/** Public Function: getChild
* Gets an item from the children collection -- Relays request to getItem
* @param {String} key (Required) The key to associate with the item.
* @return {Object|Null} item The item retrieved or null if no item was retrieved
*/
getChild : function (key, callingObj) {
return this.getItem('children', 'child', key, callingObj);
},
/** Public Function: addChild
* Add an items to the children collection -- Relays request to addItem
* @param {String} key (Required) The key to associate with the item.
* @param {Object} o (Required) The item to add.
* @param {Object} callingObj (Optional) The object making the request -- passed to listeners
* @return {Object|Null} newItem The item added or null if no item was added
*/
addChild : function (key, o, callingObj) {
return this.addItem('children', 'child', key, o, callingObj);
},
/** Public Function: clearChilds
* clears all items in children colletion -- relayed request to clearItems
* @param {Object} callingObj (Optional) The object making the request -- passed to listeners
* @return {Boolean} cleared True or false
*/
clearChilds : function (callingObj) {
return this.clearItems('children', callingObj);
},
/** Public Function: removeChild
* Remove an item from the children collection -- relays request to removeItem
* @param {Object} o (Required) The item to remove.
* @param {Object} callingObj (Optional) The object making the request -- passed to listeners
* @return {Object|Null} removedItem The item removed or null if no item was removed
*/
removeChild : function (o, callingObj) {
return this.removeItem('children', 'child', o, callingObj);
},
/** Public Function: replaceChild
* Replace an item in the children collection -- relays request to replaceItem
* @param {String} key (Required) The key associated with the item to replace, or the replacement item.
* @param {Object} o (Optional) If the first parameter passed was a key, the item to associate with that key.
* @param {Object} callingObj (Optional) The object making the request -- passed to listeners
* @return {Object|Boolean} newItem The item created or false if no item was added
*/
replaceChild : function (key, o, callingObj) {
return this.replaceItem('children', 'child', key, o, callingObj);
},
//Props:
/** Public Function: getProp
* Gets an item from the props collection -- Relays request to getItem
* @param {String} key (Required) The key to associate with the item.
* @return {Object|Null} item The item retrieved or null if no item was retrieved
*/
getProp : function (key, callingObj) {
return this.getItem('props', 'prop', key, callingObj);
},
/** Public Function: addProp
* Add an items to the props collection -- Relays request to addItem. setProp is prefered method.
* @param {String} key (Required) The key to associate with the item.
* @param {Object} o (Required) The item to add.
* @param {Object} callingObj (Optional) The object making the request -- passed to listeners
* @return {Object|Null} newItem The item added or null if no item was added
*/
addProp : function (key, o, callingObj) {
return this.addItem('props', 'prop', key, o, callingObj);
},
/** Public Function: clearProps
* clears all items in props colletion -- relayed request to clearItems
* @param {Object} callingObj (Optional) The object making the request -- passed to listeners
* @return {Boolean} cleared True or false
*/
clearProps : function (callingObj) {
return this.clearItems('props', callingObj);
},
/** Public Function: removeProp
* Remove an item from the props collection -- relays request to removeItem
* @param {Object} o (Required) The item to remove.
* @param {Object} callingObj (Optional) The object making the request -- passed to listeners
* @return {Object|Null} removedItem The item removed or null if no item was removed
*/
removeProp : function (o, callingObj) {
return this.removeItem('props', 'prop', o, callingObj);
},
/** Public Function: replaceProp
* Replace an item in the props collection -- relays request to replaceItem. setProp is prefered method.
* @param {String} key (Required) The key associated with the item to replace, or the replacement item.
* @param {Object} o (Optional) If the first parameter passed was a key, the item to associate with that key.
* @param {Object} callingObj (Optional) The object making the request -- passed to listeners
* @return {Object|Boolean} newItem The item created or false if no item was added
*/
replaceProp : function (key, o, callingObj) {
return this.replaceItem('props', 'prop', key, o, callingObj);
},
/** Public Function: setProp
* Replace an item in the props collection -- relays request to replaceItem
* @param {String} key (Required) The key associated with the item to replace, or the replacement item.
* @param {Object} o (Required) If the first parameter passed was a key, the item to associate with that key.
* @param {Object} callingObj (Optional) The object making the request -- passed to listeners
* @return {Object|Boolean} newItem The item created or false if no item was added
*/
setProp : function (key, o, callingObj) {
return this.replaceItem('props', 'prop', key, o, callingObj);
},
//Other:
/** Public Function: destroy
* Destroys this icc by purging it from the iccMgr
* should usually not need to be called directly.
* @return {Boolean} whether or not the item was destroyed
*/
destroy : function(){
if(this.fireEvent('beforedestroy', this) !== false){
Ext.ux.iccMgr.unregister(this);
this.fireEvent('afterdestroy', this);
return true;
}
return false;
},
//Private Functions:
// @private
getItem : function (collectionName, itemName, key, callingObj) {
var result = this.fireEvent("beforeget" + itemName, key, this, callingObj),
item;
if (result) {
item = this[collectionName].get(key);
this.fireEvent("afterget" + itemName, key, item, this, callingObj);
} else {
item = null;
}
return item;
},
// @private
addItem : function (collectionName, itemName, key, o, callingObj) {
var result = this.fireEvent("beforeadd" + itemName, key, o, this, callingObj),
item,
newItem;
if (result) {
item = (Ext.isObject(result))?result:o;
newItem = (!Ext.isEmpty(item))?this[collectionName].add(key, item):this[collectionName].add(key);
} else {
newItem = null;
}
return newItem;
},
// @private
clearItems : function (collectionName, callingObj) {
var result = this.fireEvent("beforeclear" + collectionName, this, callingObj),
cleared;
if (result) {
cleared = true;
this[collectionName].clear();
} else {
cleared = false;
}
return cleared;
},
// @private
removeItem : function (collectionName, itemName, o, callingObj) {
var result = this.fireEvent("beforeremove" + itemName, o, this, callingObj),
item,
removedItem;
if (result) {
item = (Ext.isObject(result))?result:o;
removedItem = this[collectionName].remove(item);
} else {
removedItem = null;
}
return removedItem;
},
// @private
replaceItem : function (collectionName, itemName, key, o, callingObj) {
var result = this.fireEvent("beforereplace" + itemName, key, o, this, callingObj),
item,
newItem;
if (result) {
item = (Ext.isObject(result))?result:o;
newItem = (!Ext.isEmpty(item))?this[collectionName].replace(key, item):this[collectionName].replace(key);
} else {
newItem = null;
}
return newItem;
},
//@private
onAfterRemoveCmp : function (key, o, target) {
if (this.autoDestroyIcc && !this.cmps.getCount()) {
this.destroy();
}
}
});
Ext.reg('ux-icc', Ext.ux.icc);


/**
* @class Ext.ux.Component.SubcribeIcc
* @extends Ext.util.Observable
* A plug in that allows you to set an icc on the component. Also will search for an icc on the ownerCts of the component if none is found it will register the component in the icc.cmps collections.
* Plugin also adds the functions: searchIcc, setIcc, getIcc on its parent component
* @param {Object} config The config object
* @ptype ux-component-subcribeicc
*
*/
Ext.ns('Ext.ux.Component');
Ext.ux.Component.SubcribeIcc = function(config){
Ext.apply(this, config);
Ext.ux.Component.SubcribeIcc.superclass.constructor.call(this);
};
Ext.extend(Ext.ux.Component.SubcribeIcc, Ext.util.Observable, {
//Public Properties:
/**
* @cfg {Ext.ux.icc} icc
* The icc applied to the plug in. If none is provided an icc will be searched for on the parent and then on the ownerCt of the parent, etc (by default behaviour). Finaly if no icc is found one will be created and set on the plugin. Defaults to null.
*/
icc : null,
/**
* @cfg {String} iccPropName
* Property name to apply the icc to on the parent, also used when searching for an icc on a parent or else where -- plugin may be added more than once and apply to multiple properties on the parent with different iccs. Defaults to 'icc'.
*/
iccPropName : 'icc',
/**
* @cfg {Boolean} searchOwnerCt
* Look for a icc on the ownerCt if one is not found on the object or the plugin. Defaults to true.
*/
searchOwnerCt : true,
/**
* @cfg {Boolean} registerComponent
* Register the component on the icc. Defaults to true.
*/
registerComponent : true,
/**
* @cfg {Boolean} mainIcc
* If this plugin is set to have the mainIcc then it will add a link to its self called: mainIccPlugin to its parent object -- this is referanced by some of the functions that are added to the parent. Defaults to true.
*/
mainIcc : true,
//Public Functions:
/** Public Function: searchIcc
* Searchs for the icc on the parent of the plug in, looking upwards on the ownerCt of the parent. May also be called on the component it's self.
* @param {String} iccPropName (Optional) The property name to the icc is stored on. Defaults to this.iccPropName or this.mainIccPlugin.iccPropName.
* @param {String} target (Optional) The target to search for the icc on. Defaults to this.parent or this.
* @return {Ext.ux.icc|Null} icc The icc that was found or null
*/
searchIcc : function (iccPropName, target) {
var icc = null,
iccPropName = (!Ext.isEmpty(iccPropName))?iccPropName:this.iccPropName,
iccPropName = (!Ext.isEmpty(iccPropName))?iccPropName:this.mainIccPlugin.iccPropName,
target = (!Ext.isEmpty(target))?target:this.parent,
target = (!Ext.isEmpty(target))?target:this;

if (!Ext.isEmpty(target)) {
while (!Ext.isEmpty(target.ownerCt) || !Ext.isEmpty(target[iccPropName])) {
if (!Ext.isEmpty(target[iccPropName])) {
icc = target[iccPropName];
break;
}
target = target.ownerCt;
}
}
return icc;
},
/** Public Function: setIcc
* Sets the icc on the plugin and it's parent. May also be called on the component it's self.
* @param {Ext.ux.icc} icc The icc to set. Defaults to new Ext.ux.icc()
* @param {String} iccPropName (Optional) The property name to the icc is stored on. Defaults to this.iccPropName or this.mainIccPlugin.iccPropName.
* @return {Ext.ux.icc} icc The icc that was set.
*/
setIcc : function (icc, iccPropName) {
var icc = (!Ext.isEmpty(icc))?icc:new Ext.ux.icc(),
iccPropName = (!Ext.isEmpty(iccPropName))?iccPropName:this.iccPropName,
iccPropName = (!Ext.isEmpty(iccPropName))?iccPropName:this.mainIccPlugin.iccPropName;
this[iccPropName] = icc;
if (!Ext.isEmpty(this.parent)) {
this.parent[iccPropName] = icc;
}
return icc;
},
/** Public Function: getIcc
* Gets the icc on the plugin or on the component.
* @param {String} iccPropName (Optional) The property name to the icc is stored on. Defaults to this.iccPropName or this.mainIccPlugin.iccPropName.
* @return {Ext.ux.icc|Null} icc The icc that was found or null
*/
getIcc : function (iccPropName) {
var iccPropName = (!Ext.isEmpty(iccPropName))?iccPropName:this.iccPropName,
iccPropName = (!Ext.isEmpty(iccPropName))?iccPropName:this.mainIccPlugin.iccPropName,
icc = this[iccPropName],
icc = (!Ext.isEmpty(icc))?icc:null;
return icc
},
//Private Functions:
//@private
init : function (parent) {
this.parent = parent;
this[this.iccPropName] = (!Ext.isEmpty(this.parent[this.iccPropName]))?this.parent[this.iccPropName]:this[this.iccPropName];
this[this.iccPropName] = (!Ext.isEmpty(this[this.iccPropName]))?this[this.iccPropName]:this.searchIcc();
this[this.iccPropName] = (!Ext.isEmpty(this[this.iccPropName]))?this[this.iccPropName]:new Ext.ux.icc();
this.parent[this.iccPropName] = this[this.iccPropName];
if (this.mainIcc) {
this.parent.mainIccPlugin = this;
}
if (this.registerComponent) {
this.icc.addCmp(this.parent);
this.parent.on('destroy', function () {
this.icc.removeCmp(this.parent)
}, this);
}
this.parent.searchIcc = this.searchIcc;
this.parent.setIcc = this.setIcc;
this.parent.getIcc = this.getIcc;
}
});
Ext.preg('ux-component-subcribeicc', Ext.ux.Component.SubcribeIcc);

Animal
22 Sep 2009, 4:17 AM
Looks good. Bit of labour saving advice. The code block



this.cmps.on('add', function(index, o, key){
this.fireEvent("afteraddcmp", index, key, o, this);
}, this);
this.cmps.on('clear', function(){
this.fireEvent("afterclearcmps", this);
}, this);
this.cmps.on('remove', function(o, key){
this.fireEvent("afterremovecmp", key, o, this);
}, this);
this.cmps.on('replace', function(key, oldObj, newObj){
this.fireEvent("afterreplacecmp", key, oldObj, newObj, this);
}, this);



And similar blocks which relay events

Can be rewritten shorter using http://www.extjs.com/deploy/dev/docs/?class=Ext.util.Observable&member=relayEvents

Of course the events names will then be the same...

Animal
22 Sep 2009, 4:20 AM
Maybe implementing your own version of relayEvents could be useful which relays events and translates event names into something new?

willf1976
22 Sep 2009, 2:33 PM
Hi Animal

Thank you much for the feedback :).

I will look into to making a simple custom relayEvents function that lets you specify making a new event name when you relay it -- might be a nice thing to have in general actually.

Hope you are well

Sincerely

Will Ferrer