source: trunk/web/addons/job_monarch/lib/extjs/source/widgets/Component.js @ 619

Last change on this file since 619 was 619, checked in by ramonb, 15 years ago

lib/:

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