linuxwindowsinboxwhatsappicloudtweetdeckhipchattelegramhangoutsslackgmailskypefacebook-workplaceoutlookemailmicrosoft-teamsdiscordmessengercustom-servicesmacos
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.
316 lines
10 KiB
316 lines
10 KiB
9 years ago
|
/**
|
||
|
* 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);
|
||
|
};
|
||
|
});
|