/**
 * Base class for all Ext components.
 *
 * The Component base class has built-in support for basic hide/show and enable/disable
 * and size control behavior.
 *
 * ## xtypes
 *
 * Every component has a specific xtype, which is its Ext-specific type name, along with
 * methods for checking the xtype like {@link #getXType} and {@link #isXType}. See the
 * [Component Guide](../guides/core_concepts/components.html) for more information on xtypes
 * and the Component hierarchy.
 *
 * ## Finding components
 *
 * All Components are registered with the {@link Ext.ComponentManager} on construction so
 * that they can be referenced at any time via {@link Ext#getCmp Ext.getCmp}, passing the
 * {@link #id}.
 *
 * Additionally the {@link Ext.ComponentQuery} provides a CSS-selectors-like way to look
 * up components by their xtype and many other attributes.  For example the following code
 * will find all textfield components inside component with `id: 'myform'`:
 *
 *     Ext.ComponentQuery.query('#myform textfield');
 *
 * ## Extending Ext.Component
 *
 * All subclasses of Component may participate in the automated Ext component
 * life cycle of creation, rendering and destruction which is provided by the
 * {@link Ext.container.Container Container} class. Components may be added to a Container
 * through the {@link Ext.container.Container#cfg-items items} config option at the time
 * the Container is created, or they may be added dynamically via the
 * {@link Ext.container.Container#method-add add} method.
 *
 * All user-developed visual widgets that are required to participate in automated
 * life cycle and size management should subclass Component.
 *
 * See the Creating new UI controls chapter in [Component Guide](../guides/core_concepts/components.html)
 * for details on how and to either extend or augment Ext JS base classes to create custom Components.
 *
 * ## The Ext.Component class by itself
 *
 * Usually one doesn't need to instantiate the Ext.Component class. There are subclasses
 * which implement specialized use cases, covering most application needs. However it is
 * possible to instantiate a base Component, and it can be rendered to document, or handled
 * by layouts as the child item of a Container:
 *
 *     @example
 *     Ext.create('Ext.Component', {
 *         html: 'Hello world!',
 *         width: 300,
 *         height: 200,
 *         padding: 20,
 *         style: {
 *             color: '#FFFFFF',
 *             backgroundColor:'#000000'
 *         },
 *         renderTo: Ext.getBody()
 *     });
 *
 * The Component above creates its encapsulating `div` upon render, and use the configured
 * HTML as content. More complex internal structure may be created using the
 * {@link #renderTpl} configuration, although to display database-derived mass data, it is
 * recommended that an ExtJS data-backed Component such as a {@link Ext.view.View View},
 * {@link Ext.grid.Panel GridPanel}, or {@link Ext.tree.Panel TreePanel} be used.
 */
Ext.define('Ext.Component', {
    alternateClassName: 'Ext.AbstractComponent',
 
    xtype: [
        'component',
        'box'
    ],
 
    requires: [
        'Ext.ComponentQuery',
        'Ext.ComponentManager',
        'Ext.util.ProtoElement',
        'Ext.dom.CompositeElement',
        'Ext.plugin.Abstract',
        'Ext.plugin.Manager',
        'Ext.scroll.Scroller'
    ],
 
    // Note that Floating must be mixed in before Positionable.
    mixins: [
        'Ext.mixin.Inheritable',
        'Ext.util.Floating',
        'Ext.util.Positionable',
        'Ext.util.Observable',
        'Ext.mixin.ComponentDelegation',
        'Ext.mixin.Bindable',
        'Ext.util.Animate',
        'Ext.util.ElementContainer',
        'Ext.util.Renderable',
        'Ext.state.Stateful',
        'Ext.mixin.Focusable',
        'Ext.mixin.Accessible',
        'Ext.mixin.Keyboard'
    ],
 
    uses: [
        'Ext.overrides.*',
        'Ext.Element',
        'Ext.DomHelper',
        'Ext.XTemplate',
        'Ext.ComponentLoader',
        'Ext.layout.Context',
        'Ext.layout.Layout',
        'Ext.layout.component.Auto',
        'Ext.LoadMask',
        'Ext.ZIndexManager',
        'Ext.util.DelayedTask',
        'Ext.resizer.Resizer',
        'Ext.util.ComponentDragger'
    ],
 
    statics: {
        AUTO_ID: 1000,
 
        pendingLayouts: null,
 
        layoutSuspendCount: 0,
 
        // Collapse/expand directions
        DIRECTION_TOP: 'top',
        DIRECTION_RIGHT: 'right',
        DIRECTION_BOTTOM: 'bottom',
        DIRECTION_LEFT: 'left',
 
        VERTICAL_DIRECTION_Re: /^(?:top|bottom)$/,
 
        // RegExp whih specifies characters in an xtype which must be translated to '-' when generating auto IDs.
        // This includes dot, comma and whitespace
        INVALID_ID_CHARS_Re: /[\.,\s]/g,
 
        /**
         * @property {String} ariaHighContrastModeCls CSS class to be applied
         * to the document body when High Contrast mode is detected in Windows.
         * @private
         */
        ariaHighContrastModeCls: Ext.baseCSSPrefix + 'aria-highcontrast',
 
        /**
         * Cancels layout of a component.
         * @param {Ext.Component} comp 
         * @param isDestroying
         */
        cancelLayout: function(comp, isDestroying) {
            var context = this.runningLayoutContext || this.pendingLayouts;
 
            if (context) {
                context.cancelComponent(comp, false, isDestroying);
            }
        },
 
        /**
         * Find the Widget or Component to which the given event/element belongs.
         *
         * @param {Ext.event.Event/Ext.dom.Element/HTMLElement} el The element or event
         * from which to start to find an owning Component.
         * @param {Ext.dom.Element/HTMLElement} [limit] The element at which to stop upward
         * searching for an owning Component, or the number of Components to traverse
         * before giving up. Defaults to the document's HTML element.
         * @param {String} [selector] An optional {@link Ext.ComponentQuery} selector to
         * filter the target.
         * @return {Ext.Component/null} Component, or null
         *
         * @since 6.5.0
         */
        from: function(el, limit, selector) {
            return Ext.ComponentManager.from(el, limit, selector);
        },
 
        /**
         * Find the Widget or Component to which the given Element belongs.
         *
         * @param {Ext.dom.Element/HTMLElement} el The element from which to start to find an owning Component.
         * @param {Ext.dom.Element/HTMLElement} [limit] The element at which to stop upward searching for an
         * owning Component, or the number of Components to traverse before giving up.
         * Defaults to the document's HTML element.
         * @param {String} [selector] An optional {@link Ext.ComponentQuery} selector to filter the target.
         * @return {Ext.Component/null} Component, or null
         *
         * @deprecated 6.5.0 Use {@link Ext.Component#method!from} instead.
         * @since 6.0.1
         */
        fromElement: function(el, limit, selector) {
            return Ext.ComponentManager.from(el, limit, selector);
        },
 
        /**
         * Performs all pending layouts that were scheduled while
         * {@link Ext.Component#suspendLayouts suspendLayouts} was in effect.
         * @static
         */
        flushLayouts: function () {
            var me = this,
                context = me.pendingLayouts;
 
            if (context && context.invalidQueue.length) {
                me.pendingLayouts = null;
                me.runningLayoutContext = context;
 
                Ext.override(context, {
                    runComplete: function () {
                        // we need to release the layout queue before running any of the
                        // finishedLayout calls because they call afterComponentLayout
                        // which can re-enter by calling updateLayout/doComponentLayout.
                        me.runningLayoutContext = null;
 
                        var Scroller = Ext.scroll.Scroller,
                            GlobalEvents = Ext.GlobalEvents,
                            result;
 
                        if (Scroller.viewport) {
                            Scroller.viewport.restoreState();
                        }
 
                        result = this.callParent(); // not "me" here!
                        if (GlobalEvents.hasListeners.afterlayout) {
                            GlobalEvents.fireEvent('afterlayout');
                        }
 
                        return result;
                    }
                });
 
                context.run();
            }
        },
 
        /**
         * Resumes layout activity in the whole framework.
         *
         * {@link Ext#suspendLayouts} is alias of {@link Ext.Component#suspendLayouts}.
         *
         * @param {Boolean} [flush=false] `true` to perform all the pending layouts. This can also be
         * achieved by calling {@link Ext.Component#flushLayouts flushLayouts} directly.
         * @static
         */
        resumeLayouts: function (flush) {
            if (this.layoutSuspendCount && ! --this.layoutSuspendCount) {
                if (flush) {
                    this.flushLayouts();
                }
                if (Ext.GlobalEvents.hasListeners.resumelayouts) {
                    Ext.GlobalEvents.fireEvent('resumelayouts');
                }
            }
        },
 
        /**
         * Stops layouts from happening in the whole framework.
         *
         * It's useful to suspend the layout activity while updating multiple components and
         * containers:
         *
         *     Ext.suspendLayouts();
         *     // batch of updates...
         *     Ext.resumeLayouts(true);
         *
         * {@link Ext#suspendLayouts} is alias of {@link Ext.Component#suspendLayouts}.
         *
         * See also {@link Ext#batchLayouts} for more abstract way of doing this.
         *
         * @static
         */
        suspendLayouts: function () {
            ++this.layoutSuspendCount;
        },
 
        /**
         * Updates layout of a component.
         *
         * @param {Ext.Component} comp The component to update.
         * @param {Boolean} [defer=false] `true` to just queue the layout if this component.
         * @static
         */
        updateLayout: function (comp, defer) {
            var me = this,
                running = me.runningLayoutContext,
                pending;
 
            if (running) {
                running.queueInvalidate(comp);
            } else {
                pending = me.pendingLayouts || (me.pendingLayouts = new Ext.layout.Context());
                pending.queueInvalidate(comp);
 
                if (!defer && !me.layoutSuspendCount && !comp.isLayoutSuspended()) {
                    me.flushLayouts();
                }
            }
        }
    },
 
    // <editor-fold desc="Config">
    // ***********************************************************************************
    // Begin Config
    // ***********************************************************************************
 
    // We do not want "_hidden" style backing properties.
    $configPrefixed: false,
    // We also want non-config system properties to go to the instance.
    $configStrict: false,
 
    clearPropertiesOnDestroy: 'async',
 
    manageLayoutScroll: true,
 
    config: {
        /**
         * @cfg {Object} data
         * The initial set of data to apply to the `{@link #tpl}` to update the content
         * area of the Component.
         *
         * @accessor
         * @since 3.4.0
         */
        data: null,
 
        /**
         * @cfg {Boolean} modelValidation
         * This config enables binding to your `{@link Ext.data.Model#validators}`. This
         * is only processed by form fields (e.g., `Ext.form.field.Text`) at present, but
         * this setting is inherited and so can be set on a parent container.
         *
         * When set to `true` by a component or not set by a component but inherited from
         * an ancestor container, `Ext.data.Validation` records are used to automatically
         * bind validation results for any form field to which a `value` is bound.
         *
         * While this config can be set arbitrarily high in the component hierarchy, doing
         * so can create a lot overhead if most of your form fields do not actually rely on
         * `validators` in your data model.
         *
         * Using this setting for a form that is bound to an `Ext.data.Model` might look
         * like this:
         *
         *      {
         *          xtype: 'panel',
         *          modelValidation: true,
         *          items: [{
         *              xtype: 'textfield',
         *              bind: '{theUser.firstName}'
         *          },{
         *              xtype: 'textfield',
         *              bind: '{theUser.lastName}'
         *          },{
         *              xtype: 'textfield',
         *              bind: '{theUser.phoneNumber}'
         *          },{
         *              xtype: 'textfield',
         *              bind: '{theUser.email}'
         *          }]
         *      }
         *
         * Notice that "validation" is a pseudo-association defined for all entities. See
         * `{@link Ext.data.Model#getValidation}` for further details.
         */
 
        /**
         * @cfg {Number} maxHeight
         * The maximum value in pixels which this Component will set its height to.
         *
         * **Warning:** This will override any size management applied by layout managers.
         */
        maxHeight: null,
 
        /**
         * @cfg {Number} maxWidth
         * The maximum value in pixels which this Component will set its width to.
         *
         * **Warning:** This will override any size management applied by layout managers.
         */
        maxWidth: null,
 
        /**
         * @cfg {Number} minHeight
         * The minimum value in pixels which this Component will set its height to.
         *
         * **Warning:** This will override any size management applied by layout managers.
         */
        minHeight: null,
 
        /**
         * @cfg {Number} minWidth
         * The minimum value in pixels which this Component will set its width to.
         *
         * **Warning:** This will override any size management applied by layout managers.
         */
        minWidth: null,
 
        /**
         * @cfg {Boolean/String/Object} scrollable
         * Configuration options to make this Component scrollable. Acceptable values are:
         *
         * - `true` to enable auto scrolling.
         * - `false` (or `null`) to disable scrolling - this is the default.
         * - `x` or `horizontal` to enable horizontal scrolling only
         * - `y` or `vertical` to enable vertical scrolling only
         *
         * Also accepts a configuration object for a `{@link Ext.scroll.Scroller}` if
         * if advanced configuration is needed.
         *
         * The getter for this config returns the {@link Ext.scroll.Scroller Scroller}
         * instance.  You can use the Scroller API to read or manipulate the scroll position:
         *
         *     // scrolls the component to 5 on the x axis and 10 on the y axis
         *     component.getScrollable().scrollTo(5, 10);
         */
        scrollable: null
    },
 
    /**
     * @cfg {Object} renderConfig
     * renderConfig wraps configs that do not get applied until after the component is
     * rendered. Unlike normal config system properties, renderConfigs use a special
     * setter method to store values on the instance instead of running the apply and
     * update methods if it is called before the component is rendered. Then, after the
     * component has been rendered, these values are processed by the normal apply and
     * update method for the config.
     *
     * This means that calling the get method for the config prior to render will return
     * whatever raw value has been set, while calling the getter after render will return
     * the value after processing by the config's apply method. If this distinction needs
     * to be made, it is the caller's responsibility to check for the rendered state and
     * handle such intermediate config values.
     */
    renderConfig: {
        /**
         * @cfg {Object} touchAction
         *
         * Emulates the behavior of the CSS
         * [touch-action](https://www.w3.org/TR/pointerevents/#the-touch-action-css-property)
         * property in a cross-browser compatible manner.
         *
         * Keys in this object are touch action names, and values are `false` to disable
         * a touch action or `true` to enable it.  Accepted keys are:
         *
         * - `panX`
         * - `panY`
         * - `pinchZoom`
         * - `doubleTapZoom`
         *
         * All touch actions are enabled (`true`) by default, so it is usually only necessary
         * to specify which touch actions to disable.  For example, the following disables
         * only horizontal scrolling and pinch-to-zoom on the component's main element:
         *
         *     touchAction: {
         *         panX: false,
         *         pinchZoom: false
         *     }
         *
         * Touch actions can be specified on child elements using the child element name,
         * for example:
         *
         *     // disables horizontal scrolling on the main element, and double-tap-zoom
         *     // on the child element named "body"
         *     touchAction: {
         *         panY: false
         *         body: {
         *             doubleTapZoom: false
         *         }
         *     }
         *
         * The primary motivation for setting the touch-action of an element is to prevent
         * the browser's default handling of a gesture such as pinch-to-zoom, or
         * drag-to-scroll, so that the application can implement its own handling of that
         * gesture on the element.  Suppose, for example, a component has a custom drag
         * handler on its element and wishes to prevent horizontal scrolling of its container
         * while it is being dragged:
         *
         *     Ext.create('Ext.Component', {
         *         touchAction: {
         *             panX: false
         *         },
         *         listeners: {
         *             drag: function(e) {
         *                 // implement drag logic
         *             }
         *         }
         *     });
         */
        touchAction: null
    },
 
    /**
     * @property defaultBindProperty
     * @inheritdoc
     */
    defaultBindProperty: 'html',
 
    /**
     * @cfg {String} alignTarget
     * A Component or Element by which to position this component according to the {@link #defaultAlign}.
     * Defaults to the owning Container.
     *
     * *Only applicable if this component is {@link #cfg-floating}*
     *
     * *Used upon first show*.
     */
    alignTarget: null,
 
    /**
     * @cfg anchor
     * @inheritDoc Ext.layout.container.Anchor#cfg-anchor
     */
 
    /**
     * @cfg {String/Object} autoEl
     * A tag name or {@link Ext.dom.Helper DomHelper} spec used to create the {@link #getEl Element} which will
     * encapsulate this Component.
     *
     * You do not normally need to specify this. For the base classes {@link Ext.Component} and
     * {@link Ext.container.Container}, this defaults to **'div'**. The more complex Sencha classes use a more
     * complex DOM structure specified by their own {@link #cfg-renderTpl}s.
     *
     * This is intended to allow the developer to create application-specific utility Components encapsulated by
     * different DOM elements. Example usage:
     *
     *     {
     *         xtype: 'component',
     *         autoEl: {
     *             tag: 'img',
     *             src: 'http://www.example.com/example.jpg'
     *         }
     *     }, {
     *         xtype: 'component',
     *         autoEl: {
     *             tag: 'blockquote',
     *             html: 'autoEl is cool!'
     *         }
     *     }, {
     *         xtype: 'container',
     *         autoEl: 'ul',
     *         cls: 'ux-unordered-list',
     *         items: {
     *             xtype: 'component',
     *             autoEl: 'li',
     *             html: 'First list item'
     *         }
     *     }
     *
     * @since 2.3.0
     */
 
    /**
     * @cfg {Boolean/String/HTMLElement/Ext.dom.Element} autoRender
     * This config is intended mainly for non-{@link #cfg-floating} Components which may or may not be shown. Instead of using
     * {@link #renderTo} in the configuration, and rendering upon construction, this allows a Component to render itself
     * upon first _{@link Ext.Component#method-show show}_. If {@link #cfg-floating} is `true`, the value of this config is omitted as if it is `true`.
     *
     * Specify as `true` to have this Component render to the document body upon first show.
     *
     * Specify as an element, or the ID of an element to have this Component render to a specific element upon first
     * show.
     */
    autoRender: false,
 
    /**
     * @cfg {Boolean} [autoScroll=false]
     * `true` to use overflow:'auto' on the components layout element and show scroll bars automatically when necessary,
     * `false` to clip any overflowing content.
     *
     * This should not be combined with {@link #overflowX} or  {@link #overflowY}.
     * @deprecated 5.1.0 Use {@link #scrollable} instead
     */
 
    /**
     * @cfg {Boolean} autoShow
     * `true` to automatically show the component upon creation. This config option may only be used for
     * {@link #cfg-floating} components or components that use {@link #autoRender}.
     *
     * @since 2.3.0
     */
    autoShow: false,
 
    /**
     * @cfg {String} baseCls
     * The base CSS class to apply to this component's element. This will also be prepended to elements within this
     * component like Panel's body will get a class `x-panel-body`. This means that if you create a subclass of Panel, and
     * you want it to get all the Panels styling for the element and the body, you leave the `baseCls` `x-panel` and use
     * `componentCls` to add specific styling for this component.
     */
    baseCls: Ext.baseCSSPrefix + 'component',
 
    /**
     * @cfg {Number/String/Boolean} border
     * Specifies the border size for this component. The border can be a single numeric value to apply to all sides or it can
     * be a CSS style specification for each style, for example: '10 5 3 10' (top, right, bottom, left).
     *
     * For components that have no border by default, setting this won't make the border appear by itself.
     * You also need to specify border color and style:
     *
     *     border: 5,
     *     style: {
     *         borderColor: 'red',
     *         borderStyle: 'solid'
     *     }
     *
     * To turn off the border, use `border: false`.
     */
 
    /**
     * @cfg childEls
     * @inheritdoc Ext.util.ElementContainer#cfg-childEls
     */
    childEls: {
        frameTable: { frame: true },
        frameTL:    { frame: 'tl' },
        frameTC:    { frame: 'tc' },
        frameTR:    { frame: 'tr' },
        frameML:    { frame: 'ml' },
        frameBody:  { frame: 'mc' },
        frameMR:    { frame: 'mr' },
        frameBL:    { frame: 'bl' },
        frameBC:    { frame: 'bc' },
        frameBR:    { frame: 'br' }
    },
 
    /**
     * @cfg {String/String[]} [cls='']
     * An optional extra CSS class that will be added to this component's Element.
     * The value can be a string, a list of strings separated by spaces, or an array of strings. This can be useful
     * for adding customized styles to the component or any of its children using standard CSS rules.
     *
     * @since 1.1.0
     */
 
    /**
     * @cfg {Number} [columnWidth]
     * Defines the column width inside {@link Ext.layout.container.Column column layout}.
     *
     * The columnWidth property is always evaluated as a percentage and must be a decimal value greater than 0 and
     * less than 1 (e.g., .25).  See the description at the top of {@link Ext.layout.container.Column column layout} for
     * additional usage details when combining width and columnWidth configs within the layout.
     */
 
    /**
     * @cfg {String} componentCls
     * CSS Class to be added to a components root level element to give distinction to it via styling.
     */
 
    // @cmd-auto-dependency { aliasPrefix : "layout." }
    /**
     * @cfg {String/Object} componentLayout
     * The sizing and positioning of a Component's internal Elements is the responsibility of the Component's layout
     * manager which sizes a Component's internal structure in response to the Component being sized.
     *
     * Generally, developers will not use this configuration as all provided Components which need their internal
     * elements sizing (Such as {@link Ext.form.field.Base input fields}) come with their own componentLayout managers.
     *
     * The {@link Ext.layout.container.Auto default layout manager} will be used on instances of the base Ext.Component
     * class which simply sizes the Component's encapsulating element to the height and width specified in the
     * {@link #setSize} method.
     *
     */
    componentLayout: 'autocomponent',
 
    /**
     * @cfg {Object/String} constraintInsets
     * An object or a string (in TRBL order) specifying insets from the configured {@link #constrainTo constrain region}
     * within which this component must be constrained when positioning or sizing.
     * example:
     *
     *     constraintInsets: '10 10 10 10' // Constrain with 10px insets from parent
     */
 
    /**
     * @cfg {Ext.util.Region/Ext.dom.Element} constrainTo
     * A {@link Ext.util.Region Region} (or an element from which a Region measurement will be read) which is used
     * to constrain the component. Only applies when the component is floating.
     */
 
    /**
     * @cfg {String} contentEl
     * Specify an existing HTML element, or the `id` of an existing HTML element to use as the content for this component.
     *
     * This config option is used to take an existing HTML element and place it in the layout element of a new component
     * (it simply moves the specified DOM element _after the Component is rendered_ to use as the content.
     *
     * **Notes:**
     *
     * The specified HTML element is appended to the layout element of the component _after any configured
     * {@link #html HTML} has been inserted_, and so the document will not contain this element at the time
     * the {@link #event-render} event is fired.
     *
     * The specified HTML element used will not participate in any **`{@link Ext.container.Container#layout layout}`**
     * scheme that the Component may use. It is just HTML. Layouts operate on child
     * **`{@link Ext.container.Container#cfg-items items}`**.
     *
     * Add either the `x-hidden` or the `x-hidden-display` CSS class to prevent a brief flicker of the content before it
     * is rendered to the panel.
     *
     * @since 3.4.0
     */
 
    /**
     * @cfg {String} defaultAlign
     * The default {@link Ext.util.Positionable#getAlignToXY Ext.dom.Element#getAlignToXY} anchor position value for this component
     * relative to its {@link #alignTarget} (which defaults to its owning Container).
     *
     * _Only applicable if this component is {@link #cfg-floating}_
     *
     * *Used upon first show*.
     */
    defaultAlign: 'c-c',
 
    /**
     * @cfg {Boolean} disabled
     * `true` to disable the component.
     * @since 2.3.0
     */
    disabled: false,
 
    // http://www.w3.org/TR/html5/disabled-elements.html
    disabledRe: /^(?:button|input|select|textarea|optgroup|option|fieldset)$/i,
 
    nonMaskableRe: (function () {
        var re = ['input', 'select', 'textarea', 'optgroup', 'option', 'table'];
 
        // All IE browsers 9 and below except for IE 9 standards.
        if (Ext.isIE9m && !(Ext.isIE9 && !Ext.isIEQuirks)) {
            // <p>.insertAdjacentHTML('BeforeEnd', '<div>...</div>') yields
            // 'Invalid source HTML for this operation' in all IEs not IE 9 standards.
            re.push('p');
        }
 
        return new RegExp('^(?:' + re.join('|') + ')$', 'i');
    }()),
 
    /**
     * @cfg {String} disabledCls
     * CSS class to add when the Component is disabled.
     */
    disabledCls: Ext.baseCSSPrefix + 'item-disabled',
 
    /**
     * @cfg {'top'/'bottom'/'left'/'right'} dock
     * The side of the {@link Ext.panel.Panel panel} where this component is to be
     * docked when specified in the panel's
     * {@link Ext.panel.Panel#dockedItems dockedItems} config.
     *
     * Possible values are:
     *
     *  - top
     *  - bottom
     *  - left
     *  - right
     */
 
    /**
     * @cfg {Boolean/Object} draggable
     * Specify as true to make a {@link #cfg-floating} Component draggable using the Component's encapsulating element as
     * the drag handle.
     *
     * This may also be specified as a config object for the {@link Ext.util.ComponentDragger ComponentDragger} which is
     * instantiated to perform dragging.
     *
     * For example to create a Component which may only be dragged around using a certain internal element as the drag
     * handle, use the delegate option:
     *
     *     new Ext.Component({
     *         constrain: true,
     *         floating: true,
     *         style: {
     *             backgroundColor: '#fff',
     *             border: '1px solid black'
     *         },
     *         html: '<h1 style="cursor:move">The title</h1><p>The content</p>',
     *         draggable: {
     *             delegate: 'h1'
     *         }
     *     }).show();
     */
    draggable: false,
 
    /**
     * @cfg {Number} flex
     * Flex may be applied to **child items** of a box layout ({@link Ext.layout.container.VBox vbox} or
     * {@link Ext.layout.container.HBox hbox}). Each child item with a flex property will
     * fill space (horizontally in `hbox`, vertically in `vbox`) according to that item's
     * **relative** flex value compared to the sum of all items with a flex value specified.
     *
     * Any child items that have either a `flex` of `0` or `undefined`
     * will not be 'flexed' (the initial size will not be changed).
     */
 
    /**
     * @cfg {Boolean} floating
     * Specify as true to float the Component outside of the document flow using CSS absolute positioning.
     *
     * Components such as {@link Ext.window.Window Window}s and {@link Ext.menu.Menu Menu}s are floating by default.
     *
     * Floating Components that are programmatically {@link Ext.Component#method-render rendered} will register
     * themselves with the global {@link Ext.WindowManager ZIndexManager}
     *
     * ### Floating Components as child items of a Container
     *
     * A floating Component may be used as a child item of a Container. This just allows the floating Component to seek
     * a ZIndexManager by examining the ownerCt chain.
     *
     * When configured as floating, Components acquire, at render time, a {@link Ext.ZIndexManager ZIndexManager} which
     * manages a stack of related floating Components. The ZIndexManager sorts its stack according to
     * an incrementing access counter and the {@link Ext.util.Floating#alwaysOnTop alwaysOnTop} config when the Component's {@link #toFront} method is called.
     *
     * The ZIndexManager is found by traversing up the {@link #ownerCt} chain to find an ancestor which itself is
     * floating. This is so that descendant floating Components of floating _Containers_ (Such as a ComboBox dropdown
     * within a Window) can have its zIndex managed relative to any siblings, but always **above** that floating
     * ancestor Container.
     *
     * If no floating ancestor is found, a floating Component registers itself with the default {@link Ext.WindowManager
     * ZIndexManager}.
     *
     * Floating components _do not participate in the Container's layout_. Because of this, they are not rendered until
     * you explicitly {@link #method-show} them.
     *
     * After rendering, the ownerCt reference is deleted, and the {@link #floatParent} property is set to the found
     * floating ancestor Container. If no floating ancestor Container was found the {@link #floatParent} property will
     * not be set.
     */
    floating: false,
 
    /**
     * @cfg {Boolean} [formBind=false]
     * When inside FormPanel, any component configured with `formBind: true` will
     * be enabled/disabled depending on the validity state of the form.
     * See {@link Ext.form.Panel} for more information and example.
     */
 
    /**
     * @cfg {Boolean} frame
     * Specify as `true` to have the Component inject framing elements within the Component at render time to provide a
     * graphical rounded frame around the Component content.
     *
     * This is only necessary when running on outdated, or non standard-compliant browsers such as Microsoft's Internet
     * Explorer prior to version 9 which do not support rounded corners natively.
     *
     * The extra space taken up by this framing is available from the read only property {@link #frameSize}.
     */
 
    /**
     * @cfg {Number|String} height
     * The height of this component. A numeric value will be interpreted as the number of
     * pixels; a string value will be treated as a CSS value with units.
     */
 
    /**
     * @cfg {Boolean} hidden
     * `true` to hide the component.
     * @since 2.3.0
     */
    hidden: false,
 
    /**
     * @cfg {String} hideMode
     * A String which specifies how this Component's encapsulating DOM element will be hidden. Values may be:
     *
     *   - `'display'` : The Component will be hidden using the `display: none` style.
     *   - `'visibility'` : The Component will be hidden using the `visibility: hidden` style.
     *   - `'offsets'` : The Component will be hidden by absolutely positioning it out of the visible area of the document.
     *     This is useful when a hidden Component must maintain measurable dimensions. Hiding using `display` results in a
     *     Component having zero dimensions.
     *
     * @since 1.1.0
     */
    hideMode: 'display',
 
    /**
     * @cfg {String/Object} [html='']
     * An HTML fragment, or a {@link Ext.dom.Helper DomHelper} specification to use as the layout element content.
     * The HTML content is added after the component is rendered, so the document will not contain this HTML at the time
     * the {@link #event-render} event is fired. This content is inserted into the body _before_ any configured {@link #contentEl}
     * is appended.
     *
     * @since 3.4.0
     */
 
    /**
     * @cfg {String} id
     * The **unique** id of this component instance.
     *
     * Use of this config should be considered carefully as this value must be unique across
     * all existing components. Components created with an `id` may be accessed globally
     * using {@link Ext#getCmp Ext.getCmp}.
     *
     * Instead of using assigned ids, consider a {@link #reference} config and a {@link #cfg-controller ViewController}
     * to respond to events and perform processing upon this Component.
     *
     * Alternatively, {@link #itemId} and {@link Ext.ComponentQuery ComponentQuery} can be
     * used to perform selector-based searching for Components analogous to DOM querying.
     * The {@link Ext.container.Container Container} class contains several helpful
     * {@link Ext.container.Container#down shortcut methods} to query its descendant
     * Components by selector.
     *
     * Note that this `id` will also be used as the element id for the containing HTML
     * element that is rendered to the page for this component. This allows you to write
     * id-based CSS rules to style the specific instance of this component uniquely, and
     * also to select sub-elements using this component's `id` as the parent.
     *
     * Defaults to an {@link #getId auto-assigned id}.
     *
     * **Note**: Valid identifiers start with a letter or underscore and are followed by
     * (optional) additional letters, underscores, digits or hyphens.
     *
     * @since 1.1.0
     */
 
    /**
     * @cfg {String} itemId
     * The **unique** id of this component instance within its container. See also the
     * {@link #reference} config.
     *
     * An `itemId` can be used as an alternative way to get a reference to a component when no object reference is
     * available. Instead of using an `{@link #id}` with {@link Ext#getCmp getCmp}, use
     * `itemId` with {@link Ext.container.Container#getComponent getComponent} which will
     * retrieve `itemId`'s or {@link #id}'s. Since `itemId`'s are an index to the container's
     * internal collection, the `itemId` is scoped locally to the container -- avoiding
     * potential conflicts with {@link Ext.ComponentManager}, which requires a **unique** {@link #id} value.
     *
     *     var c = new Ext.panel.Panel({ //
     *         height: 300,
     *         renderTo: document.body,
     *         layout: 'auto',
     *         items: [{
     *             itemId: 'p1',
     *             title: 'Panel 1',
     *             height: 150
     *         },{
     *             itemId: 'p2',
     *             title: 'Panel 2',
     *             height: 150
     *         }]
     *     });
     *
     *     p1 = c.getComponent('p1'); // not the same as Ext.getCmp()
     *     console.log(p1);
     *     p2 = p1.ownerCt.getComponent('p2'); // reference via a sibling
     *     console.log(p2);
     *
     * Also see {@link #id}, `{@link Ext.container.Container#query}`, `{@link Ext.container.Container#down}` and
     * `{@link Ext.container.Container#child}`.
     *
     * **Note**: Valid identifiers start with a letter or underscore and are followed by
     * (optional) additional letters, underscores, digits or hyphens.
     *
     * **Note**: to access the container of an item see {@link #ownerCt}.
     *
     * @since 3.4.0
     */
 
    /**
     * @cfg {Ext.ComponentLoader/Object} loader
     * A configuration object or an instance of a {@link Ext.ComponentLoader} to load remote content
     * for this Component.
     *
     *     Ext.create('Ext.Component', {
     *         loader: {
     *             url: 'content.html',
     *             autoLoad: true
     *         },
     *         renderTo: Ext.getBody()
     *     });
     */
 
    /**
     * @cfg {Number/String} margin
     * Specifies the margin for this component. The margin can be a single numeric value to apply to all sides or it can
     * be a CSS style specification for each style, for example: '10 5 3 10' (top, right, bottom, left).
     */
 
    /**
     * @cfg {String} maskElement
     * Related to the {@link #cfg-childEls} configuration which specifies named properties which correspond to component sub-elements.
     *
     * The name of the element property in this component to mask when masked by a LoadMask.
     *
     * Defaults to `null` to indicate that Components cannot by default contain a LoadMask, and that any LoadMask should be rendered into the document body.
     *
     * For example, Panels use `"el"` to indicate that the whole panel should be masked. This could be configured to be
     * `"body"` so that only the body is masked and toolbars and the header are still mouse-accessible.
     */
    maskElement: null,
    
    /**
     * @cfg {Object} [maskDefaults] Default LoadMask configuration for {@link #method-setLoading}.
     */
 
    /**
     * @cfg {String} [overCls='']
     * An optional extra CSS class that will be added to this component's Element when the mouse moves over the Element,
     * and removed when the mouse moves out. This can be useful for adding customized 'active' or 'hover' styles to the
     * component or any of its children using standard CSS rules.
     *
     * @since 2.3.0
     */
 
    /**
     * @cfg {String} overflowX
     * Possible values are:
     *
     *  - `'auto'` to enable automatic horizontal scrollbar (Style overflow-x: 'auto').
     *  - `'scroll'` to always enable horizontal scrollbar (Style overflow-x: 'scroll').
     *
     * The default is overflow-x: 'hidden'. This should not be combined with {@link #autoScroll}.
     * @deprecated 5.1.0 Use {@link #scrollable} instead
     */
 
    /**
     * @cfg {String} overflowY
     * Possible values are:
     *
     *  - `'auto'` to enable automatic vertical scrollbar (Style overflow-y: 'auto').
     *  - `'scroll'` to always enable vertical scrollbar (Style overflow-y: 'scroll').
     *
     * The default is overflow-y: 'hidden'. This should not be combined with {@link #autoScroll}.
     * @deprecated 5.1.0 Use {@link #scrollable} instead
     */
 
    /**
     * @cfg {Number/String} padding
     * Specifies the padding for this component. The padding can be a single numeric value to apply to all sides or it
     * can be a CSS style specification for each style, for example: '10 5 3 10' (top, right, bottom, left).
     */
 
    /**
     * @cfg {Array/Ext.enums.Plugin/Object/Ext.plugin.Abstract} plugins
     * This config describes one or more plugin config objects used to create plugin
     * instances for this component.
     *
     * Plugins are a way to bundle and reuse custom functionality. Plugins should extend
     * `Ext.plugin.Abstract` but technically the only requirement for a valid plugin
     * is that it contain an `init` method that accepts a reference to its owner. Once
     * a plugin is created, the owner will call the `init` method, passing a reference
     * to itself. Each plugin can then call methods or respond to events on its owner
     * as needed to provide its functionality.
     *
     * This config's value can take several different forms.
     *
     * The value can be a single string with the plugin's {@link Ext.enums.Plugin alias}:
     *
     *     plugins: 'cellediting',
     *
     * The preferred form for multiple plugins or to configure plugins is the keyed-object
     * form (new in version 6.5):
     *
     *      plugins: {
     *          gridviewdragdrop: true,
     *          cellediting: {
     *              clicksToEdit: 1
     *          }
     *      },
     *
     * The keys are `id`'s as well as the default type alias.
     *
     * The `plugins` config can also be an array of plugin aliases:
     *
     *     plugins: [ 'cellediting', 'gridviewdragdrop' ],
     *
     * An array can also contain elements that are config objects with a `ptype` property
     * holding the type alias:
     *
     *      plugins: ['gridviewdragdrop', {
     *          ptype: 'cellediting',
     *          clicksToEdit: 1
     *      }],
     *
     * @since 2.3.0
     */
 
    /**
     * @cfg {"north"/"south"/"east"/"west"/"center"} [region=undefined]
     * Defines the region inside {@link Ext.layout.container.Border border layout}.
     *
     * Possible values:
     *
     * - north - Positions component at top.
     * - south - Positions component at bottom.
     * - east - Positions component at right.
     * - west - Positions component at left.
     * - center - Positions component at the remaining space.
     *   There **must** be a component with `region: "center"` in every border layout.
     */
 
    /**
     * @cfg {Object} renderData
     *
     * The data used by {@link #renderTpl} in addition to the following property values of the component:
     *
     * - id
     * - ui
     * - uiCls
     * - baseCls
     * - componentCls
     * - frame
     *
     * See {@link #renderSelectors} and {@link #cfg-childEls} for usage examples.
     */
 
    /**
     * @cfg {Object} renderSelectors
     * An object containing properties specifying CSS selectors which identify child elements
     * created by the render process.
     *
     * After the Component's internal structure is rendered according to the {@link #renderTpl}, this object is iterated through,
     * and the found Elements are added as properties to the Component using the `renderSelector` property name.
     *
     * For example, a Component which renders a title and description into its element:
     *
     *      Ext.create('Ext.Component', {
     *          renderTo: Ext.getBody(),
     *          renderTpl: [
     *              '<h1 class="title">{title}</h1>',
     *              '<p>{desc}</p>'
     *          ],
     *          renderData: {
     *              title: "Error",
     *              desc: "Something went wrong"
     *          },
     *          renderSelectors: {
     *              titleEl: 'h1.title',
     *              descEl: 'p'
     *          },
     *          listeners: {
     *              afterrender: function(cmp){
     *                  // After rendering the component will have a titleEl and descEl properties
     *                  cmp.titleEl.setStyle({color: "red"});
     *              }
     *          }
     *      });
     *
     * The use of `renderSelectors` is deprecated (for performance reasons). The above
     * code should be refactored into something like this:
     *
     *      Ext.create('Ext.Component', {
     *          renderTo: Ext.getBody(),
     *          renderTpl: [
     *              '<h1 class="title" id="{id}-titleEl" data-ref="titleEl">{title}</h1>',
     *              '<p id="{id}-descEl" data-ref="descEl">{desc}</p>'
     *          ],
     *          renderData: {
     *              title: "Error",
     *              desc: "Something went wrong"
     *          },
     *          childEls: [
     *              'titleEl',
     *              'descEl'
     *          ]
     *      });
     *
     * To use `childEls` yet retain the use of selectors (which remains as expensive as
     * `renderSelectors`):
     *
     *      Ext.create('Ext.Component', {
     *          renderTo: Ext.getBody(),
     *          renderTpl: [
     *              '<h1 class="title">{title}</h1>',
     *              '<p>{desc}</p>'
     *          ],
     *          renderData: {
     *              title: "Error",
     *              desc: "Something went wrong"
     *          },
     *          childEls: {
     *              titleEl: { selectNode: 'h1.title' },
     *              descEl: { selectNode: 'p' }
     *          }
     *      });
     *
     * @deprecated 5.0 Use {@link #cfg-childEls} instead.
     */
 
    /**
     * @cfg {String/HTMLElement/Ext.dom.Element} renderTo
     * Specify the `id` of the element, a DOM element or an existing Element that this component will be rendered into.
     *
     * **Notes:**
     *
     * Do *not* use this option if the Component is to be a child item of a {@link Ext.container.Container Container}.
     * It is the responsibility of the {@link Ext.container.Container Container}'s
     * {@link Ext.container.Container#layout layout manager} to render and manage its child items.
     *
     * When using this config, a call to `render()` is not required.
     *
     * See also: {@link #method-render}.
     *
     * @since 2.3.0
     */
 
    /**
     * @cfg {Ext.XTemplate/String/String[]} renderTpl
     * An {@link Ext.XTemplate XTemplate} used to create the internal structure inside this Component's encapsulating
     * {@link #getEl Element}.
     *
     * You do not normally need to specify this. For the base classes {@link Ext.Component} and
     * {@link Ext.container.Container}, this defaults to **`null`** which means that they will be initially rendered
     * with no internal structure; they render their {@link #getEl Element} empty. The more specialized
     * classes with complex DOM structures provide their own template definitions.
     *
     * This is intended to allow the developer to create application-specific utility Components with customized
     * internal structure.
     *
     * Upon rendering, any created child elements may be automatically imported into object properties using the
     * {@link #renderSelectors} and {@link #cfg-childEls} options.
     * @protected
     */
    renderTpl: '{%this.renderContent(out,values)%}',
 
    /**
     * @cfg {Boolean/Object} resizable
     * Specify as `true` to apply a {@link Ext.resizer.Resizer Resizer} to this Component after rendering.
     *
     * May also be specified as a config object to be passed to the constructor of {@link Ext.resizer.Resizer Resizer}
     * to override any defaults. By default the Component passes its minimum and maximum size, and uses
     * `{@link Ext.resizer.Resizer#dynamic}: false`
     */
 
    /**
     * @cfg {String} resizeHandles
     * A valid {@link Ext.resizer.Resizer} handles config string. Only applies when resizable = true.
     */
    resizeHandles: 'all',
 
    /**
     * @cfg {Boolean/Number} shrinkWrap
     *
     * The possible values for shrinkWrap are:
     *
     *   - 0 (or `false`): Neither width nor height depend on content.
     *   - 1: Width depends on content (shrink wraps), but height does not.
     *   - 2: Height depends on content (shrink wraps), but width does not.
     *   - 3 (or `true`): Both width and height depend on content (shrink wrap).
     *
     * In CSS terms, shrink-wrap width is analogous to an inline-block element as opposed
     * to a block-level element.
     *
     * @localdoc ##Non-Panel Components
     *
     * The shrinkWrap config is a class-level config and should be used when defining a
     * subclass.
     * It is not intended to be set as a config on instances of a given component.
     *
     * For non-Panel components, shrinkWrap is a descriptive config only.  It should be
     * set when defining your own custom class including the DOM elements used to
     * construct the component.  The shrinkWrap property does not itself apply styling on
     * the component elements.  Rather, it should describe the CSS styling you've applied
     * to your custom component (_refer to the numeric matrix above_).
     *
     * When a component is owned by a container the layout of that container will inspect
     * the component's shrinkWrap property during layout.  The layout then uses the
     * content-wrapping policy described by shrinkWrap to correctly size and position the
     * container's child items.
     */
    shrinkWrap: 2,
 
    /**
     * @cfg stateEvents
     * @inheritdoc Ext.state.Stateful#cfg-stateEvents
     * @localdoc By default the following stateEvents are added:
     *
     *  - {@link #event-resize}
     */
 
    /**
     * @cfg {String/Object} style
     * A custom style specification to be applied to this component's Element. Should be a valid argument to
     * {@link Ext.dom.Element#applyStyles}.
     *
     *     new Ext.panel.Panel({
     *         title: 'Some Title',
     *         renderTo: Ext.getBody(),
     *         width: 400, height: 300,
     *         layout: 'form',
     *         items: [{
     *             xtype: 'textarea',
     *             style: {
     *                 width: '95%',
     *                 marginBottom: '10px'
     *             }
     *         },
     *         new Ext.button.Button({
     *             text: 'Send',
     *             minWidth: '100',
     *             style: {
     *                 marginBottom: '10px'
     *             }
     *         })
     *         ]
     *     });
     *
     * @since 1.1.0
     */
 
    /**
     * @cfg {Boolean} toFrontOnShow
     * True to automatically call {@link #toFront} when the {@link #method-show} method is called on an already visible,
     * floating component.
     */
    toFrontOnShow: true,
 
    /**
     * @cfg {Ext.XTemplate/Ext.Template/String/String[]} tpl
     * An {@link Ext.Template}{@link Ext.XTemplate} or an array of strings to form an Ext.XTemplate. Used in
     * conjunction with the `{@link #data}` and `{@link #tplWriteMode}` configurations.
     *
     * @since 3.4.0
     */
 
    /**
     * @property {Boolean} synthetic
     * This property is `true` if the component was created internally by the framework
     * and is not explicitly user-defined. This is set for such things as `Splitter`
     * instances managed by `border` and `box` layouts.
     * @private
     */
    synthetic: false,
 
    /**
     * @cfg {String} tplWriteMode
     * The Ext.(X)Template method to use when updating the content area of the Component.
     * See `{@link Ext.XTemplate#overwrite}` for information on default mode.
     *
     * @since 3.4.0
     */
    tplWriteMode: 'overwrite',
 
    /**
     * @cfg {String} ui
     * A UI style for a component.
     */
    ui: 'default',
 
    /**
     * @cfg {String[]} uiCls
     * An array of of `classNames` which are currently applied to this component.
     * @private
     */
    uiCls: [],
 
    /**
     * @cfg {String/String[]} userCls
     * One or more CSS classes to add to the component's primary element. This config
     * is intended solely for use by the component instantiator (the "user"), not by
     * derived classes.
     *
     * For example:
     *
     *      items: [{
     *          xtype: 'button',
     *          userCls: 'my-button'
     *      ...
     *      }]
     * @accessor
     */
    userCls: null,
 
    /**
     * @cfg {Number} weight
     * A value to control how Components are laid out in a {@link Ext.layout.container.Border Border} layout or as docked items.
     *
     * In a Border layout, this can control how the regions (not the center) region lay out if the west or east take full height
     * or if the north or south region take full width. Also look at the {@link Ext.layout.container.Border#regionWeights} on the Border layout. An example to show how you can
     * take control of this is:
     *
     *     Ext.create('Ext.container.Viewport', {
     *         layout      : 'border',
     *         defaultType : 'panel',
     *         items       : [
     *             {
     *                 region : 'north',
     *                 title  : 'North',
     *                 height : 100
     *             },
     *             {
     *                 region : 'south',
     *                 title  : 'South',
     *                 height : 100,
     *                 weight : -25
     *             },
     *             {
     *                 region : 'west',
     *                 title  : 'West',
     *                 width  : 200,
     *                 weight : 15
     *             },
     *             {
     *                 region : 'east',
     *                 title  : 'East',
     *                 width  : 200
     *             },
     *             {
     *                 region : 'center',
     *                 title  : 'center'
     *             }
     *         ]
     *     });
     *
     * If docked items, the weight will order how the items are laid out. Here is an example to put a {@link Ext.toolbar.Toolbar} above
     * a {@link Ext.panel.Panel}'s header:
     *
     *     Ext.create('Ext.panel.Panel', {
     *         renderTo    : document.body,
     *         width       : 300,
     *         height      : 300,
     *         title       : 'Panel',
     *         html        : 'Panel Body',
     *         dockedItems : [
     *             {
     *                 xtype : 'toolbar',
     *                 items : [
     *                     {
     *                         text : 'Save'
     *                     }
     *                 ]
     *             },
     *             {
     *                 xtype  : 'toolbar',
     *                 weight : -10,
     *                 items  : [
     *                     {
     *                         text : 'Remove'
     *                     }
     *                 ]
     *             }
     *         ]
     *     });
     */
    weight: null,
 
    /**
     * @cfg {Number|String} width
     * The width of this component. A numeric value will be interpreted as the number of
     * pixels; a string value will be treated as a CSS value with units.
     */
 
    /**
     * @cfg {Ext.enums.Widget} xtype
     * **Note:** Only applies to {@link Ext.Component} derived classes when used as
     * a config in {@link Ext#define Ext.define}.
     *
     * This property provides a shorter alternative to creating objects than using a full
     * class name. Using `xtype` is the most common way to define component instances,
     * especially in a container. For example, the items in a form containing text fields
     * could be created explicitly like so:
     *
     *      items: [
     *          Ext.create('Ext.form.field.Text', {
     *              fieldLabel: 'Foo'
     *          }),
     *          Ext.create('Ext.form.field.Text', {
     *              fieldLabel: 'Bar'
     *          }),
     *          Ext.create('Ext.form.field.Number', {
     *              fieldLabel: 'Num'
     *          })
     *      ]
     *
     * But by using `xtype`, the above becomes:
     *
     *      items: [
     *          {
     *              xtype: 'textfield',
     *              fieldLabel: 'Foo'
     *          },
     *          {
     *              xtype: 'textfield',
     *              fieldLabel: 'Bar'
     *          },
     *          {
     *              xtype: 'numberfield',
     *              fieldLabel: 'Num'
     *          }
     *      ]
     *
     * When the `xtype` is common to many items, {@link Ext.container.Container#defaultType}
     * is another way to specify the `xtype` for all items that don't have an explicit `xtype`:
     *
     *      defaultType: 'textfield',
     *      items: [
     *          { fieldLabel: 'Foo' },
     *          { fieldLabel: 'Bar' },
     *          { fieldLabel: 'Num', xtype: 'numberfield' }
     *      ]
     *
     * Each member of the `items` array is now just a "configuration object". These objects
     * are used to create and configure component instances. A configuration object can be
     * manually used to instantiate a component using {@link Ext#widget}:
     *
     *      var text1 = Ext.create('Ext.form.field.Text', {
     *          fieldLabel: 'Foo'
     *      });
     *
     *      // or alternatively:
     *
     *      var text1 = Ext.widget({
     *          xtype: 'textfield',
     *          fieldLabel: 'Foo'
     *      });
     *
     * This conversion of configuration objects into instantiated components is done when
     * a container is created as part of its {Ext.container.AbstractContainer#initComponent}
     * process. As part of the same process, the `items` array is converted from its raw
     * array form into a {@link Ext.util.MixedCollection} instance.
     *
     * You can define your own `xtype` on a custom {@link Ext.Component component} by specifying
     * the `xtype` property in {@link Ext#define}. For example:
     *
     *     Ext.define('MyApp.PressMeButton', {
     *         extend: 'Ext.button.Button',
     *         xtype: 'pressmebutton',
     *         text: 'Press Me'
     *     });
     *
     * Care should be taken when naming an `xtype` in a custom component because there is
     * a single, shared scope for all xtypes. Third part components should consider using
     * a prefix to avoid collisions.
     *
     *     Ext.define('Foo.form.CoolButton', {
     *         extend: 'Ext.button.Button',
     *         xtype: 'ux-coolbutton',
     *         text: 'Cool!'
     *     });
     *
     * See {@link Ext.enums.Widget} for list of all available xtypes.
     *
     * @since 2.3.0
     */
    
    /**
     * @cfg {Number} tabIndex
     * DOM tabIndex attribute for this component's {@link #focusEl}.
     */
 
    // ***********************************************************************************
    // End Config
    // ***********************************************************************************
    // </editor-fold>
 
    // <editor-fold desc="Properties">
    // ***********************************************************************************
    // Begin Properties
    // ***********************************************************************************
 
    /**
     * @private
     */
    allowDomMove: true,
 
    /**
     * @property {Boolean} autoGenId
     * `true` indicates an `id` was auto-generated rather than provided by configuration.
     * @private
     */
    autoGenId: false,
 
    /**
     * @private
     */
    borderBoxCls: Ext.baseCSSPrefix + 'border-box',
 
    /**
     * @property {Number} componentLayoutCounter
     * @private
     * The number of component layout calls made on this object.
     */
    componentLayoutCounter: 0,
 
    /**
     * @property {String} contentPaddingProperty
     * The name of the padding property that is used by the layout to manage
     * padding.  See {@link Ext.layout.container.Auto#managePadding managePadding}
     */
    contentPaddingProperty: 'padding',
 
    /**
     * @private
     */
    deferLayouts: false,
 
    /**
     * @property {Ext.Container} floatParent
     * **Only present for {@link #cfg-floating} Components which were inserted as child items of Containers.**
     *
     * There are other similar relationships such as the {@link Ext.button.Button button} which activates a {@link Ext.button.Button#cfg-menu menu}, or the
     * {@link Ext.menu.Item menu item} which activated a {@link Ext.menu.Item#cfg-menu submenu}, or the
     * {@link Ext.grid.column.Column column header} which activated the column menu.
     *
     * These differences are abstracted away by the {@link #up} method.
     *
     * Floating Components that are programmatically {@link Ext.Component#method-render rendered} will not have a `floatParent`
     * property.
     *
     * See {@link #cfg-floating} and {@link #zIndexManager}
     * @readonly
     */
 
    /**
     * @property {Object} frameSize
     * @readonly
     * Indicates the width of any framing elements which were added within the encapsulating
     * element to provide graphical, rounded borders. See the {@link #frame} config. This
     * property is `null` if the component is not framed.
     *
     * This is an object containing the frame width in pixels for all four sides of the
     * Component containing the following properties:
     *
     * @property {Number} [frameSize.top=0] The width of the top framing element in pixels.
     * @property {Number} [frameSize.right=0] The width of the right framing element in pixels.
     * @property {Number} [frameSize.bottom=0] The width of the bottom framing element in pixels.
     * @property {Number} [frameSize.left=0] The width of the left framing element in pixels.
     * @property {Number} [frameSize.width=0] The total width of the left and right framing elements in pixels.
     * @property {Number} [frameSize.height=0] The total height of the top and right bottom elements in pixels.
     */
    frameSize: null,
 
    /**
     * @private
     */
    horizontalPosProp: 'left',
 
    /**
     * @property {Boolean} isComponent
     * `true` in this class to identify an object as an instantiated Component, or subclass thereof.
     */
    isComponent: true,
 
    /**
     * @property {Boolean} _isLayoutRoot
     * Setting this property to `true` causes the {@link #isLayoutRoot} method to return
     * `true` and stop the search for the top-most component for a layout.
     * @protected
     */
    _isLayoutRoot: false,
 
    /**
     * @private
     */
    layoutSuspendCount: 0,
 
    /**
     * @cfg {Boolean} liquidLayout
     * Components that achieve their internal layout results using solely CSS with no JS
     * intervention must set this to true.  This allows the component to opt out of the
     * layout run when used inside certain container layouts such as {@link
     * Ext.layout.container.Form Form} and {@link Ext.layout.container.Auto Auto}
     * resulting in a performance gain. The following components currently use liquid
     * layout (`liquidLayout: true`):
     *
     * - All Form Fields (subclasses of {@link Ext.form.field.Base})
     * - {@link Ext.button.Button}
     *
     * It is important to keep in mind that components using liquidLayout do not fire
     * the following events:
     *
     * - {@link #event-resize}
     * - {@link #event-boxready}
     *
     * In addition, liquidLayout components do not call the following template methods:
     *
     * - {@link #method!afterComponentLayout}
     * - {@link #method!onBoxReady}
     * - {@link #method!onResize}
     *
     * Any component that needs to fire these events or to have these methods called during
     * its life cycle needs to set `liquidLayout` to `false`.  The following example
     * demonstrates how to enable the resize event for a
     * {@link Ext.form.field.TextArea TextArea Field}:
     *
     *     @example
     *     var win = Ext.create({
     *             xtype: 'window',
     *             title: 'Resize This Window!',
     *             height: 100,
     *             width: 200,
     *             layout: 'anchor',
     *             items: [{
     *                 xtype: 'textarea',
     *                 anchor: '0 0',
     *                 liquidLayout: false // allows the textarea to fire "resize"
     *             }]
     *         }),
     *         textfield = win.items.getAt(0);
     *
     *     win.show();
     *
     *     textfield.on('resize', function(textfield, width, height) {
     *         Ext.Msg.alert('Text Field Resized', 'width: ' + width + ', height: ' + height);
     *     });
     *
     * Use caution when setting `liquidLayout` to `false` as it carries a performance penalty
     * since it means the layout system must perform expensive DOM reads to determine the
     * Component's size.
     */
    liquidLayout: false,
 
    /**
     * @property {Boolean} maskOnDisable
     * This is an internal flag that you use when creating custom components. By default this is set to `true` which means
     * that every component gets a mask when it's disabled. Components like FieldContainer, FieldSet, Field, Button, Tab
     * override this property to `false` since they want to implement custom disable logic.
     */
    maskOnDisable: true,
 
    /**
     * @property {Ext.Container} ownerCt
     * This Component's owner {@link Ext.container.Container Container} (is set automatically
     * when this Component is added to a Container).
     *
     * *Important.* This is not a universal upwards navigation pointer. It indicates the Container which owns and manages
     * this Component if any. There are other similar relationships such as the {@link Ext.button.Button button} which activates a {@link Ext.button.Button#cfg-menu menu}, or the
     * {@link Ext.menu.Item menu item} which activated a {@link Ext.menu.Item#cfg-menu submenu}, or the
     * {@link Ext.grid.column.Column column header} which activated the column menu.
     *
     * These differences are abstracted away by the {@link #up} method.
     *
     * **Note**: to access items within the Container see {@link #itemId}.
     * @readonly
     * @since 2.3.0
     */
 
    /**
     * @property {Boolean} rendered
     * Indicates whether or not the component has been rendered.
     * @readonly
     * @since 1.1.0
     */
    rendered: false,
 
    /**
     * @private
     */
    rootCls: Ext.baseCSSPrefix + 'body',
 
    /**
     * @private
     */
    scrollerCls: Ext.baseCSSPrefix + 'scroll-scroller',
 
    /**
     * @property {Object} scrollFlags
     * An object property which provides unified information as to which dimensions are
     * scrollable based upon the {@link #scrollable} settings (And for *views* of trees and
     * grids, the owning panel's {@link Ext.panel.Table#scroll scroll} setting).
     *
     * Note that if you set overflow styles using the {@link #style} config or
     * {@link Ext.panel.Panel#bodyStyle bodyStyle} config, this object does not include
     * that information. Use {@link #scrollable} if you need to access these flags.
     *
     * This object has the following properties:
     * @property {Boolean} scrollFlags.x `true` if this Component is scrollable
     * horizontally - style setting may be `'auto'` or `'scroll'`.
     * @property {Boolean} scrollFlags.y `true` if this Component is scrollable
     * vertically - style setting may be `'auto'` or `'scroll'`.
     * @property {Boolean} scrollFlags.both `true` if this Component is scrollable both
     * horizontally and vertically.
     * @property {String} scrollFlags.overflowX The `overflow-x` style setting, `'auto'`
     * or `'scroll'` or `''`.
     * @property {String} scrollFlags.overflowY The `overflow-y` style setting, `'auto'`
     * or `'scroll'` or `''`.
     * @readonly
     * @private
     */
    _scrollFlags: {
        auto: {
            // x:auto, y:auto
            auto: {
                overflowX: 'auto',
                overflowY: 'auto',
                x: true,
                y: true,
                both: true
            },
            // x:auto, y:false
            'false': {
                overflowX: 'auto',
                overflowY: 'hidden',
                x: true,
                y: false,
                both: false
            },
            // x:auto, y:scroll
            scroll: {
                overflowX: 'auto',
                overflowY: 'scroll',
                x: true,
                y: true,
                both: true
            }
        },
        'false': {
            // x:false, y:auto
            auto: {
                overflowX: 'hidden',
                overflowY: 'auto',
                x: false,
                y: true,
                both: false
            },
            // x:false, y:false
            'false': {
                overflowX: 'hidden',
                overflowY: 'hidden',
                x: false,
                y: false,
                both: false
            },
            // x:false, y:scroll
            scroll: {
                overflowX: 'hidden',
                overflowY: 'scroll',
                x: false,
                y: true,
                both: false
            }
        },
        scroll: {
            // x:scroll, y:auto
            auto: {
                overflowX: 'scroll',
                overflowY: 'auto',
                x: true,
                y: true,
                both: true
            },
            // x:scroll, y:false
            'false': {
                overflowX: 'scroll',
                overflowY: 'hidden',
                x: true,
                y: false,
                both: false
            },
            // x:scroll, y:scroll
            scroll: {
                overflowX: 'scroll',
                overflowY: 'scroll',
                x: true,
                y: true,
                both: true
            }
        },
        none: {
            overflowX: '',
            overflowY: '',
            x: false,
            y: false,
            both: false
        }
    },
 
    _scrollableCfg: {
        x: {
            x: true,
            y: false
        },
        y: {
            x: false,
            y: true
        },
        horizontal: {
            x: true,
            y: false
        },
        vertical: {
            x: false,
            y: true
        },
        both: {
            x: true,
            y: true
        },
        'true': {
            x: true,
            y: true
        }
    },
 
    validIdRe: Ext.validIdRe,
 
    // ***********************************************************************************
    // End Properties
    // ***********************************************************************************
    // </editor-fold>
 
    // <editor-fold desc="Events">
    // ***********************************************************************************
    // Begin Events
    // ***********************************************************************************
 
    /**
     * @event afterlayoutanimation
     * This event first after a component's layout has been updated by a layout that
     * included animation (e.g., a {@link Ext.panel.Panel panel} in an
     * {@link Ext.layout.container.Accordion accordion} layout).
     * @param {Ext.Component} this 
     * @since 6.0.0
     */
 
    /**
     * @event beforeactivate
     * Fires before a Component has been visually activated. Returning `false` from an event listener can prevent
     * the activate from occurring.
     *
     * **Note** This event is only fired if this Component is a child of a {@link Ext.container.Container}
     * that uses {@link Ext.layout.container.Card} as it's layout.
     * @param {Ext.Component} this 
     */
 
    /**
     * @event activate
     * Fires after a Component has been visually activated.
     *
     * **Note** This event is only fired if this Component is a child of a {@link Ext.container.Container}
     * that uses {@link Ext.layout.container.Card} as it's layout or this Component is a floating Component.
     * @param {Ext.Component} this 
     */
 
    /**
     * @event beforedeactivate
     * Fires before a Component has been visually deactivated. Returning `false` from an event listener can
     * prevent the deactivate from occurring.
     *
     * **Note** This event is only fired if this Component is a child of a {@link Ext.container.Container}
     * that uses {@link Ext.layout.container.Card} as it's layout.
     * @param {Ext.Component} this 
     */
 
    /**
     * @event deactivate
     * Fires after a Component has been visually deactivated.
     *
     * **Note** This event is only fired if this Component is a child of a {@link Ext.container.Container}
     * that uses {@link Ext.layout.container.Card} as it's layout or this Component is a floating Component.
     * @param {Ext.Component} this 
     */
 
    /**
     * @event added
     * Fires after a Component had been added to a Container.
     * @param {Ext.Component} this 
     * @param {Ext.container.Container} container Parent Container
     * @param {Number} pos position of Component
     * @since 3.4.0
     */
 
    /**
     * @event disable
     * Fires after the component is disabled.
     * @param {Ext.Component} this 
     * @since 1.1.0
     */
 
    /**
     * @event enable
     * Fires after the component is enabled.
     * @param {Ext.Component} this 
     * @since 1.1.0
     */
 
    /**
     * @event beforeshow
     * Fires before the component is shown when calling the {@link Ext.Component#method-show show} method. Return `false` from an event
     * handler to stop the show.
     * @param {Ext.Component} this 
     * @since 1.1.0
     */
 
    /**
     * @event show
     * Fires after the component is shown when calling the {@link Ext.Component#method-show show} method.
     * @param {Ext.Component} this 
     * @since 1.1.0
     */
 
    /**
     * @event beforehide
     * Fires before the component is hidden when calling the {@link Ext.Component#method-hide hide} method. Return `false` from an event
     * handler to stop the hide.
     * @param {Ext.Component} this 
     * @since 1.1.0
     */
 
    /**
     * @event hide
     * Fires after the component is hidden. Fires after the component is hidden when calling the {@link Ext.Component#method-hide hide}
     * method.
     * @param {Ext.Component} this 
     * @since 1.1.0
     */
 
    /**
     * @event removed
     * Fires when a component is removed from an Ext.container.Container
     * @param {Ext.Component} this 
     * @param {Ext.container.Container} ownerCt Container which holds the component
     * @since 3.4.0
     */
 
    /**
     * @event beforerender
     * Fires before the component is {@link #rendered}. Return `false` from an event handler to stop the
     * {@link #method-render}.
     * @param {Ext.Component} this 
     * @since 1.1.0
     */
 
    /**
     * @event render
     * Fires after the component markup is {@link #rendered}.
     * @param {Ext.Component} this 
     * @since 1.1.0
     */
 
    /**
     * @event afterrender
     * Fires after the component rendering is finished.
     *
     * The `afterrender` event is fired after this Component has been {@link #rendered}, been post-processed by any
     * `afterRender` method defined for the Component.
     * @param {Ext.Component} this 
     * @since 3.4.0
     */
 
    /**
     * @event boxready
     * Fires *one time* - after the component has been laid out for the first time at its initial size.
     *
     * This event does not fire on components that use {@link #cfg-liquidLayout}, such as
     * {@link Ext.button.Button Buttons} and {@link Ext.form.field.Base Form Fields}.
     * @param {Ext.Component} this 
     * @param {Number} width The initial width.
     * @param {Number} height The initial height.
     */
 
    /**
     * @event beforedestroy
     * Fires before the component is destroyed.
     *
     * **Note:** This event should not be used to try to veto the destruction sequence by returning
     *  `false`, even though this is often permitted in other "before" events. Doing so will have
     * unpredictable side-effects and can result in partially destroyed objects. Instead look to
     * other events like {@link Ext.panel.Panel#event!beforeclose beforeclose} that occur prior to
     * the call to the {@link Ext.Base#method!destroy destroy} method.
     *
     * @param {Ext.Component} this 
     * @since 1.1.0
     */
 
    /**
     * @event destroy
     * Fires after the component is {@link #method-destroy}ed.
     * @param {Ext.Component} this 
     * @since 1.1.0
     */
 
    /**
     * @event resize
     * Fires after the component is resized. Note that this does *not* fire when the component is first laid out at its initial
     * size. To hook that point in the life cycle, use the {@link #boxready} event.
     *
     * This event does not fire on components that use {@link #cfg-liquidLayout}, such as
     * {@link Ext.button.Button Buttons} and {@link Ext.form.field.Base Form Fields}.
     * @param {Ext.Component} this 
     * @param {Number} width The new width that was set.
     * @param {Number} height The new height that was set.
     * @param {Number} oldWidth The previous width.
     * @param {Number} oldHeight The previous height.
     */
 
    /**
     * @event move
     * Fires after the component is moved.
     * @param {Ext.Component} this 
     * @param {Number} x The new x position.
     * @param {Number} y The new y position.
     */
 
    // ***********************************************************************************
    // End Events
    // ***********************************************************************************
    // </editor-fold>
 
    /**
     * Creates new Component.
     * @param {Ext.dom.Element/String/Object} config The configuration options may be specified as either:
     *
     * - **an element** : it is set as the internal element and its id used as the component id
     * - **a string** : it is assumed to be the id of an existing element and is used as the component id
     * - **anything else** : it is assumed to be a standard config object and is applied to the component
     */
    constructor: function(config) {
        var me = this,
            i, len, xhooks, controller, autoScroll, overflowX, overflowY, scrollable;
 
        config = config || {};
 
        if (config.initialConfig) {
            // Being initialized from an Ext.Action instance...
            if (config.isAction) {
                me.baseAction = config;
            }
            config = config.initialConfig;
            // component cloning / action set up
        }
        else if (config.tagName || config.dom || Ext.isString(config)) {
            // element object
            config = {
                applyTo: config,
                id: config.id || config
            };
        }
 
        // Make initialConfig available early so that config getters may access it
        /**
         * @property {Object} initialConfig
         * @readonly
         * The config object passed to the constructor during Component creation.
         */
        me.initialConfig = config;
 
        me.$iid = ++Ext.$nextIid;
 
        // We want to determine very early on whether or not we are a reference holder,
        // so peek at either the incoming config or the class config to see if we have
        // a controller defined.
        if ((config && config.controller) || me.config.controller) {
            me.referenceHolder = true;
        }
 
        // Ensure that we have an id early so that config getters may access it
        me.getId();
        me.protoEl = new Ext.util.ProtoElement();
        //<debug>
        me.$calledInitConfig = true;
        //</debug>
        me.initConfig(config);
        //<debug>
        delete me.$calledInitConfig;
        //</debug>
 
        if (me.scrollable == null) {
            autoScroll = me.autoScroll;
 
            if (autoScroll) {
                scrollable = !!autoScroll;
            } else {
                overflowX = me.overflowX;
                overflowY = me.overflowY;
 
                if (overflowX || overflowY) {
                    scrollable = {
                        x: (overflowX && overflowX !== 'hidden') ? overflowX : false,
                        y: (overflowY && overflowY !== 'hidden') ? overflowY : false
                    };
                }
            }
 
            if (scrollable) {
                me.setScrollable(scrollable);
            }
        }
 
        xhooks = me.xhooks;
        if (xhooks) {
            delete me.xhooks;
            Ext.override(me, xhooks);
        }
 
        me.mixins.elementCt.constructor.call(me);
 
        //<debug>
        if (!me.validIdRe.test(me.id)) {
            Ext.raise('Invalid component "id": "' + me.id + '"');
        }
        if (!me.validIdRe.test(me.itemId)) {
            Ext.raise('Invalid component "itemId": "' + me.itemId + '"');
        }
        //</debug>
 
        me.setupProtoEl();
 
        // initComponent, beforeRender, or event handlers may have set the style or `cls` property since the `protoEl` was set up
        // so we must apply styles and classes here too.
        if (me.cls) {
            me.initialCls = me.cls;
            me.protoEl.addCls(me.cls);
        }
        if (me.style) {
            me.initialStyle = me.style;
            me.protoEl.setStyle(me.style);
        }
 
        me.renderData = me.renderData || {};
 
        me.initComponent();
 
        // initComponent gets a chance to change the id property before registering
        if (!me.preventRegister) {
            Ext.ComponentManager.register(me);
        }
 
        me.mixins.state.constructor.call(me);
        me.addStateEvents('resize');
 
        controller = me.getController();
        if (controller) {
            controller.init(me);
        }
 
        // Move this into Observable?
        if (me.plugins) {
            for (= 0, len = me.plugins.length; i < len; i++) {
                me.plugins[i] = me.initPlugin(me.plugins[i]);
            }
        }
 
        me.loader = me.getLoader();
 
        if (me.disabled) {
            me.disabled = false;
            me.disable(true);
        }
 
        if (me.renderTo) {
            me.render(me.renderTo);
            // EXTJSIV-1935 - should be a way to do afterShow or something, but that
            // won't work. Likewise, rendering hidden and then showing (w/autoShow) has
            // implications to afterRender so we cannot do that.
        }
 
        // Auto show only works unilaterally on *uncontained* Components.
        // If contained, then it is the Container's responsibility to do the showing at next layout time.
        if (me.autoShow && !me.$initParent) {
            me.show();
        }
 
        //<debug>
        if (Ext.isDefined(me.disabledClass)) {
            if (Ext.isDefined(Ext.global.console)) {
                Ext.global.console.warn('Ext.Component: disabledClass has been deprecated. Please use disabledCls.');
            }
            me.disabledCls = me.disabledClass;
            delete me.disabledClass;
        }
        //</debug>
 
        // If we were configured from an instance of Ext.Action, (or configured with a baseAction option),
        // register this Component as one of its items
        if (me.baseAction){
            me.baseAction.addComponent(me);
        }
    },
 
    beforeInitConfig: function() {
        //<debug>
        if (!this.$calledInitConfig) {
            Ext.raise('initConfig should not be called by subclasses, it will be called by Ext.Component');
        }
        //</debug>
        this.mixins.observable.constructor.call(this);
    },
 
    // <editor-fold desc="Component Methods">
    // ***********************************************************************************
    // Begin Component Methods
    // ***********************************************************************************
 
    /**
     * Adds a CSS class to the top level element representing this component.
     * @param {String/String[]} cls The CSS class name to add.
     * @return {Ext.Component} Returns the Component to allow method chaining.
     */
    addCls: function(cls) {
        var me = this,
            el = me.rendered ? me.el : me.protoEl;
 
        el.addCls.apply(el, arguments);
        return me;
    },
 
    /**
     * Adds a `cls` to the `uiCls` array, which will also call {@link #addUIClsToElement} and adds to all elements of this
     * component.
     * @param {String/String[]} classes A string or an array of strings to add to the `uiCls`.
     * @param {Boolean} [skip] `true` to skip adding it to the class and do it later (via the return).
     */
    addClsWithUI: function(classes, skip) {
        var me = this,
            clsArray = [],
            i = 0,
            uiCls = me.uiCls = Ext.Array.clone(me.uiCls),
            activeUI = me.activeUI,
            length,
            cls;
 
        if (typeof classes === "string") {
            classes = (classes.indexOf(' ') < 0) ? [classes] : Ext.String.splitWords(classes);
        }
 
        length = classes.length;
 
        for (; i < length; i++) {
            cls = classes[i];
 
            if (cls && !me.hasUICls(cls)) {
                uiCls.push(cls);
 
                // We can skip this bit if there isn't an activeUI because we'll be called again from setUI
                if (activeUI) {
                    clsArray = clsArray.concat(me.addUIClsToElement(cls));
                }
            }
        }
 
        if (skip !== true && activeUI) {
            me.addCls(clsArray);
        }
 
        return clsArray;
    },
 
    /**
     * Called by the layout system after the Component has been laid out.
     *
     * This method is not called on components that use {@link #cfg-liquidLayout}, such as
     * {@link Ext.button.Button Buttons} and {@link Ext.form.field.Base Form Fields}.
     *
     * @param {Number} width The width that was set
     * @param {Number} height The height that was set
     * @param {Number/undefined} oldWidth The old width, or `undefined` if this was the initial layout.
     * @param {Number/undefined} oldHeight The old height, or `undefined` if this was the initial layout.
     *
     * @template
     * @protected
     */
    afterComponentLayout: function(width, height, oldWidth, oldHeight) {
        var me = this,
            scroller = me.scrollable;
 
        if (++me.componentLayoutCounter === 1) {
            me.afterFirstLayout(width, height);
        } else if (me.manageLayoutScroll && scroller) {
            scroller.restoreState();
        }
 
        if (width !== oldWidth || height !== oldHeight) {
            me.onResize(width, height, oldWidth, oldHeight);
        }
 
        if (me.floating) {
            me.onAfterFloatLayout();
        }
    },
 
    /**
     * @protected
     * Adds a plugin. May be called at any time in the component's life cycle.
     */
    addPlugin: function(plugin) {
        var me = this;
 
        plugin = me.constructPlugin(plugin);
        if (me.plugins) {
            me.plugins.push(plugin);
        } else {
            me.plugins = [ plugin ];
        }
        if (me.pluginsInitialized) {
            me.initPlugin(plugin);
        }
        return plugin;
    },
 
    /**
     * Save a property to the given state object if it is not its default or configured
     * value.
     *
     * @param {Object} state The state object.
     * @param {String} propName The name of the property on this object to save.
     * @param {String} [value] The value of the state property (defaults to `this[propName]`).
     * @return {Object} The state object or a new object if state was `null` and the property
     * was saved.
     * @protected
     */
    addPropertyToState: function (state, propName, value) {
        var me = this,
            len = arguments.length;
 
        // If the property is inherited, it is a default and we don't want to save it to
        // the state, however if we explicitly specify a value, always save it
        if (len === 3 || me.hasOwnProperty(propName)) {
            if (len < 3) {
                value = me[propName];
            }
 
            // If the property has the same value as was initially configured, again, we
            // don't want to save it.
            if (value !== me.initialConfig[propName]) {
                (state || (state = {}))[propName] = value;
            }
        }
 
        return state;
    },
 
    /**
     * Method which adds a specified UI + `uiCls` to the components element. Can be overridden
     * to add the UI to more than just the component's element.
     * @param {String} uiCls The UI class to add to the element.
     * @protected
     */
    addUIClsToElement: function (uiCls) {
        var me = this,
            baseClsUI = me.baseCls + '-' + me.ui + '-' + uiCls,
            result = [ Ext.baseCSSPrefix + uiCls, me.baseCls + '-' + uiCls, baseClsUI ],
            childEls, childElName, el, suffix;
 
        if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
            // Loop through each frame element, and if they are defined add the ui:
            baseClsUI += '-';
            childEls = me.getChildEls();
 
            for (childElName in childEls) {
                suffix = childEls[childElName].frame;
                if (suffix && suffix !== true) {
                    el = me[childElName];
                    if (el) {
                        el.addCls(baseClsUI + suffix);
                    }
                }
            }
        }
 
        return result;
    },
 
    /**
     * Method which removes a specified UI + `uiCls` from the components element. The `cls`
     * which is added to the element will be: `this.baseCls + '-' + ui + uiCls`.
     * @param {String} uiCls The UI class to remove from the element.
     * @protected
     */
    removeUIClsFromElement: function(uiCls) {
        var me = this,
            baseClsUI = me.baseCls + '-' + me.ui + '-' + uiCls,
            result = [ Ext.baseCSSPrefix + uiCls, me.baseCls + '-' + uiCls, baseClsUI ],
            childEls, childElName, el, suffix;
 
        if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
            // Loop through each frame element, and if they are defined remove the ui:
            baseClsUI += '-';
            childEls = me.getChildEls();
 
            for (childElName in childEls) {
                suffix = childEls[childElName].frame;
                if (suffix && suffix !== true) {
                    el = me[childElName];
                    if (el) {
                        el.removeCls(baseClsUI + suffix);
                    }
                }
            }
        }
 
        return result;
    },
 
    /**
     * @private
     */
    adjustPosition: function(x, y) {
        var me = this,
            floatParentBox;
 
        // Floating Components being positioned in their ownerCt have to be made absolute.
        if (me.isContainedFloater()) {
            floatParentBox = me.floatParent.getTargetEl().getViewRegion();
            x += floatParentBox.left;
            y += floatParentBox.top;
        }
 
        return {
            x: x,
            y: y
        };
    },
 
    /**
     * Invoked after the Component has been hidden.
     *
     * Gets passed the same `callback` and `scope` parameters that #onHide received.
     *
     * @param {Function} [callback] 
     * @param {Object} [scope] 
     * @template
     * @protected
     */
    afterHide: function(callback, scope) {
        var me = this,
            container = me.ownerFocusableContainer;
 
        // Top level focusEnter is only valid when a floating component stack is visible.
        delete me.getInherited().topmostFocusEvent;
 
        me.hiddenByLayout = null;
 
        // Only lay out if there is an owning layout which might be affected by the hide
        if (me.ownerLayout) {
            me.updateLayout({ isRoot: false });
        }
 
        if (container && !container.onFocusableChildHide.$nullFn) {
            container.onFocusableChildHide(me);
        }
 
        me.fireHierarchyEvent('hide');
        me.fireEvent('hide', me);
 
        // Have to fire callback the last, because it may destroy the Component
        // and firing subsequent events will become impossible. Strictly speaking,
        // hide event handler above could have destroyed the Component too, but
        // in such case it is the responsibility of the callback to accommodate.
        Ext.callback(callback, scope || me);
    },
 
    /**
     * Template method called after a Component has been positioned.
     *
     * @param {Number} x 
     * @param {Number} y 
     *
     * @template
     * @protected
     */
    afterSetPosition: function(x, y) {
        var me = this;
        me.onPosition(x, y);
        if (me.hasListeners.move) {
            me.fireEvent('move', me, x, y);
        }
    },
 
    /**
     * Invoked after the Component is shown (after #onShow is called).
     *
     * Gets passed the same parameters as #show.
     *
     * @param {String/Ext.dom.Element} [animateTarget]
     * @param {Function} [callback] 
     * @param {Object} [scope] 
     * @template
     * @protected
     */
    afterShow: function(animateTarget, callback, scope) {
        var me = this,
            myEl = me.el,
            zim = me.zIndexManager,
            fromBox,
            toBox,
            ghostPanel;
 
        // Default to configured animate target if none passed
        animateTarget = me.getAnimateTarget(animateTarget);
 
        // We are going to churn the zIndex stack, so suspend its reactions.
        if (zim) {
            zim.suspendReflow();
        }
 
        // Need to be able to ghost the Component
        if (!me.ghost) {
            animateTarget = null;
        }
        // If we're animating, kick of an animation of the ghost from the target to the *Element* current box
        if (animateTarget) {
            toBox = {
                x: myEl.getX(),
                y: myEl.getY(),
                width: myEl.dom.offsetWidth,
                height: myEl.dom.offsetHeight
            };
            fromBox = {
                x: animateTarget.getX(),
                y: animateTarget.getY(),
                width: animateTarget.dom.offsetWidth,
                height: animateTarget.dom.offsetHeight
            };
 
            // Will move to front with underlying mask, and focus if necessary.
            me.fireHierarchyEvent('show');
 
            // Ghost will brifly be topmost, but it is focusable: false
            // And ghosting does not disturb focus.
            ghostPanel = me.ghost();
            ghostPanel.el.stopAnimation();
 
            // Shunting it offscreen immediately, *before* the Animation class grabs it ensure no flicker.
            ghostPanel.setX(-10000);
 
            me.ghostBox = toBox;
            ghostPanel.el.animate({
                from: fromBox,
                to: toBox,
                listeners: {
                    afteranimate: function() {
                        if (!me.destroying) {
                            ghostPanel.componentLayout.lastComponentSize = null;
                            me.unghost();
                            me.ghostBox = null;
                            me.onShowComplete(callback, scope);
                        }
                    }
                }
            });
        }
        else {
            me.onShowComplete(callback, scope);
            me.fireHierarchyEvent('show');
        }
        
        // Take a run through the zIndex stack ensuring modal, focus and topmost is correct
        if (zim) {
            zim.resumeReflow(true);
        }
    },
 
    animate: function(animObj) {
        var me = this,
            hasToWidth,
            hasToHeight,
            toHeight,
            toWidth,
            to,
            clearWidth,
            clearHeight,
            curWidth, w, curHeight, h, isExpanding,
            wasConstrained,
            wasConstrainedHeader,
            passedCallback,
            oldOverflow;
 
        animObj = animObj || {};
        to = animObj.to || {};
 
        if (Ext.fx.Manager.hasFxBlock(me.id)) {
            return me;
        }
 
        hasToWidth = Ext.isDefined(to.width);
        if (hasToWidth) {
            toWidth = Ext.Number.constrain(to.width, me.minWidth, me.maxWidth);
        }
 
        hasToHeight = Ext.isDefined(to.height);
        if (hasToHeight) {
            toHeight = Ext.Number.constrain(to.height, me.minHeight, me.maxHeight);
        }
 
        // Special processing for animating Component dimensions.
        if (!animObj.dynamic && (hasToWidth || hasToHeight)) {
            curWidth = (animObj.from ? animObj.from.width : undefined) || me.getWidth();
            w = curWidth;
            curHeight = (animObj.from ? animObj.from.height : undefined) || me.getHeight();
            h = curHeight;
            isExpanding = false;
 
            if (hasToHeight && toHeight > curHeight) {
                h = toHeight;
                isExpanding = true;
            }
            if (hasToWidth && toWidth > curWidth) {
                w = toWidth;
                isExpanding = true;
            }
 
            // During animated sizing, overflow has to be hidden to clip expanded content
            if (hasToHeight || hasToWidth) {
                oldOverflow = me.el.getStyle('overflow');
                if (oldOverflow !== 'hidden') {
                    me.el.setStyle('overflow', 'hidden');
                }
            }
 
            // If any dimensions are being increased, we must resize the internal structure
            // of the Component, but then clip it by sizing its encapsulating element back to original dimensions.
            // The animation will then progressively reveal the larger content.
            if (isExpanding) {
                clearWidth = !Ext.isNumber(me.width);
                clearHeight = !Ext.isNumber(me.height);
 
                // Lay out this component at the new, larger size to get the internals correctly laid out.
                // Then size the encapsulating **Element** back down to size.
                // We will then just animate the element to reveal the correctly laid out content.
                me.setSize(w, h);
                me.el.setSize(curWidth, curHeight);
 
                if (clearWidth) {
                    delete me.width;
                }
                if (clearHeight) {
                    delete me.height;
                }
            }
            if (hasToWidth) {
                to.width = toWidth;
            }
 
            if (hasToHeight) {
                to.height = toHeight;
            }
        }
 
        // No constraining during the animate - the "to" size has already been calculated with respect to all settings.
        // Arrange to reinstate any constraining after the animation has completed
        wasConstrained = me.constrain;
        wasConstrainedHeader = me.constrainHeader;
        if (wasConstrained || wasConstrainedHeader) {
            me.constrain = me.constrainHeader = false;
            passedCallback = animObj.callback;
            animObj.callback = function() {
                me.constrain = wasConstrained;
                me.constrainHeader = wasConstrainedHeader;
                // Call the original callback if any
                if (passedCallback) {
                    passedCallback.call(animObj.scope||me, arguments);
                }
                if (oldOverflow !== 'hidden') {
                    me.el.setStyle('overflow', oldOverflow);
                }
            };
        }
        return me.mixins.animate.animate.apply(me, arguments);
    },
 
    applyScrollable: function(scrollable, oldScrollable) {
        var me = this,
            rendered = me.rendered,
            scrollableCfg;
 
        if (scrollable) {
            if (scrollable === true || typeof scrollable === 'string') {
                scrollableCfg = me._scrollableCfg[scrollable];
 
                //<debug>
                if (!scrollableCfg) {
                    Ext.raise("'" + scrollable + "' is not a valid value for 'scrollable'");
                }
                //</debug>
 
                scrollable = scrollableCfg;
            }
 
            if (oldScrollable) {
                oldScrollable.setConfig(scrollable);
                scrollable = oldScrollable;
            } else {
                scrollable = Ext.Object.chain(scrollable); // don't mutate the user's config
 
                if (rendered) {
                    // we create the scroller without an element by default (because the
                    // element is not available at configuration time) and then assign
                    // the element in onBoxReady. If we got here it means the scroller
                    // is being configured after render, so we need to make sure the
                    // element is in its config object
                    scrollable.element = me.getOverflowEl();
                }
 
                scrollable = Ext.scroll.Scroller.create(scrollable, me.scrollableType);
                scrollable.component = me;
            }
        }
        // We are disabling scrolling for this Component.
        else if (oldScrollable) {
            scrollable = oldScrollable;
            oldScrollable.setConfig({
                x: false,
                y: false
            });
        }
 
        if (me.rendered && !me.destroying && !me.destroyed) {
            if (scrollable) {
                me.getOverflowStyle(); // refresh the scrollFlags
            } else {
                me.scrollFlags = me._scrollFlags.none;
            }
            me.updateLayout();
        }
 
        return scrollable;
    },
 
    /**
     * This method is required by the Scroller to return the scrollable client region
     * @return {Ext.util.Region} The scrolling viewport region.
     * @private
     */
    getScrollableClientRegion: function() {
        return this.getScrollable().getElement().getClientRegion();
    },
 
    applyTouchAction: function(touchAction, oldTouchAction) {
        if (oldTouchAction != null) {
            touchAction = Ext.merge({}, oldTouchAction, touchAction);
        }
 
        return touchAction;
    },
 
    /**
     * Invoked before the Component is destroyed.
     * This method is deprecated, override {@link #onDestroy} instead.
     *
     * @method
     * @template
     * @protected
     * @deprecated 6.2.0 Please override {@link #onDestroy} instead
     */
    beforeDestroy: Ext.emptyFn,
 
    /**
     * Occurs before componentLayout is run. In previous releases, this method could
     * return `false` to prevent its layout but that is not supported in Ext JS 4.1 or
     * higher. This method is simply a notification of the impending layout to give the
     * component a chance to adjust the DOM. Ideally, DOM reads should be avoided at this
     * time to reduce expensive document reflows.
     *
     * @template
     * @protected
     */
    beforeLayout: function(){
        if (this.floating) {
            this.onBeforeFloatLayout();
        }
    },
 
    /**
     * @private
     * Template method called before a Component is positioned.
     *
     * Ensures that the position is adjusted so that the Component is constrained if so configured.
     */
    beforeSetPosition: function (x, y, animate) {
        var me = this,
            pos = null,
            x0, hasX, hasY, adj;
 
        // Decode members of x if x is an array or an object.
        // If it is numeric (including zero), we need do nothing.
        if (x) {
            // Position in first argument as an array of [x, y]
            if (Ext.isNumber(x0 = x[0])) {
                animate = y;
                y = x[1];
                x = x0;
            }
            // Position in first argument as object w/ x & y properties
            else if ((x0 = x.x) !== undefined) {
                animate = y;
                y = x.y;
                x = x0;
            }
        }
 
        if (me.constrain || me.constrainHeader) {
            pos = me.calculateConstrainedPosition(null, [x, y], true);
            if (pos) {
                x = pos[0];
                y = pos[1];
            }
        }
 
        hasX = (!== undefined);
        hasY = (!== undefined);
 
        if (hasX || hasY) {
            // The component's position is the position it was told to be at.
            // If it is contained, adjustPosition will add the floatParent's offsets.
            me.x = x;
            me.y = y;
 
            adj = me.adjustPosition(x, y);
            // Set up the return info and store the position in this object
            pos = {
                x : adj.x,
                y : adj.y,
                anim: animate,
                hasX: hasX,
                hasY: hasY
            };
        }
 
        return pos;
    },
 
    /**
     * Invoked before the Component is shown.
     *
     * @method
     * @template
     * @protected
     */
    beforeShow: Ext.emptyFn,
 
    /**
     * Bubbles up the component/container hierarchy, calling the specified function with each component. The scope
     * (*this*) of function call will be the scope provided or the current component. The arguments to the function will
     * be the args provided or the current component. If the function returns false at any point, the bubble is stopped.
     *
     * @param {Function} fn The function to call
     * @param {Object} [scope] The scope of the function. Defaults to current node.
     * @param {Array} [args] The args to call the function with. Defaults to passing the current component.
     * @return {Ext.Component} this
     */
    bubble: function(fn, scope, args) {
        var p = this;
        while (p) {
            if (fn.apply(scope || p, args || [p]) === false) {
                break;
            }
            p = p.getBubbleTarget();
        }
        return this;
    },
 
    clearListeners: function() {
        var me = this;
        me.mixins.observable.clearListeners.call(me);
        me.mixins.componentDelegation.clearDelegatedListeners.call(me);
    },
 
    /**
     * Clone the current component using the original config values passed into this instance by default.
     * @param {Object} overrides A new config containing any properties to override in the cloned version.
     * An id property can be passed on this object, otherwise one will be generated to avoid duplicates.
     * @return {Ext.Component} clone The cloned copy of this component
     */
    cloneConfig: function(overrides) {
        overrides = overrides || {};
        var id = overrides.id || Ext.id(),
            cfg = Ext.applyIf(overrides, this.initialConfig),
            self;
 
        cfg.id = id;
 
        self = Ext.getClass(this);
 
        // prevent dup id
        return new self(cfg);
    },
 
    /**
     * Destroys the Component. This method **must not** be overridden because Component
     * destruction sequence is conditional; if a `beforedestroy` handler returns `false`
     * we must abort destruction.
     *
     * To add extra functionality to destruction time in a subclass, override the
     * {@link #doDestroy} method.
     *
     * @since 1.1.0
     */
    destroy: function() {
        var me = this;
 
        if (!me.hasListeners.beforedestroy || me.fireEvent('beforedestroy', me) !== false) {
            // isDestroying added for compat reasons
            me.isDestroying = me.destroying = true;
            
            me.doDestroy();
 
            // We need to defer clearing listeners until after doDestroy() completes,
            // to let the interested parties fire events until the very end.
            me.clearListeners();
 
            // isDestroying added for compat reasons
            me.isDestroying = me.destroying = false;
 
            me.callParent(); // Ext.Base
            
            // ComponentDelegation mixin does not install "after" interceptor on the
            // base class destructor; Observable mixin does install the interceptor
            // but cannot destroy itself automatically because Components are
            // conditionally destructible.
            me.mixins.componentDelegation.destroyComponentDelegation.call(me);
            me.mixins.observable.destroyObservable.call(me, true);
        }
    },
    
    /**
     * Perform the actual destruction sequence.
     *
     * As a rule of thumb, subclasses should destroy their child Components and/or other objects
     * before calling parent method. Any object references will be nulled after this method
     * has finished, to prevent the possibility of memory leaks.
     *
     * @private
     * @since 6.2.0
     */
    doDestroy: function() {
        var me = this,
            focusableContainer = me.ownerFocusableContainer,
            container = me.container,
            selectors = me.renderSelectors,
            selector, ownerCt, el;
 
        ownerCt = me.floatParent || me.ownerCt;
        
        if (me.floating) {
            delete me.floatParent;
            
            // A zIndexManager is stamped into a *floating* Component when it is added
            // to a Container. If it has no zIndexManager at render time, it is assigned
            // to the global Ext.WindowManager instance.
            // It can also happen that Container's zIndexManager is destroyed before this.
            if (me.zIndexManager && !me.zIndexManager.destroyed) {
                me.zIndexManager.unregister(me);
            }
            
            // Some components may set floating as config object, which will be nulled
            // in the base destructor. We need this property in Containers, so set it
            // to Boolean instead.
            me.floating = true;
        }
 
        me.removeBindings();
        
        if (!me.beforeDestroy.$emptyFn) {
            me.beforeDestroy();
        }
 
        me.destroyBindable();
 
        if (ownerCt && ownerCt.remove) {
            ownerCt.remove(me, {
                destroy: false
            });
        }
 
        me.stopAnimation();
        
        // Ensure that any ancillary components are destroyed.
        if (me.rendered) {
            Ext.destroy(
                me.loadMask,
                me.dd,
                me.resizer,
                me.proxy,
                me.proxyWrap,
                me.resizerComponent,
                me.scrollable,
                me.contentEl
            );
        }
 
        if (focusableContainer && !focusableContainer.onFocusableChildDestroy.$nullFn) {
            focusableContainer.onFocusableChildDestroy(me);
        }
 
        if (me.focusable) {
            me.destroyFocusable();
        }
 
        // Destroying the floatingItems ZIndexManager will also destroy descendant floating Components
        Ext.destroy(
            me.componentLayout,
            me.loadMask,
            me.floatingDescendants
        );
        
        if (!me.onDestroy.$emptyFn) {
            me.onDestroy();
        }
 
        // Attempt to destroy all plugins
        Ext.destroy(me.plugins);
 
        if (me.rendered) {
            Ext.Component.cancelLayout(me, true);
        }
 
        me.componentLayout = null;
        
        if (me.hasListeners.destroy) {
            me.fireEvent('destroy', me);
        }
        
        if (!me.preventRegister) {
            Ext.ComponentManager.unregister(me);
        }
 
        me.mixins.state.destroy.call(me);
 
        if (me.floating) {
            me.onFloatDestroy();
        }
 
        // make sure we clean up the element references after removing all events
        if (me.rendered) {
            if (me.showListenerIE) {
                me.showListenerIE.destroy();
                me.showListenerIE = null;
            }
            
            if (!me.preserveElOnDestroy) {
                me.el.destroy();
            }
            
            // We don't own the container element so can't just destroy it as that would
            // remove it from the DOM; we have to remove the Element instance from cache
            // though.
            if (me.collectContainerElement && container) {
                if (!container.destroyed) {
                    container.collect();
                }
                me.container = null;
            }
            
            me.el.component = null;
            me.mixins.elementCt.destroy.call(me); // removes childEls
            
            if (selectors) {
                for (selector in selectors) {
                    if (selectors.hasOwnProperty(selector)) {
                        el = me[selector];
                        
                        if (el) { // in case any other code may have already removed it
                            delete me[selector];
                            el.destroy();
                        }
                    }
                }
            }
 
            // This is a very special boolean that warrants explicit clearing
            me.rendered = false;
        }
    },
 
    /**
     * Disable the component.
     * @param {Boolean} [silent=false] Passing `true` will suppress the `disable` event from being fired.
     * @param fromParent (private)
     * @since 1.1.0
     */
    disable: function(silent, fromParent) {
        var me = this,
            container = me.ownerFocusableContainer,
            inherited = me.getInherited();
 
        if (!fromParent) {
            inherited.disabled = true;
            me.savedDisabled = true;
        }
 
        if (me.maskOnDisable) {
            inherited.disableMask = true;
        }
 
        if (!me.disabled) {
            if (container && !container.beforeFocusableChildDisable.$nullFn) {
                container.beforeFocusableChildDisable(me);
            }
 
            me.addCls(me.disabledCls);
 
            if (me.rendered) {
                me.onDisable();
            }
            else {
                me.disableOnRender = true;
            }
 
            me.disabled = true;
 
            if (silent !== true) {
                me.fireEvent('disable', me);
            }
 
            if (container && !container.onFocusableChildDisable.$nullFn) {
                container.onFocusableChildDisable(me);
            }
        }
 
        return me;
    },
 
    doFireEvent: function(eventName, args, bubbles) {
        var me = this,
            ret;
        
        ret = me.mixins.observable.doFireEvent.call(me, eventName, args, bubbles);
        
        // The Component instance can be destroyed in the handler, in which case
        // we can't fire delegated events on it anymore.
        if (ret !== false && !me.destroyed) {
            ret = me.mixins.componentDelegation.doFireDelegatedEvent.call(me, eventName, args);
        }
 
        return ret;
    },
 
    /**
     * Enable the component
     * @param {Boolean} [silent=false] Passing `true` will suppress the `enable` event from being fired.
     * @param fromParent (private)
     * @since 1.1.0
     */
    enable: function(silent, fromParent) {
        var me = this,
            container = me.ownerFocusableContainer,
            inherited = me.getInherited();
 
        if (!fromParent) {
            delete me.getInherited().disabled;
            me.savedDisabled = false;
        }
 
        if (me.maskOnDisable) {
            delete inherited.disableMask;
        }
 
        if (me.disabled) {
            // A parent is asking us to enable, but if we were disabled directly, keep
            // our current state
            if (!(fromParent && inherited.hasOwnProperty('disabled'))) {
                if (container && !container.beforeFocusableChildEnable.$nullFn) {
                    container.beforeFocusableChildEnable(me);
                }
 
                me.disableOnRender = false;
                me.removeCls(me.disabledCls);
 
                if (me.rendered) {
                    me.onEnable();
                }
 
                me.disabled = false;
 
                if (silent !== true) {
                    me.fireEvent('enable', me);
                }
 
                if (container && !container.onFocusableChildEnable.$nullFn) {
                    container.onFocusableChildEnable(me);
                }
            }
        }
 
        return me;
    },
 
    /**
     * Find a container above this component at any level by a custom function. If the passed function returns true, the
     * container will be returned.
     *
     * See also the {@link Ext.Component#up up} method.
     *
     * @param {Function} fn The custom function to call with the arguments (container, this component).
     * @return {Ext.container.Container} The first Container for which the custom function returns true
     */
    findParentBy: function(fn) {
        var p;
 
        // Iterate up the owner chain until we don't have one, or we find an ancestor which matches using the selector function.
        for (= this.getRefOwner(); p && !fn(p, this); p = p.getRefOwner()) {
            // do nothing
        }
        return p || null;
    },
 
    /**
     * Find a container above this component at any level by xtype or class
     *
     * See also the {@link Ext.Component#up up} method.
     *
     * @param {String/Ext.Class} xtype The xtype string for a component, or the class of the component directly
     * @return {Ext.container.Container} The first Container which matches the given xtype or class
     */
    findParentByType: function(xtype) {
        return Ext.isFunction(xtype) ?
            this.findParentBy(function(p) {
                return p.self === xtype || p.constructor === xtype;
            })
        :
            this.up(xtype);
    },
 
    /**
     * Retrieves plugin from this component's collection by its `ptype`.
     *
     *     var grid = Ext.create('Ext.grid.Panel', {
     *         store: {
     *             fields: ['name'],
     *             data: [{
     *                 name: 'Scott Pilgrim'
     *             }]
     *         },
     *         columns: [{
     *             header: 'Name',
     *             dataIndex: 'name',
     *             editor: 'textfield',
     *             flex: 1
     *         }],
     *         selType: 'cellmodel',
     *         plugins: [{
     *             ptype: 'cellediting',
     *             clicksToEdit: 1,
     *             id: 'myplugin'
     *         }],
     *         height: 200,
     *         width: 400,
     *         renderTo: Ext.getBody()
     *     });
     *
     *     grid.findPlugin('cellediting');  // the cellediting plugin
     *
     * **Note:** See also {@link #getPlugin}
     *
     * @param {String} ptype The Plugin's `ptype` as specified by the class's
     * {@link Ext.Class#cfg-alias alias} configuration.
     * @return {Ext.plugin.Abstract} plugin instance or `undefined` if not found
     */
    findPlugin: function(ptype) {
        var i,
            plugins = this.plugins,
            ln = plugins && plugins.length;
 
        for (= 0; i < ln; i++) {
            if (plugins[i].ptype === ptype) {
                return plugins[i];
            }
        }
    },
 
    getAnimateTarget: function(target){
        target = target || this.animateTarget;
        if (target) {
            target = target.isComponent ? target.getEl() : Ext.get(target);
        }
        return target || null;
    },
 
    /**
     * @protected
     * Implements an upward event bubbling policy. By default a Component bubbles events up to its {@link #getRefOwner reference owner}.
     *
     * Component subclasses may implement a different bubbling strategy by overriding this method.
     */
    getBubbleTarget: function() {
        return this.getRefOwner();
    },
 
    getComponentLayout: function() {
        var me = this;
 
        if (!me.componentLayout || !me.componentLayout.isLayout) {
            me.setComponentLayout(Ext.layout.Layout.create(me.componentLayout, 'autocomponent'));
        }
        return me.componentLayout;
    },
 
    /**
     * Retrieves the top level element representing this component.
     * @return {Ext.dom.Element} 
     * @since 1.1.0
     */
    getEl: function() {
        return this.el;
    },
 
    /**
     * Gets the current height of the component's underlying element.
     * @return {Number} 
     */
    getHeight: function() {
        return this.el.getHeight();
    },
 
    /**
     * Called by `getInherited` to initialize the inheritedState the first time it is
     * requested.
     * @protected
     */
    initInheritedState: function (inheritedState) {
        var me = this,
            layout = me.componentLayout;
 
        if (me.hidden) {
            inheritedState.hidden = true;
        }
        if (me.collapseImmune) {
            inheritedState.collapseImmune = true;
        }
        if (me.modelValidation !== undefined) {
            inheritedState.modelValidation = me.modelValidation;
        }
 
        if (me.savedDisabled) {
            inheritedState.disabled = true;
        }
 
        me.mixins.bindable.initInheritedState.call(me, inheritedState);
 
        if (layout && layout.initInheritedState) {
            layout.initInheritedState(inheritedState);
        }
    },
 
    /**
     * Retrieves the `id` of this component. Will auto-generate an `id` if one has not already been set.
     * @return {String} 
     */
    getId: function() {
        var me = this,
            xtype;
 
        // If we have no id, attempt to gather it from our configuration.
        // Autogenerate it if none was configured.
        if (!(me.id || (me.id = me.initialConfig.id))) {
            xtype = me.getXType();
            if (xtype) {
                xtype = xtype.replace(Ext.Component.INVALID_ID_CHARS_Re, '-');
            } else {
                xtype = Ext.name.toLowerCase() + '-comp';
            }
            me.id = xtype + '-' + me.getAutoId();
        }
        return me.id;
    },
 
    /**
     * Returns the value of {@link #itemId} assigned to this component, or when that
     * is not set, returns the value of {@link #id}.
     * @return {String} 
     */
    getItemId: function() {
        return this.itemId || this.id;
    },
 
    /**
     * Gets the {@link Ext.ComponentLoader} for this Component.
     * @return {Ext.ComponentLoader} The loader instance, null if it doesn't exist.
     */
    getLoader: function(){
        var me = this,
            loader = me.loader;
 
        if (loader) {
            if (!loader.isLoader) {
                me.loader = new Ext.ComponentLoader(Ext.apply({
                    target: me
                }, loader));
            } else {
                loader.setTarget(me);
            }
            return me.loader;
 
        }
        return null;
    },
 
    /**
     * @protected
     * Returns the element which is masked by the {@link #mask} method, or into which the {@link #setLoading LoadMask} is rendered into.
     *
     * The default implementation uses the {@link #maskElement} configuration to access the Component's child element by name. By default, {@link #maskElement}
     * is `null` which means that `null` is returned from this method indicating that the mask needs to be rendered into the document because
     * component structure should not be contaminated by mask elements.
     *
     * Some subclasses may override this method if they have knowledge about external structures where a mask could usefully be rendered.
     *
     * For example a {@link Ext.view.Table GridView} will request that its owning {@link Ext.panel.Table GridPanel} be masked. The
     * GridPanel will have its own implementation of `getMaskTarget` which will return the element dictated by its own {@link #maskElement}
     * Panels use `"el"` as their {@link #maskElement} by default, but that could be overridden to be `"body"` to leave toolbars and the header
     * mouse-accessible.
     *
     */
    getMaskTarget: function() {
        return this.maskElement ? this[this.maskElement] : null;
    },
 
    /**
     * Retrieves a plugin from this component's collection by its `id`.
     *
     *     var grid = Ext.create('Ext.grid.Panel', {
     *         store: {
     *             fields: ['name'],
     *             data: [{
     *                 name: 'Scott Pilgrim'
     *             }]
     *         },
     *         columns: [{
     *             header: 'Name',
     *             dataIndex: 'name',
     *             editor: 'textfield',
     *             flex: 1
     *         }],
     *         selType: 'cellmodel',
     *         plugins: [{
     *             ptype: 'cellediting',
     *             clicksToEdit: 1,
     *             id: 'myplugin'
     *         }],
     *         height: 200,
     *         width: 400,
     *         renderTo: Ext.getBody()
     *     });
     *
     *     grid.getPlugin('myplugin');  // the cellediting plugin
     *
     * **Note:** See also {@link #findPlugin}. Prior to 6.2.0 the plugin had to have a
     * `{@link Ext.plugin.Abstract#pluginId pluginId}` property but this can now be just
     * `{@link Ext.plugin.Abstract#id id}`. Both are supported (so plugins with a
     * matching `pluginId` are still found) but `id` is preferred.
     *
     * @param {String} id The `id` set on the plugin config object.
     * @return {Ext.plugin.Abstract} plugin instance or `null` if not found
     */
    getPlugin: function (id) {
        var i,
            plugins = this.plugins,
            ln = plugins && plugins.length,
            plugin;
 
        for (= 0; i < ln; i++) {
            plugin = plugins[i];
            // pre-6.2 we only considered pluginId property...
            if (plugin.id === id || plugin.pluginId === id) {
                return plugin;
            }
        }
 
        return null;
    },
 
    /**
     * Gets the current XY position of the component's underlying element.
     * @param {Boolean} [local=false] If true the element's left and top are returned instead of page XY.
     * @return {Number[]} The XY position of the element (e.g., [100, 200])
     */
    getPosition: function(local) {
        var me = this,
            xy,
            isContainedFloater = me.isContainedFloater(),
            floatParentBox;
 
        // Local position for non-floaters means element's local position
        if ((local === true) && !isContainedFloater) {
            return [me.getLocalX(), me.getLocalY()];
        }
 
        xy = me.getXY();
 
        // Local position for floaters means position relative to the container's target element
        if ((local === true) && isContainedFloater) {
            floatParentBox = me.floatParent.getTargetEl().getViewRegion();
            xy[0] -= floatParentBox.left;
            xy[1] -= floatParentBox.top;
        }
        return xy;
    },
 
    /**
     * Returns the "x" scroll position for this component.  Only applicable for
     * {@link #scrollable} components
     * @return {Number} 
     */
    getScrollX: function() {
        var scroller = this.getScrollable();
        return scroller ? scroller.getPosition().x : 0;
    },
 
    /**
     * Returns the "y" scroll position for this component.  Only applicable for
     * {@link #scrollable} components
     * @return {Number} 
     */
    getScrollY: function() {
        var scroller = this.getScrollable();
        return scroller ? scroller.getPosition().y : 0;
    },
 
    /**
     * Gets the current size of the component's underlying element.
     * @param {Boolean} [contentSize] true to get the width/size minus borders and padding
     * @return {Object} An object containing the element's size:
     * @return {Number} return.width
     * @return {Number} return.height
     */
    getSize: function(contentSize) {
        return this.el.getSize(contentSize);
    },
 
    /**
     * Returns an object that describes how this component's width and height are managed.
     * All of these objects are shared and should not be modified.
     *
     * @return {Object} The size model for this component.
     * @return {Ext.layout.SizeModel} return.width The {@link Ext.layout.SizeModel size model}
     * for the width.
     * @return {Ext.layout.SizeModel} return.height The {@link Ext.layout.SizeModel size model}
     * for the height.
     * @protected
     */
    getSizeModel: function (ownerCtSizeModel) {
        var me = this,
            models = Ext.layout.SizeModel,
            ownerContext = me.componentLayout.ownerContext,
            width = me.width,
            height = me.height,
            typeofWidth, typeofHeight,
            hasPixelWidth, hasPixelHeight,
            hasWidthStyle, hasHeightStyle,
            heightModel, ownerLayout, policy, shrinkWrap, topLevel, widthModel,
 
            // floating === a floating Component, floated === a border layout's slideout view of a region.
            isFloating = me.floating || me.floated;
 
        if (ownerContext) {
            // If we are in the middle of a running layout, always report the current,
            // dynamic size model rather than recompute it. This is not (only) a time
            // saving thing, but a correctness thing since we cannot get the right answer
            // otherwise.
            widthModel = ownerContext.widthModel;
            heightModel = ownerContext.heightModel;
        }
 
        if (!widthModel || !heightModel) {
            hasPixelWidth = ((typeofWidth = typeof width) === 'number');
            hasPixelHeight = ((typeofHeight = typeof height) === 'number');
            topLevel = isFloating || !(ownerLayout = me.ownerLayout);
 
            // Floating or no owner layout, e.g. rendered using renderTo
            if (topLevel) {
                policy = Ext.layout.Layout.prototype.autoSizePolicy;
                shrinkWrap = isFloating ? 3 : me.shrinkWrap;
 
                if (hasPixelWidth) {
                    widthModel = models.configured;
                }
 
                if (hasPixelHeight) {
                    heightModel = models.configured;
                }
            } else {
                policy = ownerLayout.getItemSizePolicy(me, ownerCtSizeModel);
                shrinkWrap = ownerLayout.isItemShrinkWrap(me);
            }
 
            if (ownerContext) {
                ownerContext.ownerSizePolicy = policy;
            }
 
            shrinkWrap = (shrinkWrap === true) ? 3 : (shrinkWrap || 0); // false->0, true->3
 
            // Now that we have shrinkWrap as a 0-3 value, we need to turn off shrinkWrap
            // bits for any dimension that has a configured size not in pixels. These must
            // be read from the DOM.
            //
            if (topLevel && shrinkWrap) {
                if (width && typeofWidth === 'string') {
                    shrinkWrap &= 2; // percentage, "30em" or whatever - not width shrinkWrap
                    hasWidthStyle = true;
                }
                
                if (height && typeofHeight === 'string') {
                    shrinkWrap &= 1; // percentage, "30em" or whatever - not height shrinkWrap
                    hasHeightStyle = true;
                }
            }
 
            if (shrinkWrap !== 3) {
                if (!ownerCtSizeModel) {
                    ownerCtSizeModel = me.ownerCt && me.ownerCt.getSizeModel();
                }
 
                if (ownerCtSizeModel) {
                    shrinkWrap |= (ownerCtSizeModel.width.shrinkWrap ? 1 : 0) | (ownerCtSizeModel.height.shrinkWrap ? 2 : 0);
                }
            }
 
            if (!widthModel) {
                if (!policy.setsWidth && !(me.frame && hasWidthStyle)) {
                    if (hasPixelWidth) {
                        widthModel = models.configured;
                    } else {
                        widthModel = (shrinkWrap & 1) ? models.shrinkWrap : models.natural;
                    }
                } else if (policy.readsWidth) {
                    if (hasPixelWidth) {
                        widthModel = models.calculatedFromConfigured;
                    } else {
                        widthModel = (shrinkWrap & 1) ? models.calculatedFromShrinkWrap :
                                    models.calculatedFromNatural;
                    }
                } else {
                    widthModel = models.calculated;
                }
            }
 
            if (!heightModel) {
                if (!policy.setsHeight && !(me.frame && hasHeightStyle)) {
                    if (hasPixelHeight) {
                        heightModel = models.configured;
                    } else {
                        heightModel = (shrinkWrap & 2) ? models.shrinkWrap : models.natural;
                    }
                } else if (policy.readsHeight) {
                    if (hasPixelHeight) {
                        heightModel = models.calculatedFromConfigured;
                    } else {
                        heightModel = (shrinkWrap & 2) ? models.calculatedFromShrinkWrap :
                                    models.calculatedFromNatural;
                    }
                } else {
                    heightModel = models.calculated;
                }
            }
        }
 
        // We return one of the cached objects with the proper "width" and "height" as the
        // sizeModels we have determined.
        return widthModel.pairsByHeightOrdinal[heightModel.ordinal];
    },
 
    /**
     * The supplied default state gathering method for the Component class.
     *
     * This method returns dimension settings such as `flex`, `anchor`, `width` and `height` along with `collapsed`
     * state.
     *
     * Subclasses which implement more complex state should call the superclass's implementation, and apply their state
     * to the result if this basic state is to be saved.
     *
     * Note that Component state will only be saved if the Component has a {@link #stateId} and there as a StateProvider
     * configured for the document.
     *
     * @return {Object} 
     */
    getState: function() {
        var me = this,
            state = null,
            sizeModel = me.getSizeModel();
 
        if (sizeModel.width.configured) {
            state = me.addPropertyToState(state, 'width');
        }
        if (sizeModel.height.configured) {
            state = me.addPropertyToState(state, 'height');
        }
 
        return state;
    },
 
    getUserCls: function () {
        return this.userCls;
    },
 
    setUserCls: function (cls) {
        var me = this,
            was = me.userCls;
 
        if (cls !== was) {
            me.userCls = cls;
 
            if (me.rendered) {
                me.el.replaceCls(was, cls);
            }
        }
 
        return was;
    },
 
    /**
     * Gets the current width of the component's underlying element.
     * @return {Number} 
     */
    getWidth: function() {
        return this.el.getWidth();
    },
 
    /**
     * Gets the xtype for this component as registered with {@link Ext.ComponentManager}. For a list of all available
     * xtypes, see the {@link Ext.Component} header. Example usage:
     *
     *     var t = new Ext.form.field.Text();
     *     alert(t.getXType());  // alerts 'textfield'
     *
     * @return {String} The xtype
     */
    getXType: function() {
        return this.self.xtype;
    },
 
    /**
     * Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all available xtypes, see the
     * {@link Ext.Component} header.
     *
     * **If using your own subclasses, be aware that a Component must register its own xtype to participate in
     * determination of inherited xtypes.**
     *
     * Example usage:
     *
     *     @example
     *     var t = new Ext.form.field.Text();
     *     alert(t.getXTypes());  // alerts 'component/field/textfield'
     *
     * @return {String} The xtype hierarchy string
     *
     * @since 2.3.0
     */
    getXTypes: function() {
        var self = this.self,
            xtypes, parentPrototype, parentXtypes;
 
        if (!self.xtypes) {
            xtypes = [];
            parentPrototype = this;
 
            while (parentPrototype) {
                parentXtypes = parentPrototype.xtypes;
 
                if (parentXtypes !== undefined) {
                    xtypes.unshift.apply(xtypes, parentXtypes);
                }
 
                parentPrototype = parentPrototype.superclass;
            }
 
            self.xtypeChain = xtypes;
            self.xtypes = xtypes.join('/');
        }
 
        return self.xtypes;
    },
 
    /**
     * Checks if the specified CSS class exists on this element's DOM node.
     * @param {String} className The CSS class to check for.
     * @return {Boolean} `true` if the class exists, else `false`.
     * @method
     */
    hasCls: function (className) {
        var el = this.rendered ? this.el : this.protoEl;
        return el.hasCls.apply(el, arguments);
    },
 
    /**
     * Checks if there is currently a specified `uiCls`.
     * @param {String} cls The `cls` to check.
     */
    hasUICls: function(cls) {
        var me = this,
            uiCls = me.uiCls || [];
 
        return Ext.Array.contains(uiCls, cls);
    },
 
    /**
     * Hides this Component, setting it to invisible using the configured {@link #cfg-hideMode}.
     * @param {String/Ext.dom.Element/Ext.Component} [animateTarget=null] **only valid for {@link #cfg-floating} Components
     * such as {@link Ext.window.Window Window}s or {@link Ext.tip.ToolTip ToolTip}s, or regular Components which have
     * been configured with `floating: true`.**. The target to which the Component should animate while hiding.
     * @param {Function} [callback] A callback function to call after the Component is hidden.
     * @param {Object} [scope] The scope (`this` reference) in which the callback is executed.
     * Defaults to this Component.
     * @return {Ext.Component} this
     */
    hide: function(animateTarget, callback, scope) {
        var me = this,
            container = me.ownerFocusableContainer;
 
        if (me.pendingShow) {
            // If this is a hierarchically hidden floating component with a pending show
            // hide() simply cancels the pending show.
            me.pendingShow = false;
        }
 
        if (!(me.rendered && !me.isVisible())) {
            if (!me.hasListeners.beforehide || me.fireEvent('beforehide', me) !== false || me.hierarchicallyHidden) {
                me.getInherited().hidden = me.hidden = true;
                
                if (container && !container.beforeFocusableChildHide.$nullFn) {
                    container.beforeFocusableChildHide(me);
                }
 
                // Order of events is important here. Hierarchy event kicks off
                // ZIndexManager's collection sorting and floater activation;
                // The hidden flag must be set so that ZIndexManager takes it out of its stack.
                me.fireHierarchyEvent('beforehide');
 
                if (me.rendered) {
                    me.onHide.apply(me, arguments);
                }
            }
        }
        
        return me;
    },
 
    /**
     * The initComponent template method is an important initialization step for a Component. It is intended to be
     * implemented by each subclass of Ext.Component to provide any needed constructor logic. The
     * initComponent method of the class being created is called first, with each initComponent method
     * up the hierarchy to Ext.Component being called thereafter. This makes it easy to implement and,
     * if needed, override the constructor logic of the Component at any step in the hierarchy.
     *
     * The initComponent method **must** contain a call to {@link Ext.Base#method!callParent callParent} in order
     * to ensure that the parent class' initComponent method is also called.
     *
     * All config options passed to the constructor are applied to `this` before initComponent is called,
     * so you can simply access them with `this.someOption`.
     *
     * The following example demonstrates using a dynamic string for the text of a button at the time of
     * instantiation of the class.
     *
     *     Ext.define('DynamicButtonText', {
     *         extend: 'Ext.button.Button',
     *
     *         initComponent: function() {
     *             this.text = new Date();
     *             this.renderTo = Ext.getBody();
     *             this.callParent();
     *         }
     *     });
     *
     *     Ext.onReady(function() {
     *         Ext.create('DynamicButtonText');
     *     });
     *
     * @template
     * @protected
     * @since 1.1.0
     */
    initComponent: function () {
        var me = this,
            width = me.width,
            height = me.height;
 
        // If plugins have been added by a subclass's initComponent before calling up to here (or any components
        // that don't have a table view), the processed flag will not have been set, and we must process them again.
        // We could just call getPlugins here however most components don't have them so prevent the extra function call.
        if (me.plugins && !me.plugins.processed) {
            me.constructPlugins();
        }
        me.pluginsInitialized = true;
 
        // this will properly (ignore or) constrain the configured width/height to their
        // min/max values for consistency.
        if (width != null || height != null) {
            me.setSize(width, height);
        }
 
        if (me.listeners) {
            me.on(me.listeners);
            me.listeners = null; //change the value to remove any on prototype
        }
 
        if (me.focusable) {
            me.initFocusable();
        }
    },
 
    /**
     * Initialize any events on this component
     * @protected
     */
    initEvents: function() {
        var me = this,
            afterRenderEvents = me.afterRenderEvents,
            afterRenderEvent, el, property, index, len;
 
        if (afterRenderEvents) {
            for (property in afterRenderEvents) {
                el = me[property];
 
                if (el && el.on) {
                    afterRenderEvent = afterRenderEvents[property];
 
                    for (index = 0, len = afterRenderEvent.length ; index < len ; ++index) {
                        me.mon(el, afterRenderEvent[index]);
                     }
                 }
            }
        }
 
        if (me.focusable) {
            me.initFocusableEvents();
        }
 
        // FocusableContainers are not themselves focusable, but they must process
        // their keyMap config
        me.initKeyMap();
    },
 
    /**
     * Tests whether this Component matches a {@link Ext.ComponentQuery ComponentQuery}
     * selector string.
     * @param {String} selector The selector string to test against.
     * @return {Boolean} `true` if this Component matches the selector.
     */
    is: function(selector) {
        return Ext.ComponentQuery.is(this, selector);
    },
 
    /**
     * Method to determine whether this Component is currently disabled.
     * @return {Boolean} the disabled state of this Component.
     */
    isDisabled: function() {
        return this.disabled;
    },
 
    /**
     * Method to determine whether this Component is draggable.
     * @return {Boolean} the draggable state of this component.
     */
    isDraggable: function() {
        return !!this.draggable;
    },
 
    /**
     * Method to determine whether this Component is droppable.
     * @return {Boolean} the droppable state of this component.
     */
    isDroppable: function() {
        return !!this.droppable;
    },
 
    /**
     * Method to determine whether this Component is floating.
     * @return {Boolean} the floating state of this component.
     */
    isFloating: function() {
        return this.floating;
    },
 
    /**
     * Method to determine whether this Component is currently set to hidden.
     * @return {Boolean} the hidden state of this Component.
     */
    isHidden: function() {
        return this.hidden;
    },
    
    getHidden: function() {
        return this.hidden;
    },
 
    isHierarchicallyHidden: function() {
        var child = this,
            hidden = false,
            parent, parentInheritedState;
 
        // It is possible for some components to be immune to collapse meaning the immune
        // component remains visible when its direct parent is collapsed, e.g. panel header.
        // Because of this, we must walk up the component hierarchy to determine the true
        // visible state of the component.
        for (; (parent = child.ownerCt || child.floatParent); child = parent) {
            parentInheritedState = parent.getInherited();
            if (parentInheritedState.hidden) {
                hidden = true;
                break;
            }
            if (child.getInherited().collapseImmune) {
                // The child or one of its ancestors is immune to collapse.
                if (parent.collapsed && !child.collapseImmune) {
                    // If the child's direct parent is collapsed, and the child
                    // itself does not have collapse immunity we know that
                    // the child is not visible.
                    hidden = true;
                    break;
                }
            } else {
                // We have ascended the tree to a point where collapse immunity
                // is not in play.  This means if any ancestor above this point
                // is collapsed, then the component is not visible.
                hidden = !!parentInheritedState.collapsed;
                break;
            }
        }
 
        return hidden;
    },
 
    /**
     * Checks if this component will be contained by the passed component as part of its
     * layout run. If `true`, then the layout on `this` can be skipped because it will be
     * encompassed when the layout for `comp` runs. Typical cases where this may be be `false`
     * is when asking about floaters nested in containers.
     * @param {Ext.Component} ownerCandidate The potential owner.
     * @return {Boolean} `true` if this component is a layout child of `comp`.
     *
     * @private
     */
    isLayoutChild: function(ownerCandidate) {
        return !this.floating && !!this.up(ownerCandidate);
    },
 
    /**
     * Determines whether this Component is the root of a layout. This returns `true` if
     * this component can run its layout without assistance from or impact on its owner.
     * If this component cannot run its layout given these restrictions, `false` is returned
     * and its owner will be considered as the next candidate for the layout root.
     *
     * Setting the {@link #_isLayoutRoot} property to `true` causes this method to always
     * return `true`. This may be useful when updating a layout of a Container which shrink
     * wraps content, and you know that it will not change size, and so can safely be the
     * topmost participant in the layout run.
     * @protected
     */
    isLayoutRoot: function() {
        var me = this,
            ownerLayout = me.ownerLayout;
 
        // Return true if we have been explicitly flagged as the layout root, or if we are floating.
        // Sometimes floating Components get an ownerCt ref injected into them which is *not* a true ownerCt, merely
        // an upward link for reference purposes. For example a grid column menu is linked to the
        // owning header via an ownerCt reference.
        if (!ownerLayout || me._isLayoutRoot || me.floating) {
            return true;
        }
 
        return ownerLayout.isItemLayoutRoot(me);
    },
 
    /**
     * Returns `true` if layout is suspended for this component. This can come from direct
     * suspension of this component's layout activity ({@link Ext.Container#suspendLayout}) or if one
     * of this component's containers is suspended.
     *
     * @return {Boolean} `true` layout of this component is suspended.
     */
    isLayoutSuspended: function () {
        var comp = this,
            ownerLayout;
 
        while (comp) {
            if (comp.layoutSuspendCount || comp.suspendLayout) {
                return true;
            }
 
            ownerLayout = comp.ownerLayout;
            if (!ownerLayout) {
                break;
            }
 
            // TODO - what about suspending a Layout instance?
 
            // this works better than ownerCt since ownerLayout means "is managed by" in
            // the proper sense... some floating components have ownerCt but won't have an
            // ownerLayout
            comp = ownerLayout.owner;
        }
 
        return false;
    },
 
    /**
     * Returns `true` if this component is visible.
     *
     * @param {Boolean} [deep=false] Pass `true` to interrogate the visibility status of all parent Containers to
     * determine whether this Component is truly visible to the user.
     *
     * Generally, to determine whether a Component is hidden, the no argument form is needed. For example when creating
     * dynamically laid out UIs in a hidden Container before showing them.
     *
     * @return {Boolean} `true` if this component is visible, `false` otherwise.
     *
     * @since 1.1.0
     */
    isVisible: function(deep) {
        var me = this,
            hidden;
 
        if (me.hidden || !me.rendered || me.destroyed) {
            hidden = true;
        } else if (deep) {
            hidden = me.isHierarchicallyHidden();
        }
 
        return !hidden;
    },
 
    /**
     * Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended
     * from the xtype (default) or whether it is directly of the xtype specified (`shallow = true`).
     *
     * **If using your own subclasses, be aware that a Component must register its own xtype to participate in
     * determination of inherited xtypes.**
     *
     * For a list of all available xtypes, see the {@link Ext.Component} header.
     *
     * Example usage:
     *
     *     @example
     *     var t = new Ext.form.field.Text();
     *     var isText = t.isXType('textfield');        // true
     *     var isBoxSubclass = t.isXType('field');       // true, descended from Ext.form.field.Base
     *     var isBoxInstance = t.isXType('field', true); // false, not a direct Ext.form.field.Base instance
     *
     * @param {String} xtype The xtype to check for this Component
     * @param {Boolean} [shallow=false] `true` to check whether this Component is directly of the specified xtype, `false` to
     * check whether this Component is descended from the xtype.
     * @return {Boolean} `true` if this component descends from the specified xtype, `false` otherwise.
     *
     * @since 2.3.0
     */
    isXType: function(xtype, shallow) {
        return shallow ? (Ext.Array.indexOf(this.xtypes, xtype) !== -1) :
                !!this.xtypesMap[xtype];
    },
 
    /**
     * Returns masked state for this Component.
     *
     * @param {Boolean} [deep=false] True to look up this Component's parent masked state.
     *
     * @return {Boolean} True if masked, false otherwise.
     */
    isMasked: function(deep) {
        var me = this;
 
        return !!(me.masked || (me.loadMask && me.loadMask.isVisible()) ||
               (deep && me.getInherited().masked));
    },
 
    /**
     * Gets a named template instance for this class. See {@link Ext.XTemplate#getTpl}.
     * @param {String} name The name of the property that holds the template.
     * @return {Ext.XTemplate} The template, `null` if not found.
     *
     * @since 6.2.0
     */
    lookupTpl: function(name) {
        return Ext.XTemplate.getTpl(this, name);
    },
 
    /**
     * Set masked state for this Component.
     *
     * @param {Boolean} isMasked True if masked, false otherwise.
     * @private
     */
    setMasked: function(isMasked) {
        var me = this,
            container = me.ownerFocusableContainer;
 
        if (isMasked) {
            me.masked = true;
            me.getInherited().masked = isMasked;
        } else {
            me.masked = false;
            delete me.getInherited().masked;
        }
 
        if (container && !container.onFocusableChildMasked.$nullFn) {
            container.onFocusableChildMasked(me, isMasked);
        }
 
        return me;
    },
 
    /**
     * Masks this component with a semi-opaque layer and makes the contents unavailable to clicks.
     *
     * See {@link #unmask}.
     *
     * @param {String} [msg] A message to show in the center of the mask layer.
     * @param {String} [msgCls] A CSS class name to use on the message element in the center of the layer.
     * @param {Number} elHeight (private) The height of element to be masked
     */
    mask: function (msg, msgCls, elHeight) {
        var box = this.lastBox,
            // getMaskTarget may be overridden in subclasses/
            // null means that a LoadMask has to be rendered to document.body
            // Element masking falls back to masking the local el
            target = this.getMaskTarget() || this.el;
 
        // Pass it the height of our element if we know it.
        if (box) {
            elHeight = box.height;
        }
        target.mask(msg, msgCls, elHeight);
 
        this.setMasked(true);
    },
 
    /**
     * Returns the next node in the Component tree in tree traversal order.
     *
     * Note that this is not limited to siblings, and if invoked upon a node with no matching siblings, will walk the
     * tree to attempt to find a match. Contrast with {@link #nextSibling}.
     * @param {String} [selector] {@link Ext.ComponentQuery ComponentQuery} selector to filter the following nodes.
     * @param includeSelf (private)
     * @return {Ext.Component} The next node (or the next node which matches the selector).
     * Returns `null` if there is no matching node.
     */
    nextNode: function(selector, includeSelf) {
        var node = this,
            ownerCt = node.ownerCt,
            result,
            it, len, i, sib;
 
        // If asked to include self, test me
        if (includeSelf && node.is(selector)) {
            return node;
        }
 
        if (ownerCt) {
            for (it = ownerCt.items.items, i = Ext.Array.indexOf(it, node) + 1, len = it.length; i < len; i++) {
                sib = it[i];
                if (sib.is(selector)) {
                    return sib;
                }
                if (sib.down) {
                    result = sib.down(selector);
                    if (result) {
                        return result;
                    }
                }
            }
            return ownerCt.nextNode(selector);
        }
        return null;
    },
 
    /**
     * Returns the next sibling of this Component.
     *
     * Optionally selects the next sibling which matches the passed {@link Ext.ComponentQuery ComponentQuery} selector.
     *
     * May also be referred to as **`next()`**
     *
     * Note that this is limited to siblings, and if no siblings of the item match, `null` is returned. Contrast with
     * {@link #nextNode}
     * @param {String} [selector] {@link Ext.ComponentQuery ComponentQuery} selector to filter the following items.
     * @return {Ext.Component} The next sibling (or the next sibling which matches the selector).
     * Returns `null` if there is no matching sibling.
     */
    nextSibling: function(selector) {
        var o = this.ownerCt, it, last, idx, c;
        if (o) {
            it = o.items;
            idx = it.indexOf(this) + 1;
            if (idx) {
                if (selector) {
                    for (last = it.getCount(); idx < last; idx++) {
                        if ((= it.getAt(idx)).is(selector)) {
                            return c;
                        }
                    }
                } else {
                    if (idx < it.getCount()) {
                        return it.getAt(idx);
                    }
                }
            }
        }
        return null;
    },
 
    /**
     * Method to manage awareness of when components are added to their
     * respective Container, firing an #added event. References are
     * established at add time rather than at render time.
     *
     * Allows addition of behavior when a Component is added to a
     * Container. At this stage, the Component is in the parent
     * Container's collection of child items. After calling the
     * superclass's `onAdded`, the `ownerCt` reference will be present,
     * and if configured with a ref, the `refOwner` will be set.
     *
     * @param {Ext.container.Container} container Container which holds the component.
     * @param {Number} pos Position at which the component was added.
     * @param {Boolean} instanced `false` if this component was instanced by the parent
     * container. `true` if the instance already existed when it was passed to the container.
     *
     * @template
     * @protected
     * @since 3.4.0
     */
    onAdded: function (container, pos, instanced) {
        var me = this;
 
        me.ownerCt = container;
 
        me.onInheritedAdd(me, instanced);
 
        if (me.hasListeners && me.hasListeners.added) {
            me.fireEvent('added', me, container, pos);
        }
 
        if (Ext.GlobalEvents.hasListeners.added) {
            me.fireHierarchyEvent('added');
        }
    },
 
    /**
     * Method to manage awareness of when components are removed from their
     * respective Container, firing a #removed event. References are properly
     * cleaned up after removing a component from its owning container.
     *
     * Allows addition of behavior when a Component is removed from
     * its parent Container. At this stage, the Component has been
     * removed from its parent Container's collection of child items,
     * but has not been destroyed (It will be destroyed if the parent
     * Container's `autoDestroy` is `true`, or if the remove call was
     * passed a truthy second parameter). After calling the
     * superclass's `onRemoved`, the `ownerCt` and the `refOwner` will not
     * be present.
     * @param {Boolean} destroying Will be passed as `true` if the Container performing the remove operation will delete this
     * Component upon remove.
     *
     * @template
     * @protected
     * @since 3.4.0
     */
    onRemoved: function(destroying) {
        var me = this,
            focusTarget;
 
        // Revert focus to closest sibling or ancestor unless we are being moved
        // In which case Ext.container.Container's move methods will handle
        // focus restoration.
        if (!me.isLayoutMoving && me.el && me.el.contains(Ext.Element.getActiveElement())) {
            focusTarget = me.findFocusTarget();
            if (focusTarget) {
                focusTarget.focus();
            }
        }
 
        if (Ext.GlobalEvents.hasListeners.removed) {
            me.fireHierarchyEvent('removed');
        }
 
        if (me.hasListeners.removed) {
            me.fireEvent('removed', me, me.ownerCt);
        }
 
        me.onInheritedRemove(destroying);
 
        me.ownerCt = me.ownerLayout = null;
    },
 
    /**
     * Invoked when this component has first achieved size. This occurs after the
     * {@link #componentLayout} has completed its initial run.
     *
     * This method is not called on components that use {@link #cfg-liquidLayout}, such as
     * {@link Ext.button.Button Buttons} and {@link Ext.form.field.Base Form Fields}.
     *
     * **Note:** If the Component has a {@link Ext.Component#controller ViewController}
     * and the controller has a {@link Ext.app.ViewController#boxReady boxReady} method
     * it will be called passing the Component and its width and height.
     *
     *      boxReady: function (view, width, height) {
     *          // ...
     *      }
     *
     * @param {Number} width The width of this component
     * @param {Number} height The height of this component
     *
     * @template
     * @protected
     */
    onBoxReady: function (width, height) {
        var me = this,
            label;
 
        // We have to do this lookup onBoxReady instead of afterRender
        // to ensure that the components that could be referenced in
        // me.ariaLabelledBy or me.ariaDescribedBy are already rendered
        if (me.ariaLabelledBy || me.ariaDescribedBy) {
            if (me.ariaLabelledBy) {
                label = me.getAriaLabelEl(me.ariaLabelledBy);
 
                if (label) {
                    me.ariaEl.dom.setAttribute('aria-labelledby', label);
                }
            }
 
            if (me.ariaDescribedBy) {
                label = me.getAriaLabelEl(me.ariaDescribedBy);
 
                if (label) {
                    me.ariaEl.dom.setAttribute('aria-describedby', label);
                }
            }
        }
 
        if (me.resizable) {
            me.initResizable(me.resizable);
        }
 
        // Draggability must be initialized after resizability
        // Because if we have to be wrapped, the resizer wrapper must be dragged as a pseudo-Component
        if (me.draggable) {
            me.initDraggable();
        }
 
        if (me.hasListeners.boxready) {
            me.fireEvent('boxready', me, width, height);
        }
    },
 
    /**
     * Allows addition of behavior to the destroy operation.
     *
     * @template
     * @method
     * @protected
     */
    onDestroy: Ext.emptyFn,
 
    /**
     * Allows addition of behavior to the disable operation.
     * After calling the superclass's `onDisable`, the Component will be disabled.
     *
     * @template
     * @protected
     */
    onDisable: function () {
        var me = this,
            dom, nodeName;
 
        if (me.focusable) {
            me.disableFocusable();
        }
 
        if (!me.ariaStaticRoles[me.ariaRole]) {
            me.ariaEl.dom.setAttribute('aria-disabled', true);
        }
 
        // Only mask if we're set to & nobody above us will do so
        if (me.maskOnDisable && !me.getInheritedConfig('disableMask', true)) {
            dom = me.el.dom;
            nodeName = dom.nodeName;
 
            if (me.disabledRe.test(nodeName)) {
                dom.disabled = true;
            }
 
            if (!me.nonMaskableRe.test(nodeName)) {
                me.mask();
            }
        }
    },
 
    /**
     * Allows addition of behavior to the enable operation.
     * After calling the superclass's `onEnable`, the Component will be enabled.
     *
     * @template
     * @protected
     */
    onEnable: function () {
        var me = this,
            dom, nodeName;
 
        if (me.focusable) {
            me.enableFocusable();
        }
 
        if (!me.ariaStaticRoles[me.ariaRole]) {
            me.ariaEl.dom.setAttribute('aria-disabled', false);
        }
 
        if (me.maskOnDisable && me.getInherited().hasOwnProperty('masked')) {
            dom = me.el.dom;
            nodeName = dom.nodeName;
 
            if (me.disabledRe.test(nodeName)) {
                dom.disabled = false;
            }
 
            if (!me.nonMaskableRe.test(nodeName)) {
                me.unmask();
            }
        }
    },
 
    onGlobalShow: function (c) {
        if (this.up(c)) {
            this.getScrollable().restoreState();
        }
    },
 
    /**
     * Allows addition of behavior to the hide operation. After
     * calling the superclass's onHide, the Component will be hidden.
     *
     * Gets passed the same parameters as #hide.
     *
     * @param {String/Ext.dom.Element/Ext.Component} [animateTarget]
     * @param {Function} [callback] Callback function to be called when finished
     * @param {Object} [scope] 
     *
     * @template
     * @protected
     */
    onHide: function(animateTarget, callback, scope) {
        var me = this,
            ghostPanel, fromSize, toBox;
 
        if (!me.ariaStaticRoles[me.ariaRole] && !me.destroying && !me.destroyed) {
            me.ariaEl.dom.setAttribute('aria-hidden', true);
        }
 
        // Part of the Focusable mixin API.
        // If we have focus now, move focus back to whatever had it before.
        me.revertFocus();
 
        // Default to configured animate target if none passed
        animateTarget = me.getAnimateTarget(animateTarget);
 
        // Need to be able to ghost the Component
        if (!me.ghost) {
            animateTarget = null;
        }
        // If we're animating, kick off an animation of the ghost down to the target
        if (animateTarget) {
            toBox = {
                x: animateTarget.getX(),
                y: animateTarget.getY(),
                width: animateTarget.dom.offsetWidth,
                height: animateTarget.dom.offsetHeight
            };
            ghostPanel = me.ghost();
            ghostPanel.el.stopAnimation();
            fromSize = me.getSize();
            ghostPanel.el.animate({
                to: toBox,
                listeners: {
                    afteranimate: function() {
                        if (!me.destroying) {
                            ghostPanel.componentLayout.lastComponentSize = null;
                            me.unghost(false);
                            ghostPanel.el.setSize(fromSize);
                            me.afterHide(callback, scope);
                        }
                    }
                }
            });
        } else {
            me.el.hide();
        }
        
        
        if (!animateTarget) {
            me.afterHide(callback, scope);
        }
    },
 
    /**
     * @method
     * Called after the component is moved, this method is empty by default but can be implemented by any
     * subclass that needs to perform custom logic after a move occurs.
     *
     * @param {Number} x The new x position.
     * @param {Number} y The new y position.
     *
     * @template
     * @protected
     */
    onPosition: Ext.emptyFn,
 
    /**
     * Called when the component is resized.
     *
     * This method is not called on components that use {@link #cfg-liquidLayout}, such as
     * {@link Ext.button.Button Buttons} and {@link Ext.form.field.Base Form Fields}.
     *
     * @param {Number} width The new width that was set
     * @param {Number} height The new height that was set
     * @param {Number} oldWidth The previous width
     * @param {Number} oldHeight The previous height
     *
     * @method
     * @template
     * @protected
     */
    onResize: function(width, height, oldWidth, oldHeight) {
        var me = this;
 
        // constrain is a config on Floating
        if (me.floating && me.constrain) {
            me.doConstrain();
        }
 
        if (me.hasListeners.resize) {
            me.fireEvent('resize', me, width, height, oldWidth, oldHeight);
        }
    },
 
    /**
     * Invoked when a scroll is initiated on this component via its {@link #scrollable scroller}.
     * @method onScrollStart
     * @param {Number} x The current x position
     * @param {Number} y The current y position
     * @template
     * @protected
     */
 
    /**
     * Invoked when this component is scrolled via its {@link #scrollable scroller}.
     * @method onScrollMove
     * @param {Number} x The current x position
     * @param {Number} y The current y position
     * @template
     * @protected
     */
 
    /**
     * Invoked when a scroll operation is completed via this component's {@link #scrollable scroller}.
     * @method onScrollEnd
     * @param {Number} x The current x position
     * @param {Number} y The current y position
     * @template
     * @protected
     */
 
    /**
     * Allows addition of behavior to the show operation. After
     * calling the superclass's onShow, the Component will be visible.
     *
     * Override in subclasses where more complex behaviour is needed.
     *
     * Gets passed the same parameters as #show.
     *
     * @param {String/Ext.dom.Element} [animateTarget]
     * @param {Function} [callback] 
     * @param {Object} [scope] 
     *
     * @template
     * @protected
     */
    onShow: function() {
        var me = this;
 
        if (!me.ariaStaticRoles[me.ariaRole]) {
            me.ariaEl.dom.setAttribute('aria-hidden', false);
        }
 
        me.el.show();
 
        me.updateLayout({ 
            isRoot: false,
            context: me._showContext
        });
 
        // Constraining/containing element may have changed size while this Component was hidden
        if (me.floating) {
            if (me.maximized) {
                me.fitContainer();
            }
            else if (me.constrain) {
                me.doConstrain();
            }
        }
    },
 
    _showContext: {
        show: true
    },
 
    /**
     * Invoked after the #afterShow method is complete.
     *
     * Gets passed the same `callback` and `scope` parameters that #afterShow received.
     *
     * @param {Function} [callback] 
     * @param {Object} [scope] 
     *
     * @template
     * @protected
     */
    onShowComplete: function(callback, scope) {
        var me = this,
            container = me.ownerFocusableContainer;
 
        if (me.floating) {
            me.onFloatShow();
        }
 
        Ext.callback(callback, scope || me);
        me.fireEvent('show', me);
 
        if (container && !container.onFocusableChildShow.$nullFn) {
            container.onFocusableChildShow(me);
        }
 
        delete me.hiddenByLayout;
    },
 
    onShowVeto: Ext.emptyFn,
 
    /**
     * Returns the previous node in the Component tree in tree traversal order.
     *
     * Note that this is not limited to siblings, and if invoked upon a node with no matching siblings, will walk the
     * tree in reverse order to attempt to find a match. Contrast with {@link #previousSibling}.
     * @param {String} [selector] {@link Ext.ComponentQuery ComponentQuery} selector to filter the preceding nodes.
     * @param includeSelf (private)
     * @return {Ext.Component} The previous node (or the previous node which matches the selector).
     * Returns `null` if there is no matching node.
     */
    previousNode: function(selector, includeSelf) {
        var node = this,
            ownerCt = node.ownerCt,
            result,
            it, i, sib;
 
        // If asked to include self, test me
        if (includeSelf && node.is(selector)) {
            return node;
        }
 
        if (ownerCt) {
            for (it = ownerCt.items.items, i = Ext.Array.indexOf(it, node) - 1; i > -1; i--) {
                sib = it[i];
                if (sib.query) {
                    result = sib.query(selector);
                    result = result[result.length - 1];
                    if (result) {
                        return result;
                    }
                }
                if (sib.is(selector)) {
                    return sib;
                }
            }
            return ownerCt.previousNode(selector, true);
        }
        return null;
    },
 
    /**
     * Returns the previous sibling of this Component.
     *
     * Optionally selects the previous sibling which matches the passed {@link Ext.ComponentQuery ComponentQuery}
     * selector.
     *
     * May also be referred to as **`prev()`**
     *
     * Note that this is limited to siblings, and if no siblings of the item match, `null` is returned. Contrast with
     * {@link #previousNode}
     * @param {String} [selector] {@link Ext.ComponentQuery ComponentQuery} selector to filter the preceding items.
     * @return {Ext.Component} The previous sibling (or the previous sibling which matches the selector).
     * Returns `null` if there is no matching sibling.
     */
    previousSibling: function(selector) {
        var o = this.ownerCt, it, idx, c;
        if (o) {
            it = o.items;
            idx = it.indexOf(this);
            if (idx !== -1) {
                if (selector) {
                    for (--idx; idx >= 0; idx--) {
                        if ((= it.getAt(idx)).is(selector)) {
                            return c;
                        }
                    }
                } else {
                    if (idx) {
                        return it.getAt(--idx);
                    }
                }
            }
        }
        return null;
    },
 
    /**
     * Called by Component#doAutoRender
     *
     * Register a Container configured `floating: true` with this Component's {@link Ext.ZIndexManager ZIndexManager}.
     *
     * Components added in this way will not participate in any layout, but will be rendered
     * upon first show in the way that {@link Ext.window.Window Window}s are.
     */
    registerFloatingItem: function(cmp) {
        var me = this;
        if (!me.floatingDescendants) {
            me.floatingDescendants = new Ext.ZIndexManager(me);
        }
        me.floatingDescendants.register(cmp);
    },
 
    /**
     * Removes a CSS class from the top level element representing this component.
     * @param {String/String[]} cls The CSS class name to remove.
     * @return {Ext.Component} Returns the Component to allow method chaining.
     */
    removeCls: function(cls) {
        var me = this,
            el = me.rendered ? me.el : me.protoEl;
 
        el.removeCls.apply(el, arguments);
        return me;
    },
 
    /**
     * Removes a `cls` to the `uiCls` array, which will also call {@link #removeUIClsFromElement} and removes it from all
     * elements of this component.
     * @param {String/String[]} classes A string or an array of strings to remove to the `uiCls`.
     * @param {Boolean} skip True to remove the class
     */
    removeClsWithUI: function(classes, skip) {
        var me = this,
            clsArray = [],
            i = 0,
            extArray = Ext.Array,
            remove = extArray.remove,
            uiCls = me.uiCls = extArray.clone(me.uiCls),
            activeUI = me.activeUI,
            length, cls;
 
        if (typeof classes === "string") {
            classes = (classes.indexOf(' ') < 0) ? [classes] : Ext.String.splitWords(classes);
        }
 
        length = classes.length;
 
        for (= 0; i < length; i++) {
            cls = classes[i];
 
            if (cls && me.hasUICls(cls)) {
                remove(uiCls, cls);
 
                //If there's no activeUI then there's nothing to remove
                if (activeUI) {
                    clsArray = clsArray.concat(me.removeUIClsFromElement(cls));
                }
            }
        }
 
        if (skip !== true && activeUI) {
            me.removeCls(clsArray);
        }
 
        return clsArray;
    },
 
    resumeLayouts: function (flushOptions) {
        var me = this;
        if (!me.rendered) {
            return;
        }
        //<debug>
        if (!me.layoutSuspendCount) {
            Ext.log.warn('Mismatched call to resumeLayouts - layouts are currently not suspended.');
        }
        //</debug>
        if (me.layoutSuspendCount && !--me.layoutSuspendCount) {
            me.suspendLayout = false;
            if (flushOptions && !me.isLayoutSuspended()) {
                me.updateLayout(flushOptions);
            }
        }
    },
 
    /**
     * Scrolls this Component by the passed delta values, optionally animating.
     *
     * All of the following are equivalent:
     *
     *      comp.scrollBy(10, 10, true);
     *      comp.scrollBy([10, 10], true);
     *      comp.scrollBy({ x: 10, y: 10 }, true);
     *
     * @param {Number/Number[]/Object} deltaX Either the x delta, an Array specifying x and y deltas or
     * an object with "x" and "y" properties.
     * @param {Number/Boolean/Object} deltaY Either the y delta, or an animate flag or config object.
     * @param {Boolean/Object} animate Animate flag/config object if the delta values were passed separately.
     */
    scrollBy: function(deltaX, deltaY, animate) {
        var scroller = this.getScrollable();
 
        if (scroller) {
            scroller.scrollBy(deltaX, deltaY, animate);
        }
    },
 
    /**
     * Scrolls this component to the specified `x` and `y` coordinates.  Only applicable
     * for {@link #scrollable} components.
     * @param {Number} x 
     * @param {Number} y 
     * @param {Boolean/Object} [animate] true for the default animation or a standard Element
     * animation config object
     */
    scrollTo: function(x, y, animate) {
        var scroller = this.getScrollable();
 
        if (scroller) {
            scroller.scrollTo(x, y, animate);
        }
    },
 
    /**
     * Sets the overflow on the content element of the component.
     * @param {Boolean} scroll True to allow the Component to auto scroll.
     * @return {Ext.Component} this
     * @deprecated 5.0.0 Use {@link #setScrollable} instead
     */
    setAutoScroll: function(scroll) {
        this.setScrollable(!!scroll);
        return this;
    },
 
    /**
     * @param {String/Number} border The border, see {@link #border}. If a falsey value is passed
     * @param targetEl (private)
     * the border will be removed.
     */
    setBorder: function(border, targetEl) {
        var me = this,
            initial = !!targetEl;
 
        if (me.rendered || initial) {
            if (!initial) {
                targetEl = me.el;
            }
 
            if (!border) {
                border = 0;
            } else if (border === true) {
                border = '1px';
            } else {
                border = this.unitizeBox(border);
            }
            targetEl.setStyle('border-width', border);
            if (!initial) {
                me.updateLayout();
            }
        }
        me.border = border;
    },
 
    /**
     * Sets the dock position of this component in its parent panel. Note that this only has effect if this item is part
     * of the `dockedItems` collection of a parent that has a DockLayout (note that any Panel has a DockLayout by default)
     * @param {Object} dock The dock position.
     * @return {Ext.Component} this
     */
    setDock: function(dock) {
        var me = this,
            ownerCt = me.ownerCt;
 
        if (dock !== me.dock) {
            if (ownerCt && ownerCt.moveDocked) {
                ownerCt.moveDocked(me, dock);
            } else {
                me.dock = dock;
            }
        }
 
        return me;
    },
 
    /**
     * Enable or disable the component.
     * @param {Boolean} disabled `true` to disable.
     */
    setDisabled: function(disabled) {
        return this[disabled ? 'disable': 'enable']();
    },
 
    /**
     * Sets the flex property of this component. Only applicable when this component is
     * an item of a box layout
     * @private
     * @param {Number} flex 
     */
    setFlex: function(flex) {
        this.flex = flex;
    },
 
    /**
     * Sets the height of the component. This method fires the {@link #resize} event.
     *
     * @param {Number} height The new height to set. This may be one of:
     *
     *   - A Number specifying the new height in pixels.
     *   - A String used to set the CSS height style.
     *   - `undefined` to leave the height unchanged.
     *   - `null` to clear the height.
     *
     * @return {Ext.Component} this
     */
    setHeight: function(height) {
        return this.setSize(undefined, height);
    },
 
    /**
     * This method allows you to show or hide a LoadMask on top of this component.
     *
     * The mask will be rendered into the element returned by {@link #getMaskTarget} which for most Components is the Component's
     * element. See {@link #getMaskTarget} and {@link #maskElement}.
     *
     * Most Components will return `null` indicating that their LoadMask cannot reside inside their element, but must
     * be rendered into the document body.
     *
     * {@link Ext.view.Table Grid Views} however will direct a LoadMask to be rendered into the owning {@link Ext.panel.Table GridPanel}.
     *
     * @param {Boolean/Object/String} load True to show the default LoadMask, a config object that will be passed to the
     * LoadMask constructor, or a message String to show. False to hide the current LoadMask.
     * @param targetEl (private) This param is deprecated
     * @return {Ext.LoadMask} The LoadMask instance that has just been shown.
     */
    setLoading: function(load, targetEl) {
        var me = this,
            config = {
                target: me
            };
 
        if (me.rendered) {
            // Shows mask for anything but false.
            if (load !== false) {
                if (Ext.isString(load)) {
                    config.msg = load;
                }
                else {
                    Ext.apply(config, load, me.maskDefaults);
                }
                
                // We do not already have a LoadMask: create one
                if (!me.loadMask || !me.loadMask.isLoadMask) {
                    // Deprecated second parameter.
                    // maskElement config replaces this
                    if (targetEl && config.useTargetEl == null) {
                        config.useTargetEl = true;
                    }
                    me.loadMask = new Ext.LoadMask(config);
                }
                // Change any settings according to load config
                else {
                    Ext.apply(me.loadMask, config);
                }
                // If already visible, just update display with passed configs.
                if (me.loadMask.isVisible()) {
                    me.loadMask.syncMaskState();
                }
                // Otherwise show with new configs
                else {
                    me.loadMask.show();
                }
            }
            // load == falsy: Hide the mask if it exists
            else {
                if (me.loadMask && me.loadMask.isLoadMask) {
                    me.loadMask.hide();
                }
            }
        }
        return me.loadMask;
    },
 
    /**
     * Sets the margin on the target element.
     * @param {Number/String} margin The margin to set. See the {@link #margin} config.
     * @param preventLayout (private)
     */
    setMargin: function(margin, preventLayout) {
        var me = this;
 
        if (me.rendered) {
            if (!margin && margin !== 0) {
                margin = '';
            } else {
                if (margin === true) {
                    margin = 5;
                }
                margin = this.unitizeBox(margin);
            }
            me.margin = margin;
            // See: EXTJS-13359
            me.margin$ = null;
            me.getEl().setStyle('margin', margin);
            if (!preventLayout) {
                // Changing the margins can impact the position of this (and possibly)
                // other subsequent components in the layout.
                me.updateLayout(me._notAsLayoutRoot);
            }
        } else {
            me.margin = margin;
        }
    },
 
    /**
     * Sets the overflow x/y on the content element of the component. The x/y overflow
     * values can be any valid CSS overflow (e.g., 'auto' or 'scroll'). By default, the
     * value is 'hidden'.  Passing `undefined` will preserve the current value.
     *
     * @param {String} overflowX The overflow-x value.
     * @param {String} overflowY The overflow-y value.
     * @return {Ext.Component} this
     * @deprecated 5.0.0 Use {@link #setScrollable} instead
     */
    setOverflowXY: function(overflowX, overflowY) {
        this.setScrollable({
            x: (overflowX && overflowX !== 'hidden') ? overflowX : false,
            y: (overflowY && overflowY !== 'hidden') ? overflowY : false
        });
 
        return this;
    },
 
    /**
     * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
     * This method fires the {@link #event-move} event.
     * @param {Number/Number[]} x The new x position or an array of `[x,y]`.
     * @param {Number} [y] The new y position.
     * @param {Boolean/Object} [animate] True to animate the Component into its new position. You may also pass an
     * animation configuration.
     * @return {Ext.Component} this
     */
    setPagePosition: function(x, y, animate) {
        var me = this,
            p,
            floatParentBox;
 
        if (Ext.isArray(x)) {
            y = x[1];
            x = x[0];
        }
        me.pageX = x;
        me.pageY = y;
 
        if (me.floating) {
 
            // Floating Components which are registered with a Container have to have their x and y properties made relative
            if (me.isContainedFloater()) {
                floatParentBox = me.floatParent.getTargetEl().getViewRegion();
                if (Ext.isNumber(x) && Ext.isNumber(floatParentBox.left)) {
                    x -= floatParentBox.left;
                }
                if (Ext.isNumber(y) && Ext.isNumber(floatParentBox.top)) {
                    y -= floatParentBox.top;
                }
            } else {
                p = me.el.translateXY(x, y);
                x = p.x;
                y = p.y;
            }
 
            me.setPosition(x, y, animate);
        } else {
            p = me.el.translateXY(x, y);
            me.setPosition(p.x, p.y, animate);
        }
 
        return me;
    },
 
    /**
     * @member Ext.Component
     * Sets the left and top of the component. To set the page XY position instead, use {@link Ext.Component#setPagePosition setPagePosition}. This
     * method fires the {@link #event-move} event.
     * @param {Number/Number[]/Object} x The new left, an array of `[x,y]`, or animation config object containing `x` and `y` properties.
     * @param {Number} [y] The new top.
     * @param {Boolean/Object} [animate] If `true`, the Component is _animated_ into its new position. You may also pass an
     * animation configuration.
     * @return {Ext.Component} this
     */
    setPosition: function(x, y, animate) {
        var me = this,
            pos = me.beforeSetPosition.apply(me, arguments);
 
        if (pos && me.rendered) {
            x = pos.x;
            y = pos.y;
 
            if (animate) {
                // Proceed only if the new position is different from the current
                // one. We only do these DOM reads in the animate case as we don't
                // want to incur the penalty of read/write on every call to setPosition
                if (!== me.getLocalX() || y !== me.getLocalY()) {
                    me.stopAnimation();
                    me.animate(Ext.apply({
                        duration: 1000,
                        listeners: {
                            afteranimate: Ext.Function.bind(me.afterSetPosition, me, [x, y])
                        },
                        to: {
                            // Use local coordinates for a component
                            // We don't need to normalize this for RTL, the anim.target.Component
                            // calls setPosition, which will normalize the x value to right when
                            // it's necessary
                            left: x,
                            top: y
                        }
                    }, animate));
                }
            } else {
                me.setLocalXY(x, y);
                me.afterSetPosition(x, y);
            }
        }
        return me;
    },
 
    /**
     * Sets the "x" scroll position for this component.  Only applicable for
     * {@link #scrollable} components
     * @param {Number} x 
     * @param {Boolean/Object} [animate] true for the default animation or a standard Element
     * animation config object
     */
    setScrollX: function(x, animate) {
        var scroller = this.getScrollable();
 
        if (scroller) {
            scroller.scrollTo(x, null, animate);
        }
    },
 
    /**
     * Sets the "y" scroll position for this component.  Only applicable for
     * {@link #scrollable} components
     * @param {Number} y 
     * @param {Boolean/Object} [animate] true for the default animation or a standard Element
     * animation config object
     */
    setScrollY: function(y, animate) {
        var scroller = this.getScrollable();
 
        if (scroller) {
            scroller.scrollTo(null, y, animate);
        }
    },
 
    /**
     * Sets the width and height of this Component. This method fires the {@link #resize} event. This method can accept
     * either width and height as separate arguments, or you can pass a size object like `{width:10, height:20}`.
     *
     * @param {Number/String/Object} width The new width to set. This may be one of:
     *
     *   - A Number specifying the new width in pixels.
     *   - A String used to set the CSS width style.
     *   - A size object in the format `{width: widthValue, height: heightValue}`.
     *   - `undefined` to leave the width unchanged.
     *
     * @param {Number/String} height The new height to set (not required if a size object is passed as the first arg).
     * This may be one of:
     *
     *   - A Number specifying the new height in pixels.
     *   - A String used to set the CSS height style. Animation may **not** be used.
     *   - `undefined` to leave the height unchanged.
     *
     * @return {Ext.Component} this
     */
    setSize: function(width, height) {
        var me = this,
            oldWidth = me.width,
            oldHeight = me.height,
            widthIsString, heightIsString;
 
        // support for standard size objects
        if (width && typeof width === 'object') {
            height = width.height;
            width  = width.width;
        }
 
        // Constrain within configured maximum
        if (typeof width === 'number') {
            me.width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
        } else if (width === null) {
            delete me.width;
        } else if(typeof width === 'string') {
            // handle width specified as a string css style
            widthIsString = true;
            me.width = width;
        }
 
        if (typeof height === 'number') {
            me.height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
        } else if (height === null) {
            delete me.height;
        } else if(typeof height === 'string') {
            // handle width specified as a string css style
            heightIsString = true;
            me.height = height;
        }
 
        // If not rendered, all we need to is set the properties.
        // The initial layout will set the size
        if (me.rendered && me.isVisible()) {
            if (oldWidth !== me.width || oldHeight !== me.height) {
                if (me.liquidLayout || widthIsString || heightIsString) {
                    // if we have a liquid layout we must setSize now, since the following
                    // updateLayout call will not set our size in the dom if we successfully
                    // opt out of the layout run
                    me.el.setSize(me.width, me.height);
                }
 
                // If we are changing size, then we are not the root.
                me.updateLayout(me._notAsLayoutRoot);
            }
        }
 
        return me;
    },
 
    /**
     * Sets the style for this Component's primary element.
     *
     * Styles should be a valid DOM element style property.
     * [Valid style property names](http://www.w3schools.com/jsref/dom_obj_style.asp)
     * (_along with the supported CSS version for each_)
     *
     *     var name = Ext.create({
     *         xtype: 'component',
     *         renderTo: Ext.getBody(),
     *         html: 'Phineas Flynn'
     *     });
     *
     *     // two-param syntax
     *     name.setStyle('color', 'white');
     *
     *     // single-param syntax
     *     name.setStyle({
     *         fontWeight: 'bold',
     *         backgroundColor: 'gray',
     *         padding: '10px'
     *     });
     *
     * @param {String/Object} property The style property to be set, or an object of
     * multiple styles.
     * @param {String} [value] The value to apply to the given property, or null if an
     * object was passed.
     * @return {Ext.Component} this
     */
    setStyle: function (property, value) {
        var el = this.el || this.protoEl;
        el.setStyle(property, value);
        return this;
    },
 
    /**
     * Sets the UI for the component. This will remove any existing UIs on the component. It will also loop through any
     * `uiCls` set on the component and rename them so they include the new UI.
     * @param {String} ui The new UI for the component.
     */
    setUI: function(ui) {
        var me = this,
            uiCls = me.uiCls,
            activeUI = me.activeUI,
            classes;
 
        if (ui === activeUI) {
            // The ui hasn't changed
            return;
        }
 
        // activeUI will only be set if setUI has been called before. If it hasn't there's no need to remove anything
        if (activeUI) {
            classes = me.removeClsWithUI(uiCls, true);
 
            if (classes.length) {
                me.removeCls(classes);
            }
 
            // Remove the UI from the element
            me.removeUIFromElement();
        }
        else {
            // We need uiCls to be empty otherwise our call to addClsWithUI won't do anything
            me.uiCls = [];
        }
 
        // Set the UI
        me.ui = ui;
 
        // After the first call to setUI the values ui and activeUI should track each other but initially we need some
        // way to tell whether the ui has really been set.
        me.activeUI = ui;
 
        // Add the new UI to the element
        me.addUIToElement();
 
        classes = me.addClsWithUI(uiCls, true);
 
        if (classes.length) {
            me.addCls(classes);
        }
 
        // Changing the ui can lead to significant changes to a component's appearance, so the layout needs to be
        // updated. Internally most calls to setUI are pre-render. Buttons are a notable exception as setScale changes
        // the ui and often requires the layout to be updated.
        if (me.rendered) {
            me.updateLayout();
        }
    },
 
    /**
     * Convenience function to hide or show this component by Boolean.
     * @param {Boolean} visible `true` to show, `false` to hide.
     * @return {Ext.Component} this
     * @since 1.1.0
     */
    setVisible: function(visible) {
        return this[visible ? 'show': 'hide']();
    },
 
    /**
     * Sets the hidden state of this component. This is basically the same as
     * `{@link #setVisible}` but the boolean parameter has the opposite meaning.
     * @param {Boolean} hidden 
     * @return {Ext.Component} 
     */
    setHidden: function(hidden) {
        return this.setVisible(!hidden);
    },
 
    /**
     * Sets the width of the component. This method fires the {@link #resize} event.
     *
     * @param {Number} width The new width to set. This may be one of:
     *
     *   - A Number specifying the new width in pixels.
     *   - A String used to set the CSS width style.
     *   - `undefined` to leave the width unchanged.
     *   - `null` to clear the width.
     *
     * @return {Ext.Component} this
     */
    setWidth: function(width) {
        return this.setSize(width);
    },
 
    /**
     * Shows this Component, rendering it first if {@link #autoRender} or {@link #cfg-floating} are `true`.
     *
     * After being shown, a {@link #cfg-floating} Component (such as a {@link Ext.window.Window}), is activated it and
     * brought to the front of its {@link #zIndexManager z-index stack}.
     *
     * @param {String/Ext.dom.Element} [animateTarget=null] **only valid for {@link #cfg-floating} Components such as {@link
     * Ext.window.Window Window}s or {@link Ext.tip.ToolTip ToolTip}s, or regular Components which have been configured
     * with `floating: true`.** The target from which the Component should animate from while opening.
     * @param {Function} [callback] A callback function to call after the Component is displayed.
     * Only necessary if animation was specified.
     * @param {Object} [scope] The scope (`this` reference) in which the callback is executed.
     * Defaults to this Component.
     * @return {Ext.Component} this
     */
    show: function(animateTarget, callback, scope) {
        var me = this,
            rendered = me.rendered,
            container = me.ownerFocusableContainer;
 
        if (me.hierarchicallyHidden || (me.floating && !rendered && me.isHierarchicallyHidden())) {
            // If this is a hierarchically hidden floating component, we need to stash
            // the arguments to this call so that the call can be deferred until the next
            // time syncHidden() is called.
            if (!rendered) {
                // If the component has not yet been rendered it requires special treatment.
                // Normally, for rendered components we can just set the pendingShow property
                // and syncHidden() listens to events in the hierarchyEventSource and calls
                // show() when this component becomes hierarchically visible.  However,
                // if the component has not yet been rendered the hierarchy event listeners
                // have not yet been attached (since Floating is initialized during the
                // render phase.  This means we have to initialize the hierarchy event
                // listeners right now to ensure that the component will show itself when
                // it becomes hierarchically visible.
                me.initHierarchyEvents();
            }
            // defer the show call until next syncHidden(), but ignore animateTarget.
            if (arguments.length > 1) {
                arguments[0] = null; // jshint ignore:line
                me.pendingShow = arguments;
            } else {
                me.pendingShow = true;
            }
        } else if (rendered && me.isVisible()) {
            if (me.floating) {
                me.onFloatShow();
 
                // onFloatShow does not toFront this Component
                // because that is done by our ZIndexManager in response to the global
                // show event fired from afterShow.
                // Since we will not execute afterShow if already visible,
                // maintain behaviour by explicitly toFronting here.
                if (me.toFrontOnShow) {
                    me.toFront();
                }
            }
        } else {
            if (me.fireEvent('beforeshow', me) !== false) {
                me.hidden = false;
                delete this.getInherited().hidden;
                // Render on first show if there is an autoRender config, or if this
                // is a floater (Window, Menu, BoundList etc).
                
                if (container && !container.beforeFocusableChildShow.$nullFn) {
                    container.beforeFocusableChildShow(me);
                }
 
                // We suspend layouts here because floaters/autoRenders
                // will layout when onShow is called. If the render succeeded,
                // the layout will be trigger inside onShow, so we don't flush
                // in the first block. If, for some reason we couldn't render, then
                // we resume layouts and force a flush because we don't know if something
                // will force it.
                Ext.suspendLayouts();
                if (!rendered && (me.autoRender || me.floating)) {
                    me.doAutoRender();
                    rendered = me.rendered;
                }
 
                if (rendered) {
                    me.beforeShow();
                    Ext.resumeLayouts();
                    me.onShow.apply(me, arguments);
                    me.afterShow.apply(me, arguments);
                } else {
                    Ext.resumeLayouts(true);
                }
            } else {
                me.onShowVeto();
            }
        }
        return me;
    },
 
    /**
     * Displays component at specific xy position.
     * A floating component (like a menu) is positioned relative to its ownerCt if any.
     * Useful for popping up a context menu:
     *
     *     listeners: {
     *         itemcontextmenu: function(view, record, item, index, event, options) {
     *             Ext.create('Ext.menu.Menu', {
     *                 width: 100,
     *                 height: 100,
     *                 margin: '0 0 10 0',
     *                 items: [{
     *                     text: 'regular item 1'
     *                 },{
     *                     text: 'regular item 2'
     *                 },{
     *                     text: 'regular item 3'
     *                 }]
     *             }).showAt(event.getXY());
     *         }
     *     }
     *
     * @param {Number/Number[]} x The new x position or array of `[x,y]`.
     * @param {Number} [y] The new y position
     * @param {Boolean/Object} [animate] True to animate the Component into its new position. You may also pass an
     * animation configuration.
     * @return {Ext.Component} this
     */
    showAt: function(x, y, animate) {
        var me = this;
 
        // Not rendered, then animating to a position is meaningless,
        // just set the x,y position and allow show's processing to work.
        if (!me.rendered && (me.autoRender || me.floating)) {
            me.x = x;
            me.y = y;
            return me.show();
        }
        if (me.floating) {
            me.setPosition(x, y, animate);
        } else {
            me.setPagePosition(x, y, animate);
        }
        return me.show();
    },
 
    /**
     * Shows this component by the specified {@link Ext.Component Component} or {@link Ext.dom.Element Element}.
     * Used when this component is {@link #cfg-floating}.
     * @param {Ext.Component/Ext.dom.Element} component The {@link Ext.Component} or {@link Ext.dom.Element} to show the component by.
     * @param {String} [position] Alignment position as used by {@link Ext.util.Positionable#getAlignToXY}.
     * Defaults to `{@link #defaultAlign}`. See {@link #alignTo} for possible values.
     * @param {Number[]} [offset] Alignment offsets as used by {@link Ext.util.Positionable#getAlignToXY}. See {@link #alignTo} for possible values.
     * @return {Ext.Component} this
     */
    showBy: function(component, position, offset) {
        var me = this;
 
        //<debug>
        if (!me.floating) {
            Ext.log.warn('Using showBy on a non-floating component');
        }
        //</debug>
 
        if (me.floating && component) {
            me._lastAlignTarget = component;
 
            me._lastAlignToPos = position || me.defaultAlign;
 
            me._lastAlignToOffsets = offset || me.alignOffset;
 
            me.show();
        }
 
        return me;
    },
 
    suspendLayouts: function () {
        var me = this;
        if (!me.rendered) {
            return;
        }
        if (++me.layoutSuspendCount === 1) {
            me.suspendLayout = true;
        }
    },
 
    /**
     * Toggles the specified CSS class on this component (removes it if it already exists,
     * otherwise adds it).
     * @param {String} className The CSS class to toggle.
     * @param {Boolean} [state] If specified as `true`, causes the class to be added. If
     * specified as `false`, causes the class to be removed.
     * @return {Ext.Component} Returns the Component to allow method chaining.
     * @chainable
     */
    toggleCls: function (className, state) {
        if (state === undefined) {
            state = !this.hasCls(className);
        }
 
        return this[state ? 'addCls' : 'removeCls'](className);
    },
 
    unitizeBox: function(box) {
        return Ext.Element.unitizeBox(box);
    },
 
    /**
     * Removes the mask applied by {@link #mask}
     */
    unmask: function() {
        (this.getMaskTarget() || this.el).unmask();
 
        this.setMasked(false);
    },
 
    unregisterFloatingItem: function(cmp) {
        var me = this;
        if (me.floatingDescendants) {
            me.floatingDescendants.unregister(cmp);
        }
    },
 
    /**
     * Navigates up the ownership hierarchy searching for an ancestor Container which matches any passed selector or component.
     *
     * *Important.* There is not a universal upwards navigation pointer. There are several upwards relationships
     * such as the {@link Ext.button.Button button} which activates a {@link Ext.button.Button#cfg-menu menu}, or the
     * {@link Ext.menu.Item menu item} which activated a {@link Ext.menu.Item#cfg-menu submenu}, or the
     * {@link Ext.grid.column.Column column header} which activated the column menu.
     *
     * These differences are abstracted away by this method.
     *
     * Example:
     *
     *     var owningTabPanel = grid.up('tabpanel');
     *
     * @param {String/Ext.Component} [selector] The selector component or actual component to test. If not passed the immediate owner/activator is returned.
     * @param {String/Number/Ext.Component} [limit] This may be a selector upon which to stop the upward scan, or a limit of the number of steps, or Component reference to stop on.
     * @return {Ext.container.Container} The matching ancestor Container (or `undefined` if no match was found).
     */
    up: function (selector, limit) {
        var result = this.getRefOwner(),
            limitSelector = typeof limit === 'string',
            limitCount = typeof limit === 'number',
            limitComponent = limit && limit.isComponent,
            steps = 0;
 
        if (selector) {
            for (; result; result = result.getRefOwner()) {
                if (result.destroyed) {
                    return null;
                }
 
                steps++;
                if (selector.isComponent) {
                    if (result === selector) {
                        return result;
                    }
                } else {
                    if (Ext.ComponentQuery.is(result, selector)) {
                        return result;
                    }
                }
 
                // Stop when we hit the limit selector
                if (limitSelector && result.is(limit)) {
                    return;
                }
                if (limitCount && steps === limit) {
                    return;
                }
                if (limitComponent && result === limit) {
                    return;
                }
            }
        }
        return result;
    },
 
    /**
     * Update the content area of a component.
     * @param {String/Object} htmlOrData If this component has been configured with a
     * template via the tpl config then it will use this argument as data to populate the
     * template. If this component was not configured with a template, the components
     * content area will be updated via Ext.Element update.
     * @param {Boolean} [loadScripts=false] Only legitimate when using the `html`
     * configuration. Causes embedded script tags to be executed. Inline source will be executed
     * with this Component as the scope (`this` reference).
     * @param {Function} [callback] Only legitimate when using the `html` configuration.
     * Callback to execute when scripts have finished loading.
     * @param {Object} [scriptScope=`this`] The scope (`this` reference) in which to
     * execute *inline* script elements content. Scripts with a `src` attribute cannot
     * be executed with this scope.
     *
     * @since 3.4.0
     */
    update: function(htmlOrData, loadScripts, callback, scriptScope) {
        var me = this,
            isData = (me.tpl && !Ext.isString(htmlOrData)),
            container = me.ownerFocusableContainer,
            sizeModel, doLayout, el;
 
 
        if (isData) {
            me.data = (htmlOrData && htmlOrData.isEntity) ? htmlOrData.getData(true) : htmlOrData;
        } else {
            me.html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
        }
 
        if (me.rendered) {
            sizeModel = me.getSizeModel();
            doLayout = sizeModel.width.shrinkWrap || sizeModel.height.shrinkWrap;
 
            if (me.isContainer) {
                el = me.layout.getRenderTarget();
 
                // If we are a non-empty container being updated with raw content we have to lay out
                doLayout = doLayout || me.items.items.length > 0;
            } else {
                el = me.getTargetEl();
            }
            if (isData) {
                me.tpl[me.tplWriteMode](el, me.data || {});
            } else {
                el.setHtml(me.html, loadScripts, callback, scriptScope || me);
            }
 
            if (doLayout) {
                me.updateLayout();
            }
 
            if (container && !container.onFocusableChildUpdate.$nullFn) {
                container.onFocusableChildUpdate(me);
            }
        }
    },
 
    /**
     * Update the content area of a component.
     * @param {String/Object} html If this component has been configured with a
     * template via the tpl config then it will use this argument as data to populate the
     * template. If this component was not configured with a template, the components
     * content area will be updated via Ext.Element update.
     * @param {Boolean} [loadScripts=false] Only legitimate when using the `html`
     * configuration. Causes embedded script tags to be executed. Inline source will be executed
     * with this Component as the scope (`this` reference).
     * @param {Function} [callback] Only legitimate when using the `html` configuration.
     * Callback to execute when scripts have finished loading.
     * @param {Object} [scriptScope='this'] The scope (`this` reference) in which to
     * execute *inline* script elements content. Scripts with a `src` attribute cannot
     * be executed with this scope.
     *
     * @since 3.4.0
     */
    setHtml: function (html, loadScripts, callback, scriptScope) {
        this.update(html, loadScripts, null, scriptScope);
    },
 
    applyData: function (data) {
        // Don't return data here, update will set this.data
        this.update(data);
    },
 
    /**
     * Sets the current box measurements of the component's underlying element.
     * @param {Object} box An object in the format {x, y, width, height}
     * @return {Ext.Component} this
     */
    updateBox: function(box){
        this.setSize(box.width, box.height);
        this.setPagePosition(box.x, box.y);
        return this;
    },
 
    _asLayoutRoot: { isRoot: true },
    _notAsLayoutRoot: { isRoot: false },
 
    /**
     * Updates this component's layout. If this update affects this components {@link #ownerCt},
     * that component's `updateLayout` method will be called to perform the layout instead.
     * Otherwise, just this component (and its child items) will layout.
     *
     * @param {Object} [options] An object with layout options.
     * @param {Boolean} options.defer `true` if this layout should be deferred.
     * @param {Boolean} options.isRoot `true` if this layout should be the root of the layout.
     */
    updateLayout: function (options) {
        var me = this,
            defer,
            lastBox = me.lastBox,
            isRoot = options && options.isRoot,
            context = options && options.context;
 
        if (lastBox) {
            // remember that this component's last layout result is invalid and must be
            // recalculated
            lastBox.invalid = true;
        }
 
        if (!me.rendered || me.isDetached || me.layoutSuspendCount || me.suspendLayout) {
            return;
        }
 
        if (me.hidden) {
            Ext.Component.cancelLayout(me);
        } else if (typeof isRoot !== 'boolean') {
            isRoot = me.isLayoutRoot();
        }
 
        // if we aren't the root, see if our ownerLayout will handle it...
        if (isRoot || !me.ownerLayout || !me.ownerLayout.onContentChange(me, context)) {
            // either we are the root or our ownerLayout doesn't care
            if (!me.isLayoutSuspended()) {
                // we aren't suspended (knew that), but neither is any of our ownerCt's...
                defer = (options && options.hasOwnProperty('defer')) ? options.defer : me.deferLayouts;
                Ext.Component.updateLayout(me, defer);
            }
        }
    },
 
    updateMaxHeight: function(maxHeight, oldMaxHeight) {
        this.changeConstraint(maxHeight, oldMaxHeight, 'min', 'max-height', 'height');
    },
 
    updateMaxWidth: function(maxWidth, oldMaxWidth) {
        this.changeConstraint(maxWidth, oldMaxWidth, 'min', 'max-width', 'width');
    },
 
    updateMinHeight: function(minHeight, oldMinHeight) {
        this.changeConstraint(minHeight, oldMinHeight, 'max', 'min-height', 'height');
    },
 
    updateMinWidth: function(minWidth, oldMinWidth) {
        this.changeConstraint(minWidth, oldMinWidth, 'max', 'min-width', 'width');
    },
 
    updateTouchAction: function(touchAction) {
        var name, childEl, value, hasRootActions;
 
        for (name in touchAction) {
            childEl = this[name];
            value = touchAction[name];
 
            if (childEl && childEl.isElement) {
                childEl.setTouchAction(value);
            } else {
                hasRootActions = true;
            }
        }
 
        if (hasRootActions) {
            this.el.setTouchAction(touchAction);
        }
    },
 
    // ***********************************************************************************
    // End Component methods
    // ***********************************************************************************
    // </editor-fold>
 
    // <editor-fold desc="Positionable Methods">
    // ***********************************************************************************
    // Begin Positionable methods
    // ***********************************************************************************
    getAnchorToXY: function(el, anchor, local, mySize) {
        return el.getAnchorXY(anchor, local, mySize);
    },
 
    getBorderPadding: function() {
        return this.el.getBorderPadding();
    },
 
    getLocalX: function() {
        return this.el.getLocalX();
    },
 
    getLocalXY: function() {
        return this.el.getLocalXY();
    },
 
    getLocalY: function() {
        return this.el.getLocalY();
    },
 
    getX: function() {
        return this.el.getX();
    },
 
    getXY: function() {
        return this.el.getXY();
    },
 
    getY: function() {
        return this.el.getY();
    },
 
    setLocalX: function(x) {
        this.el.setLocalX(x);
    },
 
    setLocalXY: function(x, y) {
        this.el.setLocalXY(x, y);
    },
 
    setLocalY: function(y) {
        this.el.setLocalY(y);
    },
 
    setX: function(x, animate) {
        this.el.setX(x, animate);
    },
 
    setXY: function(xy, animate) {
        this.el.setXY(xy, animate);
    },
 
    setY: function(y, animate) {
        this.el.setY(y, animate);
    },
 
    // ***********************************************************************************
    // End Positionable methods
    // ***********************************************************************************
    // </editor-fold>
 
    privates: {
        addOverCls: function() {
            var me = this;
            if (!me.disabled) {
                me.el.addCls(me.overCls);
            }
        },
 
        /**
         * Method which adds a specified UI to the components element.
         * @private
         */
        addUIToElement: function() {
            var me = this,
                baseClsUI = me.baseCls + '-' + me.ui,
                childEls, childElName, el, suffix;
 
            me.addCls(baseClsUI);
 
            if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
                // Loop through each frame element, and if they are defined add the ui:
                baseClsUI += '-';
                childEls = me.getChildEls();
 
                for (childElName in childEls) {
                    suffix = childEls[childElName].frame;
                    if (suffix && suffix !== true) {
                        el = me[childElName];
                        if (el) {
                            el.addCls(baseClsUI + suffix);
                        }
                    }
                }
            }
        },
 
        /**
         * @private
         */
        changeConstraint: function(newValue, oldValue, constrainMethod, styleName, sizeName) {
            var me = this,
                size = me[sizeName];
 
            if (newValue != null && typeof size === 'number') {
                me[sizeName] = Math[constrainMethod](size, newValue);
            }
 
            if (me.liquidLayout) {
                // components that use liquidLayout need their size constraints set in the dom
                if (newValue != null) {
                    me.setStyle(styleName, newValue + 'px');
                } else if (oldValue) {
                    me.setStyle(styleName, '');
                }
            }
 
            if (me.rendered) {
                me.updateLayout();
            }
        },
 
        /**
         * @param {String/Object} plugin string or config object containing a ptype property.
         *
         * Constructs a plugin according to the passed config object/ptype string.
         *
         * Ensures that the constructed plugin always has a `cmp` reference back to this component.
         * The setting up of this is done in PluginManager. The PluginManager ensures that a reference to this
         * component is passed to the constructor. It also ensures that the plugin's `setCmp` method (if any) is called.
         * @private
         */
        constructPlugin: function(plugin) {
            var me = this,
                PM = Ext.plugin.Manager;
 
            // ptype only, pass as the defultType
            if (typeof plugin === 'string') {
                plugin = PM.create({}, plugin, me);
            }
            // Object (either config with ptype or an instantiated plugin)
            else {
                plugin = PM.create(plugin, null, me);
            }
 
            return plugin;
        },
 
        /**
         * Returns an array of fully constructed plugin instances. This converts any configs into their
         * appropriate instances.
         *
         * It does not mutate the plugins array. It creates a new array.
         * @private
         */
        constructPlugins: function() {
            var me = this,
                plugins = me.plugins,
                result, i, len;
 
            if (plugins) {
                me.plugins = result = Ext.plugin.Abstract.decode(plugins, 'ptype');
 
                // The processed flag indicates that the plugins have been constructed. This is usually done
                // at construction time, so if at initComponent time, there is a non-zero array of plugins which
                // does NOT have the processed flag, it needs to be processed again.
                result.processed = true;
 
                for (= 0, len = result.length; i < len; i++) {
                    // this just returns already-constructed plugin instances...
                    result[i] = me.constructPlugin(result[i]);
                }
            }
 
            me.pluginsInitialized = true;
            return result;
        },
 
        detachFromBody: function() {
            // Also see reattachToBody
            var me = this;
 
            if (!me.isDetached) {
                Ext.getDetachedBody().appendChild(me.el, true);
                Ext.Component.cancelLayout(me);
                me.isDetached = true;
            }
        },
 
        doAddListener: function(ename, fn, scope, options, order, caller, manager) {
            var me = this,
                listeners, option, eventOptions, elementName, element, delegate;
 
            if (Ext.isObject(fn) || (options && options.element)) {
                if (options.element) {
                    elementName = options.element;
                    listeners = {};
                    listeners[ename] = fn;
                    if (scope) {
                        listeners.scope = scope;
                    }
 
                    eventOptions = me.$elementEventOptions;
                    for (option in options) {
                        if (eventOptions[option]) {
                            listeners[option] = options[option];
                        }
                    }
                } else {
                    listeners = fn;
                    elementName = ename;
                }
 
                element = me[elementName];
 
                if (element && element.isObservable) { // can be any kind of observable, not just element
                    me.mon(element, listeners);
                } else {
                    me.afterRenderEvents = me.afterRenderEvents || {};
                    if (!me.afterRenderEvents[elementName]) {
                        me.afterRenderEvents[elementName] = [];
                    }
                    me.afterRenderEvents[elementName].push(listeners);
                }
                return;
            }
 
            if (options) {
                delegate = options.delegate;
                if (delegate) {
                    me.mixins.componentDelegation.addDelegatedListener.call(me, ename, fn, scope, options, order, caller, manager);
                    return;
                }
            }
 
            me.mixins.observable.doAddListener.call(me, ename, fn, scope, options, order, caller, manager);
        },
 
        doRemoveListener: function(eventName, fn, scope) {
            var me = this;
            me.mixins.observable.doRemoveListener.call(me, eventName, fn, scope);
            me.mixins.componentDelegation.removeDelegatedListener.call(me, eventName, fn, scope);
        },
 
        /**
         * This method fires an event on `Ext.GlobalEvents` allowing interested parties to know
         * of certain critical events for this component. This is done globally because the
         * (few) listeners can immediately receive the event rather than bubbling the event
         * only to reach the top and have no listeners.
         *
         * The main usage for these events is to do with floating components. For example, the
         * load mask is a floating component. The component it is masking may be inside several
         * containers. As such, they need to know when component is hidden, either directly, or
         * via a parent container being hidden. To do this they subscribe to these events and
         * filter out the appropriate container.
         *
         * This functionality is contained in Component (as opposed to Container) because a
         * Component can be the ownerCt for a floating component (loadmask), and the loadmask
         * needs to know when its owner is shown/hidden so that its hidden state can be
         * synchronized.
         *
         * @param {String} eventName The event name.
         * @since 4.2.0
         * @private
         */
        fireHierarchyEvent: function (eventName) {
            var globalEvents = Ext.GlobalEvents;
 
            if (globalEvents.hasListeners[eventName]) {
                globalEvents.fireEvent(eventName, this);
            }
        },
 
        getActionEl: function() {
            return this.el;
        },
 
        /**
         * @private
         */
        getAutoId: function() {
            this.autoGenId = true;
            return ++Ext.Component.AUTO_ID;
        },
 
        /**
         * @private
         */
        getContentTarget: function() {
            return this.el;
        },
 
        getDragEl: function() {
            return this.el;
        },
 
        /**
         * Get an el for overflowing, defaults to the target el
         * @private
         */
        getOverflowEl: function(){
            return this.getTargetEl();
        },
 
        /**
         * @private
         * Returns the CSS style object which will set the Component's scroll styles.
         * This must be applied to the {@link #getTargetEl target element}.
         */
        getOverflowStyle: function() {
            var me = this,
                scroller = me.getScrollable(),
                flags = me._scrollFlags,
                x, y, scrollFlags;
 
            if (scroller) {
                x = scroller.getX();
                if (=== true) {
                    x = 'auto';
                }
                y = scroller.getY();
                if (=== true) {
                    y = 'auto';
                }
                scrollFlags = flags[x][y];
            } else {
                scrollFlags = flags.none;
            }
 
            me.scrollFlags = scrollFlags;
 
            return {
                overflowX: scrollFlags.overflowX,
                overflowY: scrollFlags.overflowY
            };
        },
 
        /**
         * Returns an array of current fully constructed plugin instances.
         * @private
         */
        getPlugins : function() {
            var plugins = this.plugins;
 
            plugins = (plugins && plugins.processed) ? plugins : this.constructPlugins();
            return plugins || null;
        },
 
        getProxy: function() {
            var me = this,
                target;
 
            if (!me.proxy) {
                target = Ext.getBody();
                me.proxy = me.el.createProxy(Ext.baseCSSPrefix + 'proxy-el', target, true);
            }
            return me.proxy;
        },
 
        /**
         * This is used to determine where to insert the 'html', 'contentEl' and 'items' in this component.
         * @private
         */
        getTargetEl: function() {
            return this.frameBody || this.el;
        },
 
        /**
         * @private
         * Needed for when widget is rendered into a grid cell. The class to add to the cell element.
         */
        getTdCls: function() {
            return Ext.baseCSSPrefix + this.getTdType() + '-' + this.ui + '-cell';
        },
 
        /**
         * @private
         * Partner method to {@link #getTdCls}.
         *
         * Returns the base type for the component. Defaults to return `this.xtype`, but
         * All derived classes of {@link Ext.form.field.Text TextField} can return the type 'textfield',
         * and all derived classes of {@link Ext.button.Button Button} can return the type 'button'
         */
        getTdType: function() {
            return this.xtype;
        },
 
        /**
         * @private
         */
        getTpl: function(name) {
            //<debug>
            Ext.log.warn('getTpl is deprecated, use lookupTpl.');
            //</debug>
            return this.lookupTpl(name);
        },
 
        initCls: function() {
            var me = this,
                cls = [me.baseCls],
                targetCls = me.getComponentLayout().targetCls;
 
            if (targetCls) {
                cls.push(targetCls);
            }
 
            //<deprecated since=0.99>
            if (Ext.isDefined(me.cmpCls)) {
                if (Ext.isDefined(Ext.global.console)) {
                    Ext.global.console.warn('Ext.Component: cmpCls has been deprecated. Please use componentCls.');
                }
                me.componentCls = me.cmpCls;
                delete me.cmpCls;
            }
            //</deprecated>
 
            if (me.componentCls) {
                cls.push(me.componentCls);
            } else {
                me.componentCls = me.baseCls;
            }
 
            return cls;
        },
 
        initDraggable: function() {
            var me = this,
 
            // If we are resizable, and the resizer had to wrap this Component's el (e.g. an Img)
            // Then we have to create a pseudo-Component out of the resizer to drag that,
            // otherwise, we just drag this Component
                dragTarget = (me.resizer && me.resizer.el !== me.el) ? me.resizerComponent = new Ext.Component({
                    el: me.resizer.el,
                    rendered: true,
                    container: me.container
                }) : me,
                ddConfig = Ext.applyIf({
                    el: dragTarget.getDragEl(),
                    constrainTo: (me.constrain||me.draggable.constrain) ? (me.constrainTo || (me.floatParent ? me.floatParent.getTargetEl() : me.container)) : undefined
                }, me.draggable);
 
            // Add extra configs if Component is specified to be constrained
            if (me.constrain || me.constrainDelegate) {
                ddConfig.constrain = me.constrain;
                ddConfig.constrainDelegate = me.constrainDelegate;
            }
 
            me.dd = new Ext.util.ComponentDragger(dragTarget, ddConfig);
        },
 
        /**
         * Initializes padding by applying it to the target element, or if the layout manages
         * padding ensures that the padding on the target element is "0".
         * @private
         */
        initPadding: function(targetEl) {
            var me = this,
                padding = me.padding;
 
            if (padding != null) {
                if (me.layout && me.layout.managePadding && me.contentPaddingProperty === 'padding') {
                    // If the container layout manages padding, or if a touch scroller is in
                    // use, the padding will be applied to an inner layout element, or the
                    // touch scroller element.  This is done as a workaround for the browser bug
                    // where right and/or bottom padding is lost when the element has overflow.
                    // The assumed intent is for the configured padding to override any padding
                    // that is applied to the target element via style sheet rules.  It is
                    // therefore necessary to set the target element's padding to "0".
                    targetEl.setStyle('padding', 0);
                } else {
                    // Convert the padding, margin and border properties from a space separated string
                    // into a proper style string
                    targetEl.setStyle('padding', this.unitizeBox((padding === true) ? 5 : padding));
                }
            }
        },
 
        /**
         * @private
         */
        initPlugin: function(plugin) {
            plugin.init(this);
 
            return plugin;
        },
 
        initResizable: function(resizable) {
            var me = this;
 
            resizable = Ext.apply({
                target: me,
                dynamic: false,
                constrainTo: (me.constrain||(resizable && resizable.constrain)) ? (me.constrainTo || (me.floatParent ? me.floatParent.getTargetEl() : me.container)) : undefined,
                handles: me.resizeHandles
            }, resizable);
            resizable.target = me;
            me.resizer = new Ext.resizer.Resizer(resizable);
        },
 
        /**
         * Applies padding, margin, border, top, left, height, and width configs to the
         * appropriate elements.
         * @private
         */
        initStyles: function(targetEl) {
            var me = this,
                margin = me.margin,
                border = me.border,
                cls = me.cls,
                style = me.style,
                x = me.x,
                y = me.y,
                liquidLayout = me.liquidLayout,
                width, height;
 
            me.initPadding(targetEl);
 
            if (margin != null) {
                targetEl.setStyle('margin', this.unitizeBox((margin === true) ? 5 : margin));
            }
 
            if (border != null) {
                me.setBorder(border, targetEl);
            }
 
            // initComponent, beforeRender, or event handlers may have set the style or cls property since the protoEl was set up
            // so we must apply styles and classes here too.
            if (cls && cls !== me.initialCls) {
                targetEl.addCls(cls);
                me.cls = me.initialCls = null;
            }
            if (style && style !== me.initialStyle) {
                targetEl.setStyle(style);
                me.style = me.initialStyle = null;
            }
 
            if (!= null) {
                targetEl.setStyle(me.horizontalPosProp, (typeof x === 'number') ? (+ 'px') : x);
            }
            if (!= null) {
                targetEl.setStyle('top', (typeof y === 'number') ? (+ 'px') : y);
            }
 
            if (!me.ownerCt || me.floating) {
                if (Ext.scopeCss) {
                    targetEl.addCls(me.rootCls);
                }
                targetEl.addCls(me.borderBoxCls);
            }
 
            // Framed components need their width/height to apply to the frame, which is
            // best handled in layout at present. The exception to this rule is component
            // that use liquidLayout and so cannot rely on the layout to set their size.
            if (liquidLayout || !me.getFrameInfo()) {
                width = me.width;
                height = me.height;
 
                // If we're using the content box model, we also cannot assign numeric initial sizes since we do not know the border widths to subtract
                if (width != null) {
                    if (typeof width === 'number') {
                        targetEl.setStyle('width', width + 'px');
                    } else {
                        targetEl.setStyle('width', width);
                    }
                }
                if (height != null) {
                    if (typeof height === 'number') {
                        targetEl.setStyle('height', height + 'px');
                    } else {
                        targetEl.setStyle('height', height);
                    }
                }
            }
        },
 
        // Utility method to determine if a Component is floating, and has an owning Container whose coordinate system
        // it must be positioned in when using setPosition.
        isContainedFloater: function() {
            return (this.floating && this.floatParent);
        },
 
        isDescendant: function(ancestor) {
            if (ancestor.isContainer) {
                for (var c = this.ownerCt; c; c = c.ownerCt) {
                    if (=== ancestor) {
                        return true;
                    }
                }
            }
            return false;
        },
 
        /**
         * @private
         * Returns `true` if the passed element is within the container tree of this component.
         *
         * For example if a menu's submenu contains an {@link Ext.form.field.Date}, that top level
         * menu owns the elements of the date picker. Using this method, you can tell if an event took place
         * within a certain component tree.
         */
        owns: function(element) {
            var result = false,
                cmp;
 
            if (element.isEvent) {
                element = element.target;
            } else if (element.isElement) {
                element = element.dom;
            }
 
            cmp = Ext.Component.fromElement(element);
 
            if (cmp) {
                result = (cmp === this) || (!!cmp.up(this));
            }
 
            return result;
        },
 
        parseBox: function(box) {
            return Ext.Element.parseBox(box);
        },
 
        reattachToBody: function() {
            // Also see detachFromBody
            this.isDetached = false;
        },
 
        removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){
            var me = this,
                element = managedListener.options ? managedListener.options.element : null;
 
            if (element) {
                element = me[element];
                if (element && element.un) {
                    if (isClear || (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope))) {
                        element.un(managedListener.ename, managedListener.fn, managedListener.scope);
                        if (!isClear) {
                            Ext.Array.remove(me.managedListeners, managedListener);
                        }
                    }
                }
            } else {
                return me.mixins.observable.removeManagedListenerItem.apply(me, arguments);
            }
        },
 
        removeOverCls: function() {
            this.el.removeCls(this.overCls);
        },
 
        removePlugin: function(plugin) {
            Ext.Array.remove(this.plugins, plugin);
            plugin.destroy();
        },
 
        /**
         * Method which removes a specified UI from the components element.
         * @private
         */
        removeUIFromElement: function() {
            var me = this,
                baseClsUI = me.baseCls + '-' + me.ui,
                childEls, childElName, el, suffix;
 
            me.removeCls(baseClsUI);
 
            if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
                // Loop through each frame element, and if they are defined remove the ui:
                baseClsUI += '-';
                childEls = me.getChildEls();
 
                for (childElName in childEls) {
                    suffix = childEls[childElName].frame;
                    if (suffix && suffix !== true) {
                        el = me[childElName];
                        if (el) {
                            el.removeCls(baseClsUI + suffix);
                        }
                    }
                }
            }
        },
 
        /**
         * @private
         */
        setComponentLayout: function(layout) {
            var currentLayout = this.componentLayout;
            if (currentLayout && currentLayout.isLayout && currentLayout !== layout) {
                currentLayout.setOwner(null);
            }
            this.componentLayout = layout;
            layout.setOwner(this);
        },
 
        setHiddenState: function (hidden) {
            var me = this,
                inheritedState = me.getInherited(),
                zIndexManager = me.zIndexManager;
 
            me.hidden = hidden;
 
            if (hidden) {
                inheritedState.hidden = true;
            } else {
                delete inheritedState.hidden;
            }
 
            // Ensure any ZIndexManager knowns about visibility state change to keep its filtering correct
            if (zIndexManager) {
                zIndexManager.onComponentShowHide(me);
            }
        },
 
        setupProtoEl: function() {
            var cls = this.initCls();
 
            this.protoEl.addCls(cls);
        },
 
        wrapPrimaryEl: function (dom) {
            var me = this,
                el = me.el;
 
            if (!el || !el.isElement) { // allow subclass override to instantiate the element
                me.el = Ext.get(dom);
            }
 
            if (me.floating) {
                this.mixins.floating.constructor.call(this);
            }
        }
    }, // private
 
    deprecated: {
        5: {
            methods: {
                /**
                 * @method addClass
                 * @inheritdoc Ext.Component#addCls
                 * @deprecated 4.1 Use {@link #addCls} instead.
                 * @since 2.3.0
                 */
                addClass: 'addCls',
 
                /**
                 * @method doComponentLayout
                 * This method needs to be called whenever you change something on this component that
                 * requires the Component's layout to be recalculated.
                 * @return {Ext.Component} this
                 * @deprecated 4.1 Use {@link Ext.Component#method-updateLayout} instead.
                 */
                doComponentLayout: function() {
                    this.updateLayout();
                    return this;
                },
 
                /**
                 * @method removeClass
                 * @inheritdoc Ext.Component#removeCls
                 * @deprecated 4.1 Use {@link #addCls} instead.
                 * @since 2.3.0
                 */
                removeClass: 'removeCls',
 
                /**
                 * @method forceComponentLayout
                 * @inheritdoc Ext.Component#updateLayout
                 * @deprecated 4.1 Use {@link Ext.Component#method-updateLayout} instead.
                 */
                forceComponentLayout: 'updateLayout',
 
                /**
                 * @method setDocked
                 * @inheritdoc Ext.Component#setDock
                 * @deprecated 5.0 Use {@link #setDock} instead.
                 */
                setDocked: 'setDock'
            }
        }
    }
}, function(Component) {
    var prototype = Component.prototype;
 
    // event options for listeners that use the "element" event options must also include
    // event options from Ext.Element
    (prototype.$elementEventOptions =
        Ext.Object.chain(Ext.Element.prototype.$eventOptions)).element = 1;
 
    (prototype.$eventOptions = Ext.Object.chain(prototype.$eventOptions)).delegate = 1;
 
    Component.createAlias({
        on: 'addListener',
        prev: 'previousSibling',
        next: 'nextSibling'
    });
 
    /**
     * @method resumeLayouts
     * @inheritdoc Ext.Component#static-method-resumeLayouts
     * @member Ext
     */
    Ext.resumeLayouts = function (flush) {
        Component.resumeLayouts(flush);
    };
 
    /**
     * @method suspendLayouts
     * @inheritdoc Ext.Component#static-method-suspendLayouts
     * @member Ext
     */
    Ext.suspendLayouts = function () {
        Component.suspendLayouts();
    };
 
    /**
     * @method batchLayouts
     * Utility wrapper that suspends layouts of all components for the duration of a given
     * function.
     * @param {Function} fn The function to execute.
     * @param {Object} [scope] The scope (`this` reference) in which the specified function
     * is executed.
     * @member Ext
     */
    Ext.batchLayouts = function(fn, scope) {
        Component.suspendLayouts();
        // Invoke the function
        // note: try/finally works in IE8 standards mode
        try {
            fn.call(scope);
        }
        finally {
            Component.resumeLayouts(true);
        }
    };
 
    /**
     * @method setGlyphFontFamily
     * Sets the default font-family to use for components that support a `glyph` config.
     * @param {String} fontFamily The name of the font-family
     * @member Ext
     */
    Ext.setGlyphFontFamily = function (fontFamily) {
        Ext._glyphFontFamily = fontFamily;
    };
 
    // These are legacy names which are now subsumed by Ext.GlobalEvents
    Component.hierarchyEventSource = prototype.hierarchyEventSource =
        Ext.GlobalEvents;
 
    // High Contrast mode in Windows disables background images and usually
    // causes much pain by this. We feature detect it early and add this class
    // to allow potential workarounds.
    Ext.onReady(function() {
        if (Ext.supports.HighContrastMode) {
            Ext.getBody().addCls(Component.ariaHighContrastModeCls);
        }
    });
});
 
 
 
/* TODO
 *
 * ## Child Sessions
 *
 * By default, sessions created in child components are called "child sessions".
 * All data and edits are copied from the parent session in to the child session.
 * These changes can be written back to the parent session much like a session
 * can save its data to a server.
 *
 *      Ext.create({
 *          xtype: 'window',
 *          modal: true,
 *
 *          // Creates a new session for this Window but that session is linked
 *          // to a parent session (probably from the application's Viewport).
 *          //
 *          session: true,
 *
 *          items: [{
 *              ...
 *          },{
 *              xtype: 'button',
 *              text: 'OK',
 *              listeners: {
 *                  click: function () {
 *                      // Get the Session this component has inherited (from
 *                      // the Window) and save it back to the parent session.
 *                      //
 *                      this.lookupSession().save();
 *                  }
 *              }
 *          }]
 *      });
 *
 * ### Isolated Sessions
 *
 * This connection of a child session to its parent session is determined by the
 * `{@link Ext.data.Session#isolated isolated}` config. If `isolated` is
 * set to `true` then this session will not copy anything from a higher level
 * session and will instead do its own communication with the server.
 *
 *      Ext.create({
 *          xtype: 'window',
 *          modal: true,
 *
 *          // Creates a new session for this Window that is isolated from any
 *          // other sessions. All data for this session will be fetched from
 *          // the server and ultimately saved back to the server.
 *          //
 *          session: {
 *              isolated: true
 *          },
 *
 *          items: [{
 *              ...
 *          },{
 *              xtype: 'button',
 *              text: 'OK',
 *              listeners: {
 *                  click: function () {
 *                      // Get the Session this component has inherited (from
 *                      // the Window) and save it back to the server.
 *                      //
 *                      this.lookupSession().save();
 *                  }
 *              }
 *          }]
 *      });
 */