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 * @class Ext.AbstractComponent
17 * <p>An abstract base class which provides shared methods for Components across the Sencha product line.</p>
18 * <p>Please refer to sub class's documentation</p>
21 Ext.define('Ext.AbstractComponent', {
23 /* Begin Definitions */
26 observable: 'Ext.util.Observable',
27 animate: 'Ext.util.Animate',
28 state: 'Ext.state.Stateful'
33 'Ext.ComponentManager',
39 'Ext.ComponentLoader',
42 'Ext.layout.component.Auto'
45 // Please remember to add dependencies whenever you use it
46 // I had to fix these many times already
59 getAutoId: function() {
60 return ++Ext.AbstractComponent.AUTO_ID;
66 * <p>The <b><u>unique id of this component instance</u></b> (defaults to an {@link #getId auto-assigned id}).</p>
67 * <p>It should not be necessary to use this configuration except for singleton objects in your application.
68 * Components created with an id may be accessed globally using {@link Ext#getCmp Ext.getCmp}.</p>
69 * <p>Instead of using assigned ids, use the {@link #itemId} config, and {@link Ext.ComponentQuery ComponentQuery} which
70 * provides selector-based searching for Sencha Components analogous to DOM querying. The {@link Ext.container.Container Container}
71 * class contains {@link Ext.container.Container#down shortcut methods} to query its descendant Components by selector.</p>
72 * <p>Note that this id will also be used as the element id for the containing HTML element
73 * that is rendered to the page for this component. This allows you to write id-based CSS
74 * rules to style the specific instance of this component uniquely, and also to select
75 * sub-elements using this component's id as the parent.</p>
76 * <p><b>Note</b>: to avoid complications imposed by a unique <tt>id</tt> also see <code>{@link #itemId}</code>.</p>
77 * <p><b>Note</b>: to access the container of a Component see <code>{@link #ownerCt}</code>.</p>
81 * @cfg {String} itemId
82 * <p>An <tt>itemId</tt> can be used as an alternative way to get a reference to a component
83 * when no object reference is available. Instead of using an <code>{@link #id}</code> with
84 * {@link Ext}.{@link Ext#getCmp getCmp}, use <code>itemId</code> with
85 * {@link Ext.container.Container}.{@link Ext.container.Container#getComponent getComponent} which will retrieve
86 * <code>itemId</code>'s or <tt>{@link #id}</tt>'s. Since <code>itemId</code>'s are an index to the
87 * container's internal MixedCollection, the <code>itemId</code> is scoped locally to the container --
88 * avoiding potential conflicts with {@link Ext.ComponentManager} which requires a <b>unique</b>
89 * <code>{@link #id}</code>.</p>
91 var c = new Ext.panel.Panel({ //
92 {@link Ext.Component#height height}: 300,
93 {@link #renderTo}: document.body,
94 {@link Ext.container.Container#layout layout}: 'auto',
95 {@link Ext.container.Container#items items}: [
98 {@link Ext.panel.Panel#title title}: 'Panel 1',
99 {@link Ext.Component#height height}: 150
103 {@link Ext.panel.Panel#title title}: 'Panel 2',
104 {@link Ext.Component#height height}: 150
108 p1 = c.{@link Ext.container.Container#getComponent getComponent}('p1'); // not the same as {@link Ext#getCmp Ext.getCmp()}
109 p2 = p1.{@link #ownerCt}.{@link Ext.container.Container#getComponent getComponent}('p2'); // reference via a sibling
111 * <p>Also see <tt>{@link #id}</tt>, <code>{@link Ext.container.Container#query}</code>,
112 * <code>{@link Ext.container.Container#down}</code> and <code>{@link Ext.container.Container#child}</code>.</p>
113 * <p><b>Note</b>: to access the container of an item see <tt>{@link #ownerCt}</tt>.</p>
117 * This Component's owner {@link Ext.container.Container Container} (defaults to undefined, and is set automatically when
118 * this Component is added to a Container). Read-only.
119 * <p><b>Note</b>: to access items within the Container see <tt>{@link #itemId}</tt>.</p>
120 * @type Ext.Container
126 * Flag set by the container layout to which this Component is added.
127 * If the layout manages this Component's width, it sets the value to 1.
128 * If it does NOT manage the width, it sets it to 2.
129 * If the layout MAY affect the width, but only if the owning Container has a fixed width, this is set to 0.
131 * @property layoutManagedWidth
136 * Flag set by the container layout to which this Component is added.
137 * If the layout manages this Component's height, it sets the value to 1.
138 * If it does NOT manage the height, it sets it to 2.
139 * If the layout MAY affect the height, but only if the owning Container has a fixed height, this is set to 0.
141 * @property layoutManagedHeight
145 * @cfg {Mixed} autoEl
146 * <p>A tag name or {@link Ext.core.DomHelper DomHelper} spec used to create the {@link #getEl Element} which will
147 * encapsulate this Component.</p>
148 * <p>You do not normally need to specify this. For the base classes {@link Ext.Component} and {@link Ext.container.Container},
149 * this defaults to <b><tt>'div'</tt></b>. The more complex Sencha classes use a more complex
150 * DOM structure specified by their own {@link #renderTpl}s.</p>
151 * <p>This is intended to allow the developer to create application-specific utility Components encapsulated by
152 * different DOM elements. Example usage:</p><pre><code>
157 src: 'http://www.example.com/example.jpg'
163 html: 'autoEl is cool!'
168 cls: 'ux-unordered-list',
172 html: 'First list item'
179 * @cfg {Mixed} renderTpl
180 * <p>An {@link Ext.XTemplate XTemplate} used to create the internal structure inside this Component's
181 * encapsulating {@link #getEl Element}.</p>
182 * <p>You do not normally need to specify this. For the base classes {@link Ext.Component}
183 * and {@link Ext.container.Container}, this defaults to <b><code>null</code></b> which means that they will be initially rendered
184 * with no internal structure; they render their {@link #getEl Element} empty. The more specialized ExtJS and Touch classes
185 * which use a more complex DOM structure, provide their own template definitions.</p>
186 * <p>This is intended to allow the developer to create application-specific utility Components with customized
187 * internal structure.</p>
188 * <p>Upon rendering, any created child elements may be automatically imported into object properties using the
189 * {@link #renderSelectors} option.</p>
194 * @cfg {Object} renderSelectors
196 An object containing properties specifying {@link Ext.DomQuery DomQuery} selectors which identify child elements
197 created by the render process.
199 After the Component's internal structure is rendered according to the {@link #renderTpl}, this object is iterated through,
200 and the found Elements are added as properties to the Component using the `renderSelector` property name.
202 For example, a Component which rendered an image, and description into its element might use the following properties
203 coded into its prototype:
205 renderTpl: '<img src="{imageUrl}" class="x-image-component-img"><div class="x-image-component-desc">{description}>/div<',
208 image: 'img.x-image-component-img',
209 descEl: 'div.x-image-component-desc'
212 After rendering, the Component would have a property <code>image</code> referencing its child `img` Element,
213 and a property `descEl` referencing the `div` Element which contains the description.
219 * @cfg {Mixed} renderTo
220 * <p>Specify the id of the element, a DOM element or an existing Element that this component
221 * will be rendered into.</p><div><ul>
222 * <li><b>Notes</b> : <ul>
223 * <div class="sub-desc">Do <u>not</u> use this option if the Component is to be a child item of
224 * a {@link Ext.container.Container Container}. It is the responsibility of the
225 * {@link Ext.container.Container Container}'s {@link Ext.container.Container#layout layout manager}
226 * to render and manage its child items.</div>
227 * <div class="sub-desc">When using this config, a call to render() is not required.</div>
230 * <p>See <code>{@link #render}</code> also.</p>
234 * @cfg {Boolean} frame
235 * <p>Specify as <code>true</code> to have the Component inject framing elements within the Component at render time to
236 * provide a graphical rounded frame around the Component content.</p>
237 * <p>This is only necessary when running on outdated, or non standard-compliant browsers such as Microsoft's Internet Explorer
238 * prior to version 9 which do not support rounded corners natively.</p>
239 * <p>The extra space taken up by this framing is available from the read only property {@link #frameSize}.</p>
243 * <p>Read-only property indicating the width of any framing elements which were added within the encapsulating element
244 * to provide graphical, rounded borders. See the {@link #frame} config.</p>
245 * <p> This is an object containing the frame width in pixels for all four sides of the Component containing
246 * the following properties:</p><div class="mdetail-params"><ul>
247 * <li><code>top</code> The width of the top framing element in pixels.</li>
248 * <li><code>right</code> The width of the right framing element in pixels.</li>
249 * <li><code>bottom</code> The width of the bottom framing element in pixels.</li>
250 * <li><code>left</code> The width of the left framing element in pixels.</li>
252 * @property frameSize
257 * @cfg {String/Object} componentLayout
258 * <p>The sizing and positioning of a Component's internal Elements is the responsibility of
259 * the Component's layout manager which sizes a Component's internal structure in response to the Component being sized.</p>
260 * <p>Generally, developers will not use this configuration as all provided Components which need their internal
261 * elements sizing (Such as {@link Ext.form.field.Base input fields}) come with their own componentLayout managers.</p>
262 * <p>The {@link Ext.layout.container.Auto default layout manager} will be used on instances of the base Ext.Component class
263 * which simply sizes the Component's encapsulating element to the height and width specified in the {@link #setSize} method.</p>
268 * An <bold>{@link Ext.Template}</bold>, <bold>{@link Ext.XTemplate}</bold>
269 * or an array of strings to form an Ext.XTemplate.
270 * Used in conjunction with the <code>{@link #data}</code> and
271 * <code>{@link #tplWriteMode}</code> configurations.
276 * The initial set of data to apply to the <code>{@link #tpl}</code> to
277 * update the content area of the Component.
281 * @cfg {String} tplWriteMode The Ext.(X)Template method to use when
282 * updating the content area of the Component. Defaults to <code>'overwrite'</code>
283 * (see <code>{@link Ext.XTemplate#overwrite}</code>).
285 tplWriteMode: 'overwrite',
288 * @cfg {String} baseCls
289 * The base CSS class to apply to this components's element. This will also be prepended to
290 * elements within this component like Panel's body will get a class x-panel-body. This means
291 * that if you create a subclass of Panel, and you want it to get all the Panels styling for the
292 * element and the body, you leave the baseCls x-panel and use componentCls to add specific styling for this
295 baseCls: Ext.baseCSSPrefix + 'component',
298 * @cfg {String} componentCls
299 * CSS Class to be added to a components root level element to give distinction to it
305 * An optional extra CSS class that will be added to this component's Element (defaults to ''). This can be
306 * useful for adding customized styles to the component or any of its children using standard CSS rules.
310 * @cfg {String} overCls
311 * An optional extra CSS class that will be added to this component's Element when the mouse moves
312 * over the Element, and removed when the mouse moves out. (defaults to ''). This can be
313 * useful for adding customized 'active' or 'hover' styles to the component or any of its children using standard CSS rules.
317 * @cfg {String} disabledCls
318 * CSS class to add when the Component is disabled. Defaults to 'x-item-disabled'.
320 disabledCls: Ext.baseCSSPrefix + 'item-disabled',
323 * @cfg {String/Array} ui
324 * A set style for a component. Can be a string or an Array of multiple strings (UIs)
330 * An array of of classNames which are currently applied to this component
336 * @cfg {String} style
337 * A custom style specification to be applied to this component's Element. Should be a valid argument to
338 * {@link Ext.core.Element#applyStyles}.
340 new Ext.panel.Panel({
342 renderTo: Ext.getBody(),
343 width: 400, height: 300,
352 new Ext.button.Button({
365 * @cfg {Number} width
366 * The width of this component in pixels.
370 * @cfg {Number} height
371 * The height of this component in pixels.
375 * @cfg {Number/String} border
376 * Specifies the border for this component. The border can be a single numeric value to apply to all sides or
377 * it can be a CSS style specification for each style, for example: '10 5 3 10'.
381 * @cfg {Number/String} padding
382 * Specifies the padding for this component. The padding can be a single numeric value to apply to all sides or
383 * it can be a CSS style specification for each style, for example: '10 5 3 10'.
387 * @cfg {Number/String} margin
388 * Specifies the margin for this component. The margin can be a single numeric value to apply to all sides or
389 * it can be a CSS style specification for each style, for example: '10 5 3 10'.
393 * @cfg {Boolean} hidden
399 * @cfg {Boolean} disabled
405 * @cfg {Boolean} draggable
406 * Allows the component to be dragged.
410 * Read-only property indicating whether or not the component can be dragged
411 * @property draggable
417 * @cfg {Boolean} floating
418 * Create the Component as a floating and use absolute positioning.
424 * @cfg {String} hideMode
425 * A String which specifies how this Component's encapsulating DOM element will be hidden.
426 * Values may be<div class="mdetail-params"><ul>
427 * <li><code>'display'</code> : The Component will be hidden using the <code>display: none</code> style.</li>
428 * <li><code>'visibility'</code> : The Component will be hidden using the <code>visibility: hidden</code> style.</li>
429 * <li><code>'offsets'</code> : The Component will be hidden by absolutely positioning it out of the visible area of the document. This
430 * is useful when a hidden Component must maintain measurable dimensions. Hiding using <code>display</code> results
431 * in a Component having zero dimensions.</li></ul></div>
432 * Defaults to <code>'display'</code>.
437 * @cfg {String} contentEl
438 * <p>Optional. Specify an existing HTML element, or the <code>id</code> of an existing HTML element to use as the content
439 * for this component.</p>
441 * <li><b>Description</b> :
442 * <div class="sub-desc">This config option is used to take an existing HTML element and place it in the layout element
443 * of a new component (it simply moves the specified DOM element <i>after the Component is rendered</i> to use as the content.</div></li>
445 * <div class="sub-desc">The specified HTML element is appended to the layout element of the component <i>after any configured
446 * {@link #html HTML} has been inserted</i>, and so the document will not contain this element at the time the {@link #render} event is fired.</div>
447 * <div class="sub-desc">The specified HTML element used will not participate in any <code><b>{@link Ext.container.Container#layout layout}</b></code>
448 * scheme that the Component may use. It is just HTML. Layouts operate on child <code><b>{@link Ext.container.Container#items items}</b></code>.</div>
449 * <div class="sub-desc">Add either the <code>x-hidden</code> or the <code>x-hide-display</code> CSS class to
450 * prevent a brief flicker of the content before it is rendered to the panel.</div></li>
455 * @cfg {String/Object} html
456 * An HTML fragment, or a {@link Ext.core.DomHelper DomHelper} specification to use as the layout element
457 * content (defaults to ''). The HTML content is added after the component is rendered,
458 * so the document will not contain this HTML at the time the {@link #render} event is fired.
459 * This content is inserted into the body <i>before</i> any configured {@link #contentEl} is appended.
463 * @cfg {Boolean} styleHtmlContent
464 * True to automatically style the html inside the content target of this component (body for panels).
467 styleHtmlContent: false,
470 * @cfg {String} styleHtmlCls
471 * The class that is added to the content target when you set styleHtmlContent to true.
472 * Defaults to 'x-html'
474 styleHtmlCls: Ext.baseCSSPrefix + 'html',
477 * @cfg {Number} minHeight
478 * <p>The minimum value in pixels which this Component will set its height to.</p>
479 * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
482 * @cfg {Number} minWidth
483 * <p>The minimum value in pixels which this Component will set its width to.</p>
484 * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
487 * @cfg {Number} maxHeight
488 * <p>The maximum value in pixels which this Component will set its height to.</p>
489 * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
492 * @cfg {Number} maxWidth
493 * <p>The maximum value in pixels which this Component will set its width to.</p>
494 * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
498 * @cfg {Ext.ComponentLoader/Object} loader
499 * A configuration object or an instance of a {@link Ext.ComponentLoader} to load remote
500 * content for this Component.
507 * @cfg {Boolean} autoShow True to automatically show the component upon creation.
508 * This config option may only be used for {@link #floating} components or components
509 * that use {@link #autoRender}. Defaults to <tt>false</tt>.
514 * @cfg {Mixed} autoRender
515 * <p>This config is intended mainly for {@link #floating} Components which may or may not be shown. Instead
516 * of using {@link #renderTo} in the configuration, and rendering upon construction, this allows a Component
517 * to render itself upon first <i>{@link #show}</i>.</p>
518 * <p>Specify as <code>true</code> to have this Component render to the document body upon first show.</p>
519 * <p>Specify as an element, or the ID of an element to have this Component render to a specific element upon first show.</p>
520 * <p><b>This defaults to <code>true</code> for the {@link Ext.window.Window Window} class.</b></p>
527 * @cfg {Object/Array} plugins
528 * An object or array of objects that will provide custom functionality for this component. The only
529 * requirement for a valid plugin is that it contain an init method that accepts a reference of type Ext.Component.
530 * When a component is created, if any plugins are available, the component will call the init method on each
531 * plugin, passing a reference to itself. Each plugin can then call methods or respond to events on the
532 * component as needed to provide its functionality.
536 * Read-only property indicating whether or not the component has been rendered.
544 trimRe: /^\s+|\s+$/g,
549 * This is an internal flag that you use when creating custom components.
550 * By default this is set to true which means that every component gets a mask when its disabled.
551 * Components like FieldContainer, FieldSet, Field, Button, Tab override this property to false
552 * since they want to implement custom disable logic.
553 * @property maskOnDisable
559 * Creates new Component.
560 * @param {Object} config (optional) Config object.
562 constructor : function(config) {
566 config = config || {};
567 me.initialConfig = config;
568 Ext.apply(me, config);
572 * @event beforeactivate
573 * Fires before a Component has been visually activated.
574 * Returning false from an event listener can prevent the activate
576 * @param {Ext.Component} this
581 * Fires after a Component has been visually activated.
582 * @param {Ext.Component} this
586 * @event beforedeactivate
587 * Fires before a Component has been visually deactivated.
588 * Returning false from an event listener can prevent the deactivate
590 * @param {Ext.Component} this
595 * Fires after a Component has been visually deactivated.
596 * @param {Ext.Component} this
601 * Fires after a Component had been added to a Container.
602 * @param {Ext.Component} this
603 * @param {Ext.container.Container} container Parent Container
604 * @param {Number} pos position of Component
609 * Fires after the component is disabled.
610 * @param {Ext.Component} this
615 * Fires after the component is enabled.
616 * @param {Ext.Component} this
621 * Fires before the component is shown when calling the {@link #show} method.
622 * Return false from an event handler to stop the show.
623 * @param {Ext.Component} this
628 * Fires after the component is shown when calling the {@link #show} method.
629 * @param {Ext.Component} this
634 * Fires before the component is hidden when calling the {@link #hide} method.
635 * Return false from an event handler to stop the hide.
636 * @param {Ext.Component} this
641 * Fires after the component is hidden.
642 * Fires after the component is hidden when calling the {@link #hide} method.
643 * @param {Ext.Component} this
648 * Fires when a component is removed from an Ext.container.Container
649 * @param {Ext.Component} this
650 * @param {Ext.container.Container} ownerCt Container which holds the component
654 * @event beforerender
655 * Fires before the component is {@link #rendered}. Return false from an
656 * event handler to stop the {@link #render}.
657 * @param {Ext.Component} this
662 * Fires after the component markup is {@link #rendered}.
663 * @param {Ext.Component} this
668 * <p>Fires after the component rendering is finished.</p>
669 * <p>The afterrender event is fired after this Component has been {@link #rendered}, been postprocesed
670 * by any afterRender method defined for the Component.</p>
671 * @param {Ext.Component} this
675 * @event beforedestroy
676 * Fires before the component is {@link #destroy}ed. Return false from an event handler to stop the {@link #destroy}.
677 * @param {Ext.Component} this
682 * Fires after the component is {@link #destroy}ed.
683 * @param {Ext.Component} this
688 * Fires after the component is resized.
689 * @param {Ext.Component} this
690 * @param {Number} adjWidth The box-adjusted width that was set
691 * @param {Number} adjHeight The box-adjusted height that was set
696 * Fires after the component is moved.
697 * @param {Ext.Component} this
698 * @param {Number} x The new x position
699 * @param {Number} y The new y position
707 me.additionalCls = [];
708 me.renderData = me.renderData || {};
709 me.renderSelectors = me.renderSelectors || {};
712 me.plugins = [].concat(me.plugins);
713 for (i = 0, len = me.plugins.length; i < len; i++) {
714 me.plugins[i] = me.constructPlugin(me.plugins[i]);
720 // ititComponent gets a chance to change the id property before registering
721 Ext.ComponentManager.register(me);
723 // Dont pass the config so that it is not applied to 'this' again
724 me.mixins.observable.constructor.call(me);
725 me.mixins.state.constructor.call(me, config);
727 // Save state on resize.
728 this.addStateEvents('resize');
730 // Move this into Observable?
732 me.plugins = [].concat(me.plugins);
733 for (i = 0, len = me.plugins.length; i < len; i++) {
734 me.plugins[i] = me.initPlugin(me.plugins[i]);
738 me.loader = me.getLoader();
741 me.render(me.renderTo);
742 // EXTJSIV-1935 - should be a way to do afterShow or something, but that
743 // won't work. Likewise, rendering hidden and then showing (w/autoShow) has
744 // implications to afterRender so we cannot do that.
752 if (Ext.isDefined(me.disabledClass)) {
753 if (Ext.isDefined(Ext.global.console)) {
754 Ext.global.console.warn('Ext.Component: disabledClass has been deprecated. Please use disabledCls.');
756 me.disabledCls = me.disabledClass;
757 delete me.disabledClass;
762 initComponent: Ext.emptyFn,
765 * </p>The supplied default state gathering method for the AbstractComponent class.</p>
766 * This method returns dimension setings such as <code>flex</code>, <code>anchor</code>, <code>width</code>
767 * and <code>height</code> along with <code>collapsed</code> state.</p>
768 * <p>Subclasses which implement more complex state should call the superclass's implementation, and apply their state
769 * to the result if this basic state is to be saved.</p>
770 * <p>Note that Component state will only be saved if the Component has a {@link #stateId} and there as a StateProvider
771 * configured for the document.</p>
773 getState: function() {
775 layout = me.ownerCt ? (me.shadowOwnerCt || me.ownerCt).getLayout() : null,
777 collapsed: me.collapsed
781 cm = me.collapseMemento,
784 // If a Panel-local collapse has taken place, use remembered values as the dimensions.
785 // TODO: remove this coupling with Panel's privates! All collapse/expand logic should be refactored into one place.
786 if (me.collapsed && cm) {
787 if (Ext.isDefined(cm.data.width)) {
790 if (Ext.isDefined(cm.data.height)) {
795 // If we have flex, only store the perpendicular dimension.
796 if (layout && me.flex) {
797 state.flex = me.flex;
798 state[layout.perpendicularPrefix] = me['get' + layout.perpendicularPrefixCap]();
800 // If we have anchor, only store dimensions which are *not* being anchored
801 else if (layout && me.anchor) {
802 state.anchor = me.anchor;
803 anchors = me.anchor.split(' ').concat(null);
811 state.height = height;
821 state.height = height;
825 // Don't save dimensions if they are unchanged from the original configuration.
826 if (state.width == me.initialConfig.width) {
829 if (state.height == me.initialConfig.height) {
833 // If a Box layout was managing the perpendicular dimension, don't save that dimension
834 if (layout && layout.align && (layout.align.indexOf('stretch') !== -1)) {
835 delete state[layout.perpendicularPrefix];
842 animate: function(animObj) {
846 animObj = animObj || {};
847 to = animObj.to || {};
849 if (Ext.fx.Manager.hasFxBlock(me.id)) {
852 // Special processing for animating Component dimensions.
853 if (!animObj.dynamic && (to.height || to.width)) {
854 var curWidth = me.getWidth(),
856 curHeight = me.getHeight(),
860 if (to.height && to.height > curHeight) {
864 if (to.width && to.width > curWidth) {
869 // If any dimensions are being increased, we must resize the internal structure
870 // of the Component, but then clip it by sizing its encapsulating element back to original dimensions.
871 // The animation will then progressively reveal the larger content.
873 var clearWidth = !Ext.isNumber(me.width),
874 clearHeight = !Ext.isNumber(me.height);
876 me.componentLayout.childrenChanged = true;
877 me.setSize(w, h, me.ownerCt);
878 me.el.setSize(curWidth, curHeight);
887 return me.mixins.animate.animate.apply(me, arguments);
891 * <p>This method finds the topmost active layout who's processing will eventually determine the size and position of this
893 * <p>This method is useful when dynamically adding Components into Containers, and some processing must take place after the
894 * final sizing and positioning of the Component has been performed.</p>
897 findLayoutController: function() {
898 return this.findParentBy(function(c) {
899 // Return true if we are at the root of the Container tree
900 // or this Container's layout is busy but the next one up is not.
901 return !c.ownerCt || (c.layout.layoutBusy && !c.ownerCt.layout.layoutBusy);
905 onShow : function() {
907 var needsLayout = this.needsLayout;
908 if (Ext.isObject(needsLayout)) {
909 this.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize, needsLayout.ownerCt);
913 constructPlugin: function(plugin) {
914 if (plugin.ptype && typeof plugin.init != 'function') {
916 plugin = Ext.PluginManager.create(plugin);
918 else if (typeof plugin == 'string') {
919 plugin = Ext.PluginManager.create({
928 initPlugin : function(plugin) {
935 * Handles autoRender.
936 * Floating Components may have an ownerCt. If they are asking to be constrained, constrain them within that
937 * ownerCt, and have their z-index managed locally. Floating Components are always rendered to document.body
939 doAutoRender: function() {
942 me.render(document.body);
944 me.render(Ext.isBoolean(me.autoRender) ? Ext.getBody() : me.autoRender);
949 render : function(container, position) {
952 if (!me.rendered && me.fireEvent('beforerender', me) !== false) {
953 // If this.el is defined, we want to make sure we are dealing with
956 me.el = Ext.get(me.el);
959 // Perform render-time processing for floating Components
964 container = me.initContainer(container);
966 me.onRender(container, position);
968 // Tell the encapsulating element to hide itself in the way the Component is configured to hide
969 // This means DISPLAY, VISIBILITY or OFFSETS.
970 me.el.setVisibilityMode(Ext.core.Element[me.hideMode.toUpperCase()]);
973 me.el.hover(me.addOverCls, me.removeOverCls, me);
976 me.fireEvent('render', me);
980 me.afterRender(container);
981 me.fireEvent('afterrender', me);
986 // Hiding during the render process should not perform any ancillary
987 // actions that the full hide process does; It is not hiding, it begins in a hidden state.'
988 // So just make the element hidden according to the configured hideMode
993 // pass silent so the event doesn't fire the first time.
1001 onRender : function(container, position) {
1004 styles = me.initStyles(),
1005 renderTpl, renderData, i;
1007 position = me.getInsertPosition(position);
1011 el = Ext.core.DomHelper.insertBefore(position, me.getElConfig(), true);
1014 el = Ext.core.DomHelper.append(container, me.getElConfig(), true);
1017 else if (me.allowDomMove !== false) {
1019 container.dom.insertBefore(el.dom, position);
1021 container.dom.appendChild(el.dom);
1025 if (Ext.scopeResetCSS && !me.ownerCt) {
1026 // If this component's el is the body element, we add the reset class to the html tag
1027 if (el.dom == Ext.getBody().dom) {
1028 el.parent().addCls(Ext.baseCSSPrefix + 'reset');
1031 // Else we wrap this element in an element that adds the reset class.
1032 me.resetEl = el.wrap({
1033 cls: Ext.baseCSSPrefix + 'reset'
1040 el.addCls(me.initCls());
1041 el.setStyle(styles);
1043 // Here we check if the component has a height set through style or css.
1044 // If it does then we set the this.height to that value and it won't be
1045 // considered an auto height component
1046 // if (this.height === undefined) {
1047 // var height = el.getHeight();
1048 // // This hopefully means that the panel has an explicit height set in style or css
1049 // if (height - el.getPadding('tb') - el.getBorderWidth('tb') > 0) {
1050 // this.height = height;
1058 renderTpl = me.initRenderTpl();
1060 renderData = me.initRenderData();
1061 renderTpl.append(me.getTargetEl(), renderData);
1064 me.applyRenderSelectors();
1070 afterRender : function() {
1075 me.getComponentLayout();
1077 // Set the size if a size is configured, or if this is the outermost Container
1078 if (!me.ownerCt || (me.height || me.width)) {
1079 me.setSize(me.width, me.height);
1082 // For floaters, calculate x and y if they aren't defined by aligning
1083 // the sized element to the center of either the container or the ownerCt
1084 if (me.floating && (me.x === undefined || me.y === undefined)) {
1085 if (me.floatParent) {
1086 xy = me.el.getAlignToXY(me.floatParent.getTargetEl(), 'c-c');
1087 pos = me.floatParent.getTargetEl().translatePoints(xy[0], xy[1]);
1089 xy = me.el.getAlignToXY(me.container, 'c-c');
1090 pos = me.container.translatePoints(xy[0], xy[1]);
1092 me.x = me.x === undefined ? pos.left: me.x;
1093 me.y = me.y === undefined ? pos.top: me.y;
1096 if (Ext.isDefined(me.x) || Ext.isDefined(me.y)) {
1097 me.setPosition(me.x, me.y);
1100 if (me.styleHtmlContent) {
1101 me.getTargetEl().addCls(me.styleHtmlCls);
1105 frameCls: Ext.baseCSSPrefix + 'frame',
1121 '<tpl if="left"><div 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>',
1122 '<tpl if="right"><div 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>',
1123 '<div 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>',
1124 '<tpl if="right"></div></tpl>',
1125 '<tpl if="left"></div></tpl>',
1127 '<tpl if="left"><div 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>',
1128 '<tpl if="right"><div 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>',
1129 '<div class="{frameCls}-mc {baseCls}-mc {baseCls}-{ui}-mc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mc</tpl></tpl>" role="presentation"></div>',
1130 '<tpl if="right"></div></tpl>',
1131 '<tpl if="left"></div></tpl>',
1132 '<tpl if="bottom">',
1133 '<tpl if="left"><div 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>',
1134 '<tpl if="right"><div 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>',
1135 '<div 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>',
1136 '<tpl if="right"></div></tpl>',
1137 '<tpl if="left"></div></tpl>',
1145 '<tpl if="left"><td 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>',
1146 '<td 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>',
1147 '<tpl if="right"><td 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>',
1151 '<tpl if="left"><td 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>',
1152 '<td 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>',
1153 '<tpl if="right"><td 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>',
1155 '<tpl if="bottom">',
1157 '<tpl if="left"><td 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>',
1158 '<td 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>',
1159 '<tpl if="right"><td 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>',
1168 initFrame : function() {
1169 if (Ext.supports.CSS3BorderRadius) {
1174 frameInfo = me.getFrameInfo(),
1175 frameWidth = frameInfo.width,
1176 frameTpl = me.getFrameTpl(frameInfo.table);
1179 // Here we render the frameTpl to this component. This inserts the 9point div or the table framing.
1180 frameTpl.insertFirst(me.el, Ext.apply({}, {
1183 frameCls: me.frameCls,
1184 baseCls: me.baseCls,
1185 frameWidth: frameWidth,
1186 top: !!frameInfo.top,
1187 left: !!frameInfo.left,
1188 right: !!frameInfo.right,
1189 bottom: !!frameInfo.bottom
1190 }, me.getFramePositions(frameInfo)));
1192 // The frameBody is returned in getTargetEl, so that layouts render items to the correct target.=
1193 me.frameBody = me.el.down('.' + me.frameCls + '-mc');
1195 // Add the render selectors for each of the frame elements
1196 Ext.apply(me.renderSelectors, {
1197 frameTL: '.' + me.baseCls + '-tl',
1198 frameTC: '.' + me.baseCls + '-tc',
1199 frameTR: '.' + me.baseCls + '-tr',
1200 frameML: '.' + me.baseCls + '-ml',
1201 frameMC: '.' + me.baseCls + '-mc',
1202 frameMR: '.' + me.baseCls + '-mr',
1203 frameBL: '.' + me.baseCls + '-bl',
1204 frameBC: '.' + me.baseCls + '-bc',
1205 frameBR: '.' + me.baseCls + '-br'
1210 updateFrame: function() {
1211 if (Ext.supports.CSS3BorderRadius) {
1216 wasTable = this.frameSize && this.frameSize.table,
1217 oldFrameTL = this.frameTL,
1218 oldFrameBL = this.frameBL,
1219 oldFrameML = this.frameML,
1220 oldFrameMC = this.frameMC,
1227 // Reapply render selectors
1237 this.applyRenderSelectors();
1239 // Store the class names set on the new mc
1240 newMCClassName = this.frameMC.dom.className;
1242 // Replace the new mc with the old mc
1243 oldFrameMC.insertAfter(this.frameMC);
1244 this.frameMC.remove();
1246 // Restore the reference to the old frame mc as the framebody
1247 this.frameBody = this.frameMC = oldFrameMC;
1249 // Apply the new mc classes to the old mc element
1250 oldFrameMC.dom.className = newMCClassName;
1252 // Remove the old framing
1254 me.el.query('> table')[1].remove();
1258 oldFrameTL.remove();
1261 oldFrameBL.remove();
1263 oldFrameML.remove();
1267 // We were framed but not anymore. Move all content from the old frame to the body
1271 else if (me.frame) {
1272 this.applyRenderSelectors();
1276 getFrameInfo: function() {
1277 if (Ext.supports.CSS3BorderRadius) {
1282 left = me.el.getStyle('background-position-x'),
1283 top = me.el.getStyle('background-position-y'),
1284 info, frameInfo = false, max;
1286 // Some browsers dont support background-position-x and y, so for those
1287 // browsers let's split background-position into two parts.
1288 if (!left && !top) {
1289 info = me.el.getStyle('background-position').split(' ');
1294 // We actually pass a string in the form of '[type][tl][tr]px [type][br][bl]px' as
1295 // the background position of this.el from the css to indicate to IE that this component needs
1296 // framing. We parse it here and change the markup accordingly.
1297 if (parseInt(left, 10) >= 1000000 && parseInt(top, 10) >= 1000000) {
1301 // Table markup starts with 110, div markup with 100.
1302 table: left.substr(0, 3) == '110',
1304 // Determine if we are dealing with a horizontal or vertical component
1305 vertical: top.substr(0, 3) == '110',
1307 // Get and parse the different border radius sizes
1308 top: max(left.substr(3, 2), left.substr(5, 2)),
1309 right: max(left.substr(5, 2), top.substr(3, 2)),
1310 bottom: max(top.substr(3, 2), top.substr(5, 2)),
1311 left: max(top.substr(5, 2), left.substr(3, 2))
1314 frameInfo.width = max(frameInfo.top, frameInfo.right, frameInfo.bottom, frameInfo.left);
1316 // Just to be sure we set the background image of the el to none.
1317 me.el.setStyle('background-image', 'none');
1320 // This happens when you set frame: true explicitly without using the x-frame mixin in sass.
1321 // This way IE can't figure out what sizes to use and thus framing can't work.
1322 if (me.frame === true && !frameInfo) {
1324 Ext.Error.raise("You have set frame: true explicity on this component while it doesn't have any " +
1325 "framing defined in the CSS template. In this case IE can't figure out what sizes " +
1326 "to use and thus framing on this component will be disabled.");
1330 me.frame = me.frame || !!frameInfo;
1331 me.frameSize = frameInfo || false;
1336 getFramePositions: function(frameInfo) {
1338 frameWidth = frameInfo.width,
1340 positions, tc, bc, ml, mr;
1342 if (frameInfo.vertical) {
1343 tc = '0 -' + (frameWidth * 0) + 'px';
1344 bc = '0 -' + (frameWidth * 1) + 'px';
1346 if (dock && dock == "right") {
1347 tc = 'right -' + (frameWidth * 0) + 'px';
1348 bc = 'right -' + (frameWidth * 1) + 'px';
1352 tl: '0 -' + (frameWidth * 0) + 'px',
1353 tr: '0 -' + (frameWidth * 1) + 'px',
1354 bl: '0 -' + (frameWidth * 2) + 'px',
1355 br: '0 -' + (frameWidth * 3) + 'px',
1357 ml: '-' + (frameWidth * 1) + 'px 0',
1364 ml = '-' + (frameWidth * 0) + 'px 0';
1367 if (dock && dock == "bottom") {
1369 mr = 'right bottom';
1373 tl: '0 -' + (frameWidth * 2) + 'px',
1374 tr: 'right -' + (frameWidth * 3) + 'px',
1375 bl: '0 -' + (frameWidth * 4) + 'px',
1376 br: 'right -' + (frameWidth * 5) + 'px',
1381 tc: '0 -' + (frameWidth * 0) + 'px',
1382 bc: '0 -' + (frameWidth * 1) + 'px'
1392 getFrameTpl : function(table) {
1393 return table ? this.getTpl('frameTableTpl') : this.getTpl('frameTpl');
1397 * <p>Creates an array of class names from the configurations to add to this Component's <code>el</code> on render.</p>
1398 * <p>Private, but (possibly) used by ComponentQuery for selection by class name if Component is not rendered.</p>
1399 * @return {Array} An array of class names with which the Component's element will be rendered.
1402 initCls: function() {
1406 cls.push(me.baseCls);
1408 //<deprecated since=0.99>
1409 if (Ext.isDefined(me.cmpCls)) {
1410 if (Ext.isDefined(Ext.global.console)) {
1411 Ext.global.console.warn('Ext.Component: cmpCls has been deprecated. Please use componentCls.');
1413 me.componentCls = me.cmpCls;
1418 if (me.componentCls) {
1419 cls.push(me.componentCls);
1421 me.componentCls = me.baseCls;
1428 return cls.concat(me.additionalCls);
1432 * Sets the UI for the component. This will remove any existing UIs on the component. It will also
1433 * loop through any uiCls set on the component and rename them so they include the new UI
1434 * @param {String} ui The new UI for the component
1436 setUI: function(ui) {
1438 oldUICls = Ext.Array.clone(me.uiCls),
1444 //loop through all exisiting uiCls and update the ui in them
1445 for (i = 0; i < oldUICls.length; i++) {
1448 classes = classes.concat(me.removeClsWithUI(cls, true));
1452 if (classes.length) {
1453 me.removeCls(classes);
1456 //remove the UI from the element
1457 me.removeUIFromElement();
1462 //add the new UI to the elemend
1463 me.addUIToElement();
1465 //loop through all exisiting uiCls and update the ui in them
1467 for (i = 0; i < newUICls.length; i++) {
1469 classes = classes.concat(me.addClsWithUI(cls, true));
1472 if (classes.length) {
1478 * Adds a cls to the uiCls array, which will also call {@link #addUIClsToElement} and adds
1479 * to all elements of this component.
1480 * @param {String/Array} cls A string or an array of strings to add to the uiCls
1481 * @param (Boolean) skip True to skip adding it to the class and do it later (via the return)
1483 addClsWithUI: function(cls, skip) {
1488 if (!Ext.isArray(cls)) {
1492 for (i = 0; i < cls.length; i++) {
1493 if (cls[i] && !me.hasUICls(cls[i])) {
1494 me.uiCls = Ext.Array.clone(me.uiCls);
1495 me.uiCls.push(cls[i]);
1497 classes = classes.concat(me.addUIClsToElement(cls[i]));
1501 if (skip !== true) {
1509 * Removes a cls to the uiCls array, which will also call {@link #removeUIClsFromElement} and removes
1510 * it from all elements of this component.
1511 * @param {String/Array} cls A string or an array of strings to remove to the uiCls
1513 removeClsWithUI: function(cls, skip) {
1518 if (!Ext.isArray(cls)) {
1522 for (i = 0; i < cls.length; i++) {
1523 if (cls[i] && me.hasUICls(cls[i])) {
1524 me.uiCls = Ext.Array.remove(me.uiCls, cls[i]);
1526 classes = classes.concat(me.removeUIClsFromElement(cls[i]));
1530 if (skip !== true) {
1531 me.removeCls(classes);
1538 * Checks if there is currently a specified uiCls
1539 * @param {String} cls The cls to check
1541 hasUICls: function(cls) {
1543 uiCls = me.uiCls || [];
1545 return Ext.Array.contains(uiCls, cls);
1549 * Method which adds a specified UI + uiCls to the components element.
1550 * Can be overridden to remove the UI from more than just the components element.
1551 * @param {String} ui The UI to remove from the element
1553 addUIClsToElement: function(cls, force) {
1556 frameElementCls = me.frameElementCls;
1558 result.push(Ext.baseCSSPrefix + cls);
1559 result.push(me.baseCls + '-' + cls);
1560 result.push(me.baseCls + '-' + me.ui + '-' + cls);
1562 if (!force && me.frame && !Ext.supports.CSS3BorderRadius) {
1563 // define each element of the frame
1564 var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
1567 // loop through each of them, and if they are defined add the ui
1568 for (i = 0; i < els.length; i++) {
1569 el = me['frame' + els[i].toUpperCase()];
1570 classes = [me.baseCls + '-' + me.ui + '-' + els[i], me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]];
1574 for (j = 0; j < classes.length; j++) {
1575 if (Ext.Array.indexOf(frameElementCls[els[i]], classes[j]) == -1) {
1576 frameElementCls[els[i]].push(classes[j]);
1583 me.frameElementCls = frameElementCls;
1589 * Method which removes a specified UI + uiCls from the components element.
1590 * The cls which is added to the element will be: `this.baseCls + '-' + ui`
1591 * @param {String} ui The UI to add to the element
1593 removeUIClsFromElement: function(cls, force) {
1596 frameElementCls = me.frameElementCls;
1598 result.push(Ext.baseCSSPrefix + cls);
1599 result.push(me.baseCls + '-' + cls);
1600 result.push(me.baseCls + '-' + me.ui + '-' + cls);
1602 if (!force && me.frame && !Ext.supports.CSS3BorderRadius) {
1603 // define each element of the frame
1604 var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
1606 cls = me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i];
1607 // loop through each of them, and if they are defined add the ui
1608 for (i = 0; i < els.length; i++) {
1609 el = me['frame' + els[i].toUpperCase()];
1613 Ext.Array.remove(frameElementCls[els[i]], cls);
1618 me.frameElementCls = frameElementCls;
1624 * Method which adds a specified UI to the components element.
1627 addUIToElement: function(force) {
1629 frameElementCls = me.frameElementCls;
1631 me.addCls(me.baseCls + '-' + me.ui);
1633 if (me.frame && !Ext.supports.CSS3BorderRadius) {
1634 // define each element of the frame
1635 var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
1638 // loop through each of them, and if they are defined add the ui
1639 for (i = 0; i < els.length; i++) {
1640 el = me['frame' + els[i].toUpperCase()];
1641 cls = me.baseCls + '-' + me.ui + '-' + els[i];
1645 if (!Ext.Array.contains(frameElementCls[els[i]], cls)) {
1646 frameElementCls[els[i]].push(cls);
1654 * Method which removes a specified UI from the components element.
1657 removeUIFromElement: function() {
1659 frameElementCls = me.frameElementCls;
1661 me.removeCls(me.baseCls + '-' + me.ui);
1663 if (me.frame && !Ext.supports.CSS3BorderRadius) {
1664 // define each element of the frame
1665 var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
1668 // loop through each of them, and if they are defined add the ui
1669 for (i = 0; i < els.length; i++) {
1670 el = me['frame' + els[i].toUpperCase()];
1671 cls = me.baseCls + '-' + me.ui + '-' + els[i];
1676 Ext.Array.remove(frameElementCls[els[i]], cls);
1682 getElConfig : function() {
1683 var result = this.autoEl || {tag: 'div'};
1684 result.id = this.id;
1689 * This function takes the position argument passed to onRender and returns a
1690 * DOM element that you can use in the insertBefore.
1691 * @param {String/Number/Element/HTMLElement} position Index, element id or element you want
1692 * to put this component before.
1693 * @return {HTMLElement} DOM element that you can use in the insertBefore
1695 getInsertPosition: function(position) {
1696 // Convert the position to an element to insert before
1697 if (position !== undefined) {
1698 if (Ext.isNumber(position)) {
1699 position = this.container.dom.childNodes[position];
1702 position = Ext.getDom(position);
1710 * Adds ctCls to container.
1711 * @return {Ext.core.Element} The initialized container
1714 initContainer: function(container) {
1717 // If you render a component specifying the el, we get the container
1718 // of the el, and make sure we dont move the el around in the dom
1719 // during the render
1720 if (!container && me.el) {
1721 container = me.el.dom.parentNode;
1722 me.allowDomMove = false;
1725 me.container = Ext.get(container);
1728 me.container.addCls(me.ctCls);
1731 return me.container;
1735 * Initialized the renderData to be used when rendering the renderTpl.
1736 * @return {Object} Object with keys and values that are going to be applied to the renderTpl
1739 initRenderData: function() {
1742 return Ext.applyIf(me.renderData, {
1745 baseCls: me.baseCls,
1746 componentCls: me.componentCls,
1754 getTpl: function(name) {
1756 prototype = me.self.prototype,
1760 if (me.hasOwnProperty(name)) {
1762 if (tpl && !(tpl instanceof Ext.XTemplate)) {
1763 me[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl);
1769 if (!(prototype[name] instanceof Ext.XTemplate)) {
1770 ownerPrototype = prototype;
1773 if (ownerPrototype.hasOwnProperty(name)) {
1774 tpl = ownerPrototype[name];
1775 if (tpl && !(tpl instanceof Ext.XTemplate)) {
1776 ownerPrototype[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl);
1781 ownerPrototype = ownerPrototype.superclass;
1782 } while (ownerPrototype);
1785 return prototype[name];
1789 * Initializes the renderTpl.
1790 * @return {Ext.XTemplate} The renderTpl XTemplate instance.
1793 initRenderTpl: function() {
1794 return this.getTpl('renderTpl');
1798 * Function description
1799 * @return {String} A CSS style string with style, padding, margin and border.
1802 initStyles: function() {
1805 Element = Ext.core.Element;
1807 if (Ext.isString(me.style)) {
1808 style = Element.parseStyles(me.style);
1810 style = Ext.apply({}, me.style);
1813 // Convert the padding, margin and border properties from a space seperated string
1814 // into a proper style string
1815 if (me.padding !== undefined) {
1816 style.padding = Element.unitizeBox((me.padding === true) ? 5 : me.padding);
1819 if (me.margin !== undefined) {
1820 style.margin = Element.unitizeBox((me.margin === true) ? 5 : me.margin);
1828 * Initializes this components contents. It checks for the properties
1829 * html, contentEl and tpl/data.
1832 initContent: function() {
1834 target = me.getTargetEl(),
1839 target.update(Ext.core.DomHelper.markup(me.html));
1844 contentEl = Ext.get(me.contentEl);
1845 pre = Ext.baseCSSPrefix;
1846 contentEl.removeCls([pre + 'hidden', pre + 'hide-display', pre + 'hide-offsets', pre + 'hide-nosize']);
1847 target.appendChild(contentEl.dom);
1851 // Make sure this.tpl is an instantiated XTemplate
1852 if (!me.tpl.isTemplate) {
1853 me.tpl = Ext.create('Ext.XTemplate', me.tpl);
1857 me.tpl[me.tplWriteMode](target, me.data);
1864 initEvents : function() {
1866 afterRenderEvents = me.afterRenderEvents,
1869 fn = function(listeners){
1870 me.mon(el, listeners);
1872 if (afterRenderEvents) {
1873 for (property in afterRenderEvents) {
1874 if (afterRenderEvents.hasOwnProperty(property)) {
1877 Ext.each(afterRenderEvents[property], fn);
1885 * Sets references to elements inside the component. E.g body -> x-panel-body
1888 applyRenderSelectors: function() {
1889 var selectors = this.renderSelectors || {},
1893 for (selector in selectors) {
1894 if (selectors.hasOwnProperty(selector) && selectors[selector]) {
1895 this[selector] = Ext.get(Ext.DomQuery.selectNode(selectors[selector], el));
1901 * Tests whether this Component matches the selector string.
1902 * @param {String} selector The selector string to test against.
1903 * @return {Boolean} True if this Component matches the selector.
1905 is: function(selector) {
1906 return Ext.ComponentQuery.is(this, selector);
1910 * <p>Walks up the <code>ownerCt</code> axis looking for an ancestor Container which matches
1911 * the passed simple selector.</p>
1912 * <p>Example:<pre><code>
1913 var owningTabPanel = grid.up('tabpanel');
1915 * @param {String} selector Optional. The simple selector to test.
1916 * @return {Container} The matching ancestor Container (or <code>undefined</code> if no match was found).
1918 up: function(selector) {
1919 var result = this.ownerCt;
1921 for (; result; result = result.ownerCt) {
1922 if (Ext.ComponentQuery.is(result, selector)) {
1931 * <p>Returns the next sibling of this Component.</p>
1932 * <p>Optionally selects the next sibling which matches the passed {@link Ext.ComponentQuery ComponentQuery} selector.</p>
1933 * <p>May also be refered to as <code><b>next()</b></code></p>
1934 * <p>Note that this is limited to siblings, and if no siblings of the item match, <code>null</code> is returned. Contrast with {@link #nextNode}</p>
1935 * @param {String} selector Optional A {@link Ext.ComponentQuery ComponentQuery} selector to filter the following items.
1936 * @returns The next sibling (or the next sibling which matches the selector). Returns null if there is no matching sibling.
1938 nextSibling: function(selector) {
1939 var o = this.ownerCt, it, last, idx, c;
1942 idx = it.indexOf(this) + 1;
1945 for (last = it.getCount(); idx < last; idx++) {
1946 if ((c = it.getAt(idx)).is(selector)) {
1951 if (idx < it.getCount()) {
1952 return it.getAt(idx);
1961 * <p>Returns the previous sibling of this Component.</p>
1962 * <p>Optionally selects the previous sibling which matches the passed {@link Ext.ComponentQuery ComponentQuery} selector.</p>
1963 * <p>May also be refered to as <code><b>prev()</b></code></p>
1964 * <p>Note that this is limited to siblings, and if no siblings of the item match, <code>null</code> is returned. Contrast with {@link #previousNode}</p>
1965 * @param {String} selector Optional. A {@link Ext.ComponentQuery ComponentQuery} selector to filter the preceding items.
1966 * @returns The previous sibling (or the previous sibling which matches the selector). Returns null if there is no matching sibling.
1968 previousSibling: function(selector) {
1969 var o = this.ownerCt, it, idx, c;
1972 idx = it.indexOf(this);
1975 for (--idx; idx >= 0; idx--) {
1976 if ((c = it.getAt(idx)).is(selector)) {
1982 return it.getAt(--idx);
1991 * <p>Returns the previous node in the Component tree in tree traversal order.</p>
1992 * <p>Note that this is not limited to siblings, and if invoked upon a node with no matching siblings, will
1993 * walk the tree in reverse order to attempt to find a match. Contrast with {@link #previousSibling}.</p>
1994 * @param {String} selector Optional. A {@link Ext.ComponentQuery ComponentQuery} selector to filter the preceding nodes.
1995 * @returns The previous node (or the previous node which matches the selector). Returns null if there is no matching node.
1997 previousNode: function(selector, includeSelf) {
2002 // If asked to include self, test me
2003 if (includeSelf && node.is(selector)) {
2007 result = this.prev(selector);
2013 for (it = node.ownerCt.items.items, i = Ext.Array.indexOf(it, node) - 1; i > -1; i--) {
2015 result = it[i].query(selector);
2016 result = result[result.length - 1];
2022 return node.ownerCt.previousNode(selector, true);
2027 * <p>Returns the next node in the Component tree in tree traversal order.</p>
2028 * <p>Note that this is not limited to siblings, and if invoked upon a node with no matching siblings, will
2029 * walk the tree to attempt to find a match. Contrast with {@link #nextSibling}.</p>
2030 * @param {String} selector Optional A {@link Ext.ComponentQuery ComponentQuery} selector to filter the following nodes.
2031 * @returns The next node (or the next node which matches the selector). Returns null if there is no matching node.
2033 nextNode: function(selector, includeSelf) {
2038 // If asked to include self, test me
2039 if (includeSelf && node.is(selector)) {
2043 result = this.next(selector);
2049 for (it = node.ownerCt.items, i = it.indexOf(node) + 1, it = it.items, len = it.length; i < len; i++) {
2051 result = it[i].down(selector);
2057 return node.ownerCt.nextNode(selector);
2062 * Retrieves the id of this component.
2063 * Will autogenerate an id if one has not already been set.
2065 getId : function() {
2066 return this.id || (this.id = 'ext-comp-' + (this.getAutoId()));
2069 getItemId : function() {
2070 return this.itemId || this.id;
2074 * Retrieves the top level element representing this component.
2076 getEl : function() {
2081 * This is used to determine where to insert the 'html', 'contentEl' and 'items' in this component.
2084 getTargetEl: function() {
2085 return this.frameBody || this.el;
2089 * <p>Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended
2090 * from the xtype (default) or whether it is directly of the xtype specified (shallow = true).</p>
2091 * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
2092 * to participate in determination of inherited xtypes.</b></p>
2093 * <p>For a list of all available xtypes, see the {@link Ext.Component} header.</p>
2094 * <p>Example usage:</p>
2096 var t = new Ext.form.field.Text();
2097 var isText = t.isXType('textfield'); // true
2098 var isBoxSubclass = t.isXType('field'); // true, descended from Ext.form.field.Base
2099 var isBoxInstance = t.isXType('field', true); // false, not a direct Ext.form.field.Base instance
2101 * @param {String} xtype The xtype to check for this Component
2102 * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
2103 * the default), or true to check whether this Component is directly of the specified xtype.
2104 * @return {Boolean} True if this component descends from the specified xtype, false otherwise.
2106 isXType: function(xtype, shallow) {
2107 //assume a string by default
2108 if (Ext.isFunction(xtype)) {
2109 xtype = xtype.xtype;
2110 //handle being passed the class, e.g. Ext.Component
2111 } else if (Ext.isObject(xtype)) {
2112 xtype = xtype.statics().xtype;
2113 //handle being passed an instance
2116 return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1: this.self.xtype == xtype;
2120 * <p>Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all
2121 * available xtypes, see the {@link Ext.Component} header.</p>
2122 * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
2123 * to participate in determination of inherited xtypes.</b></p>
2124 * <p>Example usage:</p>
2126 var t = new Ext.form.field.Text();
2127 alert(t.getXTypes()); // alerts 'component/field/textfield'
2129 * @return {String} The xtype hierarchy string
2131 getXTypes: function() {
2132 var self = this.self,
2134 parentPrototype = this,
2138 while (parentPrototype && Ext.getClass(parentPrototype)) {
2139 xtype = Ext.getClass(parentPrototype).xtype;
2141 if (xtype !== undefined) {
2142 xtypes.unshift(xtype);
2145 parentPrototype = parentPrototype.superclass;
2148 self.xtypeChain = xtypes;
2149 self.xtypes = xtypes.join('/');
2156 * Update the content area of a component.
2157 * @param {Mixed} htmlOrData
2158 * If this component has been configured with a template via the tpl config
2159 * then it will use this argument as data to populate the template.
2160 * If this component was not configured with a template, the components
2161 * content area will be updated via Ext.core.Element update
2162 * @param {Boolean} loadScripts
2163 * (optional) Only legitimate when using the html configuration. Defaults to false
2164 * @param {Function} callback
2165 * (optional) Only legitimate when using the html configuration. Callback to execute when scripts have finished loading
2167 update : function(htmlOrData, loadScripts, cb) {
2170 if (me.tpl && !Ext.isString(htmlOrData)) {
2171 me.data = htmlOrData;
2173 me.tpl[me.tplWriteMode](me.getTargetEl(), htmlOrData || {});
2176 me.html = Ext.isObject(htmlOrData) ? Ext.core.DomHelper.markup(htmlOrData) : htmlOrData;
2178 me.getTargetEl().update(me.html, loadScripts, cb);
2183 me.doComponentLayout();
2188 * Convenience function to hide or show this component by boolean.
2189 * @param {Boolean} visible True to show, false to hide
2190 * @return {Ext.Component} this
2192 setVisible : function(visible) {
2193 return this[visible ? 'show': 'hide']();
2197 * Returns true if this component is visible.
2198 * @param {Boolean} deep. <p>Optional. Pass <code>true</code> to interrogate the visibility status of all
2199 * parent Containers to determine whether this Component is truly visible to the user.</p>
2200 * <p>Generally, to determine whether a Component is hidden, the no argument form is needed. For example
2201 * when creating dynamically laid out UIs in a hidden Container before showing them.</p>
2202 * @return {Boolean} True if this component is visible, false otherwise.
2204 isVisible: function(deep) {
2207 visible = !me.hidden,
2208 ancestor = me.ownerCt;
2210 // Clear hiddenOwnerCt property
2211 me.hiddenAncestor = false;
2216 if (deep && visible && me.rendered && ancestor) {
2218 // If any ancestor is hidden, then this is hidden.
2219 // If an ancestor Panel (only Panels have a collapse method) is collapsed,
2220 // then its layoutTarget (body) is hidden, so this is hidden unless its within a
2221 // docked item; they are still visible when collapsed (Unless they themseves are hidden)
2222 if (ancestor.hidden || (ancestor.collapsed &&
2223 !(ancestor.getDockedItems && Ext.Array.contains(ancestor.getDockedItems(), child)))) {
2224 // Store hiddenOwnerCt property if needed
2225 me.hiddenAncestor = ancestor;
2230 ancestor = ancestor.ownerCt;
2237 * Enable the component
2238 * @param {Boolean} silent
2239 * Passing false will supress the 'enable' event from being fired.
2241 enable: function(silent) {
2245 me.el.removeCls(me.disabledCls);
2246 me.el.dom.disabled = false;
2250 me.disabled = false;
2252 if (silent !== true) {
2253 me.fireEvent('enable', me);
2260 * Disable the component.
2261 * @param {Boolean} silent
2262 * Passing true, will supress the 'disable' event from being fired.
2264 disable: function(silent) {
2268 me.el.addCls(me.disabledCls);
2269 me.el.dom.disabled = true;
2275 if (silent !== true) {
2276 me.fireEvent('disable', me);
2283 onEnable: function() {
2284 if (this.maskOnDisable) {
2290 onDisable : function() {
2291 if (this.maskOnDisable) {
2297 * Method to determine whether this Component is currently disabled.
2298 * @return {Boolean} the disabled state of this Component.
2300 isDisabled : function() {
2301 return this.disabled;
2305 * Enable or disable the component.
2306 * @param {Boolean} disabled
2308 setDisabled : function(disabled) {
2309 return this[disabled ? 'disable': 'enable']();
2313 * Method to determine whether this Component is currently set to hidden.
2314 * @return {Boolean} the hidden state of this Component.
2316 isHidden : function() {
2321 * Adds a CSS class to the top level element representing this component.
2322 * @param {String} cls The CSS class name to add
2323 * @return {Ext.Component} Returns the Component to allow method chaining.
2325 addCls : function(className) {
2330 if (!Ext.isArray(className)){
2331 className = className.replace(me.trimRe, '').split(me.spacesRe);
2334 me.el.addCls(className);
2337 me.additionalCls = Ext.Array.unique(me.additionalCls.concat(className));
2343 * @deprecated 4.0 Replaced by {@link #addCls}
2344 * Adds a CSS class to the top level element representing this component.
2345 * @param {String} cls The CSS class name to add
2346 * @return {Ext.Component} Returns the Component to allow method chaining.
2348 addClass : function() {
2349 return this.addCls.apply(this, arguments);
2353 * Removes a CSS class from the top level element representing this component.
2354 * @returns {Ext.Component} Returns the Component to allow method chaining.
2356 removeCls : function(className) {
2362 if (!Ext.isArray(className)){
2363 className = className.replace(me.trimRe, '').split(me.spacesRe);
2366 me.el.removeCls(className);
2368 else if (me.additionalCls.length) {
2369 Ext.each(className, function(cls) {
2370 Ext.Array.remove(me.additionalCls, cls);
2377 removeClass : function() {
2378 if (Ext.isDefined(Ext.global.console)) {
2379 Ext.global.console.warn('Ext.Component: removeClass has been deprecated. Please use removeCls.');
2381 return this.removeCls.apply(this, arguments);
2385 addOverCls: function() {
2388 me.el.addCls(me.overCls);
2392 removeOverCls: function() {
2393 this.el.removeCls(this.overCls);
2396 addListener : function(element, listeners, scope, options) {
2401 if (Ext.isString(element) && (Ext.isObject(listeners) || options && options.element)) {
2402 if (options.element) {
2406 listeners[element] = fn;
2407 element = options.element;
2409 listeners.scope = scope;
2412 for (option in options) {
2413 if (options.hasOwnProperty(option)) {
2414 if (me.eventOptionsRe.test(option)) {
2415 listeners[option] = options[option];
2421 // At this point we have a variable called element,
2422 // and a listeners object that can be passed to on
2423 if (me[element] && me[element].on) {
2424 me.mon(me[element], listeners);
2426 me.afterRenderEvents = me.afterRenderEvents || {};
2427 if (!me.afterRenderEvents[element]) {
2428 me.afterRenderEvents[element] = [];
2430 me.afterRenderEvents[element].push(listeners);
2434 return me.mixins.observable.addListener.apply(me, arguments);
2438 removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){
2440 element = managedListener.options ? managedListener.options.element : null;
2443 element = me[element];
2444 if (element && element.un) {
2445 if (isClear || (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope))) {
2446 element.un(managedListener.ename, managedListener.fn, managedListener.scope);
2448 Ext.Array.remove(me.managedListeners, managedListener);
2453 return me.mixins.observable.removeManagedListenerItem.apply(me, arguments);
2458 * Provides the link for Observable's fireEvent method to bubble up the ownership hierarchy.
2459 * @return {Ext.container.Container} the Container which owns this Component.
2461 getBubbleTarget : function() {
2462 return this.ownerCt;
2466 * Method to determine whether this Component is floating.
2467 * @return {Boolean} the floating state of this component.
2469 isFloating : function() {
2470 return this.floating;
2474 * Method to determine whether this Component is draggable.
2475 * @return {Boolean} the draggable state of this component.
2477 isDraggable : function() {
2478 return !!this.draggable;
2482 * Method to determine whether this Component is droppable.
2483 * @return {Boolean} the droppable state of this component.
2485 isDroppable : function() {
2486 return !!this.droppable;
2491 * Method to manage awareness of when components are added to their
2492 * respective Container, firing an added event.
2493 * References are established at add time rather than at render time.
2494 * @param {Ext.container.Container} container Container which holds the component
2495 * @param {number} pos Position at which the component was added
2497 onAdded : function(container, pos) {
2498 this.ownerCt = container;
2499 this.fireEvent('added', this, container, pos);
2504 * Method to manage awareness of when components are removed from their
2505 * respective Container, firing an removed event. References are properly
2506 * cleaned up after removing a component from its owning container.
2508 onRemoved : function() {
2511 me.fireEvent('removed', me, me.ownerCt);
2516 beforeDestroy : Ext.emptyFn,
2519 onResize : Ext.emptyFn,
2522 * Sets the width and height of this Component. This method fires the {@link #resize} event. This method can accept
2523 * either width and height as separate arguments, or you can pass a size object like <code>{width:10, height:20}</code>.
2524 * @param {Mixed} width The new width to set. This may be one of:<div class="mdetail-params"><ul>
2525 * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.core.Element#defaultUnit}s (by default, pixels).</li>
2526 * <li>A String used to set the CSS width style.</li>
2527 * <li>A size object in the format <code>{width: widthValue, height: heightValue}</code>.</li>
2528 * <li><code>undefined</code> to leave the width unchanged.</li>
2530 * @param {Mixed} height The new height to set (not required if a size object is passed as the first arg).
2531 * This may be one of:<div class="mdetail-params"><ul>
2532 * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.core.Element#defaultUnit}s (by default, pixels).</li>
2533 * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
2534 * <li><code>undefined</code> to leave the height unchanged.</li>
2536 * @return {Ext.Component} this
2538 setSize : function(width, height) {
2542 // support for standard size objects
2543 if (Ext.isObject(width)) {
2544 height = width.height;
2545 width = width.width;
2548 // Constrain within configured maxima
2549 if (Ext.isNumber(width)) {
2550 width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
2552 if (Ext.isNumber(height)) {
2553 height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
2556 if (!me.rendered || !me.isVisible()) {
2557 // If an ownerCt is hidden, add my reference onto the layoutOnShow stack. Set the needsLayout flag.
2558 if (me.hiddenAncestor) {
2559 layoutCollection = me.hiddenAncestor.layoutOnShow;
2560 layoutCollection.remove(me);
2561 layoutCollection.add(me);
2569 me.width = (width !== undefined) ? width : me.width;
2570 me.height = (height !== undefined) ? height : me.height;
2574 me.doComponentLayout(width, height, true);
2579 isFixedWidth: function() {
2581 layoutManagedWidth = me.layoutManagedWidth;
2583 if (Ext.isDefined(me.width) || layoutManagedWidth == 1) {
2586 if (layoutManagedWidth == 2) {
2589 return (me.ownerCt && me.ownerCt.isFixedWidth());
2592 isFixedHeight: function() {
2594 layoutManagedHeight = me.layoutManagedHeight;
2596 if (Ext.isDefined(me.height) || layoutManagedHeight == 1) {
2599 if (layoutManagedHeight == 2) {
2602 return (me.ownerCt && me.ownerCt.isFixedHeight());
2605 setCalculatedSize : function(width, height, callingContainer) {
2609 // support for standard size objects
2610 if (Ext.isObject(width)) {
2611 callingContainer = width.ownerCt;
2612 height = width.height;
2613 width = width.width;
2616 // Constrain within configured maxima
2617 if (Ext.isNumber(width)) {
2618 width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
2620 if (Ext.isNumber(height)) {
2621 height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
2624 if (!me.rendered || !me.isVisible()) {
2625 // If an ownerCt is hidden, add my reference onto the layoutOnShow stack. Set the needsLayout flag.
2626 if (me.hiddenAncestor) {
2627 layoutCollection = me.hiddenAncestor.layoutOnShow;
2628 layoutCollection.remove(me);
2629 layoutCollection.add(me);
2635 ownerCt: callingContainer
2639 me.doComponentLayout(width, height, false, callingContainer);
2645 * This method needs to be called whenever you change something on this component that requires the Component's
2646 * layout to be recalculated.
2647 * @return {Ext.container.Container} this
2649 doComponentLayout : function(width, height, isSetSize, callingContainer) {
2651 componentLayout = me.getComponentLayout(),
2652 lastComponentSize = componentLayout.lastComponentSize || {
2657 // collapsed state is not relevant here, so no testing done.
2658 // Only Panels have a collapse method, and that just sets the width/height such that only
2659 // a single docked Header parallel to the collapseTo side are visible, and the Panel body is hidden.
2660 if (me.rendered && componentLayout) {
2663 // If no width passed, then only insert a value if the Component is NOT ALLOWED to autowidth itself.
2664 if (!Ext.isDefined(width)) {
2665 if (me.isFixedWidth()) {
2666 width = Ext.isDefined(me.width) ? me.width : lastComponentSize.width;
2670 // If no height passed, then only insert a value if the Component is NOT ALLOWED to autoheight itself.
2671 if (!Ext.isDefined(height)) {
2672 if (me.isFixedHeight()) {
2673 height = Ext.isDefined(me.height) ? me.height : lastComponentSize.height;
2682 componentLayout.layout(width, height, isSetSize, callingContainer);
2688 * Forces this component to redo its componentLayout.
2690 forceComponentLayout: function () {
2691 this.doComponentLayout();
2695 setComponentLayout : function(layout) {
2696 var currentLayout = this.componentLayout;
2697 if (currentLayout && currentLayout.isLayout && currentLayout != layout) {
2698 currentLayout.setOwner(null);
2700 this.componentLayout = layout;
2701 layout.setOwner(this);
2704 getComponentLayout : function() {
2707 if (!me.componentLayout || !me.componentLayout.isLayout) {
2708 me.setComponentLayout(Ext.layout.Layout.create(me.componentLayout, 'autocomponent'));
2710 return me.componentLayout;
2714 * @param {Number} adjWidth The box-adjusted width that was set
2715 * @param {Number} adjHeight The box-adjusted height that was set
2716 * @param {Boolean} isSetSize Whether or not the height/width are stored on the component permanently
2717 * @param {Ext.Component} callingContainer Container requesting the layout. Only used when isSetSize is false.
2719 afterComponentLayout: function(width, height, isSetSize, callingContainer) {
2720 this.fireEvent('resize', this, width, height);
2724 * Occurs before componentLayout is run. Returning false from this method will prevent the componentLayout
2725 * from being executed.
2726 * @param {Number} adjWidth The box-adjusted width that was set
2727 * @param {Number} adjHeight The box-adjusted height that was set
2728 * @param {Boolean} isSetSize Whether or not the height/width are stored on the component permanently
2729 * @param {Ext.Component} callingContainer Container requesting sent the layout. Only used when isSetSize is false.
2731 beforeComponentLayout: function(width, height, isSetSize, callingContainer) {
2736 * Sets the left and top of the component. To set the page XY position instead, use
2737 * {@link Ext.Component#setPagePosition setPagePosition}.
2738 * This method fires the {@link #move} event.
2739 * @param {Number} left The new left
2740 * @param {Number} top The new top
2741 * @return {Ext.Component} this
2743 setPosition : function(x, y) {
2746 if (Ext.isObject(x)) {
2755 if (x !== undefined || y !== undefined) {
2757 me.onPosition(x, y);
2758 me.fireEvent('move', me, x, y);
2764 * Called after the component is moved, this method is empty by default but can be implemented by any
2765 * subclass that needs to perform custom logic after a move occurs.
2766 * @param {Number} x The new x position
2767 * @param {Number} y The new y position
2769 onPosition: Ext.emptyFn,
2772 * Sets the width of the component. This method fires the {@link #resize} event.
2773 * @param {Number} width The new width to setThis may be one of:<div class="mdetail-params"><ul>
2774 * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.core.Element#defaultUnit}s (by default, pixels).</li>
2775 * <li>A String used to set the CSS width style.</li>
2777 * @return {Ext.Component} this
2779 setWidth : function(width) {
2780 return this.setSize(width);
2784 * Sets the height of the component. This method fires the {@link #resize} event.
2785 * @param {Number} height The new height to set. This may be one of:<div class="mdetail-params"><ul>
2786 * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.core.Element#defaultUnit}s (by default, pixels).</li>
2787 * <li>A String used to set the CSS height style.</li>
2788 * <li><i>undefined</i> to leave the height unchanged.</li>
2790 * @return {Ext.Component} this
2792 setHeight : function(height) {
2793 return this.setSize(undefined, height);
2797 * Gets the current size of the component's underlying element.
2798 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
2800 getSize : function() {
2801 return this.el.getSize();
2805 * Gets the current width of the component's underlying element.
2808 getWidth : function() {
2809 return this.el.getWidth();
2813 * Gets the current height of the component's underlying element.
2816 getHeight : function() {
2817 return this.el.getHeight();
2821 * Gets the {@link Ext.ComponentLoader} for this Component.
2822 * @return {Ext.ComponentLoader} The loader instance, null if it doesn't exist.
2824 getLoader: function(){
2826 autoLoad = me.autoLoad ? (Ext.isObject(me.autoLoad) ? me.autoLoad : {url: me.autoLoad}) : null,
2827 loader = me.loader || autoLoad;
2830 if (!loader.isLoader) {
2831 me.loader = Ext.create('Ext.ComponentLoader', Ext.apply({
2836 loader.setTarget(me);
2845 * This method allows you to show or hide a LoadMask on top of this component.
2846 * @param {Boolean/Object/String} load True to show the default LoadMask, a config object
2847 * that will be passed to the LoadMask constructor, or a message String to show. False to
2848 * hide the current LoadMask.
2849 * @param {Boolean} targetEl True to mask the targetEl of this Component instead of the this.el.
2850 * For example, setting this to true on a Panel will cause only the body to be masked. (defaults to false)
2851 * @return {Ext.LoadMask} The LoadMask instance that has just been shown.
2853 setLoading : function(load, targetEl) {
2858 if (load !== false && !me.collapsed) {
2859 if (Ext.isObject(load)) {
2862 else if (Ext.isString(load)) {
2863 config = {msg: load};
2868 me.loadMask = me.loadMask || Ext.create('Ext.LoadMask', targetEl ? me.getTargetEl() : me.el, config);
2870 } else if (me.loadMask) {
2871 Ext.destroy(me.loadMask);
2880 * Sets the dock position of this component in its parent panel. Note that
2881 * this only has effect if this item is part of the dockedItems collection
2882 * of a parent that has a DockLayout (note that any Panel has a DockLayout
2884 * @return {Component} this
2886 setDocked : function(dock, layoutParent) {
2890 if (layoutParent && me.ownerCt && me.rendered) {
2891 me.ownerCt.doComponentLayout();
2896 onDestroy : function() {
2899 if (me.monitorResize && Ext.EventManager.resizeEvent) {
2900 Ext.EventManager.resizeEvent.removeListener(me.setSize, me);
2902 Ext.destroy(me.componentLayout, me.loadMask);
2906 * Destroys the Component.
2908 destroy : function() {
2911 if (!me.isDestroyed) {
2912 if (me.fireEvent('beforedestroy', me) !== false) {
2913 me.destroying = true;
2917 delete me.floatParent;
2918 // A zIndexManager is stamped into a *floating* Component when it is added to a Container.
2919 // If it has no zIndexManager at render time, it is assigned to the global Ext.WindowManager instance.
2920 if (me.zIndexManager) {
2921 me.zIndexManager.unregister(me);
2923 } else if (me.ownerCt && me.ownerCt.remove) {
2924 me.ownerCt.remove(me, false);
2929 // Attempt to destroy all plugins
2930 Ext.destroy(me.plugins);
2936 Ext.ComponentManager.unregister(me);
2937 me.fireEvent('destroy', me);
2939 me.mixins.state.destroy.call(me);
2941 me.clearListeners();
2942 me.destroying = false;
2943 me.isDestroyed = true;
2949 * Retrieves a plugin by its pluginId which has been bound to this
2951 * @returns {Ext.AbstractPlugin} pluginInstance
2953 getPlugin: function(pluginId) {
2955 plugins = this.plugins,
2956 ln = plugins.length;
2957 for (; i < ln; i++) {
2958 if (plugins[i].pluginId === pluginId) {
2965 * Determines whether this component is the descendant of a particular container.
2966 * @param {Ext.Container} container
2967 * @returns {Boolean} isDescendant
2969 isDescendantOf: function(container) {
2970 return !!this.findParentBy(function(p){
2971 return p === container;
2977 prev: 'previousSibling',