Upgrade to ExtJS 3.1.0 - Released 12/16/2009
[extjs.git] / pkgs / cmp-foundation-debug.js
1 /*!
2  * Ext JS Library 3.1.0
3  * Copyright(c) 2006-2009 Ext JS, LLC
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**
8  * @class Ext.ComponentMgr
9  * <p>Provides a registry of all Components (instances of {@link Ext.Component} or any subclass
10  * thereof) on a page so that they can be easily accessed by {@link Ext.Component component}
11  * {@link Ext.Component#id id} (see {@link #get}, or the convenience method {@link Ext#getCmp Ext.getCmp}).</p>
12  * <p>This object also provides a registry of available Component <i>classes</i>
13  * indexed by a mnemonic code known as the Component's {@link Ext.Component#xtype xtype}.
14  * The <code>{@link Ext.Component#xtype xtype}</code> provides a way to avoid instantiating child Components
15  * when creating a full, nested config object for a complete Ext page.</p>
16  * <p>A child Component may be specified simply as a <i>config object</i>
17  * as long as the correct <code>{@link Ext.Component#xtype xtype}</code> is specified so that if and when the Component
18  * needs rendering, the correct type can be looked up for lazy instantiation.</p>
19  * <p>For a list of all available <code>{@link Ext.Component#xtype xtypes}</code>, see {@link Ext.Component}.</p>
20  * @singleton
21  */
22 Ext.ComponentMgr = function(){
23     var all = new Ext.util.MixedCollection();
24     var types = {};
25     var ptypes = {};
26
27     return {
28         /**
29          * Registers a component.
30          * @param {Ext.Component} c The component
31          */
32         register : function(c){
33             all.add(c);
34         },
35
36         /**
37          * Unregisters a component.
38          * @param {Ext.Component} c The component
39          */
40         unregister : function(c){
41             all.remove(c);
42         },
43
44         /**
45          * Returns a component by {@link Ext.Component#id id}.
46          * For additional details see {@link Ext.util.MixedCollection#get}.
47          * @param {String} id The component {@link Ext.Component#id id}
48          * @return Ext.Component The Component, <code>undefined</code> if not found, or <code>null</code> if a
49          * Class was found.
50          */
51         get : function(id){
52             return all.get(id);
53         },
54
55         /**
56          * Registers a function that will be called when a Component with the specified id is added to ComponentMgr. This will happen on instantiation.
57          * @param {String} id The component {@link Ext.Component#id id}
58          * @param {Function} fn The callback function
59          * @param {Object} scope The scope (<code>this</code> reference) in which the callback is executed. Defaults to the Component.
60          */
61         onAvailable : function(id, fn, scope){
62             all.on("add", function(index, o){
63                 if(o.id == id){
64                     fn.call(scope || o, o);
65                     all.un("add", fn, scope);
66                 }
67             });
68         },
69
70         /**
71          * The MixedCollection used internally for the component cache. An example usage may be subscribing to
72          * events on the MixedCollection to monitor addition or removal.  Read-only.
73          * @type {MixedCollection}
74          */
75         all : all,
76         
77         /**
78          * Checks if a Component type is registered.
79          * @param {Ext.Component} xtype The mnemonic string by which the Component class may be looked up
80          * @return {Boolean} Whether the type is registered.
81          */
82         isRegistered : function(xtype){
83             return types[xtype] !== undefined;    
84         },
85
86         /**
87          * <p>Registers a new Component constructor, keyed by a new
88          * {@link Ext.Component#xtype}.</p>
89          * <p>Use this method (or its alias {@link Ext#reg Ext.reg}) to register new
90          * subclasses of {@link Ext.Component} so that lazy instantiation may be used when specifying
91          * child Components.
92          * see {@link Ext.Container#items}</p>
93          * @param {String} xtype The mnemonic string by which the Component class may be looked up.
94          * @param {Constructor} cls The new Component class.
95          */
96         registerType : function(xtype, cls){
97             types[xtype] = cls;
98             cls.xtype = xtype;
99         },
100
101         /**
102          * Creates a new Component from the specified config object using the
103          * config object's {@link Ext.component#xtype xtype} to determine the class to instantiate.
104          * @param {Object} config A configuration object for the Component you wish to create.
105          * @param {Constructor} defaultType The constructor to provide the default Component type if
106          * the config object does not contain a <code>xtype</code>. (Optional if the config contains a <code>xtype</code>).
107          * @return {Ext.Component} The newly instantiated Component.
108          */
109         create : function(config, defaultType){
110             return config.render ? config : new types[config.xtype || defaultType](config);
111         },
112
113         /**
114          * <p>Registers a new Plugin constructor, keyed by a new
115          * {@link Ext.Component#ptype}.</p>
116          * <p>Use this method (or its alias {@link Ext#preg Ext.preg}) to register new
117          * plugins for {@link Ext.Component}s so that lazy instantiation may be used when specifying
118          * Plugins.</p>
119          * @param {String} ptype The mnemonic string by which the Plugin class may be looked up.
120          * @param {Constructor} cls The new Plugin class.
121          */
122         registerPlugin : function(ptype, cls){
123             ptypes[ptype] = cls;
124             cls.ptype = ptype;
125         },
126
127         /**
128          * Creates a new Plugin from the specified config object using the
129          * config object's {@link Ext.component#ptype ptype} to determine the class to instantiate.
130          * @param {Object} config A configuration object for the Plugin you wish to create.
131          * @param {Constructor} defaultType The constructor to provide the default Plugin type if
132          * the config object does not contain a <code>ptype</code>. (Optional if the config contains a <code>ptype</code>).
133          * @return {Ext.Component} The newly instantiated Plugin.
134          */
135         createPlugin : function(config, defaultType){
136             var PluginCls = ptypes[config.ptype || defaultType];
137             if (PluginCls.init) {
138                 return PluginCls;                
139             } else {
140                 return new PluginCls(config);
141             }            
142         }
143     };
144 }();
145
146 /**
147  * Shorthand for {@link Ext.ComponentMgr#registerType}
148  * @param {String} xtype The {@link Ext.component#xtype mnemonic string} by which the Component class
149  * may be looked up.
150  * @param {Constructor} cls The new Component class.
151  * @member Ext
152  * @method reg
153  */
154 Ext.reg = Ext.ComponentMgr.registerType; // this will be called a lot internally, shorthand to keep the bytes down
155 /**
156  * Shorthand for {@link Ext.ComponentMgr#registerPlugin}
157  * @param {String} ptype The {@link Ext.component#ptype mnemonic string} by which the Plugin class
158  * may be looked up.
159  * @param {Constructor} cls The new Plugin class.
160  * @member Ext
161  * @method preg
162  */
163 Ext.preg = Ext.ComponentMgr.registerPlugin;
164 /**
165  * Shorthand for {@link Ext.ComponentMgr#create}
166  * Creates a new Component from the specified config object using the
167  * config object's {@link Ext.component#xtype xtype} to determine the class to instantiate.
168  * @param {Object} config A configuration object for the Component you wish to create.
169  * @param {Constructor} defaultType The constructor to provide the default Component type if
170  * the config object does not contain a <code>xtype</code>. (Optional if the config contains a <code>xtype</code>).
171  * @return {Ext.Component} The newly instantiated Component.
172  * @member Ext
173  * @method create
174  */
175 Ext.create = Ext.ComponentMgr.create;/**
176  * @class Ext.Component
177  * @extends Ext.util.Observable
178  * <p>Base class for all Ext components.  All subclasses of Component may participate in the automated
179  * Ext component lifecycle of creation, rendering and destruction which is provided by the {@link Ext.Container Container} class.
180  * Components may be added to a Container through the {@link Ext.Container#items items} config option at the time the Container is created,
181  * or they may be added dynamically via the {@link Ext.Container#add add} method.</p>
182  * <p>The Component base class has built-in support for basic hide/show and enable/disable behavior.</p>
183  * <p>All Components are registered with the {@link Ext.ComponentMgr} on construction so that they can be referenced at any time via
184  * {@link Ext#getCmp}, passing the {@link #id}.</p>
185  * <p>All user-developed visual widgets that are required to participate in automated lifecycle and size management should subclass Component (or
186  * {@link Ext.BoxComponent} if managed box model handling is required, ie height and width management).</p>
187  * <p>See the <a href="http://extjs.com/learn/Tutorial:Creating_new_UI_controls">Creating new UI controls</a> tutorial for details on how
188  * and to either extend or augment ExtJs base classes to create custom Components.</p>
189  * <p>Every component has a specific xtype, which is its Ext-specific type name, along with methods for checking the
190  * xtype like {@link #getXType} and {@link #isXType}. This is the list of all valid xtypes:</p>
191  * <pre>
192 xtype            Class
193 -------------    ------------------
194 box              {@link Ext.BoxComponent}
195 button           {@link Ext.Button}
196 buttongroup      {@link Ext.ButtonGroup}
197 colorpalette     {@link Ext.ColorPalette}
198 component        {@link Ext.Component}
199 container        {@link Ext.Container}
200 cycle            {@link Ext.CycleButton}
201 dataview         {@link Ext.DataView}
202 datepicker       {@link Ext.DatePicker}
203 editor           {@link Ext.Editor}
204 editorgrid       {@link Ext.grid.EditorGridPanel}
205 flash            {@link Ext.FlashComponent}
206 grid             {@link Ext.grid.GridPanel}
207 listview         {@link Ext.ListView}
208 panel            {@link Ext.Panel}
209 progress         {@link Ext.ProgressBar}
210 propertygrid     {@link Ext.grid.PropertyGrid}
211 slider           {@link Ext.Slider}
212 spacer           {@link Ext.Spacer}
213 splitbutton      {@link Ext.SplitButton}
214 tabpanel         {@link Ext.TabPanel}
215 treepanel        {@link Ext.tree.TreePanel}
216 viewport         {@link Ext.ViewPort}
217 window           {@link Ext.Window}
218
219 Toolbar components
220 ---------------------------------------
221 paging           {@link Ext.PagingToolbar}
222 toolbar          {@link Ext.Toolbar}
223 tbbutton         {@link Ext.Toolbar.Button}        (deprecated; use button)
224 tbfill           {@link Ext.Toolbar.Fill}
225 tbitem           {@link Ext.Toolbar.Item}
226 tbseparator      {@link Ext.Toolbar.Separator}
227 tbspacer         {@link Ext.Toolbar.Spacer}
228 tbsplit          {@link Ext.Toolbar.SplitButton}   (deprecated; use splitbutton)
229 tbtext           {@link Ext.Toolbar.TextItem}
230
231 Menu components
232 ---------------------------------------
233 menu             {@link Ext.menu.Menu}
234 colormenu        {@link Ext.menu.ColorMenu}
235 datemenu         {@link Ext.menu.DateMenu}
236 menubaseitem     {@link Ext.menu.BaseItem}
237 menucheckitem    {@link Ext.menu.CheckItem}
238 menuitem         {@link Ext.menu.Item}
239 menuseparator    {@link Ext.menu.Separator}
240 menutextitem     {@link Ext.menu.TextItem}
241
242 Form components
243 ---------------------------------------
244 form             {@link Ext.form.FormPanel}
245 checkbox         {@link Ext.form.Checkbox}
246 checkboxgroup    {@link Ext.form.CheckboxGroup}
247 combo            {@link Ext.form.ComboBox}
248 datefield        {@link Ext.form.DateField}
249 displayfield     {@link Ext.form.DisplayField}
250 field            {@link Ext.form.Field}
251 fieldset         {@link Ext.form.FieldSet}
252 hidden           {@link Ext.form.Hidden}
253 htmleditor       {@link Ext.form.HtmlEditor}
254 label            {@link Ext.form.Label}
255 numberfield      {@link Ext.form.NumberField}
256 radio            {@link Ext.form.Radio}
257 radiogroup       {@link Ext.form.RadioGroup}
258 textarea         {@link Ext.form.TextArea}
259 textfield        {@link Ext.form.TextField}
260 timefield        {@link Ext.form.TimeField}
261 trigger          {@link Ext.form.TriggerField}
262
263 Chart components
264 ---------------------------------------
265 chart            {@link Ext.chart.Chart}
266 barchart         {@link Ext.chart.BarChart}
267 cartesianchart   {@link Ext.chart.CartesianChart}
268 columnchart      {@link Ext.chart.ColumnChart}
269 linechart        {@link Ext.chart.LineChart}
270 piechart         {@link Ext.chart.PieChart}
271
272 Store xtypes
273 ---------------------------------------
274 arraystore       {@link Ext.data.ArrayStore}
275 directstore      {@link Ext.data.DirectStore}
276 groupingstore    {@link Ext.data.GroupingStore}
277 jsonstore        {@link Ext.data.JsonStore}
278 simplestore      {@link Ext.data.SimpleStore}      (deprecated; use arraystore)
279 store            {@link Ext.data.Store}
280 xmlstore         {@link Ext.data.XmlStore}
281 </pre>
282  * @constructor
283  * @param {Ext.Element/String/Object} config The configuration options may be specified as either:
284  * <div class="mdetail-params"><ul>
285  * <li><b>an element</b> :
286  * <p class="sub-desc">it is set as the internal element and its id used as the component id</p></li>
287  * <li><b>a string</b> :
288  * <p class="sub-desc">it is assumed to be the id of an existing element and is used as the component id</p></li>
289  * <li><b>anything else</b> :
290  * <p class="sub-desc">it is assumed to be a standard config object and is applied to the component</p></li>
291  * </ul></div>
292  */
293 Ext.Component = function(config){
294     config = config || {};
295     if(config.initialConfig){
296         if(config.isAction){           // actions
297             this.baseAction = config;
298         }
299         config = config.initialConfig; // component cloning / action set up
300     }else if(config.tagName || config.dom || Ext.isString(config)){ // element object
301         config = {applyTo: config, id: config.id || config};
302     }
303
304     /**
305      * This Component's initial configuration specification. Read-only.
306      * @type Object
307      * @property initialConfig
308      */
309     this.initialConfig = config;
310
311     Ext.apply(this, config);
312     this.addEvents(
313         /**
314          * @event added
315          * Fires when a component is added to an Ext.Container
316          * @param {Ext.Component} this
317          * @param {Ext.Container} ownerCt Container which holds the component
318          * @param {number} index Position at which the component was added
319          */
320         'added',
321         /**
322          * @event disable
323          * Fires after the component is disabled.
324          * @param {Ext.Component} this
325          */
326         'disable',
327         /**
328          * @event enable
329          * Fires after the component is enabled.
330          * @param {Ext.Component} this
331          */
332         'enable',
333         /**
334          * @event beforeshow
335          * Fires before the component is shown by calling the {@link #show} method.
336          * Return false from an event handler to stop the show.
337          * @param {Ext.Component} this
338          */
339         'beforeshow',
340         /**
341          * @event show
342          * Fires after the component is shown when calling the {@link #show} method.
343          * @param {Ext.Component} this
344          */
345         'show',
346         /**
347          * @event beforehide
348          * Fires before the component is hidden by calling the {@link #hide} method.
349          * Return false from an event handler to stop the hide.
350          * @param {Ext.Component} this
351          */
352         'beforehide',
353         /**
354          * @event hide
355          * Fires after the component is hidden.
356          * Fires after the component is hidden when calling the {@link #hide} method.
357          * @param {Ext.Component} this
358          */
359         'hide',
360         /**
361          * @event removed
362          * Fires when a component is removed from an Ext.Container
363          * @param {Ext.Component} this
364          * @param {Ext.Container} ownerCt Container which holds the component
365          */
366         'removed',
367         /**
368          * @event beforerender
369          * Fires before the component is {@link #rendered}. Return false from an
370          * event handler to stop the {@link #render}.
371          * @param {Ext.Component} this
372          */
373         'beforerender',
374         /**
375          * @event render
376          * Fires after the component markup is {@link #rendered}.
377          * @param {Ext.Component} this
378          */
379         'render',
380         /**
381          * @event afterrender
382          * <p>Fires after the component rendering is finished.</p>
383          * <p>The afterrender event is fired after this Component has been {@link #rendered}, been postprocesed
384          * by any afterRender method defined for the Component, and, if {@link #stateful}, after state
385          * has been restored.</p>
386          * @param {Ext.Component} this
387          */
388         'afterrender',
389         /**
390          * @event beforedestroy
391          * Fires before the component is {@link #destroy}ed. Return false from an event handler to stop the {@link #destroy}.
392          * @param {Ext.Component} this
393          */
394         'beforedestroy',
395         /**
396          * @event destroy
397          * Fires after the component is {@link #destroy}ed.
398          * @param {Ext.Component} this
399          */
400         'destroy',
401         /**
402          * @event beforestaterestore
403          * Fires before the state of the component is restored. Return false from an event handler to stop the restore.
404          * @param {Ext.Component} this
405          * @param {Object} state The hash of state values returned from the StateProvider. If this
406          * event is not vetoed, then the state object is passed to <b><tt>applyState</tt></b>. By default,
407          * that simply copies property values into this Component. The method maybe overriden to
408          * provide custom state restoration.
409          */
410         'beforestaterestore',
411         /**
412          * @event staterestore
413          * Fires after the state of the component is restored.
414          * @param {Ext.Component} this
415          * @param {Object} state The hash of state values returned from the StateProvider. This is passed
416          * to <b><tt>applyState</tt></b>. By default, that simply copies property values into this
417          * Component. The method maybe overriden to provide custom state restoration.
418          */
419         'staterestore',
420         /**
421          * @event beforestatesave
422          * Fires before the state of the component is saved to the configured state provider. Return false to stop the save.
423          * @param {Ext.Component} this
424          * @param {Object} state The hash of state values. This is determined by calling
425          * <b><tt>getState()</tt></b> on the Component. This method must be provided by the
426          * developer to return whetever representation of state is required, by default, Ext.Component
427          * has a null implementation.
428          */
429         'beforestatesave',
430         /**
431          * @event statesave
432          * Fires after the state of the component is saved to the configured state provider.
433          * @param {Ext.Component} this
434          * @param {Object} state The hash of state values. This is determined by calling
435          * <b><tt>getState()</tt></b> on the Component. This method must be provided by the
436          * developer to return whetever representation of state is required, by default, Ext.Component
437          * has a null implementation.
438          */
439         'statesave'
440     );
441     this.getId();
442     Ext.ComponentMgr.register(this);
443     Ext.Component.superclass.constructor.call(this);
444
445     if(this.baseAction){
446         this.baseAction.addComponent(this);
447     }
448
449     this.initComponent();
450
451     if(this.plugins){
452         if(Ext.isArray(this.plugins)){
453             for(var i = 0, len = this.plugins.length; i < len; i++){
454                 this.plugins[i] = this.initPlugin(this.plugins[i]);
455             }
456         }else{
457             this.plugins = this.initPlugin(this.plugins);
458         }
459     }
460
461     if(this.stateful !== false){
462         this.initState();
463     }
464
465     if(this.applyTo){
466         this.applyToMarkup(this.applyTo);
467         delete this.applyTo;
468     }else if(this.renderTo){
469         this.render(this.renderTo);
470         delete this.renderTo;
471     }
472 };
473
474 // private
475 Ext.Component.AUTO_ID = 1000;
476
477 Ext.extend(Ext.Component, Ext.util.Observable, {
478     // Configs below are used for all Components when rendered by FormLayout.
479     /**
480      * @cfg {String} fieldLabel <p>The label text to display next to this Component (defaults to '').</p>
481      * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container which
482      * has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout manager (e.g.
483      * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>).</p><br>
484      * <p>Also see <tt>{@link #hideLabel}</tt> and
485      * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</p>
486      * Example use:<pre><code>
487 new Ext.FormPanel({
488     height: 100,
489     renderTo: Ext.getBody(),
490     items: [{
491         xtype: 'textfield',
492         fieldLabel: 'Name'
493     }]
494 });
495 </code></pre>
496      */
497     /**
498      * @cfg {String} labelStyle <p>A CSS style specification string to apply directly to this field's
499      * label.  Defaults to the container's labelStyle value if set (e.g.,
500      * <tt>{@link Ext.layout.FormLayout#labelStyle}</tt> , or '').</p>
501      * <br><p><b>Note</b>: see the note for <code>{@link #clearCls}</code>.</p><br>
502      * <p>Also see <code>{@link #hideLabel}</code> and
503      * <code>{@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</code></p>
504      * Example use:<pre><code>
505 new Ext.FormPanel({
506     height: 100,
507     renderTo: Ext.getBody(),
508     items: [{
509         xtype: 'textfield',
510         fieldLabel: 'Name',
511         labelStyle: 'font-weight:bold;'
512     }]
513 });
514 </code></pre>
515      */
516     /**
517      * @cfg {String} labelSeparator <p>The separator to display after the text of each
518      * <tt>{@link #fieldLabel}</tt>.  This property may be configured at various levels.
519      * The order of precedence is:
520      * <div class="mdetail-params"><ul>
521      * <li>field / component level</li>
522      * <li>container level</li>
523      * <li>{@link Ext.layout.FormLayout#labelSeparator layout level} (defaults to colon <tt>':'</tt>)</li>
524      * </ul></div>
525      * To display no separator for this field's label specify empty string ''.</p>
526      * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</tt>.</p><br>
527      * <p>Also see <tt>{@link #hideLabel}</tt> and
528      * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</p>
529      * Example use:<pre><code>
530 new Ext.FormPanel({
531     height: 100,
532     renderTo: Ext.getBody(),
533     layoutConfig: {
534         labelSeparator: '~'   // layout config has lowest priority (defaults to ':')
535     },
536     {@link Ext.layout.FormLayout#labelSeparator labelSeparator}: '>>',     // config at container level
537     items: [{
538         xtype: 'textfield',
539         fieldLabel: 'Field 1',
540         labelSeparator: '...' // field/component level config supersedes others
541     },{
542         xtype: 'textfield',
543         fieldLabel: 'Field 2' // labelSeparator will be '='
544     }]
545 });
546 </code></pre>
547      */
548     /**
549      * @cfg {Boolean} hideLabel <p><tt>true</tt> to completely hide the label element
550      * ({@link #fieldLabel label} and {@link #labelSeparator separator}). Defaults to <tt>false</tt>.
551      * By default, even if you do not specify a <tt>{@link #fieldLabel}</tt> the space will still be
552      * reserved so that the field will line up with other fields that do have labels.
553      * Setting this to <tt>true</tt> will cause the field to not reserve that space.</p>
554      * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</tt>.</p><br>
555      * Example use:<pre><code>
556 new Ext.FormPanel({
557     height: 100,
558     renderTo: Ext.getBody(),
559     items: [{
560         xtype: 'textfield'
561         hideLabel: true
562     }]
563 });
564 </code></pre>
565      */
566     /**
567      * @cfg {String} clearCls <p>The CSS class used to to apply to the special clearing div rendered
568      * directly after each form field wrapper to provide field clearing (defaults to
569      * <tt>'x-form-clear-left'</tt>).</p>
570      * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container
571      * which has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout
572      * manager (e.g. {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) and either a
573      * <tt>{@link #fieldLabel}</tt> is specified or <tt>isFormField=true</tt> is specified.</p><br>
574      * <p>See {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl} also.</p>
575      */
576     /**
577      * @cfg {String} itemCls
578      * <p><b>Note</b>: this config is only used when this Component is rendered by a Container which
579      * has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout manager (e.g.
580      * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>).</p><br>
581      * <p>An additional CSS class to apply to the div wrapping the form item
582      * element of this field.  If supplied, <tt>itemCls</tt> at the <b>field</b> level will override
583      * the default <tt>itemCls</tt> supplied at the <b>container</b> level. The value specified for
584      * <tt>itemCls</tt> will be added to the default class (<tt>'x-form-item'</tt>).</p>
585      * <p>Since it is applied to the item wrapper (see
586      * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}), it allows
587      * you to write standard CSS rules that can apply to the field, the label (if specified), or
588      * any other element within the markup for the field.</p>
589      * <br><p><b>Note</b>: see the note for <tt>{@link #fieldLabel}</tt>.</p><br>
590      * Example use:<pre><code>
591 // Apply a style to the field&#39;s label:
592 &lt;style>
593     .required .x-form-item-label {font-weight:bold;color:red;}
594 &lt;/style>
595
596 new Ext.FormPanel({
597     height: 100,
598     renderTo: Ext.getBody(),
599     items: [{
600         xtype: 'textfield',
601         fieldLabel: 'Name',
602         itemCls: 'required' //this label will be styled
603     },{
604         xtype: 'textfield',
605         fieldLabel: 'Favorite Color'
606     }]
607 });
608 </code></pre>
609      */
610
611     // Configs below are used for all Components when rendered by AnchorLayout.
612     /**
613      * @cfg {String} anchor <p><b>Note</b>: this config is only used when this Component is rendered
614      * by a Container which has been configured to use an <b>{@link Ext.layout.AnchorLayout AnchorLayout}</b>
615      * based layout manager, for example:<div class="mdetail-params"><ul>
616      * <li>{@link Ext.form.FormPanel}</li>
617      * <li>specifying <code>layout: 'anchor' // or 'form', or 'absolute'</code></li>
618      * </ul></div></p>
619      * <p>See {@link Ext.layout.AnchorLayout}.{@link Ext.layout.AnchorLayout#anchor anchor} also.</p>
620      */
621
622     /**
623      * @cfg {String} id
624      * <p>The <b>unique</b> id of this component (defaults to an {@link #getId auto-assigned id}).
625      * You should assign an id if you need to be able to access the component later and you do
626      * not have an object reference available (e.g., using {@link Ext}.{@link Ext#getCmp getCmp}).</p>
627      * <p>Note that this id will also be used as the element id for the containing HTML element
628      * that is rendered to the page for this component. This allows you to write id-based CSS
629      * rules to style the specific instance of this component uniquely, and also to select
630      * sub-elements using this component's id as the parent.</p>
631      * <p><b>Note</b>: to avoid complications imposed by a unique <tt>id</tt> also see
632      * <code>{@link #itemId}</code> and <code>{@link #ref}</code>.</p>
633      * <p><b>Note</b>: to access the container of an item see <code>{@link #ownerCt}</code>.</p>
634      */
635     /**
636      * @cfg {String} itemId
637      * <p>An <tt>itemId</tt> can be used as an alternative way to get a reference to a component
638      * when no object reference is available.  Instead of using an <code>{@link #id}</code> with
639      * {@link Ext}.{@link Ext#getCmp getCmp}, use <code>itemId</code> with
640      * {@link Ext.Container}.{@link Ext.Container#getComponent getComponent} which will retrieve
641      * <code>itemId</code>'s or <tt>{@link #id}</tt>'s. Since <code>itemId</code>'s are an index to the
642      * container's internal MixedCollection, the <code>itemId</code> is scoped locally to the container --
643      * avoiding potential conflicts with {@link Ext.ComponentMgr} which requires a <b>unique</b>
644      * <code>{@link #id}</code>.</p>
645      * <pre><code>
646 var c = new Ext.Panel({ //
647     {@link Ext.BoxComponent#height height}: 300,
648     {@link #renderTo}: document.body,
649     {@link Ext.Container#layout layout}: 'auto',
650     {@link Ext.Container#items items}: [
651         {
652             itemId: 'p1',
653             {@link Ext.Panel#title title}: 'Panel 1',
654             {@link Ext.BoxComponent#height height}: 150
655         },
656         {
657             itemId: 'p2',
658             {@link Ext.Panel#title title}: 'Panel 2',
659             {@link Ext.BoxComponent#height height}: 150
660         }
661     ]
662 })
663 p1 = c.{@link Ext.Container#getComponent getComponent}('p1'); // not the same as {@link Ext#getCmp Ext.getCmp()}
664 p2 = p1.{@link #ownerCt}.{@link Ext.Container#getComponent getComponent}('p2'); // reference via a sibling
665      * </code></pre>
666      * <p>Also see <tt>{@link #id}</tt> and <code>{@link #ref}</code>.</p>
667      * <p><b>Note</b>: to access the container of an item see <tt>{@link #ownerCt}</tt>.</p>
668      */
669     /**
670      * @cfg {String} xtype
671      * The registered <tt>xtype</tt> to create. This config option is not used when passing
672      * a config object into a constructor. This config option is used only when
673      * lazy instantiation is being used, and a child item of a Container is being
674      * specified not as a fully instantiated Component, but as a <i>Component config
675      * object</i>. The <tt>xtype</tt> will be looked up at render time up to determine what
676      * type of child Component to create.<br><br>
677      * The predefined xtypes are listed {@link Ext.Component here}.
678      * <br><br>
679      * If you subclass Components to create your own Components, you may register
680      * them using {@link Ext.ComponentMgr#registerType} in order to be able to
681      * take advantage of lazy instantiation and rendering.
682      */
683     /**
684      * @cfg {String} ptype
685      * The registered <tt>ptype</tt> to create. This config option is not used when passing
686      * a config object into a constructor. This config option is used only when
687      * lazy instantiation is being used, and a Plugin is being
688      * specified not as a fully instantiated Component, but as a <i>Component config
689      * object</i>. The <tt>ptype</tt> will be looked up at render time up to determine what
690      * type of Plugin to create.<br><br>
691      * If you create your own Plugins, you may register them using
692      * {@link Ext.ComponentMgr#registerPlugin} in order to be able to
693      * take advantage of lazy instantiation and rendering.
694      */
695     /**
696      * @cfg {String} cls
697      * An optional extra CSS class that will be added to this component's Element (defaults to '').  This can be
698      * useful for adding customized styles to the component or any of its children using standard CSS rules.
699      */
700     /**
701      * @cfg {String} overCls
702      * An optional extra CSS class that will be added to this component's Element when the mouse moves
703      * over the Element, and removed when the mouse moves out. (defaults to '').  This can be
704      * useful for adding customized 'active' or 'hover' styles to the component or any of its children using standard CSS rules.
705      */
706     /**
707      * @cfg {String} style
708      * A custom style specification to be applied to this component's Element.  Should be a valid argument to
709      * {@link Ext.Element#applyStyles}.
710      * <pre><code>
711 new Ext.Panel({
712     title: 'Some Title',
713     renderTo: Ext.getBody(),
714     width: 400, height: 300,
715     layout: 'form',
716     items: [{
717         xtype: 'textarea',
718         style: {
719             width: '95%',
720             marginBottom: '10px'
721         }
722     },
723         new Ext.Button({
724             text: 'Send',
725             minWidth: '100',
726             style: {
727                 marginBottom: '10px'
728             }
729         })
730     ]
731 });
732      * </code></pre>
733      */
734     /**
735      * @cfg {String} ctCls
736      * <p>An optional extra CSS class that will be added to this component's container. This can be useful for
737      * adding customized styles to the container or any of its children using standard CSS rules.  See
738      * {@link Ext.layout.ContainerLayout}.{@link Ext.layout.ContainerLayout#extraCls extraCls} also.</p>
739      * <p><b>Note</b>: <tt>ctCls</tt> defaults to <tt>''</tt> except for the following class
740      * which assigns a value by default:
741      * <div class="mdetail-params"><ul>
742      * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-layout-ct'</tt></li>
743      * </ul></div>
744      * To configure the above Class with an extra CSS class append to the default.  For example,
745      * for BoxLayout (Hbox and Vbox):<pre><code>
746      * ctCls: 'x-box-layout-ct custom-class'
747      * </code></pre>
748      * </p>
749      */
750     /**
751      * @cfg {Boolean} disabled
752      * Render this component disabled (default is false).
753      */
754     disabled : false,
755     /**
756      * @cfg {Boolean} hidden
757      * Render this component hidden (default is false). If <tt>true</tt>, the
758      * {@link #hide} method will be called internally.
759      */
760     hidden : false,
761     /**
762      * @cfg {Object/Array} plugins
763      * An object or array of objects that will provide custom functionality for this component.  The only
764      * requirement for a valid plugin is that it contain an init method that accepts a reference of type Ext.Component.
765      * When a component is created, if any plugins are available, the component will call the init method on each
766      * plugin, passing a reference to itself.  Each plugin can then call methods or respond to events on the
767      * component as needed to provide its functionality.
768      */
769     /**
770      * @cfg {Mixed} applyTo
771      * <p>Specify the id of the element, a DOM element or an existing Element corresponding to a DIV
772      * that is already present in the document that specifies some structural markup for this
773      * component.</p><div><ul>
774      * <li><b>Description</b> : <ul>
775      * <div class="sub-desc">When <tt>applyTo</tt> is used, constituent parts of the component can also be specified
776      * by id or CSS class name within the main element, and the component being created may attempt
777      * to create its subcomponents from that markup if applicable.</div>
778      * </ul></li>
779      * <li><b>Notes</b> : <ul>
780      * <div class="sub-desc">When using this config, a call to render() is not required.</div>
781      * <div class="sub-desc">If applyTo is specified, any value passed for {@link #renderTo} will be ignored and the target
782      * element's parent node will automatically be used as the component's container.</div>
783      * </ul></li>
784      * </ul></div>
785      */
786     /**
787      * @cfg {Mixed} renderTo
788      * <p>Specify the id of the element, a DOM element or an existing Element that this component
789      * will be rendered into.</p><div><ul>
790      * <li><b>Notes</b> : <ul>
791      * <div class="sub-desc">Do <u>not</u> use this option if the Component is to be a child item of
792      * a {@link Ext.Container Container}. It is the responsibility of the
793      * {@link Ext.Container Container}'s {@link Ext.Container#layout layout manager}
794      * to render and manage its child items.</div>
795      * <div class="sub-desc">When using this config, a call to render() is not required.</div>
796      * </ul></li>
797      * </ul></div>
798      * <p>See <tt>{@link #render}</tt> also.</p>
799      */
800     /**
801      * @cfg {Boolean} stateful
802      * <p>A flag which causes the Component to attempt to restore the state of
803      * internal properties from a saved state on startup. The component must have
804      * either a <code>{@link #stateId}</code> or <code>{@link #id}</code> assigned
805      * for state to be managed. Auto-generated ids are not guaranteed to be stable
806      * across page loads and cannot be relied upon to save and restore the same
807      * state for a component.<p>
808      * <p>For state saving to work, the state manager's provider must have been
809      * set to an implementation of {@link Ext.state.Provider} which overrides the
810      * {@link Ext.state.Provider#set set} and {@link Ext.state.Provider#get get}
811      * methods to save and recall name/value pairs. A built-in implementation,
812      * {@link Ext.state.CookieProvider} is available.</p>
813      * <p>To set the state provider for the current page:</p>
814      * <pre><code>
815 Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
816     expires: new Date(new Date().getTime()+(1000*60*60*24*7)), //7 days from now
817 }));
818      * </code></pre>
819      * <p>A stateful Component attempts to save state when one of the events
820      * listed in the <code>{@link #stateEvents}</code> configuration fires.</p>
821      * <p>To save state, a stateful Component first serializes its state by
822      * calling <b><code>getState</code></b>. By default, this function does
823      * nothing. The developer must provide an implementation which returns an
824      * object hash which represents the Component's restorable state.</p>
825      * <p>The value yielded by getState is passed to {@link Ext.state.Manager#set}
826      * which uses the configured {@link Ext.state.Provider} to save the object
827      * keyed by the Component's <code>{@link stateId}</code>, or, if that is not
828      * specified, its <code>{@link #id}</code>.</p>
829      * <p>During construction, a stateful Component attempts to <i>restore</i>
830      * its state by calling {@link Ext.state.Manager#get} passing the
831      * <code>{@link #stateId}</code>, or, if that is not specified, the
832      * <code>{@link #id}</code>.</p>
833      * <p>The resulting object is passed to <b><code>applyState</code></b>.
834      * The default implementation of <code>applyState</code> simply copies
835      * properties into the object, but a developer may override this to support
836      * more behaviour.</p>
837      * <p>You can perform extra processing on state save and restore by attaching
838      * handlers to the {@link #beforestaterestore}, {@link #staterestore},
839      * {@link #beforestatesave} and {@link #statesave} events.</p>
840      */
841     /**
842      * @cfg {String} stateId
843      * The unique id for this component to use for state management purposes
844      * (defaults to the component id if one was set, otherwise null if the
845      * component is using a generated id).
846      * <p>See <code>{@link #stateful}</code> for an explanation of saving and
847      * restoring Component state.</p>
848      */
849     /**
850      * @cfg {Array} stateEvents
851      * <p>An array of events that, when fired, should trigger this component to
852      * save its state (defaults to none). <code>stateEvents</code> may be any type
853      * of event supported by this component, including browser or custom events
854      * (e.g., <tt>['click', 'customerchange']</tt>).</p>
855      * <p>See <code>{@link #stateful}</code> for an explanation of saving and
856      * restoring Component state.</p>
857      */
858     /**
859      * @cfg {Mixed} autoEl
860      * <p>A tag name or {@link Ext.DomHelper DomHelper} spec used to create the {@link #getEl Element} which will
861      * encapsulate this Component.</p>
862      * <p>You do not normally need to specify this. For the base classes {@link Ext.Component}, {@link Ext.BoxComponent},
863      * and {@link Ext.Container}, this defaults to <b><tt>'div'</tt></b>. The more complex Ext classes use a more complex
864      * DOM structure created by their own onRender methods.</p>
865      * <p>This is intended to allow the developer to create application-specific utility Components encapsulated by
866      * different DOM elements. Example usage:</p><pre><code>
867 {
868     xtype: 'box',
869     autoEl: {
870         tag: 'img',
871         src: 'http://www.example.com/example.jpg'
872     }
873 }, {
874     xtype: 'box',
875     autoEl: {
876         tag: 'blockquote',
877         html: 'autoEl is cool!'
878     }
879 }, {
880     xtype: 'container',
881     autoEl: 'ul',
882     cls: 'ux-unordered-list',
883     items: {
884         xtype: 'box',
885         autoEl: 'li',
886         html: 'First list item'
887     }
888 }
889 </code></pre>
890      */
891     autoEl : 'div',
892
893     /**
894      * @cfg {String} disabledClass
895      * CSS class added to the component when it is disabled (defaults to 'x-item-disabled').
896      */
897     disabledClass : 'x-item-disabled',
898     /**
899      * @cfg {Boolean} allowDomMove
900      * Whether the component can move the Dom node when rendering (defaults to true).
901      */
902     allowDomMove : true,
903     /**
904      * @cfg {Boolean} autoShow
905      * True if the component should check for hidden classes (e.g. 'x-hidden' or 'x-hide-display') and remove
906      * them on render (defaults to false).
907      */
908     autoShow : false,
909     /**
910      * @cfg {String} hideMode
911      * <p>How this component should be hidden. Supported values are <tt>'visibility'</tt>
912      * (css visibility), <tt>'offsets'</tt> (negative offset position) and <tt>'display'</tt>
913      * (css display).</p>
914      * <br><p><b>Note</b>: the default of <tt>'display'</tt> is generally preferred
915      * since items are automatically laid out when they are first shown (no sizing
916      * is done while hidden).</p>
917      */
918     hideMode : 'display',
919     /**
920      * @cfg {Boolean} hideParent
921      * True to hide and show the component's container when hide/show is called on the component, false to hide
922      * and show the component itself (defaults to false).  For example, this can be used as a shortcut for a hide
923      * button on a window by setting hide:true on the button when adding it to its parent container.
924      */
925     hideParent : false,
926     /**
927      * <p>The {@link Ext.Element} which encapsulates this Component. Read-only.</p>
928      * <p>This will <i>usually</i> be a &lt;DIV> element created by the class's onRender method, but
929      * that may be overridden using the <code>{@link #autoEl}</code> config.</p>
930      * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br>
931      * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners
932      * for this Component's own Observable events), see the {@link Ext.util.Observable#listeners listeners}
933      * config for a suggestion, or use a render listener directly:</p><pre><code>
934 new Ext.Panel({
935     title: 'The Clickable Panel',
936     listeners: {
937         render: function(p) {
938             // Append the Panel to the click handler&#39;s argument list.
939             p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));
940         },
941         single: true  // Remove the listener after first invocation
942     }
943 });
944 </code></pre>
945      * <p>See also <tt>{@link #getEl getEl}</p>
946      * @type Ext.Element
947      * @property el
948      */
949     /**
950      * This Component's owner {@link Ext.Container Container} (defaults to undefined, and is set automatically when
951      * this Component is added to a Container).  Read-only.
952      * <p><b>Note</b>: to access items within the Container see <tt>{@link #itemId}</tt>.</p>
953      * @type Ext.Container
954      * @property ownerCt
955      */
956     /**
957      * True if this component is hidden. Read-only.
958      * @type Boolean
959      * @property hidden
960      */
961     /**
962      * True if this component is disabled. Read-only.
963      * @type Boolean
964      * @property disabled
965      */
966     /**
967      * True if this component has been rendered. Read-only.
968      * @type Boolean
969      * @property rendered
970      */
971     rendered : false,
972
973     /**
974      * @cfg {String} contentEl
975      * <p>Optional. Specify an existing HTML element, or the <code>id</code> of an existing HTML element to use as the content
976      * for this component.</p>
977      * <ul>
978      * <li><b>Description</b> :
979      * <div class="sub-desc">This config option is used to take an existing HTML element and place it in the layout element
980      * 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>
981      * <li><b>Notes</b> :
982      * <div class="sub-desc">The specified HTML element is appended to the layout element of the component <i>after any configured
983      * {@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>
984      * <div class="sub-desc">The specified HTML element used will not participate in any <code><b>{@link Ext.Container#layout layout}</b></code>
985      * scheme that the Component may use. It is just HTML. Layouts operate on child <code><b>{@link Ext.Container#items items}</b></code>.</div>
986      * <div class="sub-desc">Add either the <code>x-hidden</code> or the <code>x-hide-display</code> CSS class to
987      * prevent a brief flicker of the content before it is rendered to the panel.</div></li>
988      * </ul>
989      */
990     /**
991      * @cfg {String/Object} html
992      * An HTML fragment, or a {@link Ext.DomHelper DomHelper} specification to use as the layout element
993      * content (defaults to ''). The HTML content is added after the component is rendered,
994      * so the document will not contain this HTML at the time the {@link #render} event is fired.
995      * This content is inserted into the body <i>before</i> any configured {@link #contentEl} is appended.
996      */
997
998     /**
999      * @cfg {Mixed} tpl
1000      * An <bold>{@link Ext.Template}</bold>, <bold>{@link Ext.XTemplate}</bold>
1001      * or an array of strings to form an Ext.XTemplate.
1002      * Used in conjunction with the <code>{@link #data}</code> and 
1003      * <code>{@link #tplWriteMode}</code> configurations.
1004      */
1005
1006     /**
1007      * @cfg {String} tplWriteMode The Ext.(X)Template method to use when
1008      * updating the content area of the Component. Defaults to <tt>'overwrite'</tt>
1009      * (see <code>{@link Ext.XTemplate#overwrite}</code>).
1010      */
1011     tplWriteMode : 'overwrite',
1012
1013     /**
1014      * @cfg {Mixed} data
1015      * The initial set of data to apply to the <code>{@link #tpl}</code> to
1016      * update the content area of the Component.
1017      */
1018
1019
1020     // private
1021     ctype : 'Ext.Component',
1022
1023     // private
1024     actionMode : 'el',
1025
1026     // private
1027     getActionEl : function(){
1028         return this[this.actionMode];
1029     },
1030
1031     initPlugin : function(p){
1032         if(p.ptype && !Ext.isFunction(p.init)){
1033             p = Ext.ComponentMgr.createPlugin(p);
1034         }else if(Ext.isString(p)){
1035             p = Ext.ComponentMgr.createPlugin({
1036                 ptype: p
1037             });
1038         }
1039         p.init(this);
1040         return p;
1041     },
1042
1043     /* // protected
1044      * Function to be implemented by Component subclasses to be part of standard component initialization flow (it is empty by default).
1045      * <pre><code>
1046 // Traditional constructor:
1047 Ext.Foo = function(config){
1048     // call superclass constructor:
1049     Ext.Foo.superclass.constructor.call(this, config);
1050
1051     this.addEvents({
1052         // add events
1053     });
1054 };
1055 Ext.extend(Ext.Foo, Ext.Bar, {
1056    // class body
1057 }
1058
1059 // initComponent replaces the constructor:
1060 Ext.Foo = Ext.extend(Ext.Bar, {
1061     initComponent : function(){
1062         // call superclass initComponent
1063         Ext.Container.superclass.initComponent.call(this);
1064
1065         this.addEvents({
1066             // add events
1067         });
1068     }
1069 }
1070 </code></pre>
1071      */
1072     initComponent : Ext.emptyFn,
1073
1074     /**
1075      * <p>Render this Component into the passed HTML element.</p>
1076      * <p><b>If you are using a {@link Ext.Container Container} object to house this Component, then
1077      * do not use the render method.</b></p>
1078      * <p>A Container's child Components are rendered by that Container's
1079      * {@link Ext.Container#layout layout} manager when the Container is first rendered.</p>
1080      * <p>Certain layout managers allow dynamic addition of child components. Those that do
1081      * include {@link Ext.layout.CardLayout}, {@link Ext.layout.AnchorLayout},
1082      * {@link Ext.layout.FormLayout}, {@link Ext.layout.TableLayout}.</p>
1083      * <p>If the Container is already rendered when a new child Component is added, you may need to call
1084      * the Container's {@link Ext.Container#doLayout doLayout} to refresh the view which causes any
1085      * unrendered child Components to be rendered. This is required so that you can add multiple
1086      * child components if needed while only refreshing the layout once.</p>
1087      * <p>When creating complex UIs, it is important to remember that sizing and positioning
1088      * of child items is the responsibility of the Container's {@link Ext.Container#layout layout} manager.
1089      * If you expect child items to be sized in response to user interactions, you must
1090      * configure the Container with a layout manager which creates and manages the type of layout you
1091      * have in mind.</p>
1092      * <p><b>Omitting the Container's {@link Ext.Container#layout layout} config means that a basic
1093      * layout manager is used which does nothing but render child components sequentially into the
1094      * Container. No sizing or positioning will be performed in this situation.</b></p>
1095      * @param {Element/HTMLElement/String} container (optional) The element this Component should be
1096      * rendered into. If it is being created from existing markup, this should be omitted.
1097      * @param {String/Number} position (optional) The element ID or DOM node index within the container <b>before</b>
1098      * which this component will be inserted (defaults to appending to the end of the container)
1099      */
1100     render : function(container, position){
1101         if(!this.rendered && this.fireEvent('beforerender', this) !== false){
1102             if(!container && this.el){
1103                 this.el = Ext.get(this.el);
1104                 container = this.el.dom.parentNode;
1105                 this.allowDomMove = false;
1106             }
1107             this.container = Ext.get(container);
1108             if(this.ctCls){
1109                 this.container.addClass(this.ctCls);
1110             }
1111             this.rendered = true;
1112             if(position !== undefined){
1113                 if(Ext.isNumber(position)){
1114                     position = this.container.dom.childNodes[position];
1115                 }else{
1116                     position = Ext.getDom(position);
1117                 }
1118             }
1119             this.onRender(this.container, position || null);
1120             if(this.autoShow){
1121                 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
1122             }
1123             if(this.cls){
1124                 this.el.addClass(this.cls);
1125                 delete this.cls;
1126             }
1127             if(this.style){
1128                 this.el.applyStyles(this.style);
1129                 delete this.style;
1130             }
1131             if(this.overCls){
1132                 this.el.addClassOnOver(this.overCls);
1133             }
1134             this.fireEvent('render', this);
1135
1136
1137             // Populate content of the component with html, contentEl or
1138             // a tpl.
1139             var contentTarget = this.getContentTarget();
1140             if (this.html){
1141                 contentTarget.update(Ext.DomHelper.markup(this.html));
1142                 delete this.html;
1143             }
1144             if (this.contentEl){
1145                 var ce = Ext.getDom(this.contentEl);
1146                 Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
1147                 contentTarget.appendChild(ce);
1148             }
1149             if (this.tpl) {
1150                 if (!this.tpl.compile) {
1151                     this.tpl = new Ext.XTemplate(this.tpl);
1152                 }
1153                 if (this.data) {
1154                     this.tpl[this.tplWriteMode](contentTarget, this.data);
1155                     delete this.data;
1156                 }
1157             }
1158             this.afterRender(this.container);
1159
1160
1161             if(this.hidden){
1162                 // call this so we don't fire initial hide events.
1163                 this.doHide();
1164             }
1165             if(this.disabled){
1166                 // pass silent so the event doesn't fire the first time.
1167                 this.disable(true);
1168             }
1169
1170             if(this.stateful !== false){
1171                 this.initStateEvents();
1172             }
1173             this.fireEvent('afterrender', this);
1174         }
1175         return this;
1176     },
1177
1178
1179     /**
1180      * Update the content area of a component.
1181      * @param {Mixed} htmlOrData
1182      * If this component has been configured with a template via the tpl config
1183      * then it will use this argument as data to populate the template.
1184      * If this component was not configured with a template, the components
1185      * content area will be updated via Ext.Element update
1186      * @param {Boolean} loadScripts
1187      * (optional) Only legitimate when using the html configuration. Defaults to false
1188      * @param {Function} callback
1189      * (optional) Only legitimate when using the html configuration. Callback to execute when scripts have finished loading
1190      */
1191     update: function(htmlOrData, loadScripts, cb) {
1192         var contentTarget = this.getContentTarget();
1193         if (this.tpl && typeof htmlOrData !== "string") {
1194             this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
1195         } else {
1196             var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
1197             contentTarget.update(html, loadScripts, cb);
1198         }
1199     },
1200
1201
1202     /**
1203      * @private
1204      * Method to manage awareness of when components are added to their
1205      * respective Container, firing an added event.
1206      * References are established at add time rather than at render time.
1207      * @param {Ext.Container} container Container which holds the component
1208      * @param {number} pos Position at which the component was added
1209      */
1210     onAdded : function(container, pos) {
1211         this.ownerCt = container;
1212         this.initRef();
1213         this.fireEvent('added', this, container, pos);
1214     },
1215
1216     /**
1217      * @private
1218      * Method to manage awareness of when components are removed from their
1219      * respective Container, firing an removed event. References are properly
1220      * cleaned up after removing a component from its owning container.
1221      */
1222     onRemoved : function() {
1223         this.removeRef();
1224         this.fireEvent('removed', this, this.ownerCt);
1225         delete this.ownerCt;
1226     },
1227
1228     /**
1229      * @private
1230      * Method to establish a reference to a component.
1231      */
1232     initRef : function() {
1233         /**
1234          * @cfg {String} ref
1235          * <p>A path specification, relative to the Component's <code>{@link #ownerCt}</code>
1236          * specifying into which ancestor Container to place a named reference to this Component.</p>
1237          * <p>The ancestor axis can be traversed by using '/' characters in the path.
1238          * For example, to put a reference to a Toolbar Button into <i>the Panel which owns the Toolbar</i>:</p><pre><code>
1239 var myGrid = new Ext.grid.EditorGridPanel({
1240     title: 'My EditorGridPanel',
1241     store: myStore,
1242     colModel: myColModel,
1243     tbar: [{
1244         text: 'Save',
1245         handler: saveChanges,
1246         disabled: true,
1247         ref: '../saveButton'
1248     }],
1249     listeners: {
1250         afteredit: function() {
1251 //          The button reference is in the GridPanel
1252             myGrid.saveButton.enable();
1253         }
1254     }
1255 });
1256 </code></pre>
1257          * <p>In the code above, if the <code>ref</code> had been <code>'saveButton'</code>
1258          * the reference would have been placed into the Toolbar. Each '/' in the <code>ref</code>
1259          * moves up one level from the Component's <code>{@link #ownerCt}</code>.</p>
1260          * <p>Also see the <code>{@link #added}</code> and <code>{@link #removed}</code> events.</p>
1261          */
1262         if(this.ref && !this.refOwner){
1263             var levels = this.ref.split('/'),
1264                 last = levels.length, 
1265                 i = 0,
1266                 t = this;
1267                 
1268             while(t && i < last){
1269                 t = t.ownerCt;
1270                 ++i;
1271             }
1272             if(t){
1273                 t[this.refName = levels[--i]] = this;
1274                 /**
1275                  * @type Ext.Container
1276                  * @property refOwner
1277                  * The ancestor Container into which the {@link #ref} reference was inserted if this Component
1278                  * is a child of a Container, and has been configured with a <code>ref</code>.
1279                  */
1280                 this.refOwner = t;
1281             }
1282         }
1283     },
1284
1285     removeRef : function() {
1286         if (this.refOwner && this.refName) {
1287             delete this.refOwner[this.refName];
1288             delete this.refOwner;
1289         }
1290     },
1291
1292     // private
1293     initState : function(){
1294         if(Ext.state.Manager){
1295             var id = this.getStateId();
1296             if(id){
1297                 var state = Ext.state.Manager.get(id);
1298                 if(state){
1299                     if(this.fireEvent('beforestaterestore', this, state) !== false){
1300                         this.applyState(Ext.apply({}, state));
1301                         this.fireEvent('staterestore', this, state);
1302                     }
1303                 }
1304             }
1305         }
1306     },
1307
1308     // private
1309     getStateId : function(){
1310         return this.stateId || ((this.id.indexOf('ext-comp-') == 0 || this.id.indexOf('ext-gen') == 0) ? null : this.id);
1311     },
1312
1313     // private
1314     initStateEvents : function(){
1315         if(this.stateEvents){
1316             for(var i = 0, e; e = this.stateEvents[i]; i++){
1317                 this.on(e, this.saveState, this, {delay:100});
1318             }
1319         }
1320     },
1321
1322     // private
1323     applyState : function(state){
1324         if(state){
1325             Ext.apply(this, state);
1326         }
1327     },
1328
1329     // private
1330     getState : function(){
1331         return null;
1332     },
1333
1334     // private
1335     saveState : function(){
1336         if(Ext.state.Manager && this.stateful !== false){
1337             var id = this.getStateId();
1338             if(id){
1339                 var state = this.getState();
1340                 if(this.fireEvent('beforestatesave', this, state) !== false){
1341                     Ext.state.Manager.set(id, state);
1342                     this.fireEvent('statesave', this, state);
1343                 }
1344             }
1345         }
1346     },
1347
1348     /**
1349      * Apply this component to existing markup that is valid. With this function, no call to render() is required.
1350      * @param {String/HTMLElement} el
1351      */
1352     applyToMarkup : function(el){
1353         this.allowDomMove = false;
1354         this.el = Ext.get(el);
1355         this.render(this.el.dom.parentNode);
1356     },
1357
1358     /**
1359      * Adds a CSS class to the component's underlying element.
1360      * @param {string} cls The CSS class name to add
1361      * @return {Ext.Component} this
1362      */
1363     addClass : function(cls){
1364         if(this.el){
1365             this.el.addClass(cls);
1366         }else{
1367             this.cls = this.cls ? this.cls + ' ' + cls : cls;
1368         }
1369         return this;
1370     },
1371
1372     /**
1373      * Removes a CSS class from the component's underlying element.
1374      * @param {string} cls The CSS class name to remove
1375      * @return {Ext.Component} this
1376      */
1377     removeClass : function(cls){
1378         if(this.el){
1379             this.el.removeClass(cls);
1380         }else if(this.cls){
1381             this.cls = this.cls.split(' ').remove(cls).join(' ');
1382         }
1383         return this;
1384     },
1385
1386     // private
1387     // default function is not really useful
1388     onRender : function(ct, position){
1389         if(!this.el && this.autoEl){
1390             if(Ext.isString(this.autoEl)){
1391                 this.el = document.createElement(this.autoEl);
1392             }else{
1393                 var div = document.createElement('div');
1394                 Ext.DomHelper.overwrite(div, this.autoEl);
1395                 this.el = div.firstChild;
1396             }
1397             if (!this.el.id) {
1398                 this.el.id = this.getId();
1399             }
1400         }
1401         if(this.el){
1402             this.el = Ext.get(this.el);
1403             if(this.allowDomMove !== false){
1404                 ct.dom.insertBefore(this.el.dom, position);
1405                 if (div) {
1406                     Ext.removeNode(div);
1407                     div = null;
1408                 }
1409             }
1410         }
1411     },
1412
1413     // private
1414     getAutoCreate : function(){
1415         var cfg = Ext.isObject(this.autoCreate) ?
1416                       this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
1417         if(this.id && !cfg.id){
1418             cfg.id = this.id;
1419         }
1420         return cfg;
1421     },
1422
1423     // private
1424     afterRender : Ext.emptyFn,
1425
1426     /**
1427      * Destroys this component by purging any event listeners, removing the component's element from the DOM,
1428      * removing the component from its {@link Ext.Container} (if applicable) and unregistering it from
1429      * {@link Ext.ComponentMgr}.  Destruction is generally handled automatically by the framework and this method
1430      * should usually not need to be called directly.
1431      *
1432      */
1433     destroy : function(){
1434         if(!this.isDestroyed){
1435             if(this.fireEvent('beforedestroy', this) !== false){
1436                 this.destroying = true;
1437                 this.beforeDestroy();
1438                 if(this.ownerCt && this.ownerCt.remove){
1439                     this.ownerCt.remove(this, false);
1440                 }
1441                 if(this.rendered){
1442                     this.el.remove();
1443                     if(this.actionMode == 'container' || this.removeMode == 'container'){
1444                         this.container.remove();
1445                     }
1446                 }
1447                 this.onDestroy();
1448                 Ext.ComponentMgr.unregister(this);
1449                 this.fireEvent('destroy', this);
1450                 this.purgeListeners();
1451                 this.destroying = false;
1452                 this.isDestroyed = true;
1453             }
1454         }
1455     },
1456
1457     deleteMembers : function(){
1458         var args = arguments;
1459         for(var i = 0, len = args.length; i < len; ++i){
1460             delete this[args[i]];
1461         }
1462     },
1463
1464     // private
1465     beforeDestroy : Ext.emptyFn,
1466
1467     // private
1468     onDestroy  : Ext.emptyFn,
1469
1470     /**
1471      * <p>Returns the {@link Ext.Element} which encapsulates this Component.</p>
1472      * <p>This will <i>usually</i> be a &lt;DIV> element created by the class's onRender method, but
1473      * that may be overridden using the {@link #autoEl} config.</p>
1474      * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br>
1475      * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners
1476      * for this Component's own Observable events), see the {@link #listeners} config for a suggestion,
1477      * or use a render listener directly:</p><pre><code>
1478 new Ext.Panel({
1479     title: 'The Clickable Panel',
1480     listeners: {
1481         render: function(p) {
1482             // Append the Panel to the click handler&#39;s argument list.
1483             p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));
1484         },
1485         single: true  // Remove the listener after first invocation
1486     }
1487 });
1488 </code></pre>
1489      * @return {Ext.Element} The Element which encapsulates this Component.
1490      */
1491     getEl : function(){
1492         return this.el;
1493     },
1494
1495     // private
1496     getContentTarget : function(){
1497         return this.el;
1498     },
1499
1500     /**
1501      * Returns the <code>id</code> of this component or automatically generates and
1502      * returns an <code>id</code> if an <code>id</code> is not defined yet:<pre><code>
1503      * 'ext-comp-' + (++Ext.Component.AUTO_ID)
1504      * </code></pre>
1505      * @return {String} id
1506      */
1507     getId : function(){
1508         return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
1509     },
1510
1511     /**
1512      * Returns the <code>{@link #itemId}</code> of this component.  If an
1513      * <code>{@link #itemId}</code> was not assigned through configuration the
1514      * <code>id</code> is returned using <code>{@link #getId}</code>.
1515      * @return {String}
1516      */
1517     getItemId : function(){
1518         return this.itemId || this.getId();
1519     },
1520
1521     /**
1522      * Try to focus this component.
1523      * @param {Boolean} selectText (optional) If applicable, true to also select the text in this component
1524      * @param {Boolean/Number} delay (optional) Delay the focus this number of milliseconds (true for 10 milliseconds)
1525      * @return {Ext.Component} this
1526      */
1527     focus : function(selectText, delay){
1528         if(delay){
1529             this.focus.defer(Ext.isNumber(delay) ? delay : 10, this, [selectText, false]);
1530             return;
1531         }
1532         if(this.rendered){
1533             this.el.focus();
1534             if(selectText === true){
1535                 this.el.dom.select();
1536             }
1537         }
1538         return this;
1539     },
1540
1541     // private
1542     blur : function(){
1543         if(this.rendered){
1544             this.el.blur();
1545         }
1546         return this;
1547     },
1548
1549     /**
1550      * Disable this component and fire the 'disable' event.
1551      * @return {Ext.Component} this
1552      */
1553     disable : function(/* private */ silent){
1554         if(this.rendered){
1555             this.onDisable();
1556         }
1557         this.disabled = true;
1558         if(silent !== true){
1559             this.fireEvent('disable', this);
1560         }
1561         return this;
1562     },
1563
1564     // private
1565     onDisable : function(){
1566         this.getActionEl().addClass(this.disabledClass);
1567         this.el.dom.disabled = true;
1568     },
1569
1570     /**
1571      * Enable this component and fire the 'enable' event.
1572      * @return {Ext.Component} this
1573      */
1574     enable : function(){
1575         if(this.rendered){
1576             this.onEnable();
1577         }
1578         this.disabled = false;
1579         this.fireEvent('enable', this);
1580         return this;
1581     },
1582
1583     // private
1584     onEnable : function(){
1585         this.getActionEl().removeClass(this.disabledClass);
1586         this.el.dom.disabled = false;
1587     },
1588
1589     /**
1590      * Convenience function for setting disabled/enabled by boolean.
1591      * @param {Boolean} disabled
1592      * @return {Ext.Component} this
1593      */
1594     setDisabled : function(disabled){
1595         return this[disabled ? 'disable' : 'enable']();
1596     },
1597
1598     /**
1599      * Show this component.  Listen to the '{@link #beforeshow}' event and return
1600      * <tt>false</tt> to cancel showing the component.  Fires the '{@link #show}'
1601      * event after showing the component.
1602      * @return {Ext.Component} this
1603      */
1604     show : function(){
1605         if(this.fireEvent('beforeshow', this) !== false){
1606             this.hidden = false;
1607             if(this.autoRender){
1608                 this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
1609             }
1610             if(this.rendered){
1611                 this.onShow();
1612             }
1613             this.fireEvent('show', this);
1614         }
1615         return this;
1616     },
1617
1618     // private
1619     onShow : function(){
1620         this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);
1621     },
1622
1623     /**
1624      * Hide this component.  Listen to the '{@link #beforehide}' event and return
1625      * <tt>false</tt> to cancel hiding the component.  Fires the '{@link #hide}'
1626      * event after hiding the component. Note this method is called internally if
1627      * the component is configured to be <code>{@link #hidden}</code>.
1628      * @return {Ext.Component} this
1629      */
1630     hide : function(){
1631         if(this.fireEvent('beforehide', this) !== false){
1632             this.doHide();
1633             this.fireEvent('hide', this);
1634         }
1635         return this;
1636     },
1637
1638     // private
1639     doHide: function(){
1640         this.hidden = true;
1641         if(this.rendered){
1642             this.onHide();
1643         }
1644     },
1645
1646     // private
1647     onHide : function(){
1648         this.getVisibilityEl().addClass('x-hide-' + this.hideMode);
1649     },
1650
1651     // private
1652     getVisibilityEl : function(){
1653         return this.hideParent ? this.container : this.getActionEl();
1654     },
1655
1656     /**
1657      * Convenience function to hide or show this component by boolean.
1658      * @param {Boolean} visible True to show, false to hide
1659      * @return {Ext.Component} this
1660      */
1661     setVisible : function(visible){
1662         return this[visible ? 'show' : 'hide']();
1663     },
1664
1665     /**
1666      * Returns true if this component is visible.
1667      * @return {Boolean} True if this component is visible, false otherwise.
1668      */
1669     isVisible : function(){
1670         return this.rendered && this.getVisibilityEl().isVisible();
1671     },
1672
1673     /**
1674      * Clone the current component using the original config values passed into this instance by default.
1675      * @param {Object} overrides A new config containing any properties to override in the cloned version.
1676      * An id property can be passed on this object, otherwise one will be generated to avoid duplicates.
1677      * @return {Ext.Component} clone The cloned copy of this component
1678      */
1679     cloneConfig : function(overrides){
1680         overrides = overrides || {};
1681         var id = overrides.id || Ext.id();
1682         var cfg = Ext.applyIf(overrides, this.initialConfig);
1683         cfg.id = id; // prevent dup id
1684         return new this.constructor(cfg);
1685     },
1686
1687     /**
1688      * Gets the xtype for this component as registered with {@link Ext.ComponentMgr}. For a list of all
1689      * available xtypes, see the {@link Ext.Component} header. Example usage:
1690      * <pre><code>
1691 var t = new Ext.form.TextField();
1692 alert(t.getXType());  // alerts 'textfield'
1693 </code></pre>
1694      * @return {String} The xtype
1695      */
1696     getXType : function(){
1697         return this.constructor.xtype;
1698     },
1699
1700     /**
1701      * <p>Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended
1702      * from the xtype (default) or whether it is directly of the xtype specified (shallow = true).</p>
1703      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1704      * to participate in determination of inherited xtypes.</b></p>
1705      * <p>For a list of all available xtypes, see the {@link Ext.Component} header.</p>
1706      * <p>Example usage:</p>
1707      * <pre><code>
1708 var t = new Ext.form.TextField();
1709 var isText = t.isXType('textfield');        // true
1710 var isBoxSubclass = t.isXType('box');       // true, descended from BoxComponent
1711 var isBoxInstance = t.isXType('box', true); // false, not a direct BoxComponent instance
1712 </code></pre>
1713      * @param {String} xtype The xtype to check for this Component
1714      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
1715      * the default), or true to check whether this Component is directly of the specified xtype.
1716      * @return {Boolean} True if this component descends from the specified xtype, false otherwise.
1717      */
1718     isXType : function(xtype, shallow){
1719         //assume a string by default
1720         if (Ext.isFunction(xtype)){
1721             xtype = xtype.xtype; //handle being passed the class, e.g. Ext.Component
1722         }else if (Ext.isObject(xtype)){
1723             xtype = xtype.constructor.xtype; //handle being passed an instance
1724         }
1725
1726         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
1727     },
1728
1729     /**
1730      * <p>Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all
1731      * available xtypes, see the {@link Ext.Component} header.</p>
1732      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1733      * to participate in determination of inherited xtypes.</b></p>
1734      * <p>Example usage:</p>
1735      * <pre><code>
1736 var t = new Ext.form.TextField();
1737 alert(t.getXTypes());  // alerts 'component/box/field/textfield'
1738 </code></pre>
1739      * @return {String} The xtype hierarchy string
1740      */
1741     getXTypes : function(){
1742         var tc = this.constructor;
1743         if(!tc.xtypes){
1744             var c = [], sc = this;
1745             while(sc && sc.constructor.xtype){
1746                 c.unshift(sc.constructor.xtype);
1747                 sc = sc.constructor.superclass;
1748             }
1749             tc.xtypeChain = c;
1750             tc.xtypes = c.join('/');
1751         }
1752         return tc.xtypes;
1753     },
1754
1755     /**
1756      * Find a container above this component at any level by a custom function. If the passed function returns
1757      * true, the container will be returned.
1758      * @param {Function} fn The custom function to call with the arguments (container, this component).
1759      * @return {Ext.Container} The first Container for which the custom function returns true
1760      */
1761     findParentBy : function(fn) {
1762         for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
1763         return p || null;
1764     },
1765
1766     /**
1767      * Find a container above this component at any level by xtype or class
1768      * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
1769      * @return {Ext.Container} The first Container which matches the given xtype or class
1770      */
1771     findParentByType : function(xtype) {
1772         return Ext.isFunction(xtype) ?
1773             this.findParentBy(function(p){
1774                 return p.constructor === xtype;
1775             }) :
1776             this.findParentBy(function(p){
1777                 return p.constructor.xtype === xtype;
1778             });
1779     },
1780
1781     // protected
1782     getPositionEl : function(){
1783         return this.positionEl || this.el;
1784     },
1785
1786     // private
1787     purgeListeners : function(){
1788         Ext.Component.superclass.purgeListeners.call(this);
1789         if(this.mons){
1790             this.on('beforedestroy', this.clearMons, this, {single: true});
1791         }
1792     },
1793
1794     // private
1795     clearMons : function(){
1796         Ext.each(this.mons, function(m){
1797             m.item.un(m.ename, m.fn, m.scope);
1798         }, this);
1799         this.mons = [];
1800     },
1801
1802     // private
1803     createMons: function(){
1804         if(!this.mons){
1805             this.mons = [];
1806             this.on('beforedestroy', this.clearMons, this, {single: true});
1807         }
1808     },
1809
1810     /**
1811      * <p>Adds listeners to any Observable object (or Elements) which are automatically removed when this Component
1812      * is destroyed. Usage:</p><code><pre>
1813 myGridPanel.mon(myGridPanel.getSelectionModel(), 'selectionchange', handleSelectionChange, null, {buffer: 50});
1814 </pre></code>
1815      * <p>or:</p><code><pre>
1816 myGridPanel.mon(myGridPanel.getSelectionModel(), {
1817     selectionchange: handleSelectionChange,
1818     buffer: 50
1819 });
1820 </pre></code>
1821      * @param {Observable|Element} item The item to which to add a listener/listeners.
1822      * @param {Object|String} ename The event name, or an object containing event name properties.
1823      * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this
1824      * is the handler function.
1825      * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this
1826      * is the scope (<code>this</code> reference) in which the handler function is executed.
1827      * @param {Object} opt Optional. If the <code>ename</code> parameter was an event name, this
1828      * is the {@link Ext.util.Observable#addListener addListener} options.
1829      */
1830     mon : function(item, ename, fn, scope, opt){
1831         this.createMons();
1832         if(Ext.isObject(ename)){
1833             var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
1834
1835             var o = ename;
1836             for(var e in o){
1837                 if(propRe.test(e)){
1838                     continue;
1839                 }
1840                 if(Ext.isFunction(o[e])){
1841                     // shared options
1842                     this.mons.push({
1843                         item: item, ename: e, fn: o[e], scope: o.scope
1844                     });
1845                     item.on(e, o[e], o.scope, o);
1846                 }else{
1847                     // individual options
1848                     this.mons.push({
1849                         item: item, ename: e, fn: o[e], scope: o.scope
1850                     });
1851                     item.on(e, o[e]);
1852                 }
1853             }
1854             return;
1855         }
1856
1857         this.mons.push({
1858             item: item, ename: ename, fn: fn, scope: scope
1859         });
1860         item.on(ename, fn, scope, opt);
1861     },
1862
1863     /**
1864      * Removes listeners that were added by the {@link #mon} method.
1865      * @param {Observable|Element} item The item from which to remove a listener/listeners.
1866      * @param {Object|String} ename The event name, or an object containing event name properties.
1867      * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this
1868      * is the handler function.
1869      * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this
1870      * is the scope (<code>this</code> reference) in which the handler function is executed.
1871      */
1872     mun : function(item, ename, fn, scope){
1873         var found, mon;
1874         this.createMons();
1875         for(var i = 0, len = this.mons.length; i < len; ++i){
1876             mon = this.mons[i];
1877             if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){
1878                 this.mons.splice(i, 1);
1879                 item.un(ename, fn, scope);
1880                 found = true;
1881                 break;
1882             }
1883         }
1884         return found;
1885     },
1886
1887     /**
1888      * Returns the next component in the owning container
1889      * @return Ext.Component
1890      */
1891     nextSibling : function(){
1892         if(this.ownerCt){
1893             var index = this.ownerCt.items.indexOf(this);
1894             if(index != -1 && index+1 < this.ownerCt.items.getCount()){
1895                 return this.ownerCt.items.itemAt(index+1);
1896             }
1897         }
1898         return null;
1899     },
1900
1901     /**
1902      * Returns the previous component in the owning container
1903      * @return Ext.Component
1904      */
1905     previousSibling : function(){
1906         if(this.ownerCt){
1907             var index = this.ownerCt.items.indexOf(this);
1908             if(index > 0){
1909                 return this.ownerCt.items.itemAt(index-1);
1910             }
1911         }
1912         return null;
1913     },
1914
1915     /**
1916      * Provides the link for Observable's fireEvent method to bubble up the ownership hierarchy.
1917      * @return {Ext.Container} the Container which owns this Component.
1918      */
1919     getBubbleTarget : function(){
1920         return this.ownerCt;
1921     }
1922 });
1923
1924 Ext.reg('component', Ext.Component);/**\r
1925  * @class Ext.Action\r
1926  * <p>An Action is a piece of reusable functionality that can be abstracted out of any particular component so that it\r
1927  * can be usefully shared among multiple components.  Actions let you share handlers, configuration options and UI\r
1928  * updates across any components that support the Action interface (primarily {@link Ext.Toolbar}, {@link Ext.Button}\r
1929  * and {@link Ext.menu.Menu} components).</p>\r
1930  * <p>Aside from supporting the config object interface, any component that needs to use Actions must also support\r
1931  * the following method list, as these will be called as needed by the Action class: setText(string), setIconCls(string),\r
1932  * setDisabled(boolean), setVisible(boolean) and setHandler(function).</p>\r
1933  * Example usage:<br>\r
1934  * <pre><code>\r
1935 // Define the shared action.  Each component below will have the same\r
1936 // display text and icon, and will display the same message on click.\r
1937 var action = new Ext.Action({\r
1938     {@link #text}: 'Do something',\r
1939     {@link #handler}: function(){\r
1940         Ext.Msg.alert('Click', 'You did something.');\r
1941     },\r
1942     {@link #iconCls}: 'do-something',\r
1943     {@link #itemId}: 'myAction'\r
1944 });\r
1945 \r
1946 var panel = new Ext.Panel({\r
1947     title: 'Actions',\r
1948     width: 500,\r
1949     height: 300,\r
1950     tbar: [\r
1951         // Add the action directly to a toolbar as a menu button\r
1952         action,\r
1953         {\r
1954             text: 'Action Menu',\r
1955             // Add the action to a menu as a text item\r
1956             menu: [action]\r
1957         }\r
1958     ],\r
1959     items: [\r
1960         // Add the action to the panel body as a standard button\r
1961         new Ext.Button(action)\r
1962     ],\r
1963     renderTo: Ext.getBody()\r
1964 });\r
1965 \r
1966 // Change the text for all components using the action\r
1967 action.setText('Something else');\r
1968 \r
1969 // Reference an action through a container using the itemId\r
1970 var btn = panel.getComponent('myAction');\r
1971 var aRef = btn.baseAction;\r
1972 aRef.setText('New text');\r
1973 </code></pre>\r
1974  * @constructor\r
1975  * @param {Object} config The configuration options\r
1976  */\r
1977 Ext.Action = Ext.extend(Object, {\r
1978     /**\r
1979      * @cfg {String} text The text to set for all components using this action (defaults to '').\r
1980      */\r
1981     /**\r
1982      * @cfg {String} iconCls\r
1983      * The CSS class selector that specifies a background image to be used as the header icon for\r
1984      * all components using this action (defaults to '').\r
1985      * <p>An example of specifying a custom icon class would be something like:\r
1986      * </p><pre><code>\r
1987 // specify the property in the config for the class:\r
1988      ...\r
1989      iconCls: 'do-something'\r
1990 \r
1991 // css class that specifies background image to be used as the icon image:\r
1992 .do-something { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }\r
1993 </code></pre>\r
1994      */\r
1995     /**\r
1996      * @cfg {Boolean} disabled True to disable all components using this action, false to enable them (defaults to false).\r
1997      */\r
1998     /**\r
1999      * @cfg {Boolean} hidden True to hide all components using this action, false to show them (defaults to false).\r
2000      */\r
2001     /**\r
2002      * @cfg {Function} handler The function that will be invoked by each component tied to this action\r
2003      * when the component's primary event is triggered (defaults to undefined).\r
2004      */\r
2005     /**\r
2006      * @cfg {String} itemId\r
2007      * See {@link Ext.Component}.{@link Ext.Component#itemId itemId}.\r
2008      */\r
2009     /**\r
2010      * @cfg {Object} scope The scope (<tt><b>this</b></tt> reference) in which the\r
2011      * <code>{@link #handler}</code> is executed. Defaults to this Button.\r
2012      */\r
2013 \r
2014     constructor : function(config){\r
2015         this.initialConfig = config;\r
2016         this.itemId = config.itemId = (config.itemId || config.id || Ext.id());\r
2017         this.items = [];\r
2018     },\r
2019     \r
2020     // private\r
2021     isAction : true,\r
2022 \r
2023     /**\r
2024      * Sets the text to be displayed by all components using this action.\r
2025      * @param {String} text The text to display\r
2026      */\r
2027     setText : function(text){\r
2028         this.initialConfig.text = text;\r
2029         this.callEach('setText', [text]);\r
2030     },\r
2031 \r
2032     /**\r
2033      * Gets the text currently displayed by all components using this action.\r
2034      */\r
2035     getText : function(){\r
2036         return this.initialConfig.text;\r
2037     },\r
2038 \r
2039     /**\r
2040      * Sets the icon CSS class for all components using this action.  The class should supply\r
2041      * a background image that will be used as the icon image.\r
2042      * @param {String} cls The CSS class supplying the icon image\r
2043      */\r
2044     setIconClass : function(cls){\r
2045         this.initialConfig.iconCls = cls;\r
2046         this.callEach('setIconClass', [cls]);\r
2047     },\r
2048 \r
2049     /**\r
2050      * Gets the icon CSS class currently used by all components using this action.\r
2051      */\r
2052     getIconClass : function(){\r
2053         return this.initialConfig.iconCls;\r
2054     },\r
2055 \r
2056     /**\r
2057      * Sets the disabled state of all components using this action.  Shortcut method\r
2058      * for {@link #enable} and {@link #disable}.\r
2059      * @param {Boolean} disabled True to disable the component, false to enable it\r
2060      */\r
2061     setDisabled : function(v){\r
2062         this.initialConfig.disabled = v;\r
2063         this.callEach('setDisabled', [v]);\r
2064     },\r
2065 \r
2066     /**\r
2067      * Enables all components using this action.\r
2068      */\r
2069     enable : function(){\r
2070         this.setDisabled(false);\r
2071     },\r
2072 \r
2073     /**\r
2074      * Disables all components using this action.\r
2075      */\r
2076     disable : function(){\r
2077         this.setDisabled(true);\r
2078     },\r
2079 \r
2080     /**\r
2081      * Returns true if the components using this action are currently disabled, else returns false.  \r
2082      */\r
2083     isDisabled : function(){\r
2084         return this.initialConfig.disabled;\r
2085     },\r
2086 \r
2087     /**\r
2088      * Sets the hidden state of all components using this action.  Shortcut method\r
2089      * for <code>{@link #hide}</code> and <code>{@link #show}</code>.\r
2090      * @param {Boolean} hidden True to hide the component, false to show it\r
2091      */\r
2092     setHidden : function(v){\r
2093         this.initialConfig.hidden = v;\r
2094         this.callEach('setVisible', [!v]);\r
2095     },\r
2096 \r
2097     /**\r
2098      * Shows all components using this action.\r
2099      */\r
2100     show : function(){\r
2101         this.setHidden(false);\r
2102     },\r
2103 \r
2104     /**\r
2105      * Hides all components using this action.\r
2106      */\r
2107     hide : function(){\r
2108         this.setHidden(true);\r
2109     },\r
2110 \r
2111     /**\r
2112      * Returns true if the components using this action are currently hidden, else returns false.  \r
2113      */\r
2114     isHidden : function(){\r
2115         return this.initialConfig.hidden;\r
2116     },\r
2117 \r
2118     /**\r
2119      * Sets the function that will be called by each Component using this action when its primary event is triggered.\r
2120      * @param {Function} fn The function that will be invoked by the action's components.  The function\r
2121      * will be called with no arguments.\r
2122      * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed. Defaults to the Component firing the event.\r
2123      */\r
2124     setHandler : function(fn, scope){\r
2125         this.initialConfig.handler = fn;\r
2126         this.initialConfig.scope = scope;\r
2127         this.callEach('setHandler', [fn, scope]);\r
2128     },\r
2129 \r
2130     /**\r
2131      * Executes the specified function once for each Component currently tied to this action.  The function passed\r
2132      * in should accept a single argument that will be an object that supports the basic Action config/method interface.\r
2133      * @param {Function} fn The function to execute for each component\r
2134      * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed.  Defaults to the Component.\r
2135      */\r
2136     each : function(fn, scope){\r
2137         Ext.each(this.items, fn, scope);\r
2138     },\r
2139 \r
2140     // private\r
2141     callEach : function(fnName, args){\r
2142         var cs = this.items;\r
2143         for(var i = 0, len = cs.length; i < len; i++){\r
2144             cs[i][fnName].apply(cs[i], args);\r
2145         }\r
2146     },\r
2147 \r
2148     // private\r
2149     addComponent : function(comp){\r
2150         this.items.push(comp);\r
2151         comp.on('destroy', this.removeComponent, this);\r
2152     },\r
2153 \r
2154     // private\r
2155     removeComponent : function(comp){\r
2156         this.items.remove(comp);\r
2157     },\r
2158 \r
2159     /**\r
2160      * Executes this action manually using the handler function specified in the original config object\r
2161      * or the handler function set with <code>{@link #setHandler}</code>.  Any arguments passed to this\r
2162      * function will be passed on to the handler function.\r
2163      * @param {Mixed} arg1 (optional) Variable number of arguments passed to the handler function\r
2164      * @param {Mixed} arg2 (optional)\r
2165      * @param {Mixed} etc... (optional)\r
2166      */\r
2167     execute : function(){\r
2168         this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);\r
2169     }\r
2170 });\r
2171 /**
2172  * @class Ext.Layer
2173  * @extends Ext.Element
2174  * An extended {@link Ext.Element} object that supports a shadow and shim, constrain to viewport and
2175  * automatic maintaining of shadow/shim positions.
2176  * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true)
2177  * @cfg {String/Boolean} shadow True to automatically create an {@link Ext.Shadow}, or a string indicating the
2178  * shadow's display {@link Ext.Shadow#mode}. False to disable the shadow. (defaults to false)
2179  * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: 'div', cls: 'x-layer'}).
2180  * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true)
2181  * @cfg {String} cls CSS class to add to the element
2182  * @cfg {Number} zindex Starting z-index (defaults to 11000)
2183  * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 4)
2184  * @cfg {Boolean} useDisplay
2185  * Defaults to use css offsets to hide the Layer. Specify <tt>true</tt>
2186  * to use css style <tt>'display:none;'</tt> to hide the Layer.
2187  * @constructor
2188  * @param {Object} config An object with config options.
2189  * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element. If the element is not found it creates it.
2190  */
2191 (function(){
2192 Ext.Layer = function(config, existingEl){
2193     config = config || {};
2194     var dh = Ext.DomHelper;
2195     var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
2196     if(existingEl){
2197         this.dom = Ext.getDom(existingEl);
2198     }
2199     if(!this.dom){
2200         var o = config.dh || {tag: 'div', cls: 'x-layer'};
2201         this.dom = dh.append(pel, o);
2202     }
2203     if(config.cls){
2204         this.addClass(config.cls);
2205     }
2206     this.constrain = config.constrain !== false;
2207     this.setVisibilityMode(Ext.Element.VISIBILITY);
2208     if(config.id){
2209         this.id = this.dom.id = config.id;
2210     }else{
2211         this.id = Ext.id(this.dom);
2212     }
2213     this.zindex = config.zindex || this.getZIndex();
2214     this.position('absolute', this.zindex);
2215     if(config.shadow){
2216         this.shadowOffset = config.shadowOffset || 4;
2217         this.shadow = new Ext.Shadow({
2218             offset : this.shadowOffset,
2219             mode : config.shadow
2220         });
2221     }else{
2222         this.shadowOffset = 0;
2223     }
2224     this.useShim = config.shim !== false && Ext.useShims;
2225     this.useDisplay = config.useDisplay;
2226     this.hide();
2227 };
2228
2229 var supr = Ext.Element.prototype;
2230
2231 // shims are shared among layer to keep from having 100 iframes
2232 var shims = [];
2233
2234 Ext.extend(Ext.Layer, Ext.Element, {
2235
2236     getZIndex : function(){
2237         return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
2238     },
2239
2240     getShim : function(){
2241         if(!this.useShim){
2242             return null;
2243         }
2244         if(this.shim){
2245             return this.shim;
2246         }
2247         var shim = shims.shift();
2248         if(!shim){
2249             shim = this.createShim();
2250             shim.enableDisplayMode('block');
2251             shim.dom.style.display = 'none';
2252             shim.dom.style.visibility = 'visible';
2253         }
2254         var pn = this.dom.parentNode;
2255         if(shim.dom.parentNode != pn){
2256             pn.insertBefore(shim.dom, this.dom);
2257         }
2258         shim.setStyle('z-index', this.getZIndex()-2);
2259         this.shim = shim;
2260         return shim;
2261     },
2262
2263     hideShim : function(){
2264         if(this.shim){
2265             this.shim.setDisplayed(false);
2266             shims.push(this.shim);
2267             delete this.shim;
2268         }
2269     },
2270
2271     disableShadow : function(){
2272         if(this.shadow){
2273             this.shadowDisabled = true;
2274             this.shadow.hide();
2275             this.lastShadowOffset = this.shadowOffset;
2276             this.shadowOffset = 0;
2277         }
2278     },
2279
2280     enableShadow : function(show){
2281         if(this.shadow){
2282             this.shadowDisabled = false;
2283             this.shadowOffset = this.lastShadowOffset;
2284             delete this.lastShadowOffset;
2285             if(show){
2286                 this.sync(true);
2287             }
2288         }
2289     },
2290
2291     // private
2292     // this code can execute repeatedly in milliseconds (i.e. during a drag) so
2293     // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
2294     sync : function(doShow){
2295         var sw = this.shadow;
2296         if(!this.updating && this.isVisible() && (sw || this.useShim)){
2297             var sh = this.getShim();
2298
2299             var w = this.getWidth(),
2300                 h = this.getHeight();
2301
2302             var l = this.getLeft(true),
2303                 t = this.getTop(true);
2304
2305             if(sw && !this.shadowDisabled){
2306                 if(doShow && !sw.isVisible()){
2307                     sw.show(this);
2308                 }else{
2309                     sw.realign(l, t, w, h);
2310                 }
2311                 if(sh){
2312                     if(doShow){
2313                        sh.show();
2314                     }
2315                     // fit the shim behind the shadow, so it is shimmed too
2316                     var a = sw.adjusts, s = sh.dom.style;
2317                     s.left = (Math.min(l, l+a.l))+'px';
2318                     s.top = (Math.min(t, t+a.t))+'px';
2319                     s.width = (w+a.w)+'px';
2320                     s.height = (h+a.h)+'px';
2321                 }
2322             }else if(sh){
2323                 if(doShow){
2324                    sh.show();
2325                 }
2326                 sh.setSize(w, h);
2327                 sh.setLeftTop(l, t);
2328             }
2329
2330         }
2331     },
2332
2333     // private
2334     destroy : function(){
2335         this.hideShim();
2336         if(this.shadow){
2337             this.shadow.hide();
2338         }
2339         this.removeAllListeners();
2340         Ext.removeNode(this.dom);
2341         delete this.dom;
2342     },
2343
2344     remove : function(){
2345         this.destroy();
2346     },
2347
2348     // private
2349     beginUpdate : function(){
2350         this.updating = true;
2351     },
2352
2353     // private
2354     endUpdate : function(){
2355         this.updating = false;
2356         this.sync(true);
2357     },
2358
2359     // private
2360     hideUnders : function(negOffset){
2361         if(this.shadow){
2362             this.shadow.hide();
2363         }
2364         this.hideShim();
2365     },
2366
2367     // private
2368     constrainXY : function(){
2369         if(this.constrain){
2370             var vw = Ext.lib.Dom.getViewWidth(),
2371                 vh = Ext.lib.Dom.getViewHeight();
2372             var s = Ext.getDoc().getScroll();
2373
2374             var xy = this.getXY();
2375             var x = xy[0], y = xy[1];
2376             var so = this.shadowOffset;
2377             var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so;
2378             // only move it if it needs it
2379             var moved = false;
2380             // first validate right/bottom
2381             if((x + w) > vw+s.left){
2382                 x = vw - w - so;
2383                 moved = true;
2384             }
2385             if((y + h) > vh+s.top){
2386                 y = vh - h - so;
2387                 moved = true;
2388             }
2389             // then make sure top/left isn't negative
2390             if(x < s.left){
2391                 x = s.left;
2392                 moved = true;
2393             }
2394             if(y < s.top){
2395                 y = s.top;
2396                 moved = true;
2397             }
2398             if(moved){
2399                 if(this.avoidY){
2400                     var ay = this.avoidY;
2401                     if(y <= ay && (y+h) >= ay){
2402                         y = ay-h-5;
2403                     }
2404                 }
2405                 xy = [x, y];
2406                 this.storeXY(xy);
2407                 supr.setXY.call(this, xy);
2408                 this.sync();
2409             }
2410         }
2411         return this;
2412     },
2413
2414     isVisible : function(){
2415         return this.visible;
2416     },
2417
2418     // private
2419     showAction : function(){
2420         this.visible = true; // track visibility to prevent getStyle calls
2421         if(this.useDisplay === true){
2422             this.setDisplayed('');
2423         }else if(this.lastXY){
2424             supr.setXY.call(this, this.lastXY);
2425         }else if(this.lastLT){
2426             supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
2427         }
2428     },
2429
2430     // private
2431     hideAction : function(){
2432         this.visible = false;
2433         if(this.useDisplay === true){
2434             this.setDisplayed(false);
2435         }else{
2436             this.setLeftTop(-10000,-10000);
2437         }
2438     },
2439
2440     // overridden Element method
2441     setVisible : function(v, a, d, c, e){
2442         if(v){
2443             this.showAction();
2444         }
2445         if(a && v){
2446             var cb = function(){
2447                 this.sync(true);
2448                 if(c){
2449                     c();
2450                 }
2451             }.createDelegate(this);
2452             supr.setVisible.call(this, true, true, d, cb, e);
2453         }else{
2454             if(!v){
2455                 this.hideUnders(true);
2456             }
2457             var cb = c;
2458             if(a){
2459                 cb = function(){
2460                     this.hideAction();
2461                     if(c){
2462                         c();
2463                     }
2464                 }.createDelegate(this);
2465             }
2466             supr.setVisible.call(this, v, a, d, cb, e);
2467             if(v){
2468                 this.sync(true);
2469             }else if(!a){
2470                 this.hideAction();
2471             }
2472         }
2473         return this;
2474     },
2475
2476     storeXY : function(xy){
2477         delete this.lastLT;
2478         this.lastXY = xy;
2479     },
2480
2481     storeLeftTop : function(left, top){
2482         delete this.lastXY;
2483         this.lastLT = [left, top];
2484     },
2485
2486     // private
2487     beforeFx : function(){
2488         this.beforeAction();
2489         return Ext.Layer.superclass.beforeFx.apply(this, arguments);
2490     },
2491
2492     // private
2493     afterFx : function(){
2494         Ext.Layer.superclass.afterFx.apply(this, arguments);
2495         this.sync(this.isVisible());
2496     },
2497
2498     // private
2499     beforeAction : function(){
2500         if(!this.updating && this.shadow){
2501             this.shadow.hide();
2502         }
2503     },
2504
2505     // overridden Element method
2506     setLeft : function(left){
2507         this.storeLeftTop(left, this.getTop(true));
2508         supr.setLeft.apply(this, arguments);
2509         this.sync();
2510         return this;
2511     },
2512
2513     setTop : function(top){
2514         this.storeLeftTop(this.getLeft(true), top);
2515         supr.setTop.apply(this, arguments);
2516         this.sync();
2517         return this;
2518     },
2519
2520     setLeftTop : function(left, top){
2521         this.storeLeftTop(left, top);
2522         supr.setLeftTop.apply(this, arguments);
2523         this.sync();
2524         return this;
2525     },
2526
2527     setXY : function(xy, a, d, c, e){
2528         this.fixDisplay();
2529         this.beforeAction();
2530         this.storeXY(xy);
2531         var cb = this.createCB(c);
2532         supr.setXY.call(this, xy, a, d, cb, e);
2533         if(!a){
2534             cb();
2535         }
2536         return this;
2537     },
2538
2539     // private
2540     createCB : function(c){
2541         var el = this;
2542         return function(){
2543             el.constrainXY();
2544             el.sync(true);
2545             if(c){
2546                 c();
2547             }
2548         };
2549     },
2550
2551     // overridden Element method
2552     setX : function(x, a, d, c, e){
2553         this.setXY([x, this.getY()], a, d, c, e);
2554         return this;
2555     },
2556
2557     // overridden Element method
2558     setY : function(y, a, d, c, e){
2559         this.setXY([this.getX(), y], a, d, c, e);
2560         return this;
2561     },
2562
2563     // overridden Element method
2564     setSize : function(w, h, a, d, c, e){
2565         this.beforeAction();
2566         var cb = this.createCB(c);
2567         supr.setSize.call(this, w, h, a, d, cb, e);
2568         if(!a){
2569             cb();
2570         }
2571         return this;
2572     },
2573
2574     // overridden Element method
2575     setWidth : function(w, a, d, c, e){
2576         this.beforeAction();
2577         var cb = this.createCB(c);
2578         supr.setWidth.call(this, w, a, d, cb, e);
2579         if(!a){
2580             cb();
2581         }
2582         return this;
2583     },
2584
2585     // overridden Element method
2586     setHeight : function(h, a, d, c, e){
2587         this.beforeAction();
2588         var cb = this.createCB(c);
2589         supr.setHeight.call(this, h, a, d, cb, e);
2590         if(!a){
2591             cb();
2592         }
2593         return this;
2594     },
2595
2596     // overridden Element method
2597     setBounds : function(x, y, w, h, a, d, c, e){
2598         this.beforeAction();
2599         var cb = this.createCB(c);
2600         if(!a){
2601             this.storeXY([x, y]);
2602             supr.setXY.call(this, [x, y]);
2603             supr.setSize.call(this, w, h, a, d, cb, e);
2604             cb();
2605         }else{
2606             supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
2607         }
2608         return this;
2609     },
2610
2611     /**
2612      * Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
2613      * incremented by two more than the value passed in so that it always shows above any shadow or shim (the shadow
2614      * element, if any, will be assigned z-index + 1, and the shim element, if any, will be assigned the unmodified z-index).
2615      * @param {Number} zindex The new z-index to set
2616      * @return {this} The Layer
2617      */
2618     setZIndex : function(zindex){
2619         this.zindex = zindex;
2620         this.setStyle('z-index', zindex + 2);
2621         if(this.shadow){
2622             this.shadow.setZIndex(zindex + 1);
2623         }
2624         if(this.shim){
2625             this.shim.setStyle('z-index', zindex);
2626         }
2627         return this;
2628     }
2629 });
2630 })();
2631 /**
2632  * @class Ext.Shadow
2633  * Simple class that can provide a shadow effect for any element.  Note that the element MUST be absolutely positioned,
2634  * and the shadow does not provide any shimming.  This should be used only in simple cases -- for more advanced
2635  * functionality that can also provide the same shadow effect, see the {@link Ext.Layer} class.
2636  * @constructor
2637  * Create a new Shadow
2638  * @param {Object} config The config object
2639  */
2640 Ext.Shadow = function(config){
2641     Ext.apply(this, config);
2642     if(typeof this.mode != "string"){
2643         this.mode = this.defaultMode;
2644     }
2645     var o = this.offset, a = {h: 0};
2646     var rad = Math.floor(this.offset/2);
2647     switch(this.mode.toLowerCase()){ // all this hideous nonsense calculates the various offsets for shadows
2648         case "drop":
2649             a.w = 0;
2650             a.l = a.t = o;
2651             a.t -= 1;
2652             if(Ext.isIE){
2653                 a.l -= this.offset + rad;
2654                 a.t -= this.offset + rad;
2655                 a.w -= rad;
2656                 a.h -= rad;
2657                 a.t += 1;
2658             }
2659         break;
2660         case "sides":
2661             a.w = (o*2);
2662             a.l = -o;
2663             a.t = o-1;
2664             if(Ext.isIE){
2665                 a.l -= (this.offset - rad);
2666                 a.t -= this.offset + rad;
2667                 a.l += 1;
2668                 a.w -= (this.offset - rad)*2;
2669                 a.w -= rad + 1;
2670                 a.h -= 1;
2671             }
2672         break;
2673         case "frame":
2674             a.w = a.h = (o*2);
2675             a.l = a.t = -o;
2676             a.t += 1;
2677             a.h -= 2;
2678             if(Ext.isIE){
2679                 a.l -= (this.offset - rad);
2680                 a.t -= (this.offset - rad);
2681                 a.l += 1;
2682                 a.w -= (this.offset + rad + 1);
2683                 a.h -= (this.offset + rad);
2684                 a.h += 1;
2685             }
2686         break;
2687     };
2688
2689     this.adjusts = a;
2690 };
2691
2692 Ext.Shadow.prototype = {
2693     /**
2694      * @cfg {String} mode
2695      * The shadow display mode.  Supports the following options:<div class="mdetail-params"><ul>
2696      * <li><b><tt>sides</tt></b> : Shadow displays on both sides and bottom only</li>
2697      * <li><b><tt>frame</tt></b> : Shadow displays equally on all four sides</li>
2698      * <li><b><tt>drop</tt></b> : Traditional bottom-right drop shadow</li>
2699      * </ul></div>
2700      */
2701     /**
2702      * @cfg {String} offset
2703      * The number of pixels to offset the shadow from the element (defaults to <tt>4</tt>)
2704      */
2705     offset: 4,
2706
2707     // private
2708     defaultMode: "drop",
2709
2710     /**
2711      * Displays the shadow under the target element
2712      * @param {Mixed} targetEl The id or element under which the shadow should display
2713      */
2714     show : function(target){
2715         target = Ext.get(target);
2716         if(!this.el){
2717             this.el = Ext.Shadow.Pool.pull();
2718             if(this.el.dom.nextSibling != target.dom){
2719                 this.el.insertBefore(target);
2720             }
2721         }
2722         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
2723         if(Ext.isIE){
2724             this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
2725         }
2726         this.realign(
2727             target.getLeft(true),
2728             target.getTop(true),
2729             target.getWidth(),
2730             target.getHeight()
2731         );
2732         this.el.dom.style.display = "block";
2733     },
2734
2735     /**
2736      * Returns true if the shadow is visible, else false
2737      */
2738     isVisible : function(){
2739         return this.el ? true : false;  
2740     },
2741
2742     /**
2743      * Direct alignment when values are already available. Show must be called at least once before
2744      * calling this method to ensure it is initialized.
2745      * @param {Number} left The target element left position
2746      * @param {Number} top The target element top position
2747      * @param {Number} width The target element width
2748      * @param {Number} height The target element height
2749      */
2750     realign : function(l, t, w, h){
2751         if(!this.el){
2752             return;
2753         }
2754         var a = this.adjusts, d = this.el.dom, s = d.style;
2755         var iea = 0;
2756         s.left = (l+a.l)+"px";
2757         s.top = (t+a.t)+"px";
2758         var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
2759         if(s.width != sws || s.height != shs){
2760             s.width = sws;
2761             s.height = shs;
2762             if(!Ext.isIE){
2763                 var cn = d.childNodes;
2764                 var sww = Math.max(0, (sw-12))+"px";
2765                 cn[0].childNodes[1].style.width = sww;
2766                 cn[1].childNodes[1].style.width = sww;
2767                 cn[2].childNodes[1].style.width = sww;
2768                 cn[1].style.height = Math.max(0, (sh-12))+"px";
2769             }
2770         }
2771     },
2772
2773     /**
2774      * Hides this shadow
2775      */
2776     hide : function(){
2777         if(this.el){
2778             this.el.dom.style.display = "none";
2779             Ext.Shadow.Pool.push(this.el);
2780             delete this.el;
2781         }
2782     },
2783
2784     /**
2785      * Adjust the z-index of this shadow
2786      * @param {Number} zindex The new z-index
2787      */
2788     setZIndex : function(z){
2789         this.zIndex = z;
2790         if(this.el){
2791             this.el.setStyle("z-index", z);
2792         }
2793     }
2794 };
2795
2796 // Private utility class that manages the internal Shadow cache
2797 Ext.Shadow.Pool = function(){
2798     var p = [];
2799     var markup = Ext.isIE ?
2800                  '<div class="x-ie-shadow"></div>' :
2801                  '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';
2802     return {
2803         pull : function(){
2804             var sh = p.shift();
2805             if(!sh){
2806                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
2807                 sh.autoBoxAdjust = false;
2808             }
2809             return sh;
2810         },
2811
2812         push : function(sh){
2813             p.push(sh);
2814         }
2815     };
2816 }();/**
2817  * @class Ext.BoxComponent
2818  * @extends Ext.Component
2819  * <p>Base class for any {@link Ext.Component Component} that is to be sized as a box, using width and height.</p>
2820  * <p>BoxComponent provides automatic box model adjustments for sizing and positioning and will work correctly
2821  * within the Component rendering model.</p>
2822  * <p>A BoxComponent may be created as a custom Component which encapsulates any HTML element, either a pre-existing
2823  * element, or one that is created to your specifications at render time. Usually, to participate in layouts,
2824  * a Component will need to be a <b>Box</b>Component in order to have its width and height managed.</p>
2825  * <p>To use a pre-existing element as a BoxComponent, configure it so that you preset the <b>el</b> property to the
2826  * element to reference:<pre><code>
2827 var pageHeader = new Ext.BoxComponent({
2828     el: 'my-header-div'
2829 });</code></pre>
2830  * This may then be {@link Ext.Container#add added} to a {@link Ext.Container Container} as a child item.</p>
2831  * <p>To create a BoxComponent based around a HTML element to be created at render time, use the
2832  * {@link Ext.Component#autoEl autoEl} config option which takes the form of a
2833  * {@link Ext.DomHelper DomHelper} specification:<pre><code>
2834 var myImage = new Ext.BoxComponent({
2835     autoEl: {
2836         tag: 'img',
2837         src: '/images/my-image.jpg'
2838     }
2839 });</code></pre></p>
2840  * @constructor
2841  * @param {Ext.Element/String/Object} config The configuration options.
2842  * @xtype box
2843  */
2844 Ext.BoxComponent = Ext.extend(Ext.Component, {
2845
2846     // tabTip config is used when a BoxComponent is a child of a TabPanel
2847     /**
2848      * @cfg {String} tabTip
2849      * <p><b>Note</b>: this config is only used when this BoxComponent is a child item of a TabPanel.</p>
2850      * A string to be used as innerHTML (html tags are accepted) to show in a tooltip when mousing over
2851      * the associated tab selector element. {@link Ext.QuickTips}.init()
2852      * must be called in order for the tips to render.
2853      */
2854     // Configs below are used for all Components when rendered by BorderLayout.
2855     /**
2856      * @cfg {String} region <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2857      * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2858      * layout manager (e.g. specifying <tt>layout:'border'</tt>).</p><br>
2859      * <p>See {@link Ext.layout.BorderLayout} also.</p>
2860      */
2861     // margins config is used when a BoxComponent is rendered by BorderLayout or BoxLayout.
2862     /**
2863      * @cfg {Object} margins <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2864      * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2865      * or one of the two <b>{@link Ext.layout.BoxLayout BoxLayout} subclasses.</b></p>
2866      * <p>An object containing margins to apply to this BoxComponent in the
2867      * format:</p><pre><code>
2868 {
2869     top: (top margin),
2870     right: (right margin),
2871     bottom: (bottom margin),
2872     left: (left margin)
2873 }</code></pre>
2874      * <p>May also be a string containing space-separated, numeric margin values. The order of the
2875      * sides associated with each value matches the way CSS processes margin values:</p>
2876      * <p><div class="mdetail-params"><ul>
2877      * <li>If there is only one value, it applies to all sides.</li>
2878      * <li>If there are two values, the top and bottom borders are set to the first value and the
2879      * right and left are set to the second.</li>
2880      * <li>If there are three values, the top is set to the first value, the left and right are set
2881      * to the second, and the bottom is set to the third.</li>
2882      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
2883      * </ul></div></p>
2884      * <p>Defaults to:</p><pre><code>
2885      * {top:0, right:0, bottom:0, left:0}
2886      * </code></pre>
2887      */
2888     /**
2889      * @cfg {Number} x
2890      * The local x (left) coordinate for this component if contained within a positioning container.
2891      */
2892     /**
2893      * @cfg {Number} y
2894      * The local y (top) coordinate for this component if contained within a positioning container.
2895      */
2896     /**
2897      * @cfg {Number} pageX
2898      * The page level x coordinate for this component if contained within a positioning container.
2899      */
2900     /**
2901      * @cfg {Number} pageY
2902      * The page level y coordinate for this component if contained within a positioning container.
2903      */
2904     /**
2905      * @cfg {Number} height
2906      * The height of this component in pixels (defaults to auto).
2907      * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
2908      */
2909     /**
2910      * @cfg {Number} width
2911      * The width of this component in pixels (defaults to auto).
2912      * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
2913      */
2914     /**
2915      * @cfg {Number} boxMinHeight
2916      * <p>The minimum value in pixels which this BoxComponent will set its height to.</p>
2917      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2918      */
2919     /**
2920      * @cfg {Number} boxMinWidth
2921      * <p>The minimum value in pixels which this BoxComponent will set its width to.</p>
2922      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2923      */
2924     /**
2925      * @cfg {Number} boxMaxHeight
2926      * <p>The maximum value in pixels which this BoxComponent will set its height to.</p>
2927      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2928      */
2929     /**
2930      * @cfg {Number} boxMaxWidth
2931      * <p>The maximum value in pixels which this BoxComponent will set its width to.</p>
2932      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2933      */
2934     /**
2935      * @cfg {Boolean} autoHeight
2936      * <p>True to use height:'auto', false to use fixed height (or allow it to be managed by its parent
2937      * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
2938      * <p><b>Note</b>: Although many components inherit this config option, not all will
2939      * function as expected with a height of 'auto'. Setting autoHeight:true means that the
2940      * browser will manage height based on the element's contents, and that Ext will not manage it at all.</p>
2941      * <p>If the <i>browser</i> is managing the height, be aware that resizes performed by the browser in response
2942      * to changes within the structure of the Component cannot be detected. Therefore changes to the height might
2943      * result in elements needing to be synchronized with the new height. Example:</p><pre><code>
2944 var w = new Ext.Window({
2945     title: 'Window',
2946     width: 600,
2947     autoHeight: true,
2948     items: {
2949         title: 'Collapse Me',
2950         height: 400,
2951         collapsible: true,
2952         border: false,
2953         listeners: {
2954             beforecollapse: function() {
2955                 w.el.shadow.hide();
2956             },
2957             beforeexpand: function() {
2958                 w.el.shadow.hide();
2959             },
2960             collapse: function() {
2961                 w.syncShadow();
2962             },
2963             expand: function() {
2964                 w.syncShadow();
2965             }
2966         }
2967     }
2968 }).show();
2969 </code></pre>
2970      */
2971     /**
2972      * @cfg {Boolean} autoWidth
2973      * <p>True to use width:'auto', false to use fixed width (or allow it to be managed by its parent
2974      * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
2975      * <p><b>Note</b>: Although many components  inherit this config option, not all will
2976      * function as expected with a width of 'auto'. Setting autoWidth:true means that the
2977      * browser will manage width based on the element's contents, and that Ext will not manage it at all.</p>
2978      * <p>If the <i>browser</i> is managing the width, be aware that resizes performed by the browser in response
2979      * to changes within the structure of the Component cannot be detected. Therefore changes to the width might
2980      * result in elements needing to be synchronized with the new width. For example, where the target element is:</p><pre><code>
2981 &lt;div id='grid-container' style='margin-left:25%;width:50%'>&lt;/div>
2982 </code></pre>
2983      * A Panel rendered into that target element must listen for browser window resize in order to relay its
2984       * child items when the browser changes its width:<pre><code>
2985 var myPanel = new Ext.Panel({
2986     renderTo: 'grid-container',
2987     monitorResize: true, // relay on browser resize
2988     title: 'Panel',
2989     height: 400,
2990     autoWidth: true,
2991     layout: 'hbox',
2992     layoutConfig: {
2993         align: 'stretch'
2994     },
2995     defaults: {
2996         flex: 1
2997     },
2998     items: [{
2999         title: 'Box 1',
3000     }, {
3001         title: 'Box 2'
3002     }, {
3003         title: 'Box 3'
3004     }],
3005 });
3006 </code></pre>
3007      */
3008     /**
3009      * @cfg {Boolean} autoScroll
3010      * <code>true</code> to use overflow:'auto' on the components layout element and show scroll bars automatically when
3011      * necessary, <code>false</code> to clip any overflowing content (defaults to <code>false</code>).
3012      */
3013
3014     /* // private internal config
3015      * {Boolean} deferHeight
3016      * True to defer height calculations to an external component, false to allow this component to set its own
3017      * height (defaults to false).
3018      */
3019
3020     // private
3021     initComponent : function(){
3022         Ext.BoxComponent.superclass.initComponent.call(this);
3023         this.addEvents(
3024             /**
3025              * @event resize
3026              * Fires after the component is resized.
3027              * @param {Ext.Component} this
3028              * @param {Number} adjWidth The box-adjusted width that was set
3029              * @param {Number} adjHeight The box-adjusted height that was set
3030              * @param {Number} rawWidth The width that was originally specified
3031              * @param {Number} rawHeight The height that was originally specified
3032              */
3033             'resize',
3034             /**
3035              * @event move
3036              * Fires after the component is moved.
3037              * @param {Ext.Component} this
3038              * @param {Number} x The new x position
3039              * @param {Number} y The new y position
3040              */
3041             'move'
3042         );
3043     },
3044
3045     // private, set in afterRender to signify that the component has been rendered
3046     boxReady : false,
3047     // private, used to defer height settings to subclasses
3048     deferHeight: false,
3049
3050     /**
3051      * Sets the width and height of this BoxComponent. This method fires the {@link #resize} event. This method can accept
3052      * either width and height as separate arguments, or you can pass a size object like <code>{width:10, height:20}</code>.
3053      * @param {Mixed} width The new width to set. This may be one of:<div class="mdetail-params"><ul>
3054      * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3055      * <li>A String used to set the CSS width style.</li>
3056      * <li>A size object in the format <code>{width: widthValue, height: heightValue}</code>.</li>
3057      * <li><code>undefined</code> to leave the width unchanged.</li>
3058      * </ul></div>
3059      * @param {Mixed} height The new height to set (not required if a size object is passed as the first arg).
3060      * This may be one of:<div class="mdetail-params"><ul>
3061      * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3062      * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
3063      * <li><code>undefined</code> to leave the height unchanged.</li>
3064      * </ul></div>
3065      * @return {Ext.BoxComponent} this
3066      */
3067     setSize : function(w, h){
3068
3069         // support for standard size objects
3070         if(typeof w == 'object'){
3071             h = w.height, w = w.width;
3072         }
3073         if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
3074             w = this.boxMinWidth;
3075         }
3076         if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) {
3077             h = this.boxMinHeight;
3078         }
3079         if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) {
3080             w = this.boxMaxWidth;
3081         }
3082         if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) {
3083             h = this.boxMaxHeight;
3084         }
3085         // not rendered
3086         if(!this.boxReady){
3087             this.width = w, this.height = h;
3088             return this;
3089         }
3090
3091         // prevent recalcs when not needed
3092         if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
3093             return this;
3094         }
3095         this.lastSize = {width: w, height: h};
3096         var adj = this.adjustSize(w, h),
3097             aw = adj.width,
3098             ah = adj.height,
3099             rz;
3100         if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
3101             rz = this.getResizeEl();
3102             if(!this.deferHeight && aw !== undefined && ah !== undefined){
3103                 rz.setSize(aw, ah);
3104             }else if(!this.deferHeight && ah !== undefined){
3105                 rz.setHeight(ah);
3106             }else if(aw !== undefined){
3107                 rz.setWidth(aw);
3108             }
3109             this.onResize(aw, ah, w, h);
3110         }
3111         return this;
3112     },
3113
3114     /**
3115      * Sets the width of the component.  This method fires the {@link #resize} event.
3116      * @param {Number} width The new width to setThis may be one of:<div class="mdetail-params"><ul>
3117      * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3118      * <li>A String used to set the CSS width style.</li>
3119      * </ul></div>
3120      * @return {Ext.BoxComponent} this
3121      */
3122     setWidth : function(width){
3123         return this.setSize(width);
3124     },
3125
3126     /**
3127      * Sets the height of the component.  This method fires the {@link #resize} event.
3128      * @param {Number} height The new height to set. This may be one of:<div class="mdetail-params"><ul>
3129      * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3130      * <li>A String used to set the CSS height style.</li>
3131      * <li><i>undefined</i> to leave the height unchanged.</li>
3132      * </ul></div>
3133      * @return {Ext.BoxComponent} this
3134      */
3135     setHeight : function(height){
3136         return this.setSize(undefined, height);
3137     },
3138
3139     /**
3140      * Gets the current size of the component's underlying element.
3141      * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
3142      */
3143     getSize : function(){
3144         return this.getResizeEl().getSize();
3145     },
3146
3147     /**
3148      * Gets the current width of the component's underlying element.
3149      * @return {Number}
3150      */
3151     getWidth : function(){
3152         return this.getResizeEl().getWidth();
3153     },
3154
3155     /**
3156      * Gets the current height of the component's underlying element.
3157      * @return {Number}
3158      */
3159     getHeight : function(){
3160         return this.getResizeEl().getHeight();
3161     },
3162
3163     /**
3164      * Gets the current size of the component's underlying element, including space taken by its margins.
3165      * @return {Object} An object containing the element's size {width: (element width + left/right margins), height: (element height + top/bottom margins)}
3166      */
3167     getOuterSize : function(){
3168         var el = this.getResizeEl();
3169         return {width: el.getWidth() + el.getMargins('lr'),
3170                 height: el.getHeight() + el.getMargins('tb')};
3171     },
3172
3173     /**
3174      * Gets the current XY position of the component's underlying element.
3175      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
3176      * @return {Array} The XY position of the element (e.g., [100, 200])
3177      */
3178     getPosition : function(local){
3179         var el = this.getPositionEl();
3180         if(local === true){
3181             return [el.getLeft(true), el.getTop(true)];
3182         }
3183         return this.xy || el.getXY();
3184     },
3185
3186     /**
3187      * Gets the current box measurements of the component's underlying element.
3188      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
3189      * @return {Object} box An object in the format {x, y, width, height}
3190      */
3191     getBox : function(local){
3192         var pos = this.getPosition(local);
3193         var s = this.getSize();
3194         s.x = pos[0];
3195         s.y = pos[1];
3196         return s;
3197     },
3198
3199     /**
3200      * Sets the current box measurements of the component's underlying element.
3201      * @param {Object} box An object in the format {x, y, width, height}
3202      * @return {Ext.BoxComponent} this
3203      */
3204     updateBox : function(box){
3205         this.setSize(box.width, box.height);
3206         this.setPagePosition(box.x, box.y);
3207         return this;
3208     },
3209
3210     /**
3211      * <p>Returns the outermost Element of this Component which defines the Components overall size.</p>
3212      * <p><i>Usually</i> this will return the same Element as <code>{@link #getEl}</code>,
3213      * but in some cases, a Component may have some more wrapping Elements around its main
3214      * active Element.</p>
3215      * <p>An example is a ComboBox. It is encased in a <i>wrapping</i> Element which
3216      * contains both the <code>&lt;input></code> Element (which is what would be returned
3217      * by its <code>{@link #getEl}</code> method, <i>and</i> the trigger button Element.
3218      * This Element is returned as the <code>resizeEl</code>.
3219      * @return {Ext.Element} The Element which is to be resized by size managing layouts.
3220      */
3221     getResizeEl : function(){
3222         return this.resizeEl || this.el;
3223     },
3224
3225     /**
3226      * Sets the overflow on the content element of the component.
3227      * @param {Boolean} scroll True to allow the Component to auto scroll.
3228      * @return {Ext.BoxComponent} this
3229      */
3230     setAutoScroll : function(scroll){
3231         if(this.rendered){
3232             this.getContentTarget().setOverflow(scroll ? 'auto' : '');
3233         }
3234         this.autoScroll = scroll;
3235         return this;
3236     },
3237
3238     /**
3239      * Sets the left and top of the component.  To set the page XY position instead, use {@link #setPagePosition}.
3240      * This method fires the {@link #move} event.
3241      * @param {Number} left The new left
3242      * @param {Number} top The new top
3243      * @return {Ext.BoxComponent} this
3244      */
3245     setPosition : function(x, y){
3246         if(x && typeof x[1] == 'number'){
3247             y = x[1];
3248             x = x[0];
3249         }
3250         this.x = x;
3251         this.y = y;
3252         if(!this.boxReady){
3253             return this;
3254         }
3255         var adj = this.adjustPosition(x, y);
3256         var ax = adj.x, ay = adj.y;
3257
3258         var el = this.getPositionEl();
3259         if(ax !== undefined || ay !== undefined){
3260             if(ax !== undefined && ay !== undefined){
3261                 el.setLeftTop(ax, ay);
3262             }else if(ax !== undefined){
3263                 el.setLeft(ax);
3264             }else if(ay !== undefined){
3265                 el.setTop(ay);
3266             }
3267             this.onPosition(ax, ay);
3268             this.fireEvent('move', this, ax, ay);
3269         }
3270         return this;
3271     },
3272
3273     /**
3274      * Sets the page XY position of the component.  To set the left and top instead, use {@link #setPosition}.
3275      * This method fires the {@link #move} event.
3276      * @param {Number} x The new x position
3277      * @param {Number} y The new y position
3278      * @return {Ext.BoxComponent} this
3279      */
3280     setPagePosition : function(x, y){
3281         if(x && typeof x[1] == 'number'){
3282             y = x[1];
3283             x = x[0];
3284         }
3285         this.pageX = x;
3286         this.pageY = y;
3287         if(!this.boxReady){
3288             return;
3289         }
3290         if(x === undefined || y === undefined){ // cannot translate undefined points
3291             return;
3292         }
3293         var p = this.getPositionEl().translatePoints(x, y);
3294         this.setPosition(p.left, p.top);
3295         return this;
3296     },
3297
3298     // private
3299     afterRender : function(){
3300         Ext.BoxComponent.superclass.afterRender.call(this);
3301         if(this.resizeEl){
3302             this.resizeEl = Ext.get(this.resizeEl);
3303         }
3304         if(this.positionEl){
3305             this.positionEl = Ext.get(this.positionEl);
3306         }
3307         this.boxReady = true;
3308         this.setAutoScroll(this.autoScroll);
3309         this.setSize(this.width, this.height);
3310         if(this.x || this.y){
3311             this.setPosition(this.x, this.y);
3312         }else if(this.pageX || this.pageY){
3313             this.setPagePosition(this.pageX, this.pageY);
3314         }
3315     },
3316
3317     /**
3318      * Force the component's size to recalculate based on the underlying element's current height and width.
3319      * @return {Ext.BoxComponent} this
3320      */
3321     syncSize : function(){
3322         delete this.lastSize;
3323         this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
3324         return this;
3325     },
3326
3327     /* // protected
3328      * Called after the component is resized, this method is empty by default but can be implemented by any
3329      * subclass that needs to perform custom logic after a resize occurs.
3330      * @param {Number} adjWidth The box-adjusted width that was set
3331      * @param {Number} adjHeight The box-adjusted height that was set
3332      * @param {Number} rawWidth The width that was originally specified
3333      * @param {Number} rawHeight The height that was originally specified
3334      */
3335     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
3336         this.fireEvent('resize', this, adjWidth, adjHeight, rawWidth, rawHeight);
3337     },
3338
3339     /* // protected
3340      * Called after the component is moved, this method is empty by default but can be implemented by any
3341      * subclass that needs to perform custom logic after a move occurs.
3342      * @param {Number} x The new x position
3343      * @param {Number} y The new y position
3344      */
3345     onPosition : function(x, y){
3346
3347     },
3348
3349     // private
3350     adjustSize : function(w, h){
3351         if(this.autoWidth){
3352             w = 'auto';
3353         }
3354         if(this.autoHeight){
3355             h = 'auto';
3356         }
3357         return {width : w, height: h};
3358     },
3359
3360     // private
3361     adjustPosition : function(x, y){
3362         return {x : x, y: y};
3363     }
3364 });
3365 Ext.reg('box', Ext.BoxComponent);
3366
3367
3368 /**
3369  * @class Ext.Spacer
3370  * @extends Ext.BoxComponent
3371  * <p>Used to provide a sizable space in a layout.</p>
3372  * @constructor
3373  * @param {Object} config
3374  */
3375 Ext.Spacer = Ext.extend(Ext.BoxComponent, {
3376     autoEl:'div'
3377 });
3378 Ext.reg('spacer', Ext.Spacer);/**\r
3379  * @class Ext.SplitBar\r
3380  * @extends Ext.util.Observable\r
3381  * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).\r
3382  * <br><br>\r
3383  * Usage:\r
3384  * <pre><code>\r
3385 var split = new Ext.SplitBar("elementToDrag", "elementToSize",\r
3386                    Ext.SplitBar.HORIZONTAL, Ext.SplitBar.LEFT);\r
3387 split.setAdapter(new Ext.SplitBar.AbsoluteLayoutAdapter("container"));\r
3388 split.minSize = 100;\r
3389 split.maxSize = 600;\r
3390 split.animate = true;\r
3391 split.on('moved', splitterMoved);\r
3392 </code></pre>\r
3393  * @constructor\r
3394  * Create a new SplitBar\r
3395  * @param {Mixed} dragElement The element to be dragged and act as the SplitBar.\r
3396  * @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged\r
3397  * @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)\r
3398  * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or\r
3399                         Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial\r
3400                         position of the SplitBar).\r
3401  */\r
3402 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){\r
3403 \r
3404     /** @private */\r
3405     this.el = Ext.get(dragElement, true);\r
3406     this.el.dom.unselectable = "on";\r
3407     /** @private */\r
3408     this.resizingEl = Ext.get(resizingElement, true);\r
3409 \r
3410     /**\r
3411      * @private\r
3412      * The orientation of the split. Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)\r
3413      * Note: If this is changed after creating the SplitBar, the placement property must be manually updated\r
3414      * @type Number\r
3415      */\r
3416     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;\r
3417 \r
3418     /**\r
3419      * The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.\r
3420      * @type Number\r
3421      * @property tickSize\r
3422      */\r
3423     /**\r
3424      * The minimum size of the resizing element. (Defaults to 0)\r
3425      * @type Number\r
3426      */\r
3427     this.minSize = 0;\r
3428 \r
3429     /**\r
3430      * The maximum size of the resizing element. (Defaults to 2000)\r
3431      * @type Number\r
3432      */\r
3433     this.maxSize = 2000;\r
3434 \r
3435     /**\r
3436      * Whether to animate the transition to the new size\r
3437      * @type Boolean\r
3438      */\r
3439     this.animate = false;\r
3440 \r
3441     /**\r
3442      * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.\r
3443      * @type Boolean\r
3444      */\r
3445     this.useShim = false;\r
3446 \r
3447     /** @private */\r
3448     this.shim = null;\r
3449 \r
3450     if(!existingProxy){\r
3451         /** @private */\r
3452         this.proxy = Ext.SplitBar.createProxy(this.orientation);\r
3453     }else{\r
3454         this.proxy = Ext.get(existingProxy).dom;\r
3455     }\r
3456     /** @private */\r
3457     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});\r
3458 \r
3459     /** @private */\r
3460     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);\r
3461 \r
3462     /** @private */\r
3463     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);\r
3464 \r
3465     /** @private */\r
3466     this.dragSpecs = {};\r
3467 \r
3468     /**\r
3469      * @private The adapter to use to positon and resize elements\r
3470      */\r
3471     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();\r
3472     this.adapter.init(this);\r
3473 \r
3474     if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
3475         /** @private */\r
3476         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);\r
3477         this.el.addClass("x-splitbar-h");\r
3478     }else{\r
3479         /** @private */\r
3480         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);\r
3481         this.el.addClass("x-splitbar-v");\r
3482     }\r
3483 \r
3484     this.addEvents(\r
3485         /**\r
3486          * @event resize\r
3487          * Fires when the splitter is moved (alias for {@link #moved})\r
3488          * @param {Ext.SplitBar} this\r
3489          * @param {Number} newSize the new width or height\r
3490          */\r
3491         "resize",\r
3492         /**\r
3493          * @event moved\r
3494          * Fires when the splitter is moved\r
3495          * @param {Ext.SplitBar} this\r
3496          * @param {Number} newSize the new width or height\r
3497          */\r
3498         "moved",\r
3499         /**\r
3500          * @event beforeresize\r
3501          * Fires before the splitter is dragged\r
3502          * @param {Ext.SplitBar} this\r
3503          */\r
3504         "beforeresize",\r
3505 \r
3506         "beforeapply"\r
3507     );\r
3508 \r
3509     Ext.SplitBar.superclass.constructor.call(this);\r
3510 };\r
3511 \r
3512 Ext.extend(Ext.SplitBar, Ext.util.Observable, {\r
3513     onStartProxyDrag : function(x, y){\r
3514         this.fireEvent("beforeresize", this);\r
3515         this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);\r
3516         this.overlay.unselectable();\r
3517         this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));\r
3518         this.overlay.show();\r
3519         Ext.get(this.proxy).setDisplayed("block");\r
3520         var size = this.adapter.getElementSize(this);\r
3521         this.activeMinSize = this.getMinimumSize();\r
3522         this.activeMaxSize = this.getMaximumSize();\r
3523         var c1 = size - this.activeMinSize;\r
3524         var c2 = Math.max(this.activeMaxSize - size, 0);\r
3525         if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
3526             this.dd.resetConstraints();\r
3527             this.dd.setXConstraint(\r
3528                 this.placement == Ext.SplitBar.LEFT ? c1 : c2,\r
3529                 this.placement == Ext.SplitBar.LEFT ? c2 : c1,\r
3530                 this.tickSize\r
3531             );\r
3532             this.dd.setYConstraint(0, 0);\r
3533         }else{\r
3534             this.dd.resetConstraints();\r
3535             this.dd.setXConstraint(0, 0);\r
3536             this.dd.setYConstraint(\r
3537                 this.placement == Ext.SplitBar.TOP ? c1 : c2,\r
3538                 this.placement == Ext.SplitBar.TOP ? c2 : c1,\r
3539                 this.tickSize\r
3540             );\r
3541          }\r
3542         this.dragSpecs.startSize = size;\r
3543         this.dragSpecs.startPoint = [x, y];\r
3544         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);\r
3545     },\r
3546 \r
3547     /**\r
3548      * @private Called after the drag operation by the DDProxy\r
3549      */\r
3550     onEndProxyDrag : function(e){\r
3551         Ext.get(this.proxy).setDisplayed(false);\r
3552         var endPoint = Ext.lib.Event.getXY(e);\r
3553         if(this.overlay){\r
3554             Ext.destroy(this.overlay);\r
3555             delete this.overlay;\r
3556         }\r
3557         var newSize;\r
3558         if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
3559             newSize = this.dragSpecs.startSize +\r
3560                 (this.placement == Ext.SplitBar.LEFT ?\r
3561                     endPoint[0] - this.dragSpecs.startPoint[0] :\r
3562                     this.dragSpecs.startPoint[0] - endPoint[0]\r
3563                 );\r
3564         }else{\r
3565             newSize = this.dragSpecs.startSize +\r
3566                 (this.placement == Ext.SplitBar.TOP ?\r
3567                     endPoint[1] - this.dragSpecs.startPoint[1] :\r
3568                     this.dragSpecs.startPoint[1] - endPoint[1]\r
3569                 );\r
3570         }\r
3571         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);\r
3572         if(newSize != this.dragSpecs.startSize){\r
3573             if(this.fireEvent('beforeapply', this, newSize) !== false){\r
3574                 this.adapter.setElementSize(this, newSize);\r
3575                 this.fireEvent("moved", this, newSize);\r
3576                 this.fireEvent("resize", this, newSize);\r
3577             }\r
3578         }\r
3579     },\r
3580 \r
3581     /**\r
3582      * Get the adapter this SplitBar uses\r
3583      * @return The adapter object\r
3584      */\r
3585     getAdapter : function(){\r
3586         return this.adapter;\r
3587     },\r
3588 \r
3589     /**\r
3590      * Set the adapter this SplitBar uses\r
3591      * @param {Object} adapter A SplitBar adapter object\r
3592      */\r
3593     setAdapter : function(adapter){\r
3594         this.adapter = adapter;\r
3595         this.adapter.init(this);\r
3596     },\r
3597 \r
3598     /**\r
3599      * Gets the minimum size for the resizing element\r
3600      * @return {Number} The minimum size\r
3601      */\r
3602     getMinimumSize : function(){\r
3603         return this.minSize;\r
3604     },\r
3605 \r
3606     /**\r
3607      * Sets the minimum size for the resizing element\r
3608      * @param {Number} minSize The minimum size\r
3609      */\r
3610     setMinimumSize : function(minSize){\r
3611         this.minSize = minSize;\r
3612     },\r
3613 \r
3614     /**\r
3615      * Gets the maximum size for the resizing element\r
3616      * @return {Number} The maximum size\r
3617      */\r
3618     getMaximumSize : function(){\r
3619         return this.maxSize;\r
3620     },\r
3621 \r
3622     /**\r
3623      * Sets the maximum size for the resizing element\r
3624      * @param {Number} maxSize The maximum size\r
3625      */\r
3626     setMaximumSize : function(maxSize){\r
3627         this.maxSize = maxSize;\r
3628     },\r
3629 \r
3630     /**\r
3631      * Sets the initialize size for the resizing element\r
3632      * @param {Number} size The initial size\r
3633      */\r
3634     setCurrentSize : function(size){\r
3635         var oldAnimate = this.animate;\r
3636         this.animate = false;\r
3637         this.adapter.setElementSize(this, size);\r
3638         this.animate = oldAnimate;\r
3639     },\r
3640 \r
3641     /**\r
3642      * Destroy this splitbar.\r
3643      * @param {Boolean} removeEl True to remove the element\r
3644      */\r
3645     destroy : function(removeEl){\r
3646         Ext.destroy(this.shim, Ext.get(this.proxy));\r
3647         this.dd.unreg();\r
3648         if(removeEl){\r
3649             this.el.remove();\r
3650         }\r
3651         this.purgeListeners();\r
3652     }\r
3653 });\r
3654 \r
3655 /**\r
3656  * @private static Create our own proxy element element. So it will be the same same size on all browsers, we won't use borders. Instead we use a background color.\r
3657  */\r
3658 Ext.SplitBar.createProxy = function(dir){\r
3659     var proxy = new Ext.Element(document.createElement("div"));\r
3660     document.body.appendChild(proxy.dom);\r
3661     proxy.unselectable();\r
3662     var cls = 'x-splitbar-proxy';\r
3663     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));\r
3664     return proxy.dom;\r
3665 };\r
3666 \r
3667 /**\r
3668  * @class Ext.SplitBar.BasicLayoutAdapter\r
3669  * Default Adapter. It assumes the splitter and resizing element are not positioned\r
3670  * elements and only gets/sets the width of the element. Generally used for table based layouts.\r
3671  */\r
3672 Ext.SplitBar.BasicLayoutAdapter = function(){\r
3673 };\r
3674 \r
3675 Ext.SplitBar.BasicLayoutAdapter.prototype = {\r
3676     // do nothing for now\r
3677     init : function(s){\r
3678 \r
3679     },\r
3680     /**\r
3681      * Called before drag operations to get the current size of the resizing element.\r
3682      * @param {Ext.SplitBar} s The SplitBar using this adapter\r
3683      */\r
3684      getElementSize : function(s){\r
3685         if(s.orientation == Ext.SplitBar.HORIZONTAL){\r
3686             return s.resizingEl.getWidth();\r
3687         }else{\r
3688             return s.resizingEl.getHeight();\r
3689         }\r
3690     },\r
3691 \r
3692     /**\r
3693      * Called after drag operations to set the size of the resizing element.\r
3694      * @param {Ext.SplitBar} s The SplitBar using this adapter\r
3695      * @param {Number} newSize The new size to set\r
3696      * @param {Function} onComplete A function to be invoked when resizing is complete\r
3697      */\r
3698     setElementSize : function(s, newSize, onComplete){\r
3699         if(s.orientation == Ext.SplitBar.HORIZONTAL){\r
3700             if(!s.animate){\r
3701                 s.resizingEl.setWidth(newSize);\r
3702                 if(onComplete){\r
3703                     onComplete(s, newSize);\r
3704                 }\r
3705             }else{\r
3706                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');\r
3707             }\r
3708         }else{\r
3709 \r
3710             if(!s.animate){\r
3711                 s.resizingEl.setHeight(newSize);\r
3712                 if(onComplete){\r
3713                     onComplete(s, newSize);\r
3714                 }\r
3715             }else{\r
3716                 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');\r
3717             }\r
3718         }\r
3719     }\r
3720 };\r
3721 \r
3722 /**\r
3723  *@class Ext.SplitBar.AbsoluteLayoutAdapter\r
3724  * @extends Ext.SplitBar.BasicLayoutAdapter\r
3725  * Adapter that  moves the splitter element to align with the resized sizing element.\r
3726  * Used with an absolute positioned SplitBar.\r
3727  * @param {Mixed} container The container that wraps around the absolute positioned content. If it's\r
3728  * document.body, make sure you assign an id to the body element.\r
3729  */\r
3730 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){\r
3731     this.basic = new Ext.SplitBar.BasicLayoutAdapter();\r
3732     this.container = Ext.get(container);\r
3733 };\r
3734 \r
3735 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {\r
3736     init : function(s){\r
3737         this.basic.init(s);\r
3738     },\r
3739 \r
3740     getElementSize : function(s){\r
3741         return this.basic.getElementSize(s);\r
3742     },\r
3743 \r
3744     setElementSize : function(s, newSize, onComplete){\r
3745         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));\r
3746     },\r
3747 \r
3748     moveSplitter : function(s){\r
3749         var yes = Ext.SplitBar;\r
3750         switch(s.placement){\r
3751             case yes.LEFT:\r
3752                 s.el.setX(s.resizingEl.getRight());\r
3753                 break;\r
3754             case yes.RIGHT:\r
3755                 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");\r
3756                 break;\r
3757             case yes.TOP:\r
3758                 s.el.setY(s.resizingEl.getBottom());\r
3759                 break;\r
3760             case yes.BOTTOM:\r
3761                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());\r
3762                 break;\r
3763         }\r
3764     }\r
3765 };\r
3766 \r
3767 /**\r
3768  * Orientation constant - Create a vertical SplitBar\r
3769  * @static\r
3770  * @type Number\r
3771  */\r
3772 Ext.SplitBar.VERTICAL = 1;\r
3773 \r
3774 /**\r
3775  * Orientation constant - Create a horizontal SplitBar\r
3776  * @static\r
3777  * @type Number\r
3778  */\r
3779 Ext.SplitBar.HORIZONTAL = 2;\r
3780 \r
3781 /**\r
3782  * Placement constant - The resizing element is to the left of the splitter element\r
3783  * @static\r
3784  * @type Number\r
3785  */\r
3786 Ext.SplitBar.LEFT = 1;\r
3787 \r
3788 /**\r
3789  * Placement constant - The resizing element is to the right of the splitter element\r
3790  * @static\r
3791  * @type Number\r
3792  */\r
3793 Ext.SplitBar.RIGHT = 2;\r
3794 \r
3795 /**\r
3796  * Placement constant - The resizing element is positioned above the splitter element\r
3797  * @static\r
3798  * @type Number\r
3799  */\r
3800 Ext.SplitBar.TOP = 3;\r
3801 \r
3802 /**\r
3803  * Placement constant - The resizing element is positioned under splitter element\r
3804  * @static\r
3805  * @type Number\r
3806  */\r
3807 Ext.SplitBar.BOTTOM = 4;\r
3808 /**
3809  * @class Ext.Container
3810  * @extends Ext.BoxComponent
3811  * <p>Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the
3812  * basic behavior of containing items, namely adding, inserting and removing items.</p>
3813  *
3814  * <p>The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}.
3815  * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight
3816  * Container to be encapsulated by an HTML element to your specifications by using the
3817  * <code><b>{@link Ext.Component#autoEl autoEl}</b></code> config option. This is a useful technique when creating
3818  * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels}
3819  * for example.</p>
3820  *
3821  * <p>The code below illustrates both how to explicitly create a Container, and how to implicitly
3822  * create one using the <b><code>'container'</code></b> xtype:<pre><code>
3823 // explicitly create a Container
3824 var embeddedColumns = new Ext.Container({
3825     autoEl: 'div',  // This is the default
3826     layout: 'column',
3827     defaults: {
3828         // implicitly create Container by specifying xtype
3829         xtype: 'container',
3830         autoEl: 'div', // This is the default.
3831         layout: 'form',
3832         columnWidth: 0.5,
3833         style: {
3834             padding: '10px'
3835         }
3836     },
3837 //  The two items below will be Ext.Containers, each encapsulated by a &lt;DIV> element.
3838     items: [{
3839         items: {
3840             xtype: 'datefield',
3841             name: 'startDate',
3842             fieldLabel: 'Start date'
3843         }
3844     }, {
3845         items: {
3846             xtype: 'datefield',
3847             name: 'endDate',
3848             fieldLabel: 'End date'
3849         }
3850     }]
3851 });</code></pre></p>
3852  *
3853  * <p><u><b>Layout</b></u></p>
3854  * <p>Container classes delegate the rendering of child Components to a layout
3855  * manager class which must be configured into the Container using the
3856  * <code><b>{@link #layout}</b></code> configuration property.</p>
3857  * <p>When either specifying child <code>{@link #items}</code> of a Container,
3858  * or dynamically {@link #add adding} Components to a Container, remember to
3859  * consider how you wish the Container to arrange those child elements, and
3860  * whether those child elements need to be sized using one of Ext's built-in
3861  * <b><code>{@link #layout}</code></b> schemes. By default, Containers use the
3862  * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only
3863  * renders child components, appending them one after the other inside the
3864  * Container, and <b>does not apply any sizing</b> at all.</p>
3865  * <p>A common mistake is when a developer neglects to specify a
3866  * <b><code>{@link #layout}</code></b> (e.g. widgets like GridPanels or
3867  * TreePanels are added to Containers for which no <code><b>{@link #layout}</b></code>
3868  * has been specified). If a Container is left to use the default
3869  * {@link Ext.layout.ContainerLayout ContainerLayout} scheme, none of its
3870  * child components will be resized, or changed in any way when the Container
3871  * is resized.</p>
3872  * <p>Certain layout managers allow dynamic addition of child components.
3873  * Those that do include {@link Ext.layout.CardLayout},
3874  * {@link Ext.layout.AnchorLayout}, {@link Ext.layout.FormLayout}, and
3875  * {@link Ext.layout.TableLayout}. For example:<pre><code>
3876 //  Create the GridPanel.
3877 var myNewGrid = new Ext.grid.GridPanel({
3878     store: myStore,
3879     columns: myColumnModel,
3880     title: 'Results', // the title becomes the title of the tab
3881 });
3882
3883 myTabPanel.add(myNewGrid); // {@link Ext.TabPanel} implicitly uses {@link Ext.layout.CardLayout CardLayout}
3884 myTabPanel.{@link Ext.TabPanel#setActiveTab setActiveTab}(myNewGrid);
3885  * </code></pre></p>
3886  * <p>The example above adds a newly created GridPanel to a TabPanel. Note that
3887  * a TabPanel uses {@link Ext.layout.CardLayout} as its layout manager which
3888  * means all its child items are sized to {@link Ext.layout.FitLayout fit}
3889  * exactly into its client area.
3890  * <p><b><u>Overnesting is a common problem</u></b>.
3891  * An example of overnesting occurs when a GridPanel is added to a TabPanel
3892  * by wrapping the GridPanel <i>inside</i> a wrapping Panel (that has no
3893  * <code><b>{@link #layout}</b></code> specified) and then add that wrapping Panel
3894  * to the TabPanel. The point to realize is that a GridPanel <b>is</b> a
3895  * Component which can be added directly to a Container. If the wrapping Panel
3896  * has no <code><b>{@link #layout}</b></code> configuration, then the overnested
3897  * GridPanel will not be sized as expected.<p>
3898  *
3899  * <p><u><b>Adding via remote configuration</b></u></p>
3900  *
3901  * <p>A server side script can be used to add Components which are generated dynamically on the server.
3902  * An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server
3903  * based on certain parameters:
3904  * </p><pre><code>
3905 // execute an Ajax request to invoke server side script:
3906 Ext.Ajax.request({
3907     url: 'gen-invoice-grid.php',
3908     // send additional parameters to instruct server script
3909     params: {
3910         startDate: Ext.getCmp('start-date').getValue(),
3911         endDate: Ext.getCmp('end-date').getValue()
3912     },
3913     // process the response object to add it to the TabPanel:
3914     success: function(xhr) {
3915         var newComponent = eval(xhr.responseText); // see discussion below
3916         myTabPanel.add(newComponent); // add the component to the TabPanel
3917         myTabPanel.setActiveTab(newComponent);
3918     },
3919     failure: function() {
3920         Ext.Msg.alert("Grid create failed", "Server communication failure");
3921     }
3922 });
3923 </code></pre>
3924  * <p>The server script needs to return an executable Javascript statement which, when processed
3925  * using <code>eval()</code>, will return either a config object with an {@link Ext.Component#xtype xtype},
3926  * or an instantiated Component. The server might return this for example:</p><pre><code>
3927 (function() {
3928     function formatDate(value){
3929         return value ? value.dateFormat('M d, Y') : '';
3930     };
3931
3932     var store = new Ext.data.Store({
3933         url: 'get-invoice-data.php',
3934         baseParams: {
3935             startDate: '01/01/2008',
3936             endDate: '01/31/2008'
3937         },
3938         reader: new Ext.data.JsonReader({
3939             record: 'transaction',
3940             idProperty: 'id',
3941             totalRecords: 'total'
3942         }, [
3943            'customer',
3944            'invNo',
3945            {name: 'date', type: 'date', dateFormat: 'm/d/Y'},
3946            {name: 'value', type: 'float'}
3947         ])
3948     });
3949
3950     var grid = new Ext.grid.GridPanel({
3951         title: 'Invoice Report',
3952         bbar: new Ext.PagingToolbar(store),
3953         store: store,
3954         columns: [
3955             {header: "Customer", width: 250, dataIndex: 'customer', sortable: true},
3956             {header: "Invoice Number", width: 120, dataIndex: 'invNo', sortable: true},
3957             {header: "Invoice Date", width: 100, dataIndex: 'date', renderer: formatDate, sortable: true},
3958             {header: "Value", width: 120, dataIndex: 'value', renderer: 'usMoney', sortable: true}
3959         ],
3960     });
3961     store.load();
3962     return grid;  // return instantiated component
3963 })();
3964 </code></pre>
3965  * <p>When the above code fragment is passed through the <code>eval</code> function in the success handler
3966  * of the Ajax request, the code is executed by the Javascript processor, and the anonymous function
3967  * runs, and returns the instantiated grid component.</p>
3968  * <p>Note: since the code above is <i>generated</i> by a server script, the <code>baseParams</code> for
3969  * the Store, the metadata to allow generation of the Record layout, and the ColumnModel
3970  * can all be generated into the code since these are all known on the server.</p>
3971  *
3972  * @xtype container
3973  */
3974 Ext.Container = Ext.extend(Ext.BoxComponent, {
3975     /**
3976      * @cfg {Boolean} monitorResize
3977      * True to automatically monitor window resize events to handle anything that is sensitive to the current size
3978      * of the viewport.  This value is typically managed by the chosen <code>{@link #layout}</code> and should not need
3979      * to be set manually.
3980      */
3981     /**
3982      * @cfg {String/Object} layout
3983      * <p><b>*Important</b>: In order for child items to be correctly sized and
3984      * positioned, typically a layout manager <b>must</b> be specified through
3985      * the <code>layout</code> configuration option.</p>
3986      * <br><p>The sizing and positioning of child {@link items} is the responsibility of
3987      * the Container's layout manager which creates and manages the type of layout
3988      * you have in mind.  For example:</p><pre><code>
3989 new Ext.Window({
3990     width:300, height: 300,
3991     layout: 'fit', // explicitly set layout manager: override the default (layout:'auto')
3992     items: [{
3993         title: 'Panel inside a Window'
3994     }]
3995 }).show();
3996      * </code></pre>
3997      * <p>If the {@link #layout} configuration is not explicitly specified for
3998      * a general purpose container (e.g. Container or Panel) the
3999      * {@link Ext.layout.ContainerLayout default layout manager} will be used
4000      * which does nothing but render child components sequentially into the
4001      * Container (no sizing or positioning will be performed in this situation).
4002      * Some container classes implicitly specify a default layout
4003      * (e.g. FormPanel specifies <code>layout:'form'</code>). Other specific
4004      * purpose classes internally specify/manage their internal layout (e.g.
4005      * GridPanel, TabPanel, TreePanel, Toolbar, Menu, etc.).</p>
4006      * <br><p><b><code>layout</code></b> may be specified as either as an Object or
4007      * as a String:</p><div><ul class="mdetail-params">
4008      *
4009      * <li><u>Specify as an Object</u></li>
4010      * <div><ul class="mdetail-params">
4011      * <li>Example usage:</li>
4012 <pre><code>
4013 layout: {
4014     type: 'vbox',
4015     padding: '5',
4016     align: 'left'
4017 }
4018 </code></pre>
4019      *
4020      * <li><code><b>type</b></code></li>
4021      * <br/><p>The layout type to be used for this container.  If not specified,
4022      * a default {@link Ext.layout.ContainerLayout} will be created and used.</p>
4023      * <br/><p>Valid layout <code>type</code> values are:</p>
4024      * <div class="sub-desc"><ul class="mdetail-params">
4025      * <li><code><b>{@link Ext.layout.AbsoluteLayout absolute}</b></code></li>
4026      * <li><code><b>{@link Ext.layout.AccordionLayout accordion}</b></code></li>
4027      * <li><code><b>{@link Ext.layout.AnchorLayout anchor}</b></code></li>
4028      * <li><code><b>{@link Ext.layout.ContainerLayout auto}</b></code> &nbsp;&nbsp;&nbsp; <b>Default</b></li>
4029      * <li><code><b>{@link Ext.layout.BorderLayout border}</b></code></li>
4030      * <li><code><b>{@link Ext.layout.CardLayout card}</b></code></li>
4031      * <li><code><b>{@link Ext.layout.ColumnLayout column}</b></code></li>
4032      * <li><code><b>{@link Ext.layout.FitLayout fit}</b></code></li>
4033      * <li><code><b>{@link Ext.layout.FormLayout form}</b></code></li>
4034      * <li><code><b>{@link Ext.layout.HBoxLayout hbox}</b></code></li>
4035      * <li><code><b>{@link Ext.layout.MenuLayout menu}</b></code></li>
4036      * <li><code><b>{@link Ext.layout.TableLayout table}</b></code></li>
4037      * <li><code><b>{@link Ext.layout.ToolbarLayout toolbar}</b></code></li>
4038      * <li><code><b>{@link Ext.layout.VBoxLayout vbox}</b></code></li>
4039      * </ul></div>
4040      *
4041      * <li>Layout specific configuration properties</li>
4042      * <br/><p>Additional layout specific configuration properties may also be
4043      * specified. For complete details regarding the valid config options for
4044      * each layout type, see the layout class corresponding to the <code>type</code>
4045      * specified.</p>
4046      *
4047      * </ul></div>
4048      *
4049      * <li><u>Specify as a String</u></li>
4050      * <div><ul class="mdetail-params">
4051      * <li>Example usage:</li>
4052 <pre><code>
4053 layout: 'vbox',
4054 layoutConfig: {
4055     padding: '5',
4056     align: 'left'
4057 }
4058 </code></pre>
4059      * <li><code><b>layout</b></code></li>
4060      * <br/><p>The layout <code>type</code> to be used for this container (see list
4061      * of valid layout type values above).</p><br/>
4062      * <li><code><b>{@link #layoutConfig}</b></code></li>
4063      * <br/><p>Additional layout specific configuration properties. For complete
4064      * details regarding the valid config options for each layout type, see the
4065      * layout class corresponding to the <code>layout</code> specified.</p>
4066      * </ul></div></ul></div>
4067      */
4068     /**
4069      * @cfg {Object} layoutConfig
4070      * This is a config object containing properties specific to the chosen
4071      * <b><code>{@link #layout}</code></b> if <b><code>{@link #layout}</code></b>
4072      * has been specified as a <i>string</i>.</p>
4073      */
4074     /**
4075      * @cfg {Boolean/Number} bufferResize
4076      * When set to true (50 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer
4077      * the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers
4078      * with a large quantity of sub-components for which frequent layout calls would be expensive. Defaults to <code>50</code>.
4079      */
4080     bufferResize: 50,
4081
4082     /**
4083      * @cfg {String/Number} activeItem
4084      * A string component id or the numeric index of the component that should be initially activated within the
4085      * container's layout on render.  For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first
4086      * item in the container's collection).  activeItem only applies to layout styles that can display
4087      * items one at a time (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout} and
4088      * {@link Ext.layout.FitLayout}).  Related to {@link Ext.layout.ContainerLayout#activeItem}.
4089      */
4090     /**
4091      * @cfg {Object/Array} items
4092      * <pre><b>** IMPORTANT</b>: be sure to <b>{@link #layout specify a <code>layout</code>} if needed ! **</b></pre>
4093      * <p>A single item, or an array of child Components to be added to this container,
4094      * for example:</p>
4095      * <pre><code>
4096 // specifying a single item
4097 items: {...},
4098 layout: 'fit',    // specify a layout!
4099
4100 // specifying multiple items
4101 items: [{...}, {...}],
4102 layout: 'anchor', // specify a layout!
4103      * </code></pre>
4104      * <p>Each item may be:</p>
4105      * <div><ul class="mdetail-params">
4106      * <li>any type of object based on {@link Ext.Component}</li>
4107      * <li>a fully instanciated object or</li>
4108      * <li>an object literal that:</li>
4109      * <div><ul class="mdetail-params">
4110      * <li>has a specified <code>{@link Ext.Component#xtype xtype}</code></li>
4111      * <li>the {@link Ext.Component#xtype} specified is associated with the Component
4112      * desired and should be chosen from one of the available xtypes as listed
4113      * in {@link Ext.Component}.</li>
4114      * <li>If an <code>{@link Ext.Component#xtype xtype}</code> is not explicitly
4115      * specified, the {@link #defaultType} for that Container is used.</li>
4116      * <li>will be "lazily instanciated", avoiding the overhead of constructing a fully
4117      * instanciated Component object</li>
4118      * </ul></div></ul></div>
4119      * <p><b>Notes</b>:</p>
4120      * <div><ul class="mdetail-params">
4121      * <li>Ext uses lazy rendering. Child Components will only be rendered
4122      * should it become necessary. Items are automatically laid out when they are first
4123      * shown (no sizing is done while hidden), or in response to a {@link #doLayout} call.</li>
4124      * <li>Do not specify <code>{@link Ext.Panel#contentEl contentEl}</code>/
4125      * <code>{@link Ext.Panel#html html}</code> with <code>items</code>.</li>
4126      * </ul></div>
4127      */
4128     /**
4129      * @cfg {Object|Function} defaults
4130      * <p>This option is a means of applying default settings to all added items whether added through the {@link #items}
4131      * config or via the {@link #add} or {@link #insert} methods.</p>
4132      * <p>If an added item is a config object, and <b>not</b> an instantiated Component, then the default properties are
4133      * unconditionally applied. If the added item <b>is</b> an instantiated Component, then the default properties are
4134      * applied conditionally so as not to override existing properties in the item.</p>
4135      * <p>If the defaults option is specified as a function, then the function will be called using this Container as the
4136      * scope (<code>this</code> reference) and passing the added item as the first parameter. Any resulting object
4137      * from that call is then applied to the item as default properties.</p>
4138      * <p>For example, to automatically apply padding to the body of each of a set of
4139      * contained {@link Ext.Panel} items, you could pass: <code>defaults: {bodyStyle:'padding:15px'}</code>.</p>
4140      * <p>Usage:</p><pre><code>
4141 defaults: {               // defaults are applied to items, not the container
4142     autoScroll:true
4143 },
4144 items: [
4145     {
4146         xtype: 'panel',   // defaults <b>do not</b> have precedence over
4147         id: 'panel1',     // options in config objects, so the defaults
4148         autoScroll: false // will not be applied here, panel1 will be autoScroll:false
4149     },
4150     new Ext.Panel({       // defaults <b>do</b> have precedence over options
4151         id: 'panel2',     // options in components, so the defaults
4152         autoScroll: false // will be applied here, panel2 will be autoScroll:true.
4153     })
4154 ]
4155      * </code></pre>
4156      */
4157
4158
4159     /** @cfg {Boolean} autoDestroy
4160      * If true the container will automatically destroy any contained component that is removed from it, else
4161      * destruction must be handled manually (defaults to true).
4162      */
4163     autoDestroy : true,
4164
4165     /** @cfg {Boolean} forceLayout
4166      * If true the container will force a layout initially even if hidden or collapsed. This option
4167      * is useful for forcing forms to render in collapsed or hidden containers. (defaults to false).
4168      */
4169     forceLayout: false,
4170
4171     /** @cfg {Boolean} hideBorders
4172      * True to hide the borders of each contained component, false to defer to the component's existing
4173      * border settings (defaults to false).
4174      */
4175     /** @cfg {String} defaultType
4176      * <p>The default {@link Ext.Component xtype} of child Components to create in this Container when
4177      * a child item is specified as a raw configuration object, rather than as an instantiated Component.</p>
4178      * <p>Defaults to <code>'panel'</code>, except {@link Ext.menu.Menu} which defaults to <code>'menuitem'</code>,
4179      * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to <code>'button'</code>.</p>
4180      */
4181     defaultType : 'panel',
4182
4183     /** @cfg {String} resizeEvent
4184      * The event to listen to for resizing in layouts. Defaults to <code>'resize'</code>.
4185      */
4186     resizeEvent: 'resize',
4187
4188     /**
4189      * @cfg {Array} bubbleEvents
4190      * <p>An array of events that, when fired, should be bubbled to any parent container.
4191      * See {@link Ext.util.Observable#enableBubble}.
4192      * Defaults to <code>['add', 'remove']</code>.
4193      */
4194     bubbleEvents: ['add', 'remove'],
4195
4196     // private
4197     initComponent : function(){
4198         Ext.Container.superclass.initComponent.call(this);
4199
4200         this.addEvents(
4201             /**
4202              * @event afterlayout
4203              * Fires when the components in this container are arranged by the associated layout manager.
4204              * @param {Ext.Container} this
4205              * @param {ContainerLayout} layout The ContainerLayout implementation for this container
4206              */
4207             'afterlayout',
4208             /**
4209              * @event beforeadd
4210              * Fires before any {@link Ext.Component} is added or inserted into the container.
4211              * A handler can return false to cancel the add.
4212              * @param {Ext.Container} this
4213              * @param {Ext.Component} component The component being added
4214              * @param {Number} index The index at which the component will be added to the container's items collection
4215              */
4216             'beforeadd',
4217             /**
4218              * @event beforeremove
4219              * Fires before any {@link Ext.Component} is removed from the container.  A handler can return
4220              * false to cancel the remove.
4221              * @param {Ext.Container} this
4222              * @param {Ext.Component} component The component being removed
4223              */
4224             'beforeremove',
4225             /**
4226              * @event add
4227              * @bubbles
4228              * Fires after any {@link Ext.Component} is added or inserted into the container.
4229              * @param {Ext.Container} this
4230              * @param {Ext.Component} component The component that was added
4231              * @param {Number} index The index at which the component was added to the container's items collection
4232              */
4233             'add',
4234             /**
4235              * @event remove
4236              * @bubbles
4237              * Fires after any {@link Ext.Component} is removed from the container.
4238              * @param {Ext.Container} this
4239              * @param {Ext.Component} component The component that was removed
4240              */
4241             'remove'
4242         );
4243
4244         this.enableBubble(this.bubbleEvents);
4245
4246         /**
4247          * The collection of components in this container as a {@link Ext.util.MixedCollection}
4248          * @type MixedCollection
4249          * @property items
4250          */
4251         var items = this.items;
4252         if(items){
4253             delete this.items;
4254             this.add(items);
4255         }
4256     },
4257
4258     // private
4259     initItems : function(){
4260         if(!this.items){
4261             this.items = new Ext.util.MixedCollection(false, this.getComponentId);
4262             this.getLayout(); // initialize the layout
4263         }
4264     },
4265
4266     // private
4267     setLayout : function(layout){
4268         if(this.layout && this.layout != layout){
4269             this.layout.setContainer(null);
4270         }
4271         this.initItems();
4272         this.layout = layout;
4273         layout.setContainer(this);
4274     },
4275
4276     afterRender: function(){
4277         this.layoutDone = false;
4278         if(!this.layout){
4279             this.layout = 'auto';
4280         }
4281         if(Ext.isObject(this.layout) && !this.layout.layout){
4282             this.layoutConfig = this.layout;
4283             this.layout = this.layoutConfig.type;
4284         }
4285         if(Ext.isString(this.layout)){
4286             this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
4287         }
4288         this.setLayout(this.layout);
4289
4290         // BoxComponent's afterRender will set the size.
4291         // This will will trigger a layout if the layout is configured to monitor resize
4292         Ext.Container.superclass.afterRender.call(this);
4293
4294         if(Ext.isDefined(this.activeItem)){
4295             var item = this.activeItem;
4296             delete this.activeItem;
4297             this.layout.setActiveItem(item);
4298         }
4299
4300         // If we have no ownerCt and the BoxComponent's sizing did not trigger a layout, force a layout
4301         if(!this.ownerCt && !this.layoutDone){
4302             this.doLayout(false, true);
4303         }
4304
4305         if(this.monitorResize === true){
4306             Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
4307         }
4308     },
4309
4310     /**
4311      * <p>Returns the Element to be used to contain the child Components of this Container.</p>
4312      * <p>An implementation is provided which returns the Container's {@link #getEl Element}, but
4313      * if there is a more complex structure to a Container, this may be overridden to return
4314      * the element into which the {@link #layout layout} renders child Components.</p>
4315      * @return {Ext.Element} The Element to render child Components into.
4316      */
4317     getLayoutTarget : function(){
4318         return this.el;
4319     },
4320
4321     // private - used as the key lookup function for the items collection
4322     getComponentId : function(comp){
4323         return comp.getItemId();
4324     },
4325
4326     /**
4327      * <p>Adds {@link Ext.Component Component}(s) to this Container.</p>
4328      * <br><p><b>Description</b></u> :
4329      * <div><ul class="mdetail-params">
4330      * <li>Fires the {@link #beforeadd} event before adding</li>
4331      * <li>The Container's {@link #defaults default config values} will be applied
4332      * accordingly (see <code>{@link #defaults}</code> for details).</li>
4333      * <li>Fires the {@link #add} event after the component has been added.</li>
4334      * </ul></div>
4335      * <br><p><b>Notes</b></u> :
4336      * <div><ul class="mdetail-params">
4337      * <li>If the Container is <i>already rendered</i> when <code>add</code>
4338      * is called, you may need to call {@link #doLayout} to refresh the view which causes
4339      * any unrendered child Components to be rendered. This is required so that you can
4340      * <code>add</code> multiple child components if needed while only refreshing the layout
4341      * once. For example:<pre><code>
4342 var tb = new {@link Ext.Toolbar}();
4343 tb.render(document.body);  // toolbar is rendered
4344 tb.add({text:'Button 1'}); // add multiple items ({@link #defaultType} for {@link Ext.Toolbar Toolbar} is 'button')
4345 tb.add({text:'Button 2'});
4346 tb.{@link #doLayout}();             // refresh the layout
4347      * </code></pre></li>
4348      * <li><i>Warning:</i> Containers directly managed by the BorderLayout layout manager
4349      * may not be removed or added.  See the Notes for {@link Ext.layout.BorderLayout BorderLayout}
4350      * for more details.</li>
4351      * </ul></div>
4352      * @param {Object/Array} component
4353      * <p>Either a single component or an Array of components to add.  See
4354      * <code>{@link #items}</code> for additional information.</p>
4355      * @param {Object} (Optional) component_2
4356      * @param {Object} (Optional) component_n
4357      * @return {Ext.Component} component The Component (or config object) that was added.
4358      */
4359     add : function(comp){
4360         this.initItems();
4361         var args = arguments.length > 1;
4362         if(args || Ext.isArray(comp)){
4363             var result = [];
4364             Ext.each(args ? arguments : comp, function(c){
4365                 result.push(this.add(c));
4366             }, this);
4367             return result;
4368         }
4369         var c = this.lookupComponent(this.applyDefaults(comp));
4370         var index = this.items.length;
4371         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
4372             this.items.add(c);
4373             // *onAdded
4374             c.onAdded(this, index);
4375             this.onAdd(c);
4376             this.fireEvent('add', this, c, index);
4377         }
4378         return c;
4379     },
4380
4381     onAdd : function(c){
4382         // Empty template method
4383     },
4384     
4385     // private
4386     onAdded : function(container, pos) {
4387         //overridden here so we can cascade down, not worth creating a template method.
4388         this.ownerCt = container;
4389         this.initRef();
4390         //initialize references for child items
4391         this.cascade(function(c){
4392             c.initRef();
4393         });
4394         this.fireEvent('added', this, container, pos);
4395     },
4396
4397     /**
4398      * Inserts a Component into this Container at a specified index. Fires the
4399      * {@link #beforeadd} event before inserting, then fires the {@link #add} event after the
4400      * Component has been inserted.
4401      * @param {Number} index The index at which the Component will be inserted
4402      * into the Container's items collection
4403      * @param {Ext.Component} component The child Component to insert.<br><br>
4404      * Ext uses lazy rendering, and will only render the inserted Component should
4405      * it become necessary.<br><br>
4406      * A Component config object may be passed in order to avoid the overhead of
4407      * constructing a real Component object if lazy rendering might mean that the
4408      * inserted Component will not be rendered immediately. To take advantage of
4409      * this 'lazy instantiation', set the {@link Ext.Component#xtype} config
4410      * property to the registered type of the Component wanted.<br><br>
4411      * For a list of all available xtypes, see {@link Ext.Component}.
4412      * @return {Ext.Component} component The Component (or config object) that was
4413      * inserted with the Container's default config values applied.
4414      */
4415     insert : function(index, comp){
4416         this.initItems();
4417         var a = arguments, len = a.length;
4418         if(len > 2){
4419             var result = [];
4420             for(var i = len-1; i >= 1; --i) {
4421                 result.push(this.insert(index, a[i]));
4422             }
4423             return result;
4424         }
4425         var c = this.lookupComponent(this.applyDefaults(comp));
4426         index = Math.min(index, this.items.length);
4427         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
4428             if(c.ownerCt == this){
4429                 this.items.remove(c);
4430             }
4431             this.items.insert(index, c);
4432             c.onAdded(this, index);
4433             this.onAdd(c);
4434             this.fireEvent('add', this, c, index);
4435         }
4436         return c;
4437     },
4438
4439     // private
4440     applyDefaults : function(c){
4441         var d = this.defaults;
4442         if(d){
4443             if(Ext.isFunction(d)){
4444                 d = d.call(this, c);
4445             }
4446             if(Ext.isString(c)){
4447                 c = Ext.ComponentMgr.get(c);
4448                 Ext.apply(c, d);
4449             }else if(!c.events){
4450                 Ext.applyIf(c, d);
4451             }else{
4452                 Ext.apply(c, d);
4453             }
4454         }
4455         return c;
4456     },
4457
4458     // private
4459     onBeforeAdd : function(item){
4460         if(item.ownerCt){
4461             item.ownerCt.remove(item, false);
4462         }
4463         if(this.hideBorders === true){
4464             item.border = (item.border === true);
4465         }
4466     },
4467
4468     /**
4469      * Removes a component from this container.  Fires the {@link #beforeremove} event before removing, then fires
4470      * the {@link #remove} event after the component has been removed.
4471      * @param {Component/String} component The component reference or id to remove.
4472      * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
4473      * Defaults to the value of this Container's {@link #autoDestroy} config.
4474      * @return {Ext.Component} component The Component that was removed.
4475      */
4476     remove : function(comp, autoDestroy){
4477         this.initItems();
4478         var c = this.getComponent(comp);
4479         if(c && this.fireEvent('beforeremove', this, c) !== false){
4480             this.doRemove(c, autoDestroy);
4481             this.fireEvent('remove', this, c);
4482         }
4483         return c;
4484     },
4485
4486     onRemove: function(c){
4487         // Empty template method
4488     },
4489
4490     // private
4491     doRemove: function(c, autoDestroy){
4492         if(this.layout && this.rendered){
4493             this.layout.onRemove(c);
4494         }
4495         this.items.remove(c);
4496         c.onRemoved();
4497         this.onRemove(c);
4498         if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
4499             c.destroy();
4500         }
4501     },
4502
4503     /**
4504      * Removes all components from this container.
4505      * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
4506      * Defaults to the value of this Container's {@link #autoDestroy} config.
4507      * @return {Array} Array of the destroyed components
4508      */
4509     removeAll: function(autoDestroy){
4510         this.initItems();
4511         var item, rem = [], items = [];
4512         this.items.each(function(i){
4513             rem.push(i);
4514         });
4515         for (var i = 0, len = rem.length; i < len; ++i){
4516             item = rem[i];
4517             this.remove(item, autoDestroy);
4518             if(item.ownerCt !== this){
4519                 items.push(item);
4520             }
4521         }
4522         return items;
4523     },
4524
4525     /**
4526      * Examines this container's <code>{@link #items}</code> <b>property</b>
4527      * and gets a direct child component of this container.
4528      * @param {String/Number} comp This parameter may be any of the following:
4529      * <div><ul class="mdetail-params">
4530      * <li>a <b><code>String</code></b> : representing the <code>{@link Ext.Component#itemId itemId}</code>
4531      * or <code>{@link Ext.Component#id id}</code> of the child component </li>
4532      * <li>a <b><code>Number</code></b> : representing the position of the child component
4533      * within the <code>{@link #items}</code> <b>property</b></li>
4534      * </ul></div>
4535      * <p>For additional information see {@link Ext.util.MixedCollection#get}.
4536      * @return Ext.Component The component (if found).
4537      */
4538     getComponent : function(comp){
4539         if(Ext.isObject(comp)){
4540             comp = comp.getItemId();
4541         }
4542         return this.items.get(comp);
4543     },
4544
4545     // private
4546     lookupComponent : function(comp){
4547         if(Ext.isString(comp)){
4548             return Ext.ComponentMgr.get(comp);
4549         }else if(!comp.events){
4550             return this.createComponent(comp);
4551         }
4552         return comp;
4553     },
4554
4555     // private
4556     createComponent : function(config, defaultType){
4557         // add in ownerCt at creation time but then immediately
4558         // remove so that onBeforeAdd can handle it
4559         var c = config.render ? config : Ext.create(Ext.apply({
4560             ownerCt: this
4561         }, config), defaultType || this.defaultType);
4562         delete c.ownerCt;
4563         return c;
4564     },
4565
4566     /**
4567     * We can only lay out if there is a view area in which to layout.
4568     * display:none on the layout target, *or any of its parent elements* will mean it has no view area.
4569     */
4570     canLayout: function() {
4571         var el = this.getLayoutTarget(), vs;
4572         return !!(el && (vs = el.dom.offsetWidth || el.dom.offsetHeight));
4573     },
4574
4575     /**
4576      * Force this container's layout to be recalculated. A call to this function is required after adding a new component
4577      * to an already rendered container, or possibly after changing sizing/position properties of child components.
4578      * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto
4579      * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer)
4580      * @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden.
4581      * @return {Ext.Container} this
4582      */
4583     doLayout: function(shallow, force){
4584         var rendered = this.rendered,
4585             forceLayout = force || this.forceLayout,
4586             cs, i, len, c;
4587
4588         this.layoutDone = true;
4589         if(!this.canLayout() || this.collapsed){
4590             this.deferLayout = this.deferLayout || !shallow;
4591             if(!forceLayout){
4592                 return;
4593             }
4594             shallow = shallow && !this.deferLayout;
4595         } else {
4596             delete this.deferLayout;
4597         }
4598
4599         cs = (shallow !== true && this.items) ? this.items.items : [];
4600
4601 //      Inhibit child Containers from relaying on resize since we are about to to explicitly call doLayout on them all!
4602         for(i = 0, len = cs.length; i < len; i++){
4603             if ((c = cs[i]).layout) {
4604                 c.suspendLayoutResize = true;
4605             }
4606         }
4607
4608 //      Tell the layout manager to ensure all child items are rendered, and sized according to their rules.
4609 //      Will not cause the child items to relayout.
4610         if(rendered && this.layout){
4611             this.layout.layout();
4612         }
4613
4614 //      Explicitly lay out all child items
4615         for(i = 0; i < len; i++){
4616             if((c = cs[i]).doLayout){
4617                 c.doLayout(false, forceLayout);
4618             }
4619         }
4620         if(rendered){
4621             this.onLayout(shallow, forceLayout);
4622         }
4623         // Initial layout completed
4624         this.hasLayout = true;
4625         delete this.forceLayout;
4626
4627 //      Re-enable child layouts relaying on resize.
4628         for(i = 0; i < len; i++){
4629             if ((c = cs[i]).layout) {
4630                 delete c.suspendLayoutResize;
4631             }
4632         }
4633     },
4634
4635     //private
4636     onLayout : Ext.emptyFn,
4637
4638     onResize: function(adjWidth, adjHeight, rawWidth, rawHeight){
4639         Ext.Container.superclass.onResize.apply(this, arguments);
4640         if ((this.rendered && this.layout && this.layout.monitorResize) && !this.suspendLayoutResize) {
4641             this.layout.onResize();
4642         }
4643     },
4644
4645     // private
4646     hasLayoutPending: function(){
4647         // Traverse hierarchy to see if any parent container has a pending layout.
4648         var pending = this.layoutPending;
4649         this.ownerCt.bubble(function(c){
4650             return !(pending = c.layoutPending);
4651         });
4652         return pending;
4653
4654     },
4655
4656     onShow : function(){
4657         Ext.Container.superclass.onShow.call(this);
4658         if(Ext.isDefined(this.deferLayout)){
4659             this.doLayout(true);
4660         }
4661     },
4662
4663     /**
4664      * Returns the layout currently in use by the container.  If the container does not currently have a layout
4665      * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout.
4666      * @return {ContainerLayout} layout The container's layout
4667      */
4668     getLayout : function(){
4669         if(!this.layout){
4670             var layout = new Ext.layout.ContainerLayout(this.layoutConfig);
4671             this.setLayout(layout);
4672         }
4673         return this.layout;
4674     },
4675
4676     // private
4677     beforeDestroy : function(){
4678         var c;
4679         if(this.items){
4680             while(c = this.items.first()){
4681                 this.doRemove(c, true);
4682             }
4683         }
4684         if(this.monitorResize){
4685             Ext.EventManager.removeResizeListener(this.doLayout, this);
4686         }
4687         Ext.destroy(this.layout);
4688         Ext.Container.superclass.beforeDestroy.call(this);
4689     },
4690
4691     /**
4692      * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of
4693      * function call will be the scope provided or the current component. The arguments to the function
4694      * will be the args provided or the current component. If the function returns false at any point,
4695      * the bubble is stopped.
4696      * @param {Function} fn The function to call
4697      * @param {Object} scope (optional) The scope of the function (defaults to current node)
4698      * @param {Array} args (optional) The args to call the function with (default to passing the current component)
4699      * @return {Ext.Container} this
4700      */
4701     bubble : function(fn, scope, args){
4702         var p = this;
4703         while(p){
4704             if(fn.apply(scope || p, args || [p]) === false){
4705                 break;
4706             }
4707             p = p.ownerCt;
4708         }
4709         return this;
4710     },
4711
4712     /**
4713      * Cascades down the component/container heirarchy from this component (called first), calling the specified function with
4714      * each component. The scope (<i>this</i>) of
4715      * function call will be the scope provided or the current component. The arguments to the function
4716      * will be the args provided or the current component. If the function returns false at any point,
4717      * the cascade is stopped on that branch.
4718      * @param {Function} fn The function to call
4719      * @param {Object} scope (optional) The scope of the function (defaults to current component)
4720      * @param {Array} args (optional) The args to call the function with (defaults to passing the current component)
4721      * @return {Ext.Container} this
4722      */
4723     cascade : function(fn, scope, args){
4724         if(fn.apply(scope || this, args || [this]) !== false){
4725             if(this.items){
4726                 var cs = this.items.items;
4727                 for(var i = 0, len = cs.length; i < len; i++){
4728                     if(cs[i].cascade){
4729                         cs[i].cascade(fn, scope, args);
4730                     }else{
4731                         fn.apply(scope || cs[i], args || [cs[i]]);
4732                     }
4733                 }
4734             }
4735         }
4736         return this;
4737     },
4738
4739     /**
4740      * Find a component under this container at any level by id
4741      * @param {String} id
4742      * @return Ext.Component
4743      */
4744     findById : function(id){
4745         var m, ct = this;
4746         this.cascade(function(c){
4747             if(ct != c && c.id === id){
4748                 m = c;
4749                 return false;
4750             }
4751         });
4752         return m || null;
4753     },
4754
4755     /**
4756      * Find a component under this container at any level by xtype or class
4757      * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
4758      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
4759      * the default), or true to check whether this Component is directly of the specified xtype.
4760      * @return {Array} Array of Ext.Components
4761      */
4762     findByType : function(xtype, shallow){
4763         return this.findBy(function(c){
4764             return c.isXType(xtype, shallow);
4765         });
4766     },
4767
4768     /**
4769      * Find a component under this container at any level by property
4770      * @param {String} prop
4771      * @param {String} value
4772      * @return {Array} Array of Ext.Components
4773      */
4774     find : function(prop, value){
4775         return this.findBy(function(c){
4776             return c[prop] === value;
4777         });
4778     },
4779
4780     /**
4781      * Find a component under this container at any level by a custom function. If the passed function returns
4782      * true, the component will be included in the results. The passed function is called with the arguments (component, this container).
4783      * @param {Function} fn The function to call
4784      * @param {Object} scope (optional)
4785      * @return {Array} Array of Ext.Components
4786      */
4787     findBy : function(fn, scope){
4788         var m = [], ct = this;
4789         this.cascade(function(c){
4790             if(ct != c && fn.call(scope || c, c, ct) === true){
4791                 m.push(c);
4792             }
4793         });
4794         return m;
4795     },
4796
4797     /**
4798      * Get a component contained by this container (alias for items.get(key))
4799      * @param {String/Number} key The index or id of the component
4800      * @return {Ext.Component} Ext.Component
4801      */
4802     get : function(key){
4803         return this.items.get(key);
4804     }
4805 });
4806
4807 Ext.Container.LAYOUTS = {};
4808 Ext.reg('container', Ext.Container);
4809 /**
4810  * @class Ext.layout.ContainerLayout
4811  * <p>The ContainerLayout class is the default layout manager delegated by {@link Ext.Container} to
4812  * render any child Components when no <tt>{@link Ext.Container#layout layout}</tt> is configured into
4813  * a {@link Ext.Container Container}. ContainerLayout provides the basic foundation for all other layout
4814  * classes in Ext. It simply renders all child Components into the Container, performing no sizing or
4815  * positioning services. To utilize a layout that provides sizing and positioning of child Components,
4816  * specify an appropriate <tt>{@link Ext.Container#layout layout}</tt>.</p>
4817  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
4818  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
4819  */
4820 Ext.layout.ContainerLayout = Ext.extend(Object, {
4821     /**
4822      * @cfg {String} extraCls
4823      * <p>An optional extra CSS class that will be added to the container. This can be useful for adding
4824      * customized styles to the container or any of its children using standard CSS rules. See
4825      * {@link Ext.Component}.{@link Ext.Component#ctCls ctCls} also.</p>
4826      * <p><b>Note</b>: <tt>extraCls</tt> defaults to <tt>''</tt> except for the following classes
4827      * which assign a value by default:
4828      * <div class="mdetail-params"><ul>
4829      * <li>{@link Ext.layout.AbsoluteLayout Absolute Layout} : <tt>'x-abs-layout-item'</tt></li>
4830      * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-item'</tt></li>
4831      * <li>{@link Ext.layout.ColumnLayout Column Layout} : <tt>'x-column'</tt></li>
4832      * </ul></div>
4833      * To configure the above Classes with an extra CSS class append to the default.  For example,
4834      * for ColumnLayout:<pre><code>
4835      * extraCls: 'x-column custom-class'
4836      * </code></pre>
4837      * </p>
4838      */
4839     /**
4840      * @cfg {Boolean} renderHidden
4841      * True to hide each contained item on render (defaults to false).
4842      */
4843
4844     /**
4845      * A reference to the {@link Ext.Component} that is active.  For example, <pre><code>
4846      * if(myPanel.layout.activeItem.id == 'item-1') { ... }
4847      * </code></pre>
4848      * <tt>activeItem</tt> only applies to layout styles that can display items one at a time
4849      * (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout}
4850      * and {@link Ext.layout.FitLayout}).  Read-only.  Related to {@link Ext.Container#activeItem}.
4851      * @type {Ext.Component}
4852      * @property activeItem
4853      */
4854
4855     // private
4856     monitorResize:false,
4857     // private
4858     activeItem : null,
4859
4860     constructor : function(config){
4861         Ext.apply(this, config);
4862     },
4863
4864     // private
4865     layout : function(){
4866         var target = this.container.getLayoutTarget();
4867         if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
4868             target.addClass(this.targetCls)
4869         }
4870         this.onLayout(this.container, target);
4871         this.container.fireEvent('afterlayout', this.container, this);
4872         this.hasLayout = true;
4873     },
4874
4875     // private
4876     onLayout : function(ct, target){
4877         this.renderAll(ct, target);
4878     },
4879
4880     // private
4881     isValidParent : function(c, target){
4882         return target && c.getPositionEl().dom.parentNode == (target.dom || target);
4883     },
4884
4885     // private
4886     renderAll : function(ct, target){
4887         var items = ct.items.items;
4888         for(var i = 0, len = items.length; i < len; i++) {
4889             var c = items[i];
4890             if(c && (!c.rendered || !this.isValidParent(c, target))){
4891                 this.renderItem(c, i, target);
4892             }
4893         }
4894     },
4895
4896     // private
4897     renderItem : function(c, position, target){
4898         if(c && !c.rendered){
4899             c.render(target, position);
4900             this.configureItem(c, position);
4901         }else if(c && !this.isValidParent(c, target)){
4902             if(Ext.isNumber(position)){
4903                 position = target.dom.childNodes[position];
4904             }
4905             target.dom.insertBefore(c.getPositionEl().dom, position || null);
4906             c.container = target;
4907             this.configureItem(c, position);
4908         }
4909     },
4910
4911     // private
4912     configureItem: function(c, position){
4913         if(this.extraCls){
4914             var t = c.getPositionEl ? c.getPositionEl() : c;
4915             t.addClass(this.extraCls);
4916         }
4917         // If we are forcing a layout, do so *before* we hide so elements have height/width
4918         if(c.doLayout && this.forceLayout){
4919             c.doLayout(false, true);
4920         }
4921         if (this.renderHidden && c != this.activeItem) {
4922             c.hide();
4923         }
4924     },
4925
4926     onRemove: function(c){
4927          if(this.activeItem == c){
4928             delete this.activeItem;
4929          }
4930          if(c.rendered && this.extraCls){
4931             var t = c.getPositionEl ? c.getPositionEl() : c;
4932             t.removeClass(this.extraCls);
4933         }
4934     },
4935
4936     // private
4937     onResize: function(){
4938         var ct = this.container,
4939             b = ct.bufferResize;
4940
4941         if (ct.collapsed){
4942             return;
4943         }
4944
4945         // Not having an ownerCt negates the buffering: floating and top level
4946         // Containers (Viewport, Window, ToolTip, Menu) need to lay out ASAP.
4947         if (b && ct.ownerCt) {
4948             // If we do NOT already have a layout pending from an ancestor, schedule one.
4949             // If there is a layout pending, we do nothing here.
4950             // buffering to be deprecated soon
4951             if (!ct.hasLayoutPending()){
4952                 if(!this.resizeTask){
4953                     this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
4954                     this.resizeBuffer = Ext.isNumber(b) ? b : 50;
4955                 }
4956                 ct.layoutPending = true;
4957                 this.resizeTask.delay(this.resizeBuffer);
4958             }
4959         }else{
4960             ct.doLayout(false, this.forceLayout);
4961         }
4962     },
4963
4964     // private
4965     runLayout: function(){
4966         var ct = this.container;
4967         ct.doLayout();
4968         delete ct.layoutPending;
4969     },
4970
4971     // private
4972     setContainer : function(ct){
4973         // No longer use events to handle resize. Instead this will be handled through a direct function call.
4974         /*
4975         if(this.monitorResize && ct != this.container){
4976             var old = this.container;
4977             if(old){
4978                 old.un(old.resizeEvent, this.onResize, this);
4979             }
4980             if(ct){
4981                 ct.on(ct.resizeEvent, this.onResize, this);
4982             }
4983         }
4984         */
4985         this.container = ct;
4986     },
4987
4988     // private
4989     parseMargins : function(v){
4990         if(Ext.isNumber(v)){
4991             v = v.toString();
4992         }
4993         var ms = v.split(' ');
4994         var len = ms.length;
4995         if(len == 1){
4996             ms[1] = ms[0];
4997             ms[2] = ms[0];
4998             ms[3] = ms[0];
4999         }
5000         if(len == 2){
5001             ms[2] = ms[0];
5002             ms[3] = ms[1];
5003         }
5004         if(len == 3){
5005             ms[3] = ms[1];
5006         }
5007         return {
5008             top:parseInt(ms[0], 10) || 0,
5009             right:parseInt(ms[1], 10) || 0,
5010             bottom:parseInt(ms[2], 10) || 0,
5011             left:parseInt(ms[3], 10) || 0
5012         };
5013     },
5014
5015     /**
5016      * The {@link Ext.Template Ext.Template} used by Field rendering layout classes (such as
5017      * {@link Ext.layout.FormLayout}) to create the DOM structure of a fully wrapped,
5018      * labeled and styled form Field. A default Template is supplied, but this may be
5019      * overriden to create custom field structures. The template processes values returned from
5020      * {@link Ext.layout.FormLayout#getTemplateArgs}.
5021      * @property fieldTpl
5022      * @type Ext.Template
5023      */
5024     fieldTpl: (function() {
5025         var t = new Ext.Template(
5026             '<div class="x-form-item {itemCls}" tabIndex="-1">',
5027                 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
5028                 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
5029                 '</div><div class="{clearCls}"></div>',
5030             '</div>'
5031         );
5032         t.disableFormats = true;
5033         return t.compile();
5034     })(),
5035
5036     /*
5037      * Destroys this layout. This is a template method that is empty by default, but should be implemented
5038      * by subclasses that require explicit destruction to purge event handlers or remove DOM nodes.
5039      * @protected
5040      */
5041     destroy : function(){
5042         if(!Ext.isEmpty(this.targetCls)){
5043             var target = this.container.getLayoutTarget();
5044             if(target){
5045                 target.removeClass(this.targetCls);
5046             }
5047         }
5048     }
5049 });
5050 Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout;
5051 /**\r
5052  * @class Ext.layout.FitLayout\r
5053  * @extends Ext.layout.ContainerLayout\r
5054  * <p>This is a base class for layouts that contain <b>a single item</b> that automatically expands to fill the layout's\r
5055  * container.  This class is intended to be extended or created via the <tt>layout:'fit'</tt> {@link Ext.Container#layout}\r
5056  * config, and should generally not need to be created directly via the new keyword.</p>\r
5057  * <p>FitLayout does not have any direct config options (other than inherited ones).  To fit a panel to a container\r
5058  * using FitLayout, simply set layout:'fit' on the container and add a single panel to it.  If the container has\r
5059  * multiple panels, only the first one will be displayed.  Example usage:</p>\r
5060  * <pre><code>\r
5061 var p = new Ext.Panel({\r
5062     title: 'Fit Layout',\r
5063     layout:'fit',\r
5064     items: {\r
5065         title: 'Inner Panel',\r
5066         html: '&lt;p&gt;This is the inner panel content&lt;/p&gt;',\r
5067         border: false\r
5068     }\r
5069 });\r
5070 </code></pre>\r
5071  */\r
5072 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
5073     // private\r
5074     monitorResize:true,\r
5075 \r
5076     // private\r
5077     onLayout : function(ct, target){\r
5078         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);\r
5079         if(!this.container.collapsed){\r
5080             this.setItemSize(this.activeItem || ct.items.itemAt(0), target.getViewSize(true));\r
5081         }\r
5082     },\r
5083 \r
5084     // private\r
5085     setItemSize : function(item, size){\r
5086         if(item && size.height > 0){ // display none?\r
5087             item.setSize(size);\r
5088         }\r
5089     }\r
5090 });\r
5091 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;/**\r
5092  * @class Ext.layout.CardLayout\r
5093  * @extends Ext.layout.FitLayout\r
5094  * <p>This layout manages multiple child Components, each fitted to the Container, where only a single child Component can be\r
5095  * visible at any given time.  This layout style is most commonly used for wizards, tab implementations, etc.\r
5096  * This class is intended to be extended or created via the layout:'card' {@link Ext.Container#layout} config,\r
5097  * and should generally not need to be created directly via the new keyword.</p>\r
5098  * <p>The CardLayout's focal method is {@link #setActiveItem}.  Since only one panel is displayed at a time,\r
5099  * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of\r
5100  * the next panel to display.  The layout itself does not provide a user interface for handling this navigation,\r
5101  * so that functionality must be provided by the developer.</p>\r
5102  * <p>In the following example, a simplistic wizard setup is demonstrated.  A button bar is added\r
5103  * to the footer of the containing panel to provide navigation buttons.  The buttons will be handled by a\r
5104  * common navigation routine -- for this example, the implementation of that routine has been ommitted since\r
5105  * it can be any type of custom logic.  Note that other uses of a CardLayout (like a tab control) would require a\r
5106  * completely different implementation.  For serious implementations, a better approach would be to extend\r
5107  * CardLayout to provide the custom functionality needed.  Example usage:</p>\r
5108  * <pre><code>\r
5109 var navHandler = function(direction){\r
5110     // This routine could contain business logic required to manage the navigation steps.\r
5111     // It would call setActiveItem as needed, manage navigation button state, handle any\r
5112     // branching logic that might be required, handle alternate actions like cancellation\r
5113     // or finalization, etc.  A complete wizard implementation could get pretty\r
5114     // sophisticated depending on the complexity required, and should probably be\r
5115     // done as a subclass of CardLayout in a real-world implementation.\r
5116 };\r
5117 \r
5118 var card = new Ext.Panel({\r
5119     title: 'Example Wizard',\r
5120     layout:'card',\r
5121     activeItem: 0, // make sure the active item is set on the container config!\r
5122     bodyStyle: 'padding:15px',\r
5123     defaults: {\r
5124         // applied to each contained panel\r
5125         border:false\r
5126     },\r
5127     // just an example of one possible navigation scheme, using buttons\r
5128     bbar: [\r
5129         {\r
5130             id: 'move-prev',\r
5131             text: 'Back',\r
5132             handler: navHandler.createDelegate(this, [-1]),\r
5133             disabled: true\r
5134         },\r
5135         '->', // greedy spacer so that the buttons are aligned to each side\r
5136         {\r
5137             id: 'move-next',\r
5138             text: 'Next',\r
5139             handler: navHandler.createDelegate(this, [1])\r
5140         }\r
5141     ],\r
5142     // the panels (or "cards") within the layout\r
5143     items: [{\r
5144         id: 'card-0',\r
5145         html: '&lt;h1&gt;Welcome to the Wizard!&lt;/h1&gt;&lt;p&gt;Step 1 of 3&lt;/p&gt;'\r
5146     },{\r
5147         id: 'card-1',\r
5148         html: '&lt;p&gt;Step 2 of 3&lt;/p&gt;'\r
5149     },{\r
5150         id: 'card-2',\r
5151         html: '&lt;h1&gt;Congratulations!&lt;/h1&gt;&lt;p&gt;Step 3 of 3 - Complete&lt;/p&gt;'\r
5152     }]\r
5153 });\r
5154 </code></pre>\r
5155  */\r
5156 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {\r
5157     /**\r
5158      * @cfg {Boolean} deferredRender\r
5159      * True to render each contained item at the time it becomes active, false to render all contained items\r
5160      * as soon as the layout is rendered (defaults to false).  If there is a significant amount of content or\r
5161      * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to\r
5162      * true might improve performance.\r
5163      */\r
5164     deferredRender : false,\r
5165     \r
5166     /**\r
5167      * @cfg {Boolean} layoutOnCardChange\r
5168      * True to force a layout of the active item when the active card is changed. Defaults to false.\r
5169      */\r
5170     layoutOnCardChange : false,\r
5171 \r
5172     /**\r
5173      * @cfg {Boolean} renderHidden @hide\r
5174      */\r
5175     // private\r
5176     renderHidden : true,\r
5177     \r
5178     constructor: function(config){\r
5179         Ext.layout.CardLayout.superclass.constructor.call(this, config);\r
5180       //  this.forceLayout = (this.deferredRender === false);\r
5181     },\r
5182 \r
5183     /**\r
5184      * Sets the active (visible) item in the layout.\r
5185      * @param {String/Number} item The string component id or numeric index of the item to activate\r
5186      */\r
5187     setActiveItem : function(item){\r
5188         var ai = this.activeItem;\r
5189         item = this.container.getComponent(item);\r
5190         if(ai != item){\r
5191             if(ai){\r
5192                 ai.hide();\r
5193                 ai.fireEvent('deactivate', ai);\r
5194             }\r
5195             var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);\r
5196             this.activeItem = item;\r
5197             if(item){\r
5198                 item.show();\r
5199             }\r
5200             this.layout();\r
5201             if(item && layout){\r
5202                 item.doLayout();\r
5203             }\r
5204             item.fireEvent('activate', item);\r
5205         }\r
5206     },\r
5207 \r
5208     // private\r
5209     renderAll : function(ct, target){\r
5210         if(this.deferredRender){\r
5211             this.renderItem(this.activeItem, undefined, target);\r
5212         }else{\r
5213             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);\r
5214         }\r
5215     }\r
5216 });\r
5217 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;/**
5218  * @class Ext.layout.AnchorLayout
5219  * @extends Ext.layout.ContainerLayout
5220  * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.
5221  * If the container is resized, all anchored items are automatically rerendered according to their
5222  * <b><tt>{@link #anchor}</tt></b> rules.</p>
5223  * <p>This class is intended to be extended or created via the layout:'anchor' {@link Ext.Container#layout}
5224  * config, and should generally not need to be created directly via the new keyword.</p>
5225  * <p>AnchorLayout does not have any direct config options (other than inherited ones). By default,
5226  * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the
5227  * container using the AnchorLayout can supply an anchoring-specific config property of <b>anchorSize</b>.
5228  * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating
5229  * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring
5230  * logic if necessary.  For example:</p>
5231  * <pre><code>
5232 var viewport = new Ext.Viewport({
5233     layout:'anchor',
5234     anchorSize: {width:800, height:600},
5235     items:[{
5236         title:'Item 1',
5237         html:'Content 1',
5238         width:800,
5239         anchor:'right 20%'
5240     },{
5241         title:'Item 2',
5242         html:'Content 2',
5243         width:300,
5244         anchor:'50% 30%'
5245     },{
5246         title:'Item 3',
5247         html:'Content 3',
5248         width:600,
5249         anchor:'-100 50%'
5250     }]
5251 });
5252  * </code></pre>
5253  */
5254 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
5255     /**
5256      * @cfg {String} anchor
5257      * <p>This configuation option is to be applied to <b>child <tt>items</tt></b> of a container managed by
5258      * this layout (ie. configured with <tt>layout:'anchor'</tt>).</p><br/>
5259      *
5260      * <p>This value is what tells the layout how an item should be anchored to the container. <tt>items</tt>
5261      * added to an AnchorLayout accept an anchoring-specific config property of <b>anchor</b> which is a string
5262      * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').
5263      * The following types of anchor values are supported:<div class="mdetail-params"><ul>
5264      *
5265      * <li><b>Percentage</b> : Any value between 1 and 100, expressed as a percentage.<div class="sub-desc">
5266      * The first anchor is the percentage width that the item should take up within the container, and the
5267      * second is the percentage height.  For example:<pre><code>
5268 // two values specified
5269 anchor: '100% 50%' // render item complete width of the container and
5270                    // 1/2 height of the container
5271 // one value specified
5272 anchor: '100%'     // the width value; the height will default to auto
5273      * </code></pre></div></li>
5274      *
5275      * <li><b>Offsets</b> : Any positive or negative integer value.<div class="sub-desc">
5276      * This is a raw adjustment where the first anchor is the offset from the right edge of the container,
5277      * and the second is the offset from the bottom edge. For example:<pre><code>
5278 // two values specified
5279 anchor: '-50 -100' // render item the complete width of the container
5280                    // minus 50 pixels and
5281                    // the complete height minus 100 pixels.
5282 // one value specified
5283 anchor: '-50'      // anchor value is assumed to be the right offset value
5284                    // bottom offset will default to 0
5285      * </code></pre></div></li>
5286      *
5287      * <li><b>Sides</b> : Valid values are <tt>'right'</tt> (or <tt>'r'</tt>) and <tt>'bottom'</tt>
5288      * (or <tt>'b'</tt>).<div class="sub-desc">
5289      * Either the container must have a fixed size or an anchorSize config value defined at render time in
5290      * order for these to have any effect.</div></li>
5291      *
5292      * <li><b>Mixed</b> : <div class="sub-desc">
5293      * Anchor values can also be mixed as needed.  For example, to render the width offset from the container
5294      * right edge by 50 pixels and 75% of the container's height use:
5295      * <pre><code>
5296 anchor: '-50 75%'
5297      * </code></pre></div></li>
5298      *
5299      *
5300      * </ul></div>
5301      */
5302
5303     // private
5304     monitorResize:true,
5305
5306     // private
5307     // deprecate
5308     getAnchorViewSize : function(ct, target){
5309         return target.dom == document.body ?
5310                    target.getViewSize(true) : target.getStyleSize();
5311     },
5312
5313     // private
5314     onLayout : function(ct, target){
5315         Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
5316
5317         var size = target.getViewSize(true);
5318
5319         var w = size.width, h = size.height;
5320
5321         if(w < 20 && h < 20){
5322             return;
5323         }
5324
5325         // find the container anchoring size
5326         var aw, ah;
5327         if(ct.anchorSize){
5328             if(typeof ct.anchorSize == 'number'){
5329                 aw = ct.anchorSize;
5330             }else{
5331                 aw = ct.anchorSize.width;
5332                 ah = ct.anchorSize.height;
5333             }
5334         }else{
5335             aw = ct.initialConfig.width;
5336             ah = ct.initialConfig.height;
5337         }
5338
5339         var cs = ct.items.items, len = cs.length, i, c, a, cw, ch, el, vs;
5340         for(i = 0; i < len; i++){
5341             c = cs[i];
5342             el = c.getPositionEl();
5343             if(c.anchor){
5344                 a = c.anchorSpec;
5345                 if(!a){ // cache all anchor values
5346                     vs = c.anchor.split(' ');
5347                     c.anchorSpec = a = {
5348                         right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
5349                         bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
5350                     };
5351                 }
5352                 cw = a.right ? this.adjustWidthAnchor(a.right(w) - el.getMargins('lr'), c) : undefined;
5353                 ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h) - el.getMargins('tb'), c) : undefined;
5354
5355                 if(cw || ch){
5356                     c.setSize(cw || undefined, ch || undefined);
5357                 }
5358             }
5359         }
5360     },
5361
5362     // private
5363     parseAnchor : function(a, start, cstart){
5364         if(a && a != 'none'){
5365             var last;
5366             if(/^(r|right|b|bottom)$/i.test(a)){   // standard anchor
5367                 var diff = cstart - start;
5368                 return function(v){
5369                     if(v !== last){
5370                         last = v;
5371                         return v - diff;
5372                     }
5373                 }
5374             }else if(a.indexOf('%') != -1){
5375                 var ratio = parseFloat(a.replace('%', ''))*.01;   // percentage
5376                 return function(v){
5377                     if(v !== last){
5378                         last = v;
5379                         return Math.floor(v*ratio);
5380                     }
5381                 }
5382             }else{
5383                 a = parseInt(a, 10);
5384                 if(!isNaN(a)){                            // simple offset adjustment
5385                     return function(v){
5386                         if(v !== last){
5387                             last = v;
5388                             return v + a;
5389                         }
5390                     }
5391                 }
5392             }
5393         }
5394         return false;
5395     },
5396
5397     // private
5398     adjustWidthAnchor : function(value, comp){
5399         return value;
5400     },
5401
5402     // private
5403     adjustHeightAnchor : function(value, comp){
5404         return value;
5405     }
5406
5407     /**
5408      * @property activeItem
5409      * @hide
5410      */
5411 });
5412 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
5413 /**\r
5414  * @class Ext.layout.ColumnLayout\r
5415  * @extends Ext.layout.ContainerLayout\r
5416  * <p>This is the layout style of choice for creating structural layouts in a multi-column format where the width of\r
5417  * each column can be specified as a percentage or fixed width, but the height is allowed to vary based on the content.\r
5418  * This class is intended to be extended or created via the layout:'column' {@link Ext.Container#layout} config,\r
5419  * and should generally not need to be created directly via the new keyword.</p>\r
5420  * <p>ColumnLayout does not have any direct config options (other than inherited ones), but it does support a\r
5421  * specific config property of <b><tt>columnWidth</tt></b> that can be included in the config of any panel added to it.  The\r
5422  * layout will use the columnWidth (if present) or width of each panel during layout to determine how to size each panel.\r
5423  * If width or columnWidth is not specified for a given panel, its width will default to the panel's width (or auto).</p>\r
5424  * <p>The width property is always evaluated as pixels, and must be a number greater than or equal to 1.\r
5425  * The columnWidth property is always evaluated as a percentage, and must be a decimal value greater than 0 and\r
5426  * less than 1 (e.g., .25).</p>\r
5427  * <p>The basic rules for specifying column widths are pretty simple.  The logic makes two passes through the\r
5428  * set of contained panels.  During the first layout pass, all panels that either have a fixed width or none\r
5429  * specified (auto) are skipped, but their widths are subtracted from the overall container width.  During the second\r
5430  * pass, all panels with columnWidths are assigned pixel widths in proportion to their percentages based on\r
5431  * the total <b>remaining</b> container width.  In other words, percentage width panels are designed to fill the space\r
5432  * left over by all the fixed-width and/or auto-width panels.  Because of this, while you can specify any number of columns\r
5433  * with different percentages, the columnWidths must always add up to 1 (or 100%) when added together, otherwise your\r
5434  * layout may not render as expected.  Example usage:</p>\r
5435  * <pre><code>\r
5436 // All columns are percentages -- they must add up to 1\r
5437 var p = new Ext.Panel({\r
5438     title: 'Column Layout - Percentage Only',\r
5439     layout:'column',\r
5440     items: [{\r
5441         title: 'Column 1',\r
5442         columnWidth: .25\r
5443     },{\r
5444         title: 'Column 2',\r
5445         columnWidth: .6\r
5446     },{\r
5447         title: 'Column 3',\r
5448         columnWidth: .15\r
5449     }]\r
5450 });\r
5451 \r
5452 // Mix of width and columnWidth -- all columnWidth values must add up\r
5453 // to 1. The first column will take up exactly 120px, and the last two\r
5454 // columns will fill the remaining container width.\r
5455 var p = new Ext.Panel({\r
5456     title: 'Column Layout - Mixed',\r
5457     layout:'column',\r
5458     items: [{\r
5459         title: 'Column 1',\r
5460         width: 120\r
5461     },{\r
5462         title: 'Column 2',\r
5463         columnWidth: .8\r
5464     },{\r
5465         title: 'Column 3',\r
5466         columnWidth: .2\r
5467     }]\r
5468 });\r
5469 </code></pre>\r
5470  */\r
5471 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
5472     // private\r
5473     monitorResize:true,\r
5474 \r
5475     extraCls: 'x-column',\r
5476 \r
5477     scrollOffset : 0,\r
5478 \r
5479     // private\r
5480 \r
5481     targetCls: 'x-column-layout-ct',\r
5482 \r
5483     isValidParent : function(c, target){\r
5484         return c.getPositionEl().dom.parentNode == this.innerCt.dom;\r
5485     },\r
5486 \r
5487     // private\r
5488     onLayout : function(ct, target){\r
5489         var cs = ct.items.items, len = cs.length, c, i;\r
5490 \r
5491         if(!this.innerCt){\r
5492             // the innerCt prevents wrapping and shuffling while\r
5493             // the container is resizing\r
5494             this.innerCt = target.createChild({cls:'x-column-inner'});\r
5495             this.innerCt.createChild({cls:'x-clear'});\r
5496         }\r
5497         this.renderAll(ct, this.innerCt);\r
5498 \r
5499         var size = target.getViewSize(true);\r
5500 \r
5501         if(size.width < 1 && size.height < 1){ // display none?\r
5502             return;\r
5503         }\r
5504 \r
5505         var w = size.width - this.scrollOffset,\r
5506             h = size.height,\r
5507             pw = w;\r
5508 \r
5509         this.innerCt.setWidth(w);\r
5510 \r
5511         // some columns can be percentages while others are fixed\r
5512         // so we need to make 2 passes\r
5513 \r
5514         for(i = 0; i < len; i++){\r
5515             c = cs[i];\r
5516             if(!c.columnWidth){\r
5517                 pw -= (c.getSize().width + c.getPositionEl().getMargins('lr'));\r
5518             }\r
5519         }\r
5520 \r
5521         pw = pw < 0 ? 0 : pw;\r
5522 \r
5523         for(i = 0; i < len; i++){\r
5524             c = cs[i];\r
5525             if(c.columnWidth){\r
5526                 c.setSize(Math.floor(c.columnWidth * pw) - c.getPositionEl().getMargins('lr'));\r
5527             }\r
5528         }\r
5529     }\r
5530 \r
5531     /**\r
5532      * @property activeItem\r
5533      * @hide\r
5534      */\r
5535 });\r
5536 \r
5537 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;/**
5538  * @class Ext.layout.BorderLayout
5539  * @extends Ext.layout.ContainerLayout
5540  * <p>This is a multi-pane, application-oriented UI layout style that supports multiple
5541  * nested panels, automatic {@link Ext.layout.BorderLayout.Region#split split} bars between
5542  * {@link Ext.layout.BorderLayout.Region#BorderLayout.Region regions} and built-in
5543  * {@link Ext.layout.BorderLayout.Region#collapsible expanding and collapsing} of regions.</p>
5544  * <p>This class is intended to be extended or created via the <tt>layout:'border'</tt>
5545  * {@link Ext.Container#layout} config, and should generally not need to be created directly
5546  * via the new keyword.</p>
5547  * <p>BorderLayout does not have any direct config options (other than inherited ones).
5548  * All configuration options available for customizing the BorderLayout are at the
5549  * {@link Ext.layout.BorderLayout.Region} and {@link Ext.layout.BorderLayout.SplitRegion}
5550  * levels.</p>
5551  * <p>Example usage:</p>
5552  * <pre><code>
5553 var myBorderPanel = new Ext.Panel({
5554     {@link Ext.Component#renderTo renderTo}: document.body,
5555     {@link Ext.BoxComponent#width width}: 700,
5556     {@link Ext.BoxComponent#height height}: 500,
5557     {@link Ext.Panel#title title}: 'Border Layout',
5558     {@link Ext.Container#layout layout}: 'border',
5559     {@link Ext.Container#items items}: [{
5560         {@link Ext.Panel#title title}: 'South Region is resizable',
5561         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south',     // position for region
5562         {@link Ext.BoxComponent#height height}: 100,
5563         {@link Ext.layout.BorderLayout.Region#split split}: true,         // enable resizing
5564         {@link Ext.SplitBar#minSize minSize}: 75,         // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50}
5565         {@link Ext.SplitBar#maxSize maxSize}: 150,
5566         {@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5'
5567     },{
5568         // xtype: 'panel' implied by default
5569         {@link Ext.Panel#title title}: 'West Region is collapsible',
5570         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}:'west',
5571         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 0 0 5',
5572         {@link Ext.BoxComponent#width width}: 200,
5573         {@link Ext.layout.BorderLayout.Region#collapsible collapsible}: true,   // make collapsible
5574         {@link Ext.layout.BorderLayout.Region#cmargins cmargins}: '5 5 0 5', // adjust top margin when collapsed
5575         {@link Ext.Component#id id}: 'west-region-container',
5576         {@link Ext.Container#layout layout}: 'fit',
5577         {@link Ext.Panel#unstyled unstyled}: true
5578     },{
5579         {@link Ext.Panel#title title}: 'Center Region',
5580         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'center',     // center region is required, no width/height specified
5581         {@link Ext.Component#xtype xtype}: 'container',
5582         {@link Ext.Container#layout layout}: 'fit',
5583         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 5 0 0'
5584     }]
5585 });
5586 </code></pre>
5587  * <p><b><u>Notes</u></b>:</p><div class="mdetail-params"><ul>
5588  * <li>Any container using the BorderLayout <b>must</b> have a child item with <tt>region:'center'</tt>.
5589  * The child item in the center region will always be resized to fill the remaining space not used by
5590  * the other regions in the layout.</li>
5591  * <li>Any child items with a region of <tt>west</tt> or <tt>east</tt> must have <tt>width</tt> defined
5592  * (an integer representing the number of pixels that the region should take up).</li>
5593  * <li>Any child items with a region of <tt>north</tt> or <tt>south</tt> must have <tt>height</tt> defined.</li>
5594  * <li>The regions of a BorderLayout are <b>fixed at render time</b> and thereafter, its child Components may not be removed or added</b>.  To add/remove
5595  * Components within a BorderLayout, have them wrapped by an additional Container which is directly
5596  * managed by the BorderLayout.  If the region is to be collapsible, the Container used directly
5597  * by the BorderLayout manager should be a Panel.  In the following example a Container (an Ext.Panel)
5598  * is added to the west region:
5599  * <div style="margin-left:16px"><pre><code>
5600 wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container');
5601 wrc.{@link Ext.Panel#removeAll removeAll}();
5602 wrc.{@link Ext.Container#add add}({
5603     title: 'Added Panel',
5604     html: 'Some content'
5605 });
5606 wrc.{@link Ext.Container#doLayout doLayout}();
5607  * </code></pre></div>
5608  * </li>
5609  * <li> To reference a {@link Ext.layout.BorderLayout.Region Region}:
5610  * <div style="margin-left:16px"><pre><code>
5611 wr = myBorderPanel.layout.west;
5612  * </code></pre></div>
5613  * </li>
5614  * </ul></div>
5615  */
5616 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
5617     // private
5618     monitorResize:true,
5619     // private
5620     rendered : false,
5621
5622     targetCls: 'x-border-layout-ct',
5623
5624     // private
5625     onLayout : function(ct, target){
5626         var collapsed;
5627         if(!this.rendered){
5628             var items = ct.items.items;
5629             collapsed = [];
5630             for(var i = 0, len = items.length; i < len; i++) {
5631                 var c = items[i];
5632                 var pos = c.region;
5633                 if(c.collapsed){
5634                     collapsed.push(c);
5635                 }
5636                 c.collapsed = false;
5637                 if(!c.rendered){
5638                     c.render(target, i);
5639                     c.getPositionEl().addClass('x-border-panel');
5640                 }
5641                 this[pos] = pos != 'center' && c.split ?
5642                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
5643                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
5644                 this[pos].render(target, c);
5645             }
5646             this.rendered = true;
5647         }
5648
5649         var size = target.getViewSize(false);
5650         if(size.width < 20 || size.height < 20){ // display none?
5651             if(collapsed){
5652                 this.restoreCollapsed = collapsed;
5653             }
5654             return;
5655         }else if(this.restoreCollapsed){
5656             collapsed = this.restoreCollapsed;
5657             delete this.restoreCollapsed;
5658         }
5659
5660         var w = size.width, h = size.height;
5661         var centerW = w, centerH = h, centerY = 0, centerX = 0;
5662
5663         var n = this.north, s = this.south, west = this.west, e = this.east, c = this.center;
5664         if(!c && Ext.layout.BorderLayout.WARN !== false){
5665             throw 'No center region defined in BorderLayout ' + ct.id;
5666         }
5667
5668         if(n && n.isVisible()){
5669             var b = n.getSize();
5670             var m = n.getMargins();
5671             b.width = w - (m.left+m.right);
5672             b.x = m.left;
5673             b.y = m.top;
5674             centerY = b.height + b.y + m.bottom;
5675             centerH -= centerY;
5676             n.applyLayout(b);
5677         }
5678         if(s && s.isVisible()){
5679             var b = s.getSize();
5680             var m = s.getMargins();
5681             b.width = w - (m.left+m.right);
5682             b.x = m.left;
5683             var totalHeight = (b.height + m.top + m.bottom);
5684             b.y = h - totalHeight + m.top;
5685             centerH -= totalHeight;
5686             s.applyLayout(b);
5687         }
5688         if(west && west.isVisible()){
5689             var b = west.getSize();
5690             var m = west.getMargins();
5691             b.height = centerH - (m.top+m.bottom);
5692             b.x = m.left;
5693             b.y = centerY + m.top;
5694             var totalWidth = (b.width + m.left + m.right);
5695             centerX += totalWidth;
5696             centerW -= totalWidth;
5697             west.applyLayout(b);
5698         }
5699         if(e && e.isVisible()){
5700             var b = e.getSize();
5701             var m = e.getMargins();
5702             b.height = centerH - (m.top+m.bottom);
5703             var totalWidth = (b.width + m.left + m.right);
5704             b.x = w - totalWidth + m.left;
5705             b.y = centerY + m.top;
5706             centerW -= totalWidth;
5707             e.applyLayout(b);
5708         }
5709         if(c){
5710             var m = c.getMargins();
5711             var centerBox = {
5712                 x: centerX + m.left,
5713                 y: centerY + m.top,
5714                 width: centerW - (m.left+m.right),
5715                 height: centerH - (m.top+m.bottom)
5716             };
5717             c.applyLayout(centerBox);
5718         }
5719         if(collapsed){
5720             for(var i = 0, len = collapsed.length; i < len; i++){
5721                 collapsed[i].collapse(false);
5722             }
5723         }
5724         if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue
5725             target.repaint();
5726         }
5727     },
5728
5729     destroy: function() {
5730         var r = ['north', 'south', 'east', 'west'];
5731         for (var i = 0; i < r.length; i++) {
5732             var region = this[r[i]];
5733             if(region){
5734                 if(region.destroy){
5735                     region.destroy();
5736                 }else if (region.split){
5737                     region.split.destroy(true);
5738                 }
5739             }
5740         }
5741         Ext.layout.BorderLayout.superclass.destroy.call(this);
5742     }
5743
5744     /**
5745      * @property activeItem
5746      * @hide
5747      */
5748 });
5749
5750 /**
5751  * @class Ext.layout.BorderLayout.Region
5752  * <p>This is a region of a {@link Ext.layout.BorderLayout BorderLayout} that acts as a subcontainer
5753  * within the layout.  Each region has its own {@link Ext.layout.ContainerLayout layout} that is
5754  * independent of other regions and the containing BorderLayout, and can be any of the
5755  * {@link Ext.layout.ContainerLayout valid Ext layout types}.</p>
5756  * <p>Region size is managed automatically and cannot be changed by the user -- for
5757  * {@link #split resizable regions}, see {@link Ext.layout.BorderLayout.SplitRegion}.</p>
5758  * @constructor
5759  * Create a new Region.
5760  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
5761  * @param {Object} config The configuration options
5762  * @param {String} position The region position.  Valid values are: <tt>north</tt>, <tt>south</tt>,
5763  * <tt>east</tt>, <tt>west</tt> and <tt>center</tt>.  Every {@link Ext.layout.BorderLayout BorderLayout}
5764  * <b>must have a center region</b> for the primary content -- all other regions are optional.
5765  */
5766 Ext.layout.BorderLayout.Region = function(layout, config, pos){
5767     Ext.apply(this, config);
5768     this.layout = layout;
5769     this.position = pos;
5770     this.state = {};
5771     if(typeof this.margins == 'string'){
5772         this.margins = this.layout.parseMargins(this.margins);
5773     }
5774     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
5775     if(this.collapsible){
5776         if(typeof this.cmargins == 'string'){
5777             this.cmargins = this.layout.parseMargins(this.cmargins);
5778         }
5779         if(this.collapseMode == 'mini' && !this.cmargins){
5780             this.cmargins = {left:0,top:0,right:0,bottom:0};
5781         }else{
5782             this.cmargins = Ext.applyIf(this.cmargins || {},
5783                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
5784         }
5785     }
5786 };
5787
5788 Ext.layout.BorderLayout.Region.prototype = {
5789     /**
5790      * @cfg {Boolean} animFloat
5791      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
5792      * panel that will close again once the user mouses out of that panel (or clicks out if
5793      * <tt>{@link #autoHide} = false</tt>).  Setting <tt>{@link #animFloat} = false</tt> will
5794      * prevent the open and close of these floated panels from being animated (defaults to <tt>true</tt>).
5795      */
5796     /**
5797      * @cfg {Boolean} autoHide
5798      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
5799      * panel.  If <tt>autoHide = true</tt>, the panel will automatically hide after the user mouses
5800      * out of the panel.  If <tt>autoHide = false</tt>, the panel will continue to display until the
5801      * user clicks outside of the panel (defaults to <tt>true</tt>).
5802      */
5803     /**
5804      * @cfg {String} collapseMode
5805      * <tt>collapseMode</tt> supports two configuration values:<div class="mdetail-params"><ul>
5806      * <li><b><tt>undefined</tt></b> (default)<div class="sub-desc">By default, {@link #collapsible}
5807      * regions are collapsed by clicking the expand/collapse tool button that renders into the region's
5808      * title bar.</div></li>
5809      * <li><b><tt>'mini'</tt></b><div class="sub-desc">Optionally, when <tt>collapseMode</tt> is set to
5810      * <tt>'mini'</tt> the region's split bar will also display a small collapse button in the center of
5811      * the bar. In <tt>'mini'</tt> mode the region will collapse to a thinner bar than in normal mode.
5812      * </div></li>
5813      * </ul></div></p>
5814      * <p><b>Note</b>: if a collapsible region does not have a title bar, then set <tt>collapseMode =
5815      * 'mini'</tt> and <tt>{@link #split} = true</tt> in order for the region to be {@link #collapsible}
5816      * by the user as the expand/collapse tool button (that would go in the title bar) will not be rendered.</p>
5817      * <p>See also <tt>{@link #cmargins}</tt>.</p>
5818      */
5819     /**
5820      * @cfg {Object} margins
5821      * An object containing margins to apply to the region when in the expanded state in the
5822      * format:<pre><code>
5823 {
5824     top: (top margin),
5825     right: (right margin),
5826     bottom: (bottom margin),
5827     left: (left margin)
5828 }</code></pre>
5829      * <p>May also be a string containing space-separated, numeric margin values. The order of the
5830      * sides associated with each value matches the way CSS processes margin values:</p>
5831      * <p><div class="mdetail-params"><ul>
5832      * <li>If there is only one value, it applies to all sides.</li>
5833      * <li>If there are two values, the top and bottom borders are set to the first value and the
5834      * right and left are set to the second.</li>
5835      * <li>If there are three values, the top is set to the first value, the left and right are set
5836      * to the second, and the bottom is set to the third.</li>
5837      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
5838      * </ul></div></p>
5839      * <p>Defaults to:</p><pre><code>
5840      * {top:0, right:0, bottom:0, left:0}
5841      * </code></pre>
5842      */
5843     /**
5844      * @cfg {Object} cmargins
5845      * An object containing margins to apply to the region when in the collapsed state in the
5846      * format:<pre><code>
5847 {
5848     top: (top margin),
5849     right: (right margin),
5850     bottom: (bottom margin),
5851     left: (left margin)
5852 }</code></pre>
5853      * <p>May also be a string containing space-separated, numeric margin values. The order of the
5854      * sides associated with each value matches the way CSS processes margin values.</p>
5855      * <p><ul>
5856      * <li>If there is only one value, it applies to all sides.</li>
5857      * <li>If there are two values, the top and bottom borders are set to the first value and the
5858      * right and left are set to the second.</li>
5859      * <li>If there are three values, the top is set to the first value, the left and right are set
5860      * to the second, and the bottom is set to the third.</li>
5861      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
5862      * </ul></p>
5863      */
5864     /**
5865      * @cfg {Boolean} collapsible
5866      * <p><tt>true</tt> to allow the user to collapse this region (defaults to <tt>false</tt>).  If
5867      * <tt>true</tt>, an expand/collapse tool button will automatically be rendered into the title
5868      * bar of the region, otherwise the button will not be shown.</p>
5869      * <p><b>Note</b>: that a title bar is required to display the collapse/expand toggle button -- if
5870      * no <tt>title</tt> is specified for the region's panel, the region will only be collapsible if
5871      * <tt>{@link #collapseMode} = 'mini'</tt> and <tt>{@link #split} = true</tt>.
5872      */
5873     collapsible : false,
5874     /**
5875      * @cfg {Boolean} split
5876      * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and
5877      * display a 5px wide {@link Ext.SplitBar} between this region and its neighbor, allowing the user to
5878      * resize the regions dynamically.  Defaults to <tt>false</tt> creating a
5879      * {@link Ext.layout.BorderLayout.Region Region}.</p><br>
5880      * <p><b>Notes</b>:</p><div class="mdetail-params"><ul>
5881      * <li>this configuration option is ignored if <tt>region='center'</tt></li>
5882      * <li>when <tt>split == true</tt>, it is common to specify a
5883      * <tt>{@link Ext.SplitBar#minSize minSize}</tt> and <tt>{@link Ext.SplitBar#maxSize maxSize}</tt>
5884      * for the {@link Ext.BoxComponent BoxComponent} representing the region. These are not native
5885      * configs of {@link Ext.BoxComponent BoxComponent}, and are used only by this class.</li>
5886      * <li>if <tt>{@link #collapseMode} = 'mini'</tt> requires <tt>split = true</tt> to reserve space
5887      * for the collapse tool</tt></li>
5888      * </ul></div>
5889      */
5890     split:false,
5891     /**
5892      * @cfg {Boolean} floatable
5893      * <tt>true</tt> to allow clicking a collapsed region's bar to display the region's panel floated
5894      * above the layout, <tt>false</tt> to force the user to fully expand a collapsed region by
5895      * clicking the expand button to see it again (defaults to <tt>true</tt>).
5896      */
5897     floatable: true,
5898     /**
5899      * @cfg {Number} minWidth
5900      * <p>The minimum allowable width in pixels for this region (defaults to <tt>50</tt>).
5901      * <tt>maxWidth</tt> may also be specified.</p><br>
5902      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
5903      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
5904      * <tt>minWidth</tt> / <tt>maxWidth</tt>.</p>
5905      */
5906     minWidth:50,
5907     /**
5908      * @cfg {Number} minHeight
5909      * The minimum allowable height in pixels for this region (defaults to <tt>50</tt>)
5910      * <tt>maxHeight</tt> may also be specified.</p><br>
5911      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
5912      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
5913      * <tt>minHeight</tt> / <tt>maxHeight</tt>.</p>
5914      */
5915     minHeight:50,
5916
5917     // private
5918     defaultMargins : {left:0,top:0,right:0,bottom:0},
5919     // private
5920     defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
5921     // private
5922     defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
5923     floatingZIndex: 100,
5924
5925     /**
5926      * True if this region is collapsed. Read-only.
5927      * @type Boolean
5928      * @property
5929      */
5930     isCollapsed : false,
5931
5932     /**
5933      * This region's panel.  Read-only.
5934      * @type Ext.Panel
5935      * @property panel
5936      */
5937     /**
5938      * This region's layout.  Read-only.
5939      * @type Layout
5940      * @property layout
5941      */
5942     /**
5943      * This region's layout position (north, south, east, west or center).  Read-only.
5944      * @type String
5945      * @property position
5946      */
5947
5948     // private
5949     render : function(ct, p){
5950         this.panel = p;
5951         p.el.enableDisplayMode();
5952         this.targetEl = ct;
5953         this.el = p.el;
5954
5955         var gs = p.getState, ps = this.position;
5956         p.getState = function(){
5957             return Ext.apply(gs.call(p) || {}, this.state);
5958         }.createDelegate(this);
5959
5960         if(ps != 'center'){
5961             p.allowQueuedExpand = false;
5962             p.on({
5963                 beforecollapse: this.beforeCollapse,
5964                 collapse: this.onCollapse,
5965                 beforeexpand: this.beforeExpand,
5966                 expand: this.onExpand,
5967                 hide: this.onHide,
5968                 show: this.onShow,
5969                 scope: this
5970             });
5971             if(this.collapsible || this.floatable){
5972                 p.collapseEl = 'el';
5973                 p.slideAnchor = this.getSlideAnchor();
5974             }
5975             if(p.tools && p.tools.toggle){
5976                 p.tools.toggle.addClass('x-tool-collapse-'+ps);
5977                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
5978             }
5979         }
5980     },
5981
5982     // private
5983     getCollapsedEl : function(){
5984         if(!this.collapsedEl){
5985             if(!this.toolTemplate){
5986                 var tt = new Ext.Template(
5987                      '<div class="x-tool x-tool-{id}">&#160;</div>'
5988                 );
5989                 tt.disableFormats = true;
5990                 tt.compile();
5991                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
5992             }
5993             this.collapsedEl = this.targetEl.createChild({
5994                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
5995                 id: this.panel.id + '-xcollapsed'
5996             });
5997             this.collapsedEl.enableDisplayMode('block');
5998
5999             if(this.collapseMode == 'mini'){
6000                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
6001                 this.miniCollapsedEl = this.collapsedEl.createChild({
6002                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
6003                 });
6004                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
6005                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
6006                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
6007             }else {
6008                 if(this.collapsible !== false && !this.hideCollapseTool) {
6009                     var t = this.toolTemplate.append(
6010                             this.collapsedEl.dom,
6011                             {id:'expand-'+this.position}, true);
6012                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
6013                     t.on('click', this.onExpandClick, this, {stopEvent:true});
6014                 }
6015                 if(this.floatable !== false || this.titleCollapse){
6016                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
6017                    this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
6018                 }
6019             }
6020         }
6021         return this.collapsedEl;
6022     },
6023
6024     // private
6025     onExpandClick : function(e){
6026         if(this.isSlid){
6027             this.panel.expand(false);
6028         }else{
6029             this.panel.expand();
6030         }
6031     },
6032
6033     // private
6034     onCollapseClick : function(e){
6035         this.panel.collapse();
6036     },
6037
6038     // private
6039     beforeCollapse : function(p, animate){
6040         this.lastAnim = animate;
6041         if(this.splitEl){
6042             this.splitEl.hide();
6043         }
6044         this.getCollapsedEl().show();
6045         var el = this.panel.getEl();
6046         this.originalZIndex = el.getStyle('z-index');
6047         el.setStyle('z-index', 100);
6048         this.isCollapsed = true;
6049         this.layout.layout();
6050     },
6051
6052     // private
6053     onCollapse : function(animate){
6054         this.panel.el.setStyle('z-index', 1);
6055         if(this.lastAnim === false || this.panel.animCollapse === false){
6056             this.getCollapsedEl().dom.style.visibility = 'visible';
6057         }else{
6058             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
6059         }
6060         this.state.collapsed = true;
6061         this.panel.saveState();
6062     },
6063
6064     // private
6065     beforeExpand : function(animate){
6066         if(this.isSlid){
6067             this.afterSlideIn();
6068         }
6069         var c = this.getCollapsedEl();
6070         this.el.show();
6071         if(this.position == 'east' || this.position == 'west'){
6072             this.panel.setSize(undefined, c.getHeight());
6073         }else{
6074             this.panel.setSize(c.getWidth(), undefined);
6075         }
6076         c.hide();
6077         c.dom.style.visibility = 'hidden';
6078         this.panel.el.setStyle('z-index', this.floatingZIndex);
6079     },
6080
6081     // private
6082     onExpand : function(){
6083         this.isCollapsed = false;
6084         if(this.splitEl){
6085             this.splitEl.show();
6086         }
6087         this.layout.layout();
6088         this.panel.el.setStyle('z-index', this.originalZIndex);
6089         this.state.collapsed = false;
6090         this.panel.saveState();
6091     },
6092
6093     // private
6094     collapseClick : function(e){
6095         if(this.isSlid){
6096            e.stopPropagation();
6097            this.slideIn();
6098         }else{
6099            e.stopPropagation();
6100            this.slideOut();
6101         }
6102     },
6103
6104     // private
6105     onHide : function(){
6106         if(this.isCollapsed){
6107             this.getCollapsedEl().hide();
6108         }else if(this.splitEl){
6109             this.splitEl.hide();
6110         }
6111     },
6112
6113     // private
6114     onShow : function(){
6115         if(this.isCollapsed){
6116             this.getCollapsedEl().show();
6117         }else if(this.splitEl){
6118             this.splitEl.show();
6119         }
6120     },
6121
6122     /**
6123      * True if this region is currently visible, else false.
6124      * @return {Boolean}
6125      */
6126     isVisible : function(){
6127         return !this.panel.hidden;
6128     },
6129
6130     /**
6131      * Returns the current margins for this region.  If the region is collapsed, the
6132      * {@link #cmargins} (collapsed margins) value will be returned, otherwise the
6133      * {@link #margins} value will be returned.
6134      * @return {Object} An object containing the element's margins: <tt>{left: (left
6135      * margin), top: (top margin), right: (right margin), bottom: (bottom margin)}</tt>
6136      */
6137     getMargins : function(){
6138         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
6139     },
6140
6141     /**
6142      * Returns the current size of this region.  If the region is collapsed, the size of the
6143      * collapsedEl will be returned, otherwise the size of the region's panel will be returned.
6144      * @return {Object} An object containing the element's size: <tt>{width: (element width),
6145      * height: (element height)}</tt>
6146      */
6147     getSize : function(){
6148         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
6149     },
6150
6151     /**
6152      * Sets the specified panel as the container element for this region.
6153      * @param {Ext.Panel} panel The new panel
6154      */
6155     setPanel : function(panel){
6156         this.panel = panel;
6157     },
6158
6159     /**
6160      * Returns the minimum allowable width for this region.
6161      * @return {Number} The minimum width
6162      */
6163     getMinWidth: function(){
6164         return this.minWidth;
6165     },
6166
6167     /**
6168      * Returns the minimum allowable height for this region.
6169      * @return {Number} The minimum height
6170      */
6171     getMinHeight: function(){
6172         return this.minHeight;
6173     },
6174
6175     // private
6176     applyLayoutCollapsed : function(box){
6177         var ce = this.getCollapsedEl();
6178         ce.setLeftTop(box.x, box.y);
6179         ce.setSize(box.width, box.height);
6180     },
6181
6182     // private
6183     applyLayout : function(box){
6184         if(this.isCollapsed){
6185             this.applyLayoutCollapsed(box);
6186         }else{
6187             this.panel.setPosition(box.x, box.y);
6188             this.panel.setSize(box.width, box.height);
6189         }
6190     },
6191
6192     // private
6193     beforeSlide: function(){
6194         this.panel.beforeEffect();
6195     },
6196
6197     // private
6198     afterSlide : function(){
6199         this.panel.afterEffect();
6200     },
6201
6202     // private
6203     initAutoHide : function(){
6204         if(this.autoHide !== false){
6205             if(!this.autoHideHd){
6206                 var st = new Ext.util.DelayedTask(this.slideIn, this);
6207                 this.autoHideHd = {
6208                     "mouseout": function(e){
6209                         if(!e.within(this.el, true)){
6210                             st.delay(500);
6211                         }
6212                     },
6213                     "mouseover" : function(e){
6214                         st.cancel();
6215                     },
6216                     scope : this
6217                 };
6218             }
6219             this.el.on(this.autoHideHd);
6220             this.collapsedEl.on(this.autoHideHd);
6221         }
6222     },
6223
6224     // private
6225     clearAutoHide : function(){
6226         if(this.autoHide !== false){
6227             this.el.un("mouseout", this.autoHideHd.mouseout);
6228             this.el.un("mouseover", this.autoHideHd.mouseover);
6229             this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
6230             this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
6231         }
6232     },
6233
6234     // private
6235     clearMonitor : function(){
6236         Ext.getDoc().un("click", this.slideInIf, this);
6237     },
6238
6239     /**
6240      * If this Region is {@link #floatable}, this method slides this Region into full visibility <i>over the top
6241      * of the center Region</i> where it floats until either {@link #slideIn} is called, or other regions of the layout
6242      * are clicked, or the mouse exits the Region.
6243      */
6244     slideOut : function(){
6245         if(this.isSlid || this.el.hasActiveFx()){
6246             return;
6247         }
6248         this.isSlid = true;
6249         var ts = this.panel.tools;
6250         if(ts && ts.toggle){
6251             ts.toggle.hide();
6252         }
6253         this.el.show();
6254         if(this.position == 'east' || this.position == 'west'){
6255             this.panel.setSize(undefined, this.collapsedEl.getHeight());
6256         }else{
6257             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
6258         }
6259         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
6260         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
6261         this.el.setStyle("z-index", this.floatingZIndex+2);
6262         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
6263         if(this.animFloat !== false){
6264             this.beforeSlide();
6265             this.el.slideIn(this.getSlideAnchor(), {
6266                 callback: function(){
6267                     this.afterSlide();
6268                     this.initAutoHide();
6269                     Ext.getDoc().on("click", this.slideInIf, this);
6270                 },
6271                 scope: this,
6272                 block: true
6273             });
6274         }else{
6275             this.initAutoHide();
6276              Ext.getDoc().on("click", this.slideInIf, this);
6277         }
6278     },
6279
6280     // private
6281     afterSlideIn : function(){
6282         this.clearAutoHide();
6283         this.isSlid = false;
6284         this.clearMonitor();
6285         this.el.setStyle("z-index", "");
6286         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
6287         this.el.dom.style.left = this.restoreLT[0];
6288         this.el.dom.style.top = this.restoreLT[1];
6289
6290         var ts = this.panel.tools;
6291         if(ts && ts.toggle){
6292             ts.toggle.show();
6293         }
6294     },
6295
6296     /**
6297      * If this Region is {@link #floatable}, and this Region has been slid into floating visibility, then this method slides
6298      * this region back into its collapsed state.
6299      */
6300     slideIn : function(cb){
6301         if(!this.isSlid || this.el.hasActiveFx()){
6302             Ext.callback(cb);
6303             return;
6304         }
6305         this.isSlid = false;
6306         if(this.animFloat !== false){
6307             this.beforeSlide();
6308             this.el.slideOut(this.getSlideAnchor(), {
6309                 callback: function(){
6310                     this.el.hide();
6311                     this.afterSlide();
6312                     this.afterSlideIn();
6313                     Ext.callback(cb);
6314                 },
6315                 scope: this,
6316                 block: true
6317             });
6318         }else{
6319             this.el.hide();
6320             this.afterSlideIn();
6321         }
6322     },
6323
6324     // private
6325     slideInIf : function(e){
6326         if(!e.within(this.el)){
6327             this.slideIn();
6328         }
6329     },
6330
6331     // private
6332     anchors : {
6333         "west" : "left",
6334         "east" : "right",
6335         "north" : "top",
6336         "south" : "bottom"
6337     },
6338
6339     // private
6340     sanchors : {
6341         "west" : "l",
6342         "east" : "r",
6343         "north" : "t",
6344         "south" : "b"
6345     },
6346
6347     // private
6348     canchors : {
6349         "west" : "tl-tr",
6350         "east" : "tr-tl",
6351         "north" : "tl-bl",
6352         "south" : "bl-tl"
6353     },
6354
6355     // private
6356     getAnchor : function(){
6357         return this.anchors[this.position];
6358     },
6359
6360     // private
6361     getCollapseAnchor : function(){
6362         return this.canchors[this.position];
6363     },
6364
6365     // private
6366     getSlideAnchor : function(){
6367         return this.sanchors[this.position];
6368     },
6369
6370     // private
6371     getAlignAdj : function(){
6372         var cm = this.cmargins;
6373         switch(this.position){
6374             case "west":
6375                 return [0, 0];
6376             break;
6377             case "east":
6378                 return [0, 0];
6379             break;
6380             case "north":
6381                 return [0, 0];
6382             break;
6383             case "south":
6384                 return [0, 0];
6385             break;
6386         }
6387     },
6388
6389     // private
6390     getExpandAdj : function(){
6391         var c = this.collapsedEl, cm = this.cmargins;
6392         switch(this.position){
6393             case "west":
6394                 return [-(cm.right+c.getWidth()+cm.left), 0];
6395             break;
6396             case "east":
6397                 return [cm.right+c.getWidth()+cm.left, 0];
6398             break;
6399             case "north":
6400                 return [0, -(cm.top+cm.bottom+c.getHeight())];
6401             break;
6402             case "south":
6403                 return [0, cm.top+cm.bottom+c.getHeight()];
6404             break;
6405         }
6406     },
6407
6408     destroy : function(){
6409         Ext.destroy(this.miniCollapsedEl, this.collapsedEl);
6410     }
6411 };
6412
6413 /**
6414  * @class Ext.layout.BorderLayout.SplitRegion
6415  * @extends Ext.layout.BorderLayout.Region
6416  * <p>This is a specialized type of {@link Ext.layout.BorderLayout.Region BorderLayout region} that
6417  * has a built-in {@link Ext.SplitBar} for user resizing of regions.  The movement of the split bar
6418  * is configurable to move either {@link #tickSize smooth or incrementally}.</p>
6419  * @constructor
6420  * Create a new SplitRegion.
6421  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
6422  * @param {Object} config The configuration options
6423  * @param {String} position The region position.  Valid values are: north, south, east, west and center.  Every
6424  * BorderLayout must have a center region for the primary content -- all other regions are optional.
6425  */
6426 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
6427     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
6428     // prevent switch
6429     this.applyLayout = this.applyFns[pos];
6430 };
6431
6432 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
6433     /**
6434      * @cfg {Number} tickSize
6435      * The increment, in pixels by which to move this Region's {@link Ext.SplitBar SplitBar}.
6436      * By default, the {@link Ext.SplitBar SplitBar} moves smoothly.
6437      */
6438     /**
6439      * @cfg {String} splitTip
6440      * The tooltip to display when the user hovers over a
6441      * {@link Ext.layout.BorderLayout.Region#collapsible non-collapsible} region's split bar
6442      * (defaults to <tt>"Drag to resize."</tt>).  Only applies if
6443      * <tt>{@link #useSplitTips} = true</tt>.
6444      */
6445     splitTip : "Drag to resize.",
6446     /**
6447      * @cfg {String} collapsibleSplitTip
6448      * The tooltip to display when the user hovers over a
6449      * {@link Ext.layout.BorderLayout.Region#collapsible collapsible} region's split bar
6450      * (defaults to "Drag to resize. Double click to hide."). Only applies if
6451      * <tt>{@link #useSplitTips} = true</tt>.
6452      */
6453     collapsibleSplitTip : "Drag to resize. Double click to hide.",
6454     /**
6455      * @cfg {Boolean} useSplitTips
6456      * <tt>true</tt> to display a tooltip when the user hovers over a region's split bar
6457      * (defaults to <tt>false</tt>).  The tooltip text will be the value of either
6458      * <tt>{@link #splitTip}</tt> or <tt>{@link #collapsibleSplitTip}</tt> as appropriate.
6459      */
6460     useSplitTips : false,
6461
6462     // private
6463     splitSettings : {
6464         north : {
6465             orientation: Ext.SplitBar.VERTICAL,
6466             placement: Ext.SplitBar.TOP,
6467             maxFn : 'getVMaxSize',
6468             minProp: 'minHeight',
6469             maxProp: 'maxHeight'
6470         },
6471         south : {
6472             orientation: Ext.SplitBar.VERTICAL,
6473             placement: Ext.SplitBar.BOTTOM,
6474             maxFn : 'getVMaxSize',
6475             minProp: 'minHeight',
6476             maxProp: 'maxHeight'
6477         },
6478         east : {
6479             orientation: Ext.SplitBar.HORIZONTAL,
6480             placement: Ext.SplitBar.RIGHT,
6481             maxFn : 'getHMaxSize',
6482             minProp: 'minWidth',
6483             maxProp: 'maxWidth'
6484         },
6485         west : {
6486             orientation: Ext.SplitBar.HORIZONTAL,
6487             placement: Ext.SplitBar.LEFT,
6488             maxFn : 'getHMaxSize',
6489             minProp: 'minWidth',
6490             maxProp: 'maxWidth'
6491         }
6492     },
6493
6494     // private
6495     applyFns : {
6496         west : function(box){
6497             if(this.isCollapsed){
6498                 return this.applyLayoutCollapsed(box);
6499             }
6500             var sd = this.splitEl.dom, s = sd.style;
6501             this.panel.setPosition(box.x, box.y);
6502             var sw = sd.offsetWidth;
6503             s.left = (box.x+box.width-sw)+'px';
6504             s.top = (box.y)+'px';
6505             s.height = Math.max(0, box.height)+'px';
6506             this.panel.setSize(box.width-sw, box.height);
6507         },
6508         east : function(box){
6509             if(this.isCollapsed){
6510                 return this.applyLayoutCollapsed(box);
6511             }
6512             var sd = this.splitEl.dom, s = sd.style;
6513             var sw = sd.offsetWidth;
6514             this.panel.setPosition(box.x+sw, box.y);
6515             s.left = (box.x)+'px';
6516             s.top = (box.y)+'px';
6517             s.height = Math.max(0, box.height)+'px';
6518             this.panel.setSize(box.width-sw, box.height);
6519         },
6520         north : function(box){
6521             if(this.isCollapsed){
6522                 return this.applyLayoutCollapsed(box);
6523             }
6524             var sd = this.splitEl.dom, s = sd.style;
6525             var sh = sd.offsetHeight;
6526             this.panel.setPosition(box.x, box.y);
6527             s.left = (box.x)+'px';
6528             s.top = (box.y+box.height-sh)+'px';
6529             s.width = Math.max(0, box.width)+'px';
6530             this.panel.setSize(box.width, box.height-sh);
6531         },
6532         south : function(box){
6533             if(this.isCollapsed){
6534                 return this.applyLayoutCollapsed(box);
6535             }
6536             var sd = this.splitEl.dom, s = sd.style;
6537             var sh = sd.offsetHeight;
6538             this.panel.setPosition(box.x, box.y+sh);
6539             s.left = (box.x)+'px';
6540             s.top = (box.y)+'px';
6541             s.width = Math.max(0, box.width)+'px';
6542             this.panel.setSize(box.width, box.height-sh);
6543         }
6544     },
6545
6546     // private
6547     render : function(ct, p){
6548         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
6549
6550         var ps = this.position;
6551
6552         this.splitEl = ct.createChild({
6553             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
6554             id: this.panel.id + '-xsplit'
6555         });
6556
6557         if(this.collapseMode == 'mini'){
6558             this.miniSplitEl = this.splitEl.createChild({
6559                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
6560             });
6561             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
6562             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
6563         }
6564
6565         var s = this.splitSettings[ps];
6566
6567         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
6568         this.split.tickSize = this.tickSize;
6569         this.split.placement = s.placement;
6570         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
6571         this.split.minSize = this.minSize || this[s.minProp];
6572         this.split.on("beforeapply", this.onSplitMove, this);
6573         this.split.useShim = this.useShim === true;
6574         this.maxSize = this.maxSize || this[s.maxProp];
6575
6576         if(p.hidden){
6577             this.splitEl.hide();
6578         }
6579
6580         if(this.useSplitTips){
6581             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
6582         }
6583         if(this.collapsible){
6584             this.splitEl.on("dblclick", this.onCollapseClick,  this);
6585         }
6586     },
6587
6588     //docs inherit from superclass
6589     getSize : function(){
6590         if(this.isCollapsed){
6591             return this.collapsedEl.getSize();
6592         }
6593         var s = this.panel.getSize();
6594         if(this.position == 'north' || this.position == 'south'){
6595             s.height += this.splitEl.dom.offsetHeight;
6596         }else{
6597             s.width += this.splitEl.dom.offsetWidth;
6598         }
6599         return s;
6600     },
6601
6602     // private
6603     getHMaxSize : function(){
6604          var cmax = this.maxSize || 10000;
6605          var center = this.layout.center;
6606          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
6607     },
6608
6609     // private
6610     getVMaxSize : function(){
6611         var cmax = this.maxSize || 10000;
6612         var center = this.layout.center;
6613         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
6614     },
6615
6616     // private
6617     onSplitMove : function(split, newSize){
6618         var s = this.panel.getSize();
6619         this.lastSplitSize = newSize;
6620         if(this.position == 'north' || this.position == 'south'){
6621             this.panel.setSize(s.width, newSize);
6622             this.state.height = newSize;
6623         }else{
6624             this.panel.setSize(newSize, s.height);
6625             this.state.width = newSize;
6626         }
6627         this.layout.layout();
6628         this.panel.saveState();
6629         return false;
6630     },
6631
6632     /**
6633      * Returns a reference to the split bar in use by this region.
6634      * @return {Ext.SplitBar} The split bar
6635      */
6636     getSplitBar : function(){
6637         return this.split;
6638     },
6639
6640     // inherit docs
6641     destroy : function() {
6642         Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
6643         Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
6644     }
6645 });
6646
6647 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;/**
6648  * @class Ext.layout.FormLayout
6649  * @extends Ext.layout.AnchorLayout
6650  * <p>This layout manager is specifically designed for rendering and managing child Components of
6651  * {@link Ext.form.FormPanel forms}. It is responsible for rendering the labels of
6652  * {@link Ext.form.Field Field}s.</p>
6653  *
6654  * <p>This layout manager is used when a Container is configured with the <tt>layout:'form'</tt>
6655  * {@link Ext.Container#layout layout} config option, and should generally not need to be created directly
6656  * via the new keyword. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
6657  *
6658  * <p>In an application, it will usually be preferrable to use a {@link Ext.form.FormPanel FormPanel}
6659  * (which is configured with FormLayout as its layout class by default) since it also provides built-in
6660  * functionality for {@link Ext.form.BasicForm#doAction loading, validating and submitting} the form.</p>
6661  *
6662  * <p>A {@link Ext.Container Container} <i>using</i> the FormLayout layout manager (e.g.
6663  * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) can also accept the following
6664  * layout-specific config properties:<div class="mdetail-params"><ul>
6665  * <li><b><tt>{@link Ext.form.FormPanel#hideLabels hideLabels}</tt></b></li>
6666  * <li><b><tt>{@link Ext.form.FormPanel#labelAlign labelAlign}</tt></b></li>
6667  * <li><b><tt>{@link Ext.form.FormPanel#labelPad labelPad}</tt></b></li>
6668  * <li><b><tt>{@link Ext.form.FormPanel#labelSeparator labelSeparator}</tt></b></li>
6669  * <li><b><tt>{@link Ext.form.FormPanel#labelWidth labelWidth}</tt></b></li>
6670  * </ul></div></p>
6671  *
6672  * <p>Any Component (including Fields) managed by FormLayout accepts the following as a config option:
6673  * <div class="mdetail-params"><ul>
6674  * <li><b><tt>{@link Ext.Component#anchor anchor}</tt></b></li>
6675  * </ul></div></p>
6676  *
6677  * <p>Any Component managed by FormLayout may be rendered as a form field (with an associated label) by
6678  * configuring it with a non-null <b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b>. Components configured
6679  * in this way may be configured with the following options which affect the way the FormLayout renders them:
6680  * <div class="mdetail-params"><ul>
6681  * <li><b><tt>{@link Ext.Component#clearCls clearCls}</tt></b></li>
6682  * <li><b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b></li>
6683  * <li><b><tt>{@link Ext.Component#hideLabel hideLabel}</tt></b></li>
6684  * <li><b><tt>{@link Ext.Component#itemCls itemCls}</tt></b></li>
6685  * <li><b><tt>{@link Ext.Component#labelSeparator labelSeparator}</tt></b></li>
6686  * <li><b><tt>{@link Ext.Component#labelStyle labelStyle}</tt></b></li>
6687  * </ul></div></p>
6688  *
6689  * <p>Example usage:</p>
6690  * <pre><code>
6691 // Required if showing validation messages
6692 Ext.QuickTips.init();
6693
6694 // While you can create a basic Panel with layout:'form', practically
6695 // you should usually use a FormPanel to also get its form functionality
6696 // since it already creates a FormLayout internally.
6697 var form = new Ext.form.FormPanel({
6698     title: 'Form Layout',
6699     bodyStyle: 'padding:15px',
6700     width: 350,
6701     defaultType: 'textfield',
6702     defaults: {
6703         // applied to each contained item
6704         width: 230,
6705         msgTarget: 'side'
6706     },
6707     items: [{
6708             fieldLabel: 'First Name',
6709             name: 'first',
6710             allowBlank: false,
6711             {@link Ext.Component#labelSeparator labelSeparator}: ':' // override labelSeparator layout config
6712         },{
6713             fieldLabel: 'Last Name',
6714             name: 'last'
6715         },{
6716             fieldLabel: 'Email',
6717             name: 'email',
6718             vtype:'email'
6719         }, {
6720             xtype: 'textarea',
6721             hideLabel: true,     // override hideLabels layout config
6722             name: 'msg',
6723             anchor: '100% -53'
6724         }
6725     ],
6726     buttons: [
6727         {text: 'Save'},
6728         {text: 'Cancel'}
6729     ],
6730     layoutConfig: {
6731         {@link #labelSeparator}: '~' // superseded by assignment below
6732     },
6733     // config options applicable to container when layout='form':
6734     hideLabels: false,
6735     labelAlign: 'left',   // or 'right' or 'top'
6736     {@link Ext.form.FormPanel#labelSeparator labelSeparator}: '>>', // takes precedence over layoutConfig value
6737     labelWidth: 65,       // defaults to 100
6738     labelPad: 8           // defaults to 5, must specify labelWidth to be honored
6739 });
6740 </code></pre>
6741  */
6742 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
6743
6744     /**
6745      * @cfg {String} labelSeparator
6746      * See {@link Ext.form.FormPanel}.{@link Ext.form.FormPanel#labelSeparator labelSeparator}.  Configuration
6747      * of this property at the <b>container</b> level takes precedence.
6748      */
6749     labelSeparator : ':',
6750
6751     /**
6752      * Read only. The CSS style specification string added to field labels in this layout if not
6753      * otherwise {@link Ext.Component#labelStyle specified by each contained field}.
6754      * @type String
6755      * @property labelStyle
6756      */
6757
6758     /**
6759      * @cfg {Boolean} trackLabels
6760      * True to show/hide the field label when the field is hidden. Defaults to <tt>false</tt>.
6761      */
6762     trackLabels: false,
6763
6764
6765     onRemove: function(c){
6766         Ext.layout.FormLayout.superclass.onRemove.call(this, c);
6767         if(this.trackLabels){
6768             c.un('show', this.onFieldShow, this);
6769             c.un('hide', this.onFieldHide, this);
6770         }
6771         // check for itemCt, since we may be removing a fieldset or something similar
6772         var el = c.getPositionEl(),
6773                 ct = c.getItemCt && c.getItemCt();
6774         if(c.rendered && ct){
6775             if (el && el.dom) {
6776                 el.insertAfter(ct);
6777             }
6778             Ext.destroy(ct);
6779             Ext.destroyMembers(c, 'label', 'itemCt');
6780             if(c.customItemCt){
6781                 Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
6782             }
6783         }
6784     },
6785
6786     // private
6787     setContainer : function(ct){
6788         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
6789         if(ct.labelAlign){
6790             ct.addClass('x-form-label-'+ct.labelAlign);
6791         }
6792
6793         if(ct.hideLabels){
6794             Ext.apply(this, {
6795                 labelStyle: 'display:none',
6796                 elementStyle: 'padding-left:0;',
6797                 labelAdjust: 0
6798             });
6799         }else{
6800             this.labelSeparator = ct.labelSeparator || this.labelSeparator;
6801             ct.labelWidth = ct.labelWidth || 100;
6802             if(Ext.isNumber(ct.labelWidth)){
6803                 var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
6804                 Ext.apply(this, {
6805                     labelAdjust: ct.labelWidth + pad,
6806                     labelStyle: 'width:' + ct.labelWidth + 'px;',
6807                     elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
6808                 });
6809             }
6810             if(ct.labelAlign == 'top'){
6811                 Ext.apply(this, {
6812                     labelStyle: 'width:auto;',
6813                     labelAdjust: 0,
6814                     elementStyle: 'padding-left:0;'
6815                 });
6816             }
6817         }
6818     },
6819
6820     // private
6821     isHide: function(c){
6822         return c.hideLabel || this.container.hideLabels;
6823     },
6824
6825     onFieldShow: function(c){
6826         c.getItemCt().removeClass('x-hide-' + c.hideMode);
6827     },
6828
6829     onFieldHide: function(c){
6830         c.getItemCt().addClass('x-hide-' + c.hideMode);
6831     },
6832
6833     //private
6834     getLabelStyle: function(s){
6835         var ls = '', items = [this.labelStyle, s];
6836         for (var i = 0, len = items.length; i < len; ++i){
6837             if (items[i]){
6838                 ls += items[i];
6839                 if (ls.substr(-1, 1) != ';'){
6840                     ls += ';'
6841                 }
6842             }
6843         }
6844         return ls;
6845     },
6846
6847     /**
6848      * @cfg {Ext.Template} fieldTpl
6849      * A {@link Ext.Template#compile compile}d {@link Ext.Template} for rendering
6850      * the fully wrapped, labeled and styled form Field. Defaults to:</p><pre><code>
6851 new Ext.Template(
6852     &#39;&lt;div class="x-form-item {itemCls}" tabIndex="-1">&#39;,
6853         &#39;&lt;&#108;abel for="{id}" style="{labelStyle}" class="x-form-item-&#108;abel">{&#108;abel}{labelSeparator}&lt;/&#108;abel>&#39;,
6854         &#39;&lt;div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">&#39;,
6855         &#39;&lt;/div>&lt;div class="{clearCls}">&lt;/div>&#39;,
6856     '&lt;/div>'
6857 );
6858 </code></pre>
6859      * <p>This may be specified to produce a different DOM structure when rendering form Fields.</p>
6860      * <p>A description of the properties within the template follows:</p><div class="mdetail-params"><ul>
6861      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
6862      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
6863      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
6864      * supplied at the container level.</div></li>
6865      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
6866      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
6867      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
6868      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
6869      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
6870      * field (defaults to <tt>''</tt>)</div></li>
6871      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
6872      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
6873      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
6874      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
6875      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
6876      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
6877      * </ul></div>
6878      * <p>Also see <tt>{@link #getTemplateArgs}</tt></p>
6879      */
6880
6881     // private
6882     renderItem : function(c, position, target){
6883         if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
6884             var args = this.getTemplateArgs(c);
6885             if(Ext.isNumber(position)){
6886                 position = target.dom.childNodes[position] || null;
6887             }
6888             if(position){
6889                 c.itemCt = this.fieldTpl.insertBefore(position, args, true);
6890             }else{
6891                 c.itemCt = this.fieldTpl.append(target, args, true);
6892             }
6893             if(!c.getItemCt){
6894                 // Non form fields don't have getItemCt, apply it here
6895                 // This will get cleaned up in onRemove
6896                 Ext.apply(c, {
6897                     getItemCt: function(){
6898                         return c.itemCt;
6899                     },
6900                     customItemCt: true
6901                 });
6902             }
6903             c.label = c.getItemCt().child('label.x-form-item-label');
6904             if(!c.rendered){
6905                 c.render('x-form-el-' + c.id);
6906             }else if(!this.isValidParent(c, target)){
6907                 Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
6908             }
6909             if(this.trackLabels){
6910                 if(c.hidden){
6911                     this.onFieldHide(c);
6912                 }
6913                 c.on({
6914                     scope: this,
6915                     show: this.onFieldShow,
6916                     hide: this.onFieldHide
6917                 });
6918             }
6919             this.configureItem(c);
6920         }else {
6921             Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
6922         }
6923     },
6924
6925     /**
6926      * <p>Provides template arguments for rendering the fully wrapped, labeled and styled form Field.</p>
6927      * <p>This method returns an object hash containing properties used by the layout's {@link #fieldTpl}
6928      * to create a correctly wrapped, labeled and styled form Field. This may be overriden to
6929      * create custom layouts. The properties which must be returned are:</p><div class="mdetail-params"><ul>
6930      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
6931      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
6932      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
6933      * supplied at the container level.</div></li>
6934      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
6935      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
6936      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
6937      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
6938      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
6939      * field (defaults to <tt>''</tt>)</div></li>
6940      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
6941      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
6942      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
6943      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
6944      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
6945      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
6946      * </ul></div>
6947      * @param (Ext.form.Field} field The {@link Ext.form.Field Field} being rendered.
6948      * @return An object hash containing the properties required to render the Field.
6949      */
6950     getTemplateArgs: function(field) {
6951         var noLabelSep = !field.fieldLabel || field.hideLabel;
6952         return {
6953             id: field.id,
6954             label: field.fieldLabel,
6955             labelStyle: this.getLabelStyle(field.labelStyle),
6956             elementStyle: this.elementStyle||'',
6957             labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator),
6958             itemCls: (field.itemCls||this.container.itemCls||'') + (field.hideLabel ? ' x-hide-label' : ''),
6959             clearCls: field.clearCls || 'x-form-clear-left'
6960         };
6961     },
6962
6963     // private
6964     adjustWidthAnchor: function(value, c){
6965         if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){
6966             var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
6967             return value - this.labelAdjust + (adjust ? -3 : 0);
6968         }
6969         return value;
6970     },
6971
6972     adjustHeightAnchor : function(value, c){
6973         if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
6974             return value - c.label.getHeight();
6975         }
6976         return value;
6977     },
6978
6979     // private
6980     isValidParent : function(c, target){
6981         return target && this.container.getEl().contains(c.getPositionEl());
6982     }
6983
6984     /**
6985      * @property activeItem
6986      * @hide
6987      */
6988 });
6989
6990 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
6991 /**\r
6992  * @class Ext.layout.AccordionLayout\r
6993  * @extends Ext.layout.FitLayout\r
6994  * <p>This is a layout that manages multiple Panels in an expandable accordion style such that only\r
6995  * <b>one Panel can be expanded at any given time</b>. Each Panel has built-in support for expanding and collapsing.</p>\r
6996  * <p>Note: Only Ext.Panels <b>and all subclasses of Ext.Panel</b> may be used in an accordion layout Container.</p>\r
6997  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>\r
6998  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>\r
6999  * <p>Example usage:</p>\r
7000  * <pre><code>\r
7001 var accordion = new Ext.Panel({\r
7002     title: 'Accordion Layout',\r
7003     layout:'accordion',\r
7004     defaults: {\r
7005         // applied to each contained panel\r
7006         bodyStyle: 'padding:15px'\r
7007     },\r
7008     layoutConfig: {\r
7009         // layout-specific configs go here\r
7010         titleCollapse: false,\r
7011         animate: true,\r
7012         activeOnTop: true\r
7013     },\r
7014     items: [{\r
7015         title: 'Panel 1',\r
7016         html: '&lt;p&gt;Panel content!&lt;/p&gt;'\r
7017     },{\r
7018         title: 'Panel 2',\r
7019         html: '&lt;p&gt;Panel content!&lt;/p&gt;'\r
7020     },{\r
7021         title: 'Panel 3',\r
7022         html: '&lt;p&gt;Panel content!&lt;/p&gt;'\r
7023     }]\r
7024 });\r
7025 </code></pre>\r
7026  */\r
7027 Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {\r
7028     /**\r
7029      * @cfg {Boolean} fill\r
7030      * True to adjust the active item's height to fill the available space in the container, false to use the\r
7031      * item's current height, or auto height if not explicitly set (defaults to true).\r
7032      */\r
7033     fill : true,\r
7034     /**\r
7035      * @cfg {Boolean} autoWidth\r
7036      * True to set each contained item's width to 'auto', false to use the item's current width (defaults to true).\r
7037      * Note that some components, in particular the {@link Ext.grid.GridPanel grid}, will not function properly within\r
7038      * layouts if they have auto width, so in such cases this config should be set to false.\r
7039      */\r
7040     autoWidth : true,\r
7041     /**\r
7042      * @cfg {Boolean} titleCollapse\r
7043      * True to allow expand/collapse of each contained panel by clicking anywhere on the title bar, false to allow\r
7044      * expand/collapse only when the toggle tool button is clicked (defaults to true).  When set to false,\r
7045      * {@link #hideCollapseTool} should be false also.\r
7046      */\r
7047     titleCollapse : true,\r
7048     /**\r
7049      * @cfg {Boolean} hideCollapseTool\r
7050      * True to hide the contained panels' collapse/expand toggle buttons, false to display them (defaults to false).\r
7051      * When set to true, {@link #titleCollapse} should be true also.\r
7052      */\r
7053     hideCollapseTool : false,\r
7054     /**\r
7055      * @cfg {Boolean} collapseFirst\r
7056      * True to make sure the collapse/expand toggle button always renders first (to the left of) any other tools\r
7057      * in the contained panels' title bars, false to render it last (defaults to false).\r
7058      */\r
7059     collapseFirst : false,\r
7060     /**\r
7061      * @cfg {Boolean} animate\r
7062      * True to slide the contained panels open and closed during expand/collapse using animation, false to open and\r
7063      * close directly with no animation (defaults to false).  Note: to defer to the specific config setting of each\r
7064      * contained panel for this property, set this to undefined at the layout level.\r
7065      */\r
7066     animate : false,\r
7067     /**\r
7068      * @cfg {Boolean} sequence\r
7069      * <b>Experimental</b>. If animate is set to true, this will result in each animation running in sequence.\r
7070      */\r
7071     sequence : false,\r
7072     /**\r
7073      * @cfg {Boolean} activeOnTop\r
7074      * True to swap the position of each panel as it is expanded so that it becomes the first item in the container,\r
7075      * false to keep the panels in the rendered order. <b>This is NOT compatible with "animate:true"</b> (defaults to false).\r
7076      */\r
7077     activeOnTop : false,\r
7078 \r
7079     renderItem : function(c){\r
7080         if(this.animate === false){\r
7081             c.animCollapse = false;\r
7082         }\r
7083         c.collapsible = true;\r
7084         if(this.autoWidth){\r
7085             c.autoWidth = true;\r
7086         }\r
7087         if(this.titleCollapse){\r
7088             c.titleCollapse = true;\r
7089         }\r
7090         if(this.hideCollapseTool){\r
7091             c.hideCollapseTool = true;\r
7092         }\r
7093         if(this.collapseFirst !== undefined){\r
7094             c.collapseFirst = this.collapseFirst;\r
7095         }\r
7096         if(!this.activeItem && !c.collapsed){\r
7097             this.setActiveItem(c, true);\r
7098         }else if(this.activeItem && this.activeItem != c){\r
7099             c.collapsed = true;\r
7100         }\r
7101         Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);\r
7102         c.header.addClass('x-accordion-hd');\r
7103         c.on('beforeexpand', this.beforeExpand, this);\r
7104     },\r
7105     \r
7106     onRemove: function(c){\r
7107         Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);\r
7108         if(c.rendered){\r
7109             c.header.removeClass('x-accordion-hd');\r
7110         }\r
7111         c.un('beforeexpand', this.beforeExpand, this);\r
7112     },\r
7113 \r
7114     // private\r
7115     beforeExpand : function(p, anim){\r
7116         var ai = this.activeItem;\r
7117         if(ai){\r
7118             if(this.sequence){\r
7119                 delete this.activeItem;\r
7120                 if (!ai.collapsed){\r
7121                     ai.collapse({callback:function(){\r
7122                         p.expand(anim || true);\r
7123                     }, scope: this});\r
7124                     return false;\r
7125                 }\r
7126             }else{\r
7127                 ai.collapse(this.animate);\r
7128             }\r
7129         }\r
7130         this.setActive(p);\r
7131         if(this.activeOnTop){\r
7132             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);\r
7133         }\r
7134         this.layout();\r
7135     },\r
7136 \r
7137     // private\r
7138     setItemSize : function(item, size){\r
7139         if(this.fill && item){\r
7140             var hh = 0;\r
7141             this.container.items.each(function(p){\r
7142                 if(p != item){\r
7143                     hh += p.header.getHeight();\r
7144                 }    \r
7145             });\r
7146             size.height -= hh;\r
7147             item.setSize(size);\r
7148         }\r
7149     },\r
7150 \r
7151     /**\r
7152      * Sets the active (expanded) item in the layout.\r
7153      * @param {String/Number} item The string component id or numeric index of the item to activate\r
7154      */\r
7155     setActiveItem : function(item){\r
7156         this.setActive(item, true);\r
7157     },\r
7158     \r
7159     // private\r
7160     setActive : function(item, expand){\r
7161         var ai = this.activeItem;\r
7162         item = this.container.getComponent(item);\r
7163         if(ai != item){\r
7164             if(item.rendered && item.collapsed && expand){\r
7165                 item.expand();\r
7166             }else{\r
7167                 if(ai){\r
7168                    ai.fireEvent('deactivate', ai);\r
7169                 }\r
7170                 this.activeItem = item;\r
7171                 item.fireEvent('activate', item);\r
7172             }\r
7173         }\r
7174     }\r
7175 });\r
7176 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;\r
7177 \r
7178 //backwards compat\r
7179 Ext.layout.Accordion = Ext.layout.AccordionLayout;/**\r
7180  * @class Ext.layout.TableLayout\r
7181  * @extends Ext.layout.ContainerLayout\r
7182  * <p>This layout allows you to easily render content into an HTML table.  The total number of columns can be\r
7183  * specified, and rowspan and colspan can be used to create complex layouts within the table.\r
7184  * This class is intended to be extended or created via the layout:'table' {@link Ext.Container#layout} config,\r
7185  * and should generally not need to be created directly via the new keyword.</p>\r
7186  * <p>Note that when creating a layout via config, the layout-specific config properties must be passed in via\r
7187  * the {@link Ext.Container#layoutConfig} object which will then be applied internally to the layout.  In the\r
7188  * case of TableLayout, the only valid layout config property is {@link #columns}.  However, the items added to a\r
7189  * TableLayout can supply the following table-specific config properties:</p>\r
7190  * <ul>\r
7191  * <li><b>rowspan</b> Applied to the table cell containing the item.</li>\r
7192  * <li><b>colspan</b> Applied to the table cell containing the item.</li>\r
7193  * <li><b>cellId</b> An id applied to the table cell containing the item.</li>\r
7194  * <li><b>cellCls</b> A CSS class name added to the table cell containing the item.</li>\r
7195  * </ul>\r
7196  * <p>The basic concept of building up a TableLayout is conceptually very similar to building up a standard\r
7197  * HTML table.  You simply add each panel (or "cell") that you want to include along with any span attributes\r
7198  * specified as the special config properties of rowspan and colspan which work exactly like their HTML counterparts.\r
7199  * Rather than explicitly creating and nesting rows and columns as you would in HTML, you simply specify the\r
7200  * total column count in the layoutConfig and start adding panels in their natural order from left to right,\r
7201  * top to bottom.  The layout will automatically figure out, based on the column count, rowspans and colspans,\r
7202  * how to position each panel within the table.  Just like with HTML tables, your rowspans and colspans must add\r
7203  * up correctly in your overall layout or you'll end up with missing and/or extra cells!  Example usage:</p>\r
7204  * <pre><code>\r
7205 // This code will generate a layout table that is 3 columns by 2 rows\r
7206 // with some spanning included.  The basic layout will be:\r
7207 // +--------+-----------------+\r
7208 // |   A    |   B             |\r
7209 // |        |--------+--------|\r
7210 // |        |   C    |   D    |\r
7211 // +--------+--------+--------+\r
7212 var table = new Ext.Panel({\r
7213     title: 'Table Layout',\r
7214     layout:'table',\r
7215     defaults: {\r
7216         // applied to each contained panel\r
7217         bodyStyle:'padding:20px'\r
7218     },\r
7219     layoutConfig: {\r
7220         // The total column count must be specified here\r
7221         columns: 3\r
7222     },\r
7223     items: [{\r
7224         html: '&lt;p&gt;Cell A content&lt;/p&gt;',\r
7225         rowspan: 2\r
7226     },{\r
7227         html: '&lt;p&gt;Cell B content&lt;/p&gt;',\r
7228         colspan: 2\r
7229     },{\r
7230         html: '&lt;p&gt;Cell C content&lt;/p&gt;',\r
7231         cellCls: 'highlight'\r
7232     },{\r
7233         html: '&lt;p&gt;Cell D content&lt;/p&gt;'\r
7234     }]\r
7235 });\r
7236 </code></pre>\r
7237  */\r
7238 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
7239     /**\r
7240      * @cfg {Number} columns\r
7241      * The total number of columns to create in the table for this layout.  If not specified, all Components added to\r
7242      * this layout will be rendered into a single row using one column per Component.\r
7243      */\r
7244 \r
7245     // private\r
7246     monitorResize:false,\r
7247     \r
7248     targetCls: 'x-table-layout-ct',\r
7249 \r
7250     /**\r
7251      * @cfg {Object} tableAttrs\r
7252      * <p>An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification\r
7253      * used to create the layout's <tt>&lt;table&gt;</tt> element. Example:</p><pre><code>\r
7254 {\r
7255     xtype: 'panel',\r
7256     layout: 'table',\r
7257     layoutConfig: {\r
7258         tableAttrs: {\r
7259                 style: {\r
7260                         width: '100%'\r
7261                 }\r
7262         },\r
7263         columns: 3\r
7264     }\r
7265 }</code></pre>\r
7266      */\r
7267     tableAttrs:null,\r
7268     \r
7269     // private\r
7270     setContainer : function(ct){\r
7271         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);\r
7272 \r
7273         this.currentRow = 0;\r
7274         this.currentColumn = 0;\r
7275         this.cells = [];\r
7276     },\r
7277 \r
7278     // private\r
7279     onLayout : function(ct, target){\r
7280         var cs = ct.items.items, len = cs.length, c, i;\r
7281 \r
7282         if(!this.table){\r
7283             this.table = target.createChild(\r
7284                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);\r
7285         }\r
7286         this.renderAll(ct, target);\r
7287     },\r
7288 \r
7289     // private\r
7290     getRow : function(index){\r
7291         var row = this.table.tBodies[0].childNodes[index];\r
7292         if(!row){\r
7293             row = document.createElement('tr');\r
7294             this.table.tBodies[0].appendChild(row);\r
7295         }\r
7296         return row;\r
7297     },\r
7298 \r
7299     // private\r
7300     getNextCell : function(c){\r
7301         var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);\r
7302         var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];\r
7303         for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){\r
7304             if(!this.cells[rowIndex]){\r
7305                 this.cells[rowIndex] = [];\r
7306             }\r
7307             for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){\r
7308                 this.cells[rowIndex][colIndex] = true;\r
7309             }\r
7310         }\r
7311         var td = document.createElement('td');\r
7312         if(c.cellId){\r
7313             td.id = c.cellId;\r
7314         }\r
7315         var cls = 'x-table-layout-cell';\r
7316         if(c.cellCls){\r
7317             cls += ' ' + c.cellCls;\r
7318         }\r
7319         td.className = cls;\r
7320         if(c.colspan){\r
7321             td.colSpan = c.colspan;\r
7322         }\r
7323         if(c.rowspan){\r
7324             td.rowSpan = c.rowspan;\r
7325         }\r
7326         this.getRow(curRow).appendChild(td);\r
7327         return td;\r
7328     },\r
7329     \r
7330     // private\r
7331     getNextNonSpan: function(colIndex, rowIndex){\r
7332         var cols = this.columns;\r
7333         while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {\r
7334             if(cols && colIndex >= cols){\r
7335                 rowIndex++;\r
7336                 colIndex = 0;\r
7337             }else{\r
7338                 colIndex++;\r
7339             }\r
7340         }\r
7341         return [colIndex, rowIndex];\r
7342     },\r
7343 \r
7344     // private\r
7345     renderItem : function(c, position, target){\r
7346         if(c && !c.rendered){\r
7347             c.render(this.getNextCell(c));\r
7348             this.configureItem(c, position);\r
7349         }else if(c && !this.isValidParent(c, target)){\r
7350             var container = this.getNextCell(c);\r
7351             container.insertBefore(c.getPositionEl().dom, null);\r
7352             c.container = Ext.get(container);\r
7353             this.configureItem(c, position);\r
7354         }\r
7355     },\r
7356 \r
7357     // private\r
7358     isValidParent : function(c, target){\r
7359         return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);\r
7360     }\r
7361 \r
7362     /**\r
7363      * @property activeItem\r
7364      * @hide\r
7365      */\r
7366 });\r
7367 \r
7368 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;/**\r
7369  * @class Ext.layout.AbsoluteLayout\r
7370  * @extends Ext.layout.AnchorLayout\r
7371  * <p>This is a layout that inherits the anchoring of <b>{@link Ext.layout.AnchorLayout}</b> and adds the\r
7372  * ability for x/y positioning using the standard x and y component config options.</p>\r
7373  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>\r
7374  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>\r
7375  * <p>Example usage:</p>\r
7376  * <pre><code>\r
7377 var form = new Ext.form.FormPanel({\r
7378     title: 'Absolute Layout',\r
7379     layout:'absolute',\r
7380     layoutConfig: {\r
7381         // layout-specific configs go here\r
7382         extraCls: 'x-abs-layout-item',\r
7383     },\r
7384     baseCls: 'x-plain',\r
7385     url:'save-form.php',\r
7386     defaultType: 'textfield',\r
7387     items: [{\r
7388         x: 0,\r
7389         y: 5,\r
7390         xtype:'label',\r
7391         text: 'Send To:'\r
7392     },{\r
7393         x: 60,\r
7394         y: 0,\r
7395         name: 'to',\r
7396         anchor:'100%'  // anchor width by percentage\r
7397     },{\r
7398         x: 0,\r
7399         y: 35,\r
7400         xtype:'label',\r
7401         text: 'Subject:'\r
7402     },{\r
7403         x: 60,\r
7404         y: 30,\r
7405         name: 'subject',\r
7406         anchor: '100%'  // anchor width by percentage\r
7407     },{\r
7408         x:0,\r
7409         y: 60,\r
7410         xtype: 'textarea',\r
7411         name: 'msg',\r
7412         anchor: '100% 100%'  // anchor width and height\r
7413     }]\r
7414 });\r
7415 </code></pre>\r
7416  */\r
7417 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {\r
7418 \r
7419     extraCls: 'x-abs-layout-item',\r
7420 \r
7421     onLayout : function(ct, target){\r
7422         target.position();\r
7423         this.paddingLeft = target.getPadding('l');\r
7424         this.paddingTop = target.getPadding('t');\r
7425 \r
7426         Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);\r
7427     },\r
7428 \r
7429     // private\r
7430     adjustWidthAnchor : function(value, comp){\r
7431         return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;\r
7432     },\r
7433 \r
7434     // private\r
7435     adjustHeightAnchor : function(value, comp){\r
7436         return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;\r
7437     }\r
7438     /**\r
7439      * @property activeItem\r
7440      * @hide\r
7441      */\r
7442 });\r
7443 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
7444 /**
7445  * @class Ext.layout.BoxLayout
7446  * @extends Ext.layout.ContainerLayout
7447  * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
7448  */
7449 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
7450     /**
7451      * @cfg {Object} defaultMargins
7452      * <p>If the individual contained items do not have a <tt>margins</tt>
7453      * property specified, the default margins from this property will be
7454      * applied to each item.</p>
7455      * <br><p>This property may be specified as an object containing margins
7456      * to apply in the format:</p><pre><code>
7457 {
7458     top: (top margin),
7459     right: (right margin),
7460     bottom: (bottom margin),
7461     left: (left margin)
7462 }</code></pre>
7463      * <p>This property may also be specified as a string containing
7464      * space-separated, numeric margin values. The order of the sides associated
7465      * with each value matches the way CSS processes margin values:</p>
7466      * <div class="mdetail-params"><ul>
7467      * <li>If there is only one value, it applies to all sides.</li>
7468      * <li>If there are two values, the top and bottom borders are set to the
7469      * first value and the right and left are set to the second.</li>
7470      * <li>If there are three values, the top is set to the first value, the left
7471      * and right are set to the second, and the bottom is set to the third.</li>
7472      * <li>If there are four values, they apply to the top, right, bottom, and
7473      * left, respectively.</li>
7474      * </ul></div>
7475      * <p>Defaults to:</p><pre><code>
7476      * {top:0, right:0, bottom:0, left:0}
7477      * </code></pre>
7478      */
7479     defaultMargins : {left:0,top:0,right:0,bottom:0},
7480     /**
7481      * @cfg {String} padding
7482      * <p>Sets the padding to be applied to all child items managed by this layout.</p>
7483      * <p>This property must be specified as a string containing
7484      * space-separated, numeric padding values. The order of the sides associated
7485      * with each value matches the way CSS processes padding values:</p>
7486      * <div class="mdetail-params"><ul>
7487      * <li>If there is only one value, it applies to all sides.</li>
7488      * <li>If there are two values, the top and bottom borders are set to the
7489      * first value and the right and left are set to the second.</li>
7490      * <li>If there are three values, the top is set to the first value, the left
7491      * and right are set to the second, and the bottom is set to the third.</li>
7492      * <li>If there are four values, they apply to the top, right, bottom, and
7493      * left, respectively.</li>
7494      * </ul></div>
7495      * <p>Defaults to: <code>"0"</code></p>
7496      */
7497     padding : '0',
7498     // documented in subclasses
7499     pack : 'start',
7500
7501     // private
7502     monitorResize : true,
7503     scrollOffset : 0,
7504     extraCls : 'x-box-item',
7505     targetCls : 'x-box-layout-ct',
7506     innerCls : 'x-box-inner',
7507
7508     constructor : function(config){
7509         Ext.layout.BoxLayout.superclass.constructor.call(this, config);
7510         if(Ext.isString(this.defaultMargins)){
7511             this.defaultMargins = this.parseMargins(this.defaultMargins);
7512         }
7513     },
7514
7515     // private
7516     isValidParent : function(c, target){
7517         return c.getPositionEl().dom.parentNode == this.innerCt.dom;
7518     },
7519
7520     // private
7521     onLayout : function(ct, target){
7522         var cs = ct.items.items, len = cs.length, c, i, last = len-1, cm;
7523
7524         if(!this.innerCt){
7525             // the innerCt prevents wrapping and shuffling while
7526             // the container is resizing
7527             this.innerCt = target.createChild({cls:this.innerCls});
7528             this.padding = this.parseMargins(this.padding);
7529         }
7530         this.renderAll(ct, this.innerCt);
7531     },
7532
7533     // private
7534     renderItem : function(c){
7535         if(Ext.isString(c.margins)){
7536             c.margins = this.parseMargins(c.margins);
7537         }else if(!c.margins){
7538             c.margins = this.defaultMargins;
7539         }
7540         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
7541     },
7542
7543     // deprecate
7544     getTargetSize : function(target){
7545         return (Ext.isIE6 && Ext.isStrict && target.dom == document.body) ? target.getStyleSize() : target.getViewSize(true);
7546     },
7547
7548     getItems: function(ct){
7549         var items = [];
7550         ct.items.each(function(c){
7551             if(c.isVisible()){
7552                 items.push(c);
7553             }
7554         });
7555         return items;
7556     }
7557 });
7558
7559 /**
7560  * @class Ext.layout.VBoxLayout
7561  * @extends Ext.layout.BoxLayout
7562  * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical
7563  * space between child items containing a numeric <code>flex</code> configuration.</p>
7564  * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option.
7565  */
7566 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
7567     /**
7568      * @cfg {String} align
7569      * Controls how the child items of the container are aligned. Acceptable configuration values for this
7570      * property are:
7571      * <div class="mdetail-params"><ul>
7572      * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally
7573      * at the <b>left</b> side of the container</div></li>
7574      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the
7575      * <b>mid-width</b> of the container</div></li>
7576      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill
7577      * the width of the container</div></li>
7578      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to
7579      * the size of the largest item.</div></li>
7580      * </ul></div>
7581      */
7582     align : 'left', // left, center, stretch, strechmax
7583     /**
7584      * @cfg {String} pack
7585      * Controls how the child items of the container are packed together. Acceptable configuration values
7586      * for this property are:
7587      * <div class="mdetail-params"><ul>
7588      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
7589      * <b>top</b> side of container</div></li>
7590      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
7591      * <b>mid-height</b> of container</div></li>
7592      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>
7593      * side of container</div></li>
7594      * </ul></div>
7595      */
7596     /**
7597      * @cfg {Number} flex
7598      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
7599      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>
7600      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
7601      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
7602      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
7603      */
7604
7605     // private
7606     onLayout : function(ct, target){
7607         Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);
7608
7609         var cs = this.getItems(ct), cm, ch, margin, cl, diff, aw,
7610             size = target.getViewSize(true),
7611             w = size.width,
7612             h = size.height - this.scrollOffset,
7613             l = this.padding.left, t = this.padding.top,
7614             isStart = this.pack == 'start',
7615             stretchWidth = w - (this.padding.left + this.padding.right),
7616             extraHeight = 0,
7617             maxWidth = 0,
7618             totalFlex = 0,
7619             flexHeight = 0,
7620             usedHeight = 0,
7621             idx = 0,
7622             heights = [],
7623             restore = [],
7624             c,
7625             csLen = cs.length;
7626
7627         // Do only width calculations and apply those first, as they can affect height
7628         for (i = 0 ; i < csLen; i++) {
7629             c = cs[i];
7630             cm = c.margins;
7631             margin = cm.top + cm.bottom;
7632             maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);
7633         }
7634
7635         var innerCtWidth = maxWidth + this.padding.left + this.padding.right;
7636         switch(this.align){
7637             case 'stretch':
7638                 this.innerCt.setSize(w, h);
7639                 break;
7640             case 'stretchmax':
7641             case 'left':
7642                 this.innerCt.setSize(innerCtWidth, h);
7643                 break;
7644             case 'center':
7645                 this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);
7646                 break;
7647         }
7648
7649         var availableWidth = Math.max(0, w - this.padding.left - this.padding.right);
7650         // Apply widths
7651         for (i = 0 ; i < csLen; i++) {
7652             c = cs[i];
7653             cm = c.margins;
7654             if(this.align == 'stretch'){
7655                 c.setWidth((stretchWidth - (cm.left + cm.right)).constrain(
7656                     c.minWidth || 0, c.maxWidth || 1000000));
7657             }else if(this.align == 'stretchmax'){
7658                 c.setWidth((maxWidth - (cm.left + cm.right)).constrain(
7659                     c.minWidth || 0, c.maxWidth || 1000000));
7660             }else if(isStart && c.flex){
7661                 c.setWidth();
7662             }
7663
7664         }
7665
7666         // Do height calculations
7667         for (i = 0 ; i < csLen; i++) {
7668             c = cs[i];
7669             cm = c.margins;
7670             totalFlex += c.flex || 0;
7671             ch = c.getHeight();
7672             margin = cm.top + cm.bottom;
7673             extraHeight += ch + margin;
7674             flexHeight += margin + (c.flex ? 0 : ch);
7675         }
7676         extraHeight = h - extraHeight - this.padding.top - this.padding.bottom;
7677
7678         var availHeight = Math.max(0, h - this.padding.top - this.padding.bottom - flexHeight),
7679             leftOver = availHeight;
7680         for (i = 0 ; i < csLen; i++) {
7681             c = cs[i];
7682             if(isStart && c.flex){
7683                 ch = Math.floor(availHeight * (c.flex / totalFlex));
7684                 leftOver -= ch;
7685                 heights.push(ch);
7686             }
7687         }
7688         if(this.pack == 'center'){
7689             t += extraHeight ? extraHeight / 2 : 0;
7690         }else if(this.pack == 'end'){
7691             t += extraHeight;
7692         }
7693         idx = 0;
7694         // Apply heights
7695         for (i = 0 ; i < csLen; i++) {
7696             c = cs[i];
7697             cm = c.margins;
7698             t += cm.top;
7699             aw = availableWidth;
7700             cl = l + cm.left // default left pos
7701
7702 //          Adjust left pos for centering
7703             if(this.align == 'center'){
7704                 if((diff = availableWidth - (c.getWidth() + cm.left + cm.right)) > 0){
7705                     cl += (diff/2);
7706                     aw -= diff;
7707                 }
7708             }
7709
7710             c.setPosition(cl, t);
7711             if(isStart && c.flex){
7712                 ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));
7713                 c.setSize(aw, ch);
7714             }else{
7715                 ch = c.getHeight();
7716             }
7717             t += ch + cm.bottom;
7718         }
7719     }
7720 });
7721
7722 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
7723
7724 /**
7725  * @class Ext.layout.HBoxLayout
7726  * @extends Ext.layout.BoxLayout
7727  * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal
7728  * space between child items containing a numeric <code>flex</code> configuration.</p>
7729  * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option.
7730  */
7731 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
7732     /**
7733      * @cfg {String} align
7734      * Controls how the child items of the container are aligned. Acceptable configuration values for this
7735      * property are:
7736      * <div class="mdetail-params"><ul>
7737      * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically
7738      * at the <b>top</b> of the container</div></li>
7739      * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically in the
7740      * <b>middle</b> of the container</div></li>
7741      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill
7742      * the height of the container</div></li>
7743      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to
7744      * the height of the largest item.</div></li>
7745      */
7746     align : 'top', // top, middle, stretch, strechmax
7747     /**
7748      * @cfg {String} pack
7749      * Controls how the child items of the container are packed together. Acceptable configuration values
7750      * for this property are:
7751      * <div class="mdetail-params"><ul>
7752      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
7753      * <b>left</b> side of container</div></li>
7754      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
7755      * <b>mid-width</b> of container</div></li>
7756      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>
7757      * side of container</div></li>
7758      * </ul></div>
7759      */
7760     /**
7761      * @cfg {Number} flex
7762      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
7763      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>
7764      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
7765      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
7766      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
7767      */
7768
7769     // private
7770     onLayout : function(ct, target){
7771         Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);
7772
7773         var cs = this.getItems(ct), cm, cw, margin, ch, diff,
7774             size = target.getViewSize(true),
7775             w = size.width - this.scrollOffset,
7776             h = size.height,
7777             l = this.padding.left, t = this.padding.top,
7778             isStart = this.pack == 'start',
7779             isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
7780             stretchHeight = h - (this.padding.top + this.padding.bottom),
7781             extraWidth = 0,
7782             maxHeight = 0,
7783             totalFlex = 0,
7784             flexWidth = 0,
7785             usedWidth = 0;
7786
7787         Ext.each(cs, function(c){
7788             cm = c.margins;
7789             totalFlex += c.flex || 0;
7790             cw = c.getWidth();
7791             margin = cm.left + cm.right;
7792             extraWidth += cw + margin;
7793             flexWidth += margin + (c.flex ? 0 : cw);
7794             maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom);
7795         });
7796         extraWidth = w - extraWidth - this.padding.left - this.padding.right;
7797
7798         var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom;
7799         switch(this.align){
7800             case 'stretch':
7801                 this.innerCt.setSize(w, h);
7802                 break;
7803             case 'stretchmax':
7804             case 'top':
7805                 this.innerCt.setSize(w, innerCtHeight);
7806                 break;
7807             case 'middle':
7808                 this.innerCt.setSize(w, h = Math.max(h, innerCtHeight));
7809                 break;
7810         }
7811
7812
7813         var availWidth = Math.max(0, w - this.padding.left - this.padding.right - flexWidth),
7814             leftOver = availWidth,
7815             widths = [],
7816             restore = [],
7817             idx = 0,
7818             availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom);
7819
7820
7821         Ext.each(cs, function(c){
7822             if(isStart && c.flex){
7823                 cw = Math.floor(availWidth * (c.flex / totalFlex));
7824                 leftOver -= cw;
7825                 widths.push(cw);
7826             }
7827         });
7828
7829         if(this.pack == 'center'){
7830             l += extraWidth ? extraWidth / 2 : 0;
7831         }else if(this.pack == 'end'){
7832             l += extraWidth;
7833         }
7834         Ext.each(cs, function(c){
7835             cm = c.margins;
7836             l += cm.left;
7837             c.setPosition(l, t + cm.top);
7838             if(isStart && c.flex){
7839                 cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0));
7840                 if(isRestore){
7841                     restore.push(c.getHeight());
7842                 }
7843                 c.setSize(cw, availableHeight);
7844             }else{
7845                 cw = c.getWidth();
7846             }
7847             l += cw + cm.right;
7848         });
7849
7850         idx = 0;
7851         Ext.each(cs, function(c){
7852             cm = c.margins;
7853             ch = c.getHeight();
7854             if(isStart && c.flex){
7855                 ch = restore[idx++];
7856             }
7857             if(this.align == 'stretch'){
7858                 c.setHeight((stretchHeight - (cm.top + cm.bottom)).constrain(
7859                     c.minHeight || 0, c.maxHeight || 1000000));
7860             }else if(this.align == 'stretchmax'){
7861                 c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain(
7862                     c.minHeight || 0, c.maxHeight || 1000000));
7863             }else{
7864                 if(this.align == 'middle'){
7865                     diff = availableHeight - (ch + cm.top + cm.bottom);
7866                     ch = t + cm.top + (diff/2);
7867                     if(diff > 0){
7868                         c.setPosition(c.x, ch);
7869                     }
7870                 }
7871                 if(isStart && c.flex){
7872                     c.setHeight(ch);
7873                 }
7874             }
7875         }, this);
7876     }
7877 });
7878
7879 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
7880 /**\r
7881  * @class Ext.Viewport\r
7882  * @extends Ext.Container\r
7883  * <p>A specialized container representing the viewable application area (the browser viewport).</p>\r
7884  * <p>The Viewport renders itself to the document body, and automatically sizes itself to the size of\r
7885  * the browser viewport and manages window resizing. There may only be one Viewport created\r
7886  * in a page. Inner layouts are available by virtue of the fact that all {@link Ext.Panel Panel}s\r
7887  * added to the Viewport, either through its {@link #items}, or through the items, or the {@link #add}\r
7888  * method of any of its child Panels may themselves have a layout.</p>\r
7889  * <p>The Viewport does not provide scrolling, so child Panels within the Viewport should provide\r
7890  * for scrolling if needed using the {@link #autoScroll} config.</p>\r
7891  * <p>An example showing a classic application border layout:</p><pre><code>\r
7892 new Ext.Viewport({\r
7893     layout: 'border',\r
7894     items: [{\r
7895         region: 'north',\r
7896         html: '&lt;h1 class="x-panel-header">Page Title&lt;/h1>',\r
7897         autoHeight: true,\r
7898         border: false,\r
7899         margins: '0 0 5 0'\r
7900     }, {\r
7901         region: 'west',\r
7902         collapsible: true,\r
7903         title: 'Navigation',\r
7904         width: 200\r
7905         // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout}\r
7906     }, {\r
7907         region: 'south',\r
7908         title: 'Title for Panel',\r
7909         collapsible: true,\r
7910         html: 'Information goes here',\r
7911         split: true,\r
7912         height: 100,\r
7913         minHeight: 100\r
7914     }, {\r
7915         region: 'east',\r
7916         title: 'Title for the Grid Panel',\r
7917         collapsible: true,\r
7918         split: true,\r
7919         width: 200,\r
7920         xtype: 'grid',\r
7921         // remaining grid configuration not shown ...\r
7922         // notice that the GridPanel is added directly as the region\r
7923         // it is not "overnested" inside another Panel\r
7924     }, {\r
7925         region: 'center',\r
7926         xtype: 'tabpanel', // TabPanel itself has no title\r
7927         items: {\r
7928             title: 'Default Tab',\r
7929             html: 'The first tab\'s content. Others may be added dynamically'\r
7930         }\r
7931     }]\r
7932 });\r
7933 </code></pre>\r
7934  * @constructor\r
7935  * Create a new Viewport\r
7936  * @param {Object} config The config object\r
7937  * @xtype viewport\r
7938  */\r
7939 Ext.Viewport = Ext.extend(Ext.Container, {\r
7940     /*\r
7941      * Privatize config options which, if used, would interfere with the\r
7942      * correct operation of the Viewport as the sole manager of the\r
7943      * layout of the document body.\r
7944      */\r
7945     /**\r
7946      * @cfg {Mixed} applyTo @hide\r
7947      */\r
7948     /**\r
7949      * @cfg {Boolean} allowDomMove @hide\r
7950      */\r
7951     /**\r
7952      * @cfg {Boolean} hideParent @hide\r
7953      */\r
7954     /**\r
7955      * @cfg {Mixed} renderTo @hide\r
7956      */\r
7957     /**\r
7958      * @cfg {Boolean} hideParent @hide\r
7959      */\r
7960     /**\r
7961      * @cfg {Number} height @hide\r
7962      */\r
7963     /**\r
7964      * @cfg {Number} width @hide\r
7965      */\r
7966     /**\r
7967      * @cfg {Boolean} autoHeight @hide\r
7968      */\r
7969     /**\r
7970      * @cfg {Boolean} autoWidth @hide\r
7971      */\r
7972     /**\r
7973      * @cfg {Boolean} deferHeight @hide\r
7974      */\r
7975     /**\r
7976      * @cfg {Boolean} monitorResize @hide\r
7977      */\r
7978 \r
7979     initComponent : function() {\r
7980         Ext.Viewport.superclass.initComponent.call(this);\r
7981         document.getElementsByTagName('html')[0].className += ' x-viewport';\r
7982         this.el = Ext.getBody();\r
7983         this.el.setHeight = Ext.emptyFn;\r
7984         this.el.setWidth = Ext.emptyFn;\r
7985         this.el.setSize = Ext.emptyFn;\r
7986         this.el.dom.scroll = 'no';\r
7987         this.allowDomMove = false;\r
7988         this.autoWidth = true;\r
7989         this.autoHeight = true;\r
7990         Ext.EventManager.onWindowResize(this.fireResize, this);\r
7991         this.renderTo = this.el;\r
7992     },\r
7993 \r
7994     fireResize : function(w, h){\r
7995         this.onResize(w, h, w, h);\r
7996     }\r
7997 });\r
7998 Ext.reg('viewport', Ext.Viewport);\r
7999 /**
8000  * @class Ext.Panel
8001  * @extends Ext.Container
8002  * <p>Panel is a container that has specific functionality and structural components that make
8003  * it the perfect building block for application-oriented user interfaces.</p>
8004  * <p>Panels are, by virtue of their inheritance from {@link Ext.Container}, capable
8005  * of being configured with a {@link Ext.Container#layout layout}, and containing child Components.</p>
8006  * <p>When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.Container#add adding} Components
8007  * to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether
8008  * those child elements need to be sized using one of Ext's built-in <code><b>{@link Ext.Container#layout layout}</b></code> schemes. By
8009  * default, Panels use the {@link Ext.layout.ContainerLayout ContainerLayout} scheme. This simply renders
8010  * child components, appending them one after the other inside the Container, and <b>does not apply any sizing</b>
8011  * at all.</p>
8012  * <p>A Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate
8013  * {@link #header}, {@link #footer} and {@link #body} sections (see {@link #frame} for additional
8014  * information).</p>
8015  * <p>Panel also provides built-in {@link #collapsible expandable and collapsible behavior}, along with
8016  * a variety of {@link #tools prebuilt tool buttons} that can be wired up to provide other customized
8017  * behavior.  Panels can be easily dropped into any {@link Ext.Container Container} or layout, and the
8018  * layout and rendering pipeline is {@link Ext.Container#add completely managed by the framework}.</p>
8019  * @constructor
8020  * @param {Object} config The config object
8021  * @xtype panel
8022  */
8023 Ext.Panel = Ext.extend(Ext.Container, {
8024     /**
8025      * The Panel's header {@link Ext.Element Element}. Read-only.
8026      * <p>This Element is used to house the {@link #title} and {@link #tools}</p>
8027      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
8028      * @type Ext.Element
8029      * @property header
8030      */
8031     /**
8032      * The Panel's body {@link Ext.Element Element} which may be used to contain HTML content.
8033      * The content may be specified in the {@link #html} config, or it may be loaded using the
8034      * {@link autoLoad} config, or through the Panel's {@link #getUpdater Updater}. Read-only.
8035      * <p>If this is used to load visible HTML elements in either way, then
8036      * the Panel may not be used as a Layout for hosting nested Panels.</p>
8037      * <p>If this Panel is intended to be used as the host of a Layout (See {@link #layout}
8038      * then the body Element must not be loaded or changed - it is under the control
8039      * of the Panel's Layout.
8040      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
8041      * @type Ext.Element
8042      * @property body
8043      */
8044     /**
8045      * The Panel's bwrap {@link Ext.Element Element} used to contain other Panel elements
8046      * (tbar, body, bbar, footer). See {@link #bodyCfg}. Read-only.
8047      * @type Ext.Element
8048      * @property bwrap
8049      */
8050     /**
8051      * True if this panel is collapsed. Read-only.
8052      * @type Boolean
8053      * @property collapsed
8054      */
8055     /**
8056      * @cfg {Object} bodyCfg
8057      * <p>A {@link Ext.DomHelper DomHelper} element specification object may be specified for any
8058      * Panel Element.</p>
8059      * <p>By default, the Default element in the table below will be used for the html markup to
8060      * create a child element with the commensurate Default class name (<code>baseCls</code> will be
8061      * replaced by <code>{@link #baseCls}</code>):</p>
8062      * <pre>
8063      * Panel      Default  Default             Custom      Additional       Additional
8064      * Element    element  class               element     class            style
8065      * ========   ==========================   =========   ==============   ===========
8066      * {@link #header}     div      {@link #baseCls}+'-header'   {@link #headerCfg}   headerCssClass   headerStyle
8067      * {@link #bwrap}      div      {@link #baseCls}+'-bwrap'     {@link #bwrapCfg}    bwrapCssClass    bwrapStyle
8068      * + tbar     div      {@link #baseCls}+'-tbar'       {@link #tbarCfg}     tbarCssClass     tbarStyle
8069      * + {@link #body}     div      {@link #baseCls}+'-body'       {@link #bodyCfg}     {@link #bodyCssClass}     {@link #bodyStyle}
8070      * + bbar     div      {@link #baseCls}+'-bbar'       {@link #bbarCfg}     bbarCssClass     bbarStyle
8071      * + {@link #footer}   div      {@link #baseCls}+'-footer'   {@link #footerCfg}   footerCssClass   footerStyle
8072      * </pre>
8073      * <p>Configuring a Custom element may be used, for example, to force the {@link #body} Element
8074      * to use a different form of markup than is created by default. An example of this might be
8075      * to {@link Ext.Element#createChild create a child} Panel containing a custom content, such as
8076      * a header, or forcing centering of all Panel content by having the body be a &lt;center&gt;
8077      * element:</p>
8078      * <pre><code>
8079 new Ext.Panel({
8080     title: 'Message Title',
8081     renderTo: Ext.getBody(),
8082     width: 200, height: 130,
8083     <b>bodyCfg</b>: {
8084         tag: 'center',
8085         cls: 'x-panel-body',  // Default class not applied if Custom element specified
8086         html: 'Message'
8087     },
8088     footerCfg: {
8089         tag: 'h2',
8090         cls: 'x-panel-footer'        // same as the Default class
8091         html: 'footer html'
8092     },
8093     footerCssClass: 'custom-footer', // additional css class, see {@link Ext.element#addClass addClass}
8094     footerStyle:    'background-color:red' // see {@link #bodyStyle}
8095 });
8096      * </code></pre>
8097      * <p>The example above also explicitly creates a <code>{@link #footer}</code> with custom markup and
8098      * styling applied.</p>
8099      */
8100     /**
8101      * @cfg {Object} headerCfg
8102      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
8103      * of this Panel's {@link #header} Element.  See <code>{@link #bodyCfg}</code> also.</p>
8104      */
8105     /**
8106      * @cfg {Object} bwrapCfg
8107      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
8108      * of this Panel's {@link #bwrap} Element.  See <code>{@link #bodyCfg}</code> also.</p>
8109      */
8110     /**
8111      * @cfg {Object} tbarCfg
8112      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
8113      * of this Panel's {@link #tbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
8114      */
8115     /**
8116      * @cfg {Object} bbarCfg
8117      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
8118      * of this Panel's {@link #bbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
8119      */
8120     /**
8121      * @cfg {Object} footerCfg
8122      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
8123      * of this Panel's {@link #footer} Element.  See <code>{@link #bodyCfg}</code> also.</p>
8124      */
8125     /**
8126      * @cfg {Boolean} closable
8127      * Panels themselves do not directly support being closed, but some Panel subclasses do (like
8128      * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}.  Specify <code>true</code>
8129      * to enable closing in such situations. Defaults to <code>false</code>.
8130      */
8131     /**
8132      * The Panel's footer {@link Ext.Element Element}. Read-only.
8133      * <p>This Element is used to house the Panel's <code>{@link #buttons}</code> or <code>{@link #fbar}</code>.</p>
8134      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
8135      * @type Ext.Element
8136      * @property footer
8137      */
8138     /**
8139      * @cfg {Mixed} applyTo
8140      * <p>The id of the node, a DOM node or an existing Element corresponding to a DIV that is already present in
8141      * the document that specifies some panel-specific structural markup.  When <code>applyTo</code> is used,
8142      * constituent parts of the panel can be specified by CSS class name within the main element, and the panel
8143      * will automatically create those components from that markup. Any required components not specified in the
8144      * markup will be autogenerated if necessary.</p>
8145      * <p>The following class names are supported (baseCls will be replaced by {@link #baseCls}):</p>
8146      * <ul><li>baseCls + '-header'</li>
8147      * <li>baseCls + '-header-text'</li>
8148      * <li>baseCls + '-bwrap'</li>
8149      * <li>baseCls + '-tbar'</li>
8150      * <li>baseCls + '-body'</li>
8151      * <li>baseCls + '-bbar'</li>
8152      * <li>baseCls + '-footer'</li></ul>
8153      * <p>Using this config, a call to render() is not required.  If applyTo is specified, any value passed for
8154      * {@link #renderTo} will be ignored and the target element's parent node will automatically be used as the
8155      * panel's container.</p>
8156      */
8157     /**
8158      * @cfg {Object/Array} tbar
8159      * <p>The top toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
8160      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
8161      * To access the top toolbar after render, use {@link #getTopToolbar}.</p>
8162      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
8163      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
8164      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
8165      * submission parameters are collected from the DOM tree.</p>
8166      */
8167     /**
8168      * @cfg {Object/Array} bbar
8169      * <p>The bottom toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
8170      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
8171      * To access the bottom toolbar after render, use {@link #getBottomToolbar}.</p>
8172      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
8173      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
8174      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
8175      * submission parameters are collected from the DOM tree.</p>
8176      */
8177     /** @cfg {Object/Array} fbar
8178      * <p>A {@link Ext.Toolbar Toolbar} object, a Toolbar config, or an array of
8179      * {@link Ext.Button Button}s/{@link Ext.Button Button} configs, describing a {@link Ext.Toolbar Toolbar} to be rendered into this Panel's footer element.</p>
8180      * <p>After render, the <code>fbar</code> property will be an {@link Ext.Toolbar Toolbar} instance.</p>
8181      * <p>If <code>{@link #buttons}</code> are specified, they will supersede the <code>fbar</code> configuration property.</p>
8182      * The Panel's <code>{@link #buttonAlign}</code> configuration affects the layout of these items, for example:
8183      * <pre><code>
8184 var w = new Ext.Window({
8185     height: 250,
8186     width: 500,
8187     bbar: new Ext.Toolbar({
8188         items: [{
8189             text: 'bbar Left'
8190         },'->',{
8191             text: 'bbar Right'
8192         }]
8193     }),
8194     {@link #buttonAlign}: 'left', // anything but 'center' or 'right' and you can use '-', and '->'
8195                                   // to control the alignment of fbar items
8196     fbar: [{
8197         text: 'fbar Left'
8198     },'->',{
8199         text: 'fbar Right'
8200     }]
8201 }).show();
8202      * </code></pre>
8203      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
8204      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
8205      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
8206      * submission parameters are collected from the DOM tree.</p>
8207      */
8208     /**
8209      * @cfg {Boolean} header
8210      * <code>true</code> to create the Panel's header element explicitly, <code>false</code> to skip creating
8211      * it.  If a <code>{@link #title}</code> is set the header will be created automatically, otherwise it will not.
8212      * If a <code>{@link #title}</code> is set but <code>header</code> is explicitly set to <code>false</code>, the header
8213      * will not be rendered.
8214      */
8215     /**
8216      * @cfg {Boolean} footer
8217      * <code>true</code> to create the footer element explicitly, false to skip creating it. The footer
8218      * will be created automatically if <code>{@link #buttons}</code> or a <code>{@link #fbar}</code> have
8219      * been configured.  See <code>{@link #bodyCfg}</code> for an example.
8220      */
8221     /**
8222      * @cfg {String} title
8223      * The title text to be used as innerHTML (html tags are accepted) to display in the panel
8224      * <code>{@link #header}</code> (defaults to ''). When a <code>title</code> is specified the
8225      * <code>{@link #header}</code> element will automatically be created and displayed unless
8226      * {@link #header} is explicitly set to <code>false</code>.  If you do not want to specify a
8227      * <code>title</code> at config time, but you may want one later, you must either specify a non-empty
8228      * <code>title</code> (a blank space ' ' will do) or <code>header:true</code> so that the container
8229      * element will get created.
8230      */
8231     /**
8232      * @cfg {Array} buttons
8233      * <code>buttons</code> will be used as <code>{@link Ext.Container#items items}</code> for the toolbar in
8234      * the footer (<code>{@link #fbar}</code>). Typically the value of this configuration property will be
8235      * an array of {@link Ext.Button}s or {@link Ext.Button} configuration objects.
8236      * If an item is configured with <code>minWidth</code> or the Panel is configured with <code>minButtonWidth</code>,
8237      * that width will be applied to the item.
8238      */
8239     /**
8240      * @cfg {Object/String/Function} autoLoad
8241      * A valid url spec according to the Updater {@link Ext.Updater#update} method.
8242      * If autoLoad is not null, the panel will attempt to load its contents
8243      * immediately upon render.<p>
8244      * The URL will become the default URL for this panel's {@link #body} element,
8245      * so it may be {@link Ext.Element#refresh refresh}ed at any time.</p>
8246      */
8247     /**
8248      * @cfg {Boolean} frame
8249      * <code>false</code> by default to render with plain 1px square borders. <code>true</code> to render with
8250      * 9 elements, complete with custom rounded corners (also see {@link Ext.Element#boxWrap}).
8251      * <p>The template generated for each condition is depicted below:</p><pre><code>
8252      *
8253 // frame = false
8254 &lt;div id="developer-specified-id-goes-here" class="x-panel">
8255
8256     &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:false)&lt;/span>&lt;/div>
8257
8258     &lt;div class="x-panel-bwrap">
8259         &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
8260     &lt;/div>
8261 &lt;/div>
8262
8263 // frame = true (create 9 elements)
8264 &lt;div id="developer-specified-id-goes-here" class="x-panel">
8265     &lt;div class="x-panel-tl">&lt;div class="x-panel-tr">&lt;div class="x-panel-tc">
8266         &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:true)&lt;/span>&lt;/div>
8267     &lt;/div>&lt;/div>&lt;/div>
8268
8269     &lt;div class="x-panel-bwrap">
8270         &lt;div class="x-panel-ml">&lt;div class="x-panel-mr">&lt;div class="x-panel-mc">
8271             &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
8272         &lt;/div>&lt;/div>&lt;/div>
8273
8274         &lt;div class="x-panel-bl">&lt;div class="x-panel-br">&lt;div class="x-panel-bc"/>
8275         &lt;/div>&lt;/div>&lt;/div>
8276 &lt;/div>
8277      * </code></pre>
8278      */
8279     /**
8280      * @cfg {Boolean} border
8281      * True to display the borders of the panel's body element, false to hide them (defaults to true).  By default,
8282      * the border is a 2px wide inset border, but this can be further altered by setting {@link #bodyBorder} to false.
8283      */
8284     /**
8285      * @cfg {Boolean} bodyBorder
8286      * True to display an interior border on the body element of the panel, false to hide it (defaults to true).
8287      * This only applies when {@link #border} == true.  If border == true and bodyBorder == false, the border will display
8288      * as a 1px wide inset border, giving the entire body element an inset appearance.
8289      */
8290     /**
8291      * @cfg {String/Object/Function} bodyCssClass
8292      * Additional css class selector to be applied to the {@link #body} element in the format expected by
8293      * {@link Ext.Element#addClass} (defaults to null). See {@link #bodyCfg}.
8294      */
8295     /**
8296      * @cfg {String/Object/Function} bodyStyle
8297      * Custom CSS styles to be applied to the {@link #body} element in the format expected by
8298      * {@link Ext.Element#applyStyles} (defaults to null). See {@link #bodyCfg}.
8299      */
8300     /**
8301      * @cfg {String} iconCls
8302      * The CSS class selector that specifies a background image to be used as the header icon (defaults to '').
8303      * <p>An example of specifying a custom icon class would be something like:
8304      * </p><pre><code>
8305 // specify the property in the config for the class:
8306      ...
8307      iconCls: 'my-icon'
8308
8309 // css class that specifies background image to be used as the icon image:
8310 .my-icon { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
8311 </code></pre>
8312      */
8313     /**
8314      * @cfg {Boolean} collapsible
8315      * True to make the panel collapsible and have the expand/collapse toggle button automatically rendered into
8316      * the header tool button area, false to keep the panel statically sized with no button (defaults to false).
8317      */
8318     /**
8319      * @cfg {Array} tools
8320      * An array of tool button configs to be added to the header tool area. When rendered, each tool is
8321      * stored as an {@link Ext.Element Element} referenced by a public property called <code><b></b>tools.<i>&lt;tool-type&gt;</i></code>
8322      * <p>Each tool config may contain the following properties:
8323      * <div class="mdetail-params"><ul>
8324      * <li><b>id</b> : String<div class="sub-desc"><b>Required.</b> The type
8325      * of tool to create. By default, this assigns a CSS class of the form <code>x-tool-<i>&lt;tool-type&gt;</i></code> to the
8326      * resulting tool Element. Ext provides CSS rules, and an icon sprite containing images for the tool types listed below.
8327      * The developer may implement custom tools by supplying alternate CSS rules and background images:
8328      * <ul>
8329      * <div class="x-tool x-tool-toggle" style="float:left; margin-right:5;"> </div><div><code> toggle</code> (Created by default when {@link #collapsible} is <code>true</code>)</div>
8330      * <div class="x-tool x-tool-close" style="float:left; margin-right:5;"> </div><div><code> close</code></div>
8331      * <div class="x-tool x-tool-minimize" style="float:left; margin-right:5;"> </div><div><code> minimize</code></div>
8332      * <div class="x-tool x-tool-maximize" style="float:left; margin-right:5;"> </div><div><code> maximize</code></div>
8333      * <div class="x-tool x-tool-restore" style="float:left; margin-right:5;"> </div><div><code> restore</code></div>
8334      * <div class="x-tool x-tool-gear" style="float:left; margin-right:5;"> </div><div><code> gear</code></div>
8335      * <div class="x-tool x-tool-pin" style="float:left; margin-right:5;"> </div><div><code> pin</code></div>
8336      * <div class="x-tool x-tool-unpin" style="float:left; margin-right:5;"> </div><div><code> unpin</code></div>
8337      * <div class="x-tool x-tool-right" style="float:left; margin-right:5;"> </div><div><code> right</code></div>
8338      * <div class="x-tool x-tool-left" style="float:left; margin-right:5;"> </div><div><code> left</code></div>
8339      * <div class="x-tool x-tool-up" style="float:left; margin-right:5;"> </div><div><code> up</code></div>
8340      * <div class="x-tool x-tool-down" style="float:left; margin-right:5;"> </div><div><code> down</code></div>
8341      * <div class="x-tool x-tool-refresh" style="float:left; margin-right:5;"> </div><div><code> refresh</code></div>
8342      * <div class="x-tool x-tool-minus" style="float:left; margin-right:5;"> </div><div><code> minus</code></div>
8343      * <div class="x-tool x-tool-plus" style="float:left; margin-right:5;"> </div><div><code> plus</code></div>
8344      * <div class="x-tool x-tool-help" style="float:left; margin-right:5;"> </div><div><code> help</code></div>
8345      * <div class="x-tool x-tool-search" style="float:left; margin-right:5;"> </div><div><code> search</code></div>
8346      * <div class="x-tool x-tool-save" style="float:left; margin-right:5;"> </div><div><code> save</code></div>
8347      * <div class="x-tool x-tool-print" style="float:left; margin-right:5;"> </div><div><code> print</code></div>
8348      * </ul></div></li>
8349      * <li><b>handler</b> : Function<div class="sub-desc"><b>Required.</b> The function to
8350      * call when clicked. Arguments passed are:<ul>
8351      * <li><b>event</b> : Ext.EventObject<div class="sub-desc">The click event.</div></li>
8352      * <li><b>toolEl</b> : Ext.Element<div class="sub-desc">The tool Element.</div></li>
8353      * <li><b>panel</b> : Ext.Panel<div class="sub-desc">The host Panel</div></li>
8354      * <li><b>tc</b> : Object<div class="sub-desc">The tool configuration object</div></li>
8355      * </ul></div></li>
8356      * <li><b>stopEvent</b> : Boolean<div class="sub-desc">Defaults to true. Specify as false to allow click event to propagate.</div></li>
8357      * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the handler.</div></li>
8358      * <li><b>qtip</b> : String/Object<div class="sub-desc">A tip string, or
8359      * a config argument to {@link Ext.QuickTip#register}</div></li>
8360      * <li><b>hidden</b> : Boolean<div class="sub-desc">True to initially render hidden.</div></li>
8361      * <li><b>on</b> : Object<div class="sub-desc">A listener config object specifiying
8362      * event listeners in the format of an argument to {@link #addListener}</div></li>
8363      * </ul></div>
8364      * <p>Note that, apart from the toggle tool which is provided when a panel is collapsible, these
8365      * tools only provide the visual button. Any required functionality must be provided by adding
8366      * handlers that implement the necessary behavior.</p>
8367      * <p>Example usage:</p>
8368      * <pre><code>
8369 tools:[{
8370     id:'refresh',
8371     qtip: 'Refresh form Data',
8372     // hidden:true,
8373     handler: function(event, toolEl, panel){
8374         // refresh logic
8375     }
8376 },
8377 {
8378     id:'help',
8379     qtip: 'Get Help',
8380     handler: function(event, toolEl, panel){
8381         // whatever
8382     }
8383 }]
8384 </code></pre>
8385      * <p>For the custom id of <code>'help'</code> define two relevant css classes with a link to
8386      * a 15x15 image:</p>
8387      * <pre><code>
8388 .x-tool-help {background-image: url(images/help.png);}
8389 .x-tool-help-over {background-image: url(images/help_over.png);}
8390 // if using an image sprite:
8391 .x-tool-help {background-image: url(images/help.png) no-repeat 0 0;}
8392 .x-tool-help-over {background-position:-15px 0;}
8393 </code></pre>
8394      */
8395     /**
8396      * @cfg {Ext.Template/Ext.XTemplate} toolTemplate
8397      * <p>A Template used to create {@link #tools} in the {@link #header} Element. Defaults to:</p><pre><code>
8398 new Ext.Template('&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>')</code></pre>
8399      * <p>This may may be overridden to provide a custom DOM structure for tools based upon a more
8400      * complex XTemplate. The template's data is a single tool configuration object (Not the entire Array)
8401      * as specified in {@link #tools}.  In the following example an &lt;a> tag is used to provide a
8402      * visual indication when hovering over the tool:</p><pre><code>
8403 var win = new Ext.Window({
8404     tools: [{
8405         id: 'download',
8406         href: '/MyPdfDoc.pdf'
8407     }],
8408     toolTemplate: new Ext.XTemplate(
8409         '&lt;tpl if="id==\'download\'">',
8410             '&lt;a class="x-tool x-tool-pdf" href="{href}">&lt;/a>',
8411         '&lt;/tpl>',
8412         '&lt;tpl if="id!=\'download\'">',
8413             '&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>',
8414         '&lt;/tpl>'
8415     ),
8416     width:500,
8417     height:300,
8418     closeAction:'hide'
8419 });</code></pre>
8420      * <p>Note that the CSS class 'x-tool-pdf' should have an associated style rule which provides an
8421      * appropriate background image, something like:</p>
8422     <pre><code>
8423     a.x-tool-pdf {background-image: url(../shared/extjs/images/pdf.gif)!important;}
8424     </code></pre>
8425      */
8426     /**
8427      * @cfg {Boolean} hideCollapseTool
8428      * <code>true</code> to hide the expand/collapse toggle button when <code>{@link #collapsible} == true</code>,
8429      * <code>false</code> to display it (defaults to <code>false</code>).
8430      */
8431     /**
8432      * @cfg {Boolean} titleCollapse
8433      * <code>true</code> to allow expanding and collapsing the panel (when <code>{@link #collapsible} = true</code>)
8434      * by clicking anywhere in the header bar, <code>false</code>) to allow it only by clicking to tool button
8435      * (defaults to <code>false</code>)). If this panel is a child item of a border layout also see the
8436      * {@link Ext.layout.BorderLayout.Region BorderLayout.Region}
8437      * <code>{@link Ext.layout.BorderLayout.Region#floatable floatable}</code> config option.
8438      */
8439
8440     /**
8441      * @cfg {Mixed} floating
8442      * <p>This property is used to configure the underlying {@link Ext.Layer}. Acceptable values for this
8443      * configuration property are:</p><div class="mdetail-params"><ul>
8444      * <li><b><code>false</code></b> : <b>Default.</b><div class="sub-desc">Display the panel inline where it is
8445      * rendered.</div></li>
8446      * <li><b><code>true</code></b> : <div class="sub-desc">Float the panel (absolute position it with automatic
8447      * shimming and shadow).<ul>
8448      * <div class="sub-desc">Setting floating to true will create an Ext.Layer for this panel and display the
8449      * panel at negative offsets so that it is hidden.</div>
8450      * <div class="sub-desc">Since the panel will be absolute positioned, the position must be set explicitly
8451      * <i>after</i> render (e.g., <code>myPanel.setPosition(100,100);</code>).</div>
8452      * <div class="sub-desc"><b>Note</b>: when floating a panel you should always assign a fixed width,
8453      * otherwise it will be auto width and will expand to fill to the right edge of the viewport.</div>
8454      * </ul></div></li>
8455      * <li><b><code>{@link Ext.Layer object}</code></b> : <div class="sub-desc">The specified object will be used
8456      * as the configuration object for the {@link Ext.Layer} that will be created.</div></li>
8457      * </ul></div>
8458      */
8459     /**
8460      * @cfg {Boolean/String} shadow
8461      * <code>true</code> (or a valid Ext.Shadow {@link Ext.Shadow#mode} value) to display a shadow behind the
8462      * panel, <code>false</code> to display no shadow (defaults to <code>'sides'</code>).  Note that this option
8463      * only applies when <code>{@link #floating} = true</code>.
8464      */
8465     /**
8466      * @cfg {Number} shadowOffset
8467      * The number of pixels to offset the shadow if displayed (defaults to <code>4</code>). Note that this
8468      * option only applies when <code>{@link #floating} = true</code>.
8469      */
8470     /**
8471      * @cfg {Boolean} shim
8472      * <code>false</code> to disable the iframe shim in browsers which need one (defaults to <code>true</code>).
8473      * Note that this option only applies when <code>{@link #floating} = true</code>.
8474      */
8475     /**
8476      * @cfg {Object/Array} keys
8477      * A {@link Ext.KeyMap} config object (in the format expected by {@link Ext.KeyMap#addBinding}
8478      * used to assign custom key handling to this panel (defaults to <code>null</code>).
8479      */
8480     /**
8481      * @cfg {Boolean/Object} draggable
8482      * <p><code>true</code> to enable dragging of this Panel (defaults to <code>false</code>).</p>
8483      * <p>For custom drag/drop implementations, an <b>Ext.Panel.DD</b> config could also be passed
8484      * in this config instead of <code>true</code>. Ext.Panel.DD is an internal, undocumented class which
8485      * moves a proxy Element around in place of the Panel's element, but provides no other behaviour
8486      * during dragging or on drop. It is a subclass of {@link Ext.dd.DragSource}, so behaviour may be
8487      * added by implementing the interface methods of {@link Ext.dd.DragDrop} e.g.:
8488      * <pre><code>
8489 new Ext.Panel({
8490     title: 'Drag me',
8491     x: 100,
8492     y: 100,
8493     renderTo: Ext.getBody(),
8494     floating: true,
8495     frame: true,
8496     width: 400,
8497     height: 200,
8498     draggable: {
8499 //      Config option of Ext.Panel.DD class.
8500 //      It&#39;s a floating Panel, so do not show a placeholder proxy in the original position.
8501         insertProxy: false,
8502
8503 //      Called for each mousemove event while dragging the DD object.
8504         onDrag : function(e){
8505 //          Record the x,y position of the drag proxy so that we can
8506 //          position the Panel at end of drag.
8507             var pel = this.proxy.getEl();
8508             this.x = pel.getLeft(true);
8509             this.y = pel.getTop(true);
8510
8511 //          Keep the Shadow aligned if there is one.
8512             var s = this.panel.getEl().shadow;
8513             if (s) {
8514                 s.realign(this.x, this.y, pel.getWidth(), pel.getHeight());
8515             }
8516         },
8517
8518 //      Called on the mouseup event.
8519         endDrag : function(e){
8520             this.panel.setPosition(this.x, this.y);
8521         }
8522     }
8523 }).show();
8524 </code></pre>
8525      */
8526     /**
8527      * @cfg {Boolean} disabled
8528      * Render this panel disabled (default is <code>false</code>). An important note when using the disabled
8529      * config on panels is that IE will often fail to initialize the disabled mask element correectly if
8530      * the panel's layout has not yet completed by the time the Panel is disabled during the render process.
8531      * If you experience this issue, you may need to instead use the {@link #afterlayout} event to initialize
8532      * the disabled state:
8533      * <pre><code>
8534 new Ext.Panel({
8535     ...
8536     listeners: {
8537         'afterlayout': {
8538             fn: function(p){
8539                 p.disable();
8540             },
8541             single: true // important, as many layouts can occur
8542         }
8543     }
8544 });
8545 </code></pre>
8546      */
8547     /**
8548      * @cfg {Boolean} autoHeight
8549      * <code>true</code> to use height:'auto', <code>false</code> to use fixed height (defaults to <code>false</code>).
8550      * <b>Note</b>: Setting <code>autoHeight: true</code> means that the browser will manage the panel's height
8551      * based on its contents, and that Ext will not manage it at all. If the panel is within a layout that
8552      * manages dimensions (<code>fit</code>, <code>border</code>, etc.) then setting <code>autoHeight: true</code>
8553      * can cause issues with scrolling and will not generally work as expected since the panel will take
8554      * on the height of its contents rather than the height required by the Ext layout.
8555      */
8556
8557
8558     /**
8559      * @cfg {String} baseCls
8560      * The base CSS class to apply to this panel's element (defaults to <code>'x-panel'</code>).
8561      * <p>Another option available by default is to specify <code>'x-plain'</code> which strips all styling
8562      * except for required attributes for Ext layouts to function (e.g. overflow:hidden).
8563      * See <code>{@link #unstyled}</code> also.</p>
8564      */
8565     baseCls : 'x-panel',
8566     /**
8567      * @cfg {String} collapsedCls
8568      * A CSS class to add to the panel's element after it has been collapsed (defaults to
8569      * <code>'x-panel-collapsed'</code>).
8570      */
8571     collapsedCls : 'x-panel-collapsed',
8572     /**
8573      * @cfg {Boolean} maskDisabled
8574      * <code>true</code> to mask the panel when it is {@link #disabled}, <code>false</code> to not mask it (defaults
8575      * to <code>true</code>).  Either way, the panel will always tell its contained elements to disable themselves
8576      * when it is disabled, but masking the panel can provide an additional visual cue that the panel is
8577      * disabled.
8578      */
8579     maskDisabled : true,
8580     /**
8581      * @cfg {Boolean} animCollapse
8582      * <code>true</code> to animate the transition when the panel is collapsed, <code>false</code> to skip the
8583      * animation (defaults to <code>true</code> if the {@link Ext.Fx} class is available, otherwise <code>false</code>).
8584      */
8585     animCollapse : Ext.enableFx,
8586     /**
8587      * @cfg {Boolean} headerAsText
8588      * <code>true</code> to display the panel <code>{@link #title}</code> in the <code>{@link #header}</code>,
8589      * <code>false</code> to hide it (defaults to <code>true</code>).
8590      */
8591     headerAsText : true,
8592     /**
8593      * @cfg {String} buttonAlign
8594      * The alignment of any {@link #buttons} added to this panel.  Valid values are <code>'right'</code>,
8595      * <code>'left'</code> and <code>'center'</code> (defaults to <code>'right'</code>).
8596      */
8597     buttonAlign : 'right',
8598     /**
8599      * @cfg {Boolean} collapsed
8600      * <code>true</code> to render the panel collapsed, <code>false</code> to render it expanded (defaults to
8601      * <code>false</code>).
8602      */
8603     collapsed : false,
8604     /**
8605      * @cfg {Boolean} collapseFirst
8606      * <code>true</code> to make sure the collapse/expand toggle button always renders first (to the left of)
8607      * any other tools in the panel's title bar, <code>false</code> to render it last (defaults to <code>true</code>).
8608      */
8609     collapseFirst : true,
8610     /**
8611      * @cfg {Number} minButtonWidth
8612      * Minimum width in pixels of all {@link #buttons} in this panel (defaults to <code>75</code>)
8613      */
8614     minButtonWidth : 75,
8615     /**
8616      * @cfg {Boolean} unstyled
8617      * Overrides the <code>{@link #baseCls}</code> setting to <code>{@link #baseCls} = 'x-plain'</code> which renders
8618      * the panel unstyled except for required attributes for Ext layouts to function (e.g. overflow:hidden).
8619      */
8620     /**
8621      * @cfg {String} elements
8622      * A comma-delimited list of panel elements to initialize when the panel is rendered.  Normally, this list will be
8623      * generated automatically based on the items added to the panel at config time, but sometimes it might be useful to
8624      * make sure a structural element is rendered even if not specified at config time (for example, you may want
8625      * to add a button or toolbar dynamically after the panel has been rendered).  Adding those elements to this
8626      * list will allocate the required placeholders in the panel when it is rendered.  Valid values are<div class="mdetail-params"><ul>
8627      * <li><code>header</code></li>
8628      * <li><code>tbar</code> (top bar)</li>
8629      * <li><code>body</code></li>
8630      * <li><code>bbar</code> (bottom bar)</li>
8631      * <li><code>footer</code></li>
8632      * </ul></div>
8633      * Defaults to '<code>body</code>'.
8634      */
8635     elements : 'body',
8636     /**
8637      * @cfg {Boolean} preventBodyReset
8638      * Defaults to <code>false</code>.  When set to <code>true</code>, an extra css class <code>'x-panel-normal'</code>
8639      * will be added to the panel's element, effectively applying css styles suggested by the W3C
8640      * (see http://www.w3.org/TR/CSS21/sample.html) to the Panel's <b>body</b> element (not the header,
8641      * footer, etc.).
8642      */
8643     preventBodyReset : false,
8644
8645     /**
8646      * @cfg {Number/String} padding
8647      * A shortcut for setting a padding style on the body element. The value can either be
8648      * a number to be applied to all sides, or a normal css string describing padding.
8649      * Defaults to <tt>undefined</tt>.
8650      *
8651      */
8652     padding: undefined,
8653
8654     /** @cfg {String} resizeEvent
8655      * The event to listen to for resizing in layouts. Defaults to <tt>'bodyresize'</tt>.
8656      */
8657     resizeEvent: 'bodyresize',
8658
8659     // protected - these could be used to customize the behavior of the window,
8660     // but changing them would not be useful without further mofifications and
8661     // could lead to unexpected or undesirable results.
8662     toolTarget : 'header',
8663     collapseEl : 'bwrap',
8664     slideAnchor : 't',
8665     disabledClass : '',
8666
8667     // private, notify box this class will handle heights
8668     deferHeight : true,
8669     // private
8670     expandDefaults: {
8671         duration : 0.25
8672     },
8673     // private
8674     collapseDefaults : {
8675         duration : 0.25
8676     },
8677
8678     // private
8679     initComponent : function(){
8680         Ext.Panel.superclass.initComponent.call(this);
8681
8682         this.addEvents(
8683             /**
8684              * @event bodyresize
8685              * Fires after the Panel has been resized.
8686              * @param {Ext.Panel} p the Panel which has been resized.
8687              * @param {Number} width The Panel's new width.
8688              * @param {Number} height The Panel's new height.
8689              */
8690             'bodyresize',
8691             /**
8692              * @event titlechange
8693              * Fires after the Panel title has been {@link #title set} or {@link #setTitle changed}.
8694              * @param {Ext.Panel} p the Panel which has had its title changed.
8695              * @param {String} The new title.
8696              */
8697             'titlechange',
8698             /**
8699              * @event iconchange
8700              * Fires after the Panel icon class has been {@link #iconCls set} or {@link #setIconClass changed}.
8701              * @param {Ext.Panel} p the Panel which has had its {@link #iconCls icon class} changed.
8702              * @param {String} The new icon class.
8703              * @param {String} The old icon class.
8704              */
8705             'iconchange',
8706             /**
8707              * @event collapse
8708              * Fires after the Panel has been collapsed.
8709              * @param {Ext.Panel} p the Panel that has been collapsed.
8710              */
8711             'collapse',
8712             /**
8713              * @event expand
8714              * Fires after the Panel has been expanded.
8715              * @param {Ext.Panel} p The Panel that has been expanded.
8716              */
8717             'expand',
8718             /**
8719              * @event beforecollapse
8720              * Fires before the Panel is collapsed.  A handler can return false to cancel the collapse.
8721              * @param {Ext.Panel} p the Panel being collapsed.
8722              * @param {Boolean} animate True if the collapse is animated, else false.
8723              */
8724             'beforecollapse',
8725             /**
8726              * @event beforeexpand
8727              * Fires before the Panel is expanded.  A handler can return false to cancel the expand.
8728              * @param {Ext.Panel} p The Panel being expanded.
8729              * @param {Boolean} animate True if the expand is animated, else false.
8730              */
8731             'beforeexpand',
8732             /**
8733              * @event beforeclose
8734              * Fires before the Panel is closed.  Note that Panels do not directly support being closed, but some
8735              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.  This event only
8736              * applies to such subclasses.
8737              * A handler can return false to cancel the close.
8738              * @param {Ext.Panel} p The Panel being closed.
8739              */
8740             'beforeclose',
8741             /**
8742              * @event close
8743              * Fires after the Panel is closed.  Note that Panels do not directly support being closed, but some
8744              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.
8745              * @param {Ext.Panel} p The Panel that has been closed.
8746              */
8747             'close',
8748             /**
8749              * @event activate
8750              * Fires after the Panel has been visually activated.
8751              * Note that Panels do not directly support being activated, but some Panel subclasses
8752              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
8753              * activate and deactivate events under the control of the TabPanel.
8754              * @param {Ext.Panel} p The Panel that has been activated.
8755              */
8756             'activate',
8757             /**
8758              * @event deactivate
8759              * Fires after the Panel has been visually deactivated.
8760              * Note that Panels do not directly support being deactivated, but some Panel subclasses
8761              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
8762              * activate and deactivate events under the control of the TabPanel.
8763              * @param {Ext.Panel} p The Panel that has been deactivated.
8764              */
8765             'deactivate'
8766         );
8767
8768         if(this.unstyled){
8769             this.baseCls = 'x-plain';
8770         }
8771
8772
8773         this.toolbars = [];
8774         // shortcuts
8775         if(this.tbar){
8776             this.elements += ',tbar';
8777             this.topToolbar = this.createToolbar(this.tbar);
8778             delete this.tbar;
8779
8780         }
8781         if(this.bbar){
8782             this.elements += ',bbar';
8783             this.bottomToolbar = this.createToolbar(this.bbar);
8784             delete this.bbar;
8785         }
8786
8787         if(this.header === true){
8788             this.elements += ',header';
8789             delete this.header;
8790         }else if(this.headerCfg || (this.title && this.header !== false)){
8791             this.elements += ',header';
8792         }
8793
8794         if(this.footerCfg || this.footer === true){
8795             this.elements += ',footer';
8796             delete this.footer;
8797         }
8798
8799         if(this.buttons){
8800             this.fbar = this.buttons;
8801             delete this.buttons;
8802         }
8803         if(this.fbar){
8804             this.createFbar(this.fbar);
8805         }
8806         if(this.autoLoad){
8807             this.on('render', this.doAutoLoad, this, {delay:10});
8808         }
8809     },
8810
8811     // private
8812     createFbar : function(fbar){
8813         var min = this.minButtonWidth;
8814         this.elements += ',footer';
8815         this.fbar = this.createToolbar(fbar, {
8816             buttonAlign: this.buttonAlign,
8817             toolbarCls: 'x-panel-fbar',
8818             enableOverflow: false,
8819             defaults: function(c){
8820                 return {
8821                     minWidth: c.minWidth || min
8822                 };
8823             }
8824         });
8825         //@compat addButton and buttons could possibly be removed
8826         //@target 4.0
8827         /**
8828          * This Panel's Array of buttons as created from the <code>{@link #buttons}</code>
8829          * config property. Read only.
8830          * @type Array
8831          * @property buttons
8832          */
8833         this.fbar.items.each(function(c){
8834             c.minWidth = c.minWidth || this.minButtonWidth;
8835         }, this);
8836         this.buttons = this.fbar.items.items;
8837     },
8838
8839     // private
8840     createToolbar: function(tb, options){
8841         var result;
8842         // Convert array to proper toolbar config
8843         if(Ext.isArray(tb)){
8844             tb = {
8845                 items: tb
8846             };
8847         }
8848         result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
8849         result.ownerCt = this;
8850         result.bufferResize = false;
8851         this.toolbars.push(result);
8852         return result;
8853     },
8854
8855     // private
8856     createElement : function(name, pnode){
8857         if(this[name]){
8858             pnode.appendChild(this[name].dom);
8859             return;
8860         }
8861
8862         if(name === 'bwrap' || this.elements.indexOf(name) != -1){
8863             if(this[name+'Cfg']){
8864                 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
8865             }else{
8866                 var el = document.createElement('div');
8867                 el.className = this[name+'Cls'];
8868                 this[name] = Ext.get(pnode.appendChild(el));
8869             }
8870             if(this[name+'CssClass']){
8871                 this[name].addClass(this[name+'CssClass']);
8872             }
8873             if(this[name+'Style']){
8874                 this[name].applyStyles(this[name+'Style']);
8875             }
8876         }
8877     },
8878
8879     // private
8880     onRender : function(ct, position){
8881         Ext.Panel.superclass.onRender.call(this, ct, position);
8882         this.createClasses();
8883
8884         var el = this.el,
8885             d = el.dom,
8886             bw,
8887             ts;
8888
8889
8890         if(this.collapsible && !this.hideCollapseTool){
8891             this.tools = this.tools ? this.tools.slice(0) : [];
8892             this.tools[this.collapseFirst?'unshift':'push']({
8893                 id: 'toggle',
8894                 handler : this.toggleCollapse,
8895                 scope: this
8896             });
8897         }
8898
8899         if(this.tools){
8900             ts = this.tools;
8901             this.elements += (this.header !== false) ? ',header' : '';
8902         }
8903         this.tools = {};
8904
8905         el.addClass(this.baseCls);
8906         if(d.firstChild){ // existing markup
8907             this.header = el.down('.'+this.headerCls);
8908             this.bwrap = el.down('.'+this.bwrapCls);
8909             var cp = this.bwrap ? this.bwrap : el;
8910             this.tbar = cp.down('.'+this.tbarCls);
8911             this.body = cp.down('.'+this.bodyCls);
8912             this.bbar = cp.down('.'+this.bbarCls);
8913             this.footer = cp.down('.'+this.footerCls);
8914             this.fromMarkup = true;
8915         }
8916         if (this.preventBodyReset === true) {
8917             el.addClass('x-panel-reset');
8918         }
8919         if(this.cls){
8920             el.addClass(this.cls);
8921         }
8922
8923         if(this.buttons){
8924             this.elements += ',footer';
8925         }
8926
8927         // This block allows for maximum flexibility and performance when using existing markup
8928
8929         // framing requires special markup
8930         if(this.frame){
8931             el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
8932
8933             this.createElement('header', d.firstChild.firstChild.firstChild);
8934             this.createElement('bwrap', d);
8935
8936             // append the mid and bottom frame to the bwrap
8937             bw = this.bwrap.dom;
8938             var ml = d.childNodes[1], bl = d.childNodes[2];
8939             bw.appendChild(ml);
8940             bw.appendChild(bl);
8941
8942             var mc = bw.firstChild.firstChild.firstChild;
8943             this.createElement('tbar', mc);
8944             this.createElement('body', mc);
8945             this.createElement('bbar', mc);
8946             this.createElement('footer', bw.lastChild.firstChild.firstChild);
8947
8948             if(!this.footer){
8949                 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
8950             }
8951             /*
8952              * Store a reference to this element so:
8953              * a) We aren't looking it up all the time
8954              * b) The last element is reported incorrectly when using a loadmask
8955              */
8956             this.ft = Ext.get(this.bwrap.dom.lastChild);
8957             this.mc = Ext.get(mc);
8958         }else{
8959             this.createElement('header', d);
8960             this.createElement('bwrap', d);
8961
8962             // append the mid and bottom frame to the bwrap
8963             bw = this.bwrap.dom;
8964             this.createElement('tbar', bw);
8965             this.createElement('body', bw);
8966             this.createElement('bbar', bw);
8967             this.createElement('footer', bw);
8968
8969             if(!this.header){
8970                 this.body.addClass(this.bodyCls + '-noheader');
8971                 if(this.tbar){
8972                     this.tbar.addClass(this.tbarCls + '-noheader');
8973                 }
8974             }
8975         }
8976
8977         if(Ext.isDefined(this.padding)){
8978             this.body.setStyle('padding', this.body.addUnits(this.padding));
8979         }
8980
8981         if(this.border === false){
8982             this.el.addClass(this.baseCls + '-noborder');
8983             this.body.addClass(this.bodyCls + '-noborder');
8984             if(this.header){
8985                 this.header.addClass(this.headerCls + '-noborder');
8986             }
8987             if(this.footer){
8988                 this.footer.addClass(this.footerCls + '-noborder');
8989             }
8990             if(this.tbar){
8991                 this.tbar.addClass(this.tbarCls + '-noborder');
8992             }
8993             if(this.bbar){
8994                 this.bbar.addClass(this.bbarCls + '-noborder');
8995             }
8996         }
8997
8998         if(this.bodyBorder === false){
8999            this.body.addClass(this.bodyCls + '-noborder');
9000         }
9001
9002         this.bwrap.enableDisplayMode('block');
9003
9004         if(this.header){
9005             this.header.unselectable();
9006
9007             // for tools, we need to wrap any existing header markup
9008             if(this.headerAsText){
9009                 this.header.dom.innerHTML =
9010                     '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
9011
9012                 if(this.iconCls){
9013                     this.setIconClass(this.iconCls);
9014                 }
9015             }
9016         }
9017
9018         if(this.floating){
9019             this.makeFloating(this.floating);
9020         }
9021
9022         if(this.collapsible && this.titleCollapse && this.header){
9023             this.mon(this.header, 'click', this.toggleCollapse, this);
9024             this.header.setStyle('cursor', 'pointer');
9025         }
9026         if(ts){
9027             this.addTool.apply(this, ts);
9028         }
9029         if(this.fbar){
9030             this.footer.addClass('x-panel-btns');
9031             this.fbar.render(this.footer);
9032             this.footer.createChild({cls:'x-clear'});
9033         }
9034
9035         if(this.tbar && this.topToolbar){
9036             this.topToolbar.render(this.tbar);
9037         }
9038         if(this.bbar && this.bottomToolbar){
9039             this.bottomToolbar.render(this.bbar);
9040
9041         }
9042     },
9043
9044     /**
9045      * Sets the CSS class that provides the icon image for this panel.  This method will replace any existing
9046      * icon class if one has already been set and fire the {@link #iconchange} event after completion.
9047      * @param {String} cls The new CSS class name
9048      */
9049     setIconClass : function(cls){
9050         var old = this.iconCls;
9051         this.iconCls = cls;
9052         if(this.rendered && this.header){
9053             if(this.frame){
9054                 this.header.addClass('x-panel-icon');
9055                 this.header.replaceClass(old, this.iconCls);
9056             }else{
9057                 var hd = this.header,
9058                     img = hd.child('img.x-panel-inline-icon');
9059                 if(img){
9060                     Ext.fly(img).replaceClass(old, this.iconCls);
9061                 }else{
9062                     Ext.DomHelper.insertBefore(hd.dom.firstChild, {
9063                         tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
9064                     });
9065                  }
9066             }
9067         }
9068         this.fireEvent('iconchange', this, cls, old);
9069     },
9070
9071     // private
9072     makeFloating : function(cfg){
9073         this.floating = true;
9074         this.el = new Ext.Layer(Ext.apply({}, cfg, {
9075             shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
9076             shadowOffset: this.shadowOffset,
9077             constrain:false,
9078             shim: this.shim === false ? false : undefined
9079         }), this.el);
9080     },
9081
9082     /**
9083      * Returns the {@link Ext.Toolbar toolbar} from the top (<code>{@link #tbar}</code>) section of the panel.
9084      * @return {Ext.Toolbar} The toolbar
9085      */
9086     getTopToolbar : function(){
9087         return this.topToolbar;
9088     },
9089
9090     /**
9091      * Returns the {@link Ext.Toolbar toolbar} from the bottom (<code>{@link #bbar}</code>) section of the panel.
9092      * @return {Ext.Toolbar} The toolbar
9093      */
9094     getBottomToolbar : function(){
9095         return this.bottomToolbar;
9096     },
9097
9098     /**
9099      * Adds a button to this panel.  Note that this method must be called prior to rendering.  The preferred
9100      * approach is to add buttons via the {@link #buttons} config.
9101      * @param {String/Object} config A valid {@link Ext.Button} config.  A string will become the text for a default
9102      * button config, an object will be treated as a button config object.
9103      * @param {Function} handler The function to be called on button {@link Ext.Button#click}
9104      * @param {Object} scope The scope (<code>this</code> reference) in which the button handler function is executed. Defaults to the Button.
9105      * @return {Ext.Button} The button that was added
9106      */
9107     addButton : function(config, handler, scope){
9108         if(!this.fbar){
9109             this.createFbar([]);
9110         }
9111         if(handler){
9112             if(Ext.isString(config)){
9113                 config = {text: config};
9114             }
9115             config = Ext.apply({
9116                 handler: handler,
9117                 scope: scope
9118             }, config)
9119         }
9120         return this.fbar.add(config);
9121     },
9122
9123     // private
9124     addTool : function(){
9125         if(!this.rendered){
9126             if(!this.tools){
9127                 this.tools = [];
9128             }
9129             Ext.each(arguments, function(arg){
9130                 this.tools.push(arg)
9131             }, this);
9132             return;
9133         }
9134          // nowhere to render tools!
9135         if(!this[this.toolTarget]){
9136             return;
9137         }
9138         if(!this.toolTemplate){
9139             // initialize the global tool template on first use
9140             var tt = new Ext.Template(
9141                  '<div class="x-tool x-tool-{id}">&#160;</div>'
9142             );
9143             tt.disableFormats = true;
9144             tt.compile();
9145             Ext.Panel.prototype.toolTemplate = tt;
9146         }
9147         for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9148             var tc = a[i];
9149             if(!this.tools[tc.id]){
9150                 var overCls = 'x-tool-'+tc.id+'-over';
9151                 var t = this.toolTemplate.insertFirst((tc.align !== 'left') ? this[this.toolTarget] : this[this.toolTarget].child('span'), tc, true);
9152                 this.tools[tc.id] = t;
9153                 t.enableDisplayMode('block');
9154                 this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
9155                 if(tc.on){
9156                     this.mon(t, tc.on);
9157                 }
9158                 if(tc.hidden){
9159                     t.hide();
9160                 }
9161                 if(tc.qtip){
9162                     if(Ext.isObject(tc.qtip)){
9163                         Ext.QuickTips.register(Ext.apply({
9164                               target: t.id
9165                         }, tc.qtip));
9166                     } else {
9167                         t.dom.qtip = tc.qtip;
9168                     }
9169                 }
9170                 t.addClassOnOver(overCls);
9171             }
9172         }
9173     },
9174
9175     onLayout : function(shallow, force){
9176         if(this.hasLayout && this.toolbars.length > 0){
9177             Ext.each(this.toolbars, function(tb){
9178                 tb.doLayout(undefined, force);
9179             });
9180             this.syncHeight();
9181         }
9182     },
9183
9184     syncHeight : function(){
9185         var h = this.toolbarHeight,
9186                 bd = this.body,
9187                 lsh = this.lastSize.height,
9188                 sz;
9189
9190         if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
9191             return;
9192         }
9193
9194
9195         if(h != this.getToolbarHeight()){
9196             h = Math.max(0, this.adjustBodyHeight(lsh - this.getFrameHeight()));
9197             bd.setHeight(h);
9198             sz = bd.getSize();
9199             this.toolbarHeight = this.getToolbarHeight();
9200             this.onBodyResize(sz.width, sz.height);
9201         }
9202     },
9203
9204     // private
9205     onShow : function(){
9206         if(this.floating){
9207             return this.el.show();
9208         }
9209         Ext.Panel.superclass.onShow.call(this);
9210     },
9211
9212     // private
9213     onHide : function(){
9214         if(this.floating){
9215             return this.el.hide();
9216         }
9217         Ext.Panel.superclass.onHide.call(this);
9218     },
9219
9220     // private
9221     createToolHandler : function(t, tc, overCls, panel){
9222         return function(e){
9223             t.removeClass(overCls);
9224             if(tc.stopEvent !== false){
9225                 e.stopEvent();
9226             }
9227             if(tc.handler){
9228                 tc.handler.call(tc.scope || t, e, t, panel, tc);
9229             }
9230         };
9231     },
9232
9233     // private    
9234     afterRender : function(){
9235         if(this.floating && !this.hidden){
9236             this.el.show();
9237         }
9238         if(this.title){
9239             this.setTitle(this.title);
9240         }
9241         if(this.collapsed){
9242             this.collapsed = false;
9243             this.collapse(false);
9244         }
9245         Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
9246         this.initEvents();
9247     },    
9248
9249     // private
9250     getKeyMap : function(){
9251         if(!this.keyMap){
9252             this.keyMap = new Ext.KeyMap(this.el, this.keys);
9253         }
9254         return this.keyMap;
9255     },
9256
9257     // private
9258     initEvents : function(){
9259         if(this.keys){
9260             this.getKeyMap();
9261         }
9262         if(this.draggable){
9263             this.initDraggable();
9264         }
9265         if(this.toolbars.length > 0){
9266             Ext.each(this.toolbars, function(tb){
9267                 tb.doLayout();
9268                 tb.on({
9269                     scope: this,
9270                     afterlayout: this.syncHeight,
9271                     remove: this.syncHeight
9272                 });
9273             }, this);
9274             if(!this.ownerCt){
9275                 this.syncHeight();
9276             }
9277         }
9278
9279     },
9280
9281     // private
9282     initDraggable : function(){
9283         /**
9284          * <p>If this Panel is configured {@link #draggable}, this property will contain
9285          * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.</p>
9286          * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource}
9287          * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
9288          * @type Ext.dd.DragSource.
9289          * @property dd
9290          */
9291         this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
9292     },
9293
9294     // private
9295     beforeEffect : function(anim){
9296         if(this.floating){
9297             this.el.beforeAction();
9298         }
9299         if(anim !== false){
9300             this.el.addClass('x-panel-animated');
9301         }
9302     },
9303
9304     // private
9305     afterEffect : function(anim){
9306         this.syncShadow();
9307         if(anim !== false){
9308             this.el.removeClass('x-panel-animated');
9309         }
9310     },
9311
9312     // private - wraps up an animation param with internal callbacks
9313     createEffect : function(a, cb, scope){
9314         var o = {
9315             scope:scope,
9316             block:true
9317         };
9318         if(a === true){
9319             o.callback = cb;
9320             return o;
9321         }else if(!a.callback){
9322             o.callback = cb;
9323         }else { // wrap it up
9324             o.callback = function(){
9325                 cb.call(scope);
9326                 Ext.callback(a.callback, a.scope);
9327             };
9328         }
9329         return Ext.applyIf(o, a);
9330     },
9331
9332     /**
9333      * Collapses the panel body so that it becomes hidden.  Fires the {@link #beforecollapse} event which will
9334      * cancel the collapse action if it returns false.
9335      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
9336      * {@link #animCollapse} panel config)
9337      * @return {Ext.Panel} this
9338      */
9339     collapse : function(animate){
9340         if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
9341             return;
9342         }
9343         var doAnim = animate === true || (animate !== false && this.animCollapse);
9344         this.beforeEffect(doAnim);
9345         this.onCollapse(doAnim, animate);
9346         return this;
9347     },
9348
9349     // private
9350     onCollapse : function(doAnim, animArg){
9351         if(doAnim){
9352             this[this.collapseEl].slideOut(this.slideAnchor,
9353                     Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
9354                         this.collapseDefaults));
9355         }else{
9356             this[this.collapseEl].hide();
9357             this.afterCollapse(false);
9358         }
9359     },
9360
9361     // private
9362     afterCollapse : function(anim){
9363         this.collapsed = true;
9364         this.el.addClass(this.collapsedCls);
9365         this.afterEffect(anim);
9366         this.fireEvent('collapse', this);
9367     },
9368
9369     /**
9370      * Expands the panel body so that it becomes visible.  Fires the {@link #beforeexpand} event which will
9371      * cancel the expand action if it returns false.
9372      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
9373      * {@link #animCollapse} panel config)
9374      * @return {Ext.Panel} this
9375      */
9376     expand : function(animate){
9377         if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
9378             return;
9379         }
9380         var doAnim = animate === true || (animate !== false && this.animCollapse);
9381         this.el.removeClass(this.collapsedCls);
9382         this.beforeEffect(doAnim);
9383         this.onExpand(doAnim, animate);
9384         return this;
9385     },
9386
9387     // private
9388     onExpand : function(doAnim, animArg){
9389         if(doAnim){
9390             this[this.collapseEl].slideIn(this.slideAnchor,
9391                     Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
9392                         this.expandDefaults));
9393         }else{
9394             this[this.collapseEl].show();
9395             this.afterExpand(false);
9396         }
9397     },
9398
9399     // private
9400     afterExpand : function(anim){
9401         this.collapsed = false;
9402         this.afterEffect(anim);
9403         if(Ext.isDefined(this.deferLayout)){
9404             this.doLayout(true);
9405         }
9406         this.fireEvent('expand', this);
9407     },
9408
9409     /**
9410      * Shortcut for performing an {@link #expand} or {@link #collapse} based on the current state of the panel.
9411      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
9412      * {@link #animCollapse} panel config)
9413      * @return {Ext.Panel} this
9414      */
9415     toggleCollapse : function(animate){
9416         this[this.collapsed ? 'expand' : 'collapse'](animate);
9417         return this;
9418     },
9419
9420     // private
9421     onDisable : function(){
9422         if(this.rendered && this.maskDisabled){
9423             this.el.mask();
9424         }
9425         Ext.Panel.superclass.onDisable.call(this);
9426     },
9427
9428     // private
9429     onEnable : function(){
9430         if(this.rendered && this.maskDisabled){
9431             this.el.unmask();
9432         }
9433         Ext.Panel.superclass.onEnable.call(this);
9434     },
9435
9436     // private
9437     onResize : function(w, h){
9438         if(Ext.isDefined(w) || Ext.isDefined(h)){
9439             if(!this.collapsed){
9440                 // First, set the the Panel's body width.
9441                 // If we have auto-widthed it, get the resulting full offset width so we can size the Toolbars to match
9442                 // The Toolbars must not buffer this resize operation because we need to know their heights.
9443
9444                 if(Ext.isNumber(w)){
9445                     this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
9446                 } else if (w == 'auto') {
9447                     w = this.body.setWidth('auto').dom.offsetWidth;
9448                 } else {
9449                     w = this.body.dom.offsetWidth;
9450                 }
9451
9452                 if(this.tbar){
9453                     this.tbar.setWidth(w);
9454                     if(this.topToolbar){
9455                         this.topToolbar.setSize(w);
9456                     }
9457                 }
9458                 if(this.bbar){
9459                     this.bbar.setWidth(w);
9460                     if(this.bottomToolbar){
9461                         this.bottomToolbar.setSize(w);
9462                         // The bbar does not move on resize without this.
9463                         if (Ext.isIE) {
9464                             this.bbar.setStyle('position', 'static');
9465                             this.bbar.setStyle('position', '');
9466                         }
9467                     }
9468                 }
9469                 if(this.footer){
9470                     this.footer.setWidth(w);
9471                     if(this.fbar){
9472                         this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
9473                     }
9474                 }
9475
9476                 // At this point, the Toolbars must be layed out for getFrameHeight to find a result.
9477                 if(Ext.isNumber(h)){
9478                     h = Math.max(0, this.adjustBodyHeight(h - this.getFrameHeight()));
9479                     this.body.setHeight(h);
9480                 }else if(h == 'auto'){
9481                     this.body.setHeight(h);
9482                 }
9483
9484                 if(this.disabled && this.el._mask){
9485                     this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
9486                 }
9487             }else{
9488                 this.queuedBodySize = {width: w, height: h};
9489                 if(!this.queuedExpand && this.allowQueuedExpand !== false){
9490                     this.queuedExpand = true;
9491                     this.on('expand', function(){
9492                         delete this.queuedExpand;
9493                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
9494                     }, this, {single:true});
9495                 }
9496             }
9497             this.onBodyResize(w, h);
9498         }
9499         this.syncShadow();
9500         Ext.Panel.superclass.onResize.call(this);
9501     },
9502
9503     // private
9504     onBodyResize: function(w, h){
9505         this.fireEvent('bodyresize', this, w, h);
9506     },
9507
9508     // private
9509     getToolbarHeight: function(){
9510         var h = 0;
9511         if(this.rendered){
9512             Ext.each(this.toolbars, function(tb){
9513                 h += tb.getHeight();
9514             }, this);
9515         }
9516         return h;
9517     },
9518
9519     // private
9520     adjustBodyHeight : function(h){
9521         return h;
9522     },
9523
9524     // private
9525     adjustBodyWidth : function(w){
9526         return w;
9527     },
9528
9529     // private
9530     onPosition : function(){
9531         this.syncShadow();
9532     },
9533
9534     /**
9535      * Returns the width in pixels of the framing elements of this panel (not including the body width).  To
9536      * retrieve the body width see {@link #getInnerWidth}.
9537      * @return {Number} The frame width
9538      */
9539     getFrameWidth : function(){
9540         var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
9541
9542         if(this.frame){
9543             var l = this.bwrap.dom.firstChild;
9544             w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
9545             w += this.mc.getFrameWidth('lr');
9546         }
9547         return w;
9548     },
9549
9550     /**
9551      * Returns the height in pixels of the framing elements of this panel (including any top and bottom bars and
9552      * header and footer elements, but not including the body height).  To retrieve the body height see {@link #getInnerHeight}.
9553      * @return {Number} The frame height
9554      */
9555     getFrameHeight : function(){
9556         var h  = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
9557         h += (this.tbar ? this.tbar.getHeight() : 0) +
9558              (this.bbar ? this.bbar.getHeight() : 0);
9559
9560         if(this.frame){
9561             h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
9562         }else{
9563             h += (this.header ? this.header.getHeight() : 0) +
9564                 (this.footer ? this.footer.getHeight() : 0);
9565         }
9566         return h;
9567     },
9568
9569     /**
9570      * Returns the width in pixels of the body element (not including the width of any framing elements).
9571      * For the frame width see {@link #getFrameWidth}.
9572      * @return {Number} The body width
9573      */
9574     getInnerWidth : function(){
9575         return this.getSize().width - this.getFrameWidth();
9576     },
9577
9578     /**
9579      * Returns the height in pixels of the body element (not including the height of any framing elements).
9580      * For the frame height see {@link #getFrameHeight}.
9581      * @return {Number} The body height
9582      */
9583     getInnerHeight : function(){
9584         return this.getSize().height - this.getFrameHeight();
9585     },
9586
9587     // private
9588     syncShadow : function(){
9589         if(this.floating){
9590             this.el.sync(true);
9591         }
9592     },
9593
9594     // private
9595     getLayoutTarget : function(){
9596         return this.body;
9597     },
9598
9599     // private
9600     getContentTarget : function(){
9601         return this.body;
9602     },
9603
9604     /**
9605      * <p>Sets the title text for the panel and optionally the {@link #iconCls icon class}.</p>
9606      * <p>In order to be able to set the title, a header element must have been created
9607      * for the Panel. This is triggered either by configuring the Panel with a non-blank <code>{@link #title}</code>,
9608      * or configuring it with <code><b>{@link #header}: true</b></code>.</p>
9609      * @param {String} title The title text to set
9610      * @param {String} iconCls (optional) {@link #iconCls iconCls} A user-defined CSS class that provides the icon image for this panel
9611      */
9612     setTitle : function(title, iconCls){
9613         this.title = title;
9614         if(this.header && this.headerAsText){
9615             this.header.child('span').update(title);
9616         }
9617         if(iconCls){
9618             this.setIconClass(iconCls);
9619         }
9620         this.fireEvent('titlechange', this, title);
9621         return this;
9622     },
9623
9624     /**
9625      * Get the {@link Ext.Updater} for this panel. Enables you to perform Ajax updates of this panel's body.
9626      * @return {Ext.Updater} The Updater
9627      */
9628     getUpdater : function(){
9629         return this.body.getUpdater();
9630     },
9631
9632      /**
9633      * Loads this content panel immediately with content returned from an XHR call.
9634      * @param {Object/String/Function} config A config object containing any of the following options:
9635 <pre><code>
9636 panel.load({
9637     url: 'your-url.php',
9638     params: {param1: 'foo', param2: 'bar'}, // or a URL encoded string
9639     callback: yourFunction,
9640     scope: yourObject, // optional scope for the callback
9641     discardUrl: false,
9642     nocache: false,
9643     text: 'Loading...',
9644     timeout: 30,
9645     scripts: false
9646 });
9647 </code></pre>
9648      * The only required property is url. The optional properties nocache, text and scripts
9649      * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their
9650      * associated property on this panel Updater instance.
9651      * @return {Ext.Panel} this
9652      */
9653     load : function(){
9654         var um = this.body.getUpdater();
9655         um.update.apply(um, arguments);
9656         return this;
9657     },
9658
9659     // private
9660     beforeDestroy : function(){
9661         Ext.Panel.superclass.beforeDestroy.call(this);
9662         if(this.header){
9663             this.header.removeAllListeners();
9664         }
9665         if(this.tools){
9666             for(var k in this.tools){
9667                 Ext.destroy(this.tools[k]);
9668             }
9669         }
9670         if(Ext.isArray(this.buttons)){
9671             while(this.buttons.length) {
9672                 Ext.destroy(this.buttons[0]);
9673             }
9674         }
9675         if(this.rendered){
9676             Ext.destroy(
9677                 this.ft,
9678                 this.header,
9679                 this.footer,
9680                 this.toolbars,
9681                 this.tbar,
9682                 this.bbar,
9683                 this.body,
9684                 this.mc,
9685                 this.bwrap
9686             );
9687             if (this.fbar) {
9688                 Ext.destroy(
9689                     this.fbar,
9690                     this.fbar.el
9691                 );
9692             }
9693         }else{
9694             Ext.destroy(
9695                 this.topToolbar,
9696                 this.bottomToolbar
9697             );
9698         }
9699     },
9700
9701     // private
9702     createClasses : function(){
9703         this.headerCls = this.baseCls + '-header';
9704         this.headerTextCls = this.baseCls + '-header-text';
9705         this.bwrapCls = this.baseCls + '-bwrap';
9706         this.tbarCls = this.baseCls + '-tbar';
9707         this.bodyCls = this.baseCls + '-body';
9708         this.bbarCls = this.baseCls + '-bbar';
9709         this.footerCls = this.baseCls + '-footer';
9710     },
9711
9712     // private
9713     createGhost : function(cls, useShim, appendTo){
9714         var el = document.createElement('div');
9715         el.className = 'x-panel-ghost ' + (cls ? cls : '');
9716         if(this.header){
9717             el.appendChild(this.el.dom.firstChild.cloneNode(true));
9718         }
9719         Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
9720         el.style.width = this.el.dom.offsetWidth + 'px';;
9721         if(!appendTo){
9722             this.container.dom.appendChild(el);
9723         }else{
9724             Ext.getDom(appendTo).appendChild(el);
9725         }
9726         if(useShim !== false && this.el.useShim !== false){
9727             var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
9728             layer.show();
9729             return layer;
9730         }else{
9731             return new Ext.Element(el);
9732         }
9733     },
9734
9735     // private
9736     doAutoLoad : function(){
9737         var u = this.body.getUpdater();
9738         if(this.renderer){
9739             u.setRenderer(this.renderer);
9740         }
9741         u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
9742     },
9743
9744     /**
9745      * Retrieve a tool by id.
9746      * @param {String} id
9747      * @return {Object} tool
9748      */
9749     getTool : function(id) {
9750         return this.tools[id];
9751     }
9752
9753 /**
9754  * @cfg {String} autoEl @hide
9755  */
9756 });
9757 Ext.reg('panel', Ext.Panel);
9758 /**
9759  * @class Ext.Editor
9760  * @extends Ext.Component
9761  * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
9762  * @constructor
9763  * Create a new Editor
9764  * @param {Object} config The config object
9765  * @xtype editor
9766  */
9767 Ext.Editor = function(field, config){
9768     if(field.field){
9769         this.field = Ext.create(field.field, 'textfield');
9770         config = Ext.apply({}, field); // copy so we don't disturb original config
9771         delete config.field;
9772     }else{
9773         this.field = field;
9774     }
9775     Ext.Editor.superclass.constructor.call(this, config);
9776 };
9777
9778 Ext.extend(Ext.Editor, Ext.Component, {
9779     /**
9780     * @cfg {Ext.form.Field} field
9781     * The Field object (or descendant) or config object for field
9782     */
9783     /**
9784      * @cfg {Boolean} allowBlur
9785      * True to {@link #completeEdit complete the editing process} if in edit mode when the
9786      * field is blurred. Defaults to <tt>false</tt>.
9787      */
9788     /**
9789      * @cfg {Boolean/String} autoSize
9790      * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only,
9791      * or "height" to adopt the height only, "none" to always use the field dimensions. (defaults to false)
9792      */
9793     /**
9794      * @cfg {Boolean} revertInvalid
9795      * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
9796      * validation fails (defaults to true)
9797      */
9798     /**
9799      * @cfg {Boolean} ignoreNoChange
9800      * True to skip the edit completion process (no save, no events fired) if the user completes an edit and
9801      * the value has not changed (defaults to false).  Applies only to string values - edits for other data types
9802      * will never be ignored.
9803      */
9804     /**
9805      * @cfg {Boolean} hideEl
9806      * False to keep the bound element visible while the editor is displayed (defaults to true)
9807      */
9808     /**
9809      * @cfg {Mixed} value
9810      * The data value of the underlying field (defaults to "")
9811      */
9812     value : "",
9813     /**
9814      * @cfg {String} alignment
9815      * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?").
9816      */
9817     alignment: "c-c?",
9818     /**
9819      * @cfg {Array} offsets
9820      * The offsets to use when aligning (see {@link Ext.Element#alignTo} for more details. Defaults to <tt>[0, 0]</tt>.
9821      */
9822     offsets: [0, 0],
9823     /**
9824      * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
9825      * for bottom-right shadow (defaults to "frame")
9826      */
9827     shadow : "frame",
9828     /**
9829      * @cfg {Boolean} constrain True to constrain the editor to the viewport
9830      */
9831     constrain : false,
9832     /**
9833      * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true)
9834      */
9835     swallowKeys : true,
9836     /**
9837      * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed. Defaults to <tt>true</tt>.
9838      */
9839     completeOnEnter : true,
9840     /**
9841      * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed. Defaults to <tt>true</tt>.
9842      */
9843     cancelOnEsc : true,
9844     /**
9845      * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
9846      */
9847     updateEl : false,
9848
9849     initComponent : function(){
9850         Ext.Editor.superclass.initComponent.call(this);
9851         this.addEvents(
9852             /**
9853              * @event beforestartedit
9854              * Fires when editing is initiated, but before the value changes.  Editing can be canceled by returning
9855              * false from the handler of this event.
9856              * @param {Editor} this
9857              * @param {Ext.Element} boundEl The underlying element bound to this editor
9858              * @param {Mixed} value The field value being set
9859              */
9860             "beforestartedit",
9861             /**
9862              * @event startedit
9863              * Fires when this editor is displayed
9864              * @param {Ext.Element} boundEl The underlying element bound to this editor
9865              * @param {Mixed} value The starting field value
9866              */
9867             "startedit",
9868             /**
9869              * @event beforecomplete
9870              * Fires after a change has been made to the field, but before the change is reflected in the underlying
9871              * field.  Saving the change to the field can be canceled by returning false from the handler of this event.
9872              * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
9873              * event will not fire since no edit actually occurred.
9874              * @param {Editor} this
9875              * @param {Mixed} value The current field value
9876              * @param {Mixed} startValue The original field value
9877              */
9878             "beforecomplete",
9879             /**
9880              * @event complete
9881              * Fires after editing is complete and any changed value has been written to the underlying field.
9882              * @param {Editor} this
9883              * @param {Mixed} value The current field value
9884              * @param {Mixed} startValue The original field value
9885              */
9886             "complete",
9887             /**
9888              * @event canceledit
9889              * Fires after editing has been canceled and the editor's value has been reset.
9890              * @param {Editor} this
9891              * @param {Mixed} value The user-entered field value that was discarded
9892              * @param {Mixed} startValue The original field value that was set back into the editor after cancel
9893              */
9894             "canceledit",
9895             /**
9896              * @event specialkey
9897              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
9898              * {@link Ext.EventObject#getKey} to determine which key was pressed.
9899              * @param {Ext.form.Field} this
9900              * @param {Ext.EventObject} e The event object
9901              */
9902             "specialkey"
9903         );
9904     },
9905
9906     // private
9907     onRender : function(ct, position){
9908         this.el = new Ext.Layer({
9909             shadow: this.shadow,
9910             cls: "x-editor",
9911             parentEl : ct,
9912             shim : this.shim,
9913             shadowOffset: this.shadowOffset || 4,
9914             id: this.id,
9915             constrain: this.constrain
9916         });
9917         if(this.zIndex){
9918             this.el.setZIndex(this.zIndex);
9919         }
9920         this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
9921         if(this.field.msgTarget != 'title'){
9922             this.field.msgTarget = 'qtip';
9923         }
9924         this.field.inEditor = true;
9925         this.mon(this.field, {
9926             scope: this,
9927             blur: this.onBlur,
9928             specialkey: this.onSpecialKey
9929         });
9930         if(this.field.grow){
9931             this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
9932         }
9933         this.field.render(this.el).show();
9934         this.field.getEl().dom.name = '';
9935         if(this.swallowKeys){
9936             this.field.el.swallowEvent([
9937                 'keypress', // *** Opera
9938                 'keydown'   // *** all other browsers
9939             ]);
9940         }
9941     },
9942
9943     // private
9944     onSpecialKey : function(field, e){
9945         var key = e.getKey(),
9946             complete = this.completeOnEnter && key == e.ENTER,
9947             cancel = this.cancelOnEsc && key == e.ESC;
9948         if(complete || cancel){
9949             e.stopEvent();
9950             if(complete){
9951                 this.completeEdit();
9952             }else{
9953                 this.cancelEdit();
9954             }
9955             if(field.triggerBlur){
9956                 field.triggerBlur(); 
9957             }
9958         }
9959         this.fireEvent('specialkey', field, e);
9960     },
9961
9962     /**
9963      * Starts the editing process and shows the editor.
9964      * @param {Mixed} el The element to edit
9965      * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
9966       * to the innerHTML of el.
9967      */
9968     startEdit : function(el, value){
9969         if(this.editing){
9970             this.completeEdit();
9971         }
9972         this.boundEl = Ext.get(el);
9973         var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
9974         if(!this.rendered){
9975             this.render(this.parentEl || document.body);
9976         }
9977         if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
9978             this.startValue = v;
9979             this.field.reset();
9980             this.field.setValue(v);
9981             this.realign(true);
9982             this.editing = true;
9983             this.show();
9984         }
9985     },
9986
9987     // private
9988     doAutoSize : function(){
9989         if(this.autoSize){
9990             var sz = this.boundEl.getSize(),
9991                 fs = this.field.getSize();
9992
9993             switch(this.autoSize){
9994                 case "width":
9995                     this.setSize(sz.width, fs.height);
9996                     break;
9997                 case "height":
9998                     this.setSize(fs.width, sz.height);
9999                     break;
10000                 case "none":
10001                     this.setSize(fs.width, fs.height);
10002                     break;
10003                 default:
10004                     this.setSize(sz.width, sz.height);
10005             }
10006         }
10007     },
10008
10009     /**
10010      * Sets the height and width of this editor.
10011      * @param {Number} width The new width
10012      * @param {Number} height The new height
10013      */
10014     setSize : function(w, h){
10015         delete this.field.lastSize;
10016         this.field.setSize(w, h);
10017         if(this.el){
10018             if(Ext.isGecko2 || Ext.isOpera){
10019                 // prevent layer scrollbars
10020                 this.el.setSize(w, h);
10021             }
10022             this.el.sync();
10023         }
10024     },
10025
10026     /**
10027      * Realigns the editor to the bound field based on the current alignment config value.
10028      * @param {Boolean} autoSize (optional) True to size the field to the dimensions of the bound element.
10029      */
10030     realign : function(autoSize){
10031         if(autoSize === true){
10032             this.doAutoSize();
10033         }
10034         this.el.alignTo(this.boundEl, this.alignment, this.offsets);
10035     },
10036
10037     /**
10038      * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
10039      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
10040      */
10041     completeEdit : function(remainVisible){
10042         if(!this.editing){
10043             return;
10044         }
10045         var v = this.getValue();
10046         if(!this.field.isValid()){
10047             if(this.revertInvalid !== false){
10048                 this.cancelEdit(remainVisible);
10049             }
10050             return;
10051         }
10052         if(String(v) === String(this.startValue) && this.ignoreNoChange){
10053             this.hideEdit(remainVisible);
10054             return;
10055         }
10056         if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
10057             v = this.getValue();
10058             if(this.updateEl && this.boundEl){
10059                 this.boundEl.update(v);
10060             }
10061             this.hideEdit(remainVisible);
10062             this.fireEvent("complete", this, v, this.startValue);
10063         }
10064     },
10065
10066     // private
10067     onShow : function(){
10068         this.el.show();
10069         if(this.hideEl !== false){
10070             this.boundEl.hide();
10071         }
10072         this.field.show().focus(false, true);
10073         this.fireEvent("startedit", this.boundEl, this.startValue);
10074     },
10075
10076     /**
10077      * Cancels the editing process and hides the editor without persisting any changes.  The field value will be
10078      * reverted to the original starting value.
10079      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
10080      * cancel (defaults to false)
10081      */
10082     cancelEdit : function(remainVisible){
10083         if(this.editing){
10084             var v = this.getValue();
10085             this.setValue(this.startValue);
10086             this.hideEdit(remainVisible);
10087             this.fireEvent("canceledit", this, v, this.startValue);
10088         }
10089     },
10090     
10091     // private
10092     hideEdit: function(remainVisible){
10093         if(remainVisible !== true){
10094             this.editing = false;
10095             this.hide();
10096         }
10097     },
10098
10099     // private
10100     onBlur : function(){
10101         if(this.allowBlur !== true && this.editing){
10102             this.completeEdit();
10103         }
10104     },
10105
10106     // private
10107     onHide : function(){
10108         if(this.editing){
10109             this.completeEdit();
10110             return;
10111         }
10112         this.field.blur();
10113         if(this.field.collapse){
10114             this.field.collapse();
10115         }
10116         this.el.hide();
10117         if(this.hideEl !== false){
10118             this.boundEl.show();
10119         }
10120     },
10121
10122     /**
10123      * Sets the data value of the editor
10124      * @param {Mixed} value Any valid value supported by the underlying field
10125      */
10126     setValue : function(v){
10127         this.field.setValue(v);
10128     },
10129
10130     /**
10131      * Gets the data value of the editor
10132      * @return {Mixed} The data value
10133      */
10134     getValue : function(){
10135         return this.field.getValue();
10136     },
10137
10138     beforeDestroy : function(){
10139         Ext.destroyMembers(this, 'field');
10140         
10141         delete this.parentEl;
10142         delete this.boundEl;
10143     }
10144 });
10145 Ext.reg('editor', Ext.Editor);
10146 /**
10147  * @class Ext.ColorPalette
10148  * @extends Ext.Component
10149  * Simple color palette class for choosing colors.  The palette can be rendered to any container.<br />
10150  * Here's an example of typical usage:
10151  * <pre><code>
10152 var cp = new Ext.ColorPalette({value:'993300'});  // initial selected color
10153 cp.render('my-div');
10154
10155 cp.on('select', function(palette, selColor){
10156     // do something with selColor
10157 });
10158 </code></pre>
10159  * @constructor
10160  * Create a new ColorPalette
10161  * @param {Object} config The config object
10162  * @xtype colorpalette
10163  */
10164 Ext.ColorPalette = Ext.extend(Ext.Component, {
10165         /**
10166          * @cfg {String} tpl An existing XTemplate instance to be used in place of the default template for rendering the component.
10167          */
10168     /**
10169      * @cfg {String} itemCls
10170      * The CSS class to apply to the containing element (defaults to 'x-color-palette')
10171      */
10172     itemCls : 'x-color-palette',
10173     /**
10174      * @cfg {String} value
10175      * The initial color to highlight (should be a valid 6-digit color hex code without the # symbol).  Note that
10176      * the hex codes are case-sensitive.
10177      */
10178     value : null,
10179     /**
10180      * @cfg {String} clickEvent
10181      * The DOM event that will cause a color to be selected. This can be any valid event name (dblclick, contextmenu). 
10182      * Defaults to <tt>'click'</tt>.
10183      */
10184     clickEvent :'click',
10185     // private
10186     ctype : 'Ext.ColorPalette',
10187
10188     /**
10189      * @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the {@link #select} event
10190      */
10191     allowReselect : false,
10192
10193     /**
10194      * <p>An array of 6-digit color hex code strings (without the # symbol).  This array can contain any number
10195      * of colors, and each hex code should be unique.  The width of the palette is controlled via CSS by adjusting
10196      * the width property of the 'x-color-palette' class (or assigning a custom class), so you can balance the number
10197      * of colors with the width setting until the box is symmetrical.</p>
10198      * <p>You can override individual colors if needed:</p>
10199      * <pre><code>
10200 var cp = new Ext.ColorPalette();
10201 cp.colors[0] = 'FF0000';  // change the first box to red
10202 </code></pre>
10203
10204 Or you can provide a custom array of your own for complete control:
10205 <pre><code>
10206 var cp = new Ext.ColorPalette();
10207 cp.colors = ['000000', '993300', '333300'];
10208 </code></pre>
10209      * @type Array
10210      */
10211     colors : [
10212         '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
10213         '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
10214         'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
10215         'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
10216         'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
10217     ],
10218
10219     /**
10220      * @cfg {Function} handler
10221      * Optional. A function that will handle the select event of this palette.
10222      * The handler is passed the following parameters:<div class="mdetail-params"><ul>
10223      * <li><code>palette</code> : ColorPalette<div class="sub-desc">The {@link #palette Ext.ColorPalette}.</div></li>
10224      * <li><code>color</code> : String<div class="sub-desc">The 6-digit color hex code (without the # symbol).</div></li>
10225      * </ul></div>
10226      */
10227     /**
10228      * @cfg {Object} scope
10229      * The scope (<tt><b>this</b></tt> reference) in which the <code>{@link #handler}</code>
10230      * function will be called.  Defaults to this ColorPalette instance.
10231      */
10232     
10233     // private
10234     initComponent : function(){
10235         Ext.ColorPalette.superclass.initComponent.call(this);
10236         this.addEvents(
10237             /**
10238              * @event select
10239              * Fires when a color is selected
10240              * @param {ColorPalette} this
10241              * @param {String} color The 6-digit color hex code (without the # symbol)
10242              */
10243             'select'
10244         );
10245
10246         if(this.handler){
10247             this.on('select', this.handler, this.scope, true);
10248         }    
10249     },
10250
10251     // private
10252     onRender : function(container, position){
10253         this.autoEl = {
10254             tag: 'div',
10255             cls: this.itemCls
10256         };
10257         Ext.ColorPalette.superclass.onRender.call(this, container, position);
10258         var t = this.tpl || new Ext.XTemplate(
10259             '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
10260         );
10261         t.overwrite(this.el, this.colors);
10262         this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
10263         if(this.clickEvent != 'click'){
10264                 this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
10265         }
10266     },
10267
10268     // private
10269     afterRender : function(){
10270         Ext.ColorPalette.superclass.afterRender.call(this);
10271         if(this.value){
10272             var s = this.value;
10273             this.value = null;
10274             this.select(s);
10275         }
10276     },
10277
10278     // private
10279     handleClick : function(e, t){
10280         e.preventDefault();
10281         if(!this.disabled){
10282             var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
10283             this.select(c.toUpperCase());
10284         }
10285     },
10286
10287     /**
10288      * Selects the specified color in the palette (fires the {@link #select} event)
10289      * @param {String} color A valid 6-digit color hex code (# will be stripped if included)
10290      */
10291     select : function(color){
10292         color = color.replace('#', '');
10293         if(color != this.value || this.allowReselect){
10294             var el = this.el;
10295             if(this.value){
10296                 el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
10297             }
10298             el.child('a.color-'+color).addClass('x-color-palette-sel');
10299             this.value = color;
10300             this.fireEvent('select', this, color);
10301         }
10302     }
10303
10304     /**
10305      * @cfg {String} autoEl @hide
10306      */
10307 });
10308 Ext.reg('colorpalette', Ext.ColorPalette);
10309 /**
10310  * @class Ext.DatePicker
10311  * @extends Ext.Component
10312  * <p>A popup date picker. This class is used by the {@link Ext.form.DateField DateField} class
10313  * to allow browsing and selection of valid dates.</p>
10314  * <p>All the string values documented below may be overridden by including an Ext locale file in
10315  * your page.</p>
10316  * @constructor
10317  * Create a new DatePicker
10318  * @param {Object} config The config object
10319  * @xtype datepicker
10320  */
10321 Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
10322     /**
10323      * @cfg {String} todayText
10324      * The text to display on the button that selects the current date (defaults to <code>'Today'</code>)
10325      */
10326     todayText : 'Today',
10327     /**
10328      * @cfg {String} okText
10329      * The text to display on the ok button (defaults to <code>'&#160;OK&#160;'</code> to give the user extra clicking room)
10330      */
10331     okText : '&#160;OK&#160;',
10332     /**
10333      * @cfg {String} cancelText
10334      * The text to display on the cancel button (defaults to <code>'Cancel'</code>)
10335      */
10336     cancelText : 'Cancel',
10337     /**
10338      * @cfg {Function} handler
10339      * Optional. A function that will handle the select event of this picker.
10340      * The handler is passed the following parameters:<div class="mdetail-params"><ul>
10341      * <li><code>picker</code> : DatePicker<div class="sub-desc">This DatePicker.</div></li>
10342      * <li><code>date</code> : Date<div class="sub-desc">The selected date.</div></li>
10343      * </ul></div>
10344      */
10345     /**
10346      * @cfg {Object} scope
10347      * The scope (<code><b>this</b></code> reference) in which the <code>{@link #handler}</code>
10348      * function will be called.  Defaults to this DatePicker instance.
10349      */ 
10350     /**
10351      * @cfg {String} todayTip
10352      * A string used to format the message for displaying in a tooltip over the button that
10353      * selects the current date. Defaults to <code>'{0} (Spacebar)'</code> where
10354      * the <code>{0}</code> token is replaced by today's date.
10355      */
10356     todayTip : '{0} (Spacebar)',
10357     /**
10358      * @cfg {String} minText
10359      * The error text to display if the minDate validation fails (defaults to <code>'This date is before the minimum date'</code>)
10360      */
10361     minText : 'This date is before the minimum date',
10362     /**
10363      * @cfg {String} maxText
10364      * The error text to display if the maxDate validation fails (defaults to <code>'This date is after the maximum date'</code>)
10365      */
10366     maxText : 'This date is after the maximum date',
10367     /**
10368      * @cfg {String} format
10369      * The default date format string which can be overriden for localization support.  The format must be
10370      * valid according to {@link Date#parseDate} (defaults to <code>'m/d/y'</code>).
10371      */
10372     format : 'm/d/y',
10373     /**
10374      * @cfg {String} disabledDaysText
10375      * The tooltip to display when the date falls on a disabled day (defaults to <code>'Disabled'</code>)
10376      */
10377     disabledDaysText : 'Disabled',
10378     /**
10379      * @cfg {String} disabledDatesText
10380      * The tooltip text to display when the date falls on a disabled date (defaults to <code>'Disabled'</code>)
10381      */
10382     disabledDatesText : 'Disabled',
10383     /**
10384      * @cfg {Array} monthNames
10385      * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
10386      */
10387     monthNames : Date.monthNames,
10388     /**
10389      * @cfg {Array} dayNames
10390      * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
10391      */
10392     dayNames : Date.dayNames,
10393     /**
10394      * @cfg {String} nextText
10395      * The next month navigation button tooltip (defaults to <code>'Next Month (Control+Right)'</code>)
10396      */
10397     nextText : 'Next Month (Control+Right)',
10398     /**
10399      * @cfg {String} prevText
10400      * The previous month navigation button tooltip (defaults to <code>'Previous Month (Control+Left)'</code>)
10401      */
10402     prevText : 'Previous Month (Control+Left)',
10403     /**
10404      * @cfg {String} monthYearText
10405      * The header month selector tooltip (defaults to <code>'Choose a month (Control+Up/Down to move years)'</code>)
10406      */
10407     monthYearText : 'Choose a month (Control+Up/Down to move years)',
10408     /**
10409      * @cfg {Number} startDay
10410      * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
10411      */
10412     startDay : 0,
10413     /**
10414      * @cfg {Boolean} showToday
10415      * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar
10416      * that selects the current date (defaults to <code>true</code>).
10417      */
10418     showToday : true,
10419     /**
10420      * @cfg {Date} minDate
10421      * Minimum allowable date (JavaScript date object, defaults to null)
10422      */
10423     /**
10424      * @cfg {Date} maxDate
10425      * Maximum allowable date (JavaScript date object, defaults to null)
10426      */
10427     /**
10428      * @cfg {Array} disabledDays
10429      * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
10430      */
10431     /**
10432      * @cfg {RegExp} disabledDatesRE
10433      * JavaScript regular expression used to disable a pattern of dates (defaults to null).  The {@link #disabledDates}
10434      * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the
10435      * disabledDates value.
10436      */
10437     /**
10438      * @cfg {Array} disabledDates
10439      * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular
10440      * expression so they are very powerful. Some examples:
10441      * <ul>
10442      * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>
10443      * <li>['03/08', '09/16'] would disable those days for every year</li>
10444      * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>
10445      * <li>['03/../2006'] would disable every day in March 2006</li>
10446      * <li>['^03'] would disable every day in every March</li>
10447      * </ul>
10448      * Note that the format of the dates included in the array should exactly match the {@link #format} config.
10449      * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to
10450      * escape the dot when restricting dates. For example: ['03\\.08\\.03'].
10451      */
10452     
10453     // private
10454     // Set by other components to stop the picker focus being updated when the value changes.
10455     focusOnSelect: true,
10456
10457     // private
10458     initComponent : function(){
10459         Ext.DatePicker.superclass.initComponent.call(this);
10460
10461         this.value = this.value ?
10462                  this.value.clearTime(true) : new Date().clearTime();
10463
10464         this.addEvents(
10465             /**
10466              * @event select
10467              * Fires when a date is selected
10468              * @param {DatePicker} this DatePicker
10469              * @param {Date} date The selected date
10470              */
10471             'select'
10472         );
10473
10474         if(this.handler){
10475             this.on('select', this.handler,  this.scope || this);
10476         }
10477
10478         this.initDisabledDays();
10479     },
10480
10481     // private
10482     initDisabledDays : function(){
10483         if(!this.disabledDatesRE && this.disabledDates){
10484             var dd = this.disabledDates,
10485                 len = dd.length - 1,
10486                 re = '(?:';
10487                 
10488             Ext.each(dd, function(d, i){
10489                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
10490                 if(i != len){
10491                     re += '|';
10492                 }
10493             }, this);
10494             this.disabledDatesRE = new RegExp(re + ')');
10495         }
10496     },
10497
10498     /**
10499      * Replaces any existing disabled dates with new values and refreshes the DatePicker.
10500      * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config
10501      * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.
10502      */
10503     setDisabledDates : function(dd){
10504         if(Ext.isArray(dd)){
10505             this.disabledDates = dd;
10506             this.disabledDatesRE = null;
10507         }else{
10508             this.disabledDatesRE = dd;
10509         }
10510         this.initDisabledDays();
10511         this.update(this.value, true);
10512     },
10513
10514     /**
10515      * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.
10516      * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config
10517      * for details on supported values.
10518      */
10519     setDisabledDays : function(dd){
10520         this.disabledDays = dd;
10521         this.update(this.value, true);
10522     },
10523
10524     /**
10525      * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
10526      * @param {Date} value The minimum date that can be selected
10527      */
10528     setMinDate : function(dt){
10529         this.minDate = dt;
10530         this.update(this.value, true);
10531     },
10532
10533     /**
10534      * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
10535      * @param {Date} value The maximum date that can be selected
10536      */
10537     setMaxDate : function(dt){
10538         this.maxDate = dt;
10539         this.update(this.value, true);
10540     },
10541
10542     /**
10543      * Sets the value of the date field
10544      * @param {Date} value The date to set
10545      */
10546     setValue : function(value){
10547         this.value = value.clearTime(true);
10548         this.update(this.value);
10549     },
10550
10551     /**
10552      * Gets the current selected value of the date field
10553      * @return {Date} The selected date
10554      */
10555     getValue : function(){
10556         return this.value;
10557     },
10558
10559     // private
10560     focus : function(){
10561         this.update(this.activeDate);
10562     },
10563     
10564     // private
10565     onEnable: function(initial){
10566         Ext.DatePicker.superclass.onEnable.call(this);    
10567         this.doDisabled(false);
10568         this.update(initial ? this.value : this.activeDate);
10569         if(Ext.isIE){
10570             this.el.repaint();
10571         }
10572         
10573     },
10574     
10575     // private
10576     onDisable : function(){
10577         Ext.DatePicker.superclass.onDisable.call(this);   
10578         this.doDisabled(true);
10579         if(Ext.isIE && !Ext.isIE8){
10580             /* Really strange problem in IE6/7, when disabled, have to explicitly
10581              * repaint each of the nodes to get them to display correctly, simply
10582              * calling repaint on the main element doesn't appear to be enough.
10583              */
10584              Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
10585                  Ext.fly(el).repaint();
10586              });
10587         }
10588     },
10589     
10590     // private
10591     doDisabled : function(disabled){
10592         this.keyNav.setDisabled(disabled);
10593         this.prevRepeater.setDisabled(disabled);
10594         this.nextRepeater.setDisabled(disabled);
10595         if(this.showToday){
10596             this.todayKeyListener.setDisabled(disabled);
10597             this.todayBtn.setDisabled(disabled);
10598         }
10599     },
10600
10601     // private
10602     onRender : function(container, position){
10603         var m = [
10604              '<table cellspacing="0">',
10605                 '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'">&#160;</a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'">&#160;</a></td></tr>',
10606                 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
10607                 dn = this.dayNames,
10608                 i;
10609         for(i = 0; i < 7; i++){
10610             var d = this.startDay+i;
10611             if(d > 6){
10612                 d = d-7;
10613             }
10614             m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
10615         }
10616         m[m.length] = '</tr></thead><tbody><tr>';
10617         for(i = 0; i < 42; i++) {
10618             if(i % 7 === 0 && i !== 0){
10619                 m[m.length] = '</tr><tr>';
10620             }
10621             m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
10622         }
10623         m.push('</tr></tbody></table></td></tr>',
10624                 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
10625                 '</table><div class="x-date-mp"></div>');
10626
10627         var el = document.createElement('div');
10628         el.className = 'x-date-picker';
10629         el.innerHTML = m.join('');
10630
10631         container.dom.insertBefore(el, position);
10632
10633         this.el = Ext.get(el);
10634         this.eventEl = Ext.get(el.firstChild);
10635
10636         this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
10637             handler: this.showPrevMonth,
10638             scope: this,
10639             preventDefault:true,
10640             stopDefault:true
10641         });
10642
10643         this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
10644             handler: this.showNextMonth,
10645             scope: this,
10646             preventDefault:true,
10647             stopDefault:true
10648         });
10649
10650         this.monthPicker = this.el.down('div.x-date-mp');
10651         this.monthPicker.enableDisplayMode('block');
10652
10653         this.keyNav = new Ext.KeyNav(this.eventEl, {
10654             'left' : function(e){
10655                 if(e.ctrlKey){
10656                     this.showPrevMonth();
10657                 }else{
10658                     this.update(this.activeDate.add('d', -1));    
10659                 }
10660             },
10661
10662             'right' : function(e){
10663                 if(e.ctrlKey){
10664                     this.showNextMonth();
10665                 }else{
10666                     this.update(this.activeDate.add('d', 1));    
10667                 }
10668             },
10669
10670             'up' : function(e){
10671                 if(e.ctrlKey){
10672                     this.showNextYear();
10673                 }else{
10674                     this.update(this.activeDate.add('d', -7));
10675                 }
10676             },
10677
10678             'down' : function(e){
10679                 if(e.ctrlKey){
10680                     this.showPrevYear();
10681                 }else{
10682                     this.update(this.activeDate.add('d', 7));
10683                 }
10684             },
10685
10686             'pageUp' : function(e){
10687                 this.showNextMonth();
10688             },
10689
10690             'pageDown' : function(e){
10691                 this.showPrevMonth();
10692             },
10693
10694             'enter' : function(e){
10695                 e.stopPropagation();
10696                 return true;
10697             },
10698
10699             scope : this
10700         });
10701
10702         this.el.unselectable();
10703
10704         this.cells = this.el.select('table.x-date-inner tbody td');
10705         this.textNodes = this.el.query('table.x-date-inner tbody span');
10706
10707         this.mbtn = new Ext.Button({
10708             text: '&#160;',
10709             tooltip: this.monthYearText,
10710             renderTo: this.el.child('td.x-date-middle', true)
10711         });
10712         this.mbtn.el.child('em').addClass('x-btn-arrow');
10713
10714         if(this.showToday){
10715             this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
10716             var today = (new Date()).dateFormat(this.format);
10717             this.todayBtn = new Ext.Button({
10718                 renderTo: this.el.child('td.x-date-bottom', true),
10719                 text: String.format(this.todayText, today),
10720                 tooltip: String.format(this.todayTip, today),
10721                 handler: this.selectToday,
10722                 scope: this
10723             });
10724         }
10725         this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
10726         this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
10727         this.mon(this.mbtn, 'click', this.showMonthPicker, this);
10728         this.onEnable(true);
10729     },
10730
10731     // private
10732     createMonthPicker : function(){
10733         if(!this.monthPicker.dom.firstChild){
10734             var buf = ['<table border="0" cellspacing="0">'];
10735             for(var i = 0; i < 6; i++){
10736                 buf.push(
10737                     '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
10738                     '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
10739                     i === 0 ?
10740                     '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
10741                     '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
10742                 );
10743             }
10744             buf.push(
10745                 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
10746                     this.okText,
10747                     '</button><button type="button" class="x-date-mp-cancel">',
10748                     this.cancelText,
10749                     '</button></td></tr>',
10750                 '</table>'
10751             );
10752             this.monthPicker.update(buf.join(''));
10753
10754             this.mon(this.monthPicker, 'click', this.onMonthClick, this);
10755             this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
10756
10757             this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
10758             this.mpYears = this.monthPicker.select('td.x-date-mp-year');
10759
10760             this.mpMonths.each(function(m, a, i){
10761                 i += 1;
10762                 if((i%2) === 0){
10763                     m.dom.xmonth = 5 + Math.round(i * 0.5);
10764                 }else{
10765                     m.dom.xmonth = Math.round((i-1) * 0.5);
10766                 }
10767             });
10768         }
10769     },
10770
10771     // private
10772     showMonthPicker : function(){
10773         if(!this.disabled){
10774             this.createMonthPicker();
10775             var size = this.el.getSize();
10776             this.monthPicker.setSize(size);
10777             this.monthPicker.child('table').setSize(size);
10778
10779             this.mpSelMonth = (this.activeDate || this.value).getMonth();
10780             this.updateMPMonth(this.mpSelMonth);
10781             this.mpSelYear = (this.activeDate || this.value).getFullYear();
10782             this.updateMPYear(this.mpSelYear);
10783
10784             this.monthPicker.slideIn('t', {duration:0.2});
10785         }
10786     },
10787
10788     // private
10789     updateMPYear : function(y){
10790         this.mpyear = y;
10791         var ys = this.mpYears.elements;
10792         for(var i = 1; i <= 10; i++){
10793             var td = ys[i-1], y2;
10794             if((i%2) === 0){
10795                 y2 = y + Math.round(i * 0.5);
10796                 td.firstChild.innerHTML = y2;
10797                 td.xyear = y2;
10798             }else{
10799                 y2 = y - (5-Math.round(i * 0.5));
10800                 td.firstChild.innerHTML = y2;
10801                 td.xyear = y2;
10802             }
10803             this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
10804         }
10805     },
10806
10807     // private
10808     updateMPMonth : function(sm){
10809         this.mpMonths.each(function(m, a, i){
10810             m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
10811         });
10812     },
10813
10814     // private
10815     selectMPMonth : function(m){
10816
10817     },
10818
10819     // private
10820     onMonthClick : function(e, t){
10821         e.stopEvent();
10822         var el = new Ext.Element(t), pn;
10823         if(el.is('button.x-date-mp-cancel')){
10824             this.hideMonthPicker();
10825         }
10826         else if(el.is('button.x-date-mp-ok')){
10827             var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
10828             if(d.getMonth() != this.mpSelMonth){
10829                 // 'fix' the JS rolling date conversion if needed
10830                 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
10831             }
10832             this.update(d);
10833             this.hideMonthPicker();
10834         }
10835         else if((pn = el.up('td.x-date-mp-month', 2))){
10836             this.mpMonths.removeClass('x-date-mp-sel');
10837             pn.addClass('x-date-mp-sel');
10838             this.mpSelMonth = pn.dom.xmonth;
10839         }
10840         else if((pn = el.up('td.x-date-mp-year', 2))){
10841             this.mpYears.removeClass('x-date-mp-sel');
10842             pn.addClass('x-date-mp-sel');
10843             this.mpSelYear = pn.dom.xyear;
10844         }
10845         else if(el.is('a.x-date-mp-prev')){
10846             this.updateMPYear(this.mpyear-10);
10847         }
10848         else if(el.is('a.x-date-mp-next')){
10849             this.updateMPYear(this.mpyear+10);
10850         }
10851     },
10852
10853     // private
10854     onMonthDblClick : function(e, t){
10855         e.stopEvent();
10856         var el = new Ext.Element(t), pn;
10857         if((pn = el.up('td.x-date-mp-month', 2))){
10858             this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
10859             this.hideMonthPicker();
10860         }
10861         else if((pn = el.up('td.x-date-mp-year', 2))){
10862             this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
10863             this.hideMonthPicker();
10864         }
10865     },
10866
10867     // private
10868     hideMonthPicker : function(disableAnim){
10869         if(this.monthPicker){
10870             if(disableAnim === true){
10871                 this.monthPicker.hide();
10872             }else{
10873                 this.monthPicker.slideOut('t', {duration:0.2});
10874             }
10875         }
10876     },
10877
10878     // private
10879     showPrevMonth : function(e){
10880         this.update(this.activeDate.add('mo', -1));
10881     },
10882
10883     // private
10884     showNextMonth : function(e){
10885         this.update(this.activeDate.add('mo', 1));
10886     },
10887
10888     // private
10889     showPrevYear : function(){
10890         this.update(this.activeDate.add('y', -1));
10891     },
10892
10893     // private
10894     showNextYear : function(){
10895         this.update(this.activeDate.add('y', 1));
10896     },
10897
10898     // private
10899     handleMouseWheel : function(e){
10900         e.stopEvent();
10901         if(!this.disabled){
10902             var delta = e.getWheelDelta();
10903             if(delta > 0){
10904                 this.showPrevMonth();
10905             } else if(delta < 0){
10906                 this.showNextMonth();
10907             }
10908         }
10909     },
10910
10911     // private
10912     handleDateClick : function(e, t){
10913         e.stopEvent();
10914         if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
10915             this.cancelFocus = this.focusOnSelect === false;
10916             this.setValue(new Date(t.dateValue));
10917             delete this.cancelFocus;
10918             this.fireEvent('select', this, this.value);
10919         }
10920     },
10921
10922     // private
10923     selectToday : function(){
10924         if(this.todayBtn && !this.todayBtn.disabled){
10925             this.setValue(new Date().clearTime());
10926             this.fireEvent('select', this, this.value);
10927         }
10928     },
10929
10930     // private
10931     update : function(date, forceRefresh){
10932         if(this.rendered){
10933                 var vd = this.activeDate, vis = this.isVisible();
10934                 this.activeDate = date;
10935                 if(!forceRefresh && vd && this.el){
10936                     var t = date.getTime();
10937                     if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
10938                         this.cells.removeClass('x-date-selected');
10939                         this.cells.each(function(c){
10940                            if(c.dom.firstChild.dateValue == t){
10941                                c.addClass('x-date-selected');
10942                                if(vis && !this.cancelFocus){
10943                                    Ext.fly(c.dom.firstChild).focus(50);
10944                                }
10945                                return false;
10946                            }
10947                         }, this);
10948                         return;
10949                     }
10950                 }
10951                 var days = date.getDaysInMonth(),
10952                     firstOfMonth = date.getFirstDateOfMonth(),
10953                     startingPos = firstOfMonth.getDay()-this.startDay;
10954         
10955                 if(startingPos < 0){
10956                     startingPos += 7;
10957                 }
10958                 days += startingPos;
10959         
10960                 var pm = date.add('mo', -1),
10961                     prevStart = pm.getDaysInMonth()-startingPos,
10962                     cells = this.cells.elements,
10963                     textEls = this.textNodes,
10964                     // convert everything to numbers so it's fast
10965                     day = 86400000,
10966                     d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime(),
10967                     today = new Date().clearTime().getTime(),
10968                     sel = date.clearTime(true).getTime(),
10969                     min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
10970                     max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
10971                     ddMatch = this.disabledDatesRE,
10972                     ddText = this.disabledDatesText,
10973                     ddays = this.disabledDays ? this.disabledDays.join('') : false,
10974                     ddaysText = this.disabledDaysText,
10975                     format = this.format;
10976         
10977                 if(this.showToday){
10978                     var td = new Date().clearTime(),
10979                         disable = (td < min || td > max ||
10980                         (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
10981                         (ddays && ddays.indexOf(td.getDay()) != -1));
10982         
10983                     if(!this.disabled){
10984                         this.todayBtn.setDisabled(disable);
10985                         this.todayKeyListener[disable ? 'disable' : 'enable']();
10986                     }
10987                 }
10988         
10989                 var setCellClass = function(cal, cell){
10990                     cell.title = '';
10991                     var t = d.getTime();
10992                     cell.firstChild.dateValue = t;
10993                     if(t == today){
10994                         cell.className += ' x-date-today';
10995                         cell.title = cal.todayText;
10996                     }
10997                     if(t == sel){
10998                         cell.className += ' x-date-selected';
10999                         if(vis){
11000                             Ext.fly(cell.firstChild).focus(50);
11001                         }
11002                     }
11003                     // disabling
11004                     if(t < min) {
11005                         cell.className = ' x-date-disabled';
11006                         cell.title = cal.minText;
11007                         return;
11008                     }
11009                     if(t > max) {
11010                         cell.className = ' x-date-disabled';
11011                         cell.title = cal.maxText;
11012                         return;
11013                     }
11014                     if(ddays){
11015                         if(ddays.indexOf(d.getDay()) != -1){
11016                             cell.title = ddaysText;
11017                             cell.className = ' x-date-disabled';
11018                         }
11019                     }
11020                     if(ddMatch && format){
11021                         var fvalue = d.dateFormat(format);
11022                         if(ddMatch.test(fvalue)){
11023                             cell.title = ddText.replace('%0', fvalue);
11024                             cell.className = ' x-date-disabled';
11025                         }
11026                     }
11027                 };
11028         
11029                 var i = 0;
11030                 for(; i < startingPos; i++) {
11031                     textEls[i].innerHTML = (++prevStart);
11032                     d.setDate(d.getDate()+1);
11033                     cells[i].className = 'x-date-prevday';
11034                     setCellClass(this, cells[i]);
11035                 }
11036                 for(; i < days; i++){
11037                     var intDay = i - startingPos + 1;
11038                     textEls[i].innerHTML = (intDay);
11039                     d.setDate(d.getDate()+1);
11040                     cells[i].className = 'x-date-active';
11041                     setCellClass(this, cells[i]);
11042                 }
11043                 var extraDays = 0;
11044                 for(; i < 42; i++) {
11045                      textEls[i].innerHTML = (++extraDays);
11046                      d.setDate(d.getDate()+1);
11047                      cells[i].className = 'x-date-nextday';
11048                      setCellClass(this, cells[i]);
11049                 }
11050         
11051                 this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
11052         
11053                 if(!this.internalRender){
11054                     var main = this.el.dom.firstChild,
11055                         w = main.offsetWidth;
11056                     this.el.setWidth(w + this.el.getBorderWidth('lr'));
11057                     Ext.fly(main).setWidth(w);
11058                     this.internalRender = true;
11059                     // opera does not respect the auto grow header center column
11060                     // then, after it gets a width opera refuses to recalculate
11061                     // without a second pass
11062                     if(Ext.isOpera && !this.secondPass){
11063                         main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
11064                         this.secondPass = true;
11065                         this.update.defer(10, this, [date]);
11066                     }
11067                 }
11068         }
11069     },
11070
11071     // private
11072     beforeDestroy : function() {
11073         if(this.rendered){
11074             Ext.destroy(
11075                 this.keyNav,
11076                 this.monthPicker,
11077                 this.eventEl,
11078                 this.mbtn,
11079                 this.nextRepeater,
11080                 this.prevRepeater,
11081                 this.cells.el,
11082                 this.todayBtn
11083             );
11084             delete this.textNodes;
11085             delete this.cells.elements;
11086         }
11087     }
11088
11089     /**
11090      * @cfg {String} autoEl @hide
11091      */
11092 });
11093
11094 Ext.reg('datepicker', Ext.DatePicker);
11095 /**
11096  * @class Ext.LoadMask
11097  * A simple utility class for generically masking elements while loading data.  If the {@link #store}
11098  * config option is specified, the masking will be automatically synchronized with the store's loading
11099  * process and the mask element will be cached for reuse.  For all other elements, this mask will replace the
11100  * element's Updater load indicator and will be destroyed after the initial load.
11101  * <p>Example usage:</p>
11102  *<pre><code>
11103 // Basic mask:
11104 var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
11105 myMask.show();
11106 </code></pre>
11107  * @constructor
11108  * Create a new LoadMask
11109  * @param {Mixed} el The element or DOM node, or its id
11110  * @param {Object} config The config object
11111  */
11112 Ext.LoadMask = function(el, config){
11113     this.el = Ext.get(el);
11114     Ext.apply(this, config);
11115     if(this.store){
11116         this.store.on({
11117             scope: this,
11118             beforeload: this.onBeforeLoad,
11119             load: this.onLoad,
11120             exception: this.onLoad
11121         });
11122         this.removeMask = Ext.value(this.removeMask, false);
11123     }else{
11124         var um = this.el.getUpdater();
11125         um.showLoadIndicator = false; // disable the default indicator
11126         um.on({
11127             scope: this,
11128             beforeupdate: this.onBeforeLoad,
11129             update: this.onLoad,
11130             failure: this.onLoad
11131         });
11132         this.removeMask = Ext.value(this.removeMask, true);
11133     }
11134 };
11135
11136 Ext.LoadMask.prototype = {
11137     /**
11138      * @cfg {Ext.data.Store} store
11139      * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and
11140      * hidden on either load sucess, or load fail.
11141      */
11142     /**
11143      * @cfg {Boolean} removeMask
11144      * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
11145      * False to persist the mask element reference for multiple uses (e.g., for paged data widgets).  Defaults to false.
11146      */
11147     /**
11148      * @cfg {String} msg
11149      * The text to display in a centered loading message box (defaults to 'Loading...')
11150      */
11151     msg : 'Loading...',
11152     /**
11153      * @cfg {String} msgCls
11154      * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
11155      */
11156     msgCls : 'x-mask-loading',
11157
11158     /**
11159      * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
11160      * @type Boolean
11161      */
11162     disabled: false,
11163
11164     /**
11165      * Disables the mask to prevent it from being displayed
11166      */
11167     disable : function(){
11168        this.disabled = true;
11169     },
11170
11171     /**
11172      * Enables the mask so that it can be displayed
11173      */
11174     enable : function(){
11175         this.disabled = false;
11176     },
11177
11178     // private
11179     onLoad : function(){
11180         this.el.unmask(this.removeMask);
11181     },
11182
11183     // private
11184     onBeforeLoad : function(){
11185         if(!this.disabled){
11186             this.el.mask(this.msg, this.msgCls);
11187         }
11188     },
11189
11190     /**
11191      * Show this LoadMask over the configured Element.
11192      */
11193     show: function(){
11194         this.onBeforeLoad();
11195     },
11196
11197     /**
11198      * Hide this LoadMask.
11199      */
11200     hide: function(){
11201         this.onLoad();
11202     },
11203
11204     // private
11205     destroy : function(){
11206         if(this.store){
11207             this.store.un('beforeload', this.onBeforeLoad, this);
11208             this.store.un('load', this.onLoad, this);
11209             this.store.un('exception', this.onLoad, this);
11210         }else{
11211             var um = this.el.getUpdater();
11212             um.un('beforeupdate', this.onBeforeLoad, this);
11213             um.un('update', this.onLoad, this);
11214             um.un('failure', this.onLoad, this);
11215         }
11216     }
11217 };/**\r
11218  * @class Ext.Slider\r
11219  * @extends Ext.BoxComponent\r
11220  * Slider which supports vertical or horizontal orientation, keyboard adjustments,\r
11221  * configurable snapping, axis clicking and animation. Can be added as an item to\r
11222  * any container. Example usage:\r
11223 <pre><code>\r
11224 new Ext.Slider({\r
11225     renderTo: Ext.getBody(),\r
11226     width: 200,\r
11227     value: 50,\r
11228     increment: 10,\r
11229     minValue: 0,\r
11230     maxValue: 100\r
11231 });\r
11232 </code></pre>\r
11233  */\r
11234 Ext.Slider = Ext.extend(Ext.BoxComponent, {\r
11235         /**\r
11236          * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.\r
11237          */\r
11238         /**\r
11239          * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.\r
11240          */\r
11241     vertical: false,\r
11242         /**\r
11243          * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.\r
11244          */\r
11245     minValue: 0,\r
11246         /**\r
11247          * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.\r
11248          */\r
11249     maxValue: 100,\r
11250     /**\r
11251      * @cfg {Number/Boolean} decimalPrecision.\r
11252      * <p>The number of decimal places to which to round the Slider's value. Defaults to 0.</p>\r
11253      * <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>\r
11254      */\r
11255     decimalPrecision: 0,\r
11256         /**\r
11257          * @cfg {Number} keyIncrement How many units to change the Slider when adjusting with keyboard navigation. Defaults to 1. If the increment config is larger, it will be used instead.\r
11258          */\r
11259     keyIncrement: 1,\r
11260         /**\r
11261          * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.\r
11262          */\r
11263     increment: 0,\r
11264         // private\r
11265     clickRange: [5,15],\r
11266         /**\r
11267          * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true\r
11268          */\r
11269     clickToChange : true,\r
11270         /**\r
11271          * @cfg {Boolean} animate Turn on or off animation. Defaults to true\r
11272          */\r
11273     animate: true,\r
11274 \r
11275     /**\r
11276      * True while the thumb is in a drag operation\r
11277      * @type boolean\r
11278      */\r
11279     dragging: false,\r
11280 \r
11281     // private override\r
11282     initComponent : function(){\r
11283         if(!Ext.isDefined(this.value)){\r
11284             this.value = this.minValue;\r
11285         }\r
11286         Ext.Slider.superclass.initComponent.call(this);\r
11287         this.keyIncrement = Math.max(this.increment, this.keyIncrement);\r
11288         this.addEvents(\r
11289             /**\r
11290              * @event beforechange\r
11291              * Fires before the slider value is changed. By returning false from an event handler,\r
11292              * you can cancel the event and prevent the slider from changing.\r
11293                          * @param {Ext.Slider} slider The slider\r
11294                          * @param {Number} newValue The new value which the slider is being changed to.\r
11295                          * @param {Number} oldValue The old value which the slider was previously.\r
11296              */\r
11297                         'beforechange',\r
11298                         /**\r
11299                          * @event change\r
11300                          * Fires when the slider value is changed.\r
11301                          * @param {Ext.Slider} slider The slider\r
11302                          * @param {Number} newValue The new value which the slider has been changed to.\r
11303                          */\r
11304                         'change',\r
11305                         /**\r
11306                          * @event changecomplete\r
11307                          * Fires when the slider value is changed by the user and any drag operations have completed.\r
11308                          * @param {Ext.Slider} slider The slider\r
11309                          * @param {Number} newValue The new value which the slider has been changed to.\r
11310                          */\r
11311                         'changecomplete',\r
11312                         /**\r
11313                          * @event dragstart\r
11314              * Fires after a drag operation has started.\r
11315                          * @param {Ext.Slider} slider The slider\r
11316                          * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
11317                          */\r
11318                         'dragstart',\r
11319                         /**\r
11320                          * @event drag\r
11321              * Fires continuously during the drag operation while the mouse is moving.\r
11322                          * @param {Ext.Slider} slider The slider\r
11323                          * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
11324                          */\r
11325                         'drag',\r
11326                         /**\r
11327                          * @event dragend\r
11328              * Fires after the drag operation has completed.\r
11329                          * @param {Ext.Slider} slider The slider\r
11330                          * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
11331                          */\r
11332                         'dragend'\r
11333                 );\r
11334 \r
11335         if(this.vertical){\r
11336             Ext.apply(this, Ext.Slider.Vertical);\r
11337         }\r
11338     },\r
11339 \r
11340         // private override\r
11341     onRender : function(){\r
11342         this.autoEl = {\r
11343             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),\r
11344             cn:{cls:'x-slider-end',cn:{cls:'x-slider-inner',cn:[{cls:'x-slider-thumb'},{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]}}\r
11345         };\r
11346         Ext.Slider.superclass.onRender.apply(this, arguments);\r
11347         this.endEl = this.el.first();\r
11348         this.innerEl = this.endEl.first();\r
11349         this.thumb = this.innerEl.first();\r
11350         this.halfThumb = (this.vertical ? this.thumb.getHeight() : this.thumb.getWidth())/2;\r
11351         this.focusEl = this.thumb.next();\r
11352         this.initEvents();\r
11353     },\r
11354 \r
11355         // private override\r
11356     initEvents : function(){\r
11357         this.thumb.addClassOnOver('x-slider-thumb-over');\r
11358         this.mon(this.el, {\r
11359             scope: this,\r
11360             mousedown: this.onMouseDown,\r
11361             keydown: this.onKeyDown\r
11362         });\r
11363 \r
11364         this.focusEl.swallowEvent("click", true);\r
11365 \r
11366         this.tracker = new Ext.dd.DragTracker({\r
11367             onBeforeStart: this.onBeforeDragStart.createDelegate(this),\r
11368             onStart: this.onDragStart.createDelegate(this),\r
11369             onDrag: this.onDrag.createDelegate(this),\r
11370             onEnd: this.onDragEnd.createDelegate(this),\r
11371             tolerance: 3,\r
11372             autoStart: 300\r
11373         });\r
11374         this.tracker.initEl(this.thumb);\r
11375     },\r
11376 \r
11377         // private override\r
11378     onMouseDown : function(e){\r
11379         if(this.disabled){\r
11380             return;\r
11381         }\r
11382         if(this.clickToChange && e.target != this.thumb.dom){\r
11383             var local = this.innerEl.translatePoints(e.getXY());\r
11384             this.onClickChange(local);\r
11385         }\r
11386         this.focus();\r
11387     },\r
11388 \r
11389         // private\r
11390     onClickChange : function(local){\r
11391         if(local.top > this.clickRange[0] && local.top < this.clickRange[1]){\r
11392             this.setValue(Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);\r
11393         }\r
11394     },\r
11395 \r
11396         // private\r
11397     onKeyDown : function(e){\r
11398         if(this.disabled){e.preventDefault();return;}\r
11399         var k = e.getKey();\r
11400         switch(k){\r
11401             case e.UP:\r
11402             case e.RIGHT:\r
11403                 e.stopEvent();\r
11404                 if(e.ctrlKey){\r
11405                     this.setValue(this.maxValue, undefined, true);\r
11406                 }else{\r
11407                     this.setValue(this.value+this.keyIncrement, undefined, true);\r
11408                 }\r
11409             break;\r
11410             case e.DOWN:\r
11411             case e.LEFT:\r
11412                 e.stopEvent();\r
11413                 if(e.ctrlKey){\r
11414                     this.setValue(this.minValue, undefined, true);\r
11415                 }else{\r
11416                     this.setValue(this.value-this.keyIncrement, undefined, true);\r
11417                 }\r
11418             break;\r
11419             default:\r
11420                 e.preventDefault();\r
11421         }\r
11422     },\r
11423 \r
11424         // private\r
11425     doSnap : function(value){\r
11426         if(!(this.increment && value)){\r
11427             return value;\r
11428         }\r
11429         var newValue = value, \r
11430             inc = this.increment,\r
11431             m = value % inc;\r
11432         if(m != 0){\r
11433             newValue -= m;\r
11434             if(m * 2 > inc){\r
11435                 newValue += inc;\r
11436             }else if(m * 2 < -inc){\r
11437                 newValue -= inc;\r
11438             }\r
11439         }\r
11440         return newValue.constrain(this.minValue,  this.maxValue);\r
11441     },\r
11442 \r
11443         // private\r
11444     afterRender : function(){\r
11445         Ext.Slider.superclass.afterRender.apply(this, arguments);\r
11446         if(this.value !== undefined){\r
11447             var v = this.normalizeValue(this.value);\r
11448             if(v !== this.value){\r
11449                 delete this.value;\r
11450                 this.setValue(v, false);\r
11451             }else{\r
11452                 this.moveThumb(this.translateValue(v), false);\r
11453             }\r
11454         }\r
11455     },\r
11456 \r
11457         // private\r
11458     getRatio : function(){\r
11459         var w = this.innerEl.getWidth(),\r
11460             v = this.maxValue - this.minValue;\r
11461         return v == 0 ? w : (w/v);\r
11462     },\r
11463 \r
11464         // private\r
11465     normalizeValue : function(v){\r
11466         v = this.doSnap(v);\r
11467         v = Ext.util.Format.round(v, this.decimalPrecision);\r
11468         v = v.constrain(this.minValue, this.maxValue);\r
11469         return v;\r
11470     },\r
11471 \r
11472         /**\r
11473          * Programmatically sets the value of the Slider. Ensures that the value is constrained within\r
11474          * the minValue and maxValue.\r
11475          * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)\r
11476          * @param {Boolean} animate Turn on or off animation, defaults to true\r
11477          */\r
11478     setValue : function(v, animate, changeComplete){\r
11479         v = this.normalizeValue(v);\r
11480         if(v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false){\r
11481             this.value = v;\r
11482             this.moveThumb(this.translateValue(v), animate !== false);\r
11483             this.fireEvent('change', this, v);\r
11484             if(changeComplete){\r
11485                 this.fireEvent('changecomplete', this, v);\r
11486             }\r
11487         }\r
11488     },\r
11489 \r
11490         // private\r
11491     translateValue : function(v){\r
11492         var ratio = this.getRatio();\r
11493         return (v * ratio) - (this.minValue * ratio) - this.halfThumb;\r
11494     },\r
11495 \r
11496         reverseValue : function(pos){\r
11497         var ratio = this.getRatio();\r
11498         return (pos + this.halfThumb + (this.minValue * ratio)) / ratio;\r
11499     },\r
11500 \r
11501         // private\r
11502     moveThumb: function(v, animate){\r
11503         if(!animate || this.animate === false){\r
11504             this.thumb.setLeft(v);\r
11505         }else{\r
11506             this.thumb.shift({left: v, stopFx: true, duration:.35});\r
11507         }\r
11508     },\r
11509 \r
11510         // private\r
11511     focus : function(){\r
11512         this.focusEl.focus(10);\r
11513     },\r
11514 \r
11515         // private\r
11516     onBeforeDragStart : function(e){\r
11517         return !this.disabled;\r
11518     },\r
11519 \r
11520         // private\r
11521     onDragStart: function(e){\r
11522         this.thumb.addClass('x-slider-thumb-drag');\r
11523         this.dragging = true;\r
11524         this.dragStartValue = this.value;\r
11525         this.fireEvent('dragstart', this, e);\r
11526     },\r
11527 \r
11528         // private\r
11529     onDrag: function(e){\r
11530         var pos = this.innerEl.translatePoints(this.tracker.getXY());\r
11531         this.setValue(Ext.util.Format.round(this.reverseValue(pos.left), this.decimalPrecision), false);\r
11532         this.fireEvent('drag', this, e);\r
11533     },\r
11534 \r
11535         // private\r
11536     onDragEnd: function(e){\r
11537         this.thumb.removeClass('x-slider-thumb-drag');\r
11538         this.dragging = false;\r
11539         this.fireEvent('dragend', this, e);\r
11540         if(this.dragStartValue != this.value){\r
11541             this.fireEvent('changecomplete', this, this.value);\r
11542         }\r
11543     },\r
11544 \r
11545         // private\r
11546     onResize : function(w, h){\r
11547         this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));\r
11548         this.syncThumb();\r
11549     },\r
11550     \r
11551     //private\r
11552     onDisable: function(){\r
11553         Ext.Slider.superclass.onDisable.call(this);\r
11554         this.thumb.addClass(this.disabledClass);\r
11555         if(Ext.isIE){\r
11556             //IE breaks when using overflow visible and opacity other than 1.\r
11557             //Create a place holder for the thumb and display it.\r
11558             var xy = this.thumb.getXY();\r
11559             this.thumb.hide();\r
11560             this.innerEl.addClass(this.disabledClass).dom.disabled = true;\r
11561             if (!this.thumbHolder){\r
11562                 this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});    \r
11563             }\r
11564             this.thumbHolder.show().setXY(xy);\r
11565         }\r
11566     },\r
11567     \r
11568     //private\r
11569     onEnable: function(){\r
11570         Ext.Slider.superclass.onEnable.call(this);\r
11571         this.thumb.removeClass(this.disabledClass);\r
11572         if(Ext.isIE){\r
11573             this.innerEl.removeClass(this.disabledClass).dom.disabled = false;\r
11574             if(this.thumbHolder){\r
11575                 this.thumbHolder.hide();\r
11576             }\r
11577             this.thumb.show();\r
11578             this.syncThumb();\r
11579         }\r
11580     },\r
11581     \r
11582     /**\r
11583      * Synchronizes the thumb position to the proper proportion of the total component width based\r
11584      * on the current slider {@link #value}.  This will be called automatically when the Slider\r
11585      * is resized by a layout, but if it is rendered auto width, this method can be called from\r
11586      * another resize handler to sync the Slider if necessary.\r
11587      */\r
11588     syncThumb : function(){\r
11589         if(this.rendered){\r
11590             this.moveThumb(this.translateValue(this.value));\r
11591         }\r
11592     },\r
11593 \r
11594         /**\r
11595          * Returns the current value of the slider\r
11596          * @return {Number} The current value of the slider\r
11597          */\r
11598     getValue : function(){\r
11599         return this.value;\r
11600     },\r
11601     \r
11602     // private\r
11603     beforeDestroy : function(){\r
11604         Ext.destroyMembers(this, 'endEl', 'innerEl', 'thumb', 'halfThumb', 'focusEl', 'tracker', 'thumbHolder');\r
11605         Ext.Slider.superclass.beforeDestroy.call(this);\r
11606     }\r
11607 });\r
11608 Ext.reg('slider', Ext.Slider);\r
11609 \r
11610 // private class to support vertical sliders\r
11611 Ext.Slider.Vertical = {\r
11612     onResize : function(w, h){\r
11613         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));\r
11614         this.syncThumb();\r
11615     },\r
11616 \r
11617     getRatio : function(){\r
11618         var h = this.innerEl.getHeight(),\r
11619             v = this.maxValue - this.minValue;\r
11620         return h/v;\r
11621     },\r
11622 \r
11623     moveThumb: function(v, animate){\r
11624         if(!animate || this.animate === false){\r
11625             this.thumb.setBottom(v);\r
11626         }else{\r
11627             this.thumb.shift({bottom: v, stopFx: true, duration:.35});\r
11628         }\r
11629     },\r
11630 \r
11631     onDrag: function(e){\r
11632         var pos = this.innerEl.translatePoints(this.tracker.getXY()),\r
11633             bottom = this.innerEl.getHeight()-pos.top;\r
11634         this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), false);\r
11635         this.fireEvent('drag', this, e);\r
11636     },\r
11637 \r
11638     onClickChange : function(local){\r
11639         if(local.left > this.clickRange[0] && local.left < this.clickRange[1]){\r
11640             var bottom = this.innerEl.getHeight() - local.top;\r
11641             this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), undefined, true);\r
11642         }\r
11643     }\r
11644 };/**\r
11645  * @class Ext.ProgressBar\r
11646  * @extends Ext.BoxComponent\r
11647  * <p>An updateable progress bar component.  The progress bar supports two different modes: manual and automatic.</p>\r
11648  * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the\r
11649  * progress bar as needed from your own code.  This method is most appropriate when you want to show progress\r
11650  * throughout an operation that has predictable points of interest at which you can update the control.</p>\r
11651  * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it\r
11652  * once the operation is complete.  You can optionally have the progress bar wait for a specific amount of time\r
11653  * and then clear itself.  Automatic mode is most appropriate for timed operations or asynchronous operations in\r
11654  * which you have no need for indicating intermediate progress.</p>\r
11655  * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0)\r
11656  * @cfg {String} text The progress bar text (defaults to '')\r
11657  * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress\r
11658  * bar's internal text element)\r
11659  * @cfg {String} id The progress bar element's id (defaults to an auto-generated id)\r
11660  * @xtype progress\r
11661  */\r
11662 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {\r
11663    /**\r
11664     * @cfg {String} baseCls\r
11665     * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress')\r
11666     */\r
11667     baseCls : 'x-progress',\r
11668     \r
11669     /**\r
11670     * @cfg {Boolean} animate\r
11671     * True to animate the progress bar during transitions (defaults to false)\r
11672     */\r
11673     animate : false,\r
11674 \r
11675     // private\r
11676     waitTimer : null,\r
11677 \r
11678     // private\r
11679     initComponent : function(){\r
11680         Ext.ProgressBar.superclass.initComponent.call(this);\r
11681         this.addEvents(\r
11682             /**\r
11683              * @event update\r
11684              * Fires after each update interval\r
11685              * @param {Ext.ProgressBar} this\r
11686              * @param {Number} The current progress value\r
11687              * @param {String} The current progress text\r
11688              */\r
11689             "update"\r
11690         );\r
11691     },\r
11692 \r
11693     // private\r
11694     onRender : function(ct, position){\r
11695         var tpl = new Ext.Template(\r
11696             '<div class="{cls}-wrap">',\r
11697                 '<div class="{cls}-inner">',\r
11698                     '<div class="{cls}-bar">',\r
11699                         '<div class="{cls}-text">',\r
11700                             '<div>&#160;</div>',\r
11701                         '</div>',\r
11702                     '</div>',\r
11703                     '<div class="{cls}-text {cls}-text-back">',\r
11704                         '<div>&#160;</div>',\r
11705                     '</div>',\r
11706                 '</div>',\r
11707             '</div>'\r
11708         );\r
11709 \r
11710         this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)\r
11711                 : tpl.append(ct, {cls: this.baseCls}, true);\r
11712                         \r
11713         if(this.id){\r
11714             this.el.dom.id = this.id;\r
11715         }\r
11716         var inner = this.el.dom.firstChild;\r
11717         this.progressBar = Ext.get(inner.firstChild);\r
11718 \r
11719         if(this.textEl){\r
11720             //use an external text el\r
11721             this.textEl = Ext.get(this.textEl);\r
11722             delete this.textTopEl;\r
11723         }else{\r
11724             //setup our internal layered text els\r
11725             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);\r
11726             var textBackEl = Ext.get(inner.childNodes[1]);\r
11727             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');\r
11728             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);\r
11729             this.textEl.setWidth(inner.offsetWidth);\r
11730         }\r
11731         this.progressBar.setHeight(inner.offsetHeight);\r
11732     },\r
11733     \r
11734     // private\r
11735     afterRender : function(){\r
11736         Ext.ProgressBar.superclass.afterRender.call(this);\r
11737         if(this.value){\r
11738             this.updateProgress(this.value, this.text);\r
11739         }else{\r
11740             this.updateText(this.text);\r
11741         }\r
11742     },\r
11743 \r
11744     /**\r
11745      * Updates the progress bar value, and optionally its text.  If the text argument is not specified,\r
11746      * any existing text value will be unchanged.  To blank out existing text, pass ''.  Note that even\r
11747      * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for\r
11748      * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control.\r
11749      * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0)\r
11750      * @param {String} text (optional) The string to display in the progress text element (defaults to '')\r
11751      * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is\r
11752      * not specified, the default for the class is used (default to false)\r
11753      * @return {Ext.ProgressBar} this\r
11754      */\r
11755     updateProgress : function(value, text, animate){\r
11756         this.value = value || 0;\r
11757         if(text){\r
11758             this.updateText(text);\r
11759         }\r
11760         if(this.rendered){\r
11761             var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);\r
11762             this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));\r
11763             if(this.textTopEl){\r
11764                 //textTopEl should be the same width as the bar so overflow will clip as the bar moves\r
11765                 this.textTopEl.removeClass('x-hidden').setWidth(w);\r
11766             }\r
11767         }\r
11768         this.fireEvent('update', this, value, text);\r
11769         return this;\r
11770     },\r
11771 \r
11772     /**\r
11773      * Initiates an auto-updating progress bar.  A duration can be specified, in which case the progress\r
11774      * bar will automatically reset after a fixed amount of time and optionally call a callback function\r
11775      * if specified.  If no duration is passed in, then the progress bar will run indefinitely and must\r
11776      * be manually cleared by calling {@link #reset}.  The wait method accepts a config object with\r
11777      * the following properties:\r
11778      * <pre>\r
11779 Property   Type          Description\r
11780 ---------- ------------  ----------------------------------------------------------------------\r
11781 duration   Number        The length of time in milliseconds that the progress bar should\r
11782                          run before resetting itself (defaults to undefined, in which case it\r
11783                          will run indefinitely until reset is called)\r
11784 interval   Number        The length of time in milliseconds between each progress update\r
11785                          (defaults to 1000 ms)\r
11786 animate    Boolean       Whether to animate the transition of the progress bar. If this value is\r
11787                          not specified, the default for the class is used.                                                   \r
11788 increment  Number        The number of progress update segments to display within the progress\r
11789                          bar (defaults to 10).  If the bar reaches the end and is still\r
11790                          updating, it will automatically wrap back to the beginning.\r
11791 text       String        Optional text to display in the progress bar element (defaults to '').\r
11792 fn         Function      A callback function to execute after the progress bar finishes auto-\r
11793                          updating.  The function will be called with no arguments.  This function\r
11794                          will be ignored if duration is not specified since in that case the\r
11795                          progress bar can only be stopped programmatically, so any required function\r
11796                          should be called by the same code after it resets the progress bar.\r
11797 scope      Object        The scope that is passed to the callback function (only applies when\r
11798                          duration and fn are both passed).\r
11799 </pre>\r
11800          *\r
11801          * Example usage:\r
11802          * <pre><code>\r
11803 var p = new Ext.ProgressBar({\r
11804    renderTo: 'my-el'\r
11805 });\r
11806 \r
11807 //Wait for 5 seconds, then update the status el (progress bar will auto-reset)\r
11808 p.wait({\r
11809    interval: 100, //bar will move fast!\r
11810    duration: 5000,\r
11811    increment: 15,\r
11812    text: 'Updating...',\r
11813    scope: this,\r
11814    fn: function(){\r
11815       Ext.fly('status').update('Done!');\r
11816    }\r
11817 });\r
11818 \r
11819 //Or update indefinitely until some async action completes, then reset manually\r
11820 p.wait();\r
11821 myAction.on('complete', function(){\r
11822     p.reset();\r
11823     Ext.fly('status').update('Done!');\r
11824 });\r
11825 </code></pre>\r
11826      * @param {Object} config (optional) Configuration options\r
11827      * @return {Ext.ProgressBar} this\r
11828      */\r
11829     wait : function(o){\r
11830         if(!this.waitTimer){\r
11831             var scope = this;\r
11832             o = o || {};\r
11833             this.updateText(o.text);\r
11834             this.waitTimer = Ext.TaskMgr.start({\r
11835                 run: function(i){\r
11836                     var inc = o.increment || 10;\r
11837                     i -= 1;\r
11838                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);\r
11839                 },\r
11840                 interval: o.interval || 1000,\r
11841                 duration: o.duration,\r
11842                 onStop: function(){\r
11843                     if(o.fn){\r
11844                         o.fn.apply(o.scope || this);\r
11845                     }\r
11846                     this.reset();\r
11847                 },\r
11848                 scope: scope\r
11849             });\r
11850         }\r
11851         return this;\r
11852     },\r
11853 \r
11854     /**\r
11855      * Returns true if the progress bar is currently in a {@link #wait} operation\r
11856      * @return {Boolean} True if waiting, else false\r
11857      */\r
11858     isWaiting : function(){\r
11859         return this.waitTimer !== null;\r
11860     },\r
11861 \r
11862     /**\r
11863      * Updates the progress bar text.  If specified, textEl will be updated, otherwise the progress\r
11864      * bar itself will display the updated text.\r
11865      * @param {String} text (optional) The string to display in the progress text element (defaults to '')\r
11866      * @return {Ext.ProgressBar} this\r
11867      */\r
11868     updateText : function(text){\r
11869         this.text = text || '&#160;';\r
11870         if(this.rendered){\r
11871             this.textEl.update(this.text);\r
11872         }\r
11873         return this;\r
11874     },\r
11875     \r
11876     /**\r
11877      * Synchronizes the inner bar width to the proper proportion of the total componet width based\r
11878      * on the current progress {@link #value}.  This will be called automatically when the ProgressBar\r
11879      * is resized by a layout, but if it is rendered auto width, this method can be called from\r
11880      * another resize handler to sync the ProgressBar if necessary.\r
11881      */\r
11882     syncProgressBar : function(){\r
11883         if(this.value){\r
11884             this.updateProgress(this.value, this.text);\r
11885         }\r
11886         return this;\r
11887     },\r
11888 \r
11889     /**\r
11890      * Sets the size of the progress bar.\r
11891      * @param {Number} width The new width in pixels\r
11892      * @param {Number} height The new height in pixels\r
11893      * @return {Ext.ProgressBar} this\r
11894      */\r
11895     setSize : function(w, h){\r
11896         Ext.ProgressBar.superclass.setSize.call(this, w, h);\r
11897         if(this.textTopEl){\r
11898             var inner = this.el.dom.firstChild;\r
11899             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);\r
11900         }\r
11901         this.syncProgressBar();\r
11902         return this;\r
11903     },\r
11904 \r
11905     /**\r
11906      * Resets the progress bar value to 0 and text to empty string.  If hide = true, the progress\r
11907      * bar will also be hidden (using the {@link #hideMode} property internally).\r
11908      * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false)\r
11909      * @return {Ext.ProgressBar} this\r
11910      */\r
11911     reset : function(hide){\r
11912         this.updateProgress(0);\r
11913         if(this.textTopEl){\r
11914             this.textTopEl.addClass('x-hidden');\r
11915         }\r
11916         if(this.waitTimer){\r
11917             this.waitTimer.onStop = null; //prevent recursion\r
11918             Ext.TaskMgr.stop(this.waitTimer);\r
11919             this.waitTimer = null;\r
11920         }\r
11921         if(hide === true){\r
11922             this.hide();\r
11923         }\r
11924         return this;\r
11925     },\r
11926     \r
11927     onDestroy: function(){\r
11928         if(this.rendered){\r
11929             if(this.textEl.isComposite){\r
11930                 this.textEl.clear();\r
11931             }\r
11932             Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');\r
11933         }\r
11934         Ext.ProgressBar.superclass.onDestroy.call(this);\r
11935     }\r
11936 });\r
11937 Ext.reg('progress', Ext.ProgressBar);