3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * An abstract base class which provides shared methods for Components across the Sencha product line.
18 * Please refer to sub class's documentation
21 Ext.define('Ext.AbstractComponent', {
23 /* Begin Definitions */
26 'Ext.ComponentManager'
30 observable: 'Ext.util.Observable',
31 animate: 'Ext.util.Animate',
32 state: 'Ext.state.Stateful'
35 // The "uses" property specifies class which are used in an instantiated AbstractComponent.
36 // They do *not* have to be loaded before this class may be defined - that is what "requires" is for.
39 'Ext.ComponentManager',
44 'Ext.ComponentLoader',
47 'Ext.layout.component.Auto',
60 getAutoId: function() {
61 return ++Ext.AbstractComponent.AUTO_ID;
67 * The **unique id of this component instance.**
69 * It should not be necessary to use this configuration except for singleton objects in your application. Components
70 * created with an id may be accessed globally using {@link Ext#getCmp Ext.getCmp}.
72 * Instead of using assigned ids, use the {@link #itemId} config, and {@link Ext.ComponentQuery ComponentQuery}
73 * which provides selector-based searching for Sencha Components analogous to DOM querying. The {@link
74 * Ext.container.Container Container} class contains {@link Ext.container.Container#down shortcut methods} to query
75 * its descendant Components by selector.
77 * Note that this id will also be used as the element id for the containing HTML element that is rendered to the
78 * page for this component. This allows you to write id-based CSS rules to style the specific instance of this
79 * component uniquely, and also to select sub-elements using this component's id as the parent.
81 * **Note**: to avoid complications imposed by a unique id also see `{@link #itemId}`.
83 * **Note**: to access the container of a Component see `{@link #ownerCt}`.
85 * Defaults to an {@link #getId auto-assigned id}.
89 * @cfg {String} itemId
90 * An itemId can be used as an alternative way to get a reference to a component when no object reference is
91 * available. Instead of using an `{@link #id}` with {@link Ext}.{@link Ext#getCmp getCmp}, use `itemId` with
92 * {@link Ext.container.Container}.{@link Ext.container.Container#getComponent getComponent} which will retrieve
93 * `itemId`'s or {@link #id}'s. Since `itemId`'s are an index to the container's internal MixedCollection, the
94 * `itemId` is scoped locally to the container -- avoiding potential conflicts with {@link Ext.ComponentManager}
95 * which requires a **unique** `{@link #id}`.
97 * var c = new Ext.panel.Panel({ //
98 * {@link Ext.Component#height height}: 300,
99 * {@link #renderTo}: document.body,
100 * {@link Ext.container.Container#layout layout}: 'auto',
101 * {@link Ext.container.Container#items items}: [
104 * {@link Ext.panel.Panel#title title}: 'Panel 1',
105 * {@link Ext.Component#height height}: 150
109 * {@link Ext.panel.Panel#title title}: 'Panel 2',
110 * {@link Ext.Component#height height}: 150
114 * p1 = c.{@link Ext.container.Container#getComponent getComponent}('p1'); // not the same as {@link Ext#getCmp Ext.getCmp()}
115 * p2 = p1.{@link #ownerCt}.{@link Ext.container.Container#getComponent getComponent}('p2'); // reference via a sibling
117 * Also see {@link #id}, `{@link Ext.container.Container#query}`, `{@link Ext.container.Container#down}` and
118 * `{@link Ext.container.Container#child}`.
120 * **Note**: to access the container of an item see {@link #ownerCt}.
124 * @property {Ext.Container} ownerCt
125 * This Component's owner {@link Ext.container.Container Container} (is set automatically
126 * when this Component is added to a Container). Read-only.
128 * **Note**: to access items within the Container see {@link #itemId}.
132 * @property {Boolean} layoutManagedWidth
134 * Flag set by the container layout to which this Component is added.
135 * If the layout manages this Component's width, it sets the value to 1.
136 * If it does NOT manage the width, it sets it to 2.
137 * If the layout MAY affect the width, but only if the owning Container has a fixed width, this is set to 0.
141 * @property {Boolean} layoutManagedHeight
143 * Flag set by the container layout to which this Component is added.
144 * If the layout manages this Component's height, it sets the value to 1.
145 * If it does NOT manage the height, it sets it to 2.
146 * If the layout MAY affect the height, but only if the owning Container has a fixed height, this is set to 0.
150 * @cfg {String/Object} autoEl
151 * A tag name or {@link Ext.DomHelper DomHelper} spec used to create the {@link #getEl Element} which will
152 * encapsulate this Component.
154 * You do not normally need to specify this. For the base classes {@link Ext.Component} and
155 * {@link Ext.container.Container}, this defaults to **'div'**. The more complex Sencha classes use a more
156 * complex DOM structure specified by their own {@link #renderTpl}s.
158 * This is intended to allow the developer to create application-specific utility Components encapsulated by
159 * different DOM elements. Example usage:
162 * xtype: 'component',
165 * src: 'http://www.example.com/example.jpg'
168 * xtype: 'component',
171 * html: 'autoEl is cool!'
174 * xtype: 'container',
176 * cls: 'ux-unordered-list',
178 * xtype: 'component',
180 * html: 'First list item'
186 * @cfg {Ext.XTemplate/String/String[]} renderTpl
187 * An {@link Ext.XTemplate XTemplate} used to create the internal structure inside this Component's encapsulating
188 * {@link #getEl Element}.
190 * You do not normally need to specify this. For the base classes {@link Ext.Component} and
191 * {@link Ext.container.Container}, this defaults to **`null`** which means that they will be initially rendered
192 * with no internal structure; they render their {@link #getEl Element} empty. The more specialized ExtJS and Touch
193 * classes which use a more complex DOM structure, provide their own template definitions.
195 * This is intended to allow the developer to create application-specific utility Components with customized
196 * internal structure.
198 * Upon rendering, any created child elements may be automatically imported into object properties using the
199 * {@link #renderSelectors} and {@link #childEls} options.
204 * @cfg {Object} renderData
206 * The data used by {@link #renderTpl} in addition to the following property values of the component:
215 * See {@link #renderSelectors} and {@link #childEls} for usage examples.
219 * @cfg {Object} renderSelectors
220 * An object containing properties specifying {@link Ext.DomQuery DomQuery} selectors which identify child elements
221 * created by the render process.
223 * After the Component's internal structure is rendered according to the {@link #renderTpl}, this object is iterated through,
224 * and the found Elements are added as properties to the Component using the `renderSelector` property name.
226 * For example, a Component which renderes a title and description into its element:
228 * Ext.create('Ext.Component', {
229 * renderTo: Ext.getBody(),
231 * '<h1 class="title">{title}</h1>',
236 * desc: "Something went wrong"
239 * titleEl: 'h1.title',
243 * afterrender: function(cmp){
244 * // After rendering the component will have a titleEl and descEl properties
245 * cmp.titleEl.setStyle({color: "red"});
250 * For a faster, but less flexible, alternative that achieves the same end result (properties for child elements on the
251 * Component after render), see {@link #childEls} and {@link #addChildEls}.
255 * @cfg {Object[]} childEls
256 * An array describing the child elements of the Component. Each member of the array
257 * is an object with these properties:
259 * - `name` - The property name on the Component for the child element.
260 * - `itemId` - The id to combine with the Component's id that is the id of the child element.
261 * - `id` - The id of the child element.
263 * If the array member is a string, it is equivalent to `{ name: m, itemId: m }`.
265 * For example, a Component which renders a title and body text:
267 * Ext.create('Ext.Component', {
268 * renderTo: Ext.getBody(),
270 * '<h1 id="{id}-title">{title}</h1>',
275 * msg: "Something went wrong"
277 * childEls: ["title"],
279 * afterrender: function(cmp){
280 * // After rendering the component will have a title property
281 * cmp.title.setStyle({color: "red"});
286 * A more flexible, but somewhat slower, approach is {@link #renderSelectors}.
290 * @cfg {String/HTMLElement/Ext.Element} renderTo
291 * Specify the id of the element, a DOM element or an existing Element that this component will be rendered into.
295 * Do *not* use this option if the Component is to be a child item of a {@link Ext.container.Container Container}.
296 * It is the responsibility of the {@link Ext.container.Container Container}'s
297 * {@link Ext.container.Container#layout layout manager} to render and manage its child items.
299 * When using this config, a call to render() is not required.
301 * See `{@link #render}` also.
305 * @cfg {Boolean} frame
306 * Specify as `true` to have the Component inject framing elements within the Component at render time to provide a
307 * graphical rounded frame around the Component content.
309 * This is only necessary when running on outdated, or non standard-compliant browsers such as Microsoft's Internet
310 * Explorer prior to version 9 which do not support rounded corners natively.
312 * The extra space taken up by this framing is available from the read only property {@link #frameSize}.
316 * @property {Object} frameSize
317 * Read-only property indicating the width of any framing elements which were added within the encapsulating element
318 * to provide graphical, rounded borders. See the {@link #frame} config.
320 * This is an object containing the frame width in pixels for all four sides of the Component containing the
321 * following properties:
323 * @property {Number} frameSize.top The width of the top framing element in pixels.
324 * @property {Number} frameSize.right The width of the right framing element in pixels.
325 * @property {Number} frameSize.bottom The width of the bottom framing element in pixels.
326 * @property {Number} frameSize.left The width of the left framing element in pixels.
330 * @cfg {String/Object} componentLayout
331 * The sizing and positioning of a Component's internal Elements is the responsibility of the Component's layout
332 * manager which sizes a Component's internal structure in response to the Component being sized.
334 * Generally, developers will not use this configuration as all provided Components which need their internal
335 * elements sizing (Such as {@link Ext.form.field.Base input fields}) come with their own componentLayout managers.
337 * The {@link Ext.layout.container.Auto default layout manager} will be used on instances of the base Ext.Component
338 * class which simply sizes the Component's encapsulating element to the height and width specified in the
339 * {@link #setSize} method.
343 * @cfg {Ext.XTemplate/Ext.Template/String/String[]} tpl
344 * An {@link Ext.Template}, {@link Ext.XTemplate} or an array of strings to form an Ext.XTemplate. Used in
345 * conjunction with the `{@link #data}` and `{@link #tplWriteMode}` configurations.
350 * The initial set of data to apply to the `{@link #tpl}` to update the content area of the Component.
354 * @cfg {String} xtype
355 * The `xtype` configuration option can be used to optimize Component creation and rendering. It serves as a
356 * shortcut to the full componet name. For example, the component `Ext.button.Button` has an xtype of `button`.
358 * You can define your own xtype on a custom {@link Ext.Component component} by specifying the
359 * {@link Ext.Class#alias alias} config option with a prefix of `widget`. For example:
361 * Ext.define('PressMeButton', {
362 * extend: 'Ext.button.Button',
363 * alias: 'widget.pressmebutton',
367 * Any Component can be created implicitly as an object config with an xtype specified, allowing it to be
368 * declared and passed into the rendering pipeline without actually being instantiated as an object. Not only is
369 * rendering deferred, but the actual creation of the object itself is also deferred, saving memory and resources
370 * until they are actually needed. In complex, nested layouts containing many Components, this can make a
371 * noticeable improvement in performance.
373 * // Explicit creation of contained Components:
374 * var panel = new Ext.Panel({
377 * Ext.create('Ext.button.Button', {
383 * // Implicit creation using xtype:
384 * var panel = new Ext.Panel({
392 * In the first example, the button will always be created immediately during the panel's initialization. With
393 * many added Components, this approach could potentially slow the rendering of the page. In the second example,
394 * the button will not be created or rendered until the panel is actually displayed in the browser. If the panel
395 * is never displayed (for example, if it is a tab that remains hidden) then the button will never be created and
396 * will never consume any resources whatsoever.
400 * @cfg {String} tplWriteMode
401 * The Ext.(X)Template method to use when updating the content area of the Component.
402 * See `{@link Ext.XTemplate#overwrite}` for information on default mode.
404 tplWriteMode: 'overwrite',
407 * @cfg {String} [baseCls='x-component']
408 * The base CSS class to apply to this components's element. This will also be prepended to elements within this
409 * component like Panel's body will get a class x-panel-body. This means that if you create a subclass of Panel, and
410 * you want it to get all the Panels styling for the element and the body, you leave the baseCls x-panel and use
411 * componentCls to add specific styling for this component.
413 baseCls: Ext.baseCSSPrefix + 'component',
416 * @cfg {String} componentCls
417 * CSS Class to be added to a components root level element to give distinction to it via styling.
421 * @cfg {String} [cls='']
422 * An optional extra CSS class that will be added to this component's Element. This can be useful
423 * for adding customized styles to the component or any of its children using standard CSS rules.
427 * @cfg {String} [overCls='']
428 * An optional extra CSS class that will be added to this component's Element when the mouse moves over the Element,
429 * and removed when the mouse moves out. This can be useful for adding customized 'active' or 'hover' styles to the
430 * component or any of its children using standard CSS rules.
434 * @cfg {String} [disabledCls='x-item-disabled']
435 * CSS class to add when the Component is disabled. Defaults to 'x-item-disabled'.
437 disabledCls: Ext.baseCSSPrefix + 'item-disabled',
440 * @cfg {String/String[]} ui
441 * A set style for a component. Can be a string or an Array of multiple strings (UIs)
446 * @cfg {String[]} uiCls
447 * An array of of classNames which are currently applied to this component
453 * @cfg {String} style
454 * A custom style specification to be applied to this component's Element. Should be a valid argument to
455 * {@link Ext.Element#applyStyles}.
457 * new Ext.panel.Panel({
458 * title: 'Some Title',
459 * renderTo: Ext.getBody(),
460 * width: 400, height: 300,
466 * marginBottom: '10px'
469 * new Ext.button.Button({
473 * marginBottom: '10px'
481 * @cfg {Number} width
482 * The width of this component in pixels.
486 * @cfg {Number} height
487 * The height of this component in pixels.
491 * @cfg {Number/String} border
492 * Specifies the border for this component. The border can be a single numeric value to apply to all sides or it can
493 * be a CSS style specification for each style, for example: '10 5 3 10'.
497 * @cfg {Number/String} padding
498 * Specifies the padding for this component. The padding can be a single numeric value to apply to all sides or it
499 * can be a CSS style specification for each style, for example: '10 5 3 10'.
503 * @cfg {Number/String} margin
504 * Specifies the margin for this component. The margin can be a single numeric value to apply to all sides or it can
505 * be a CSS style specification for each style, for example: '10 5 3 10'.
509 * @cfg {Boolean} hidden
510 * True to hide the component.
515 * @cfg {Boolean} disabled
516 * True to disable the component.
521 * @cfg {Boolean} [draggable=false]
522 * Allows the component to be dragged.
526 * @property {Boolean} draggable
527 * Read-only property indicating whether or not the component can be dragged
532 * @cfg {Boolean} floating
533 * Create the Component as a floating and use absolute positioning.
535 * The z-index of floating Components is handled by a ZIndexManager. If you simply render a floating Component into the DOM, it will be managed
536 * by the global {@link Ext.WindowManager WindowManager}.
538 * If you include a floating Component as a child item of a Container, then upon render, ExtJS will seek an ancestor floating Component to house a new
539 * ZIndexManager instance to manage its descendant floaters. If no floating ancestor can be found, the global WindowManager will be used.
541 * When a floating Component which has a ZindexManager managing descendant floaters is destroyed, those descendant floaters will also be destroyed.
546 * @cfg {String} hideMode
547 * A String which specifies how this Component's encapsulating DOM element will be hidden. Values may be:
549 * - `'display'` : The Component will be hidden using the `display: none` style.
550 * - `'visibility'` : The Component will be hidden using the `visibility: hidden` style.
551 * - `'offsets'` : The Component will be hidden by absolutely positioning it out of the visible area of the document.
552 * This is useful when a hidden Component must maintain measurable dimensions. Hiding using `display` results in a
553 * Component having zero dimensions.
558 * @cfg {String} contentEl
559 * Specify an existing HTML element, or the `id` of an existing HTML element to use as the content for this component.
561 * This config option is used to take an existing HTML element and place it in the layout element of a new component
562 * (it simply moves the specified DOM element _after the Component is rendered_ to use as the content.
566 * The specified HTML element is appended to the layout element of the component _after any configured
567 * {@link #html HTML} has been inserted_, and so the document will not contain this element at the time
568 * the {@link #render} event is fired.
570 * The specified HTML element used will not participate in any **`{@link Ext.container.Container#layout layout}`**
571 * scheme that the Component may use. It is just HTML. Layouts operate on child
572 * **`{@link Ext.container.Container#items items}`**.
574 * Add either the `x-hidden` or the `x-hide-display` CSS class to prevent a brief flicker of the content before it
575 * is rendered to the panel.
579 * @cfg {String/Object} [html='']
580 * An HTML fragment, or a {@link Ext.DomHelper DomHelper} specification to use as the layout element content.
581 * The HTML content is added after the component is rendered, so the document will not contain this HTML at the time
582 * the {@link #render} event is fired. This content is inserted into the body _before_ any configured {@link #contentEl}
587 * @cfg {Boolean} styleHtmlContent
588 * True to automatically style the html inside the content target of this component (body for panels).
590 styleHtmlContent: false,
593 * @cfg {String} [styleHtmlCls='x-html']
594 * The class that is added to the content target when you set styleHtmlContent to true.
596 styleHtmlCls: Ext.baseCSSPrefix + 'html',
599 * @cfg {Number} minHeight
600 * The minimum value in pixels which this Component will set its height to.
602 * **Warning:** This will override any size management applied by layout managers.
605 * @cfg {Number} minWidth
606 * The minimum value in pixels which this Component will set its width to.
608 * **Warning:** This will override any size management applied by layout managers.
611 * @cfg {Number} maxHeight
612 * The maximum value in pixels which this Component will set its height to.
614 * **Warning:** This will override any size management applied by layout managers.
617 * @cfg {Number} maxWidth
618 * The maximum value in pixels which this Component will set its width to.
620 * **Warning:** This will override any size management applied by layout managers.
624 * @cfg {Ext.ComponentLoader/Object} loader
625 * A configuration object or an instance of a {@link Ext.ComponentLoader} to load remote content for this Component.
629 * @cfg {Boolean} autoShow
630 * True to automatically show the component upon creation. This config option may only be used for
631 * {@link #floating} components or components that use {@link #autoRender}. Defaults to false.
636 * @cfg {Boolean/String/HTMLElement/Ext.Element} autoRender
637 * This config is intended mainly for non-{@link #floating} Components which may or may not be shown. Instead of using
638 * {@link #renderTo} in the configuration, and rendering upon construction, this allows a Component to render itself
639 * upon first _{@link #show}_. If {@link #floating} is true, the value of this config is omited as if it is `true`.
641 * Specify as `true` to have this Component render to the document body upon first show.
643 * Specify as an element, or the ID of an element to have this Component render to a specific element upon first
646 * **This defaults to `true` for the {@link Ext.window.Window Window} class.**
656 * @cfg {Object/Object[]} plugins
657 * An object or array of objects that will provide custom functionality for this component. The only requirement for
658 * a valid plugin is that it contain an init method that accepts a reference of type Ext.Component. When a component
659 * is created, if any plugins are available, the component will call the init method on each plugin, passing a
660 * reference to itself. Each plugin can then call methods or respond to events on the component as needed to provide
665 * @property {Boolean} rendered
666 * Read-only property indicating whether or not the component has been rendered.
671 * @property {Number} componentLayoutCounter
673 * The number of component layout calls made on this object.
675 componentLayoutCounter: 0,
679 trimRe: /^\s+|\s+$/g,
684 * @property {Boolean} maskOnDisable
685 * This is an internal flag that you use when creating custom components. By default this is set to true which means
686 * that every component gets a mask when its disabled. Components like FieldContainer, FieldSet, Field, Button, Tab
687 * override this property to false since they want to implement custom disable logic.
692 * Creates new Component.
693 * @param {Object} config (optional) Config object.
695 constructor : function(config) {
699 config = config || {};
700 me.initialConfig = config;
701 Ext.apply(me, config);
705 * @event beforeactivate
706 * Fires before a Component has been visually activated. Returning false from an event listener can prevent
707 * the activate from occurring.
708 * @param {Ext.Component} this
713 * Fires after a Component has been visually activated.
714 * @param {Ext.Component} this
718 * @event beforedeactivate
719 * Fires before a Component has been visually deactivated. Returning false from an event listener can
720 * prevent the deactivate from occurring.
721 * @param {Ext.Component} this
726 * Fires after a Component has been visually deactivated.
727 * @param {Ext.Component} this
732 * Fires after a Component had been added to a Container.
733 * @param {Ext.Component} this
734 * @param {Ext.container.Container} container Parent Container
735 * @param {Number} pos position of Component
740 * Fires after the component is disabled.
741 * @param {Ext.Component} this
746 * Fires after the component is enabled.
747 * @param {Ext.Component} this
752 * Fires before the component is shown when calling the {@link #show} method. Return false from an event
753 * handler to stop the show.
754 * @param {Ext.Component} this
759 * Fires after the component is shown when calling the {@link #show} method.
760 * @param {Ext.Component} this
765 * Fires before the component is hidden when calling the {@link #hide} method. Return false from an event
766 * handler to stop the hide.
767 * @param {Ext.Component} this
772 * Fires after the component is hidden. Fires after the component is hidden when calling the {@link #hide}
774 * @param {Ext.Component} this
779 * Fires when a component is removed from an Ext.container.Container
780 * @param {Ext.Component} this
781 * @param {Ext.container.Container} ownerCt Container which holds the component
785 * @event beforerender
786 * Fires before the component is {@link #rendered}. Return false from an event handler to stop the
788 * @param {Ext.Component} this
793 * Fires after the component markup is {@link #rendered}.
794 * @param {Ext.Component} this
799 * Fires after the component rendering is finished.
801 * The afterrender event is fired after this Component has been {@link #rendered}, been postprocesed by any
802 * afterRender method defined for the Component.
803 * @param {Ext.Component} this
807 * @event beforedestroy
808 * Fires before the component is {@link #destroy}ed. Return false from an event handler to stop the
810 * @param {Ext.Component} this
815 * Fires after the component is {@link #destroy}ed.
816 * @param {Ext.Component} this
821 * Fires after the component is resized.
822 * @param {Ext.Component} this
823 * @param {Number} adjWidth The box-adjusted width that was set
824 * @param {Number} adjHeight The box-adjusted height that was set
829 * Fires after the component is moved.
830 * @param {Ext.Component} this
831 * @param {Number} x The new x position
832 * @param {Number} y The new y position
840 me.additionalCls = [];
841 me.renderData = me.renderData || {};
842 me.renderSelectors = me.renderSelectors || {};
845 me.plugins = [].concat(me.plugins);
846 me.constructPlugins();
851 // ititComponent gets a chance to change the id property before registering
852 Ext.ComponentManager.register(me);
854 // Dont pass the config so that it is not applied to 'this' again
855 me.mixins.observable.constructor.call(me);
856 me.mixins.state.constructor.call(me, config);
858 // Save state on resize.
859 this.addStateEvents('resize');
861 // Move this into Observable?
863 me.plugins = [].concat(me.plugins);
864 for (i = 0, len = me.plugins.length; i < len; i++) {
865 me.plugins[i] = me.initPlugin(me.plugins[i]);
869 me.loader = me.getLoader();
872 me.render(me.renderTo);
873 // EXTJSIV-1935 - should be a way to do afterShow or something, but that
874 // won't work. Likewise, rendering hidden and then showing (w/autoShow) has
875 // implications to afterRender so we cannot do that.
883 if (Ext.isDefined(me.disabledClass)) {
884 if (Ext.isDefined(Ext.global.console)) {
885 Ext.global.console.warn('Ext.Component: disabledClass has been deprecated. Please use disabledCls.');
887 me.disabledCls = me.disabledClass;
888 delete me.disabledClass;
893 initComponent: function () {
894 // This is called again here to allow derived classes to add plugin configs to the
895 // plugins array before calling down to this, the base initComponent.
896 this.constructPlugins();
900 * The supplied default state gathering method for the AbstractComponent class.
902 * This method returns dimension settings such as `flex`, `anchor`, `width` and `height` along with `collapsed`
905 * Subclasses which implement more complex state should call the superclass's implementation, and apply their state
906 * to the result if this basic state is to be saved.
908 * Note that Component state will only be saved if the Component has a {@link #stateId} and there as a StateProvider
909 * configured for the document.
913 getState: function() {
915 layout = me.ownerCt ? (me.shadowOwnerCt || me.ownerCt).getLayout() : null,
917 collapsed: me.collapsed
921 cm = me.collapseMemento,
924 // If a Panel-local collapse has taken place, use remembered values as the dimensions.
925 // TODO: remove this coupling with Panel's privates! All collapse/expand logic should be refactored into one place.
926 if (me.collapsed && cm) {
927 if (Ext.isDefined(cm.data.width)) {
930 if (Ext.isDefined(cm.data.height)) {
935 // If we have flex, only store the perpendicular dimension.
936 if (layout && me.flex) {
937 state.flex = me.flex;
938 if (layout.perpendicularPrefix) {
939 state[layout.perpendicularPrefix] = me['get' + layout.perpendicularPrefixCap]();
942 if (Ext.isDefined(Ext.global.console)) {
943 Ext.global.console.warn('Ext.Component: Specified a flex value on a component not inside a Box layout');
948 // If we have anchor, only store dimensions which are *not* being anchored
949 else if (layout && me.anchor) {
950 state.anchor = me.anchor;
951 anchors = me.anchor.split(' ').concat(null);
959 state.height = height;
969 state.height = height;
973 // Don't save dimensions if they are unchanged from the original configuration.
974 if (state.width == me.initialConfig.width) {
977 if (state.height == me.initialConfig.height) {
981 // If a Box layout was managing the perpendicular dimension, don't save that dimension
982 if (layout && layout.align && (layout.align.indexOf('stretch') !== -1)) {
983 delete state[layout.perpendicularPrefix];
990 animate: function(animObj) {
994 animObj = animObj || {};
995 to = animObj.to || {};
997 if (Ext.fx.Manager.hasFxBlock(me.id)) {
1000 // Special processing for animating Component dimensions.
1001 if (!animObj.dynamic && (to.height || to.width)) {
1002 var curWidth = me.getWidth(),
1004 curHeight = me.getHeight(),
1006 needsResize = false;
1008 if (to.height && to.height > curHeight) {
1012 if (to.width && to.width > curWidth) {
1017 // If any dimensions are being increased, we must resize the internal structure
1018 // of the Component, but then clip it by sizing its encapsulating element back to original dimensions.
1019 // The animation will then progressively reveal the larger content.
1021 var clearWidth = !Ext.isNumber(me.width),
1022 clearHeight = !Ext.isNumber(me.height);
1024 me.componentLayout.childrenChanged = true;
1025 me.setSize(w, h, me.ownerCt);
1026 me.el.setSize(curWidth, curHeight);
1035 return me.mixins.animate.animate.apply(me, arguments);
1039 * This method finds the topmost active layout who's processing will eventually determine the size and position of
1042 * This method is useful when dynamically adding Components into Containers, and some processing must take place
1043 * after the final sizing and positioning of the Component has been performed.
1045 * @return {Ext.Component}
1047 findLayoutController: function() {
1048 return this.findParentBy(function(c) {
1049 // Return true if we are at the root of the Container tree
1050 // or this Container's layout is busy but the next one up is not.
1051 return !c.ownerCt || (c.layout.layoutBusy && !c.ownerCt.layout.layoutBusy);
1055 onShow : function() {
1057 var needsLayout = this.needsLayout;
1058 if (Ext.isObject(needsLayout)) {
1059 this.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize, needsLayout.ownerCt);
1063 constructPlugin: function(plugin) {
1064 if (plugin.ptype && typeof plugin.init != 'function') {
1066 plugin = Ext.PluginManager.create(plugin);
1068 else if (typeof plugin == 'string') {
1069 plugin = Ext.PluginManager.create({
1078 * Ensures that the plugins array contains fully constructed plugin instances. This converts any configs into their
1079 * appropriate instances.
1081 constructPlugins: function() {
1083 plugins = me.plugins,
1087 for (i = 0, len = plugins.length; i < len; i++) {
1088 // this just returns already-constructed plugin instances...
1089 plugins[i] = me.constructPlugin(plugins[i]);
1095 initPlugin : function(plugin) {
1102 * Handles autoRender. Floating Components may have an ownerCt. If they are asking to be constrained, constrain them
1103 * within that ownerCt, and have their z-index managed locally. Floating Components are always rendered to
1106 doAutoRender: function() {
1109 me.render(document.body);
1111 me.render(Ext.isBoolean(me.autoRender) ? Ext.getBody() : me.autoRender);
1116 render : function(container, position) {
1119 if (!me.rendered && me.fireEvent('beforerender', me) !== false) {
1121 // Flag set during the render process.
1122 // It can be used to inhibit event-driven layout calls during the render phase
1123 me.rendering = true;
1125 // If this.el is defined, we want to make sure we are dealing with
1128 me.el = Ext.get(me.el);
1131 // Perform render-time processing for floating Components
1136 container = me.initContainer(container);
1138 me.onRender(container, position);
1140 // Tell the encapsulating element to hide itself in the way the Component is configured to hide
1141 // This means DISPLAY, VISIBILITY or OFFSETS.
1142 me.el.setVisibilityMode(Ext.Element[me.hideMode.toUpperCase()]);
1145 me.el.hover(me.addOverCls, me.removeOverCls, me);
1148 me.fireEvent('render', me);
1152 me.afterRender(container);
1153 me.fireEvent('afterrender', me);
1158 // Hiding during the render process should not perform any ancillary
1159 // actions that the full hide process does; It is not hiding, it begins in a hidden state.'
1160 // So just make the element hidden according to the configured hideMode
1165 // pass silent so the event doesn't fire the first time.
1169 // Delete the flag once the rendering is done.
1170 delete me.rendering;
1176 onRender : function(container, position) {
1179 styles = me.initStyles(),
1180 renderTpl, renderData, i;
1182 position = me.getInsertPosition(position);
1186 el = Ext.DomHelper.insertBefore(position, me.getElConfig(), true);
1189 el = Ext.DomHelper.append(container, me.getElConfig(), true);
1192 else if (me.allowDomMove !== false) {
1194 container.dom.insertBefore(el.dom, position);
1196 container.dom.appendChild(el.dom);
1200 if (Ext.scopeResetCSS && !me.ownerCt) {
1201 // If this component's el is the body element, we add the reset class to the html tag
1202 if (el.dom == Ext.getBody().dom) {
1203 el.parent().addCls(Ext.baseCSSPrefix + 'reset');
1206 // Else we wrap this element in an element that adds the reset class.
1207 me.resetEl = el.wrap({
1208 cls: Ext.baseCSSPrefix + 'reset'
1215 el.addCls(me.initCls());
1216 el.setStyle(styles);
1218 // Here we check if the component has a height set through style or css.
1219 // If it does then we set the this.height to that value and it won't be
1220 // considered an auto height component
1221 // if (this.height === undefined) {
1222 // var height = el.getHeight();
1223 // // This hopefully means that the panel has an explicit height set in style or css
1224 // if (height - el.getPadding('tb') - el.getBorderWidth('tb') > 0) {
1225 // this.height = height;
1233 renderTpl = me.initRenderTpl();
1235 renderData = me.initRenderData();
1236 renderTpl.append(me.getTargetEl(), renderData);
1239 me.applyRenderSelectors();
1245 afterRender : function() {
1250 me.getComponentLayout();
1252 // Set the size if a size is configured, or if this is the outermost Container.
1253 // Also, if this is a collapsed Panel, it needs an initial component layout
1254 // to lay out its header so that it can have a height determined.
1255 if (me.collapsed || (!me.ownerCt || (me.height || me.width))) {
1256 me.setSize(me.width, me.height);
1258 // It is expected that child items be rendered before this method returns and
1259 // the afterrender event fires. Since we aren't going to do the layout now, we
1260 // must render the child items. This is handled implicitly above in the layout
1261 // caused by setSize.
1262 me.renderChildren();
1265 // For floaters, calculate x and y if they aren't defined by aligning
1266 // the sized element to the center of either the container or the ownerCt
1267 if (me.floating && (me.x === undefined || me.y === undefined)) {
1268 if (me.floatParent) {
1269 xy = me.el.getAlignToXY(me.floatParent.getTargetEl(), 'c-c');
1270 pos = me.floatParent.getTargetEl().translatePoints(xy[0], xy[1]);
1272 xy = me.el.getAlignToXY(me.container, 'c-c');
1273 pos = me.container.translatePoints(xy[0], xy[1]);
1275 me.x = me.x === undefined ? pos.left: me.x;
1276 me.y = me.y === undefined ? pos.top: me.y;
1279 if (Ext.isDefined(me.x) || Ext.isDefined(me.y)) {
1280 me.setPosition(me.x, me.y);
1283 if (me.styleHtmlContent) {
1284 me.getTargetEl().addCls(me.styleHtmlCls);
1290 * Called by Component#doAutoRender
1292 * Register a Container configured `floating: true` with this Component's {@link Ext.ZIndexManager ZIndexManager}.
1294 * Components added in ths way will not participate in any layout, but will be rendered
1295 * upon first show in the way that {@link Ext.window.Window Window}s are.
1297 registerFloatingItem: function(cmp) {
1299 if (!me.floatingItems) {
1300 me.floatingItems = Ext.create('Ext.ZIndexManager', me);
1302 me.floatingItems.register(cmp);
1305 renderChildren: function () {
1307 layout = me.getComponentLayout();
1309 me.suspendLayout = true;
1310 layout.renderChildren();
1311 delete me.suspendLayout;
1314 frameCls: Ext.baseCSSPrefix + 'frame',
1316 frameIdRegex: /[-]frame\d+[TMB][LCR]$/,
1332 '<tpl if="left"><div id="{fgid}TL" class="{frameCls}-tl {baseCls}-tl {baseCls}-{ui}-tl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tl</tpl></tpl>" style="background-position: {tl}; padding-left: {frameWidth}px" role="presentation"></tpl>',
1333 '<tpl if="right"><div id="{fgid}TR" class="{frameCls}-tr {baseCls}-tr {baseCls}-{ui}-tr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tr</tpl></tpl>" style="background-position: {tr}; padding-right: {frameWidth}px" role="presentation"></tpl>',
1334 '<div id="{fgid}TC" class="{frameCls}-tc {baseCls}-tc {baseCls}-{ui}-tc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tc</tpl></tpl>" style="background-position: {tc}; height: {frameWidth}px" role="presentation"></div>',
1335 '<tpl if="right"></div></tpl>',
1336 '<tpl if="left"></div></tpl>',
1338 '<tpl if="left"><div id="{fgid}ML" class="{frameCls}-ml {baseCls}-ml {baseCls}-{ui}-ml<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-ml</tpl></tpl>" style="background-position: {ml}; padding-left: {frameWidth}px" role="presentation"></tpl>',
1339 '<tpl if="right"><div id="{fgid}MR" class="{frameCls}-mr {baseCls}-mr {baseCls}-{ui}-mr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mr</tpl></tpl>" style="background-position: {mr}; padding-right: {frameWidth}px" role="presentation"></tpl>',
1340 '<div id="{fgid}MC" class="{frameCls}-mc {baseCls}-mc {baseCls}-{ui}-mc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mc</tpl></tpl>" role="presentation"></div>',
1341 '<tpl if="right"></div></tpl>',
1342 '<tpl if="left"></div></tpl>',
1343 '<tpl if="bottom">',
1344 '<tpl if="left"><div id="{fgid}BL" class="{frameCls}-bl {baseCls}-bl {baseCls}-{ui}-bl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bl</tpl></tpl>" style="background-position: {bl}; padding-left: {frameWidth}px" role="presentation"></tpl>',
1345 '<tpl if="right"><div id="{fgid}BR" class="{frameCls}-br {baseCls}-br {baseCls}-{ui}-br<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-br</tpl></tpl>" style="background-position: {br}; padding-right: {frameWidth}px" role="presentation"></tpl>',
1346 '<div id="{fgid}BC" class="{frameCls}-bc {baseCls}-bc {baseCls}-{ui}-bc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bc</tpl></tpl>" style="background-position: {bc}; height: {frameWidth}px" role="presentation"></div>',
1347 '<tpl if="right"></div></tpl>',
1348 '<tpl if="left"></div></tpl>',
1356 '<tpl if="left"><td id="{fgid}TL" class="{frameCls}-tl {baseCls}-tl {baseCls}-{ui}-tl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tl</tpl></tpl>" style="background-position: {tl}; padding-left:{frameWidth}px" role="presentation"></td></tpl>',
1357 '<td id="{fgid}TC" class="{frameCls}-tc {baseCls}-tc {baseCls}-{ui}-tc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tc</tpl></tpl>" style="background-position: {tc}; height: {frameWidth}px" role="presentation"></td>',
1358 '<tpl if="right"><td id="{fgid}TR" class="{frameCls}-tr {baseCls}-tr {baseCls}-{ui}-tr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tr</tpl></tpl>" style="background-position: {tr}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
1362 '<tpl if="left"><td id="{fgid}ML" class="{frameCls}-ml {baseCls}-ml {baseCls}-{ui}-ml<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-ml</tpl></tpl>" style="background-position: {ml}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
1363 '<td id="{fgid}MC" class="{frameCls}-mc {baseCls}-mc {baseCls}-{ui}-mc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mc</tpl></tpl>" style="background-position: 0 0;" role="presentation"></td>',
1364 '<tpl if="right"><td id="{fgid}MR" class="{frameCls}-mr {baseCls}-mr {baseCls}-{ui}-mr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mr</tpl></tpl>" style="background-position: {mr}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
1366 '<tpl if="bottom">',
1368 '<tpl if="left"><td id="{fgid}BL" class="{frameCls}-bl {baseCls}-bl {baseCls}-{ui}-bl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bl</tpl></tpl>" style="background-position: {bl}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
1369 '<td id="{fgid}BC" class="{frameCls}-bc {baseCls}-bc {baseCls}-{ui}-bc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bc</tpl></tpl>" style="background-position: {bc}; height: {frameWidth}px" role="presentation"></td>',
1370 '<tpl if="right"><td id="{fgid}BR" class="{frameCls}-br {baseCls}-br {baseCls}-{ui}-br<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-br</tpl></tpl>" style="background-position: {br}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
1379 initFrame : function() {
1380 if (Ext.supports.CSS3BorderRadius) {
1385 frameInfo = me.getFrameInfo(),
1386 frameWidth = frameInfo.width,
1387 frameTpl = me.getFrameTpl(frameInfo.table),
1391 // since we render id's into the markup and id's NEED to be unique, we have a
1392 // simple strategy for numbering their generations.
1393 me.frameGenId = frameGenId = (me.frameGenId || 0) + 1;
1394 frameGenId = me.id + '-frame' + frameGenId;
1396 // Here we render the frameTpl to this component. This inserts the 9point div or the table framing.
1397 frameTpl.insertFirst(me.el, Ext.apply({}, {
1401 frameCls: me.frameCls,
1402 baseCls: me.baseCls,
1403 frameWidth: frameWidth,
1404 top: !!frameInfo.top,
1405 left: !!frameInfo.left,
1406 right: !!frameInfo.right,
1407 bottom: !!frameInfo.bottom
1408 }, me.getFramePositions(frameInfo)));
1410 // The frameBody is returned in getTargetEl, so that layouts render items to the correct target.=
1411 me.frameBody = me.el.down('.' + me.frameCls + '-mc');
1413 // Clean out the childEls for the old frame elements (the majority of the els)
1414 me.removeChildEls(function (c) {
1415 return c.id && me.frameIdRegex.test(c.id);
1418 // Add the childEls for each of the new frame elements
1419 Ext.each(['TL','TC','TR','ML','MC','MR','BL','BC','BR'], function (suffix) {
1420 me.childEls.push({ name: 'frame' + suffix, id: frameGenId + suffix });
1425 updateFrame: function() {
1426 if (Ext.supports.CSS3BorderRadius) {
1431 wasTable = this.frameSize && this.frameSize.table,
1432 oldFrameTL = this.frameTL,
1433 oldFrameBL = this.frameBL,
1434 oldFrameML = this.frameML,
1435 oldFrameMC = this.frameMC,
1442 // Reapply render selectors
1452 this.applyRenderSelectors();
1454 // Store the class names set on the new mc
1455 newMCClassName = this.frameMC.dom.className;
1457 // Replace the new mc with the old mc
1458 oldFrameMC.insertAfter(this.frameMC);
1459 this.frameMC.remove();
1461 // Restore the reference to the old frame mc as the framebody
1462 this.frameBody = this.frameMC = oldFrameMC;
1464 // Apply the new mc classes to the old mc element
1465 oldFrameMC.dom.className = newMCClassName;
1467 // Remove the old framing
1469 me.el.query('> table')[1].remove();
1473 oldFrameTL.remove();
1476 oldFrameBL.remove();
1478 oldFrameML.remove();
1482 // We were framed but not anymore. Move all content from the old frame to the body
1486 else if (me.frame) {
1487 this.applyRenderSelectors();
1491 getFrameInfo: function() {
1492 if (Ext.supports.CSS3BorderRadius) {
1497 left = me.el.getStyle('background-position-x'),
1498 top = me.el.getStyle('background-position-y'),
1499 info, frameInfo = false, max;
1501 // Some browsers dont support background-position-x and y, so for those
1502 // browsers let's split background-position into two parts.
1503 if (!left && !top) {
1504 info = me.el.getStyle('background-position').split(' ');
1509 // We actually pass a string in the form of '[type][tl][tr]px [type][br][bl]px' as
1510 // the background position of this.el from the css to indicate to IE that this component needs
1511 // framing. We parse it here and change the markup accordingly.
1512 if (parseInt(left, 10) >= 1000000 && parseInt(top, 10) >= 1000000) {
1516 // Table markup starts with 110, div markup with 100.
1517 table: left.substr(0, 3) == '110',
1519 // Determine if we are dealing with a horizontal or vertical component
1520 vertical: top.substr(0, 3) == '110',
1522 // Get and parse the different border radius sizes
1523 top: max(left.substr(3, 2), left.substr(5, 2)),
1524 right: max(left.substr(5, 2), top.substr(3, 2)),
1525 bottom: max(top.substr(3, 2), top.substr(5, 2)),
1526 left: max(top.substr(5, 2), left.substr(3, 2))
1529 frameInfo.width = max(frameInfo.top, frameInfo.right, frameInfo.bottom, frameInfo.left);
1531 // Just to be sure we set the background image of the el to none.
1532 me.el.setStyle('background-image', 'none');
1535 // This happens when you set frame: true explicitly without using the x-frame mixin in sass.
1536 // This way IE can't figure out what sizes to use and thus framing can't work.
1537 if (me.frame === true && !frameInfo) {
1539 Ext.Error.raise("You have set frame: true explicity on this component while it doesn't have any " +
1540 "framing defined in the CSS template. In this case IE can't figure out what sizes " +
1541 "to use and thus framing on this component will be disabled.");
1545 me.frame = me.frame || !!frameInfo;
1546 me.frameSize = frameInfo || false;
1551 getFramePositions: function(frameInfo) {
1553 frameWidth = frameInfo.width,
1555 positions, tc, bc, ml, mr;
1557 if (frameInfo.vertical) {
1558 tc = '0 -' + (frameWidth * 0) + 'px';
1559 bc = '0 -' + (frameWidth * 1) + 'px';
1561 if (dock && dock == "right") {
1562 tc = 'right -' + (frameWidth * 0) + 'px';
1563 bc = 'right -' + (frameWidth * 1) + 'px';
1567 tl: '0 -' + (frameWidth * 0) + 'px',
1568 tr: '0 -' + (frameWidth * 1) + 'px',
1569 bl: '0 -' + (frameWidth * 2) + 'px',
1570 br: '0 -' + (frameWidth * 3) + 'px',
1572 ml: '-' + (frameWidth * 1) + 'px 0',
1579 ml = '-' + (frameWidth * 0) + 'px 0';
1582 if (dock && dock == "bottom") {
1584 mr = 'right bottom';
1588 tl: '0 -' + (frameWidth * 2) + 'px',
1589 tr: 'right -' + (frameWidth * 3) + 'px',
1590 bl: '0 -' + (frameWidth * 4) + 'px',
1591 br: 'right -' + (frameWidth * 5) + 'px',
1596 tc: '0 -' + (frameWidth * 0) + 'px',
1597 bc: '0 -' + (frameWidth * 1) + 'px'
1607 getFrameTpl : function(table) {
1608 return table ? this.getTpl('frameTableTpl') : this.getTpl('frameTpl');
1612 * Creates an array of class names from the configurations to add to this Component's `el` on render.
1614 * Private, but (possibly) used by ComponentQuery for selection by class name if Component is not rendered.
1616 * @return {String[]} An array of class names with which the Component's element will be rendered.
1619 initCls: function() {
1623 cls.push(me.baseCls);
1625 //<deprecated since=0.99>
1626 if (Ext.isDefined(me.cmpCls)) {
1627 if (Ext.isDefined(Ext.global.console)) {
1628 Ext.global.console.warn('Ext.Component: cmpCls has been deprecated. Please use componentCls.');
1630 me.componentCls = me.cmpCls;
1635 if (me.componentCls) {
1636 cls.push(me.componentCls);
1638 me.componentCls = me.baseCls;
1645 return cls.concat(me.additionalCls);
1649 * Sets the UI for the component. This will remove any existing UIs on the component. It will also loop through any
1650 * uiCls set on the component and rename them so they include the new UI
1651 * @param {String} ui The new UI for the component
1653 setUI: function(ui) {
1655 oldUICls = Ext.Array.clone(me.uiCls),
1661 //loop through all exisiting uiCls and update the ui in them
1662 for (i = 0; i < oldUICls.length; i++) {
1665 classes = classes.concat(me.removeClsWithUI(cls, true));
1669 if (classes.length) {
1670 me.removeCls(classes);
1673 //remove the UI from the element
1674 me.removeUIFromElement();
1679 //add the new UI to the elemend
1680 me.addUIToElement();
1682 //loop through all exisiting uiCls and update the ui in them
1684 for (i = 0; i < newUICls.length; i++) {
1686 classes = classes.concat(me.addClsWithUI(cls, true));
1689 if (classes.length) {
1695 * Adds a cls to the uiCls array, which will also call {@link #addUIClsToElement} and adds to all elements of this
1697 * @param {String/String[]} cls A string or an array of strings to add to the uiCls
1698 * @param {Object} skip (Boolean) skip True to skip adding it to the class and do it later (via the return)
1700 addClsWithUI: function(cls, skip) {
1705 if (!Ext.isArray(cls)) {
1709 for (i = 0; i < cls.length; i++) {
1710 if (cls[i] && !me.hasUICls(cls[i])) {
1711 me.uiCls = Ext.Array.clone(me.uiCls);
1712 me.uiCls.push(cls[i]);
1714 classes = classes.concat(me.addUIClsToElement(cls[i]));
1718 if (skip !== true) {
1726 * Removes a cls to the uiCls array, which will also call {@link #removeUIClsFromElement} and removes it from all
1727 * elements of this component.
1728 * @param {String/String[]} cls A string or an array of strings to remove to the uiCls
1730 removeClsWithUI: function(cls, skip) {
1735 if (!Ext.isArray(cls)) {
1739 for (i = 0; i < cls.length; i++) {
1740 if (cls[i] && me.hasUICls(cls[i])) {
1741 me.uiCls = Ext.Array.remove(me.uiCls, cls[i]);
1743 classes = classes.concat(me.removeUIClsFromElement(cls[i]));
1747 if (skip !== true) {
1748 me.removeCls(classes);
1755 * Checks if there is currently a specified uiCls
1756 * @param {String} cls The cls to check
1758 hasUICls: function(cls) {
1760 uiCls = me.uiCls || [];
1762 return Ext.Array.contains(uiCls, cls);
1766 * Method which adds a specified UI + uiCls to the components element. Can be overridden to remove the UI from more
1767 * than just the components element.
1768 * @param {String} ui The UI to remove from the element
1770 addUIClsToElement: function(cls, force) {
1773 frameElementCls = me.frameElementCls;
1775 result.push(Ext.baseCSSPrefix + cls);
1776 result.push(me.baseCls + '-' + cls);
1777 result.push(me.baseCls + '-' + me.ui + '-' + cls);
1779 if (!force && me.frame && !Ext.supports.CSS3BorderRadius) {
1780 // define each element of the frame
1781 var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
1784 // loop through each of them, and if they are defined add the ui
1785 for (i = 0; i < els.length; i++) {
1786 el = me['frame' + els[i].toUpperCase()];
1787 classes = [me.baseCls + '-' + me.ui + '-' + els[i], me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]];
1791 for (j = 0; j < classes.length; j++) {
1792 if (Ext.Array.indexOf(frameElementCls[els[i]], classes[j]) == -1) {
1793 frameElementCls[els[i]].push(classes[j]);
1800 me.frameElementCls = frameElementCls;
1806 * Method which removes a specified UI + uiCls from the components element. The cls which is added to the element
1807 * will be: `this.baseCls + '-' + ui`
1808 * @param {String} ui The UI to add to the element
1810 removeUIClsFromElement: function(cls, force) {
1813 frameElementCls = me.frameElementCls;
1815 result.push(Ext.baseCSSPrefix + cls);
1816 result.push(me.baseCls + '-' + cls);
1817 result.push(me.baseCls + '-' + me.ui + '-' + cls);
1819 if (!force && me.frame && !Ext.supports.CSS3BorderRadius) {
1820 // define each element of the frame
1821 var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
1823 cls = me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i];
1824 // loop through each of them, and if they are defined add the ui
1825 for (i = 0; i < els.length; i++) {
1826 el = me['frame' + els[i].toUpperCase()];
1830 Ext.Array.remove(frameElementCls[els[i]], cls);
1835 me.frameElementCls = frameElementCls;
1841 * Method which adds a specified UI to the components element.
1844 addUIToElement: function(force) {
1846 frameElementCls = me.frameElementCls;
1848 me.addCls(me.baseCls + '-' + me.ui);
1850 if (me.frame && !Ext.supports.CSS3BorderRadius) {
1851 // define each element of the frame
1852 var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
1855 // loop through each of them, and if they are defined add the ui
1856 for (i = 0; i < els.length; i++) {
1857 el = me['frame' + els[i].toUpperCase()];
1858 cls = me.baseCls + '-' + me.ui + '-' + els[i];
1862 if (!Ext.Array.contains(frameElementCls[els[i]], cls)) {
1863 frameElementCls[els[i]].push(cls);
1871 * Method which removes a specified UI from the components element.
1874 removeUIFromElement: function() {
1876 frameElementCls = me.frameElementCls;
1878 me.removeCls(me.baseCls + '-' + me.ui);
1880 if (me.frame && !Ext.supports.CSS3BorderRadius) {
1881 // define each element of the frame
1882 var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
1885 // loop through each of them, and if they are defined add the ui
1886 for (i = 0; i < els.length; i++) {
1887 el = me['frame' + els[i].toUpperCase()];
1888 cls = me.baseCls + '-' + me.ui + '-' + els[i];
1893 Ext.Array.remove(frameElementCls[els[i]], cls);
1899 getElConfig : function() {
1900 if (Ext.isString(this.autoEl)) {
1906 var result = this.autoEl || {tag: 'div'};
1907 result.id = this.id;
1912 * This function takes the position argument passed to onRender and returns a DOM element that you can use in the
1914 * @param {String/Number/Ext.Element/HTMLElement} position Index, element id or element you want to put this
1916 * @return {HTMLElement} DOM element that you can use in the insertBefore
1918 getInsertPosition: function(position) {
1919 // Convert the position to an element to insert before
1920 if (position !== undefined) {
1921 if (Ext.isNumber(position)) {
1922 position = this.container.dom.childNodes[position];
1925 position = Ext.getDom(position);
1933 * Adds ctCls to container.
1934 * @return {Ext.Element} The initialized container
1937 initContainer: function(container) {
1940 // If you render a component specifying the el, we get the container
1941 // of the el, and make sure we dont move the el around in the dom
1942 // during the render
1943 if (!container && me.el) {
1944 container = me.el.dom.parentNode;
1945 me.allowDomMove = false;
1948 me.container = Ext.get(container);
1951 me.container.addCls(me.ctCls);
1954 return me.container;
1958 * Initialized the renderData to be used when rendering the renderTpl.
1959 * @return {Object} Object with keys and values that are going to be applied to the renderTpl
1962 initRenderData: function() {
1965 return Ext.applyIf(me.renderData, {
1969 baseCls: me.baseCls,
1970 componentCls: me.componentCls,
1978 getTpl: function(name) {
1980 prototype = me.self.prototype,
1984 if (me.hasOwnProperty(name)) {
1986 if (tpl && !(tpl instanceof Ext.XTemplate)) {
1987 me[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl);
1993 if (!(prototype[name] instanceof Ext.XTemplate)) {
1994 ownerPrototype = prototype;
1997 if (ownerPrototype.hasOwnProperty(name)) {
1998 tpl = ownerPrototype[name];
1999 if (tpl && !(tpl instanceof Ext.XTemplate)) {
2000 ownerPrototype[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl);
2005 ownerPrototype = ownerPrototype.superclass;
2006 } while (ownerPrototype);
2009 return prototype[name];
2013 * Initializes the renderTpl.
2014 * @return {Ext.XTemplate} The renderTpl XTemplate instance.
2017 initRenderTpl: function() {
2018 return this.getTpl('renderTpl');
2022 * Converts style definitions to String.
2023 * @return {String} A CSS style string with style, padding, margin and border.
2026 initStyles: function() {
2029 Element = Ext.Element;
2031 if (Ext.isString(me.style)) {
2032 style = Element.parseStyles(me.style);
2034 style = Ext.apply({}, me.style);
2037 // Convert the padding, margin and border properties from a space seperated string
2038 // into a proper style string
2039 if (me.padding !== undefined) {
2040 style.padding = Element.unitizeBox((me.padding === true) ? 5 : me.padding);
2043 if (me.margin !== undefined) {
2044 style.margin = Element.unitizeBox((me.margin === true) ? 5 : me.margin);
2052 * Initializes this components contents. It checks for the properties html, contentEl and tpl/data.
2055 initContent: function() {
2057 target = me.getTargetEl(),
2062 target.update(Ext.DomHelper.markup(me.html));
2067 contentEl = Ext.get(me.contentEl);
2068 pre = Ext.baseCSSPrefix;
2069 contentEl.removeCls([pre + 'hidden', pre + 'hide-display', pre + 'hide-offsets', pre + 'hide-nosize']);
2070 target.appendChild(contentEl.dom);
2074 // Make sure this.tpl is an instantiated XTemplate
2075 if (!me.tpl.isTemplate) {
2076 me.tpl = Ext.create('Ext.XTemplate', me.tpl);
2080 me.tpl[me.tplWriteMode](target, me.data);
2087 initEvents : function() {
2089 afterRenderEvents = me.afterRenderEvents,
2092 fn = function(listeners){
2093 me.mon(el, listeners);
2095 if (afterRenderEvents) {
2096 for (property in afterRenderEvents) {
2097 if (afterRenderEvents.hasOwnProperty(property)) {
2100 Ext.each(afterRenderEvents[property], fn);
2108 * Adds each argument passed to this method to the {@link #childEls} array.
2110 addChildEls: function () {
2112 childEls = me.childEls || (me.childEls = []);
2114 childEls.push.apply(childEls, arguments);
2118 * Removes items in the childEls array based on the return value of a supplied test function. The function is called
2119 * with a entry in childEls and if the test function return true, that entry is removed. If false, that entry is
2121 * @param {Function} testFn The test function.
2123 removeChildEls: function (testFn) {
2126 keepers = (me.childEls = []),
2129 for (i = 0, n = old.length; i < n; ++i) {
2138 * Sets references to elements inside the component. This applies {@link #renderSelectors}
2139 * as well as {@link #childEls}.
2142 applyRenderSelectors: function() {
2144 childEls = me.childEls,
2145 selectors = me.renderSelectors,
2148 baseId, childName, childId, i, selector;
2151 baseId = me.id + '-';
2152 for (i = childEls.length; i--; ) {
2153 childName = childId = childEls[i];
2154 if (typeof(childName) != 'string') {
2155 childId = childName.id || (baseId + childName.itemId);
2156 childName = childName.name;
2158 childId = baseId + childId;
2161 // We don't use Ext.get because that is 3x (or more) slower on IE6-8. Since
2162 // we know the el's are children of our el we use getById instead:
2163 me[childName] = el.getById(childId);
2167 // We still support renderSelectors. There are a few places in the framework that
2168 // need them and they are a documented part of the API. In fact, we support mixing
2169 // childEls and renderSelectors (no reason not to).
2171 for (selector in selectors) {
2172 if (selectors.hasOwnProperty(selector) && selectors[selector]) {
2173 me[selector] = Ext.get(Ext.DomQuery.selectNode(selectors[selector], dom));
2180 * Tests whether this Component matches the selector string.
2181 * @param {String} selector The selector string to test against.
2182 * @return {Boolean} True if this Component matches the selector.
2184 is: function(selector) {
2185 return Ext.ComponentQuery.is(this, selector);
2189 * Walks up the `ownerCt` axis looking for an ancestor Container which matches the passed simple selector.
2193 * var owningTabPanel = grid.up('tabpanel');
2195 * @param {String} [selector] The simple selector to test.
2196 * @return {Ext.container.Container} The matching ancestor Container (or `undefined` if no match was found).
2198 up: function(selector) {
2199 var result = this.ownerCt;
2201 for (; result; result = result.ownerCt) {
2202 if (Ext.ComponentQuery.is(result, selector)) {
2211 * Returns the next sibling of this Component.
2213 * Optionally selects the next sibling which matches the passed {@link Ext.ComponentQuery ComponentQuery} selector.
2215 * May also be refered to as **`next()`**
2217 * Note that this is limited to siblings, and if no siblings of the item match, `null` is returned. Contrast with
2219 * @param {String} [selector] A {@link Ext.ComponentQuery ComponentQuery} selector to filter the following items.
2220 * @return {Ext.Component} The next sibling (or the next sibling which matches the selector).
2221 * Returns null if there is no matching sibling.
2223 nextSibling: function(selector) {
2224 var o = this.ownerCt, it, last, idx, c;
2227 idx = it.indexOf(this) + 1;
2230 for (last = it.getCount(); idx < last; idx++) {
2231 if ((c = it.getAt(idx)).is(selector)) {
2236 if (idx < it.getCount()) {
2237 return it.getAt(idx);
2246 * Returns the previous sibling of this Component.
2248 * Optionally selects the previous sibling which matches the passed {@link Ext.ComponentQuery ComponentQuery}
2251 * May also be refered to as **`prev()`**
2253 * Note that this is limited to siblings, and if no siblings of the item match, `null` is returned. Contrast with
2254 * {@link #previousNode}
2255 * @param {String} [selector] A {@link Ext.ComponentQuery ComponentQuery} selector to filter the preceding items.
2256 * @return {Ext.Component} The previous sibling (or the previous sibling which matches the selector).
2257 * Returns null if there is no matching sibling.
2259 previousSibling: function(selector) {
2260 var o = this.ownerCt, it, idx, c;
2263 idx = it.indexOf(this);
2266 for (--idx; idx >= 0; idx--) {
2267 if ((c = it.getAt(idx)).is(selector)) {
2273 return it.getAt(--idx);
2282 * Returns the previous node in the Component tree in tree traversal order.
2284 * Note that this is not limited to siblings, and if invoked upon a node with no matching siblings, will walk the
2285 * tree in reverse order to attempt to find a match. Contrast with {@link #previousSibling}.
2286 * @param {String} [selector] A {@link Ext.ComponentQuery ComponentQuery} selector to filter the preceding nodes.
2287 * @return {Ext.Component} The previous node (or the previous node which matches the selector).
2288 * Returns null if there is no matching node.
2290 previousNode: function(selector, includeSelf) {
2295 // If asked to include self, test me
2296 if (includeSelf && node.is(selector)) {
2300 result = this.prev(selector);
2306 for (it = node.ownerCt.items.items, i = Ext.Array.indexOf(it, node) - 1; i > -1; i--) {
2308 result = it[i].query(selector);
2309 result = result[result.length - 1];
2315 return node.ownerCt.previousNode(selector, true);
2320 * Returns the next node in the Component tree in tree traversal order.
2322 * Note that this is not limited to siblings, and if invoked upon a node with no matching siblings, will walk the
2323 * tree to attempt to find a match. Contrast with {@link #nextSibling}.
2324 * @param {String} [selector] A {@link Ext.ComponentQuery ComponentQuery} selector to filter the following nodes.
2325 * @return {Ext.Component} The next node (or the next node which matches the selector).
2326 * Returns null if there is no matching node.
2328 nextNode: function(selector, includeSelf) {
2333 // If asked to include self, test me
2334 if (includeSelf && node.is(selector)) {
2338 result = this.next(selector);
2344 for (it = node.ownerCt.items, i = it.indexOf(node) + 1, it = it.items, len = it.length; i < len; i++) {
2346 result = it[i].down(selector);
2352 return node.ownerCt.nextNode(selector);
2357 * Retrieves the id of this component. Will autogenerate an id if one has not already been set.
2360 getId : function() {
2361 return this.id || (this.id = 'ext-comp-' + (this.getAutoId()));
2364 getItemId : function() {
2365 return this.itemId || this.id;
2369 * Retrieves the top level element representing this component.
2370 * @return {Ext.core.Element}
2372 getEl : function() {
2377 * This is used to determine where to insert the 'html', 'contentEl' and 'items' in this component.
2380 getTargetEl: function() {
2381 return this.frameBody || this.el;
2385 * Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended
2386 * from the xtype (default) or whether it is directly of the xtype specified (shallow = true).
2388 * **If using your own subclasses, be aware that a Component must register its own xtype to participate in
2389 * determination of inherited xtypes.**
2391 * For a list of all available xtypes, see the {@link Ext.Component} header.
2395 * var t = new Ext.form.field.Text();
2396 * var isText = t.isXType('textfield'); // true
2397 * var isBoxSubclass = t.isXType('field'); // true, descended from Ext.form.field.Base
2398 * var isBoxInstance = t.isXType('field', true); // false, not a direct Ext.form.field.Base instance
2400 * @param {String} xtype The xtype to check for this Component
2401 * @param {Boolean} [shallow=false] True to check whether this Component is directly of the specified xtype, false to
2402 * check whether this Component is descended from the xtype.
2403 * @return {Boolean} True if this component descends from the specified xtype, false otherwise.
2405 isXType: function(xtype, shallow) {
2406 //assume a string by default
2407 if (Ext.isFunction(xtype)) {
2408 xtype = xtype.xtype;
2409 //handle being passed the class, e.g. Ext.Component
2410 } else if (Ext.isObject(xtype)) {
2411 xtype = xtype.statics().xtype;
2412 //handle being passed an instance
2415 return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1: this.self.xtype == xtype;
2419 * Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all available xtypes, see the
2420 * {@link Ext.Component} header.
2422 * **If using your own subclasses, be aware that a Component must register its own xtype to participate in
2423 * determination of inherited xtypes.**
2427 * var t = new Ext.form.field.Text();
2428 * alert(t.getXTypes()); // alerts 'component/field/textfield'
2430 * @return {String} The xtype hierarchy string
2432 getXTypes: function() {
2433 var self = this.self,
2434 xtypes, parentPrototype, parentXtypes;
2438 parentPrototype = this;
2440 while (parentPrototype) {
2441 parentXtypes = parentPrototype.xtypes;
2443 if (parentXtypes !== undefined) {
2444 xtypes.unshift.apply(xtypes, parentXtypes);
2447 parentPrototype = parentPrototype.superclass;
2450 self.xtypeChain = xtypes;
2451 self.xtypes = xtypes.join('/');
2458 * Update the content area of a component.
2459 * @param {String/Object} htmlOrData If this component has been configured with a template via the tpl config then
2460 * it will use this argument as data to populate the template. If this component was not configured with a template,
2461 * the components content area will be updated via Ext.Element update
2462 * @param {Boolean} [loadScripts=false] Only legitimate when using the html configuration.
2463 * @param {Function} [callback] Only legitimate when using the html configuration. Callback to execute when
2464 * scripts have finished loading
2466 update : function(htmlOrData, loadScripts, cb) {
2469 if (me.tpl && !Ext.isString(htmlOrData)) {
2470 me.data = htmlOrData;
2472 me.tpl[me.tplWriteMode](me.getTargetEl(), htmlOrData || {});
2475 me.html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
2477 me.getTargetEl().update(me.html, loadScripts, cb);
2482 me.doComponentLayout();
2487 * Convenience function to hide or show this component by boolean.
2488 * @param {Boolean} visible True to show, false to hide
2489 * @return {Ext.Component} this
2491 setVisible : function(visible) {
2492 return this[visible ? 'show': 'hide']();
2496 * Returns true if this component is visible.
2498 * @param {Boolean} [deep=false] Pass `true` to interrogate the visibility status of all parent Containers to
2499 * determine whether this Component is truly visible to the user.
2501 * Generally, to determine whether a Component is hidden, the no argument form is needed. For example when creating
2502 * dynamically laid out UIs in a hidden Container before showing them.
2504 * @return {Boolean} True if this component is visible, false otherwise.
2506 isVisible: function(deep) {
2509 visible = !me.hidden,
2510 ancestor = me.ownerCt;
2512 // Clear hiddenOwnerCt property
2513 me.hiddenAncestor = false;
2518 if (deep && visible && me.rendered && ancestor) {
2520 // If any ancestor is hidden, then this is hidden.
2521 // If an ancestor Panel (only Panels have a collapse method) is collapsed,
2522 // then its layoutTarget (body) is hidden, so this is hidden unless its within a
2523 // docked item; they are still visible when collapsed (Unless they themseves are hidden)
2524 if (ancestor.hidden || (ancestor.collapsed &&
2525 !(ancestor.getDockedItems && Ext.Array.contains(ancestor.getDockedItems(), child)))) {
2526 // Store hiddenOwnerCt property if needed
2527 me.hiddenAncestor = ancestor;
2532 ancestor = ancestor.ownerCt;
2539 * Enable the component
2540 * @param {Boolean} [silent=false] Passing true will supress the 'enable' event from being fired.
2542 enable: function(silent) {
2546 me.el.removeCls(me.disabledCls);
2547 me.el.dom.disabled = false;
2551 me.disabled = false;
2553 if (silent !== true) {
2554 me.fireEvent('enable', me);
2561 * Disable the component.
2562 * @param {Boolean} [silent=false] Passing true will supress the 'disable' event from being fired.
2564 disable: function(silent) {
2568 me.el.addCls(me.disabledCls);
2569 me.el.dom.disabled = true;
2575 if (silent !== true) {
2576 me.fireEvent('disable', me);
2583 onEnable: function() {
2584 if (this.maskOnDisable) {
2590 onDisable : function() {
2591 if (this.maskOnDisable) {
2597 * Method to determine whether this Component is currently disabled.
2598 * @return {Boolean} the disabled state of this Component.
2600 isDisabled : function() {
2601 return this.disabled;
2605 * Enable or disable the component.
2606 * @param {Boolean} disabled True to disable.
2608 setDisabled : function(disabled) {
2609 return this[disabled ? 'disable': 'enable']();
2613 * Method to determine whether this Component is currently set to hidden.
2614 * @return {Boolean} the hidden state of this Component.
2616 isHidden : function() {
2621 * Adds a CSS class to the top level element representing this component.
2622 * @param {String} cls The CSS class name to add
2623 * @return {Ext.Component} Returns the Component to allow method chaining.
2625 addCls : function(className) {
2630 if (!Ext.isArray(className)){
2631 className = className.replace(me.trimRe, '').split(me.spacesRe);
2634 me.el.addCls(className);
2637 me.additionalCls = Ext.Array.unique(me.additionalCls.concat(className));
2643 * Adds a CSS class to the top level element representing this component.
2644 * @param {String} cls The CSS class name to add
2645 * @return {Ext.Component} Returns the Component to allow method chaining.
2647 addClass : function() {
2648 return this.addCls.apply(this, arguments);
2652 * Removes a CSS class from the top level element representing this component.
2653 * @param {Object} className
2654 * @return {Ext.Component} Returns the Component to allow method chaining.
2656 removeCls : function(className) {
2662 if (!Ext.isArray(className)){
2663 className = className.replace(me.trimRe, '').split(me.spacesRe);
2666 me.el.removeCls(className);
2668 else if (me.additionalCls.length) {
2669 Ext.each(className, function(cls) {
2670 Ext.Array.remove(me.additionalCls, cls);
2677 removeClass : function() {
2678 if (Ext.isDefined(Ext.global.console)) {
2679 Ext.global.console.warn('Ext.Component: removeClass has been deprecated. Please use removeCls.');
2681 return this.removeCls.apply(this, arguments);
2685 addOverCls: function() {
2688 me.el.addCls(me.overCls);
2692 removeOverCls: function() {
2693 this.el.removeCls(this.overCls);
2696 addListener : function(element, listeners, scope, options) {
2701 if (Ext.isString(element) && (Ext.isObject(listeners) || options && options.element)) {
2702 if (options.element) {
2706 listeners[element] = fn;
2707 element = options.element;
2709 listeners.scope = scope;
2712 for (option in options) {
2713 if (options.hasOwnProperty(option)) {
2714 if (me.eventOptionsRe.test(option)) {
2715 listeners[option] = options[option];
2721 // At this point we have a variable called element,
2722 // and a listeners object that can be passed to on
2723 if (me[element] && me[element].on) {
2724 me.mon(me[element], listeners);
2726 me.afterRenderEvents = me.afterRenderEvents || {};
2727 if (!me.afterRenderEvents[element]) {
2728 me.afterRenderEvents[element] = [];
2730 me.afterRenderEvents[element].push(listeners);
2734 return me.mixins.observable.addListener.apply(me, arguments);
2738 removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){
2740 element = managedListener.options ? managedListener.options.element : null;
2743 element = me[element];
2744 if (element && element.un) {
2745 if (isClear || (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope))) {
2746 element.un(managedListener.ename, managedListener.fn, managedListener.scope);
2748 Ext.Array.remove(me.managedListeners, managedListener);
2753 return me.mixins.observable.removeManagedListenerItem.apply(me, arguments);
2758 * Provides the link for Observable's fireEvent method to bubble up the ownership hierarchy.
2759 * @return {Ext.container.Container} the Container which owns this Component.
2761 getBubbleTarget : function() {
2762 return this.ownerCt;
2766 * Method to determine whether this Component is floating.
2767 * @return {Boolean} the floating state of this component.
2769 isFloating : function() {
2770 return this.floating;
2774 * Method to determine whether this Component is draggable.
2775 * @return {Boolean} the draggable state of this component.
2777 isDraggable : function() {
2778 return !!this.draggable;
2782 * Method to determine whether this Component is droppable.
2783 * @return {Boolean} the droppable state of this component.
2785 isDroppable : function() {
2786 return !!this.droppable;
2791 * Method to manage awareness of when components are added to their
2792 * respective Container, firing an added event.
2793 * References are established at add time rather than at render time.
2794 * @param {Ext.container.Container} container Container which holds the component
2795 * @param {Number} pos Position at which the component was added
2797 onAdded : function(container, pos) {
2798 this.ownerCt = container;
2799 this.fireEvent('added', this, container, pos);
2804 * Method to manage awareness of when components are removed from their
2805 * respective Container, firing an removed event. References are properly
2806 * cleaned up after removing a component from its owning container.
2808 onRemoved : function() {
2811 me.fireEvent('removed', me, me.ownerCt);
2816 beforeDestroy : Ext.emptyFn,
2819 onResize : Ext.emptyFn,
2822 * Sets the width and height of this Component. This method fires the {@link #resize} event. This method can accept
2823 * either width and height as separate arguments, or you can pass a size object like `{width:10, height:20}`.
2825 * @param {Number/String/Object} width The new width to set. This may be one of:
2827 * - A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).
2828 * - A String used to set the CSS width style.
2829 * - A size object in the format `{width: widthValue, height: heightValue}`.
2830 * - `undefined` to leave the width unchanged.
2832 * @param {Number/String} height The new height to set (not required if a size object is passed as the first arg).
2833 * This may be one of:
2835 * - A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).
2836 * - A String used to set the CSS height style. Animation may **not** be used.
2837 * - `undefined` to leave the height unchanged.
2839 * @return {Ext.Component} this
2841 setSize : function(width, height) {
2845 // support for standard size objects
2846 if (Ext.isObject(width)) {
2847 height = width.height;
2848 width = width.width;
2851 // Constrain within configured maxima
2852 if (Ext.isNumber(width)) {
2853 width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
2855 if (Ext.isNumber(height)) {
2856 height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
2859 if (!me.rendered || !me.isVisible()) {
2860 // If an ownerCt is hidden, add my reference onto the layoutOnShow stack. Set the needsLayout flag.
2861 if (me.hiddenAncestor) {
2862 layoutCollection = me.hiddenAncestor.layoutOnShow;
2863 layoutCollection.remove(me);
2864 layoutCollection.add(me);
2872 me.width = (width !== undefined) ? width : me.width;
2873 me.height = (height !== undefined) ? height : me.height;
2877 me.doComponentLayout(width, height, true);
2882 isFixedWidth: function() {
2884 layoutManagedWidth = me.layoutManagedWidth;
2886 if (Ext.isDefined(me.width) || layoutManagedWidth == 1) {
2889 if (layoutManagedWidth == 2) {
2892 return (me.ownerCt && me.ownerCt.isFixedWidth());
2895 isFixedHeight: function() {
2897 layoutManagedHeight = me.layoutManagedHeight;
2899 if (Ext.isDefined(me.height) || layoutManagedHeight == 1) {
2902 if (layoutManagedHeight == 2) {
2905 return (me.ownerCt && me.ownerCt.isFixedHeight());
2908 setCalculatedSize : function(width, height, callingContainer) {
2912 // support for standard size objects
2913 if (Ext.isObject(width)) {
2914 callingContainer = width.ownerCt;
2915 height = width.height;
2916 width = width.width;
2919 // Constrain within configured maxima
2920 if (Ext.isNumber(width)) {
2921 width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
2923 if (Ext.isNumber(height)) {
2924 height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
2927 if (!me.rendered || !me.isVisible()) {
2928 // If an ownerCt is hidden, add my reference onto the layoutOnShow stack. Set the needsLayout flag.
2929 if (me.hiddenAncestor) {
2930 layoutCollection = me.hiddenAncestor.layoutOnShow;
2931 layoutCollection.remove(me);
2932 layoutCollection.add(me);
2938 ownerCt: callingContainer
2942 me.doComponentLayout(width, height, false, callingContainer);
2948 * This method needs to be called whenever you change something on this component that requires the Component's
2949 * layout to be recalculated.
2950 * @param {Object} width
2951 * @param {Object} height
2952 * @param {Object} isSetSize
2953 * @param {Object} callingContainer
2954 * @return {Ext.container.Container} this
2956 doComponentLayout : function(width, height, isSetSize, callingContainer) {
2958 componentLayout = me.getComponentLayout(),
2959 lastComponentSize = componentLayout.lastComponentSize || {
2964 // collapsed state is not relevant here, so no testing done.
2965 // Only Panels have a collapse method, and that just sets the width/height such that only
2966 // a single docked Header parallel to the collapseTo side are visible, and the Panel body is hidden.
2967 if (me.rendered && componentLayout) {
2968 // If no width passed, then only insert a value if the Component is NOT ALLOWED to autowidth itself.
2969 if (!Ext.isDefined(width)) {
2970 if (me.isFixedWidth()) {
2971 width = Ext.isDefined(me.width) ? me.width : lastComponentSize.width;
2974 // If no height passed, then only insert a value if the Component is NOT ALLOWED to autoheight itself.
2975 if (!Ext.isDefined(height)) {
2976 if (me.isFixedHeight()) {
2977 height = Ext.isDefined(me.height) ? me.height : lastComponentSize.height;
2986 componentLayout.layout(width, height, isSetSize, callingContainer);
2993 * Forces this component to redo its componentLayout.
2995 forceComponentLayout: function () {
2996 this.doComponentLayout();
3000 setComponentLayout : function(layout) {
3001 var currentLayout = this.componentLayout;
3002 if (currentLayout && currentLayout.isLayout && currentLayout != layout) {
3003 currentLayout.setOwner(null);
3005 this.componentLayout = layout;
3006 layout.setOwner(this);
3009 getComponentLayout : function() {
3012 if (!me.componentLayout || !me.componentLayout.isLayout) {
3013 me.setComponentLayout(Ext.layout.Layout.create(me.componentLayout, 'autocomponent'));
3015 return me.componentLayout;
3019 * Occurs after componentLayout is run.
3020 * @param {Number} adjWidth The box-adjusted width that was set
3021 * @param {Number} adjHeight The box-adjusted height that was set
3022 * @param {Boolean} isSetSize Whether or not the height/width are stored on the component permanently
3023 * @param {Ext.Component} callingContainer Container requesting the layout. Only used when isSetSize is false.
3025 afterComponentLayout: function(width, height, isSetSize, callingContainer) {
3027 layout = me.componentLayout,
3028 oldSize = me.preLayoutSize;
3030 ++me.componentLayoutCounter;
3031 if (!oldSize || ((width !== oldSize.width) || (height !== oldSize.height))) {
3032 me.fireEvent('resize', me, width, height);
3037 * Occurs before componentLayout is run. Returning false from this method will prevent the componentLayout from
3039 * @param {Number} adjWidth The box-adjusted width that was set
3040 * @param {Number} adjHeight The box-adjusted height that was set
3041 * @param {Boolean} isSetSize Whether or not the height/width are stored on the component permanently
3042 * @param {Ext.Component} callingContainer Container requesting sent the layout. Only used when isSetSize is false.
3044 beforeComponentLayout: function(width, height, isSetSize, callingContainer) {
3045 this.preLayoutSize = this.componentLayout.lastComponentSize;
3050 * Sets the left and top of the component. To set the page XY position instead, use
3051 * {@link Ext.Component#setPagePosition setPagePosition}. This method fires the {@link #move} event.
3052 * @param {Number} left The new left
3053 * @param {Number} top The new top
3054 * @return {Ext.Component} this
3056 setPosition : function(x, y) {
3059 if (Ext.isObject(x)) {
3068 if (x !== undefined || y !== undefined) {
3070 me.onPosition(x, y);
3071 me.fireEvent('move', me, x, y);
3078 * Called after the component is moved, this method is empty by default but can be implemented by any
3079 * subclass that needs to perform custom logic after a move occurs.
3080 * @param {Number} x The new x position
3081 * @param {Number} y The new y position
3083 onPosition: Ext.emptyFn,
3086 * Sets the width of the component. This method fires the {@link #resize} event.
3088 * @param {Number} width The new width to setThis may be one of:
3090 * - A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).
3091 * - A String used to set the CSS width style.
3093 * @return {Ext.Component} this
3095 setWidth : function(width) {
3096 return this.setSize(width);
3100 * Sets the height of the component. This method fires the {@link #resize} event.
3102 * @param {Number} height The new height to set. This may be one of:
3104 * - A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).
3105 * - A String used to set the CSS height style.
3106 * - _undefined_ to leave the height unchanged.
3108 * @return {Ext.Component} this
3110 setHeight : function(height) {
3111 return this.setSize(undefined, height);
3115 * Gets the current size of the component's underlying element.
3116 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
3118 getSize : function() {
3119 return this.el.getSize();
3123 * Gets the current width of the component's underlying element.
3126 getWidth : function() {
3127 return this.el.getWidth();
3131 * Gets the current height of the component's underlying element.
3134 getHeight : function() {
3135 return this.el.getHeight();
3139 * Gets the {@link Ext.ComponentLoader} for this Component.
3140 * @return {Ext.ComponentLoader} The loader instance, null if it doesn't exist.
3142 getLoader: function(){
3144 autoLoad = me.autoLoad ? (Ext.isObject(me.autoLoad) ? me.autoLoad : {url: me.autoLoad}) : null,
3145 loader = me.loader || autoLoad;
3148 if (!loader.isLoader) {
3149 me.loader = Ext.create('Ext.ComponentLoader', Ext.apply({
3154 loader.setTarget(me);
3163 * This method allows you to show or hide a LoadMask on top of this component.
3165 * @param {Boolean/Object/String} load True to show the default LoadMask, a config object that will be passed to the
3166 * LoadMask constructor, or a message String to show. False to hide the current LoadMask.
3167 * @param {Boolean} [targetEl=false] True to mask the targetEl of this Component instead of the `this.el`. For example,
3168 * setting this to true on a Panel will cause only the body to be masked.
3169 * @return {Ext.LoadMask} The LoadMask instance that has just been shown.
3171 setLoading : function(load, targetEl) {
3176 if (load !== false && !me.collapsed) {
3177 if (Ext.isObject(load)) {
3180 else if (Ext.isString(load)) {
3181 config = {msg: load};
3186 me.loadMask = me.loadMask || Ext.create('Ext.LoadMask', targetEl ? me.getTargetEl() : me.el, config);
3188 } else if (me.loadMask) {
3189 Ext.destroy(me.loadMask);
3198 * Sets the dock position of this component in its parent panel. Note that this only has effect if this item is part
3199 * of the dockedItems collection of a parent that has a DockLayout (note that any Panel has a DockLayout by default)
3200 * @param {Object} dock The dock position.
3201 * @param {Boolean} [layoutParent=false] True to re-layout parent.
3202 * @return {Ext.Component} this
3204 setDocked : function(dock, layoutParent) {
3208 if (layoutParent && me.ownerCt && me.rendered) {
3209 me.ownerCt.doComponentLayout();
3214 onDestroy : function() {
3217 if (me.monitorResize && Ext.EventManager.resizeEvent) {
3218 Ext.EventManager.resizeEvent.removeListener(me.setSize, me);
3220 // Destroying the floatingItems ZIndexManager will also destroy descendant floating Components
3229 * Remove any references to elements added via renderSelectors/childEls
3232 cleanElementRefs: function(){
3235 childEls = me.childEls,
3236 selectors = me.renderSelectors,
3243 for (len = childEls.length; i < len; ++i) {
3245 if (typeof(name) != 'string') {
3253 for (selector in selectors) {
3254 if (selectors.hasOwnProperty(selector)) {
3255 delete me[selector];
3262 delete me.frameBody;
3266 * Destroys the Component.
3268 destroy : function() {
3271 if (!me.isDestroyed) {
3272 if (me.fireEvent('beforedestroy', me) !== false) {
3273 me.destroying = true;
3277 delete me.floatParent;
3278 // A zIndexManager is stamped into a *floating* Component when it is added to a Container.
3279 // If it has no zIndexManager at render time, it is assigned to the global Ext.WindowManager instance.
3280 if (me.zIndexManager) {
3281 me.zIndexManager.unregister(me);
3283 } else if (me.ownerCt && me.ownerCt.remove) {
3284 me.ownerCt.remove(me, false);
3289 // Attempt to destroy all plugins
3290 Ext.destroy(me.plugins);
3296 me.fireEvent('destroy', me);
3297 Ext.ComponentManager.unregister(me);
3299 me.mixins.state.destroy.call(me);
3301 me.clearListeners();
3302 // make sure we clean up the element references after removing all events
3303 me.cleanElementRefs();
3304 me.destroying = false;
3305 me.isDestroyed = true;
3311 * Retrieves a plugin by its pluginId which has been bound to this component.
3312 * @param {Object} pluginId
3313 * @return {Ext.AbstractPlugin} plugin instance.
3315 getPlugin: function(pluginId) {
3317 plugins = this.plugins,
3318 ln = plugins.length;
3319 for (; i < ln; i++) {
3320 if (plugins[i].pluginId === pluginId) {
3327 * Determines whether this component is the descendant of a particular container.
3328 * @param {Ext.Container} container
3329 * @return {Boolean} True if it is.
3331 isDescendantOf: function(container) {
3332 return !!this.findParentBy(function(p){
3333 return p === container;
3339 prev: 'previousSibling',