Upgrade to ExtJS 4.0.1 - Released 05/18/2011
[extjs.git] / src / AbstractComponent.js
1 /**
2  * @class Ext.AbstractComponent
3  * <p>An abstract base class which provides shared methods for Components across the Sencha product line.</p>
4  * <p>Please refer to sub class's documentation</p>
5  * @constructor
6  */
7
8 Ext.define('Ext.AbstractComponent', {
9
10     /* Begin Definitions */
11
12     mixins: {
13         observable: 'Ext.util.Observable',
14         animate: 'Ext.util.Animate',
15         state: 'Ext.state.Stateful'
16     },
17
18     requires: [
19         'Ext.PluginManager',
20         'Ext.ComponentManager',
21         'Ext.core.Element',
22         'Ext.core.DomHelper',
23         'Ext.XTemplate',
24         'Ext.ComponentQuery',
25         'Ext.LoadMask',
26         'Ext.ComponentLoader',
27         'Ext.EventManager',
28         'Ext.layout.Layout',
29         'Ext.layout.component.Auto'
30     ],
31
32     // Please remember to add dependencies whenever you use it
33     // I had to fix these many times already
34     uses: [
35         'Ext.ZIndexManager'
36     ],
37
38     statics: {
39         AUTO_ID: 1000
40     },
41
42     /* End Definitions */
43
44     isComponent: true,
45
46     getAutoId: function() {
47         return ++Ext.AbstractComponent.AUTO_ID;
48     },
49
50     /**
51      * @cfg {String} id
52      * <p>The <b><u>unique id of this component instance</u></b> (defaults to an {@link #getId auto-assigned id}).</p>
53      * <p>It should not be necessary to use this configuration except for singleton objects in your application.
54      * Components created with an id may be accessed globally using {@link Ext#getCmp Ext.getCmp}.</p>
55      * <p>Instead of using assigned ids, use the {@link #itemId} config, and {@link Ext.ComponentQuery ComponentQuery} which
56      * provides selector-based searching for Sencha Components analogous to DOM querying. The {@link Ext.container.Container Container}
57      * class contains {@link Ext.container.Container#down shortcut methods} to query its descendant Components by selector.</p>
58      * <p>Note that this id will also be used as the element id for the containing HTML element
59      * that is rendered to the page for this component. This allows you to write id-based CSS
60      * rules to style the specific instance of this component uniquely, and also to select
61      * sub-elements using this component's id as the parent.</p>
62      * <p><b>Note</b>: to avoid complications imposed by a unique <tt>id</tt> also see <code>{@link #itemId}</code>.</p>
63      * <p><b>Note</b>: to access the container of a Component see <code>{@link #ownerCt}</code>.</p>
64      */
65
66     /**
67      * @cfg {String} itemId
68      * <p>An <tt>itemId</tt> can be used as an alternative way to get a reference to a component
69      * when no object reference is available.  Instead of using an <code>{@link #id}</code> with
70      * {@link Ext}.{@link Ext#getCmp getCmp}, use <code>itemId</code> with
71      * {@link Ext.container.Container}.{@link Ext.container.Container#getComponent getComponent} which will retrieve
72      * <code>itemId</code>'s or <tt>{@link #id}</tt>'s. Since <code>itemId</code>'s are an index to the
73      * container's internal MixedCollection, the <code>itemId</code> is scoped locally to the container --
74      * avoiding potential conflicts with {@link Ext.ComponentManager} which requires a <b>unique</b>
75      * <code>{@link #id}</code>.</p>
76      * <pre><code>
77 var c = new Ext.panel.Panel({ //
78     {@link Ext.Component#height height}: 300,
79     {@link #renderTo}: document.body,
80     {@link Ext.container.Container#layout layout}: 'auto',
81     {@link Ext.container.Container#items items}: [
82         {
83             itemId: 'p1',
84             {@link Ext.panel.Panel#title title}: 'Panel 1',
85             {@link Ext.Component#height height}: 150
86         },
87         {
88             itemId: 'p2',
89             {@link Ext.panel.Panel#title title}: 'Panel 2',
90             {@link Ext.Component#height height}: 150
91         }
92     ]
93 })
94 p1 = c.{@link Ext.container.Container#getComponent getComponent}('p1'); // not the same as {@link Ext#getCmp Ext.getCmp()}
95 p2 = p1.{@link #ownerCt}.{@link Ext.container.Container#getComponent getComponent}('p2'); // reference via a sibling
96      * </code></pre>
97      * <p>Also see <tt>{@link #id}</tt>, <code>{@link #query}</code>, <code>{@link #down}</code> and <code>{@link #child}</code>.</p>
98      * <p><b>Note</b>: to access the container of an item see <tt>{@link #ownerCt}</tt>.</p>
99      */
100
101     /**
102      * This Component's owner {@link Ext.container.Container Container} (defaults to undefined, and is set automatically when
103      * this Component is added to a Container).  Read-only.
104      * <p><b>Note</b>: to access items within the Container see <tt>{@link #itemId}</tt>.</p>
105      * @type Ext.Container
106      * @property ownerCt
107      */
108
109     /**
110      * @cfg {Mixed} autoEl
111      * <p>A tag name or {@link Ext.core.DomHelper DomHelper} spec used to create the {@link #getEl Element} which will
112      * encapsulate this Component.</p>
113      * <p>You do not normally need to specify this. For the base classes {@link Ext.Component} and {@link Ext.container.Container},
114      * this defaults to <b><tt>'div'</tt></b>. The more complex Sencha classes use a more complex
115      * DOM structure specified by their own {@link #renderTpl}s.</p>
116      * <p>This is intended to allow the developer to create application-specific utility Components encapsulated by
117      * different DOM elements. Example usage:</p><pre><code>
118 {
119     xtype: 'component',
120     autoEl: {
121         tag: 'img',
122         src: 'http://www.example.com/example.jpg'
123     }
124 }, {
125     xtype: 'component',
126     autoEl: {
127         tag: 'blockquote',
128         html: 'autoEl is cool!'
129     }
130 }, {
131     xtype: 'container',
132     autoEl: 'ul',
133     cls: 'ux-unordered-list',
134     items: {
135         xtype: 'component',
136         autoEl: 'li',
137         html: 'First list item'
138     }
139 }
140 </code></pre>
141      */
142
143     /**
144      * @cfg {Mixed} renderTpl
145      * <p>An {@link Ext.XTemplate XTemplate} used to create the internal structure inside this Component's
146      * encapsulating {@link #getEl Element}.</p>
147      * <p>You do not normally need to specify this. For the base classes {@link Ext.Component}
148      * and {@link Ext.container.Container}, this defaults to <b><code>null</code></b> which means that they will be initially rendered
149      * with no internal structure; they render their {@link #getEl Element} empty. The more specialized ExtJS and Touch classes
150      * which use a more complex DOM structure, provide their own template definitions.</p>
151      * <p>This is intended to allow the developer to create application-specific utility Components with customized
152      * internal structure.</p>
153      * <p>Upon rendering, any created child elements may be automatically imported into object properties using the
154      * {@link #renderSelectors} option.</p>
155      */
156     renderTpl: null,
157
158     /**
159      * @cfg {Object} renderSelectors
160
161 An object containing properties specifying {@link Ext.DomQuery DomQuery} selectors which identify child elements
162 created by the render process.
163
164 After the Component's internal structure is rendered according to the {@link #renderTpl}, this object is iterated through,
165 and the found Elements are added as properties to the Component using the `renderSelector` property name.
166
167 For example, a Component which rendered an image, and description into its element might use the following properties
168 coded into its prototype:
169
170     renderTpl: '&lt;img src="{imageUrl}" class="x-image-component-img">&lt;div class="x-image-component-desc">{description}&gt;/div&lt;',
171
172     renderSelectors: {
173         image: 'img.x-image-component-img',
174         descEl: 'div.x-image-component-desc'
175     }
176
177 After rendering, the Component would have a property <code>image</code> referencing its child `img` Element,
178 and a property `descEl` referencing the `div` Element which contains the description.
179
180      * @markdown
181      */
182
183     /**
184      * @cfg {Mixed} renderTo
185      * <p>Specify the id of the element, a DOM element or an existing Element that this component
186      * will be rendered into.</p><div><ul>
187      * <li><b>Notes</b> : <ul>
188      * <div class="sub-desc">Do <u>not</u> use this option if the Component is to be a child item of
189      * a {@link Ext.container.Container Container}. It is the responsibility of the
190      * {@link Ext.container.Container Container}'s {@link Ext.container.Container#layout layout manager}
191      * to render and manage its child items.</div>
192      * <div class="sub-desc">When using this config, a call to render() is not required.</div>
193      * </ul></li>
194      * </ul></div>
195      * <p>See <code>{@link #render}</code> also.</p>
196      */
197
198     /**
199      * @cfg {Boolean} frame
200      * <p>Specify as <code>true</code> to have the Component inject framing elements within the Component at render time to
201      * provide a graphical rounded frame around the Component content.</p>
202      * <p>This is only necessary when running on outdated, or non standard-compliant browsers such as Microsoft's Internet Explorer
203      * prior to version 9 which do not support rounded corners natively.</p>
204      * <p>The extra space taken up by this framing is available from the read only property {@link #frameSize}.</p>
205      */
206
207     /**
208      * <p>Read-only property indicating the width of any framing elements which were added within the encapsulating element
209      * to provide graphical, rounded borders. See the {@link #frame} config.</p>
210      * <p> This is an object containing the frame width in pixels for all four sides of the Component containing
211      * the following properties:</p><div class="mdetail-params"><ul>
212      * <li><code>top</code> The width of the top framing element in pixels.</li>
213      * <li><code>right</code> The width of the right framing element in pixels.</li>
214      * <li><code>bottom</code> The width of the bottom framing element in pixels.</li>
215      * <li><code>left</code> The width of the left framing element in pixels.</li>
216      * </ul></div>
217      * @property frameSize
218      * @type {Object}
219      */
220
221     /**
222      * @cfg {String/Object} componentLayout
223      * <p>The sizing and positioning of a Component's internal Elements is the responsibility of
224      * the Component's layout manager which sizes a Component's internal structure in response to the Component being sized.</p>
225      * <p>Generally, developers will not use this configuration as all provided Components which need their internal
226      * elements sizing (Such as {@link Ext.form.field.Base input fields}) come with their own componentLayout managers.</p>
227      * <p>The {@link Ext.layout.container.Auto default layout manager} will be used on instances of the base Ext.Component class
228      * which simply sizes the Component's encapsulating element to the height and width specified in the {@link #setSize} method.</p>
229      */
230
231     /**
232      * @cfg {Mixed} tpl
233      * An <bold>{@link Ext.Template}</bold>, <bold>{@link Ext.XTemplate}</bold>
234      * or an array of strings to form an Ext.XTemplate.
235      * Used in conjunction with the <code>{@link #data}</code> and
236      * <code>{@link #tplWriteMode}</code> configurations.
237      */
238
239     /**
240      * @cfg {Mixed} data
241      * The initial set of data to apply to the <code>{@link #tpl}</code> to
242      * update the content area of the Component.
243      */
244
245     /**
246      * @cfg {String} tplWriteMode The Ext.(X)Template method to use when
247      * updating the content area of the Component. Defaults to <code>'overwrite'</code>
248      * (see <code>{@link Ext.XTemplate#overwrite}</code>).
249      */
250     tplWriteMode: 'overwrite',
251
252     /**
253      * @cfg {String} baseCls
254      * The base CSS class to apply to this components's element. This will also be prepended to
255      * elements within this component like Panel's body will get a class x-panel-body. This means
256      * that if you create a subclass of Panel, and you want it to get all the Panels styling for the
257      * element and the body, you leave the baseCls x-panel and use componentCls to add specific styling for this
258      * component.
259      */
260     baseCls: Ext.baseCSSPrefix + 'component',
261
262     /**
263      * @cfg {String} componentCls
264      * CSS Class to be added to a components root level element to give distinction to it
265      * via styling.
266      */
267
268     /**
269      * @cfg {String} cls
270      * An optional extra CSS class that will be added to this component's Element (defaults to '').  This can be
271      * useful for adding customized styles to the component or any of its children using standard CSS rules.
272      */
273
274     /**
275      * @cfg {String} overCls
276      * An optional extra CSS class that will be added to this component's Element when the mouse moves
277      * over the Element, and removed when the mouse moves out. (defaults to '').  This can be
278      * useful for adding customized 'active' or 'hover' styles to the component or any of its children using standard CSS rules.
279      */
280
281     /**
282      * @cfg {String} disabledCls
283      * CSS class to add when the Component is disabled. Defaults to 'x-item-disabled'.
284      */
285     disabledCls: Ext.baseCSSPrefix + 'item-disabled',
286
287     /**
288      * @cfg {String/Array} ui
289      * A set style for a component. Can be a string or an Array of multiple strings (UIs)
290      */
291     ui: 'default',
292     
293     /**
294      * @cfg {Array} uiCls
295      * An array of of classNames which are currently applied to this component
296      * @private
297      */
298     uiCls: [],
299     
300     /**
301      * @cfg {String} style
302      * A custom style specification to be applied to this component's Element.  Should be a valid argument to
303      * {@link Ext.core.Element#applyStyles}.
304      * <pre><code>
305         new Ext.panel.Panel({
306             title: 'Some Title',
307             renderTo: Ext.getBody(),
308             width: 400, height: 300,
309             layout: 'form',
310             items: [{
311                 xtype: 'textarea',
312                 style: {
313                     width: '95%',
314                     marginBottom: '10px'
315                 }
316             },
317             new Ext.button.Button({
318                 text: 'Send',
319                 minWidth: '100',
320                 style: {
321                     marginBottom: '10px'
322                 }
323             })
324             ]
325         });
326      </code></pre>
327      */
328
329     /**
330      * @cfg {Number} width
331      * The width of this component in pixels.
332      */
333
334     /**
335      * @cfg {Number} height
336      * The height of this component in pixels.
337      */
338
339     /**
340      * @cfg {Number/String} border
341      * Specifies the border for this component. The border can be a single numeric value to apply to all sides or
342      * it can be a CSS style specification for each style, for example: '10 5 3 10'.
343      */
344
345     /**
346      * @cfg {Number/String} padding
347      * Specifies the padding for this component. The padding can be a single numeric value to apply to all sides or
348      * it can be a CSS style specification for each style, for example: '10 5 3 10'.
349      */
350
351     /**
352      * @cfg {Number/String} margin
353      * Specifies the margin for this component. The margin can be a single numeric value to apply to all sides or
354      * it can be a CSS style specification for each style, for example: '10 5 3 10'.
355      */
356
357     /**
358      * @cfg {Boolean} hidden
359      * Defaults to false.
360      */
361     hidden: false,
362
363     /**
364      * @cfg {Boolean} disabled
365      * Defaults to false.
366      */
367     disabled: false,
368
369     /**
370      * @cfg {Boolean} draggable
371      * Allows the component to be dragged.
372      */
373
374     /**
375      * Read-only property indicating whether or not the component can be dragged
376      * @property draggable
377      * @type {Boolean}
378      */
379     draggable: false,
380
381     /**
382      * @cfg {Boolean} floating
383      * Create the Component as a floating and use absolute positioning.
384      * Defaults to false.
385      */
386     floating: false,
387
388     /**
389      * @cfg {String} hideMode
390      * A String which specifies how this Component's encapsulating DOM element will be hidden.
391      * Values may be<div class="mdetail-params"><ul>
392      * <li><code>'display'</code> : The Component will be hidden using the <code>display: none</code> style.</li>
393      * <li><code>'visibility'</code> : The Component will be hidden using the <code>visibility: hidden</code> style.</li>
394      * <li><code>'offsets'</code> : The Component will be hidden by absolutely positioning it out of the visible area of the document. This
395      * is useful when a hidden Component must maintain measurable dimensions. Hiding using <code>display</code> results
396      * in a Component having zero dimensions.</li></ul></div>
397      * Defaults to <code>'display'</code>.
398      */
399     hideMode: 'display',
400
401     /**
402      * @cfg {String} contentEl
403      * <p>Optional. Specify an existing HTML element, or the <code>id</code> of an existing HTML element to use as the content
404      * for this component.</p>
405      * <ul>
406      * <li><b>Description</b> :
407      * <div class="sub-desc">This config option is used to take an existing HTML element and place it in the layout element
408      * 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>
409      * <li><b>Notes</b> :
410      * <div class="sub-desc">The specified HTML element is appended to the layout element of the component <i>after any configured
411      * {@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>
412      * <div class="sub-desc">The specified HTML element used will not participate in any <code><b>{@link Ext.container.Container#layout layout}</b></code>
413      * 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>
414      * <div class="sub-desc">Add either the <code>x-hidden</code> or the <code>x-hide-display</code> CSS class to
415      * prevent a brief flicker of the content before it is rendered to the panel.</div></li>
416      * </ul>
417      */
418
419     /**
420      * @cfg {String/Object} html
421      * An HTML fragment, or a {@link Ext.core.DomHelper DomHelper} specification to use as the layout element
422      * content (defaults to ''). The HTML content is added after the component is rendered,
423      * so the document will not contain this HTML at the time the {@link #render} event is fired.
424      * This content is inserted into the body <i>before</i> any configured {@link #contentEl} is appended.
425      */
426
427     /**
428      * @cfg {Boolean} styleHtmlContent
429      * True to automatically style the html inside the content target of this component (body for panels).
430      * Defaults to false.
431      */
432     styleHtmlContent: false,
433
434     /**
435      * @cfg {String} styleHtmlCls
436      * The class that is added to the content target when you set styleHtmlContent to true.
437      * Defaults to 'x-html'
438      */
439     styleHtmlCls: Ext.baseCSSPrefix + 'html',
440
441     /**
442      * @cfg {Number} minHeight
443      * <p>The minimum value in pixels which this Component will set its height to.</p>
444      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
445      */
446     /**
447      * @cfg {Number} minWidth
448      * <p>The minimum value in pixels which this Component will set its width to.</p>
449      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
450      */
451     /**
452      * @cfg {Number} maxHeight
453      * <p>The maximum value in pixels which this Component will set its height to.</p>
454      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
455      */
456     /**
457      * @cfg {Number} maxWidth
458      * <p>The maximum value in pixels which this Component will set its width to.</p>
459      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
460      */
461
462     /**
463      * @cfg {Ext.ComponentLoader/Object} loader
464      * A configuration object or an instance of a {@link Ext.ComponentLoader} to load remote
465      * content for this Component.
466      */
467
468      // @private
469      allowDomMove: true,
470
471      /**
472       * @cfg {Boolean} autoShow True to automatically show the component upon creation.
473       * This config option may only be used for {@link #floating} components or components
474       * that use {@link #autoRender}. Defaults to <tt>false</tt>.
475       */
476      autoShow: false,
477
478     /**
479      * @cfg {Mixed} autoRender
480      * <p>This config is intended mainly for {@link #floating} Components which may or may not be shown. Instead
481      * of using {@link #renderTo} in the configuration, and rendering upon construction, this allows a Component
482      * to render itself upon first <i>{@link #show}</i>.</p>
483      * <p>Specify as <code>true</code> to have this Component render to the document body upon first show.</p>
484      * <p>Specify as an element, or the ID of an element to have this Component render to a specific element upon first show.</p>
485      * <p><b>This defaults to <code>true</code> for the {@link Ext.window.Window Window} class.</b></p>
486      */
487      autoRender: false,
488
489      needsLayout: false,
490
491     /**
492      * @cfg {Object/Array} plugins
493      * An object or array of objects that will provide custom functionality for this component.  The only
494      * requirement for a valid plugin is that it contain an init method that accepts a reference of type Ext.Component.
495      * When a component is created, if any plugins are available, the component will call the init method on each
496      * plugin, passing a reference to itself.  Each plugin can then call methods or respond to events on the
497      * component as needed to provide its functionality.
498      */
499
500     /**
501      * Read-only property indicating whether or not the component has been rendered.
502      * @property rendered
503      * @type {Boolean}
504      */
505     rendered: false,
506
507     weight: 0,
508
509     trimRe: /^\s+|\s+$/g,
510     spacesRe: /\s+/,
511     
512     
513     /**
514      * This is an internal flag that you use when creating custom components.
515      * By default this is set to true which means that every component gets a mask when its disabled.
516      * Components like FieldContainer, FieldSet, Field, Button, Tab override this property to false
517      * since they want to implement custom disable logic.
518      * @property maskOnDisable
519      * @type {Boolean}
520      */     
521     maskOnDisable: true,
522
523     constructor : function(config) {
524         var me = this,
525             i, len;
526
527         config = config || {};
528         me.initialConfig = config;
529         Ext.apply(me, config);
530
531         me.addEvents(
532             /**
533              * @event beforeactivate
534              * Fires before a Component has been visually activated.
535              * Returning false from an event listener can prevent the activate
536              * from occurring.
537              * @param {Ext.Component} this
538              */
539              'beforeactivate',
540             /**
541              * @event activate
542              * Fires after a Component has been visually activated.
543              * @param {Ext.Component} this
544              */
545              'activate',
546             /**
547              * @event beforedeactivate
548              * Fires before a Component has been visually deactivated.
549              * Returning false from an event listener can prevent the deactivate
550              * from occurring.
551              * @param {Ext.Component} this
552              */
553              'beforedeactivate',
554             /**
555              * @event deactivate
556              * Fires after a Component has been visually deactivated.
557              * @param {Ext.Component} this
558              */
559              'deactivate',
560             /**
561              * @event added
562              * Fires after a Component had been added to a Container.
563              * @param {Ext.Component} this
564              * @param {Ext.container.Container} container Parent Container
565              * @param {Number} pos position of Component
566              */
567              'added',
568             /**
569              * @event disable
570              * Fires after the component is disabled.
571              * @param {Ext.Component} this
572              */
573              'disable',
574             /**
575              * @event enable
576              * Fires after the component is enabled.
577              * @param {Ext.Component} this
578              */
579              'enable',
580             /**
581              * @event beforeshow
582              * Fires before the component is shown when calling the {@link #show} method.
583              * Return false from an event handler to stop the show.
584              * @param {Ext.Component} this
585              */
586              'beforeshow',
587             /**
588              * @event show
589              * Fires after the component is shown when calling the {@link #show} method.
590              * @param {Ext.Component} this
591              */
592              'show',
593             /**
594              * @event beforehide
595              * Fires before the component is hidden when calling the {@link #hide} method.
596              * Return false from an event handler to stop the hide.
597              * @param {Ext.Component} this
598              */
599              'beforehide',
600             /**
601              * @event hide
602              * Fires after the component is hidden.
603              * Fires after the component is hidden when calling the {@link #hide} method.
604              * @param {Ext.Component} this
605              */
606              'hide',
607             /**
608              * @event removed
609              * Fires when a component is removed from an Ext.container.Container
610              * @param {Ext.Component} this
611              * @param {Ext.container.Container} ownerCt Container which holds the component
612              */
613              'removed',
614             /**
615              * @event beforerender
616              * Fires before the component is {@link #rendered}. Return false from an
617              * event handler to stop the {@link #render}.
618              * @param {Ext.Component} this
619              */
620              'beforerender',
621             /**
622              * @event render
623              * Fires after the component markup is {@link #rendered}.
624              * @param {Ext.Component} this
625              */
626              'render',
627             /**
628              * @event afterrender
629              * <p>Fires after the component rendering is finished.</p>
630              * <p>The afterrender event is fired after this Component has been {@link #rendered}, been postprocesed
631              * by any afterRender method defined for the Component.</p>
632              * @param {Ext.Component} this
633              */
634              'afterrender',
635             /**
636              * @event beforedestroy
637              * Fires before the component is {@link #destroy}ed. Return false from an event handler to stop the {@link #destroy}.
638              * @param {Ext.Component} this
639              */
640              'beforedestroy',
641             /**
642              * @event destroy
643              * Fires after the component is {@link #destroy}ed.
644              * @param {Ext.Component} this
645              */
646              'destroy',
647             /**
648              * @event resize
649              * Fires after the component is resized.
650              * @param {Ext.Component} this
651              * @param {Number} adjWidth The box-adjusted width that was set
652              * @param {Number} adjHeight The box-adjusted height that was set
653              */
654              'resize',
655             /**
656              * @event move
657              * Fires after the component is moved.
658              * @param {Ext.Component} this
659              * @param {Number} x The new x position
660              * @param {Number} y The new y position
661              */
662              'move'
663         );
664
665         me.getId();
666
667         me.mons = [];
668         me.additionalCls = [];
669         me.renderData = me.renderData || {};
670         me.renderSelectors = me.renderSelectors || {};
671
672         if (me.plugins) {
673             me.plugins = [].concat(me.plugins);
674             for (i = 0, len = me.plugins.length; i < len; i++) {
675                 me.plugins[i] = me.constructPlugin(me.plugins[i]);
676             }
677         }
678         
679         me.initComponent();
680
681         // ititComponent gets a chance to change the id property before registering
682         Ext.ComponentManager.register(me);
683
684         // Dont pass the config so that it is not applied to 'this' again
685         me.mixins.observable.constructor.call(me);
686         me.mixins.state.constructor.call(me, config);
687
688         // Move this into Observable?
689         if (me.plugins) {
690             me.plugins = [].concat(me.plugins);
691             for (i = 0, len = me.plugins.length; i < len; i++) {
692                 me.plugins[i] = me.initPlugin(me.plugins[i]);
693             }
694         }
695
696         me.loader = me.getLoader();
697
698         if (me.renderTo) {
699             me.render(me.renderTo);
700             // EXTJSIV-1935 - should be a way to do afterShow or something, but that
701             // won't work. Likewise, rendering hidden and then showing (w/autoShow) has
702             // implications to afterRender so we cannot do that.
703         }
704
705         if (me.autoShow) {
706             me.show();
707         }
708         
709         //<debug>
710         if (Ext.isDefined(me.disabledClass)) {
711             if (Ext.isDefined(Ext.global.console)) {
712                 Ext.global.console.warn('Ext.Component: disabledClass has been deprecated. Please use disabledCls.');
713             }
714             me.disabledCls = me.disabledClass;
715             delete me.disabledClass;
716         }
717         //</debug>
718     },
719
720     initComponent: Ext.emptyFn,
721
722     show: Ext.emptyFn,
723
724     animate: function(animObj) {
725         var me = this,
726             to;
727
728         animObj = animObj || {};
729         to = animObj.to || {};
730
731         if (Ext.fx.Manager.hasFxBlock(me.id)) {
732             return me;
733         }
734         // Special processing for animating Component dimensions.
735         if (!animObj.dynamic && (to.height || to.width)) {
736             var curWidth = me.getWidth(),
737                 w = curWidth,
738                 curHeight = me.getHeight(),
739                 h = curHeight,
740                 needsResize = false;
741
742             if (to.height && to.height > curHeight) {
743                 h = to.height;
744                 needsResize = true;
745             }
746             if (to.width && to.width > curWidth) {
747                 w = to.width;
748                 needsResize = true;
749             }
750
751             // If any dimensions are being increased, we must resize the internal structure
752             // of the Component, but then clip it by sizing its encapsulating element back to original dimensions.
753             // The animation will then progressively reveal the larger content.
754             if (needsResize) {
755                 var clearWidth = !Ext.isNumber(me.width),
756                     clearHeight = !Ext.isNumber(me.height);
757
758                 me.componentLayout.childrenChanged = true;
759                 me.setSize(w, h, me.ownerCt);
760                 me.el.setSize(curWidth, curHeight);
761                 if (clearWidth) {
762                     delete me.width;
763                 }
764                 if (clearHeight) {
765                     delete me.height;
766                 }
767             }
768         }
769         return me.mixins.animate.animate.apply(me, arguments);
770     },
771
772     /**
773      * <p>This method finds the topmost active layout who's processing will eventually determine the size and position of this
774      * Component.<p>
775      * <p>This method is useful when dynamically adding Components into Containers, and some processing must take place after the
776      * final sizing and positioning of the Component has been performed.</p>
777      * @returns
778      */
779     findLayoutController: function() {
780         return this.findParentBy(function(c) {
781             // Return true if we are at the root of the Container tree
782             // or this Container's layout is busy but the next one up is not.
783             return !c.ownerCt || (c.layout.layoutBusy && !c.ownerCt.layout.layoutBusy);
784         });
785     },
786
787     onShow : function() {
788         // Layout if needed
789         var needsLayout = this.needsLayout;
790         if (Ext.isObject(needsLayout)) {
791             this.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize, needsLayout.ownerCt);
792         }
793     },
794
795     constructPlugin: function(plugin) {
796         if (plugin.ptype && typeof plugin.init != 'function') {
797             plugin.cmp = this;
798             plugin = Ext.PluginManager.create(plugin);
799         }
800         else if (typeof plugin == 'string') {
801             plugin = Ext.PluginManager.create({
802                 ptype: plugin,
803                 cmp: this
804             });
805         }
806         return plugin;
807     },
808
809     // @private
810     initPlugin : function(plugin) {
811         plugin.init(this);
812
813         return plugin;
814     },
815
816     /**
817      * Handles autoRender.
818      * Floating Components may have an ownerCt. If they are asking to be constrained, constrain them within that
819      * ownerCt, and have their z-index managed locally. Floating Components are always rendered to document.body
820      */
821     doAutoRender: function() {
822         var me = this;
823         if (me.floating) {
824             me.render(document.body);
825         } else {
826             me.render(Ext.isBoolean(me.autoRender) ? Ext.getBody() : me.autoRender);
827         }
828     },
829
830     // @private
831     render : function(container, position) {
832         var me = this;
833
834         if (!me.rendered && me.fireEvent('beforerender', me) !== false) {
835             // If this.el is defined, we want to make sure we are dealing with
836             // an Ext Element.
837             if (me.el) {
838                 me.el = Ext.get(me.el);
839             }
840
841             // Perform render-time processing for floating Components
842             if (me.floating) {
843                 me.onFloatRender();
844             }
845
846             container = me.initContainer(container);
847
848             me.onRender(container, position);
849
850             // Tell the encapsulating element to hide itself in the way the Component is configured to hide
851             // This means DISPLAY, VISIBILITY or OFFSETS.
852             me.el.setVisibilityMode(Ext.core.Element[me.hideMode.toUpperCase()]);
853
854             if (me.overCls) {
855                 me.el.hover(me.addOverCls, me.removeOverCls, me);
856             }
857
858             me.fireEvent('render', me);
859
860             me.initContent();
861
862             me.afterRender(container);
863             me.fireEvent('afterrender', me);
864
865             me.initEvents();
866
867             if (me.hidden) {
868                 // Hiding during the render process should not perform any ancillary
869                 // actions that the full hide process does; It is not hiding, it begins in a hidden state.'
870                 // So just make the element hidden according to the configured hideMode
871                 me.el.hide();
872             }
873
874             if (me.disabled) {
875                 // pass silent so the event doesn't fire the first time.
876                 me.disable(true);
877             }
878         }
879         return me;
880     },
881
882     // @private
883     onRender : function(container, position) {
884         var me = this,
885             el = me.el,
886             cls = me.initCls(),
887             styles = me.initStyles(),
888             renderTpl, renderData, i;
889
890         position = me.getInsertPosition(position);
891
892         if (!el) {
893             if (position) {
894                 el = Ext.core.DomHelper.insertBefore(position, me.getElConfig(), true);
895             }
896             else {
897                 el = Ext.core.DomHelper.append(container, me.getElConfig(), true);
898             }
899         }
900         else if (me.allowDomMove !== false) {
901             if (position) {
902                 container.dom.insertBefore(el.dom, position);
903             } else {
904                 container.dom.appendChild(el.dom);
905             }
906         }
907
908         if (Ext.scopeResetCSS && !me.ownerCt) {
909             // If this component's el is the body element, we add the reset class to the html tag
910             if (el.dom == Ext.getBody().dom) {
911                 el.parent().addCls(Ext.baseCSSPrefix + 'reset');
912             }
913             else {
914                 // Else we wrap this element in an element that adds the reset class.
915                 me.resetEl = el.wrap({
916                     cls: Ext.baseCSSPrefix + 'reset'
917                 });
918             }
919         }
920
921         el.addCls(cls);
922         el.setStyle(styles);
923
924         // Here we check if the component has a height set through style or css.
925         // If it does then we set the this.height to that value and it won't be
926         // considered an auto height component
927         // if (this.height === undefined) {
928         //     var height = el.getHeight();
929         //     // This hopefully means that the panel has an explicit height set in style or css
930         //     if (height - el.getPadding('tb') - el.getBorderWidth('tb') > 0) {
931         //         this.height = height;
932         //     }
933         // }
934
935         me.el = el;
936         
937         me.rendered = true;
938         me.addUIToElement(true);
939         //loop through all exisiting uiCls and update the ui in them
940         for (i = 0; i < me.uiCls.length; i++) {
941             me.addUIClsToElement(me.uiCls[i], true);
942         }
943         me.rendered = false;
944         me.initFrame();
945
946         renderTpl = me.initRenderTpl();
947         if (renderTpl) {
948             renderData = me.initRenderData();
949             renderTpl.append(me.getTargetEl(), renderData);
950         }
951
952         me.applyRenderSelectors();
953         
954         me.rendered = true;
955         
956         me.setUI(me.ui);
957     },
958
959     // @private
960     afterRender : function() {
961         var me = this,
962             pos,
963             xy;
964
965         me.getComponentLayout();
966
967         // Set the size if a size is configured, or if this is the outermost Container
968         if (!me.ownerCt || (me.height || me.width)) {
969             me.setSize(me.width, me.height);
970         }
971
972         // For floaters, calculate x and y if they aren't defined by aligning
973         // the sized element to the center of either the the container or the ownerCt
974         if (me.floating && (me.x === undefined || me.y === undefined)) {
975             if (me.floatParent) {
976                 xy = me.el.getAlignToXY(me.floatParent.getTargetEl(), 'c-c');
977                 pos = me.floatParent.getTargetEl().translatePoints(xy[0], xy[1]);
978             } else {
979                 xy = me.el.getAlignToXY(me.container, 'c-c');
980                 pos = me.container.translatePoints(xy[0], xy[1]);
981             }
982             me.x = me.x === undefined ? pos.left: me.x;
983             me.y = me.y === undefined ? pos.top: me.y;
984         }
985
986         if (Ext.isDefined(me.x) || Ext.isDefined(me.y)) {
987             me.setPosition(me.x, me.y);
988         }
989
990         if (me.styleHtmlContent) {
991             me.getTargetEl().addCls(me.styleHtmlCls);
992         }
993     },
994
995     frameCls: Ext.baseCSSPrefix + 'frame',
996
997     frameTpl: [
998         '<tpl if="top">',
999             '<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>',
1000                 '<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>',
1001                     '<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>',
1002                 '<tpl if="right"></div></tpl>',
1003             '<tpl if="left"></div></tpl>',
1004         '</tpl>',
1005         '<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>',
1006             '<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>',
1007                 '<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>',
1008             '<tpl if="right"></div></tpl>',
1009         '<tpl if="left"></div></tpl>',
1010         '<tpl if="bottom">',
1011             '<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>',
1012                 '<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>',
1013                     '<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>',
1014                 '<tpl if="right"></div></tpl>',
1015             '<tpl if="left"></div></tpl>',
1016         '</tpl>'
1017     ],
1018
1019     frameTableTpl: [
1020         '<table><tbody>',
1021             '<tpl if="top">',
1022                 '<tr>',
1023                     '<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>',
1024                     '<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>',
1025                     '<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>',
1026                 '</tr>',
1027             '</tpl>',
1028             '<tr>',
1029                 '<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>',
1030                 '<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>',
1031                 '<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>',
1032             '</tr>',
1033             '<tpl if="bottom">',
1034                 '<tr>',
1035                     '<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>',
1036                     '<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>',
1037                     '<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>',
1038                 '</tr>',
1039             '</tpl>',
1040         '</tbody></table>'
1041     ],
1042     
1043     /**
1044      * @private
1045      */
1046     initFrame : function() {
1047         if (Ext.supports.CSS3BorderRadius) {
1048             return false;
1049         }
1050         
1051         var me = this,
1052             frameInfo = me.getFrameInfo(),
1053             frameWidth = frameInfo.width,
1054             frameTpl = me.getFrameTpl(frameInfo.table);
1055                         
1056         if (me.frame) {
1057             // Here we render the frameTpl to this component. This inserts the 9point div or the table framing.
1058             frameTpl.insertFirst(me.el, Ext.apply({}, {
1059                 ui:         me.ui,
1060                 uiCls:      me.uiCls,
1061                 frameCls:   me.frameCls,
1062                 baseCls:    me.baseCls,
1063                 frameWidth: frameWidth,
1064                 top:        !!frameInfo.top,
1065                 left:       !!frameInfo.left,
1066                 right:      !!frameInfo.right,
1067                 bottom:     !!frameInfo.bottom
1068             }, me.getFramePositions(frameInfo)));
1069
1070             // The frameBody is returned in getTargetEl, so that layouts render items to the correct target.=
1071             me.frameBody = me.el.down('.' + me.frameCls + '-mc');
1072             
1073             // Add the render selectors for each of the frame elements
1074             Ext.apply(me.renderSelectors, {
1075                 frameTL: '.' + me.baseCls + '-tl',
1076                 frameTC: '.' + me.baseCls + '-tc',
1077                 frameTR: '.' + me.baseCls + '-tr',
1078                 frameML: '.' + me.baseCls + '-ml',
1079                 frameMC: '.' + me.baseCls + '-mc',
1080                 frameMR: '.' + me.baseCls + '-mr',
1081                 frameBL: '.' + me.baseCls + '-bl',
1082                 frameBC: '.' + me.baseCls + '-bc',
1083                 frameBR: '.' + me.baseCls + '-br'
1084             });
1085         }
1086     },
1087     
1088     updateFrame: function() {
1089         if (Ext.supports.CSS3BorderRadius) {
1090             return false;
1091         }
1092         
1093         var me = this,
1094             wasTable = this.frameSize && this.frameSize.table,
1095             oldFrameTL = this.frameTL,
1096             oldFrameBL = this.frameBL,
1097             oldFrameML = this.frameML,
1098             oldFrameMC = this.frameMC,
1099             newMCClassName;
1100         
1101         this.initFrame();
1102         
1103         if (oldFrameMC) {
1104             if (me.frame) {                
1105                 // Reapply render selectors
1106                 delete me.frameTL;
1107                 delete me.frameTC;
1108                 delete me.frameTR;
1109                 delete me.frameML;
1110                 delete me.frameMC;
1111                 delete me.frameMR;
1112                 delete me.frameBL;
1113                 delete me.frameBC;
1114                 delete me.frameBR;    
1115                 this.applyRenderSelectors();
1116                 
1117                 // Store the class names set on the new mc
1118                 newMCClassName = this.frameMC.dom.className;
1119                 
1120                 // Replace the new mc with the old mc
1121                 oldFrameMC.insertAfter(this.frameMC);
1122                 this.frameMC.remove();
1123                 
1124                 // Restore the reference to the old frame mc as the framebody
1125                 this.frameBody = this.frameMC = oldFrameMC;
1126                 
1127                 // Apply the new mc classes to the old mc element
1128                 oldFrameMC.dom.className = newMCClassName;
1129                 
1130                 // Remove the old framing
1131                 if (wasTable) {
1132                     me.el.query('> table')[1].remove();
1133                 }                                
1134                 else {
1135                     if (oldFrameTL) {
1136                         oldFrameTL.remove();
1137                     }
1138                     if (oldFrameBL) {
1139                         oldFrameBL.remove();
1140                     }
1141                     oldFrameML.remove();
1142                 }
1143             }
1144             else {
1145                 // We were framed but not anymore. Move all content from the old frame to the body
1146                 
1147             }
1148         }
1149         else if (me.frame) {
1150             this.applyRenderSelectors();
1151         }
1152     },
1153     
1154     getFrameInfo: function() {
1155         if (Ext.supports.CSS3BorderRadius) {
1156             return false;
1157         }
1158         
1159         var me = this,
1160             left = me.el.getStyle('background-position-x'),
1161             top = me.el.getStyle('background-position-y'),
1162             info, frameInfo = false, max;
1163
1164         // Some browsers dont support background-position-x and y, so for those
1165         // browsers let's split background-position into two parts.
1166         if (!left && !top) {
1167             info = me.el.getStyle('background-position').split(' ');
1168             left = info[0];
1169             top = info[1];
1170         }
1171         
1172         // We actually pass a string in the form of '[type][tl][tr]px [type][br][bl]px' as
1173         // the background position of this.el from the css to indicate to IE that this component needs
1174         // framing. We parse it here and change the markup accordingly.
1175         if (parseInt(left, 10) >= 1000000 && parseInt(top, 10) >= 1000000) {
1176             max = Math.max;
1177             
1178             frameInfo = {
1179                 // Table markup starts with 110, div markup with 100.
1180                 table: left.substr(0, 3) == '110',
1181                 
1182                 // Determine if we are dealing with a horizontal or vertical component
1183                 vertical: top.substr(0, 3) == '110',
1184                 
1185                 // Get and parse the different border radius sizes
1186                 top:    max(left.substr(3, 2), left.substr(5, 2)),
1187                 right:  max(left.substr(5, 2), top.substr(3, 2)),
1188                 bottom: max(top.substr(3, 2), top.substr(5, 2)),
1189                 left:   max(top.substr(5, 2), left.substr(3, 2))
1190             };
1191             
1192             frameInfo.width = max(frameInfo.top, frameInfo.right, frameInfo.bottom, frameInfo.left);
1193
1194             // Just to be sure we set the background image of the el to none.
1195             me.el.setStyle('background-image', 'none');
1196         }        
1197         
1198         // This happens when you set frame: true explicitly without using the x-frame mixin in sass.
1199         // This way IE can't figure out what sizes to use and thus framing can't work.
1200         if (me.frame === true && !frameInfo) {
1201             //<debug error>
1202             Ext.Error.raise("You have set frame: true explicity on this component while it doesn't have any " +
1203                             "framing defined in the CSS template. In this case IE can't figure out what sizes " +
1204                             "to use and thus framing on this component will be disabled.");
1205             //</debug>
1206         }
1207         
1208         me.frame = me.frame || !!frameInfo;
1209         me.frameSize = frameInfo || false;
1210         
1211         return frameInfo;
1212     },
1213     
1214     getFramePositions: function(frameInfo) {
1215         var me = this,
1216             frameWidth = frameInfo.width,
1217             dock = me.dock,
1218             positions, tc, bc, ml, mr;
1219             
1220         if (frameInfo.vertical) {
1221             tc = '0 -' + (frameWidth * 0) + 'px';
1222             bc = '0 -' + (frameWidth * 1) + 'px';
1223             
1224             if (dock && dock == "right") {
1225                 tc = 'right -' + (frameWidth * 0) + 'px';
1226                 bc = 'right -' + (frameWidth * 1) + 'px';
1227             }
1228             
1229             positions = {
1230                 tl: '0 -' + (frameWidth * 0) + 'px',
1231                 tr: '0 -' + (frameWidth * 1) + 'px',
1232                 bl: '0 -' + (frameWidth * 2) + 'px',
1233                 br: '0 -' + (frameWidth * 3) + 'px',
1234
1235                 ml: '-' + (frameWidth * 1) + 'px 0',
1236                 mr: 'right 0',
1237
1238                 tc: tc,
1239                 bc: bc
1240             };
1241         } else {
1242             ml = '-' + (frameWidth * 0) + 'px 0';
1243             mr = 'right 0';
1244             
1245             if (dock && dock == "bottom") {
1246                 ml = 'left bottom';
1247                 mr = 'right bottom';
1248             }
1249             
1250             positions = {
1251                 tl: '0 -' + (frameWidth * 2) + 'px',
1252                 tr: 'right -' + (frameWidth * 3) + 'px',
1253                 bl: '0 -' + (frameWidth * 4) + 'px',
1254                 br: 'right -' + (frameWidth * 5) + 'px',
1255
1256                 ml: ml,
1257                 mr: mr,
1258
1259                 tc: '0 -' + (frameWidth * 0) + 'px',
1260                 bc: '0 -' + (frameWidth * 1) + 'px'
1261             };
1262         }
1263         
1264         return positions;
1265     },
1266     
1267     /**
1268      * @private
1269      */
1270     getFrameTpl : function(table) {
1271         return table ? this.getTpl('frameTableTpl') : this.getTpl('frameTpl');
1272     },
1273
1274     /**
1275      * <p>Creates an array of class names from the configurations to add to this Component's <code>el</code> on render.</p>
1276      * <p>Private, but (possibly) used by ComponentQuery for selection by class name if Component is not rendered.</p>
1277      * @return {Array} An array of class names with which the Component's element will be rendered.
1278      * @private
1279      */
1280     initCls: function() {
1281         var me = this,
1282             cls = [];
1283
1284         cls.push(me.baseCls);
1285
1286         //<deprecated since=0.99>
1287         if (Ext.isDefined(me.cmpCls)) {
1288             if (Ext.isDefined(Ext.global.console)) {
1289                 Ext.global.console.warn('Ext.Component: cmpCls has been deprecated. Please use componentCls.');
1290             }
1291             me.componentCls = me.cmpCls;
1292             delete me.cmpCls;
1293         }
1294         //</deprecated>
1295
1296         if (me.componentCls) {
1297             cls.push(me.componentCls);
1298         } else {
1299             me.componentCls = me.baseCls;
1300         }
1301         if (me.cls) {
1302             cls.push(me.cls);
1303             delete me.cls;
1304         }
1305
1306         return cls.concat(me.additionalCls);
1307     },
1308     
1309     /**
1310      * Sets the UI for the component. This will remove any existing UIs on the component. It will also
1311      * loop through any uiCls set on the component and rename them so they include the new UI
1312      * @param {String} ui The new UI for the component
1313      */
1314     setUI: function(ui) {
1315         var me = this,
1316             oldUICls = Ext.Array.clone(me.uiCls),
1317             newUICls = [],
1318             cls,
1319             i;
1320         
1321         //loop through all exisiting uiCls and update the ui in them
1322         for (i = 0; i < oldUICls.length; i++) {
1323             cls = oldUICls[i];
1324             
1325             me.removeClsWithUI(cls);
1326             newUICls.push(cls);
1327         }
1328         
1329         //remove the UI from the element
1330         me.removeUIFromElement();
1331         
1332         //set the UI
1333         me.ui = ui;
1334         
1335         //add the new UI to the elemend
1336         me.addUIToElement();
1337         
1338         //loop through all exisiting uiCls and update the ui in them
1339         for (i = 0; i < newUICls.length; i++) {
1340             cls = newUICls[i];
1341             
1342             me.addClsWithUI(cls);
1343         }
1344     },
1345     
1346     /**
1347      * Adds a cls to the uiCls array, which will also call {@link #addUIClsToElement} and adds
1348      * to all elements of this component.
1349      * @param {String/Array} cls A string or an array of strings to add to the uiCls
1350      */
1351     addClsWithUI: function(cls) {
1352         var me = this,
1353             i;
1354         
1355         if (!Ext.isArray(cls)) {
1356             cls = [cls];
1357         }
1358         
1359         for (i = 0; i < cls.length; i++) {
1360             if (cls[i] && !me.hasUICls(cls[i])) {
1361                 me.uiCls = Ext.Array.clone(me.uiCls);
1362                 me.uiCls.push(cls[i]);
1363                 me.addUIClsToElement(cls[i]);
1364             }
1365         }
1366     },
1367     
1368     /**
1369      * Removes a cls to the uiCls array, which will also call {@link #removeUIClsToElement} and removes
1370      * it from all elements of this component.
1371      * @param {String/Array} cls A string or an array of strings to remove to the uiCls
1372      */
1373     removeClsWithUI: function(cls) {
1374         var me = this,
1375             i;
1376         
1377         if (!Ext.isArray(cls)) {
1378             cls = [cls];
1379         }
1380         
1381         for (i = 0; i < cls.length; i++) {
1382             if (cls[i] && me.hasUICls(cls[i])) {
1383                 me.uiCls = Ext.Array.remove(me.uiCls, cls[i]);
1384                 me.removeUIClsFromElement(cls[i]);
1385             }
1386         }
1387     },
1388     
1389     /**
1390      * Checks if there is currently a specified uiCls
1391      * @param {String} cls The cls to check
1392      */
1393     hasUICls: function(cls) {
1394         var me = this,
1395             uiCls = me.uiCls || [];
1396         
1397         return Ext.Array.contains(uiCls, cls);
1398     },
1399     
1400     /**
1401      * Method which adds a specified UI + uiCls to the components element.
1402      * Can be overridden to remove the UI from more than just the components element.
1403      * @param {String} ui The UI to remove from the element
1404      * @private
1405      */
1406     addUIClsToElement: function(cls, force) {
1407         var me = this;
1408         
1409         me.addCls(Ext.baseCSSPrefix + cls);
1410         me.addCls(me.baseCls + '-' + cls);
1411         me.addCls(me.baseCls + '-' + me.ui + '-' + cls);
1412         
1413         if (!force && me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
1414             // define each element of the frame
1415             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
1416                 i, el;
1417             
1418             // loop through each of them, and if they are defined add the ui
1419             for (i = 0; i < els.length; i++) {
1420                 el = me['frame' + els[i].toUpperCase()];
1421                 
1422                 if (el && el.dom) {
1423                     el.addCls(me.baseCls + '-' + me.ui + '-' + els[i]);
1424                     el.addCls(me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]);
1425                 }
1426             }
1427         }
1428     },
1429     
1430     /**
1431      * Method which removes a specified UI + uiCls from the components element.
1432      * The cls which is added to the element will be: `this.baseCls + '-' + ui`
1433      * @param {String} ui The UI to add to the element
1434      * @private
1435      */
1436     removeUIClsFromElement: function(cls, force) {
1437         var me = this;
1438         
1439         me.removeCls(Ext.baseCSSPrefix + cls);
1440         me.removeCls(me.baseCls + '-' + cls);
1441         me.removeCls(me.baseCls + '-' + me.ui + '-' + cls);
1442         
1443         if (!force &&me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
1444             // define each element of the frame
1445             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
1446                 i, el;
1447             
1448             // loop through each of them, and if they are defined add the ui
1449             for (i = 0; i < els.length; i++) {
1450                 el = me['frame' + els[i].toUpperCase()];
1451                 if (el && el.dom) {
1452                     el.removeCls(me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]);
1453                 }
1454             }
1455         }
1456     },
1457     
1458     /**
1459      * Method which adds a specified UI to the components element.
1460      * @private
1461      */
1462     addUIToElement: function(force) {
1463         var me = this;
1464         
1465         me.addCls(me.baseCls + '-' + me.ui);
1466         
1467         if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
1468             // define each element of the frame
1469             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
1470                 i, el;
1471             
1472             // loop through each of them, and if they are defined add the ui
1473             for (i = 0; i < els.length; i++) {
1474                 el = me['frame' + els[i].toUpperCase()];
1475                 
1476                 if (el) {
1477                     el.addCls(me.baseCls + '-' + me.ui + '-' + els[i]);
1478                 }
1479             }
1480         }
1481     },
1482     
1483     /**
1484      * Method which removes a specified UI from the components element.
1485      * @private
1486      */
1487     removeUIFromElement: function() {
1488         var me = this;
1489         
1490         me.removeCls(me.baseCls + '-' + me.ui);
1491         
1492         if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) {
1493             // define each element of the frame
1494             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
1495                 i, el;
1496             
1497             // loop through each of them, and if they are defined add the ui
1498             for (i = 0; i < els.length; i++) {
1499                 el = me['frame' + els[i].toUpperCase()];
1500                 if (el) {
1501                     el.removeCls(me.baseCls + '-' + me.ui + '-' + els[i]);
1502                 }
1503             }
1504         }
1505     },
1506     
1507     getElConfig : function() {
1508         var result = this.autoEl || {tag: 'div'};
1509         result.id = this.id;
1510         return result;
1511     },
1512
1513     /**
1514      * This function takes the position argument passed to onRender and returns a
1515      * DOM element that you can use in the insertBefore.
1516      * @param {String/Number/Element/HTMLElement} position Index, element id or element you want
1517      * to put this component before.
1518      * @return {HTMLElement} DOM element that you can use in the insertBefore
1519      */
1520     getInsertPosition: function(position) {
1521         // Convert the position to an element to insert before
1522         if (position !== undefined) {
1523             if (Ext.isNumber(position)) {
1524                 position = this.container.dom.childNodes[position];
1525             }
1526             else {
1527                 position = Ext.getDom(position);
1528             }
1529         }
1530
1531         return position;
1532     },
1533
1534     /**
1535      * Adds ctCls to container.
1536      * @return {Ext.core.Element} The initialized container
1537      * @private
1538      */
1539     initContainer: function(container) {
1540         var me = this;
1541
1542         // If you render a component specifying the el, we get the container
1543         // of the el, and make sure we dont move the el around in the dom
1544         // during the render
1545         if (!container && me.el) {
1546             container = me.el.dom.parentNode;
1547             me.allowDomMove = false;
1548         }
1549
1550         me.container = Ext.get(container);
1551
1552         if (me.ctCls) {
1553             me.container.addCls(me.ctCls);
1554         }
1555
1556         return me.container;
1557     },
1558
1559     /**
1560      * Initialized the renderData to be used when rendering the renderTpl.
1561      * @return {Object} Object with keys and values that are going to be applied to the renderTpl
1562      * @private
1563      */
1564     initRenderData: function() {
1565         var me = this;
1566
1567         return Ext.applyIf(me.renderData, {
1568             ui: me.ui,
1569             uiCls: me.uiCls,
1570             baseCls: me.baseCls,
1571             componentCls: me.componentCls,
1572             frame: me.frame
1573         });
1574     },
1575
1576     /**
1577      * @private
1578      */
1579     getTpl: function(name) {
1580         var prototype = this.self.prototype,
1581             ownerPrototype;
1582
1583         if (this.hasOwnProperty(name)) {
1584             if (!(this[name] instanceof Ext.XTemplate)) {
1585                 this[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', this[name]);
1586             }
1587
1588             return this[name];
1589         }
1590
1591         if (!(prototype[name] instanceof Ext.XTemplate)) {
1592             ownerPrototype = prototype;
1593
1594             do {
1595                 if (ownerPrototype.hasOwnProperty(name)) {
1596                     ownerPrototype[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', ownerPrototype[name]);
1597                     break;
1598                 }
1599
1600                 ownerPrototype = ownerPrototype.superclass;
1601             } while (ownerPrototype);
1602         }
1603
1604         return prototype[name];
1605     },
1606
1607     /**
1608      * Initializes the renderTpl.
1609      * @return {Ext.XTemplate} The renderTpl XTemplate instance.
1610      * @private
1611      */
1612     initRenderTpl: function() {
1613         return this.getTpl('renderTpl');
1614     },
1615
1616     /**
1617      * Function description
1618      * @return {String} A CSS style string with style, padding, margin and border.
1619      * @private
1620      */
1621     initStyles: function() {
1622         var style = {},
1623             me = this,
1624             Element = Ext.core.Element;
1625
1626         if (Ext.isString(me.style)) {
1627             style = Element.parseStyles(me.style);
1628         } else {
1629             style = Ext.apply({}, me.style);
1630         }
1631
1632         // Convert the padding, margin and border properties from a space seperated string
1633         // into a proper style string
1634         if (me.padding !== undefined) {
1635             style.padding = Element.unitizeBox((me.padding === true) ? 5 : me.padding);
1636         }
1637
1638         if (me.margin !== undefined) {
1639             style.margin = Element.unitizeBox((me.margin === true) ? 5 : me.margin);
1640         }
1641
1642         delete me.style;
1643         return style;
1644     },
1645
1646     /**
1647      * Initializes this components contents. It checks for the properties
1648      * html, contentEl and tpl/data.
1649      * @private
1650      */
1651     initContent: function() {
1652         var me = this,
1653             target = me.getTargetEl(),
1654             contentEl,
1655             pre;
1656
1657         if (me.html) {
1658             target.update(Ext.core.DomHelper.markup(me.html));
1659             delete me.html;
1660         }
1661
1662         if (me.contentEl) {
1663             contentEl = Ext.get(me.contentEl);
1664             pre = Ext.baseCSSPrefix;
1665             contentEl.removeCls([pre + 'hidden', pre + 'hide-display', pre + 'hide-offsets', pre + 'hide-nosize']);
1666             target.appendChild(contentEl.dom);
1667         }
1668
1669         if (me.tpl) {
1670             // Make sure this.tpl is an instantiated XTemplate
1671             if (!me.tpl.isTemplate) {
1672                 me.tpl = Ext.create('Ext.XTemplate', me.tpl);
1673             }
1674
1675             if (me.data) {
1676                 me.tpl[me.tplWriteMode](target, me.data);
1677                 delete me.data;
1678             }
1679         }
1680     },
1681
1682     // @private
1683     initEvents : function() {
1684         var me = this,
1685             afterRenderEvents = me.afterRenderEvents,
1686             property, listeners;
1687         if (afterRenderEvents) {
1688             for (property in afterRenderEvents) {
1689                 if (afterRenderEvents.hasOwnProperty(property)) {
1690                     listeners = afterRenderEvents[property];
1691                     if (me[property] && me[property].on) {
1692                         me.mon(me[property], listeners);
1693                     }
1694                 }
1695             }
1696         }
1697     },
1698
1699     /**
1700      * Sets references to elements inside the component. E.g body -> x-panel-body
1701      * @private
1702      */
1703     applyRenderSelectors: function() {
1704         var selectors = this.renderSelectors || {},
1705             el = this.el.dom,
1706             selector;
1707
1708         for (selector in selectors) {
1709             if (selectors.hasOwnProperty(selector) && selectors[selector]) {
1710                 this[selector] = Ext.get(Ext.DomQuery.selectNode(selectors[selector], el));
1711             }
1712         }
1713     },
1714
1715     /**
1716      * Tests whether this Component matches the selector string.
1717      * @param {String} selector The selector string to test against.
1718      * @return {Boolean} True if this Component matches the selector.
1719      */
1720     is: function(selector) {
1721         return Ext.ComponentQuery.is(this, selector);
1722     },
1723
1724     /**
1725      * <p>Walks up the <code>ownerCt</code> axis looking for an ancestor Container which matches
1726      * the passed simple selector.</p>
1727      * <p>Example:<pre><code>
1728 var owningTabPanel = grid.up('tabpanel');
1729 </code></pre>
1730      * @param {String} selector Optional. The simple selector to test.
1731      * @return {Container} The matching ancestor Container (or <code>undefined</code> if no match was found).
1732      */
1733     up: function(selector) {
1734         var result = this.ownerCt;
1735         if (selector) {
1736             for (; result; result = result.ownerCt) {
1737                 if (Ext.ComponentQuery.is(result, selector)) {
1738                     return result;
1739                 }
1740             }
1741         }
1742         return result;
1743     },
1744
1745     /**
1746      * <p>Returns the next sibling of this Component.</p>
1747      * <p>Optionally selects the next sibling which matches the passed {@link Ext.ComponentQuery ComponentQuery} selector.</p>
1748      * <p>May also be refered to as <code><b>next()</b></code></p>
1749      * <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>
1750      * @param {String} selector Optional A {@link Ext.ComponentQuery ComponentQuery} selector to filter the following items.
1751      * @returns The next sibling (or the next sibling which matches the selector). Returns null if there is no matching sibling.
1752      */
1753     nextSibling: function(selector) {
1754         var o = this.ownerCt, it, last, idx, c;
1755         if (o) {
1756             it = o.items;
1757             idx = it.indexOf(this) + 1;
1758             if (idx) {
1759                 if (selector) {
1760                     for (last = it.getCount(); idx < last; idx++) {
1761                         if ((c = it.getAt(idx)).is(selector)) {
1762                             return c;
1763                         }
1764                     }
1765                 } else {
1766                     if (idx < it.getCount()) {
1767                         return it.getAt(idx);
1768                     }
1769                 }
1770             }
1771         }
1772         return null;
1773     },
1774
1775     /**
1776      * <p>Returns the previous sibling of this Component.</p>
1777      * <p>Optionally selects the previous sibling which matches the passed {@link Ext.ComponentQuery ComponentQuery} selector.</p>
1778      * <p>May also be refered to as <code><b>prev()</b></code></p>
1779      * <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>
1780      * @param {String} selector Optional. A {@link Ext.ComponentQuery ComponentQuery} selector to filter the preceding items.
1781      * @returns The previous sibling (or the previous sibling which matches the selector). Returns null if there is no matching sibling.
1782      */
1783     previousSibling: function(selector) {
1784         var o = this.ownerCt, it, idx, c;
1785         if (o) {
1786             it = o.items;
1787             idx = it.indexOf(this);
1788             if (idx != -1) {
1789                 if (selector) {
1790                     for (--idx; idx >= 0; idx--) {
1791                         if ((c = it.getAt(idx)).is(selector)) {
1792                             return c;
1793                         }
1794                     }
1795                 } else {
1796                     if (idx) {
1797                         return it.getAt(--idx);
1798                     }
1799                 }
1800             }
1801         }
1802         return null;
1803     },
1804
1805     /**
1806      * <p>Returns the previous node in the Component tree in tree traversal order.</p>
1807      * <p>Note that this is not limited to siblings, and if invoked upon a node with no matching siblings, will
1808      * walk the tree in reverse order to attempt to find a match. Contrast with {@link #previousSibling}.</p>
1809      * @param {String} selector Optional. A {@link Ext.ComponentQuery ComponentQuery} selector to filter the preceding nodes.
1810      * @returns The previous node (or the previous node which matches the selector). Returns null if there is no matching node.
1811      */
1812     previousNode: function(selector, includeSelf) {
1813         var node = this,
1814             result,
1815             it, len, i;
1816
1817         // If asked to include self, test me
1818         if (includeSelf && node.is(selector)) {
1819             return node;
1820         }
1821
1822         result = this.prev(selector);
1823         if (result) {
1824             return result;
1825         }
1826
1827         if (node.ownerCt) {
1828             for (it = node.ownerCt.items.items, i = Ext.Array.indexOf(it, node) - 1; i > -1; i--) {
1829                 if (it[i].query) {
1830                     result = it[i].query(selector);
1831                     result = result[result.length - 1];
1832                     if (result) {
1833                         return result;
1834                     }
1835                 }
1836             }
1837             return node.ownerCt.previousNode(selector, true);
1838         }
1839     },
1840
1841     /**
1842      * <p>Returns the next node in the Component tree in tree traversal order.</p>
1843      * <p>Note that this is not limited to siblings, and if invoked upon a node with no matching siblings, will
1844      * walk the tree to attempt to find a match. Contrast with {@link #pnextSibling}.</p>
1845      * @param {String} selector Optional A {@link Ext.ComponentQuery ComponentQuery} selector to filter the following nodes.
1846      * @returns The next node (or the next node which matches the selector). Returns null if there is no matching node.
1847      */
1848     nextNode: function(selector, includeSelf) {
1849         var node = this,
1850             result,
1851             it, len, i;
1852
1853         // If asked to include self, test me
1854         if (includeSelf && node.is(selector)) {
1855             return node;
1856         }
1857
1858         result = this.next(selector);
1859         if (result) {
1860             return result;
1861         }
1862
1863         if (node.ownerCt) {
1864             for (it = node.ownerCt.items, i = it.indexOf(node) + 1, it = it.items, len = it.length; i < len; i++) {
1865                 if (it[i].down) {
1866                     result = it[i].down(selector);
1867                     if (result) {
1868                         return result;
1869                     }
1870                 }
1871             }
1872             return node.ownerCt.nextNode(selector);
1873         }
1874     },
1875
1876     /**
1877      * Retrieves the id of this component.
1878      * Will autogenerate an id if one has not already been set.
1879      */
1880     getId : function() {
1881         return this.id || (this.id = 'ext-comp-' + (this.getAutoId()));
1882     },
1883
1884     getItemId : function() {
1885         return this.itemId || this.id;
1886     },
1887
1888     /**
1889      * Retrieves the top level element representing this component.
1890      */
1891     getEl : function() {
1892         return this.el;
1893     },
1894
1895     /**
1896      * This is used to determine where to insert the 'html', 'contentEl' and 'items' in this component.
1897      * @private
1898      */
1899     getTargetEl: function() {
1900         return this.frameBody || this.el;
1901     },
1902
1903     /**
1904      * <p>Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended
1905      * from the xtype (default) or whether it is directly of the xtype specified (shallow = true).</p>
1906      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1907      * to participate in determination of inherited xtypes.</b></p>
1908      * <p>For a list of all available xtypes, see the {@link Ext.Component} header.</p>
1909      * <p>Example usage:</p>
1910      * <pre><code>
1911 var t = new Ext.form.field.Text();
1912 var isText = t.isXType('textfield');        // true
1913 var isBoxSubclass = t.isXType('field');       // true, descended from Ext.form.field.Base
1914 var isBoxInstance = t.isXType('field', true); // false, not a direct Ext.form.field.Base instance
1915 </code></pre>
1916      * @param {String} xtype The xtype to check for this Component
1917      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
1918      * the default), or true to check whether this Component is directly of the specified xtype.
1919      * @return {Boolean} True if this component descends from the specified xtype, false otherwise.
1920      */
1921     isXType: function(xtype, shallow) {
1922         //assume a string by default
1923         if (Ext.isFunction(xtype)) {
1924             xtype = xtype.xtype;
1925             //handle being passed the class, e.g. Ext.Component
1926         } else if (Ext.isObject(xtype)) {
1927             xtype = xtype.statics().xtype;
1928             //handle being passed an instance
1929         }
1930
1931         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1: this.self.xtype == xtype;
1932     },
1933
1934     /**
1935      * <p>Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all
1936      * available xtypes, see the {@link Ext.Component} header.</p>
1937      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1938      * to participate in determination of inherited xtypes.</b></p>
1939      * <p>Example usage:</p>
1940      * <pre><code>
1941 var t = new Ext.form.field.Text();
1942 alert(t.getXTypes());  // alerts 'component/field/textfield'
1943 </code></pre>
1944      * @return {String} The xtype hierarchy string
1945      */
1946     getXTypes: function() {
1947         var self = this.self,
1948             xtypes      = [],
1949             parentPrototype  = this,
1950             xtype;
1951
1952         if (!self.xtypes) {
1953             while (parentPrototype && Ext.getClass(parentPrototype)) {
1954                 xtype = Ext.getClass(parentPrototype).xtype;
1955
1956                 if (xtype !== undefined) {
1957                     xtypes.unshift(xtype);
1958                 }
1959
1960                 parentPrototype = parentPrototype.superclass;
1961             }
1962
1963             self.xtypeChain = xtypes;
1964             self.xtypes = xtypes.join('/');
1965         }
1966
1967         return self.xtypes;
1968     },
1969
1970     /**
1971      * Update the content area of a component.
1972      * @param {Mixed} htmlOrData
1973      * If this component has been configured with a template via the tpl config
1974      * then it will use this argument as data to populate the template.
1975      * If this component was not configured with a template, the components
1976      * content area will be updated via Ext.core.Element update
1977      * @param {Boolean} loadScripts
1978      * (optional) Only legitimate when using the html configuration. Defaults to false
1979      * @param {Function} callback
1980      * (optional) Only legitimate when using the html configuration. Callback to execute when scripts have finished loading
1981      */
1982     update : function(htmlOrData, loadScripts, cb) {
1983         var me = this;
1984
1985         if (me.tpl && !Ext.isString(htmlOrData)) {
1986             me.data = htmlOrData;
1987             if (me.rendered) {
1988                 me.tpl[me.tplWriteMode](me.getTargetEl(), htmlOrData || {});
1989             }
1990         } else {
1991             me.html = Ext.isObject(htmlOrData) ? Ext.core.DomHelper.markup(htmlOrData) : htmlOrData;
1992             if (me.rendered) {
1993                 me.getTargetEl().update(me.html, loadScripts, cb);
1994             }
1995         }
1996
1997         if (me.rendered) {
1998             me.doComponentLayout();
1999         }
2000     },
2001
2002     /**
2003      * Convenience function to hide or show this component by boolean.
2004      * @param {Boolean} visible True to show, false to hide
2005      * @return {Ext.Component} this
2006      */
2007     setVisible : function(visible) {
2008         return this[visible ? 'show': 'hide']();
2009     },
2010
2011     /**
2012      * Returns true if this component is visible.
2013      * @param {Boolean} deep. <p>Optional. Pass <code>true</code> to interrogate the visibility status of all
2014      * parent Containers to determine whether this Component is truly visible to the user.</p>
2015      * <p>Generally, to determine whether a Component is hidden, the no argument form is needed. For example
2016      * when creating dynamically laid out UIs in a hidden Container before showing them.</p>
2017      * @return {Boolean} True if this component is visible, false otherwise.
2018      */
2019     isVisible: function(deep) {
2020         var me = this,
2021             child = me,
2022             visible = !me.hidden,
2023             ancestor = me.ownerCt;
2024
2025         // Clear hiddenOwnerCt property
2026         me.hiddenAncestor = false;
2027         if (me.destroyed) {
2028             return false;
2029         }
2030
2031         if (deep && visible && me.rendered && ancestor) {
2032             while (ancestor) {
2033                 // If any ancestor is hidden, then this is hidden.
2034                 // If an ancestor Panel (only Panels have a collapse method) is collapsed,
2035                 // then its layoutTarget (body) is hidden, so this is hidden unless its within a
2036                 // docked item; they are still visible when collapsed (Unless they themseves are hidden)
2037                 if (ancestor.hidden || (ancestor.collapsed &&
2038                         !(ancestor.getDockedItems && Ext.Array.contains(ancestor.getDockedItems(), child)))) {
2039                     // Store hiddenOwnerCt property if needed
2040                     me.hiddenAncestor = ancestor;
2041                     visible = false;
2042                     break;
2043                 }
2044                 child = ancestor;
2045                 ancestor = ancestor.ownerCt;
2046             }
2047         }
2048         return visible;
2049     },
2050
2051     /**
2052      * Enable the component
2053      * @param {Boolean} silent
2054      * Passing false will supress the 'enable' event from being fired.
2055      */
2056     enable: function(silent) {
2057         var me = this;
2058
2059         if (me.rendered) {
2060             me.el.removeCls(me.disabledCls);
2061             me.el.dom.disabled = false;
2062             me.onEnable();
2063         }
2064
2065         me.disabled = false;
2066
2067         if (silent !== true) {
2068             me.fireEvent('enable', me);
2069         }
2070
2071         return me;
2072     },
2073
2074     /**
2075      * Disable the component.
2076      * @param {Boolean} silent
2077      * Passing true, will supress the 'disable' event from being fired.
2078      */
2079     disable: function(silent) {
2080         var me = this;
2081
2082         if (me.rendered) {
2083             me.el.addCls(me.disabledCls);
2084             me.el.dom.disabled = true;
2085             me.onDisable();
2086         }
2087
2088         me.disabled = true;
2089
2090         if (silent !== true) {
2091             me.fireEvent('disable', me);
2092         }
2093
2094         return me;
2095     },
2096     
2097     // @private
2098     onEnable: function() {
2099         if (this.maskOnDisable) {
2100             this.el.unmask();
2101         }        
2102     },
2103
2104     // @private
2105     onDisable : function() {
2106         if (this.maskOnDisable) {
2107             this.el.mask();
2108         }
2109     },
2110     
2111     /**
2112      * Method to determine whether this Component is currently disabled.
2113      * @return {Boolean} the disabled state of this Component.
2114      */
2115     isDisabled : function() {
2116         return this.disabled;
2117     },
2118
2119     /**
2120      * Enable or disable the component.
2121      * @param {Boolean} disabled
2122      */
2123     setDisabled : function(disabled) {
2124         return this[disabled ? 'disable': 'enable']();
2125     },
2126
2127     /**
2128      * Method to determine whether this Component is currently set to hidden.
2129      * @return {Boolean} the hidden state of this Component.
2130      */
2131     isHidden : function() {
2132         return this.hidden;
2133     },
2134
2135     /**
2136      * Adds a CSS class to the top level element representing this component.
2137      * @param {String} cls The CSS class name to add
2138      * @return {Ext.Component} Returns the Component to allow method chaining.
2139      */
2140     addCls : function(className) {
2141         var me = this;
2142         if (!className) {
2143             return me;
2144         }
2145         if (!Ext.isArray(className)){
2146             className = className.replace(me.trimRe, '').split(me.spacesRe);
2147         }
2148         if (me.rendered) {
2149             me.el.addCls(className);
2150         }
2151         else {
2152             me.additionalCls = Ext.Array.unique(me.additionalCls.concat(className));
2153         }
2154         return me;
2155     },
2156
2157     /**
2158      * @deprecated 4.0 Replaced by {@link #addCls}
2159      * Adds a CSS class to the top level element representing this component.
2160      * @param {String} cls The CSS class name to add
2161      * @return {Ext.Component} Returns the Component to allow method chaining.
2162      */
2163     addClass : function() {
2164         return this.addCls.apply(this, arguments);
2165     },
2166
2167     /**
2168      * Removes a CSS class from the top level element representing this component.
2169      * @returns {Ext.Component} Returns the Component to allow method chaining.
2170      */
2171     removeCls : function(className) {
2172         var me = this;
2173
2174         if (!className) {
2175             return me;
2176         }
2177         if (!Ext.isArray(className)){
2178             className = className.replace(me.trimRe, '').split(me.spacesRe);
2179         }
2180         if (me.rendered) {
2181             me.el.removeCls(className);
2182         }
2183         else if (me.additionalCls.length) {
2184             Ext.each(className, function(cls) {
2185                 Ext.Array.remove(me.additionalCls, cls);
2186             });
2187         }
2188         return me;
2189     },
2190
2191     //<debug>
2192     removeClass : function() {
2193         if (Ext.isDefined(Ext.global.console)) {
2194             Ext.global.console.warn('Ext.Component: removeClass has been deprecated. Please use removeCls.');
2195         }
2196         return this.removeCls.apply(this, arguments);
2197     },
2198     //</debug>
2199
2200     addOverCls: function() {
2201         var me = this;
2202         if (!me.disabled) {
2203             me.el.addCls(me.overCls);
2204         }
2205     },
2206
2207     removeOverCls: function() {
2208         this.el.removeCls(this.overCls);
2209     },
2210
2211     addListener : function(element, listeners, scope, options) {
2212         var me = this,
2213             fn,
2214             option;
2215
2216         if (Ext.isString(element) && (Ext.isObject(listeners) || options && options.element)) {
2217             if (options.element) {
2218                 fn = listeners;
2219
2220                 listeners = {};
2221                 listeners[element] = fn;
2222                 element = options.element;
2223                 if (scope) {
2224                     listeners.scope = scope;
2225                 }
2226
2227                 for (option in options) {
2228                     if (options.hasOwnProperty(option)) {
2229                         if (me.eventOptionsRe.test(option)) {
2230                             listeners[option] = options[option];
2231                         }
2232                     }
2233                 }
2234             }
2235
2236             // At this point we have a variable called element,
2237             // and a listeners object that can be passed to on
2238             if (me[element] && me[element].on) {
2239                 me.mon(me[element], listeners);
2240             } else {
2241                 me.afterRenderEvents = me.afterRenderEvents || {};
2242                 me.afterRenderEvents[element] = listeners;
2243             }
2244         }
2245
2246         return me.mixins.observable.addListener.apply(me, arguments);
2247     },
2248     
2249     // inherit docs
2250     removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){
2251         var me = this,
2252             element = managedListener.options ? managedListener.options.element : null;
2253         
2254         if (element) {
2255             element = me[element];
2256             if (element && element.un) {
2257                 if (isClear || (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope))) {
2258                     element.un(managedListener.ename, managedListener.fn, managedListener.scope);
2259                     if (!isClear) {
2260                         Ext.Array.remove(me.managedListeners, managedListener);
2261                     }
2262                 }
2263             }
2264         } else {
2265             return me.mixins.observable.removeManagedListenerItem.apply(me, arguments);
2266         }
2267     },
2268
2269     /**
2270      * Provides the link for Observable's fireEvent method to bubble up the ownership hierarchy.
2271      * @return {Ext.container.Container} the Container which owns this Component.
2272      */
2273     getBubbleTarget : function() {
2274         return this.ownerCt;
2275     },
2276
2277     /**
2278      * Method to determine whether this Component is floating.
2279      * @return {Boolean} the floating state of this component.
2280      */
2281     isFloating : function() {
2282         return this.floating;
2283     },
2284
2285     /**
2286      * Method to determine whether this Component is draggable.
2287      * @return {Boolean} the draggable state of this component.
2288      */
2289     isDraggable : function() {
2290         return !!this.draggable;
2291     },
2292
2293     /**
2294      * Method to determine whether this Component is droppable.
2295      * @return {Boolean} the droppable state of this component.
2296      */
2297     isDroppable : function() {
2298         return !!this.droppable;
2299     },
2300
2301     /**
2302      * @private
2303      * Method to manage awareness of when components are added to their
2304      * respective Container, firing an added event.
2305      * References are established at add time rather than at render time.
2306      * @param {Ext.container.Container} container Container which holds the component
2307      * @param {number} pos Position at which the component was added
2308      */
2309     onAdded : function(container, pos) {
2310         this.ownerCt = container;
2311         this.fireEvent('added', this, container, pos);
2312     },
2313
2314     /**
2315      * @private
2316      * Method to manage awareness of when components are removed from their
2317      * respective Container, firing an removed event. References are properly
2318      * cleaned up after removing a component from its owning container.
2319      */
2320     onRemoved : function() {
2321         var me = this;
2322
2323         me.fireEvent('removed', me, me.ownerCt);
2324         delete me.ownerCt;
2325     },
2326
2327     // @private
2328     beforeDestroy : Ext.emptyFn,
2329     // @private
2330     // @private
2331     onResize : Ext.emptyFn,
2332
2333     /**
2334      * Sets the width and height of this Component. This method fires the {@link #resize} event. This method can accept
2335      * either width and height as separate arguments, or you can pass a size object like <code>{width:10, height:20}</code>.
2336      * @param {Mixed} width The new width to set. This may be one of:<div class="mdetail-params"><ul>
2337      * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.core.Element#defaultUnit}s (by default, pixels).</li>
2338      * <li>A String used to set the CSS width style.</li>
2339      * <li>A size object in the format <code>{width: widthValue, height: heightValue}</code>.</li>
2340      * <li><code>undefined</code> to leave the width unchanged.</li>
2341      * </ul></div>
2342      * @param {Mixed} height The new height to set (not required if a size object is passed as the first arg).
2343      * This may be one of:<div class="mdetail-params"><ul>
2344      * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.core.Element#defaultUnit}s (by default, pixels).</li>
2345      * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
2346      * <li><code>undefined</code> to leave the height unchanged.</li>
2347      * </ul></div>
2348      * @return {Ext.Component} this
2349      */
2350     setSize : function(width, height) {
2351         var me = this,
2352             layoutCollection;
2353
2354         // support for standard size objects
2355         if (Ext.isObject(width)) {
2356             height = width.height;
2357             width  = width.width;
2358         }
2359
2360         // Constrain within configured maxima
2361         if (Ext.isNumber(width)) {
2362             width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
2363         }
2364         if (Ext.isNumber(height)) {
2365             height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
2366         }
2367
2368         if (!me.rendered || !me.isVisible()) {
2369             // If an ownerCt is hidden, add my reference onto the layoutOnShow stack.  Set the needsLayout flag.
2370             if (me.hiddenAncestor) {
2371                 layoutCollection = me.hiddenAncestor.layoutOnShow;
2372                 layoutCollection.remove(me);
2373                 layoutCollection.add(me);
2374             }
2375             me.needsLayout = {
2376                 width: width,
2377                 height: height,
2378                 isSetSize: true
2379             };
2380             if (!me.rendered) {
2381                 me.width  = (width !== undefined) ? width : me.width;
2382                 me.height = (height !== undefined) ? height : me.height;
2383             }
2384             return me;
2385         }
2386         me.doComponentLayout(width, height, true);
2387
2388         return me;
2389     },
2390
2391     setCalculatedSize : function(width, height, ownerCt) {
2392         var me = this,
2393             layoutCollection;
2394
2395         // support for standard size objects
2396         if (Ext.isObject(width)) {
2397             ownerCt = width.ownerCt;
2398             height = width.height;
2399             width  = width.width;
2400         }
2401
2402         // Constrain within configured maxima
2403         if (Ext.isNumber(width)) {
2404             width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
2405         }
2406         if (Ext.isNumber(height)) {
2407             height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
2408         }
2409
2410         if (!me.rendered || !me.isVisible()) {
2411             // If an ownerCt is hidden, add my reference onto the layoutOnShow stack.  Set the needsLayout flag.
2412             if (me.hiddenAncestor) {
2413                 layoutCollection = me.hiddenAncestor.layoutOnShow;
2414                 layoutCollection.remove(me);
2415                 layoutCollection.add(me);
2416             }
2417             me.needsLayout = {
2418                 width: width,
2419                 height: height,
2420                 isSetSize: false,
2421                 ownerCt: ownerCt
2422             };
2423             return me;
2424         }
2425         me.doComponentLayout(width, height, false, ownerCt);
2426
2427         return me;
2428     },
2429
2430     /**
2431      * This method needs to be called whenever you change something on this component that requires the Component's
2432      * layout to be recalculated.
2433      * @return {Ext.container.Container} this
2434      */
2435     doComponentLayout : function(width, height, isSetSize, ownerCt) {
2436         var me = this,
2437             componentLayout = me.getComponentLayout();
2438
2439         // collapsed state is not relevant here, so no testing done.
2440         // Only Panels have a collapse method, and that just sets the width/height such that only
2441         // a single docked Header parallel to the collapseTo side are visible, and the Panel body is hidden.
2442         if (me.rendered && componentLayout) {
2443             width = (width !== undefined) ? width : me.width;
2444             height = (height !== undefined) ? height : me.height;
2445             if (isSetSize) {
2446                 me.width = width;
2447                 me.height = height;
2448             }
2449
2450             componentLayout.layout(width, height, isSetSize, ownerCt);
2451         }
2452         return me;
2453     },
2454
2455     // @private
2456     setComponentLayout : function(layout) {
2457         var currentLayout = this.componentLayout;
2458         if (currentLayout && currentLayout.isLayout && currentLayout != layout) {
2459             currentLayout.setOwner(null);
2460         }
2461         this.componentLayout = layout;
2462         layout.setOwner(this);
2463     },
2464
2465     getComponentLayout : function() {
2466         var me = this;
2467
2468         if (!me.componentLayout || !me.componentLayout.isLayout) {
2469             me.setComponentLayout(Ext.layout.Layout.create(me.componentLayout, 'autocomponent'));
2470         }
2471         return me.componentLayout;
2472     },
2473
2474     /**
2475      * @param {Number} adjWidth The box-adjusted width that was set
2476      * @param {Number} adjHeight The box-adjusted height that was set
2477      * @param {Boolean} isSetSize Whether or not the height/width are stored on the component permanently
2478      * @param {Ext.Component} layoutOwner Component which sent the layout. Only used when isSetSize is false.
2479      */
2480     afterComponentLayout: function(width, height, isSetSize, layoutOwner) {
2481         this.fireEvent('resize', this, width, height);
2482     },
2483
2484     /**
2485      * Occurs before componentLayout is run. Returning false from this method will prevent the componentLayout
2486      * from being executed.
2487      * @param {Number} adjWidth The box-adjusted width that was set
2488      * @param {Number} adjHeight The box-adjusted height that was set
2489      * @param {Boolean} isSetSize Whether or not the height/width are stored on the component permanently
2490      * @param {Ext.Component} layoutOwner Component which sent the layout. Only used when isSetSize is false.
2491      */
2492     beforeComponentLayout: function(width, height, isSetSize, layoutOwner) {
2493         return true;
2494     },
2495
2496     /**
2497      * Sets the left and top of the component.  To set the page XY position instead, use {@link #setPagePosition}.
2498      * This method fires the {@link #move} event.
2499      * @param {Number} left The new left
2500      * @param {Number} top The new top
2501      * @return {Ext.Component} this
2502      */
2503     setPosition : function(x, y) {
2504         var me = this;
2505
2506         if (Ext.isObject(x)) {
2507             y = x.y;
2508             x = x.x;
2509         }
2510
2511         if (!me.rendered) {
2512             return me;
2513         }
2514
2515         if (x !== undefined || y !== undefined) {
2516             me.el.setBox(x, y);
2517             me.onPosition(x, y);
2518             me.fireEvent('move', me, x, y);
2519         }
2520         return me;
2521     },
2522
2523     /* @private
2524      * Called after the component is moved, this method is empty by default but can be implemented by any
2525      * subclass that needs to perform custom logic after a move occurs.
2526      * @param {Number} x The new x position
2527      * @param {Number} y The new y position
2528      */
2529     onPosition: Ext.emptyFn,
2530
2531     /**
2532      * Sets the width of the component.  This method fires the {@link #resize} event.
2533      * @param {Number} width The new width to setThis may be one of:<div class="mdetail-params"><ul>
2534      * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.core.Element#defaultUnit}s (by default, pixels).</li>
2535      * <li>A String used to set the CSS width style.</li>
2536      * </ul></div>
2537      * @return {Ext.Component} this
2538      */
2539     setWidth : function(width) {
2540         return this.setSize(width);
2541     },
2542
2543     /**
2544      * Sets the height of the component.  This method fires the {@link #resize} event.
2545      * @param {Number} height The new height to set. This may be one of:<div class="mdetail-params"><ul>
2546      * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.core.Element#defaultUnit}s (by default, pixels).</li>
2547      * <li>A String used to set the CSS height style.</li>
2548      * <li><i>undefined</i> to leave the height unchanged.</li>
2549      * </ul></div>
2550      * @return {Ext.Component} this
2551      */
2552     setHeight : function(height) {
2553         return this.setSize(undefined, height);
2554     },
2555
2556     /**
2557      * Gets the current size of the component's underlying element.
2558      * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
2559      */
2560     getSize : function() {
2561         return this.el.getSize();
2562     },
2563
2564     /**
2565      * Gets the current width of the component's underlying element.
2566      * @return {Number}
2567      */
2568     getWidth : function() {
2569         return this.el.getWidth();
2570     },
2571
2572     /**
2573      * Gets the current height of the component's underlying element.
2574      * @return {Number}
2575      */
2576     getHeight : function() {
2577         return this.el.getHeight();
2578     },
2579
2580     /**
2581      * Gets the {@link Ext.ComponentLoader} for this Component.
2582      * @return {Ext.ComponentLoader} The loader instance, null if it doesn't exist.
2583      */
2584     getLoader: function(){
2585         var me = this,
2586             autoLoad = me.autoLoad ? (Ext.isObject(me.autoLoad) ? me.autoLoad : {url: me.autoLoad}) : null,
2587             loader = me.loader || autoLoad;
2588
2589         if (loader) {
2590             if (!loader.isLoader) {
2591                 me.loader = Ext.create('Ext.ComponentLoader', Ext.apply({
2592                     target: me,
2593                     autoLoad: autoLoad
2594                 }, loader));
2595             } else {
2596                 loader.setTarget(me);
2597             }
2598             return me.loader;
2599
2600         }
2601         return null;
2602     },
2603
2604     /**
2605      * This method allows you to show or hide a LoadMask on top of this component.
2606      * @param {Boolean/Object/String} load True to show the default LoadMask, a config object
2607      * that will be passed to the LoadMask constructor, or a message String to show. False to
2608      * hide the current LoadMask.
2609      * @param {Boolean} targetEl True to mask the targetEl of this Component instead of the this.el.
2610      * For example, setting this to true on a Panel will cause only the body to be masked. (defaults to false)
2611      * @return {Ext.LoadMask} The LoadMask instance that has just been shown.
2612      */
2613     setLoading : function(load, targetEl) {
2614         var me = this,
2615             config;
2616
2617         if (me.rendered) {
2618             if (load !== false && !me.collapsed) {
2619                 if (Ext.isObject(load)) {
2620                     config = load;
2621                 }
2622                 else if (Ext.isString(load)) {
2623                     config = {msg: load};
2624                 }
2625                 else {
2626                     config = {};
2627                 }
2628                 me.loadMask = me.loadMask || Ext.create('Ext.LoadMask', targetEl ? me.getTargetEl() : me.el, config);
2629                 me.loadMask.show();
2630             } else if (me.loadMask) {
2631                 Ext.destroy(me.loadMask);
2632                 me.loadMask = null;
2633             }
2634         }
2635
2636         return me.loadMask;
2637     },
2638
2639     /**
2640      * Sets the dock position of this component in its parent panel. Note that
2641      * this only has effect if this item is part of the dockedItems collection
2642      * of a parent that has a DockLayout (note that any Panel has a DockLayout
2643      * by default)
2644      * @return {Component} this
2645      */
2646     setDocked : function(dock, layoutParent) {
2647         var me = this;
2648
2649         me.dock = dock;
2650         if (layoutParent && me.ownerCt && me.rendered) {
2651             me.ownerCt.doComponentLayout();
2652         }
2653         return me;
2654     },
2655
2656     onDestroy : function() {
2657         var me = this;
2658
2659         if (me.monitorResize && Ext.EventManager.resizeEvent) {
2660             Ext.EventManager.resizeEvent.removeListener(me.setSize, me);
2661         }
2662         Ext.destroy(me.componentLayout, me.loadMask);
2663     },
2664
2665     /**
2666      * Destroys the Component.
2667      */
2668     destroy : function() {
2669         var me = this;
2670
2671         if (!me.isDestroyed) {
2672             if (me.fireEvent('beforedestroy', me) !== false) {
2673                 me.destroying = true;
2674                 me.beforeDestroy();
2675
2676                 if (me.floating) {
2677                     delete me.floatParent;
2678                     // A zIndexManager is stamped into a *floating* Component when it is added to a Container.
2679                     // If it has no zIndexManager at render time, it is assigned to the global Ext.WindowManager instance.
2680                     if (me.zIndexManager) {
2681                         me.zIndexManager.unregister(me);
2682                     }
2683                 } else if (me.ownerCt && me.ownerCt.remove) {
2684                     me.ownerCt.remove(me, false);
2685                 }
2686
2687                 if (me.rendered) {
2688                     me.el.remove();
2689                 }
2690
2691                 me.onDestroy();
2692
2693                 // Attempt to destroy all plugins
2694                 Ext.destroy(me.plugins);
2695
2696                 Ext.ComponentManager.unregister(me);
2697                 me.fireEvent('destroy', me);
2698
2699                 me.mixins.state.destroy.call(me);
2700
2701                 me.clearListeners();
2702                 me.destroying = false;
2703                 me.isDestroyed = true;
2704             }
2705         }
2706     },
2707
2708     /**
2709      * Retrieves a plugin by its pluginId which has been bound to this
2710      * component.
2711      * @returns {Ext.AbstractPlugin} pluginInstance
2712      */
2713     getPlugin: function(pluginId) {
2714         var i = 0,
2715             plugins = this.plugins,
2716             ln = plugins.length;
2717         for (; i < ln; i++) {
2718             if (plugins[i].pluginId === pluginId) {
2719                 return plugins[i];
2720             }
2721         }
2722     },
2723     
2724     /**
2725      * Determines whether this component is the descendant of a particular container.
2726      * @param {Ext.Container} container
2727      * @returns {Boolean} isDescendant
2728      */
2729     isDescendantOf: function(container) {
2730         return !!this.findParentBy(function(p){
2731             return p === container;
2732         });
2733     }
2734 }, function() {
2735     this.createAlias({
2736         on: 'addListener',
2737         prev: 'previousSibling',
2738         next: 'nextSibling'
2739     });
2740 });