Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / src / AbstractComponent.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
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.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
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>
19  */
20
21 Ext.define('Ext.AbstractComponent', {
22
23     /* Begin Definitions */
24
25     mixins: {
26         observable: 'Ext.util.Observable',
27         animate: 'Ext.util.Animate',
28         state: 'Ext.state.Stateful'
29     },
30
31     requires: [
32         'Ext.PluginManager',
33         'Ext.ComponentManager',
34         'Ext.core.Element',
35         'Ext.core.DomHelper',
36         'Ext.XTemplate',
37         'Ext.ComponentQuery',
38         'Ext.LoadMask',
39         'Ext.ComponentLoader',
40         'Ext.EventManager',
41         'Ext.layout.Layout',
42         'Ext.layout.component.Auto'
43     ],
44
45     // Please remember to add dependencies whenever you use it
46     // I had to fix these many times already
47     uses: [
48         'Ext.ZIndexManager'
49     ],
50
51     statics: {
52         AUTO_ID: 1000
53     },
54
55     /* End Definitions */
56
57     isComponent: true,
58
59     getAutoId: function() {
60         return ++Ext.AbstractComponent.AUTO_ID;
61     },
62
63
64     /**
65      * @cfg {String} 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>
78      */
79
80     /**
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>
90      * <pre><code>
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}: [
96         {
97             itemId: 'p1',
98             {@link Ext.panel.Panel#title title}: 'Panel 1',
99             {@link Ext.Component#height height}: 150
100         },
101         {
102             itemId: 'p2',
103             {@link Ext.panel.Panel#title title}: 'Panel 2',
104             {@link Ext.Component#height height}: 150
105         }
106     ]
107 })
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
110      * </code></pre>
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>
114      */
115
116     /**
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
121      * @property ownerCt
122      */
123
124      /**
125       * @private
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.
130       * @type boolean
131       * @property layoutManagedWidth
132       */
133
134      /**
135       * @private
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.
140       * @type boolean
141       * @property layoutManagedHeight
142       */
143
144     /**
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>
153 {
154     xtype: 'component',
155     autoEl: {
156         tag: 'img',
157         src: 'http://www.example.com/example.jpg'
158     }
159 }, {
160     xtype: 'component',
161     autoEl: {
162         tag: 'blockquote',
163         html: 'autoEl is cool!'
164     }
165 }, {
166     xtype: 'container',
167     autoEl: 'ul',
168     cls: 'ux-unordered-list',
169     items: {
170         xtype: 'component',
171         autoEl: 'li',
172         html: 'First list item'
173     }
174 }
175 </code></pre>
176      */
177
178     /**
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>
190      */
191     renderTpl: null,
192
193     /**
194      * @cfg {Object} renderSelectors
195
196 An object containing properties specifying {@link Ext.DomQuery DomQuery} selectors which identify child elements
197 created by the render process.
198
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.
201
202 For example, a Component which rendered an image, and description into its element might use the following properties
203 coded into its prototype:
204
205     renderTpl: '&lt;img src="{imageUrl}" class="x-image-component-img">&lt;div class="x-image-component-desc">{description}&gt;/div&lt;',
206
207     renderSelectors: {
208         image: 'img.x-image-component-img',
209         descEl: 'div.x-image-component-desc'
210     }
211
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.
214
215      * @markdown
216      */
217
218     /**
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>
228      * </ul></li>
229      * </ul></div>
230      * <p>See <code>{@link #render}</code> also.</p>
231      */
232
233     /**
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>
240      */
241
242     /**
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>
251      * </ul></div>
252      * @property frameSize
253      * @type {Object}
254      */
255
256     /**
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>
264      */
265
266     /**
267      * @cfg {Mixed} tpl
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.
272      */
273
274     /**
275      * @cfg {Mixed} data
276      * The initial set of data to apply to the <code>{@link #tpl}</code> to
277      * update the content area of the Component.
278      */
279
280     /**
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>).
284      */
285     tplWriteMode: 'overwrite',
286
287     /**
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
293      * component.
294      */
295     baseCls: Ext.baseCSSPrefix + 'component',
296
297     /**
298      * @cfg {String} componentCls
299      * CSS Class to be added to a components root level element to give distinction to it
300      * via styling.
301      */
302
303     /**
304      * @cfg {String} cls
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.
307      */
308
309     /**
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.
314      */
315
316     /**
317      * @cfg {String} disabledCls
318      * CSS class to add when the Component is disabled. Defaults to 'x-item-disabled'.
319      */
320     disabledCls: Ext.baseCSSPrefix + 'item-disabled',
321
322     /**
323      * @cfg {String/Array} ui
324      * A set style for a component. Can be a string or an Array of multiple strings (UIs)
325      */
326     ui: 'default',
327
328     /**
329      * @cfg {Array} uiCls
330      * An array of of classNames which are currently applied to this component
331      * @private
332      */
333     uiCls: [],
334
335     /**
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}.
339      * <pre><code>
340         new Ext.panel.Panel({
341             title: 'Some Title',
342             renderTo: Ext.getBody(),
343             width: 400, height: 300,
344             layout: 'form',
345             items: [{
346                 xtype: 'textarea',
347                 style: {
348                     width: '95%',
349                     marginBottom: '10px'
350                 }
351             },
352             new Ext.button.Button({
353                 text: 'Send',
354                 minWidth: '100',
355                 style: {
356                     marginBottom: '10px'
357                 }
358             })
359             ]
360         });
361      </code></pre>
362      */
363
364     /**
365      * @cfg {Number} width
366      * The width of this component in pixels.
367      */
368
369     /**
370      * @cfg {Number} height
371      * The height of this component in pixels.
372      */
373
374     /**
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'.
378      */
379
380     /**
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'.
384      */
385
386     /**
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'.
390      */
391
392     /**
393      * @cfg {Boolean} hidden
394      * Defaults to false.
395      */
396     hidden: false,
397
398     /**
399      * @cfg {Boolean} disabled
400      * Defaults to false.
401      */
402     disabled: false,
403
404     /**
405      * @cfg {Boolean} draggable
406      * Allows the component to be dragged.
407      */
408
409     /**
410      * Read-only property indicating whether or not the component can be dragged
411      * @property draggable
412      * @type {Boolean}
413      */
414     draggable: false,
415
416     /**
417      * @cfg {Boolean} floating
418      * Create the Component as a floating and use absolute positioning.
419      * Defaults to false.
420      */
421     floating: false,
422
423     /**
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>.
433      */
434     hideMode: 'display',
435
436     /**
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>
440      * <ul>
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>
444      * <li><b>Notes</b> :
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>
451      * </ul>
452      */
453
454     /**
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.
460      */
461
462     /**
463      * @cfg {Boolean} styleHtmlContent
464      * True to automatically style the html inside the content target of this component (body for panels).
465      * Defaults to false.
466      */
467     styleHtmlContent: false,
468
469     /**
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'
473      */
474     styleHtmlCls: Ext.baseCSSPrefix + 'html',
475
476     /**
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>
480      */
481     /**
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>
485      */
486     /**
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>
490      */
491     /**
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>
495      */
496
497     /**
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.
501      */
502
503      // @private
504      allowDomMove: true,
505
506      /**
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>.
510       */
511      autoShow: false,
512
513     /**
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>
521      */
522      autoRender: false,
523
524      needsLayout: false,
525
526     /**
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.
533      */
534
535     /**
536      * Read-only property indicating whether or not the component has been rendered.
537      * @property rendered
538      * @type {Boolean}
539      */
540     rendered: false,
541
542     weight: 0,
543
544     trimRe: /^\s+|\s+$/g,
545     spacesRe: /\s+/,
546
547
548     /**
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
554      * @type {Boolean}
555      */
556     maskOnDisable: true,
557
558     /**
559      * Creates new Component.
560      * @param {Object} config  (optional) Config object.
561      */
562     constructor : function(config) {
563         var me = this,
564             i, len;
565
566         config = config || {};
567         me.initialConfig = config;
568         Ext.apply(me, config);
569
570         me.addEvents(
571             /**
572              * @event beforeactivate
573              * Fires before a Component has been visually activated.
574              * Returning false from an event listener can prevent the activate
575              * from occurring.
576              * @param {Ext.Component} this
577              */
578              'beforeactivate',
579             /**
580              * @event activate
581              * Fires after a Component has been visually activated.
582              * @param {Ext.Component} this
583              */
584              'activate',
585             /**
586              * @event beforedeactivate
587              * Fires before a Component has been visually deactivated.
588              * Returning false from an event listener can prevent the deactivate
589              * from occurring.
590              * @param {Ext.Component} this
591              */
592              'beforedeactivate',
593             /**
594              * @event deactivate
595              * Fires after a Component has been visually deactivated.
596              * @param {Ext.Component} this
597              */
598              'deactivate',
599             /**
600              * @event added
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
605              */
606              'added',
607             /**
608              * @event disable
609              * Fires after the component is disabled.
610              * @param {Ext.Component} this
611              */
612              'disable',
613             /**
614              * @event enable
615              * Fires after the component is enabled.
616              * @param {Ext.Component} this
617              */
618              'enable',
619             /**
620              * @event beforeshow
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
624              */
625              'beforeshow',
626             /**
627              * @event show
628              * Fires after the component is shown when calling the {@link #show} method.
629              * @param {Ext.Component} this
630              */
631              'show',
632             /**
633              * @event beforehide
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
637              */
638              'beforehide',
639             /**
640              * @event hide
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
644              */
645              'hide',
646             /**
647              * @event removed
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
651              */
652              'removed',
653             /**
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
658              */
659              'beforerender',
660             /**
661              * @event render
662              * Fires after the component markup is {@link #rendered}.
663              * @param {Ext.Component} this
664              */
665              'render',
666             /**
667              * @event afterrender
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
672              */
673              'afterrender',
674             /**
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
678              */
679              'beforedestroy',
680             /**
681              * @event destroy
682              * Fires after the component is {@link #destroy}ed.
683              * @param {Ext.Component} this
684              */
685              'destroy',
686             /**
687              * @event resize
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
692              */
693              'resize',
694             /**
695              * @event move
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
700              */
701              'move'
702         );
703
704         me.getId();
705
706         me.mons = [];
707         me.additionalCls = [];
708         me.renderData = me.renderData || {};
709         me.renderSelectors = me.renderSelectors || {};
710
711         if (me.plugins) {
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]);
715             }
716         }
717
718         me.initComponent();
719
720         // ititComponent gets a chance to change the id property before registering
721         Ext.ComponentManager.register(me);
722
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);
726
727         // Save state on resize.
728         this.addStateEvents('resize');
729
730         // Move this into Observable?
731         if (me.plugins) {
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]);
735             }
736         }
737
738         me.loader = me.getLoader();
739
740         if (me.renderTo) {
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.
745         }
746
747         if (me.autoShow) {
748             me.show();
749         }
750
751         //<debug>
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.');
755             }
756             me.disabledCls = me.disabledClass;
757             delete me.disabledClass;
758         }
759         //</debug>
760     },
761
762     initComponent: Ext.emptyFn,
763
764     /**
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>
772      */
773     getState: function() {
774         var me = this,
775             layout = me.ownerCt ? (me.shadowOwnerCt || me.ownerCt).getLayout() : null,
776             state = {
777                 collapsed: me.collapsed
778             },
779             width = me.width,
780             height = me.height,
781             cm = me.collapseMemento,
782             anchors;
783
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)) {
788                 width = cm.width;
789             }
790             if (Ext.isDefined(cm.data.height)) {
791                 height = cm.height;
792             }
793         }
794
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]();
799         }
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);
804             if (!anchors[0]) {
805                 if (me.width) {
806                     state.width = width;
807                 }
808             }
809             if (!anchors[1]) {
810                 if (me.height) {
811                     state.height = height;
812                 }
813             }
814         }
815         // Store dimensions.
816         else {
817             if (me.width) {
818                 state.width = width;
819             }
820             if (me.height) {
821                 state.height = height;
822             }
823         }
824
825         // Don't save dimensions if they are unchanged from the original configuration.
826         if (state.width == me.initialConfig.width) {
827             delete state.width;
828         }
829         if (state.height == me.initialConfig.height) {
830             delete state.height;
831         }
832
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];
836         }
837         return state;
838     },
839
840     show: Ext.emptyFn,
841
842     animate: function(animObj) {
843         var me = this,
844             to;
845
846         animObj = animObj || {};
847         to = animObj.to || {};
848
849         if (Ext.fx.Manager.hasFxBlock(me.id)) {
850             return me;
851         }
852         // Special processing for animating Component dimensions.
853         if (!animObj.dynamic && (to.height || to.width)) {
854             var curWidth = me.getWidth(),
855                 w = curWidth,
856                 curHeight = me.getHeight(),
857                 h = curHeight,
858                 needsResize = false;
859
860             if (to.height && to.height > curHeight) {
861                 h = to.height;
862                 needsResize = true;
863             }
864             if (to.width && to.width > curWidth) {
865                 w = to.width;
866                 needsResize = true;
867             }
868
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.
872             if (needsResize) {
873                 var clearWidth = !Ext.isNumber(me.width),
874                     clearHeight = !Ext.isNumber(me.height);
875
876                 me.componentLayout.childrenChanged = true;
877                 me.setSize(w, h, me.ownerCt);
878                 me.el.setSize(curWidth, curHeight);
879                 if (clearWidth) {
880                     delete me.width;
881                 }
882                 if (clearHeight) {
883                     delete me.height;
884                 }
885             }
886         }
887         return me.mixins.animate.animate.apply(me, arguments);
888     },
889
890     /**
891      * <p>This method finds the topmost active layout who's processing will eventually determine the size and position of this
892      * Component.<p>
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>
895      * @returns
896      */
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);
902         });
903     },
904
905     onShow : function() {
906         // Layout if needed
907         var needsLayout = this.needsLayout;
908         if (Ext.isObject(needsLayout)) {
909             this.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize, needsLayout.ownerCt);
910         }
911     },
912
913     constructPlugin: function(plugin) {
914         if (plugin.ptype && typeof plugin.init != 'function') {
915             plugin.cmp = this;
916             plugin = Ext.PluginManager.create(plugin);
917         }
918         else if (typeof plugin == 'string') {
919             plugin = Ext.PluginManager.create({
920                 ptype: plugin,
921                 cmp: this
922             });
923         }
924         return plugin;
925     },
926
927     // @private
928     initPlugin : function(plugin) {
929         plugin.init(this);
930
931         return plugin;
932     },
933
934     /**
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
938      */
939     doAutoRender: function() {
940         var me = this;
941         if (me.floating) {
942             me.render(document.body);
943         } else {
944             me.render(Ext.isBoolean(me.autoRender) ? Ext.getBody() : me.autoRender);
945         }
946     },
947
948     // @private
949     render : function(container, position) {
950         var me = this;
951
952         if (!me.rendered && me.fireEvent('beforerender', me) !== false) {
953             // If this.el is defined, we want to make sure we are dealing with
954             // an Ext Element.
955             if (me.el) {
956                 me.el = Ext.get(me.el);
957             }
958
959             // Perform render-time processing for floating Components
960             if (me.floating) {
961                 me.onFloatRender();
962             }
963
964             container = me.initContainer(container);
965
966             me.onRender(container, position);
967
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()]);
971
972             if (me.overCls) {
973                 me.el.hover(me.addOverCls, me.removeOverCls, me);
974             }
975
976             me.fireEvent('render', me);
977
978             me.initContent();
979
980             me.afterRender(container);
981             me.fireEvent('afterrender', me);
982
983             me.initEvents();
984
985             if (me.hidden) {
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
989                 me.el.hide();
990             }
991
992             if (me.disabled) {
993                 // pass silent so the event doesn't fire the first time.
994                 me.disable(true);
995             }
996         }
997         return me;
998     },
999
1000     // @private
1001     onRender : function(container, position) {
1002         var me = this,
1003             el = me.el,
1004             styles = me.initStyles(),
1005             renderTpl, renderData, i;
1006
1007         position = me.getInsertPosition(position);
1008
1009         if (!el) {
1010             if (position) {
1011                 el = Ext.core.DomHelper.insertBefore(position, me.getElConfig(), true);
1012             }
1013             else {
1014                 el = Ext.core.DomHelper.append(container, me.getElConfig(), true);
1015             }
1016         }
1017         else if (me.allowDomMove !== false) {
1018             if (position) {
1019                 container.dom.insertBefore(el.dom, position);
1020             } else {
1021                 container.dom.appendChild(el.dom);
1022             }
1023         }
1024
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');
1029             }
1030             else {
1031                 // Else we wrap this element in an element that adds the reset class.
1032                 me.resetEl = el.wrap({
1033                     cls: Ext.baseCSSPrefix + 'reset'
1034                 });
1035             }
1036         }
1037
1038         me.setUI(me.ui);
1039
1040         el.addCls(me.initCls());
1041         el.setStyle(styles);
1042
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;
1051         //     }
1052         // }
1053
1054         me.el = el;
1055
1056         me.initFrame();
1057
1058         renderTpl = me.initRenderTpl();
1059         if (renderTpl) {
1060             renderData = me.initRenderData();
1061             renderTpl.append(me.getTargetEl(), renderData);
1062         }
1063
1064         me.applyRenderSelectors();
1065
1066         me.rendered = true;
1067     },
1068
1069     // @private
1070     afterRender : function() {
1071         var me = this,
1072             pos,
1073             xy;
1074
1075         me.getComponentLayout();
1076
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);
1080         }
1081
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]);
1088             } else {
1089                 xy = me.el.getAlignToXY(me.container, 'c-c');
1090                 pos = me.container.translatePoints(xy[0], xy[1]);
1091             }
1092             me.x = me.x === undefined ? pos.left: me.x;
1093             me.y = me.y === undefined ? pos.top: me.y;
1094         }
1095
1096         if (Ext.isDefined(me.x) || Ext.isDefined(me.y)) {
1097             me.setPosition(me.x, me.y);
1098         }
1099
1100         if (me.styleHtmlContent) {
1101             me.getTargetEl().addCls(me.styleHtmlCls);
1102         }
1103     },
1104
1105     frameCls: Ext.baseCSSPrefix + 'frame',
1106
1107     frameElementCls: {
1108         tl: [],
1109         tc: [],
1110         tr: [],
1111         ml: [],
1112         mc: [],
1113         mr: [],
1114         bl: [],
1115         bc: [],
1116         br: []
1117     },
1118
1119     frameTpl: [
1120         '<tpl if="top">',
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>',
1126         '</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>',
1138         '</tpl>'
1139     ],
1140
1141     frameTableTpl: [
1142         '<table><tbody>',
1143             '<tpl if="top">',
1144                 '<tr>',
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>',
1148                 '</tr>',
1149             '</tpl>',
1150             '<tr>',
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>',
1154             '</tr>',
1155             '<tpl if="bottom">',
1156                 '<tr>',
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>',
1160                 '</tr>',
1161             '</tpl>',
1162         '</tbody></table>'
1163     ],
1164
1165     /**
1166      * @private
1167      */
1168     initFrame : function() {
1169         if (Ext.supports.CSS3BorderRadius) {
1170             return false;
1171         }
1172
1173         var me = this,
1174             frameInfo = me.getFrameInfo(),
1175             frameWidth = frameInfo.width,
1176             frameTpl = me.getFrameTpl(frameInfo.table);
1177
1178         if (me.frame) {
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({}, {
1181                 ui:         me.ui,
1182                 uiCls:      me.uiCls,
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)));
1191
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');
1194
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'
1206             });
1207         }
1208     },
1209
1210     updateFrame: function() {
1211         if (Ext.supports.CSS3BorderRadius) {
1212             return false;
1213         }
1214
1215         var me = this,
1216             wasTable = this.frameSize && this.frameSize.table,
1217             oldFrameTL = this.frameTL,
1218             oldFrameBL = this.frameBL,
1219             oldFrameML = this.frameML,
1220             oldFrameMC = this.frameMC,
1221             newMCClassName;
1222
1223         this.initFrame();
1224
1225         if (oldFrameMC) {
1226             if (me.frame) {
1227                 // Reapply render selectors
1228                 delete me.frameTL;
1229                 delete me.frameTC;
1230                 delete me.frameTR;
1231                 delete me.frameML;
1232                 delete me.frameMC;
1233                 delete me.frameMR;
1234                 delete me.frameBL;
1235                 delete me.frameBC;
1236                 delete me.frameBR;
1237                 this.applyRenderSelectors();
1238
1239                 // Store the class names set on the new mc
1240                 newMCClassName = this.frameMC.dom.className;
1241
1242                 // Replace the new mc with the old mc
1243                 oldFrameMC.insertAfter(this.frameMC);
1244                 this.frameMC.remove();
1245
1246                 // Restore the reference to the old frame mc as the framebody
1247                 this.frameBody = this.frameMC = oldFrameMC;
1248
1249                 // Apply the new mc classes to the old mc element
1250                 oldFrameMC.dom.className = newMCClassName;
1251
1252                 // Remove the old framing
1253                 if (wasTable) {
1254                     me.el.query('> table')[1].remove();
1255                 }
1256                 else {
1257                     if (oldFrameTL) {
1258                         oldFrameTL.remove();
1259                     }
1260                     if (oldFrameBL) {
1261                         oldFrameBL.remove();
1262                     }
1263                     oldFrameML.remove();
1264                 }
1265             }
1266             else {
1267                 // We were framed but not anymore. Move all content from the old frame to the body
1268
1269             }
1270         }
1271         else if (me.frame) {
1272             this.applyRenderSelectors();
1273         }
1274     },
1275
1276     getFrameInfo: function() {
1277         if (Ext.supports.CSS3BorderRadius) {
1278             return false;
1279         }
1280
1281         var me = this,
1282             left = me.el.getStyle('background-position-x'),
1283             top = me.el.getStyle('background-position-y'),
1284             info, frameInfo = false, max;
1285
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(' ');
1290             left = info[0];
1291             top = info[1];
1292         }
1293
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) {
1298             max = Math.max;
1299
1300             frameInfo = {
1301                 // Table markup starts with 110, div markup with 100.
1302                 table: left.substr(0, 3) == '110',
1303
1304                 // Determine if we are dealing with a horizontal or vertical component
1305                 vertical: top.substr(0, 3) == '110',
1306
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))
1312             };
1313
1314             frameInfo.width = max(frameInfo.top, frameInfo.right, frameInfo.bottom, frameInfo.left);
1315
1316             // Just to be sure we set the background image of the el to none.
1317             me.el.setStyle('background-image', 'none');
1318         }
1319
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) {
1323             //<debug error>
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.");
1327             //</debug>
1328         }
1329
1330         me.frame = me.frame || !!frameInfo;
1331         me.frameSize = frameInfo || false;
1332
1333         return frameInfo;
1334     },
1335
1336     getFramePositions: function(frameInfo) {
1337         var me = this,
1338             frameWidth = frameInfo.width,
1339             dock = me.dock,
1340             positions, tc, bc, ml, mr;
1341
1342         if (frameInfo.vertical) {
1343             tc = '0 -' + (frameWidth * 0) + 'px';
1344             bc = '0 -' + (frameWidth * 1) + 'px';
1345
1346             if (dock && dock == "right") {
1347                 tc = 'right -' + (frameWidth * 0) + 'px';
1348                 bc = 'right -' + (frameWidth * 1) + 'px';
1349             }
1350
1351             positions = {
1352                 tl: '0 -' + (frameWidth * 0) + 'px',
1353                 tr: '0 -' + (frameWidth * 1) + 'px',
1354                 bl: '0 -' + (frameWidth * 2) + 'px',
1355                 br: '0 -' + (frameWidth * 3) + 'px',
1356
1357                 ml: '-' + (frameWidth * 1) + 'px 0',
1358                 mr: 'right 0',
1359
1360                 tc: tc,
1361                 bc: bc
1362             };
1363         } else {
1364             ml = '-' + (frameWidth * 0) + 'px 0';
1365             mr = 'right 0';
1366
1367             if (dock && dock == "bottom") {
1368                 ml = 'left bottom';
1369                 mr = 'right bottom';
1370             }
1371
1372             positions = {
1373                 tl: '0 -' + (frameWidth * 2) + 'px',
1374                 tr: 'right -' + (frameWidth * 3) + 'px',
1375                 bl: '0 -' + (frameWidth * 4) + 'px',
1376                 br: 'right -' + (frameWidth * 5) + 'px',
1377
1378                 ml: ml,
1379                 mr: mr,
1380
1381                 tc: '0 -' + (frameWidth * 0) + 'px',
1382                 bc: '0 -' + (frameWidth * 1) + 'px'
1383             };
1384         }
1385
1386         return positions;
1387     },
1388
1389     /**
1390      * @private
1391      */
1392     getFrameTpl : function(table) {
1393         return table ? this.getTpl('frameTableTpl') : this.getTpl('frameTpl');
1394     },
1395
1396     /**
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.
1400      * @private
1401      */
1402     initCls: function() {
1403         var me = this,
1404             cls = [];
1405
1406         cls.push(me.baseCls);
1407
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.');
1412             }
1413             me.componentCls = me.cmpCls;
1414             delete me.cmpCls;
1415         }
1416         //</deprecated>
1417
1418         if (me.componentCls) {
1419             cls.push(me.componentCls);
1420         } else {
1421             me.componentCls = me.baseCls;
1422         }
1423         if (me.cls) {
1424             cls.push(me.cls);
1425             delete me.cls;
1426         }
1427
1428         return cls.concat(me.additionalCls);
1429     },
1430
1431     /**
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
1435      */
1436     setUI: function(ui) {
1437         var me = this,
1438             oldUICls = Ext.Array.clone(me.uiCls),
1439             newUICls = [],
1440             classes = [],
1441             cls,
1442             i;
1443
1444         //loop through all exisiting uiCls and update the ui in them
1445         for (i = 0; i < oldUICls.length; i++) {
1446             cls = oldUICls[i];
1447
1448             classes = classes.concat(me.removeClsWithUI(cls, true));
1449             newUICls.push(cls);
1450         }
1451
1452         if (classes.length) {
1453             me.removeCls(classes);
1454         }
1455
1456         //remove the UI from the element
1457         me.removeUIFromElement();
1458
1459         //set the UI
1460         me.ui = ui;
1461
1462         //add the new UI to the elemend
1463         me.addUIToElement();
1464
1465         //loop through all exisiting uiCls and update the ui in them
1466         classes = [];
1467         for (i = 0; i < newUICls.length; i++) {
1468             cls = newUICls[i];
1469             classes = classes.concat(me.addClsWithUI(cls, true));
1470         }
1471
1472         if (classes.length) {
1473             me.addCls(classes);
1474         }
1475     },
1476
1477     /**
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)
1482      */
1483     addClsWithUI: function(cls, skip) {
1484         var me = this,
1485             classes = [],
1486             i;
1487
1488         if (!Ext.isArray(cls)) {
1489             cls = [cls];
1490         }
1491
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]);
1496
1497                 classes = classes.concat(me.addUIClsToElement(cls[i]));
1498             }
1499         }
1500
1501         if (skip !== true) {
1502             me.addCls(classes);
1503         }
1504
1505         return classes;
1506     },
1507
1508     /**
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
1512      */
1513     removeClsWithUI: function(cls, skip) {
1514         var me = this,
1515             classes = [],
1516             i;
1517
1518         if (!Ext.isArray(cls)) {
1519             cls = [cls];
1520         }
1521
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]);
1525
1526                 classes = classes.concat(me.removeUIClsFromElement(cls[i]));
1527             }
1528         }
1529
1530         if (skip !== true) {
1531             me.removeCls(classes);
1532         }
1533
1534         return classes;
1535     },
1536
1537     /**
1538      * Checks if there is currently a specified uiCls
1539      * @param {String} cls The cls to check
1540      */
1541     hasUICls: function(cls) {
1542         var me = this,
1543             uiCls = me.uiCls || [];
1544
1545         return Ext.Array.contains(uiCls, cls);
1546     },
1547
1548     /**
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
1552      */
1553     addUIClsToElement: function(cls, force) {
1554         var me = this,
1555             result = [],
1556             frameElementCls = me.frameElementCls;
1557         
1558         result.push(Ext.baseCSSPrefix + cls);
1559         result.push(me.baseCls + '-' + cls);
1560         result.push(me.baseCls + '-' + me.ui + '-' + cls);
1561         
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'],
1565                 classes, i, j, el;
1566
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]];
1571                 if (el && el.dom) {
1572                     el.addCls(classes);
1573                 } else {
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]);
1577                         }
1578                     }
1579                 }
1580             }
1581         }
1582
1583         me.frameElementCls = frameElementCls;
1584
1585         return result;
1586     },
1587
1588     /**
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
1592      */
1593     removeUIClsFromElement: function(cls, force) {
1594         var me = this,
1595             result = [],
1596             frameElementCls = me.frameElementCls;
1597         
1598         result.push(Ext.baseCSSPrefix + cls);
1599         result.push(me.baseCls + '-' + cls);
1600         result.push(me.baseCls + '-' + me.ui + '-' + cls);
1601         
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'],
1605                 i, el;
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()];
1610                 if (el && el.dom) {
1611                     el.removeCls(cls);
1612                 } else {
1613                     Ext.Array.remove(frameElementCls[els[i]], cls);
1614                 }
1615             }
1616         }
1617
1618         me.frameElementCls = frameElementCls;
1619
1620         return result;
1621     },
1622
1623     /**
1624      * Method which adds a specified UI to the components element.
1625      * @private
1626      */
1627     addUIToElement: function(force) {
1628         var me = this,
1629             frameElementCls = me.frameElementCls;
1630         
1631         me.addCls(me.baseCls + '-' + me.ui);
1632         
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'],
1636                 i, el, cls;
1637             
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];
1642                 if (el) {
1643                     el.addCls(cls);
1644                 } else {
1645                     if (!Ext.Array.contains(frameElementCls[els[i]], cls)) {
1646                         frameElementCls[els[i]].push(cls);
1647                     }
1648                 }
1649             }
1650         }
1651     },
1652
1653     /**
1654      * Method which removes a specified UI from the components element.
1655      * @private
1656      */
1657     removeUIFromElement: function() {
1658         var me = this,
1659             frameElementCls = me.frameElementCls;
1660         
1661         me.removeCls(me.baseCls + '-' + me.ui);
1662         
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'],
1666                 i, j, el, cls;
1667                 
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];
1672
1673                 if (el) {
1674                     el.removeCls(cls);
1675                 } else {
1676                     Ext.Array.remove(frameElementCls[els[i]], cls);
1677                 }
1678             }
1679         }
1680     },
1681
1682     getElConfig : function() {
1683         var result = this.autoEl || {tag: 'div'};
1684         result.id = this.id;
1685         return result;
1686     },
1687
1688     /**
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
1694      */
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];
1700             }
1701             else {
1702                 position = Ext.getDom(position);
1703             }
1704         }
1705
1706         return position;
1707     },
1708
1709     /**
1710      * Adds ctCls to container.
1711      * @return {Ext.core.Element} The initialized container
1712      * @private
1713      */
1714     initContainer: function(container) {
1715         var me = this;
1716
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;
1723         }
1724
1725         me.container = Ext.get(container);
1726
1727         if (me.ctCls) {
1728             me.container.addCls(me.ctCls);
1729         }
1730
1731         return me.container;
1732     },
1733
1734     /**
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
1737      * @private
1738      */
1739     initRenderData: function() {
1740         var me = this;
1741
1742         return Ext.applyIf(me.renderData, {
1743             ui: me.ui,
1744             uiCls: me.uiCls,
1745             baseCls: me.baseCls,
1746             componentCls: me.componentCls,
1747             frame: me.frame
1748         });
1749     },
1750
1751     /**
1752      * @private
1753      */
1754     getTpl: function(name) {
1755         var me = this,
1756             prototype = me.self.prototype,
1757             ownerPrototype,
1758             tpl;
1759
1760         if (me.hasOwnProperty(name)) {
1761             tpl = me[name];
1762             if (tpl && !(tpl instanceof Ext.XTemplate)) {
1763                 me[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl);
1764             }
1765
1766             return me[name];
1767         }
1768
1769         if (!(prototype[name] instanceof Ext.XTemplate)) {
1770             ownerPrototype = prototype;
1771
1772             do {
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);
1777                         break;
1778                     }
1779                 }
1780
1781                 ownerPrototype = ownerPrototype.superclass;
1782             } while (ownerPrototype);
1783         }
1784
1785         return prototype[name];
1786     },
1787
1788     /**
1789      * Initializes the renderTpl.
1790      * @return {Ext.XTemplate} The renderTpl XTemplate instance.
1791      * @private
1792      */
1793     initRenderTpl: function() {
1794         return this.getTpl('renderTpl');
1795     },
1796
1797     /**
1798      * Function description
1799      * @return {String} A CSS style string with style, padding, margin and border.
1800      * @private
1801      */
1802     initStyles: function() {
1803         var style = {},
1804             me = this,
1805             Element = Ext.core.Element;
1806
1807         if (Ext.isString(me.style)) {
1808             style = Element.parseStyles(me.style);
1809         } else {
1810             style = Ext.apply({}, me.style);
1811         }
1812
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);
1817         }
1818
1819         if (me.margin !== undefined) {
1820             style.margin = Element.unitizeBox((me.margin === true) ? 5 : me.margin);
1821         }
1822
1823         delete me.style;
1824         return style;
1825     },
1826
1827     /**
1828      * Initializes this components contents. It checks for the properties
1829      * html, contentEl and tpl/data.
1830      * @private
1831      */
1832     initContent: function() {
1833         var me = this,
1834             target = me.getTargetEl(),
1835             contentEl,
1836             pre;
1837
1838         if (me.html) {
1839             target.update(Ext.core.DomHelper.markup(me.html));
1840             delete me.html;
1841         }
1842
1843         if (me.contentEl) {
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);
1848         }
1849
1850         if (me.tpl) {
1851             // Make sure this.tpl is an instantiated XTemplate
1852             if (!me.tpl.isTemplate) {
1853                 me.tpl = Ext.create('Ext.XTemplate', me.tpl);
1854             }
1855
1856             if (me.data) {
1857                 me.tpl[me.tplWriteMode](target, me.data);
1858                 delete me.data;
1859             }
1860         }
1861     },
1862
1863     // @private
1864     initEvents : function() {
1865         var me = this,
1866             afterRenderEvents = me.afterRenderEvents,
1867             el,
1868             property,
1869             fn = function(listeners){
1870                 me.mon(el, listeners);
1871             };
1872         if (afterRenderEvents) {
1873             for (property in afterRenderEvents) {
1874                 if (afterRenderEvents.hasOwnProperty(property)) {
1875                     el = me[property];
1876                     if (el && el.on) {
1877                         Ext.each(afterRenderEvents[property], fn);
1878                     }
1879                 }
1880             }
1881         }
1882     },
1883
1884     /**
1885      * Sets references to elements inside the component. E.g body -> x-panel-body
1886      * @private
1887      */
1888     applyRenderSelectors: function() {
1889         var selectors = this.renderSelectors || {},
1890             el = this.el.dom,
1891             selector;
1892
1893         for (selector in selectors) {
1894             if (selectors.hasOwnProperty(selector) && selectors[selector]) {
1895                 this[selector] = Ext.get(Ext.DomQuery.selectNode(selectors[selector], el));
1896             }
1897         }
1898     },
1899
1900     /**
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.
1904      */
1905     is: function(selector) {
1906         return Ext.ComponentQuery.is(this, selector);
1907     },
1908
1909     /**
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');
1914 </code></pre>
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).
1917      */
1918     up: function(selector) {
1919         var result = this.ownerCt;
1920         if (selector) {
1921             for (; result; result = result.ownerCt) {
1922                 if (Ext.ComponentQuery.is(result, selector)) {
1923                     return result;
1924                 }
1925             }
1926         }
1927         return result;
1928     },
1929
1930     /**
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.
1937      */
1938     nextSibling: function(selector) {
1939         var o = this.ownerCt, it, last, idx, c;
1940         if (o) {
1941             it = o.items;
1942             idx = it.indexOf(this) + 1;
1943             if (idx) {
1944                 if (selector) {
1945                     for (last = it.getCount(); idx < last; idx++) {
1946                         if ((c = it.getAt(idx)).is(selector)) {
1947                             return c;
1948                         }
1949                     }
1950                 } else {
1951                     if (idx < it.getCount()) {
1952                         return it.getAt(idx);
1953                     }
1954                 }
1955             }
1956         }
1957         return null;
1958     },
1959
1960     /**
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.
1967      */
1968     previousSibling: function(selector) {
1969         var o = this.ownerCt, it, idx, c;
1970         if (o) {
1971             it = o.items;
1972             idx = it.indexOf(this);
1973             if (idx != -1) {
1974                 if (selector) {
1975                     for (--idx; idx >= 0; idx--) {
1976                         if ((c = it.getAt(idx)).is(selector)) {
1977                             return c;
1978                         }
1979                     }
1980                 } else {
1981                     if (idx) {
1982                         return it.getAt(--idx);
1983                     }
1984                 }
1985             }
1986         }
1987         return null;
1988     },
1989
1990     /**
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.
1996      */
1997     previousNode: function(selector, includeSelf) {
1998         var node = this,
1999             result,
2000             it, len, i;
2001
2002         // If asked to include self, test me
2003         if (includeSelf && node.is(selector)) {
2004             return node;
2005         }
2006
2007         result = this.prev(selector);
2008         if (result) {
2009             return result;
2010         }
2011
2012         if (node.ownerCt) {
2013             for (it = node.ownerCt.items.items, i = Ext.Array.indexOf(it, node) - 1; i > -1; i--) {
2014                 if (it[i].query) {
2015                     result = it[i].query(selector);
2016                     result = result[result.length - 1];
2017                     if (result) {
2018                         return result;
2019                     }
2020                 }
2021             }
2022             return node.ownerCt.previousNode(selector, true);
2023         }
2024     },
2025
2026     /**
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.
2032      */
2033     nextNode: function(selector, includeSelf) {
2034         var node = this,
2035             result,
2036             it, len, i;
2037
2038         // If asked to include self, test me
2039         if (includeSelf && node.is(selector)) {
2040             return node;
2041         }
2042
2043         result = this.next(selector);
2044         if (result) {
2045             return result;
2046         }
2047
2048         if (node.ownerCt) {
2049             for (it = node.ownerCt.items, i = it.indexOf(node) + 1, it = it.items, len = it.length; i < len; i++) {
2050                 if (it[i].down) {
2051                     result = it[i].down(selector);
2052                     if (result) {
2053                         return result;
2054                     }
2055                 }
2056             }
2057             return node.ownerCt.nextNode(selector);
2058         }
2059     },
2060
2061     /**
2062      * Retrieves the id of this component.
2063      * Will autogenerate an id if one has not already been set.
2064      */
2065     getId : function() {
2066         return this.id || (this.id = 'ext-comp-' + (this.getAutoId()));
2067     },
2068
2069     getItemId : function() {
2070         return this.itemId || this.id;
2071     },
2072
2073     /**
2074      * Retrieves the top level element representing this component.
2075      */
2076     getEl : function() {
2077         return this.el;
2078     },
2079
2080     /**
2081      * This is used to determine where to insert the 'html', 'contentEl' and 'items' in this component.
2082      * @private
2083      */
2084     getTargetEl: function() {
2085         return this.frameBody || this.el;
2086     },
2087
2088     /**
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>
2095      * <pre><code>
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
2100 </code></pre>
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.
2105      */
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
2114         }
2115
2116         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1: this.self.xtype == xtype;
2117     },
2118
2119     /**
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>
2125      * <pre><code>
2126 var t = new Ext.form.field.Text();
2127 alert(t.getXTypes());  // alerts 'component/field/textfield'
2128 </code></pre>
2129      * @return {String} The xtype hierarchy string
2130      */
2131     getXTypes: function() {
2132         var self = this.self,
2133             xtypes      = [],
2134             parentPrototype  = this,
2135             xtype;
2136
2137         if (!self.xtypes) {
2138             while (parentPrototype && Ext.getClass(parentPrototype)) {
2139                 xtype = Ext.getClass(parentPrototype).xtype;
2140
2141                 if (xtype !== undefined) {
2142                     xtypes.unshift(xtype);
2143                 }
2144
2145                 parentPrototype = parentPrototype.superclass;
2146             }
2147
2148             self.xtypeChain = xtypes;
2149             self.xtypes = xtypes.join('/');
2150         }
2151
2152         return self.xtypes;
2153     },
2154
2155     /**
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
2166      */
2167     update : function(htmlOrData, loadScripts, cb) {
2168         var me = this;
2169
2170         if (me.tpl && !Ext.isString(htmlOrData)) {
2171             me.data = htmlOrData;
2172             if (me.rendered) {
2173                 me.tpl[me.tplWriteMode](me.getTargetEl(), htmlOrData || {});
2174             }
2175         } else {
2176             me.html = Ext.isObject(htmlOrData) ? Ext.core.DomHelper.markup(htmlOrData) : htmlOrData;
2177             if (me.rendered) {
2178                 me.getTargetEl().update(me.html, loadScripts, cb);
2179             }
2180         }
2181
2182         if (me.rendered) {
2183             me.doComponentLayout();
2184         }
2185     },
2186
2187     /**
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
2191      */
2192     setVisible : function(visible) {
2193         return this[visible ? 'show': 'hide']();
2194     },
2195
2196     /**
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.
2203      */
2204     isVisible: function(deep) {
2205         var me = this,
2206             child = me,
2207             visible = !me.hidden,
2208             ancestor = me.ownerCt;
2209
2210         // Clear hiddenOwnerCt property
2211         me.hiddenAncestor = false;
2212         if (me.destroyed) {
2213             return false;
2214         }
2215
2216         if (deep && visible && me.rendered && ancestor) {
2217             while (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;
2226                     visible = false;
2227                     break;
2228                 }
2229                 child = ancestor;
2230                 ancestor = ancestor.ownerCt;
2231             }
2232         }
2233         return visible;
2234     },
2235
2236     /**
2237      * Enable the component
2238      * @param {Boolean} silent
2239      * Passing false will supress the 'enable' event from being fired.
2240      */
2241     enable: function(silent) {
2242         var me = this;
2243
2244         if (me.rendered) {
2245             me.el.removeCls(me.disabledCls);
2246             me.el.dom.disabled = false;
2247             me.onEnable();
2248         }
2249
2250         me.disabled = false;
2251
2252         if (silent !== true) {
2253             me.fireEvent('enable', me);
2254         }
2255
2256         return me;
2257     },
2258
2259     /**
2260      * Disable the component.
2261      * @param {Boolean} silent
2262      * Passing true, will supress the 'disable' event from being fired.
2263      */
2264     disable: function(silent) {
2265         var me = this;
2266
2267         if (me.rendered) {
2268             me.el.addCls(me.disabledCls);
2269             me.el.dom.disabled = true;
2270             me.onDisable();
2271         }
2272
2273         me.disabled = true;
2274
2275         if (silent !== true) {
2276             me.fireEvent('disable', me);
2277         }
2278
2279         return me;
2280     },
2281
2282     // @private
2283     onEnable: function() {
2284         if (this.maskOnDisable) {
2285             this.el.unmask();
2286         }
2287     },
2288
2289     // @private
2290     onDisable : function() {
2291         if (this.maskOnDisable) {
2292             this.el.mask();
2293         }
2294     },
2295
2296     /**
2297      * Method to determine whether this Component is currently disabled.
2298      * @return {Boolean} the disabled state of this Component.
2299      */
2300     isDisabled : function() {
2301         return this.disabled;
2302     },
2303
2304     /**
2305      * Enable or disable the component.
2306      * @param {Boolean} disabled
2307      */
2308     setDisabled : function(disabled) {
2309         return this[disabled ? 'disable': 'enable']();
2310     },
2311
2312     /**
2313      * Method to determine whether this Component is currently set to hidden.
2314      * @return {Boolean} the hidden state of this Component.
2315      */
2316     isHidden : function() {
2317         return this.hidden;
2318     },
2319
2320     /**
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.
2324      */
2325     addCls : function(className) {
2326         var me = this;
2327         if (!className) {
2328             return me;
2329         }
2330         if (!Ext.isArray(className)){
2331             className = className.replace(me.trimRe, '').split(me.spacesRe);
2332         }
2333         if (me.rendered) {
2334             me.el.addCls(className);
2335         }
2336         else {
2337             me.additionalCls = Ext.Array.unique(me.additionalCls.concat(className));
2338         }
2339         return me;
2340     },
2341
2342     /**
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.
2347      */
2348     addClass : function() {
2349         return this.addCls.apply(this, arguments);
2350     },
2351
2352     /**
2353      * Removes a CSS class from the top level element representing this component.
2354      * @returns {Ext.Component} Returns the Component to allow method chaining.
2355      */
2356     removeCls : function(className) {
2357         var me = this;
2358
2359         if (!className) {
2360             return me;
2361         }
2362         if (!Ext.isArray(className)){
2363             className = className.replace(me.trimRe, '').split(me.spacesRe);
2364         }
2365         if (me.rendered) {
2366             me.el.removeCls(className);
2367         }
2368         else if (me.additionalCls.length) {
2369             Ext.each(className, function(cls) {
2370                 Ext.Array.remove(me.additionalCls, cls);
2371             });
2372         }
2373         return me;
2374     },
2375
2376     //<debug>
2377     removeClass : function() {
2378         if (Ext.isDefined(Ext.global.console)) {
2379             Ext.global.console.warn('Ext.Component: removeClass has been deprecated. Please use removeCls.');
2380         }
2381         return this.removeCls.apply(this, arguments);
2382     },
2383     //</debug>
2384
2385     addOverCls: function() {
2386         var me = this;
2387         if (!me.disabled) {
2388             me.el.addCls(me.overCls);
2389         }
2390     },
2391
2392     removeOverCls: function() {
2393         this.el.removeCls(this.overCls);
2394     },
2395
2396     addListener : function(element, listeners, scope, options) {
2397         var me = this,
2398             fn,
2399             option;
2400
2401         if (Ext.isString(element) && (Ext.isObject(listeners) || options && options.element)) {
2402             if (options.element) {
2403                 fn = listeners;
2404
2405                 listeners = {};
2406                 listeners[element] = fn;
2407                 element = options.element;
2408                 if (scope) {
2409                     listeners.scope = scope;
2410                 }
2411
2412                 for (option in options) {
2413                     if (options.hasOwnProperty(option)) {
2414                         if (me.eventOptionsRe.test(option)) {
2415                             listeners[option] = options[option];
2416                         }
2417                     }
2418                 }
2419             }
2420
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);
2425             } else {
2426                 me.afterRenderEvents = me.afterRenderEvents || {};
2427                 if (!me.afterRenderEvents[element]) {
2428                     me.afterRenderEvents[element] = [];
2429                 }
2430                 me.afterRenderEvents[element].push(listeners);
2431             }
2432         }
2433
2434         return me.mixins.observable.addListener.apply(me, arguments);
2435     },
2436
2437     // inherit docs
2438     removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){
2439         var me = this,
2440             element = managedListener.options ? managedListener.options.element : null;
2441
2442         if (element) {
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);
2447                     if (!isClear) {
2448                         Ext.Array.remove(me.managedListeners, managedListener);
2449                     }
2450                 }
2451             }
2452         } else {
2453             return me.mixins.observable.removeManagedListenerItem.apply(me, arguments);
2454         }
2455     },
2456
2457     /**
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.
2460      */
2461     getBubbleTarget : function() {
2462         return this.ownerCt;
2463     },
2464
2465     /**
2466      * Method to determine whether this Component is floating.
2467      * @return {Boolean} the floating state of this component.
2468      */
2469     isFloating : function() {
2470         return this.floating;
2471     },
2472
2473     /**
2474      * Method to determine whether this Component is draggable.
2475      * @return {Boolean} the draggable state of this component.
2476      */
2477     isDraggable : function() {
2478         return !!this.draggable;
2479     },
2480
2481     /**
2482      * Method to determine whether this Component is droppable.
2483      * @return {Boolean} the droppable state of this component.
2484      */
2485     isDroppable : function() {
2486         return !!this.droppable;
2487     },
2488
2489     /**
2490      * @private
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
2496      */
2497     onAdded : function(container, pos) {
2498         this.ownerCt = container;
2499         this.fireEvent('added', this, container, pos);
2500     },
2501
2502     /**
2503      * @private
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.
2507      */
2508     onRemoved : function() {
2509         var me = this;
2510
2511         me.fireEvent('removed', me, me.ownerCt);
2512         delete me.ownerCt;
2513     },
2514
2515     // @private
2516     beforeDestroy : Ext.emptyFn,
2517     // @private
2518     // @private
2519     onResize : Ext.emptyFn,
2520
2521     /**
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>
2529      * </ul></div>
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>
2535      * </ul></div>
2536      * @return {Ext.Component} this
2537      */
2538     setSize : function(width, height) {
2539         var me = this,
2540             layoutCollection;
2541
2542         // support for standard size objects
2543         if (Ext.isObject(width)) {
2544             height = width.height;
2545             width  = width.width;
2546         }
2547
2548         // Constrain within configured maxima
2549         if (Ext.isNumber(width)) {
2550             width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
2551         }
2552         if (Ext.isNumber(height)) {
2553             height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
2554         }
2555
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);
2562             }
2563             me.needsLayout = {
2564                 width: width,
2565                 height: height,
2566                 isSetSize: true
2567             };
2568             if (!me.rendered) {
2569                 me.width  = (width !== undefined) ? width : me.width;
2570                 me.height = (height !== undefined) ? height : me.height;
2571             }
2572             return me;
2573         }
2574         me.doComponentLayout(width, height, true);
2575
2576         return me;
2577     },
2578
2579     isFixedWidth: function() {
2580         var me = this,
2581             layoutManagedWidth = me.layoutManagedWidth;
2582
2583         if (Ext.isDefined(me.width) || layoutManagedWidth == 1) {
2584             return true;
2585         }
2586         if (layoutManagedWidth == 2) {
2587             return false;
2588         }
2589         return (me.ownerCt && me.ownerCt.isFixedWidth());
2590     },
2591
2592     isFixedHeight: function() {
2593         var me = this,
2594             layoutManagedHeight = me.layoutManagedHeight;
2595
2596         if (Ext.isDefined(me.height) || layoutManagedHeight == 1) {
2597             return true;
2598         }
2599         if (layoutManagedHeight == 2) {
2600             return false;
2601         }
2602         return (me.ownerCt && me.ownerCt.isFixedHeight());
2603     },
2604
2605     setCalculatedSize : function(width, height, callingContainer) {
2606         var me = this,
2607             layoutCollection;
2608
2609         // support for standard size objects
2610         if (Ext.isObject(width)) {
2611             callingContainer = width.ownerCt;
2612             height = width.height;
2613             width  = width.width;
2614         }
2615
2616         // Constrain within configured maxima
2617         if (Ext.isNumber(width)) {
2618             width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
2619         }
2620         if (Ext.isNumber(height)) {
2621             height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
2622         }
2623
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);
2630             }
2631             me.needsLayout = {
2632                 width: width,
2633                 height: height,
2634                 isSetSize: false,
2635                 ownerCt: callingContainer
2636             };
2637             return me;
2638         }
2639         me.doComponentLayout(width, height, false, callingContainer);
2640
2641         return me;
2642     },
2643
2644     /**
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
2648      */
2649     doComponentLayout : function(width, height, isSetSize, callingContainer) {
2650         var me = this,
2651             componentLayout = me.getComponentLayout(),
2652             lastComponentSize = componentLayout.lastComponentSize || {
2653                 width: undefined,
2654                 height: undefined
2655             };
2656
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) {
2661
2662
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;
2667                 }
2668             }
2669
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;
2674                 }
2675             }
2676
2677             if (isSetSize) {
2678                 me.width = width;
2679                 me.height = height;
2680             }
2681
2682             componentLayout.layout(width, height, isSetSize, callingContainer);
2683         }
2684         return me;
2685     },
2686
2687     /**
2688      * Forces this component to redo its componentLayout.
2689      */
2690     forceComponentLayout: function () {
2691         this.doComponentLayout();
2692     },
2693
2694     // @private
2695     setComponentLayout : function(layout) {
2696         var currentLayout = this.componentLayout;
2697         if (currentLayout && currentLayout.isLayout && currentLayout != layout) {
2698             currentLayout.setOwner(null);
2699         }
2700         this.componentLayout = layout;
2701         layout.setOwner(this);
2702     },
2703
2704     getComponentLayout : function() {
2705         var me = this;
2706
2707         if (!me.componentLayout || !me.componentLayout.isLayout) {
2708             me.setComponentLayout(Ext.layout.Layout.create(me.componentLayout, 'autocomponent'));
2709         }
2710         return me.componentLayout;
2711     },
2712
2713     /**
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.
2718      */
2719     afterComponentLayout: function(width, height, isSetSize, callingContainer) {
2720         this.fireEvent('resize', this, width, height);
2721     },
2722
2723     /**
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.
2730      */
2731     beforeComponentLayout: function(width, height, isSetSize, callingContainer) {
2732         return true;
2733     },
2734
2735     /**
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
2742      */
2743     setPosition : function(x, y) {
2744         var me = this;
2745
2746         if (Ext.isObject(x)) {
2747             y = x.y;
2748             x = x.x;
2749         }
2750
2751         if (!me.rendered) {
2752             return me;
2753         }
2754
2755         if (x !== undefined || y !== undefined) {
2756             me.el.setBox(x, y);
2757             me.onPosition(x, y);
2758             me.fireEvent('move', me, x, y);
2759         }
2760         return me;
2761     },
2762
2763     /* @private
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
2768      */
2769     onPosition: Ext.emptyFn,
2770
2771     /**
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>
2776      * </ul></div>
2777      * @return {Ext.Component} this
2778      */
2779     setWidth : function(width) {
2780         return this.setSize(width);
2781     },
2782
2783     /**
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>
2789      * </ul></div>
2790      * @return {Ext.Component} this
2791      */
2792     setHeight : function(height) {
2793         return this.setSize(undefined, height);
2794     },
2795
2796     /**
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)}
2799      */
2800     getSize : function() {
2801         return this.el.getSize();
2802     },
2803
2804     /**
2805      * Gets the current width of the component's underlying element.
2806      * @return {Number}
2807      */
2808     getWidth : function() {
2809         return this.el.getWidth();
2810     },
2811
2812     /**
2813      * Gets the current height of the component's underlying element.
2814      * @return {Number}
2815      */
2816     getHeight : function() {
2817         return this.el.getHeight();
2818     },
2819
2820     /**
2821      * Gets the {@link Ext.ComponentLoader} for this Component.
2822      * @return {Ext.ComponentLoader} The loader instance, null if it doesn't exist.
2823      */
2824     getLoader: function(){
2825         var me = this,
2826             autoLoad = me.autoLoad ? (Ext.isObject(me.autoLoad) ? me.autoLoad : {url: me.autoLoad}) : null,
2827             loader = me.loader || autoLoad;
2828
2829         if (loader) {
2830             if (!loader.isLoader) {
2831                 me.loader = Ext.create('Ext.ComponentLoader', Ext.apply({
2832                     target: me,
2833                     autoLoad: autoLoad
2834                 }, loader));
2835             } else {
2836                 loader.setTarget(me);
2837             }
2838             return me.loader;
2839
2840         }
2841         return null;
2842     },
2843
2844     /**
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.
2852      */
2853     setLoading : function(load, targetEl) {
2854         var me = this,
2855             config;
2856
2857         if (me.rendered) {
2858             if (load !== false && !me.collapsed) {
2859                 if (Ext.isObject(load)) {
2860                     config = load;
2861                 }
2862                 else if (Ext.isString(load)) {
2863                     config = {msg: load};
2864                 }
2865                 else {
2866                     config = {};
2867                 }
2868                 me.loadMask = me.loadMask || Ext.create('Ext.LoadMask', targetEl ? me.getTargetEl() : me.el, config);
2869                 me.loadMask.show();
2870             } else if (me.loadMask) {
2871                 Ext.destroy(me.loadMask);
2872                 me.loadMask = null;
2873             }
2874         }
2875
2876         return me.loadMask;
2877     },
2878
2879     /**
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
2883      * by default)
2884      * @return {Component} this
2885      */
2886     setDocked : function(dock, layoutParent) {
2887         var me = this;
2888
2889         me.dock = dock;
2890         if (layoutParent && me.ownerCt && me.rendered) {
2891             me.ownerCt.doComponentLayout();
2892         }
2893         return me;
2894     },
2895
2896     onDestroy : function() {
2897         var me = this;
2898
2899         if (me.monitorResize && Ext.EventManager.resizeEvent) {
2900             Ext.EventManager.resizeEvent.removeListener(me.setSize, me);
2901         }
2902         Ext.destroy(me.componentLayout, me.loadMask);
2903     },
2904
2905     /**
2906      * Destroys the Component.
2907      */
2908     destroy : function() {
2909         var me = this;
2910
2911         if (!me.isDestroyed) {
2912             if (me.fireEvent('beforedestroy', me) !== false) {
2913                 me.destroying = true;
2914                 me.beforeDestroy();
2915
2916                 if (me.floating) {
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);
2922                     }
2923                 } else if (me.ownerCt && me.ownerCt.remove) {
2924                     me.ownerCt.remove(me, false);
2925                 }
2926
2927                 me.onDestroy();
2928
2929                 // Attempt to destroy all plugins
2930                 Ext.destroy(me.plugins);
2931
2932                 if (me.rendered) {
2933                     me.el.remove();
2934                 }
2935
2936                 Ext.ComponentManager.unregister(me);
2937                 me.fireEvent('destroy', me);
2938
2939                 me.mixins.state.destroy.call(me);
2940
2941                 me.clearListeners();
2942                 me.destroying = false;
2943                 me.isDestroyed = true;
2944             }
2945         }
2946     },
2947
2948     /**
2949      * Retrieves a plugin by its pluginId which has been bound to this
2950      * component.
2951      * @returns {Ext.AbstractPlugin} pluginInstance
2952      */
2953     getPlugin: function(pluginId) {
2954         var i = 0,
2955             plugins = this.plugins,
2956             ln = plugins.length;
2957         for (; i < ln; i++) {
2958             if (plugins[i].pluginId === pluginId) {
2959                 return plugins[i];
2960             }
2961         }
2962     },
2963
2964     /**
2965      * Determines whether this component is the descendant of a particular container.
2966      * @param {Ext.Container} container
2967      * @returns {Boolean} isDescendant
2968      */
2969     isDescendantOf: function(container) {
2970         return !!this.findParentBy(function(p){
2971             return p === container;
2972         });
2973     }
2974 }, function() {
2975     this.createAlias({
2976         on: 'addListener',
2977         prev: 'previousSibling',
2978         next: 'nextSibling'
2979     });
2980 });
2981