provide installation instructions
[extjs.git] / source / widgets / Component.js
1 /*\r
2  * Ext JS Library 2.2.1\r
3  * Copyright(c) 2006-2009, Ext JS, LLC.\r
4  * licensing@extjs.com\r
5  * \r
6  * http://extjs.com/license\r
7  */\r
8 \r
9 /**\r
10  * @class Ext.Component\r
11  * @extends Ext.util.Observable\r
12  * <p>Base class for all Ext components.  All subclasses of Component can automatically participate in the standard\r
13  * Ext component lifecycle of creation, rendering and destruction.  They also have automatic support for basic hide/show\r
14  * and enable/disable behavior.  Component allows any subclass to be lazy-rendered into any {@link Ext.Container} and\r
15  * to be automatically registered with the {@link Ext.ComponentMgr} so that it can be referenced at any time via\r
16  * {@link Ext#getCmp}.  All visual widgets that require rendering into a layout should subclass Component (or\r
17  * {@link Ext.BoxComponent} if managed box model handling is required).</p>\r
18  * <p>Every component has a specific xtype, which is its Ext-specific type name, along with methods for checking the\r
19  * xtype like {@link #getXType} and {@link #isXType}. This is the list of all valid xtypes:</p>\r
20  * <pre>\r
21 xtype            Class\r
22 -------------    ------------------\r
23 box              Ext.BoxComponent\r
24 button           Ext.Button\r
25 colorpalette     Ext.ColorPalette\r
26 component        Ext.Component\r
27 container        Ext.Container\r
28 cycle            Ext.CycleButton\r
29 dataview         Ext.DataView\r
30 datepicker       Ext.DatePicker\r
31 editor           Ext.Editor\r
32 editorgrid       Ext.grid.EditorGridPanel\r
33 grid             Ext.grid.GridPanel\r
34 paging           Ext.PagingToolbar\r
35 panel            Ext.Panel\r
36 progress         Ext.ProgressBar\r
37 propertygrid     Ext.grid.PropertyGrid\r
38 slider           Ext.Slider\r
39 splitbutton      Ext.SplitButton\r
40 statusbar        Ext.StatusBar\r
41 tabpanel         Ext.TabPanel\r
42 treepanel        Ext.tree.TreePanel\r
43 viewport         Ext.Viewport\r
44 window           Ext.Window\r
45 \r
46 Toolbar components\r
47 ---------------------------------------\r
48 toolbar          Ext.Toolbar\r
49 tbbutton         Ext.Toolbar.Button\r
50 tbfill           Ext.Toolbar.Fill\r
51 tbitem           Ext.Toolbar.Item\r
52 tbseparator      Ext.Toolbar.Separator\r
53 tbspacer         Ext.Toolbar.Spacer\r
54 tbsplit          Ext.Toolbar.SplitButton\r
55 tbtext           Ext.Toolbar.TextItem\r
56 \r
57 Form components\r
58 ---------------------------------------\r
59 form             Ext.FormPanel\r
60 checkbox         Ext.form.Checkbox\r
61 combo            Ext.form.ComboBox\r
62 datefield        Ext.form.DateField\r
63 field            Ext.form.Field\r
64 fieldset         Ext.form.FieldSet\r
65 hidden           Ext.form.Hidden\r
66 htmleditor       Ext.form.HtmlEditor\r
67 label            Ext.form.Label\r
68 numberfield      Ext.form.NumberField\r
69 radio            Ext.form.Radio\r
70 textarea         Ext.form.TextArea\r
71 textfield        Ext.form.TextField\r
72 timefield        Ext.form.TimeField\r
73 trigger          Ext.form.TriggerField\r
74 </pre>\r
75  * @constructor\r
76  * @param {Ext.Element/String/Object} config The configuration options.  If an element is passed, it is set as the internal\r
77  * element and its id used as the component id.  If a string is passed, it is assumed to be the id of an existing element\r
78  * and is used as the component id.  Otherwise, it is assumed to be a standard config object and is applied to the component.\r
79  */\r
80 Ext.Component = function(config){\r
81     config = config || {};\r
82     if(config.initialConfig){\r
83         if(config.isAction){           // actions\r
84             this.baseAction = config;\r
85         }\r
86         config = config.initialConfig; // component cloning / action set up\r
87     }else if(config.tagName || config.dom || typeof config == "string"){ // element object\r
88         config = {applyTo: config, id: config.id || config};\r
89     }\r
90 \r
91     /**\r
92      * This Component's initial configuration specification. Read-only.\r
93      * @type Object\r
94      * @property initialConfig\r
95      */\r
96     this.initialConfig = config;\r
97 \r
98     Ext.apply(this, config);\r
99     this.addEvents(\r
100         /**\r
101          * @event disable\r
102          * Fires after the component is disabled.\r
103              * @param {Ext.Component} this\r
104              */\r
105         'disable',\r
106         /**\r
107          * @event enable\r
108          * Fires after the component is enabled.\r
109              * @param {Ext.Component} this\r
110              */\r
111         'enable',\r
112         /**\r
113          * @event beforeshow\r
114          * Fires before the component is shown. Return false to stop the show.\r
115              * @param {Ext.Component} this\r
116              */\r
117         'beforeshow',\r
118         /**\r
119          * @event show\r
120          * Fires after the component is shown.\r
121              * @param {Ext.Component} this\r
122              */\r
123         'show',\r
124         /**\r
125          * @event beforehide\r
126          * Fires before the component is hidden. Return false to stop the hide.\r
127              * @param {Ext.Component} this\r
128              */\r
129         'beforehide',\r
130         /**\r
131          * @event hide\r
132          * Fires after the component is hidden.\r
133              * @param {Ext.Component} this\r
134              */\r
135         'hide',\r
136         /**\r
137          * @event beforerender\r
138          * Fires before the component is rendered. Return false to stop the render.\r
139              * @param {Ext.Component} this\r
140              */\r
141         'beforerender',\r
142         /**\r
143          * @event render\r
144          * Fires after the component is rendered.\r
145              * @param {Ext.Component} this\r
146              */\r
147         'render',\r
148         /**\r
149          * @event beforedestroy\r
150          * Fires before the component is destroyed. Return false to stop the destroy.\r
151              * @param {Ext.Component} this\r
152              */\r
153         'beforedestroy',\r
154         /**\r
155          * @event destroy\r
156          * Fires after the component is destroyed.\r
157              * @param {Ext.Component} this\r
158              */\r
159         'destroy',\r
160         /**\r
161          * @event beforestaterestore\r
162          * Fires before the state of the component is restored. Return false to stop the restore.\r
163              * @param {Ext.Component} this\r
164              * @param {Object} state The hash of state values\r
165              */\r
166         'beforestaterestore',\r
167         /**\r
168          * @event staterestore\r
169          * Fires after the state of the component is restored.\r
170              * @param {Ext.Component} this\r
171              * @param {Object} state The hash of state values\r
172              */\r
173         'staterestore',\r
174         /**\r
175          * @event beforestatesave\r
176          * Fires before the state of the component is saved to the configured state provider. Return false to stop the save.\r
177              * @param {Ext.Component} this\r
178              * @param {Object} state The hash of state values\r
179              */\r
180         'beforestatesave',\r
181         /**\r
182          * @event statesave\r
183          * Fires after the state of the component is saved to the configured state provider.\r
184              * @param {Ext.Component} this\r
185              * @param {Object} state The hash of state values\r
186              */\r
187         'statesave'\r
188     );\r
189     this.getId();\r
190     Ext.ComponentMgr.register(this);\r
191     Ext.Component.superclass.constructor.call(this);\r
192 \r
193     if(this.baseAction){\r
194         this.baseAction.addComponent(this);\r
195     }\r
196 \r
197     this.initComponent();\r
198 \r
199     if(this.plugins){\r
200         if(Ext.isArray(this.plugins)){\r
201             for(var i = 0, len = this.plugins.length; i < len; i++){\r
202                 this.plugins[i] = this.initPlugin(this.plugins[i]);\r
203             }\r
204         }else{\r
205             this.plugins = this.initPlugin(this.plugins);\r
206         }\r
207     }\r
208 \r
209     if(this.stateful !== false){\r
210         this.initState(config);\r
211     }\r
212 \r
213     if(this.applyTo){\r
214         this.applyToMarkup(this.applyTo);\r
215         delete this.applyTo;\r
216     }else if(this.renderTo){\r
217         this.render(this.renderTo);\r
218         delete this.renderTo;\r
219     }\r
220 };\r
221 \r
222 // private\r
223 Ext.Component.AUTO_ID = 1000;\r
224 \r
225 Ext.extend(Ext.Component, Ext.util.Observable, {\r
226     // Configs below are used for all Components when rendered by FormLayout.\r
227     /**\r
228      * @cfg {String} fieldLabel The label text to display next to this Component (defaults to '')\r
229      * <p><b>This config is only used when this Component is rendered by a Container which has been\r
230      * configured to use the {@link Ext.form.FormLayout FormLayout} layout manager.</b></p>\r
231      * Example use:<pre><code>\r
232 new Ext.FormPanel({\r
233     height: 100,\r
234     renderTo: Ext.getBody(),\r
235     items: [{\r
236         xtype: 'textfield',\r
237         fieldLabel: 'Name'\r
238     }]\r
239 });\r
240 </code></pre>\r
241      */\r
242     /**\r
243      * @cfg {String} labelStyle A CSS style specification to apply directly to this field's label (defaults to the\r
244      * container's labelStyle value if set, or '').<code></code>.\r
245      * <p><b>This config is only used when this Component is rendered by a Container which has been\r
246      * configured to use the {@link Ext.form.FormLayout FormLayout} layout manager.</b></p>\r
247      * Example use:<pre><code>\r
248 new Ext.FormPanel({\r
249     height: 100,\r
250     renderTo: Ext.getBody(),\r
251     items: [{\r
252         xtype: 'textfield',\r
253         fieldLabel: 'Name',\r
254         labelStyle: 'font-weight:bold;'\r
255     }]\r
256 });\r
257 </code></pre>\r
258      */\r
259     /**\r
260      * @cfg {String} labelSeparator The standard separator to display after the text of each form label (defaults\r
261      * to the value of {@link Ext.layout.FormLayout#labelSeparator}, which is a colon ':' by default).  To display\r
262      * no separator for this field's label specify empty string ''.\r
263      * <p><b>This config is only used when this Component is rendered by a Container which has been\r
264      * configured to use the {@link Ext.form.FormLayout FormLayout} layout manager.</b></p>\r
265      * Example use:<pre><code>\r
266 new Ext.FormPanel({\r
267     height: 100,\r
268     renderTo: Ext.getBody(),\r
269     items: [{\r
270         xtype: 'textfield',\r
271         fieldLabel: 'Name',\r
272         labelSeparator: '...'\r
273     }]\r
274 });\r
275 </code></pre>\r
276      */\r
277     /**\r
278      * @cfg {Boolean} hideLabel True to completely hide the label element (defaults to false).  By default, even if\r
279      * you do not specify a {@link fieldLabel} the space will still be reserved so that the field will line up with\r
280      * other fields that do have labels. Setting this to true will cause the field to not reserve that space.\r
281      * <p><b>This config is only used when this Component is rendered by a Container which has been\r
282      * configured to use the {@link Ext.form.FormLayout FormLayout} layout manager.</b></p>\r
283      * Example use:<pre><code>\r
284 new Ext.FormPanel({\r
285     height: 100,\r
286     renderTo: Ext.getBody(),\r
287     items: [{\r
288         xtype: 'textfield'\r
289         hideLabel: true\r
290     }]\r
291 });\r
292 </code></pre>\r
293      */\r
294     /**\r
295      * @cfg {String} clearCls The CSS class used to provide field clearing (defaults to 'x-form-clear-left').\r
296      * <p><b>This config is only used when this Component is rendered by a Container which has been\r
297      * configured to use the {@link Ext.form.FormLayout FormLayout} layout manager.</b></p>\r
298      */\r
299     /**\r
300      * @cfg {String} itemCls An additional CSS class to apply to the wrapper's form item element of this field (defaults\r
301      * to the container's itemCls value if set, or '').  Since it is applied to the item wrapper, it allows you to write\r
302      * standard CSS rules that can apply to the field, the label (if specified) or any other element within the markup for\r
303      * the field.\r
304      * <p><b>This config is only used when this Component is rendered by a Container which has been\r
305      * configured to use the {@link Ext.form.FormLayout FormLayout} layout manager.</b></p>\r
306      * Example use:<pre><code>\r
307 // Apply a style to the field's label:\r
308 &lt;style>\r
309     .required .x-form-item-label {font-weight:bold;color:red;}\r
310 &lt;/style>\r
311 \r
312 new Ext.FormPanel({\r
313     height: 100,\r
314     renderTo: Ext.getBody(),\r
315     items: [{\r
316         xtype: 'textfield',\r
317         fieldLabel: 'Name',\r
318         itemCls: 'required' //this label will be styled\r
319     },{\r
320         xtype: 'textfield',\r
321         fieldLabel: 'Favorite Color'\r
322     }]\r
323 });\r
324 </code></pre>\r
325      */\r
326 \r
327     /**\r
328      * @cfg {String} id\r
329      * The unique id of this component (defaults to an auto-assigned id). You should assign an id if you need to\r
330      * be able to access the component later and you do not have an object reference available (e.g., using\r
331      * {@link Ext.ComponentMgr#getCmp}). Note that this id will also be used as the element id for the containing\r
332      * HTML element that is rendered to the page for this component. This allows you to write id-based CSS rules to\r
333      * style the specific instance of this component uniquely, and also to select sub-elements using this\r
334      * component's id as the parent.\r
335      */\r
336     /**\r
337      * @cfg {String/Object} autoEl\r
338      * A tag name or DomHelper spec to create an element with. This is intended to create shorthand\r
339      * utility components inline via JSON. It should not be used for higher level components which already create\r
340      * their own elements. Example usage:\r
341      * <pre><code>\r
342 {xtype:'box', autoEl: 'div', cls:'my-class'}\r
343 {xtype:'box', autoEl: {tag:'blockquote', html:'autoEl is cool!'}} // with DomHelper\r
344 </code></pre>\r
345      */\r
346     /**\r
347      * @cfg {String} xtype\r
348      * The registered xtype to create. This config option is not used when passing\r
349      * a config object into a constructor. This config option is used only when\r
350      * lazy instantiation is being used, and a child item of a Container is being\r
351      * specified not as a fully instantiated Component, but as a <i>Component config\r
352      * object</i>. The xtype will be looked up at render time up to determine what\r
353      * type of child Component to create.<br><br>\r
354      * The predefined xtypes are listed {@link Ext.Component here}.\r
355      * <br><br>\r
356      * If you subclass Components to create your own Components, you may register\r
357      * them using {@link Ext.ComponentMgr#registerType} in order to be able to\r
358      * take advantage of lazy instantiation and rendering.\r
359      */\r
360     /**\r
361      * @cfg {String} cls\r
362      * An optional extra CSS class that will be added to this component's Element (defaults to '').  This can be\r
363      * useful for adding customized styles to the component or any of its children using standard CSS rules.\r
364      */\r
365     /**\r
366      * @cfg {String} overCls\r
367      * An optional extra CSS class that will be added to this component's Element when the mouse moves\r
368      * over the Element, and removed when the mouse moves out. (defaults to '').  This can be\r
369      * useful for adding customized "active" or "hover" styles to the component or any of its children using standard CSS rules.\r
370      */\r
371     /**\r
372      * @cfg {String} style\r
373      * A custom style specification to be applied to this component's Element.  Should be a valid argument to\r
374      * {@link Ext.Element#applyStyles}.\r
375      */\r
376     /**\r
377      * @cfg {String} ctCls\r
378      * An optional extra CSS class that will be added to this component's container (defaults to '').  This can be\r
379      * useful for adding customized styles to the container or any of its children using standard CSS rules.\r
380      */\r
381     /**\r
382      * @cfg {Boolean} disabled\r
383      * Render this component disabled (default is false).\r
384      */\r
385     /**\r
386      * @cfg {Boolean} hidden\r
387      * Render this component hidden (default is false).\r
388      */\r
389     /**\r
390      * @cfg {Object/Array} plugins\r
391      * An object or array of objects that will provide custom functionality for this component.  The only\r
392      * requirement for a valid plugin is that it contain an init method that accepts a reference of type Ext.Component.\r
393      * When a component is created, if any plugins are available, the component will call the init method on each\r
394      * plugin, passing a reference to itself.  Each plugin can then call methods or respond to events on the\r
395      * component as needed to provide its functionality.\r
396      */\r
397     /**\r
398      * @cfg {Mixed} applyTo\r
399      * The id of the node, a DOM node or an existing Element corresponding to a DIV that is already present in\r
400      * the document that specifies some structural markup for this component.  When applyTo is used, constituent parts of\r
401      * the component can also be specified by id or CSS class name within the main element, and the component being created\r
402      * may attempt to create its subcomponents from that markup if applicable. Using this config, a call to render() is\r
403      * not required.  If applyTo is specified, any value passed for {@link #renderTo} will be ignored and the target\r
404      * element's parent node will automatically be used as the component's container.\r
405      */\r
406     /**\r
407      * @cfg {Mixed} renderTo\r
408      * The id of the node, a DOM node or an existing Element that will be the container to render this component into.\r
409      * Using this config, a call to render() is not required.\r
410      */\r
411 \r
412     /**\r
413      * @cfg {Boolean} stateful\r
414      * <p>A flag which causes the Component to attempt to restore the state of internal properties\r
415      * from a saved state on startup. The component must have either a {@link #stateId} or {@link #id}\r
416      * assigned for state to be managed.  Auto-generated ids are not guaranteed to be stable across page\r
417      * loads and cannot be relied upon to save and restore the same state for a component.<p>\r
418      * For state saving to work, the state manager's provider must have been set to an implementation\r
419      * of {@link Ext.state.Provider} which overrides the {@link Ext.state.Provider#set set}\r
420      * and {@link Ext.state.Provider#get get} methods to save and recall name/value pairs.\r
421      * A built-in implementation, {@link Ext.state.CookieProvider} is available.</p>\r
422      * <p>To set the state provider for the current page:</p>\r
423      * <pre><code>\r
424 Ext.state.Manager.setProvider(new Ext.state.CookieProvider());\r
425 </code></pre>\r
426      * <p>Components attempt to save state when one of the events listed in the {@link #stateEvents}\r
427      * configuration fires.</p>\r
428      * <p>You can perform extra processing on state save and restore by attaching handlers to the\r
429      * {@link #beforestaterestore}, {@link #staterestore}, {@link #beforestatesave} and {@link #statesave} events</p>\r
430      */\r
431     /**\r
432      * @cfg {String} stateId\r
433      * The unique id for this component to use for state management purposes (defaults to the component id if one was\r
434      * set, otherwise null if the component is using a generated id).\r
435      * <p>See {@link #stateful} for an explanation of saving and restoring Component state.</p>\r
436      */\r
437     /* //internal - to be set by subclasses\r
438      * @cfg {Array} stateEvents\r
439      * An array of events that, when fired, should trigger this component to save its state (defaults to none).\r
440      * These can be any types of events supported by this component, including browser or custom events (e.g.,\r
441      * ['click', 'customerchange']).\r
442      * <p>See {@link #stateful} for an explanation of saving and restoring Component state.</p>\r
443      */\r
444 \r
445     /**\r
446      * @cfg {String} disabledClass\r
447      * CSS class added to the component when it is disabled (defaults to "x-item-disabled").\r
448      */\r
449     disabledClass : "x-item-disabled",\r
450         /**\r
451          * @cfg {Boolean} allowDomMove\r
452          * Whether the component can move the Dom node when rendering (defaults to true).\r
453          */\r
454     allowDomMove : true,\r
455         /**\r
456          * @cfg {Boolean} autoShow\r
457          * True if the component should check for hidden classes (e.g. 'x-hidden' or 'x-hide-display') and remove\r
458          * them on render (defaults to false).\r
459          */\r
460     autoShow : false,\r
461     /**\r
462      * @cfg {String} hideMode\r
463      * <p>How this component should be hidden. Supported values are "visibility" (css visibility), "offsets" (negative\r
464      * offset position) and "display" (css display) - defaults to "display".</p>\r
465      * <p>For Containers which may be hidden and shown as part of a {@link Ext.layout.CardLayout card layout} Container such as a\r
466      * {@link Ext.TabPanel TabPanel}, it is recommended that hideMode is configured as "offsets". This ensures\r
467      * that hidden Components still have height and width so that layout managers can perform measurements when\r
468      * calculating layouts.</p>\r
469      */\r
470     hideMode: 'display',\r
471     /**\r
472      * @cfg {Boolean} hideParent\r
473      * True to hide and show the component's container when hide/show is called on the component, false to hide\r
474      * and show the component itself (defaults to false).  For example, this can be used as a shortcut for a hide\r
475      * button on a window by setting hide:true on the button when adding it to its parent container.\r
476      */\r
477     hideParent: false,\r
478 \r
479     /**\r
480      * The component's owner {@link Ext.Container} (defaults to undefined, and is set automatically when\r
481      * the component is added to a container).  Read-only.\r
482      * @type Ext.Container\r
483      * @property ownerCt\r
484      */\r
485     /**\r
486      * True if this component is hidden. Read-only.\r
487      * @type Boolean\r
488      * @property\r
489      */\r
490     hidden : false,\r
491     /**\r
492      * True if this component is disabled. Read-only.\r
493      * @type Boolean\r
494      * @property\r
495      */\r
496     disabled : false,\r
497     /**\r
498      * True if this component has been rendered. Read-only.\r
499      * @type Boolean\r
500      * @property\r
501      */\r
502     rendered : false,\r
503 \r
504     // private\r
505     ctype : "Ext.Component",\r
506 \r
507     // private\r
508     actionMode : "el",\r
509 \r
510     // private\r
511     getActionEl : function(){\r
512         return this[this.actionMode];\r
513     },\r
514 \r
515     initPlugin : function(p){\r
516         p.init(this);\r
517         return p;\r
518     },\r
519 \r
520     /* // protected\r
521      * Function to be implemented by Component subclasses to be part of standard component initialization flow (it is empty by default).\r
522      * <pre><code>\r
523 // Traditional constructor:\r
524 Ext.Foo = function(config){\r
525         // call superclass constructor:\r
526     Ext.Foo.superclass.constructor.call(this, config);\r
527 \r
528     this.addEvents({\r
529                 // add events\r
530     });\r
531 };\r
532 Ext.extend(Ext.Foo, Ext.Bar, {\r
533    // class body\r
534 }\r
535 \r
536 // initComponent replaces the constructor:\r
537 Ext.Foo = Ext.extend(Ext.Bar, {\r
538     initComponent : function(){\r
539                 // call superclass initComponent\r
540         Ext.Container.superclass.initComponent.call(this);\r
541 \r
542         this.addEvents({\r
543             // add events\r
544         });\r
545     }\r
546 }\r
547 </code></pre>\r
548      */\r
549     initComponent : Ext.emptyFn,\r
550 \r
551     /**\r
552      * <p>Render this Component into the passed HTML element.</p>\r
553      * <p><b>If you are using a {@link Ext.Container Container} object to house this Component, then\r
554      * do not use the render method.</b></p>\r
555      * <p>A Container's child Components are rendered by that Container's\r
556      * {@link Ext.Container#layout layout} manager when the Container is first rendered.</p>\r
557      * <p>Certain layout managers allow dynamic addition of child components. Those that do\r
558      * include {@link Ext.layout.CardLayout}, {@link Ext.layout.AnchorLayout},\r
559      * {@link Ext.layout.FormLayout}, {@link Ext.layout.TableLayout}.</p>\r
560      * <p>If the Container is already rendered when a new child Component is added, you may need to call\r
561      * the Container's {@link Ext.Container#doLayout doLayout} to refresh the view which causes any\r
562      * unrendered child Components to be rendered. This is required so that you can add multiple\r
563      * child components if needed while only refreshing the layout once.</p>\r
564      * <p>When creating complex UIs, it is important to remember that sizing and positioning\r
565      * of child items is the responsibility of the Container's {@link Ext.Container#layout layout} manager.\r
566      * If you expect child items to be sized in response to user interactions, you must\r
567      * configure the Container with a layout manager which creates and manages the type of layout you\r
568      * have in mind.</p>\r
569      * <p><b>Omitting the Container's {@link Ext.Container#layout layout} config means that a basic\r
570      * layout manager is used which does nothing but render child components sequentially into the\r
571      * Container. No sizing or positioning will be performed in this situation.</b></p>\r
572      * @param {Element/HTMLElement/String} container (optional) The element this Component should be\r
573      * rendered into. If it is being created from existing markup, this should be omitted.\r
574      * @param {String/Number} position (optional) The element ID or DOM node index within the container <b>before</b>\r
575      * which this component will be inserted (defaults to appending to the end of the container)\r
576      */\r
577     render : function(container, position){\r
578         if(!this.rendered && this.fireEvent("beforerender", this) !== false){\r
579             if(!container && this.el){\r
580                 this.el = Ext.get(this.el);\r
581                 container = this.el.dom.parentNode;\r
582                 this.allowDomMove = false;\r
583             }\r
584             this.container = Ext.get(container);\r
585             if(this.ctCls){\r
586                 this.container.addClass(this.ctCls);\r
587             }\r
588             this.rendered = true;\r
589             if(position !== undefined){\r
590                 if(typeof position == 'number'){\r
591                     position = this.container.dom.childNodes[position];\r
592                 }else{\r
593                     position = Ext.getDom(position);\r
594                 }\r
595             }\r
596             this.onRender(this.container, position || null);\r
597             if(this.autoShow){\r
598                 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);\r
599             }\r
600             if(this.cls){\r
601                 this.el.addClass(this.cls);\r
602                 delete this.cls;\r
603             }\r
604             if(this.style){\r
605                 this.el.applyStyles(this.style);\r
606                 delete this.style;\r
607             }\r
608             if(this.overCls){\r
609                 this.el.addClassOnOver(this.overCls);\r
610             }\r
611             this.fireEvent("render", this);\r
612             this.afterRender(this.container);\r
613             if(this.hidden){\r
614                 this.hide();\r
615             }\r
616             if(this.disabled){\r
617                 this.disable();\r
618             }\r
619 \r
620             if(this.stateful !== false){\r
621                 this.initStateEvents();\r
622             }\r
623         }\r
624         return this;\r
625     },\r
626 \r
627     // private\r
628     initState : function(config){\r
629         if(Ext.state.Manager){\r
630             var id = this.getStateId();\r
631             if(id){\r
632                 var state = Ext.state.Manager.get(id);\r
633                 if(state){\r
634                     if(this.fireEvent('beforestaterestore', this, state) !== false){\r
635                         this.applyState(state);\r
636                         this.fireEvent('staterestore', this, state);\r
637                     }\r
638                 }\r
639             }\r
640         }\r
641     },\r
642 \r
643     // private\r
644     getStateId : function(){\r
645         return this.stateId || ((this.id.indexOf('ext-comp-') == 0 || this.id.indexOf('ext-gen') == 0) ? null : this.id);\r
646     },\r
647 \r
648     // private\r
649     initStateEvents : function(){\r
650         if(this.stateEvents){\r
651             for(var i = 0, e; e = this.stateEvents[i]; i++){\r
652                 this.on(e, this.saveState, this, {delay:100});\r
653             }\r
654         }\r
655     },\r
656 \r
657     // private\r
658     applyState : function(state, config){\r
659         if(state){\r
660             Ext.apply(this, state);\r
661         }\r
662     },\r
663 \r
664     // private\r
665     getState : function(){\r
666         return null;\r
667     },\r
668 \r
669     // private\r
670     saveState : function(){\r
671         if(Ext.state.Manager){\r
672             var id = this.getStateId();\r
673             if(id){\r
674                 var state = this.getState();\r
675                 if(this.fireEvent('beforestatesave', this, state) !== false){\r
676                     Ext.state.Manager.set(id, state);\r
677                     this.fireEvent('statesave', this, state);\r
678                 }\r
679             }\r
680         }\r
681     },\r
682 \r
683     /**\r
684      * Apply this component to existing markup that is valid. With this function, no call to render() is required.\r
685      * @param {String/HTMLElement} el\r
686      */\r
687     applyToMarkup : function(el){\r
688         this.allowDomMove = false;\r
689         this.el = Ext.get(el);\r
690         this.render(this.el.dom.parentNode);\r
691     },\r
692 \r
693     /**\r
694      * Adds a CSS class to the component's underlying element.\r
695      * @param {string} cls The CSS class name to add\r
696      */\r
697     addClass : function(cls){\r
698         if(this.el){\r
699             this.el.addClass(cls);\r
700         }else{\r
701             this.cls = this.cls ? this.cls + ' ' + cls : cls;\r
702         }\r
703     },\r
704 \r
705     /**\r
706      * Removes a CSS class from the component's underlying element.\r
707      * @param {string} cls The CSS class name to remove\r
708      */\r
709     removeClass : function(cls){\r
710         if(this.el){\r
711             this.el.removeClass(cls);\r
712         }else if(this.cls){\r
713             this.cls = this.cls.split(' ').remove(cls).join(' ');\r
714         }\r
715     },\r
716 \r
717     // private\r
718     // default function is not really useful\r
719     onRender : function(ct, position){\r
720         if(this.autoEl){\r
721             if(typeof this.autoEl == 'string'){\r
722                 this.el = document.createElement(this.autoEl);\r
723             }else{\r
724                 var div = document.createElement('div');\r
725                 Ext.DomHelper.overwrite(div, this.autoEl);\r
726                 this.el = div.firstChild;\r
727             }\r
728             if (!this.el.id) {\r
729                 this.el.id = this.getId();\r
730             }\r
731         }\r
732         if(this.el){\r
733             this.el = Ext.get(this.el);\r
734             if(this.allowDomMove !== false){\r
735                 ct.dom.insertBefore(this.el.dom, position);\r
736             }\r
737         }\r
738     },\r
739 \r
740     // private\r
741     getAutoCreate : function(){\r
742         var cfg = typeof this.autoCreate == "object" ?\r
743                       this.autoCreate : Ext.apply({}, this.defaultAutoCreate);\r
744         if(this.id && !cfg.id){\r
745             cfg.id = this.id;\r
746         }\r
747         return cfg;\r
748     },\r
749 \r
750     // private\r
751     afterRender : Ext.emptyFn,\r
752 \r
753     /**\r
754      * Destroys this component by purging any event listeners, removing the component's element from the DOM,\r
755      * removing the component from its {@link Ext.Container} (if applicable) and unregistering it from\r
756      * {@link Ext.ComponentMgr}.  Destruction is generally handled automatically by the framework and this method\r
757      * should usually not need to be called directly.\r
758      */\r
759     destroy : function(){\r
760         if(this.fireEvent("beforedestroy", this) !== false){\r
761             this.beforeDestroy();\r
762             if(this.rendered){\r
763                 this.el.removeAllListeners();\r
764                 this.el.remove();\r
765                 if(this.actionMode == "container"){\r
766                     this.container.remove();\r
767                 }\r
768             }\r
769             this.onDestroy();\r
770             Ext.ComponentMgr.unregister(this);\r
771             this.fireEvent("destroy", this);\r
772             this.purgeListeners();\r
773         }\r
774     },\r
775 \r
776         // private\r
777     beforeDestroy : Ext.emptyFn,\r
778 \r
779         // private\r
780     onDestroy  : Ext.emptyFn,\r
781 \r
782     /**\r
783      * Returns the underlying {@link Ext.Element}.\r
784      * @return {Ext.Element} The element\r
785      */\r
786     getEl : function(){\r
787         return this.el;\r
788     },\r
789 \r
790     /**\r
791      * Returns the id of this component.\r
792      * @return {String}\r
793      */\r
794     getId : function(){\r
795         return this.id || (this.id = "ext-comp-" + (++Ext.Component.AUTO_ID));\r
796     },\r
797 \r
798     /**\r
799      * Returns the item id of this component.\r
800      * @return {String}\r
801      */\r
802     getItemId : function(){\r
803         return this.itemId || this.getId();\r
804     },\r
805 \r
806     /**\r
807      * Try to focus this component.\r
808      * @param {Boolean} selectText (optional) If applicable, true to also select the text in this component\r
809      * @param {Boolean/Number} delay (optional) Delay the focus this number of milliseconds (true for 10 milliseconds)\r
810      * @return {Ext.Component} this\r
811      */\r
812     focus : function(selectText, delay){\r
813         if(delay){\r
814             this.focus.defer(typeof delay == 'number' ? delay : 10, this, [selectText, false]);\r
815             return;\r
816         }\r
817         if(this.rendered){\r
818             this.el.focus();\r
819             if(selectText === true){\r
820                 this.el.dom.select();\r
821             }\r
822         }\r
823         return this;\r
824     },\r
825 \r
826     // private\r
827     blur : function(){\r
828         if(this.rendered){\r
829             this.el.blur();\r
830         }\r
831         return this;\r
832     },\r
833 \r
834     /**\r
835      * Disable this component.\r
836      * @return {Ext.Component} this\r
837      */\r
838     disable : function(){\r
839         if(this.rendered){\r
840             this.onDisable();\r
841         }\r
842         this.disabled = true;\r
843         this.fireEvent("disable", this);\r
844         return this;\r
845     },\r
846 \r
847         // private\r
848     onDisable : function(){\r
849         this.getActionEl().addClass(this.disabledClass);\r
850         this.el.dom.disabled = true;\r
851     },\r
852 \r
853     /**\r
854      * Enable this component.\r
855      * @return {Ext.Component} this\r
856      */\r
857     enable : function(){\r
858         if(this.rendered){\r
859             this.onEnable();\r
860         }\r
861         this.disabled = false;\r
862         this.fireEvent("enable", this);\r
863         return this;\r
864     },\r
865 \r
866         // private\r
867     onEnable : function(){\r
868         this.getActionEl().removeClass(this.disabledClass);\r
869         this.el.dom.disabled = false;\r
870     },\r
871 \r
872     /**\r
873      * Convenience function for setting disabled/enabled by boolean.\r
874      * @param {Boolean} disabled\r
875      */\r
876     setDisabled : function(disabled){\r
877         this[disabled ? "disable" : "enable"]();\r
878     },\r
879 \r
880     /**\r
881      * Show this component.\r
882      * @return {Ext.Component} this\r
883      */\r
884     show: function(){\r
885         if(this.fireEvent("beforeshow", this) !== false){\r
886             this.hidden = false;\r
887             if(this.autoRender){\r
888                 this.render(typeof this.autoRender == 'boolean' ? Ext.getBody() : this.autoRender);\r
889             }\r
890             if(this.rendered){\r
891                 this.onShow();\r
892             }\r
893             this.fireEvent("show", this);\r
894         }\r
895         return this;\r
896     },\r
897 \r
898     // private\r
899     onShow : function(){\r
900         if(this.hideParent){\r
901             this.container.removeClass('x-hide-' + this.hideMode);\r
902         }else{\r
903             this.getActionEl().removeClass('x-hide-' + this.hideMode);\r
904         }\r
905 \r
906     },\r
907 \r
908     /**\r
909      * Hide this component.\r
910      * @return {Ext.Component} this\r
911      */\r
912     hide: function(){\r
913         if(this.fireEvent("beforehide", this) !== false){\r
914             this.hidden = true;\r
915             if(this.rendered){\r
916                 this.onHide();\r
917             }\r
918             this.fireEvent("hide", this);\r
919         }\r
920         return this;\r
921     },\r
922 \r
923     // private\r
924     onHide : function(){\r
925         if(this.hideParent){\r
926             this.container.addClass('x-hide-' + this.hideMode);\r
927         }else{\r
928             this.getActionEl().addClass('x-hide-' + this.hideMode);\r
929         }\r
930     },\r
931 \r
932     /**\r
933      * Convenience function to hide or show this component by boolean.\r
934      * @param {Boolean} visible True to show, false to hide\r
935      * @return {Ext.Component} this\r
936      */\r
937     setVisible: function(visible){\r
938         if(visible) {\r
939             this.show();\r
940         }else{\r
941             this.hide();\r
942         }\r
943         return this;\r
944     },\r
945 \r
946     /**\r
947      * Returns true if this component is visible.\r
948      */\r
949     isVisible : function(){\r
950         return this.rendered && this.getActionEl().isVisible();\r
951     },\r
952 \r
953     /**\r
954      * Clone the current component using the original config values passed into this instance by default.\r
955      * @param {Object} overrides A new config containing any properties to override in the cloned version.\r
956      * An id property can be passed on this object, otherwise one will be generated to avoid duplicates.\r
957      * @return {Ext.Component} clone The cloned copy of this component\r
958      */\r
959     cloneConfig : function(overrides){\r
960         overrides = overrides || {};\r
961         var id = overrides.id || Ext.id();\r
962         var cfg = Ext.applyIf(overrides, this.initialConfig);\r
963         cfg.id = id; // prevent dup id\r
964         return new this.constructor(cfg);\r
965     },\r
966 \r
967     /**\r
968      * Gets the xtype for this component as registered with {@link Ext.ComponentMgr}. For a list of all\r
969      * available xtypes, see the {@link Ext.Component} header. Example usage:\r
970      * <pre><code>\r
971 var t = new Ext.form.TextField();\r
972 alert(t.getXType());  // alerts 'textfield'\r
973 </code></pre>\r
974      * @return {String} The xtype\r
975      */\r
976     getXType : function(){\r
977         return this.constructor.xtype;\r
978     },\r
979 \r
980     /**\r
981      * <p>Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended\r
982      * from the xtype (default) or whether it is directly of the xtype specified (shallow = true).</p>\r
983      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype\r
984      * to participate in determination of inherited xtypes.</b></p>\r
985      * <p>For a list of all available xtypes, see the {@link Ext.Component} header.</p>\r
986      * <p>Example usage:</p>\r
987      * <pre><code>\r
988 var t = new Ext.form.TextField();\r
989 var isText = t.isXType('textfield');        // true\r
990 var isBoxSubclass = t.isXType('box');       // true, descended from BoxComponent\r
991 var isBoxInstance = t.isXType('box', true); // false, not a direct BoxComponent instance\r
992 </code></pre>\r
993      * @param {String} xtype The xtype to check for this Component\r
994      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is\r
995      * the default), or true to check whether this Component is directly of the specified xtype.\r
996      */\r
997     isXType : function(xtype, shallow){\r
998         //assume a string by default\r
999         if (typeof xtype == 'function'){\r
1000             xtype = xtype.xtype; //handle being passed the class, eg. Ext.Component\r
1001         }else if (typeof xtype == 'object'){\r
1002             xtype = xtype.constructor.xtype; //handle being passed an instance\r
1003         }\r
1004             \r
1005         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;\r
1006     },\r
1007 \r
1008     /**\r
1009      * <p>Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all\r
1010      * available xtypes, see the {@link Ext.Component} header.</p>\r
1011      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype\r
1012      * to participate in determination of inherited xtypes.</b></p>\r
1013      * <p>Example usage:</p>\r
1014      * <pre><code>\r
1015 var t = new Ext.form.TextField();\r
1016 alert(t.getXTypes());  // alerts 'component/box/field/textfield'\r
1017 </pre></code>\r
1018      * @return {String} The xtype hierarchy string\r
1019      */\r
1020     getXTypes : function(){\r
1021         var tc = this.constructor;\r
1022         if(!tc.xtypes){\r
1023             var c = [], sc = this;\r
1024             while(sc && sc.constructor.xtype){\r
1025                 c.unshift(sc.constructor.xtype);\r
1026                 sc = sc.constructor.superclass;\r
1027             }\r
1028             tc.xtypeChain = c;\r
1029             tc.xtypes = c.join('/');\r
1030         }\r
1031         return tc.xtypes;\r
1032     },\r
1033 \r
1034     /**\r
1035      * Find a container above this component at any level by a custom function. If the passed function returns\r
1036      * true, the container will be returned. The passed function is called with the arguments (container, this component).\r
1037      * @param {Function} fcn\r
1038      * @param {Object} scope (optional)\r
1039      * @return {Ext.Container} The first Container for which the custom function returns true\r
1040      */\r
1041     findParentBy: function(fn) {\r
1042         for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);\r
1043         return p || null;\r
1044     },\r
1045 \r
1046     /**\r
1047      * Find a container above this component at any level by xtype or class\r
1048      * @param {String/Class} xtype The xtype string for a component, or the class of the component directly\r
1049      * @return {Ext.Container} The first Container which matches the given xtype or class\r
1050      */\r
1051     findParentByType: function(xtype) {\r
1052         return typeof xtype == 'function' ?\r
1053             this.findParentBy(function(p){\r
1054                 return p.constructor === xtype;\r
1055             }) :\r
1056             this.findParentBy(function(p){\r
1057                 return p.constructor.xtype === xtype;\r
1058             });\r
1059     },\r
1060 \r
1061     // internal function for auto removal of assigned event handlers on destruction\r
1062     mon : function(item, ename, fn, scope, opt){\r
1063         if(!this.mons){\r
1064             this.mons = [];\r
1065             this.on('beforedestroy', function(){\r
1066                 for(var i= 0, len = this.mons.length; i < len; i++){\r
1067                     var m = this.mons[i];\r
1068                     m.item.un(m.ename, m.fn, m.scope);\r
1069                 }\r
1070             }, this);\r
1071         }\r
1072         this.mons.push({\r
1073             item: item, ename: ename, fn: fn, scope: scope\r
1074         });\r
1075         item.on(ename, fn, scope, opt);\r
1076     }\r
1077 });\r
1078 \r
1079 Ext.reg('component', Ext.Component);\r