windowsinboxwhatsappicloudtweetdeckhipchattelegramhangoutsslackgmailskypefacebook-workplaceoutlookemailmicrosoft-teamsdiscordmessengercustom-servicesmacoslinux
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
315 lines
10 KiB
315 lines
10 KiB
/** |
|
* Provides a registry of all Components (instances of {@link Ext.Component} or any subclass |
|
* thereof) on a page so that they can be easily accessed by {@link Ext.Component component} |
|
* {@link Ext.Component#id id} (see {@link #get}, or the convenience method |
|
* {@link Ext#getCmp Ext.getCmp}). |
|
* |
|
* This object also provides a registry of available Component *classes* indexed by a |
|
* mnemonic code known as the Component's {@link Ext.Component#xtype xtype}. The `xtype` |
|
* provides a way to avoid instantiating child Components when creating a full, nested |
|
* config object for a complete Ext page. |
|
* |
|
* A child Component may be specified simply as a *config object* as long as the correct |
|
* `{@link Ext.Component#xtype xtype}` is specified so that if and when the Component |
|
* needs rendering, the correct type can be looked up for lazy instantiation. |
|
* |
|
* @singleton |
|
*/ |
|
Ext.define('Ext.ComponentManager', { |
|
alternateClassName: 'Ext.ComponentMgr', |
|
|
|
singleton: true, |
|
|
|
count: 0, |
|
|
|
typeName: 'xtype', |
|
|
|
/** |
|
* @private |
|
*/ |
|
constructor: function(config) { |
|
var me = this; |
|
|
|
Ext.apply(me, config || {}); |
|
me.all = {}; |
|
me.references = {}; |
|
me.onAvailableCallbacks = {}; |
|
}, |
|
|
|
/** |
|
* Creates a new Component from the specified config object using the config object's |
|
* `xtype` to determine the class to instantiate. |
|
* |
|
* @param {Object} config A configuration object for the Component you wish to create. |
|
* @param {String} [defaultType] The `xtype` to use if the config object does not |
|
* contain a `xtype`. (Optional if the config contains a `xtype`). |
|
* @return {Ext.Component} The newly instantiated Component. |
|
*/ |
|
create: function (config, defaultType) { |
|
if (typeof config === 'string') { |
|
return Ext.widget(config); |
|
} |
|
if (config.isComponent) { |
|
return config; |
|
} |
|
|
|
if ('xclass' in config) { |
|
return Ext.create(config.xclass, config); |
|
} |
|
|
|
return Ext.widget(config.xtype || defaultType, config); |
|
}, |
|
|
|
/** |
|
* Returns an item by id. |
|
* @param {String} id The id of the item |
|
* @return {Object} The item, undefined if not found. |
|
*/ |
|
get: function(id) { |
|
return this.all[id]; |
|
}, |
|
|
|
register: function(component) { |
|
var me = this, |
|
all = me.all, |
|
key = component.getId(), |
|
onAvailableCallbacks = me.onAvailableCallbacks; |
|
|
|
//<debug> |
|
if (key === undefined) { |
|
Ext.Error.raise('Component id is undefined. Please ensure the component has an id.'); |
|
} |
|
if (key in all) { |
|
Ext.Error.raise('Registering duplicate component id "' + key + '"'); |
|
} |
|
//</debug> |
|
|
|
all[key] = component; |
|
|
|
if (component.reference) { |
|
me.references[key] = component; |
|
} |
|
|
|
++me.count; |
|
|
|
if (!me.hasFocusListener) { |
|
Ext.on('focus', me.onGlobalFocus, me); |
|
me.hasFocusListener = true; |
|
} |
|
|
|
onAvailableCallbacks = onAvailableCallbacks && onAvailableCallbacks[key]; |
|
if (onAvailableCallbacks && onAvailableCallbacks.length) { |
|
me.notifyAvailable(component); |
|
} |
|
}, |
|
|
|
unregister: function(component) { |
|
var id = component.getId(); |
|
|
|
if (component.reference) { |
|
delete this.references[id]; |
|
} |
|
delete this.all[id]; |
|
|
|
this.count--; |
|
}, |
|
|
|
markReferencesDirty: function() { |
|
this.referencesDirty = true; |
|
}, |
|
|
|
fixReferences: function() { |
|
var me = this, |
|
references = me.references, |
|
key; |
|
|
|
if (me.referencesDirty) { |
|
for (key in references) { |
|
if (references.hasOwnProperty(key)) { |
|
references[key].fixReference(); |
|
} |
|
} |
|
me.referencesDirty = false; |
|
} |
|
}, |
|
|
|
/** |
|
* Registers a function that will be called (a single time) when an item with the specified id is added to the manager. |
|
* This will happen on instantiation. |
|
* @param {String} id The item id |
|
* @param {Function} fn The callback function. Called with a single parameter, the item. |
|
* @param {Object} scope The scope ('this' reference) in which the callback is executed. |
|
* Defaults to the item. |
|
*/ |
|
onAvailable : function(id, fn, scope){ |
|
var me = this, |
|
callbacks = me.onAvailableCallbacks, |
|
all = me.all, |
|
item; |
|
|
|
if (id in all) { //if already an instance, callback immediately |
|
item = all[id]; |
|
fn.call(scope || item, item); |
|
|
|
} else if (id) { // otherwise, queue for dispatch |
|
|
|
if (!Ext.isArray(callbacks[id])) { |
|
callbacks[id] = [ ]; |
|
} |
|
callbacks[id].push( function(item) { fn.call(scope || item, item);} ); |
|
} |
|
}, |
|
|
|
// @private |
|
notifyAvailable : function(item) { |
|
var callbacks = this.onAvailableCallbacks[item && item.getId()] || []; |
|
while (callbacks.length) { |
|
(callbacks.shift())(item); |
|
} |
|
}, |
|
|
|
/** |
|
* Executes the specified function once for each item in the collection. |
|
* @param {Function} fn The function to execute. |
|
* @param {String} fn.key The key of the item |
|
* @param {Number} fn.value The value of the item |
|
* @param {Number} fn.length The total number of items in the collection ** Removed |
|
* in 5.0 ** |
|
* @param {Boolean} fn.return False to cease iteration. |
|
* @param {Object} scope The scope to execute in. Defaults to `this`. |
|
*/ |
|
each: function(fn, scope){ |
|
return Ext.Object.each(this.all, fn, scope); |
|
}, |
|
|
|
/** |
|
* Gets the number of items in the collection. |
|
* @return {Number} The number of items in the collection. |
|
*/ |
|
getCount: function() { |
|
return this.count; |
|
}, |
|
|
|
/** |
|
* Returns an array of all components |
|
* @return {Array} |
|
*/ |
|
getAll: function() { |
|
return Ext.Object.getValues(this.all); |
|
}, |
|
|
|
/** |
|
* Return the currently active (focused) Component |
|
* |
|
* @return {Ext.Component/null} Active Component, or null |
|
* @private |
|
*/ |
|
getActiveComponent: function() { |
|
return Ext.Component.fromElement(Ext.dom.Element.getActiveElement()); |
|
}, |
|
|
|
// Deliver focus events to Component |
|
onGlobalFocus: function(e) { |
|
var me = this, |
|
toElement = e.toElement, |
|
fromElement = e.fromElement, |
|
toComponent = Ext.Component.fromElement(toElement), |
|
fromComponent = Ext.Component.fromElement(fromElement), |
|
commonAncestor = me.getCommonAncestor(fromComponent, toComponent), |
|
event, |
|
targetComponent; |
|
|
|
if (fromComponent && !(fromComponent.isDestroyed || fromComponent.destroying)) { |
|
// Call the Blurred Component's blur event handler directly with a synthesized blur event. |
|
if (fromComponent.focusable && fromElement === fromComponent.getFocusEl().dom) { |
|
event = new Ext.event.Event(e.event); |
|
event.type = 'blur'; |
|
event.target = fromElement; |
|
event.relatedTarget = toElement; |
|
fromComponent.onBlur(event); |
|
} |
|
|
|
// Call onFocusLeave on the component axis from which focus is exiting |
|
for (targetComponent = fromComponent; targetComponent && targetComponent !== commonAncestor; targetComponent = targetComponent.getRefOwner()) { |
|
if (!(targetComponent.isDestroyed || targetComponent.destroying)) { |
|
targetComponent.onFocusLeave({ |
|
event: e.event, |
|
type: 'focusleave', |
|
target: fromElement, |
|
relatedTarget: toElement, |
|
fromComponent: fromComponent, |
|
toComponent: toComponent |
|
}); |
|
} |
|
} |
|
} |
|
if (toComponent && !toComponent.isDestroyed) { |
|
// Call the Focused Component's focus event handler directly with a synthesized focus event. |
|
if (toComponent.focusable && toElement === toComponent.getFocusEl().dom) { |
|
event = new Ext.event.Event(e.event); |
|
event.type = 'focus'; |
|
event.relatedTarget = fromElement; |
|
event.target = toElement; |
|
toComponent.onFocus(event); |
|
} |
|
|
|
// Call onFocusEnter on the component axis to which focus is entering |
|
for (targetComponent = toComponent; targetComponent && targetComponent !== commonAncestor; targetComponent = targetComponent.getRefOwner()) { |
|
targetComponent.onFocusEnter({ |
|
event: e.event, |
|
type: 'focusenter', |
|
relatedTarget: fromElement, |
|
target: toElement, |
|
fromComponent: fromComponent, |
|
toComponent: toComponent |
|
}); |
|
} |
|
} |
|
}, |
|
|
|
getCommonAncestor: function(compA, compB) { |
|
if (compA === compB) { |
|
return compA; |
|
} |
|
while (compA && !(compA.isAncestor(compB) || compA === compB)) { |
|
compA = compA.getRefOwner(); |
|
} |
|
return compA; |
|
}, |
|
|
|
deprecated: { |
|
5: { |
|
methods: { |
|
/** |
|
* Checks if an item is registered. |
|
* @param {String} component The mnemonic string by which the class may be looked up. |
|
* @return {Boolean} Whether the type is registered. |
|
* @deprecated 5.0 |
|
*/ |
|
isRegistered: null, |
|
|
|
/** |
|
* Registers a new item constructor, keyed by a type key. |
|
* @param {String} type The mnemonic string by which the class may be looked up. |
|
* @param {Function} cls The new instance class. |
|
* @deprecated 5.0 |
|
*/ |
|
registerType: null |
|
} |
|
} |
|
} |
|
}, |
|
function () { |
|
/** |
|
* This is shorthand reference to {@link Ext.ComponentManager#get}. |
|
* Looks up an existing {@link Ext.Component Component} by {@link Ext.Component#id id} |
|
* |
|
* @param {String} id The component {@link Ext.Component#id id} |
|
* @return Ext.Component The Component, `undefined` if not found, or `null` if a |
|
* Class was found. |
|
* @member Ext |
|
*/ |
|
Ext.getCmp = function(id) { |
|
return Ext.ComponentManager.get(id); |
|
}; |
|
});
|
|
|