Upgrade to ExtJS 3.2.1 - Released 04/27/2010
[extjs.git] / pkgs / cmp-foundation-debug.js
1 /*!
2  * Ext JS Library 3.2.1
3  * Copyright(c) 2006-2010 Ext JS, Inc.
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          * The xtypes that have been registered with the component manager.
79          * @type {Object}
80          */
81         types : types,
82         
83         /**
84          * The ptypes that have been registered with the component manager.
85          * @type {Object}
86          */
87         ptypes: ptypes,
88         
89         /**
90          * Checks if a Component type is registered.
91          * @param {Ext.Component} xtype The mnemonic string by which the Component class may be looked up
92          * @return {Boolean} Whether the type is registered.
93          */
94         isRegistered : function(xtype){
95             return types[xtype] !== undefined;    
96         },
97         
98         /**
99          * Checks if a Plugin type is registered.
100          * @param {Ext.Component} ptype The mnemonic string by which the Plugin class may be looked up
101          * @return {Boolean} Whether the type is registered.
102          */
103         isPluginRegistered : function(ptype){
104             return ptypes[ptype] !== undefined;    
105         },        
106
107         /**
108          * <p>Registers a new Component constructor, keyed by a new
109          * {@link Ext.Component#xtype}.</p>
110          * <p>Use this method (or its alias {@link Ext#reg Ext.reg}) to register new
111          * subclasses of {@link Ext.Component} so that lazy instantiation may be used when specifying
112          * child Components.
113          * see {@link Ext.Container#items}</p>
114          * @param {String} xtype The mnemonic string by which the Component class may be looked up.
115          * @param {Constructor} cls The new Component class.
116          */
117         registerType : function(xtype, cls){
118             types[xtype] = cls;
119             cls.xtype = xtype;
120         },
121
122         /**
123          * Creates a new Component from the specified config object using the
124          * config object's {@link Ext.component#xtype xtype} to determine the class to instantiate.
125          * @param {Object} config A configuration object for the Component you wish to create.
126          * @param {Constructor} defaultType The constructor to provide the default Component type if
127          * the config object does not contain a <code>xtype</code>. (Optional if the config contains a <code>xtype</code>).
128          * @return {Ext.Component} The newly instantiated Component.
129          */
130         create : function(config, defaultType){
131             return config.render ? config : new types[config.xtype || defaultType](config);
132         },
133
134         /**
135          * <p>Registers a new Plugin constructor, keyed by a new
136          * {@link Ext.Component#ptype}.</p>
137          * <p>Use this method (or its alias {@link Ext#preg Ext.preg}) to register new
138          * plugins for {@link Ext.Component}s so that lazy instantiation may be used when specifying
139          * Plugins.</p>
140          * @param {String} ptype The mnemonic string by which the Plugin class may be looked up.
141          * @param {Constructor} cls The new Plugin class.
142          */
143         registerPlugin : function(ptype, cls){
144             ptypes[ptype] = cls;
145             cls.ptype = ptype;
146         },
147
148         /**
149          * Creates a new Plugin from the specified config object using the
150          * config object's {@link Ext.component#ptype ptype} to determine the class to instantiate.
151          * @param {Object} config A configuration object for the Plugin you wish to create.
152          * @param {Constructor} defaultType The constructor to provide the default Plugin type if
153          * the config object does not contain a <code>ptype</code>. (Optional if the config contains a <code>ptype</code>).
154          * @return {Ext.Component} The newly instantiated Plugin.
155          */
156         createPlugin : function(config, defaultType){
157             var PluginCls = ptypes[config.ptype || defaultType];
158             if (PluginCls.init) {
159                 return PluginCls;                
160             } else {
161                 return new PluginCls(config);
162             }            
163         }
164     };
165 }();
166
167 /**
168  * Shorthand for {@link Ext.ComponentMgr#registerType}
169  * @param {String} xtype The {@link Ext.component#xtype mnemonic string} by which the Component class
170  * may be looked up.
171  * @param {Constructor} cls The new Component class.
172  * @member Ext
173  * @method reg
174  */
175 Ext.reg = Ext.ComponentMgr.registerType; // this will be called a lot internally, shorthand to keep the bytes down
176 /**
177  * Shorthand for {@link Ext.ComponentMgr#registerPlugin}
178  * @param {String} ptype The {@link Ext.component#ptype mnemonic string} by which the Plugin class
179  * may be looked up.
180  * @param {Constructor} cls The new Plugin class.
181  * @member Ext
182  * @method preg
183  */
184 Ext.preg = Ext.ComponentMgr.registerPlugin;
185 /**
186  * Shorthand for {@link Ext.ComponentMgr#create}
187  * Creates a new Component from the specified config object using the
188  * config object's {@link Ext.component#xtype xtype} to determine the class to instantiate.
189  * @param {Object} config A configuration object for the Component you wish to create.
190  * @param {Constructor} defaultType The constructor to provide the default Component type if
191  * the config object does not contain a <code>xtype</code>. (Optional if the config contains a <code>xtype</code>).
192  * @return {Ext.Component} The newly instantiated Component.
193  * @member Ext
194  * @method create
195  */
196 Ext.create = Ext.ComponentMgr.create;/**
197  * @class Ext.Component
198  * @extends Ext.util.Observable
199  * <p>Base class for all Ext components.  All subclasses of Component may participate in the automated
200  * Ext component lifecycle of creation, rendering and destruction which is provided by the {@link Ext.Container Container} class.
201  * Components may be added to a Container through the {@link Ext.Container#items items} config option at the time the Container is created,
202  * or they may be added dynamically via the {@link Ext.Container#add add} method.</p>
203  * <p>The Component base class has built-in support for basic hide/show and enable/disable behavior.</p>
204  * <p>All Components are registered with the {@link Ext.ComponentMgr} on construction so that they can be referenced at any time via
205  * {@link Ext#getCmp}, passing the {@link #id}.</p>
206  * <p>All user-developed visual widgets that are required to participate in automated lifecycle and size management should subclass Component (or
207  * {@link Ext.BoxComponent} if managed box model handling is required, ie height and width management).</p>
208  * <p>See the <a href="http://extjs.com/learn/Tutorial:Creating_new_UI_controls">Creating new UI controls</a> tutorial for details on how
209  * and to either extend or augment ExtJs base classes to create custom Components.</p>
210  * <p>Every component has a specific xtype, which is its Ext-specific type name, along with methods for checking the
211  * xtype like {@link #getXType} and {@link #isXType}. This is the list of all valid xtypes:</p>
212  * <pre>
213 xtype            Class
214 -------------    ------------------
215 box              {@link Ext.BoxComponent}
216 button           {@link Ext.Button}
217 buttongroup      {@link Ext.ButtonGroup}
218 colorpalette     {@link Ext.ColorPalette}
219 component        {@link Ext.Component}
220 container        {@link Ext.Container}
221 cycle            {@link Ext.CycleButton}
222 dataview         {@link Ext.DataView}
223 datepicker       {@link Ext.DatePicker}
224 editor           {@link Ext.Editor}
225 editorgrid       {@link Ext.grid.EditorGridPanel}
226 flash            {@link Ext.FlashComponent}
227 grid             {@link Ext.grid.GridPanel}
228 listview         {@link Ext.ListView}
229 panel            {@link Ext.Panel}
230 progress         {@link Ext.ProgressBar}
231 propertygrid     {@link Ext.grid.PropertyGrid}
232 slider           {@link Ext.Slider}
233 spacer           {@link Ext.Spacer}
234 splitbutton      {@link Ext.SplitButton}
235 tabpanel         {@link Ext.TabPanel}
236 treepanel        {@link Ext.tree.TreePanel}
237 viewport         {@link Ext.ViewPort}
238 window           {@link Ext.Window}
239
240 Toolbar components
241 ---------------------------------------
242 paging           {@link Ext.PagingToolbar}
243 toolbar          {@link Ext.Toolbar}
244 tbbutton         {@link Ext.Toolbar.Button}        (deprecated; use button)
245 tbfill           {@link Ext.Toolbar.Fill}
246 tbitem           {@link Ext.Toolbar.Item}
247 tbseparator      {@link Ext.Toolbar.Separator}
248 tbspacer         {@link Ext.Toolbar.Spacer}
249 tbsplit          {@link Ext.Toolbar.SplitButton}   (deprecated; use splitbutton)
250 tbtext           {@link Ext.Toolbar.TextItem}
251
252 Menu components
253 ---------------------------------------
254 menu             {@link Ext.menu.Menu}
255 colormenu        {@link Ext.menu.ColorMenu}
256 datemenu         {@link Ext.menu.DateMenu}
257 menubaseitem     {@link Ext.menu.BaseItem}
258 menucheckitem    {@link Ext.menu.CheckItem}
259 menuitem         {@link Ext.menu.Item}
260 menuseparator    {@link Ext.menu.Separator}
261 menutextitem     {@link Ext.menu.TextItem}
262
263 Form components
264 ---------------------------------------
265 form             {@link Ext.form.FormPanel}
266 checkbox         {@link Ext.form.Checkbox}
267 checkboxgroup    {@link Ext.form.CheckboxGroup}
268 combo            {@link Ext.form.ComboBox}
269 datefield        {@link Ext.form.DateField}
270 displayfield     {@link Ext.form.DisplayField}
271 field            {@link Ext.form.Field}
272 fieldset         {@link Ext.form.FieldSet}
273 hidden           {@link Ext.form.Hidden}
274 htmleditor       {@link Ext.form.HtmlEditor}
275 label            {@link Ext.form.Label}
276 numberfield      {@link Ext.form.NumberField}
277 radio            {@link Ext.form.Radio}
278 radiogroup       {@link Ext.form.RadioGroup}
279 textarea         {@link Ext.form.TextArea}
280 textfield        {@link Ext.form.TextField}
281 timefield        {@link Ext.form.TimeField}
282 trigger          {@link Ext.form.TriggerField}
283
284 Chart components
285 ---------------------------------------
286 chart            {@link Ext.chart.Chart}
287 barchart         {@link Ext.chart.BarChart}
288 cartesianchart   {@link Ext.chart.CartesianChart}
289 columnchart      {@link Ext.chart.ColumnChart}
290 linechart        {@link Ext.chart.LineChart}
291 piechart         {@link Ext.chart.PieChart}
292
293 Store xtypes
294 ---------------------------------------
295 arraystore       {@link Ext.data.ArrayStore}
296 directstore      {@link Ext.data.DirectStore}
297 groupingstore    {@link Ext.data.GroupingStore}
298 jsonstore        {@link Ext.data.JsonStore}
299 simplestore      {@link Ext.data.SimpleStore}      (deprecated; use arraystore)
300 store            {@link Ext.data.Store}
301 xmlstore         {@link Ext.data.XmlStore}
302 </pre>
303  * @constructor
304  * @param {Ext.Element/String/Object} config The configuration options may be specified as either:
305  * <div class="mdetail-params"><ul>
306  * <li><b>an element</b> :
307  * <p class="sub-desc">it is set as the internal element and its id used as the component id</p></li>
308  * <li><b>a string</b> :
309  * <p class="sub-desc">it is assumed to be the id of an existing element and is used as the component id</p></li>
310  * <li><b>anything else</b> :
311  * <p class="sub-desc">it is assumed to be a standard config object and is applied to the component</p></li>
312  * </ul></div>
313  */
314 Ext.Component = function(config){
315     config = config || {};
316     if(config.initialConfig){
317         if(config.isAction){           // actions
318             this.baseAction = config;
319         }
320         config = config.initialConfig; // component cloning / action set up
321     }else if(config.tagName || config.dom || Ext.isString(config)){ // element object
322         config = {applyTo: config, id: config.id || config};
323     }
324
325     /**
326      * This Component's initial configuration specification. Read-only.
327      * @type Object
328      * @property initialConfig
329      */
330     this.initialConfig = config;
331
332     Ext.apply(this, config);
333     this.addEvents(
334         /**
335          * @event added
336          * Fires when a component is added to an Ext.Container
337          * @param {Ext.Component} this
338          * @param {Ext.Container} ownerCt Container which holds the component
339          * @param {number} index Position at which the component was added
340          */
341         'added',
342         /**
343          * @event disable
344          * Fires after the component is disabled.
345          * @param {Ext.Component} this
346          */
347         'disable',
348         /**
349          * @event enable
350          * Fires after the component is enabled.
351          * @param {Ext.Component} this
352          */
353         'enable',
354         /**
355          * @event beforeshow
356          * Fires before the component is shown by calling the {@link #show} method.
357          * Return false from an event handler to stop the show.
358          * @param {Ext.Component} this
359          */
360         'beforeshow',
361         /**
362          * @event show
363          * Fires after the component is shown when calling the {@link #show} method.
364          * @param {Ext.Component} this
365          */
366         'show',
367         /**
368          * @event beforehide
369          * Fires before the component is hidden by calling the {@link #hide} method.
370          * Return false from an event handler to stop the hide.
371          * @param {Ext.Component} this
372          */
373         'beforehide',
374         /**
375          * @event hide
376          * Fires after the component is hidden.
377          * Fires after the component is hidden when calling the {@link #hide} method.
378          * @param {Ext.Component} this
379          */
380         'hide',
381         /**
382          * @event removed
383          * Fires when a component is removed from an Ext.Container
384          * @param {Ext.Component} this
385          * @param {Ext.Container} ownerCt Container which holds the component
386          */
387         'removed',
388         /**
389          * @event beforerender
390          * Fires before the component is {@link #rendered}. Return false from an
391          * event handler to stop the {@link #render}.
392          * @param {Ext.Component} this
393          */
394         'beforerender',
395         /**
396          * @event render
397          * Fires after the component markup is {@link #rendered}.
398          * @param {Ext.Component} this
399          */
400         'render',
401         /**
402          * @event afterrender
403          * <p>Fires after the component rendering is finished.</p>
404          * <p>The afterrender event is fired after this Component has been {@link #rendered}, been postprocesed
405          * by any afterRender method defined for the Component, and, if {@link #stateful}, after state
406          * has been restored.</p>
407          * @param {Ext.Component} this
408          */
409         'afterrender',
410         /**
411          * @event beforedestroy
412          * Fires before the component is {@link #destroy}ed. Return false from an event handler to stop the {@link #destroy}.
413          * @param {Ext.Component} this
414          */
415         'beforedestroy',
416         /**
417          * @event destroy
418          * Fires after the component is {@link #destroy}ed.
419          * @param {Ext.Component} this
420          */
421         'destroy',
422         /**
423          * @event beforestaterestore
424          * Fires before the state of the component is restored. Return false from an event handler to stop the restore.
425          * @param {Ext.Component} this
426          * @param {Object} state The hash of state values returned from the StateProvider. If this
427          * event is not vetoed, then the state object is passed to <b><tt>applyState</tt></b>. By default,
428          * that simply copies property values into this Component. The method maybe overriden to
429          * provide custom state restoration.
430          */
431         'beforestaterestore',
432         /**
433          * @event staterestore
434          * Fires after the state of the component is restored.
435          * @param {Ext.Component} this
436          * @param {Object} state The hash of state values returned from the StateProvider. This is passed
437          * to <b><tt>applyState</tt></b>. By default, that simply copies property values into this
438          * Component. The method maybe overriden to provide custom state restoration.
439          */
440         'staterestore',
441         /**
442          * @event beforestatesave
443          * Fires before the state of the component is saved to the configured state provider. Return false to stop the save.
444          * @param {Ext.Component} this
445          * @param {Object} state The hash of state values. This is determined by calling
446          * <b><tt>getState()</tt></b> on the Component. This method must be provided by the
447          * developer to return whetever representation of state is required, by default, Ext.Component
448          * has a null implementation.
449          */
450         'beforestatesave',
451         /**
452          * @event statesave
453          * Fires after the state of the component is saved to the configured state provider.
454          * @param {Ext.Component} this
455          * @param {Object} state The hash of state values. This is determined by calling
456          * <b><tt>getState()</tt></b> on the Component. This method must be provided by the
457          * developer to return whetever representation of state is required, by default, Ext.Component
458          * has a null implementation.
459          */
460         'statesave'
461     );
462     this.getId();
463     Ext.ComponentMgr.register(this);
464     Ext.Component.superclass.constructor.call(this);
465
466     if(this.baseAction){
467         this.baseAction.addComponent(this);
468     }
469
470     this.initComponent();
471
472     if(this.plugins){
473         if(Ext.isArray(this.plugins)){
474             for(var i = 0, len = this.plugins.length; i < len; i++){
475                 this.plugins[i] = this.initPlugin(this.plugins[i]);
476             }
477         }else{
478             this.plugins = this.initPlugin(this.plugins);
479         }
480     }
481
482     if(this.stateful !== false){
483         this.initState();
484     }
485
486     if(this.applyTo){
487         this.applyToMarkup(this.applyTo);
488         delete this.applyTo;
489     }else if(this.renderTo){
490         this.render(this.renderTo);
491         delete this.renderTo;
492     }
493 };
494
495 // private
496 Ext.Component.AUTO_ID = 1000;
497
498 Ext.extend(Ext.Component, Ext.util.Observable, {
499     // Configs below are used for all Components when rendered by FormLayout.
500     /**
501      * @cfg {String} fieldLabel <p>The label text to display next to this Component (defaults to '').</p>
502      * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container which
503      * has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout manager (e.g.
504      * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>).</p><br>
505      * <p>Also see <tt>{@link #hideLabel}</tt> and
506      * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</p>
507      * Example use:<pre><code>
508 new Ext.FormPanel({
509     height: 100,
510     renderTo: Ext.getBody(),
511     items: [{
512         xtype: 'textfield',
513         fieldLabel: 'Name'
514     }]
515 });
516 </code></pre>
517      */
518     /**
519      * @cfg {String} labelStyle <p>A CSS style specification string to apply directly to this field's
520      * label.  Defaults to the container's labelStyle value if set (e.g.,
521      * <tt>{@link Ext.layout.FormLayout#labelStyle}</tt> , or '').</p>
522      * <br><p><b>Note</b>: see the note for <code>{@link #clearCls}</code>.</p><br>
523      * <p>Also see <code>{@link #hideLabel}</code> and
524      * <code>{@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</code></p>
525      * Example use:<pre><code>
526 new Ext.FormPanel({
527     height: 100,
528     renderTo: Ext.getBody(),
529     items: [{
530         xtype: 'textfield',
531         fieldLabel: 'Name',
532         labelStyle: 'font-weight:bold;'
533     }]
534 });
535 </code></pre>
536      */
537     /**
538      * @cfg {String} labelSeparator <p>The separator to display after the text of each
539      * <tt>{@link #fieldLabel}</tt>.  This property may be configured at various levels.
540      * The order of precedence is:
541      * <div class="mdetail-params"><ul>
542      * <li>field / component level</li>
543      * <li>container level</li>
544      * <li>{@link Ext.layout.FormLayout#labelSeparator layout level} (defaults to colon <tt>':'</tt>)</li>
545      * </ul></div>
546      * To display no separator for this field's label specify empty string ''.</p>
547      * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</tt>.</p><br>
548      * <p>Also see <tt>{@link #hideLabel}</tt> and
549      * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</p>
550      * Example use:<pre><code>
551 new Ext.FormPanel({
552     height: 100,
553     renderTo: Ext.getBody(),
554     layoutConfig: {
555         labelSeparator: '~'   // layout config has lowest priority (defaults to ':')
556     },
557     {@link Ext.layout.FormLayout#labelSeparator labelSeparator}: '>>',     // config at container level
558     items: [{
559         xtype: 'textfield',
560         fieldLabel: 'Field 1',
561         labelSeparator: '...' // field/component level config supersedes others
562     },{
563         xtype: 'textfield',
564         fieldLabel: 'Field 2' // labelSeparator will be '='
565     }]
566 });
567 </code></pre>
568      */
569     /**
570      * @cfg {Boolean} hideLabel <p><tt>true</tt> to completely hide the label element
571      * ({@link #fieldLabel label} and {@link #labelSeparator separator}). Defaults to <tt>false</tt>.
572      * By default, even if you do not specify a <tt>{@link #fieldLabel}</tt> the space will still be
573      * reserved so that the field will line up with other fields that do have labels.
574      * Setting this to <tt>true</tt> will cause the field to not reserve that space.</p>
575      * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</tt>.</p><br>
576      * Example use:<pre><code>
577 new Ext.FormPanel({
578     height: 100,
579     renderTo: Ext.getBody(),
580     items: [{
581         xtype: 'textfield'
582         hideLabel: true
583     }]
584 });
585 </code></pre>
586      */
587     /**
588      * @cfg {String} clearCls <p>The CSS class used to to apply to the special clearing div rendered
589      * directly after each form field wrapper to provide field clearing (defaults to
590      * <tt>'x-form-clear-left'</tt>).</p>
591      * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container
592      * which has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout
593      * manager (e.g. {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) and either a
594      * <tt>{@link #fieldLabel}</tt> is specified or <tt>isFormField=true</tt> is specified.</p><br>
595      * <p>See {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl} also.</p>
596      */
597     /**
598      * @cfg {String} itemCls
599      * <p><b>Note</b>: this config is only used when this Component is rendered by a Container which
600      * has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout manager (e.g.
601      * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>).</p><br>
602      * <p>An additional CSS class to apply to the div wrapping the form item
603      * element of this field.  If supplied, <tt>itemCls</tt> at the <b>field</b> level will override
604      * the default <tt>itemCls</tt> supplied at the <b>container</b> level. The value specified for
605      * <tt>itemCls</tt> will be added to the default class (<tt>'x-form-item'</tt>).</p>
606      * <p>Since it is applied to the item wrapper (see
607      * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}), it allows
608      * you to write standard CSS rules that can apply to the field, the label (if specified), or
609      * any other element within the markup for the field.</p>
610      * <br><p><b>Note</b>: see the note for <tt>{@link #fieldLabel}</tt>.</p><br>
611      * Example use:<pre><code>
612 // Apply a style to the field&#39;s label:
613 &lt;style>
614     .required .x-form-item-label {font-weight:bold;color:red;}
615 &lt;/style>
616
617 new Ext.FormPanel({
618     height: 100,
619     renderTo: Ext.getBody(),
620     items: [{
621         xtype: 'textfield',
622         fieldLabel: 'Name',
623         itemCls: 'required' //this label will be styled
624     },{
625         xtype: 'textfield',
626         fieldLabel: 'Favorite Color'
627     }]
628 });
629 </code></pre>
630      */
631
632     /**
633      * @cfg {String} id
634      * <p>The <b>unique</b> id of this component (defaults to an {@link #getId auto-assigned id}).
635      * You should assign an id if you need to be able to access the component later and you do
636      * not have an object reference available (e.g., using {@link Ext}.{@link Ext#getCmp getCmp}).</p>
637      * <p>Note that this id will also be used as the element id for the containing HTML element
638      * that is rendered to the page for this component. This allows you to write id-based CSS
639      * rules to style the specific instance of this component uniquely, and also to select
640      * sub-elements using this component's id as the parent.</p>
641      * <p><b>Note</b>: to avoid complications imposed by a unique <tt>id</tt> also see
642      * <code>{@link #itemId}</code> and <code>{@link #ref}</code>.</p>
643      * <p><b>Note</b>: to access the container of an item see <code>{@link #ownerCt}</code>.</p>
644      */
645     /**
646      * @cfg {String} itemId
647      * <p>An <tt>itemId</tt> can be used as an alternative way to get a reference to a component
648      * when no object reference is available.  Instead of using an <code>{@link #id}</code> with
649      * {@link Ext}.{@link Ext#getCmp getCmp}, use <code>itemId</code> with
650      * {@link Ext.Container}.{@link Ext.Container#getComponent getComponent} which will retrieve
651      * <code>itemId</code>'s or <tt>{@link #id}</tt>'s. Since <code>itemId</code>'s are an index to the
652      * container's internal MixedCollection, the <code>itemId</code> is scoped locally to the container --
653      * avoiding potential conflicts with {@link Ext.ComponentMgr} which requires a <b>unique</b>
654      * <code>{@link #id}</code>.</p>
655      * <pre><code>
656 var c = new Ext.Panel({ //
657     {@link Ext.BoxComponent#height height}: 300,
658     {@link #renderTo}: document.body,
659     {@link Ext.Container#layout layout}: 'auto',
660     {@link Ext.Container#items items}: [
661         {
662             itemId: 'p1',
663             {@link Ext.Panel#title title}: 'Panel 1',
664             {@link Ext.BoxComponent#height height}: 150
665         },
666         {
667             itemId: 'p2',
668             {@link Ext.Panel#title title}: 'Panel 2',
669             {@link Ext.BoxComponent#height height}: 150
670         }
671     ]
672 })
673 p1 = c.{@link Ext.Container#getComponent getComponent}('p1'); // not the same as {@link Ext#getCmp Ext.getCmp()}
674 p2 = p1.{@link #ownerCt}.{@link Ext.Container#getComponent getComponent}('p2'); // reference via a sibling
675      * </code></pre>
676      * <p>Also see <tt>{@link #id}</tt> and <code>{@link #ref}</code>.</p>
677      * <p><b>Note</b>: to access the container of an item see <tt>{@link #ownerCt}</tt>.</p>
678      */
679     /**
680      * @cfg {String} xtype
681      * The registered <tt>xtype</tt> to create. This config option is not used when passing
682      * a config object into a constructor. This config option is used only when
683      * lazy instantiation is being used, and a child item of a Container is being
684      * specified not as a fully instantiated Component, but as a <i>Component config
685      * object</i>. The <tt>xtype</tt> will be looked up at render time up to determine what
686      * type of child Component to create.<br><br>
687      * The predefined xtypes are listed {@link Ext.Component here}.
688      * <br><br>
689      * If you subclass Components to create your own Components, you may register
690      * them using {@link Ext.ComponentMgr#registerType} in order to be able to
691      * take advantage of lazy instantiation and rendering.
692      */
693     /**
694      * @cfg {String} ptype
695      * The registered <tt>ptype</tt> to create. This config option is not used when passing
696      * a config object into a constructor. This config option is used only when
697      * lazy instantiation is being used, and a Plugin is being
698      * specified not as a fully instantiated Component, but as a <i>Component config
699      * object</i>. The <tt>ptype</tt> will be looked up at render time up to determine what
700      * type of Plugin to create.<br><br>
701      * If you create your own Plugins, you may register them using
702      * {@link Ext.ComponentMgr#registerPlugin} in order to be able to
703      * take advantage of lazy instantiation and rendering.
704      */
705     /**
706      * @cfg {String} cls
707      * An optional extra CSS class that will be added to this component's Element (defaults to '').  This can be
708      * useful for adding customized styles to the component or any of its children using standard CSS rules.
709      */
710     /**
711      * @cfg {String} overCls
712      * An optional extra CSS class that will be added to this component's Element when the mouse moves
713      * over the Element, and removed when the mouse moves out. (defaults to '').  This can be
714      * useful for adding customized 'active' or 'hover' styles to the component or any of its children using standard CSS rules.
715      */
716     /**
717      * @cfg {String} style
718      * A custom style specification to be applied to this component's Element.  Should be a valid argument to
719      * {@link Ext.Element#applyStyles}.
720      * <pre><code>
721 new Ext.Panel({
722     title: 'Some Title',
723     renderTo: Ext.getBody(),
724     width: 400, height: 300,
725     layout: 'form',
726     items: [{
727         xtype: 'textarea',
728         style: {
729             width: '95%',
730             marginBottom: '10px'
731         }
732     },
733         new Ext.Button({
734             text: 'Send',
735             minWidth: '100',
736             style: {
737                 marginBottom: '10px'
738             }
739         })
740     ]
741 });
742      * </code></pre>
743      */
744     /**
745      * @cfg {String} ctCls
746      * <p>An optional extra CSS class that will be added to this component's container. This can be useful for
747      * adding customized styles to the container or any of its children using standard CSS rules.  See
748      * {@link Ext.layout.ContainerLayout}.{@link Ext.layout.ContainerLayout#extraCls extraCls} also.</p>
749      * <p><b>Note</b>: <tt>ctCls</tt> defaults to <tt>''</tt> except for the following class
750      * which assigns a value by default:
751      * <div class="mdetail-params"><ul>
752      * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-layout-ct'</tt></li>
753      * </ul></div>
754      * To configure the above Class with an extra CSS class append to the default.  For example,
755      * for BoxLayout (Hbox and Vbox):<pre><code>
756      * ctCls: 'x-box-layout-ct custom-class'
757      * </code></pre>
758      * </p>
759      */
760     /**
761      * @cfg {Boolean} disabled
762      * Render this component disabled (default is false).
763      */
764     disabled : false,
765     /**
766      * @cfg {Boolean} hidden
767      * Render this component hidden (default is false). If <tt>true</tt>, the
768      * {@link #hide} method will be called internally.
769      */
770     hidden : false,
771     /**
772      * @cfg {Object/Array} plugins
773      * An object or array of objects that will provide custom functionality for this component.  The only
774      * requirement for a valid plugin is that it contain an init method that accepts a reference of type Ext.Component.
775      * When a component is created, if any plugins are available, the component will call the init method on each
776      * plugin, passing a reference to itself.  Each plugin can then call methods or respond to events on the
777      * component as needed to provide its functionality.
778      */
779     /**
780      * @cfg {Mixed} applyTo
781      * <p>Specify the id of the element, a DOM element or an existing Element corresponding to a DIV
782      * that is already present in the document that specifies some structural markup for this
783      * component.</p><div><ul>
784      * <li><b>Description</b> : <ul>
785      * <div class="sub-desc">When <tt>applyTo</tt> is used, constituent parts of the component can also be specified
786      * by id or CSS class name within the main element, and the component being created may attempt
787      * to create its subcomponents from that markup if applicable.</div>
788      * </ul></li>
789      * <li><b>Notes</b> : <ul>
790      * <div class="sub-desc">When using this config, a call to render() is not required.</div>
791      * <div class="sub-desc">If applyTo is specified, any value passed for {@link #renderTo} will be ignored and the target
792      * element's parent node will automatically be used as the component's container.</div>
793      * </ul></li>
794      * </ul></div>
795      */
796     /**
797      * @cfg {Mixed} renderTo
798      * <p>Specify the id of the element, a DOM element or an existing Element that this component
799      * will be rendered into.</p><div><ul>
800      * <li><b>Notes</b> : <ul>
801      * <div class="sub-desc">Do <u>not</u> use this option if the Component is to be a child item of
802      * a {@link Ext.Container Container}. It is the responsibility of the
803      * {@link Ext.Container Container}'s {@link Ext.Container#layout layout manager}
804      * to render and manage its child items.</div>
805      * <div class="sub-desc">When using this config, a call to render() is not required.</div>
806      * </ul></li>
807      * </ul></div>
808      * <p>See <tt>{@link #render}</tt> also.</p>
809      */
810     /**
811      * @cfg {Boolean} stateful
812      * <p>A flag which causes the Component to attempt to restore the state of
813      * internal properties from a saved state on startup. The component must have
814      * either a <code>{@link #stateId}</code> or <code>{@link #id}</code> assigned
815      * for state to be managed. Auto-generated ids are not guaranteed to be stable
816      * across page loads and cannot be relied upon to save and restore the same
817      * state for a component.<p>
818      * <p>For state saving to work, the state manager's provider must have been
819      * set to an implementation of {@link Ext.state.Provider} which overrides the
820      * {@link Ext.state.Provider#set set} and {@link Ext.state.Provider#get get}
821      * methods to save and recall name/value pairs. A built-in implementation,
822      * {@link Ext.state.CookieProvider} is available.</p>
823      * <p>To set the state provider for the current page:</p>
824      * <pre><code>
825 Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
826     expires: new Date(new Date().getTime()+(1000*60*60*24*7)), //7 days from now
827 }));
828      * </code></pre>
829      * <p>A stateful Component attempts to save state when one of the events
830      * listed in the <code>{@link #stateEvents}</code> configuration fires.</p>
831      * <p>To save state, a stateful Component first serializes its state by
832      * calling <b><code>getState</code></b>. By default, this function does
833      * nothing. The developer must provide an implementation which returns an
834      * object hash which represents the Component's restorable state.</p>
835      * <p>The value yielded by getState is passed to {@link Ext.state.Manager#set}
836      * which uses the configured {@link Ext.state.Provider} to save the object
837      * keyed by the Component's <code>{@link stateId}</code>, or, if that is not
838      * specified, its <code>{@link #id}</code>.</p>
839      * <p>During construction, a stateful Component attempts to <i>restore</i>
840      * its state by calling {@link Ext.state.Manager#get} passing the
841      * <code>{@link #stateId}</code>, or, if that is not specified, the
842      * <code>{@link #id}</code>.</p>
843      * <p>The resulting object is passed to <b><code>applyState</code></b>.
844      * The default implementation of <code>applyState</code> simply copies
845      * properties into the object, but a developer may override this to support
846      * more behaviour.</p>
847      * <p>You can perform extra processing on state save and restore by attaching
848      * handlers to the {@link #beforestaterestore}, {@link #staterestore},
849      * {@link #beforestatesave} and {@link #statesave} events.</p>
850      */
851     /**
852      * @cfg {String} stateId
853      * The unique id for this component to use for state management purposes
854      * (defaults to the component id if one was set, otherwise null if the
855      * component is using a generated id).
856      * <p>See <code>{@link #stateful}</code> for an explanation of saving and
857      * restoring Component state.</p>
858      */
859     /**
860      * @cfg {Array} stateEvents
861      * <p>An array of events that, when fired, should trigger this component to
862      * save its state (defaults to none). <code>stateEvents</code> may be any type
863      * of event supported by this component, including browser or custom events
864      * (e.g., <tt>['click', 'customerchange']</tt>).</p>
865      * <p>See <code>{@link #stateful}</code> for an explanation of saving and
866      * restoring Component state.</p>
867      */
868     /**
869      * @cfg {Mixed} autoEl
870      * <p>A tag name or {@link Ext.DomHelper DomHelper} spec used to create the {@link #getEl Element} which will
871      * encapsulate this Component.</p>
872      * <p>You do not normally need to specify this. For the base classes {@link Ext.Component}, {@link Ext.BoxComponent},
873      * and {@link Ext.Container}, this defaults to <b><tt>'div'</tt></b>. The more complex Ext classes use a more complex
874      * DOM structure created by their own onRender methods.</p>
875      * <p>This is intended to allow the developer to create application-specific utility Components encapsulated by
876      * different DOM elements. Example usage:</p><pre><code>
877 {
878     xtype: 'box',
879     autoEl: {
880         tag: 'img',
881         src: 'http://www.example.com/example.jpg'
882     }
883 }, {
884     xtype: 'box',
885     autoEl: {
886         tag: 'blockquote',
887         html: 'autoEl is cool!'
888     }
889 }, {
890     xtype: 'container',
891     autoEl: 'ul',
892     cls: 'ux-unordered-list',
893     items: {
894         xtype: 'box',
895         autoEl: 'li',
896         html: 'First list item'
897     }
898 }
899 </code></pre>
900      */
901     autoEl : 'div',
902
903     /**
904      * @cfg {String} disabledClass
905      * CSS class added to the component when it is disabled (defaults to 'x-item-disabled').
906      */
907     disabledClass : 'x-item-disabled',
908     /**
909      * @cfg {Boolean} allowDomMove
910      * Whether the component can move the Dom node when rendering (defaults to true).
911      */
912     allowDomMove : true,
913     /**
914      * @cfg {Boolean} autoShow
915      * True if the component should check for hidden classes (e.g. 'x-hidden' or 'x-hide-display') and remove
916      * them on render (defaults to false).
917      */
918     autoShow : false,
919     /**
920      * @cfg {String} hideMode
921      * <p>How this component should be hidden. Supported values are <tt>'visibility'</tt>
922      * (css visibility), <tt>'offsets'</tt> (negative offset position) and <tt>'display'</tt>
923      * (css display).</p>
924      * <br><p><b>Note</b>: the default of <tt>'display'</tt> is generally preferred
925      * since items are automatically laid out when they are first shown (no sizing
926      * is done while hidden).</p>
927      */
928     hideMode : 'display',
929     /**
930      * @cfg {Boolean} hideParent
931      * True to hide and show the component's container when hide/show is called on the component, false to hide
932      * and show the component itself (defaults to false).  For example, this can be used as a shortcut for a hide
933      * button on a window by setting hide:true on the button when adding it to its parent container.
934      */
935     hideParent : false,
936     /**
937      * <p>The {@link Ext.Element} which encapsulates this Component. Read-only.</p>
938      * <p>This will <i>usually</i> be a &lt;DIV> element created by the class's onRender method, but
939      * that may be overridden using the <code>{@link #autoEl}</code> config.</p>
940      * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br>
941      * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners
942      * for this Component's own Observable events), see the {@link Ext.util.Observable#listeners listeners}
943      * config for a suggestion, or use a render listener directly:</p><pre><code>
944 new Ext.Panel({
945     title: 'The Clickable Panel',
946     listeners: {
947         render: function(p) {
948             // Append the Panel to the click handler&#39;s argument list.
949             p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));
950         },
951         single: true  // Remove the listener after first invocation
952     }
953 });
954 </code></pre>
955      * <p>See also <tt>{@link #getEl getEl}</p>
956      * @type Ext.Element
957      * @property el
958      */
959     /**
960      * This Component's owner {@link Ext.Container Container} (defaults to undefined, and is set automatically when
961      * this Component is added to a Container).  Read-only.
962      * <p><b>Note</b>: to access items within the Container see <tt>{@link #itemId}</tt>.</p>
963      * @type Ext.Container
964      * @property ownerCt
965      */
966     /**
967      * True if this component is hidden. Read-only.
968      * @type Boolean
969      * @property hidden
970      */
971     /**
972      * True if this component is disabled. Read-only.
973      * @type Boolean
974      * @property disabled
975      */
976     /**
977      * True if this component has been rendered. Read-only.
978      * @type Boolean
979      * @property rendered
980      */
981     rendered : false,
982
983     /**
984      * @cfg {String} contentEl
985      * <p>Optional. Specify an existing HTML element, or the <code>id</code> of an existing HTML element to use as the content
986      * for this component.</p>
987      * <ul>
988      * <li><b>Description</b> :
989      * <div class="sub-desc">This config option is used to take an existing HTML element and place it in the layout element
990      * 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>
991      * <li><b>Notes</b> :
992      * <div class="sub-desc">The specified HTML element is appended to the layout element of the component <i>after any configured
993      * {@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>
994      * <div class="sub-desc">The specified HTML element used will not participate in any <code><b>{@link Ext.Container#layout layout}</b></code>
995      * scheme that the Component may use. It is just HTML. Layouts operate on child <code><b>{@link Ext.Container#items items}</b></code>.</div>
996      * <div class="sub-desc">Add either the <code>x-hidden</code> or the <code>x-hide-display</code> CSS class to
997      * prevent a brief flicker of the content before it is rendered to the panel.</div></li>
998      * </ul>
999      */
1000     /**
1001      * @cfg {String/Object} html
1002      * An HTML fragment, or a {@link Ext.DomHelper DomHelper} specification to use as the layout element
1003      * content (defaults to ''). The HTML content is added after the component is rendered,
1004      * so the document will not contain this HTML at the time the {@link #render} event is fired.
1005      * This content is inserted into the body <i>before</i> any configured {@link #contentEl} is appended.
1006      */
1007
1008     /**
1009      * @cfg {Mixed} tpl
1010      * An <bold>{@link Ext.Template}</bold>, <bold>{@link Ext.XTemplate}</bold>
1011      * or an array of strings to form an Ext.XTemplate.
1012      * Used in conjunction with the <code>{@link #data}</code> and
1013      * <code>{@link #tplWriteMode}</code> configurations.
1014      */
1015
1016     /**
1017      * @cfg {String} tplWriteMode The Ext.(X)Template method to use when
1018      * updating the content area of the Component. Defaults to <tt>'overwrite'</tt>
1019      * (see <code>{@link Ext.XTemplate#overwrite}</code>).
1020      */
1021     tplWriteMode : 'overwrite',
1022
1023     /**
1024      * @cfg {Mixed} data
1025      * The initial set of data to apply to the <code>{@link #tpl}</code> to
1026      * update the content area of the Component.
1027      */
1028     
1029     /**
1030      * @cfg {Array} bubbleEvents
1031      * <p>An array of events that, when fired, should be bubbled to any parent container.
1032      * See {@link Ext.util.Observable#enableBubble}.
1033      * Defaults to <tt>[]</tt>.
1034      */
1035     bubbleEvents: [],
1036
1037
1038     // private
1039     ctype : 'Ext.Component',
1040
1041     // private
1042     actionMode : 'el',
1043
1044     // private
1045     getActionEl : function(){
1046         return this[this.actionMode];
1047     },
1048
1049     initPlugin : function(p){
1050         if(p.ptype && !Ext.isFunction(p.init)){
1051             p = Ext.ComponentMgr.createPlugin(p);
1052         }else if(Ext.isString(p)){
1053             p = Ext.ComponentMgr.createPlugin({
1054                 ptype: p
1055             });
1056         }
1057         p.init(this);
1058         return p;
1059     },
1060
1061     /* // protected
1062      * Function to be implemented by Component subclasses to be part of standard component initialization flow (it is empty by default).
1063      * <pre><code>
1064 // Traditional constructor:
1065 Ext.Foo = function(config){
1066     // call superclass constructor:
1067     Ext.Foo.superclass.constructor.call(this, config);
1068
1069     this.addEvents({
1070         // add events
1071     });
1072 };
1073 Ext.extend(Ext.Foo, Ext.Bar, {
1074    // class body
1075 }
1076
1077 // initComponent replaces the constructor:
1078 Ext.Foo = Ext.extend(Ext.Bar, {
1079     initComponent : function(){
1080         // call superclass initComponent
1081         Ext.Container.superclass.initComponent.call(this);
1082
1083         this.addEvents({
1084             // add events
1085         });
1086     }
1087 }
1088 </code></pre>
1089      */
1090     initComponent : function(){
1091         /*
1092          * this is double processing, however it allows people to be able to do
1093          * Ext.apply(this, {
1094          *     listeners: {
1095          *         //here
1096          *     }
1097          * });
1098          * MyClass.superclass.initComponent.call(this);
1099          */
1100         if(this.listeners){
1101             this.on(this.listeners);
1102             delete this.listeners;
1103         }
1104         this.enableBubble(this.bubbleEvents);
1105     },
1106
1107     /**
1108      * <p>Render this Component into the passed HTML element.</p>
1109      * <p><b>If you are using a {@link Ext.Container Container} object to house this Component, then
1110      * do not use the render method.</b></p>
1111      * <p>A Container's child Components are rendered by that Container's
1112      * {@link Ext.Container#layout layout} manager when the Container is first rendered.</p>
1113      * <p>Certain layout managers allow dynamic addition of child components. Those that do
1114      * include {@link Ext.layout.CardLayout}, {@link Ext.layout.AnchorLayout},
1115      * {@link Ext.layout.FormLayout}, {@link Ext.layout.TableLayout}.</p>
1116      * <p>If the Container is already rendered when a new child Component is added, you may need to call
1117      * the Container's {@link Ext.Container#doLayout doLayout} to refresh the view which causes any
1118      * unrendered child Components to be rendered. This is required so that you can add multiple
1119      * child components if needed while only refreshing the layout once.</p>
1120      * <p>When creating complex UIs, it is important to remember that sizing and positioning
1121      * of child items is the responsibility of the Container's {@link Ext.Container#layout layout} manager.
1122      * If you expect child items to be sized in response to user interactions, you must
1123      * configure the Container with a layout manager which creates and manages the type of layout you
1124      * have in mind.</p>
1125      * <p><b>Omitting the Container's {@link Ext.Container#layout layout} config means that a basic
1126      * layout manager is used which does nothing but render child components sequentially into the
1127      * Container. No sizing or positioning will be performed in this situation.</b></p>
1128      * @param {Element/HTMLElement/String} container (optional) The element this Component should be
1129      * rendered into. If it is being created from existing markup, this should be omitted.
1130      * @param {String/Number} position (optional) The element ID or DOM node index within the container <b>before</b>
1131      * which this component will be inserted (defaults to appending to the end of the container)
1132      */
1133     render : function(container, position){
1134         if(!this.rendered && this.fireEvent('beforerender', this) !== false){
1135             if(!container && this.el){
1136                 this.el = Ext.get(this.el);
1137                 container = this.el.dom.parentNode;
1138                 this.allowDomMove = false;
1139             }
1140             this.container = Ext.get(container);
1141             if(this.ctCls){
1142                 this.container.addClass(this.ctCls);
1143             }
1144             this.rendered = true;
1145             if(position !== undefined){
1146                 if(Ext.isNumber(position)){
1147                     position = this.container.dom.childNodes[position];
1148                 }else{
1149                     position = Ext.getDom(position);
1150                 }
1151             }
1152             this.onRender(this.container, position || null);
1153             if(this.autoShow){
1154                 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
1155             }
1156             if(this.cls){
1157                 this.el.addClass(this.cls);
1158                 delete this.cls;
1159             }
1160             if(this.style){
1161                 this.el.applyStyles(this.style);
1162                 delete this.style;
1163             }
1164             if(this.overCls){
1165                 this.el.addClassOnOver(this.overCls);
1166             }
1167             this.fireEvent('render', this);
1168
1169
1170             // Populate content of the component with html, contentEl or
1171             // a tpl.
1172             var contentTarget = this.getContentTarget();
1173             if (this.html){
1174                 contentTarget.update(Ext.DomHelper.markup(this.html));
1175                 delete this.html;
1176             }
1177             if (this.contentEl){
1178                 var ce = Ext.getDom(this.contentEl);
1179                 Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
1180                 contentTarget.appendChild(ce);
1181             }
1182             if (this.tpl) {
1183                 if (!this.tpl.compile) {
1184                     this.tpl = new Ext.XTemplate(this.tpl);
1185                 }
1186                 if (this.data) {
1187                     this.tpl[this.tplWriteMode](contentTarget, this.data);
1188                     delete this.data;
1189                 }
1190             }
1191             this.afterRender(this.container);
1192
1193
1194             if(this.hidden){
1195                 // call this so we don't fire initial hide events.
1196                 this.doHide();
1197             }
1198             if(this.disabled){
1199                 // pass silent so the event doesn't fire the first time.
1200                 this.disable(true);
1201             }
1202
1203             if(this.stateful !== false){
1204                 this.initStateEvents();
1205             }
1206             this.fireEvent('afterrender', this);
1207         }
1208         return this;
1209     },
1210
1211
1212     /**
1213      * Update the content area of a component.
1214      * @param {Mixed} htmlOrData
1215      * If this component has been configured with a template via the tpl config
1216      * then it will use this argument as data to populate the template.
1217      * If this component was not configured with a template, the components
1218      * content area will be updated via Ext.Element update
1219      * @param {Boolean} loadScripts
1220      * (optional) Only legitimate when using the html configuration. Defaults to false
1221      * @param {Function} callback
1222      * (optional) Only legitimate when using the html configuration. Callback to execute when scripts have finished loading
1223      */
1224     update: function(htmlOrData, loadScripts, cb) {
1225         var contentTarget = this.getContentTarget();
1226         if (this.tpl && typeof htmlOrData !== "string") {
1227             this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
1228         } else {
1229             var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
1230             contentTarget.update(html, loadScripts, cb);
1231         }
1232     },
1233
1234
1235     /**
1236      * @private
1237      * Method to manage awareness of when components are added to their
1238      * respective Container, firing an added event.
1239      * References are established at add time rather than at render time.
1240      * @param {Ext.Container} container Container which holds the component
1241      * @param {number} pos Position at which the component was added
1242      */
1243     onAdded : function(container, pos) {
1244         this.ownerCt = container;
1245         this.initRef();
1246         this.fireEvent('added', this, container, pos);
1247     },
1248
1249     /**
1250      * @private
1251      * Method to manage awareness of when components are removed from their
1252      * respective Container, firing an removed event. References are properly
1253      * cleaned up after removing a component from its owning container.
1254      */
1255     onRemoved : function() {
1256         this.removeRef();
1257         this.fireEvent('removed', this, this.ownerCt);
1258         delete this.ownerCt;
1259     },
1260
1261     /**
1262      * @private
1263      * Method to establish a reference to a component.
1264      */
1265     initRef : function() {
1266         /**
1267          * @cfg {String} ref
1268          * <p>A path specification, relative to the Component's <code>{@link #ownerCt}</code>
1269          * specifying into which ancestor Container to place a named reference to this Component.</p>
1270          * <p>The ancestor axis can be traversed by using '/' characters in the path.
1271          * For example, to put a reference to a Toolbar Button into <i>the Panel which owns the Toolbar</i>:</p><pre><code>
1272 var myGrid = new Ext.grid.EditorGridPanel({
1273     title: 'My EditorGridPanel',
1274     store: myStore,
1275     colModel: myColModel,
1276     tbar: [{
1277         text: 'Save',
1278         handler: saveChanges,
1279         disabled: true,
1280         ref: '../saveButton'
1281     }],
1282     listeners: {
1283         afteredit: function() {
1284 //          The button reference is in the GridPanel
1285             myGrid.saveButton.enable();
1286         }
1287     }
1288 });
1289 </code></pre>
1290          * <p>In the code above, if the <code>ref</code> had been <code>'saveButton'</code>
1291          * the reference would have been placed into the Toolbar. Each '/' in the <code>ref</code>
1292          * moves up one level from the Component's <code>{@link #ownerCt}</code>.</p>
1293          * <p>Also see the <code>{@link #added}</code> and <code>{@link #removed}</code> events.</p>
1294          */
1295         if(this.ref && !this.refOwner){
1296             var levels = this.ref.split('/'),
1297                 last = levels.length,
1298                 i = 0,
1299                 t = this;
1300
1301             while(t && i < last){
1302                 t = t.ownerCt;
1303                 ++i;
1304             }
1305             if(t){
1306                 t[this.refName = levels[--i]] = this;
1307                 /**
1308                  * @type Ext.Container
1309                  * @property refOwner
1310                  * The ancestor Container into which the {@link #ref} reference was inserted if this Component
1311                  * is a child of a Container, and has been configured with a <code>ref</code>.
1312                  */
1313                 this.refOwner = t;
1314             }
1315         }
1316     },
1317
1318     removeRef : function() {
1319         if (this.refOwner && this.refName) {
1320             delete this.refOwner[this.refName];
1321             delete this.refOwner;
1322         }
1323     },
1324
1325     // private
1326     initState : function(){
1327         if(Ext.state.Manager){
1328             var id = this.getStateId();
1329             if(id){
1330                 var state = Ext.state.Manager.get(id);
1331                 if(state){
1332                     if(this.fireEvent('beforestaterestore', this, state) !== false){
1333                         this.applyState(Ext.apply({}, state));
1334                         this.fireEvent('staterestore', this, state);
1335                     }
1336                 }
1337             }
1338         }
1339     },
1340
1341     // private
1342     getStateId : function(){
1343         return this.stateId || ((/^(ext-comp-|ext-gen)/).test(String(this.id)) ? null : this.id);
1344     },
1345
1346     // private
1347     initStateEvents : function(){
1348         if(this.stateEvents){
1349             for(var i = 0, e; e = this.stateEvents[i]; i++){
1350                 this.on(e, this.saveState, this, {delay:100});
1351             }
1352         }
1353     },
1354
1355     // private
1356     applyState : function(state){
1357         if(state){
1358             Ext.apply(this, state);
1359         }
1360     },
1361
1362     // private
1363     getState : function(){
1364         return null;
1365     },
1366
1367     // private
1368     saveState : function(){
1369         if(Ext.state.Manager && this.stateful !== false){
1370             var id = this.getStateId();
1371             if(id){
1372                 var state = this.getState();
1373                 if(this.fireEvent('beforestatesave', this, state) !== false){
1374                     Ext.state.Manager.set(id, state);
1375                     this.fireEvent('statesave', this, state);
1376                 }
1377             }
1378         }
1379     },
1380
1381     /**
1382      * Apply this component to existing markup that is valid. With this function, no call to render() is required.
1383      * @param {String/HTMLElement} el
1384      */
1385     applyToMarkup : function(el){
1386         this.allowDomMove = false;
1387         this.el = Ext.get(el);
1388         this.render(this.el.dom.parentNode);
1389     },
1390
1391     /**
1392      * Adds a CSS class to the component's underlying element.
1393      * @param {string} cls The CSS class name to add
1394      * @return {Ext.Component} this
1395      */
1396     addClass : function(cls){
1397         if(this.el){
1398             this.el.addClass(cls);
1399         }else{
1400             this.cls = this.cls ? this.cls + ' ' + cls : cls;
1401         }
1402         return this;
1403     },
1404
1405     /**
1406      * Removes a CSS class from the component's underlying element.
1407      * @param {string} cls The CSS class name to remove
1408      * @return {Ext.Component} this
1409      */
1410     removeClass : function(cls){
1411         if(this.el){
1412             this.el.removeClass(cls);
1413         }else if(this.cls){
1414             this.cls = this.cls.split(' ').remove(cls).join(' ');
1415         }
1416         return this;
1417     },
1418
1419     // private
1420     // default function is not really useful
1421     onRender : function(ct, position){
1422         if(!this.el && this.autoEl){
1423             if(Ext.isString(this.autoEl)){
1424                 this.el = document.createElement(this.autoEl);
1425             }else{
1426                 var div = document.createElement('div');
1427                 Ext.DomHelper.overwrite(div, this.autoEl);
1428                 this.el = div.firstChild;
1429             }
1430             if (!this.el.id) {
1431                 this.el.id = this.getId();
1432             }
1433         }
1434         if(this.el){
1435             this.el = Ext.get(this.el);
1436             if(this.allowDomMove !== false){
1437                 ct.dom.insertBefore(this.el.dom, position);
1438                 if (div) {
1439                     Ext.removeNode(div);
1440                     div = null;
1441                 }
1442             }
1443         }
1444     },
1445
1446     // private
1447     getAutoCreate : function(){
1448         var cfg = Ext.isObject(this.autoCreate) ?
1449                       this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
1450         if(this.id && !cfg.id){
1451             cfg.id = this.id;
1452         }
1453         return cfg;
1454     },
1455
1456     // private
1457     afterRender : Ext.emptyFn,
1458
1459     /**
1460      * Destroys this component by purging any event listeners, removing the component's element from the DOM,
1461      * removing the component from its {@link Ext.Container} (if applicable) and unregistering it from
1462      * {@link Ext.ComponentMgr}.  Destruction is generally handled automatically by the framework and this method
1463      * should usually not need to be called directly.
1464      *
1465      */
1466     destroy : function(){
1467         if(!this.isDestroyed){
1468             if(this.fireEvent('beforedestroy', this) !== false){
1469                 this.destroying = true;
1470                 this.beforeDestroy();
1471                 if(this.ownerCt && this.ownerCt.remove){
1472                     this.ownerCt.remove(this, false);
1473                 }
1474                 if(this.rendered){
1475                     this.el.remove();
1476                     if(this.actionMode == 'container' || this.removeMode == 'container'){
1477                         this.container.remove();
1478                     }
1479                 }
1480                 // Stop any buffered tasks
1481                 if(this.focusTask && this.focusTask.cancel){
1482                     this.focusTask.cancel();
1483                 }
1484                 this.onDestroy();
1485                 Ext.ComponentMgr.unregister(this);
1486                 this.fireEvent('destroy', this);
1487                 this.purgeListeners();
1488                 this.destroying = false;
1489                 this.isDestroyed = true;
1490             }
1491         }
1492     },
1493
1494     deleteMembers : function(){
1495         var args = arguments;
1496         for(var i = 0, len = args.length; i < len; ++i){
1497             delete this[args[i]];
1498         }
1499     },
1500
1501     // private
1502     beforeDestroy : Ext.emptyFn,
1503
1504     // private
1505     onDestroy  : Ext.emptyFn,
1506
1507     /**
1508      * <p>Returns the {@link Ext.Element} which encapsulates this Component.</p>
1509      * <p>This will <i>usually</i> be a &lt;DIV> element created by the class's onRender method, but
1510      * that may be overridden using the {@link #autoEl} config.</p>
1511      * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br>
1512      * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners
1513      * for this Component's own Observable events), see the {@link #listeners} config for a suggestion,
1514      * or use a render listener directly:</p><pre><code>
1515 new Ext.Panel({
1516     title: 'The Clickable Panel',
1517     listeners: {
1518         render: function(p) {
1519             // Append the Panel to the click handler&#39;s argument list.
1520             p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));
1521         },
1522         single: true  // Remove the listener after first invocation
1523     }
1524 });
1525 </code></pre>
1526      * @return {Ext.Element} The Element which encapsulates this Component.
1527      */
1528     getEl : function(){
1529         return this.el;
1530     },
1531
1532     // private
1533     getContentTarget : function(){
1534         return this.el;
1535     },
1536
1537     /**
1538      * Returns the <code>id</code> of this component or automatically generates and
1539      * returns an <code>id</code> if an <code>id</code> is not defined yet:<pre><code>
1540      * 'ext-comp-' + (++Ext.Component.AUTO_ID)
1541      * </code></pre>
1542      * @return {String} id
1543      */
1544     getId : function(){
1545         return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
1546     },
1547
1548     /**
1549      * Returns the <code>{@link #itemId}</code> of this component.  If an
1550      * <code>{@link #itemId}</code> was not assigned through configuration the
1551      * <code>id</code> is returned using <code>{@link #getId}</code>.
1552      * @return {String}
1553      */
1554     getItemId : function(){
1555         return this.itemId || this.getId();
1556     },
1557
1558     /**
1559      * Try to focus this component.
1560      * @param {Boolean} selectText (optional) If applicable, true to also select the text in this component
1561      * @param {Boolean/Number} delay (optional) Delay the focus this number of milliseconds (true for 10 milliseconds)
1562      * @return {Ext.Component} this
1563      */
1564     focus : function(selectText, delay){
1565         if(delay){
1566             this.focusTask = new Ext.util.DelayedTask(this.focus, this, [selectText, false]);
1567             this.focusTask.delay(Ext.isNumber(delay) ? delay : 10);
1568             return;
1569         }
1570         if(this.rendered && !this.isDestroyed){
1571             this.el.focus();
1572             if(selectText === true){
1573                 this.el.dom.select();
1574             }
1575         }
1576         return this;
1577     },
1578
1579     // private
1580     blur : function(){
1581         if(this.rendered){
1582             this.el.blur();
1583         }
1584         return this;
1585     },
1586
1587     /**
1588      * Disable this component and fire the 'disable' event.
1589      * @return {Ext.Component} this
1590      */
1591     disable : function(/* private */ silent){
1592         if(this.rendered){
1593             this.onDisable();
1594         }
1595         this.disabled = true;
1596         if(silent !== true){
1597             this.fireEvent('disable', this);
1598         }
1599         return this;
1600     },
1601
1602     // private
1603     onDisable : function(){
1604         this.getActionEl().addClass(this.disabledClass);
1605         this.el.dom.disabled = true;
1606     },
1607
1608     /**
1609      * Enable this component and fire the 'enable' event.
1610      * @return {Ext.Component} this
1611      */
1612     enable : function(){
1613         if(this.rendered){
1614             this.onEnable();
1615         }
1616         this.disabled = false;
1617         this.fireEvent('enable', this);
1618         return this;
1619     },
1620
1621     // private
1622     onEnable : function(){
1623         this.getActionEl().removeClass(this.disabledClass);
1624         this.el.dom.disabled = false;
1625     },
1626
1627     /**
1628      * Convenience function for setting disabled/enabled by boolean.
1629      * @param {Boolean} disabled
1630      * @return {Ext.Component} this
1631      */
1632     setDisabled : function(disabled){
1633         return this[disabled ? 'disable' : 'enable']();
1634     },
1635
1636     /**
1637      * Show this component.  Listen to the '{@link #beforeshow}' event and return
1638      * <tt>false</tt> to cancel showing the component.  Fires the '{@link #show}'
1639      * event after showing the component.
1640      * @return {Ext.Component} this
1641      */
1642     show : function(){
1643         if(this.fireEvent('beforeshow', this) !== false){
1644             this.hidden = false;
1645             if(this.autoRender){
1646                 this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
1647             }
1648             if(this.rendered){
1649                 this.onShow();
1650             }
1651             this.fireEvent('show', this);
1652         }
1653         return this;
1654     },
1655
1656     // private
1657     onShow : function(){
1658         this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);
1659     },
1660
1661     /**
1662      * Hide this component.  Listen to the '{@link #beforehide}' event and return
1663      * <tt>false</tt> to cancel hiding the component.  Fires the '{@link #hide}'
1664      * event after hiding the component. Note this method is called internally if
1665      * the component is configured to be <code>{@link #hidden}</code>.
1666      * @return {Ext.Component} this
1667      */
1668     hide : function(){
1669         if(this.fireEvent('beforehide', this) !== false){
1670             this.doHide();
1671             this.fireEvent('hide', this);
1672         }
1673         return this;
1674     },
1675
1676     // private
1677     doHide: function(){
1678         this.hidden = true;
1679         if(this.rendered){
1680             this.onHide();
1681         }
1682     },
1683
1684     // private
1685     onHide : function(){
1686         this.getVisibilityEl().addClass('x-hide-' + this.hideMode);
1687     },
1688
1689     // private
1690     getVisibilityEl : function(){
1691         return this.hideParent ? this.container : this.getActionEl();
1692     },
1693
1694     /**
1695      * Convenience function to hide or show this component by boolean.
1696      * @param {Boolean} visible True to show, false to hide
1697      * @return {Ext.Component} this
1698      */
1699     setVisible : function(visible){
1700         return this[visible ? 'show' : 'hide']();
1701     },
1702
1703     /**
1704      * Returns true if this component is visible.
1705      * @return {Boolean} True if this component is visible, false otherwise.
1706      */
1707     isVisible : function(){
1708         return this.rendered && this.getVisibilityEl().isVisible();
1709     },
1710
1711     /**
1712      * Clone the current component using the original config values passed into this instance by default.
1713      * @param {Object} overrides A new config containing any properties to override in the cloned version.
1714      * An id property can be passed on this object, otherwise one will be generated to avoid duplicates.
1715      * @return {Ext.Component} clone The cloned copy of this component
1716      */
1717     cloneConfig : function(overrides){
1718         overrides = overrides || {};
1719         var id = overrides.id || Ext.id();
1720         var cfg = Ext.applyIf(overrides, this.initialConfig);
1721         cfg.id = id; // prevent dup id
1722         return new this.constructor(cfg);
1723     },
1724
1725     /**
1726      * Gets the xtype for this component as registered with {@link Ext.ComponentMgr}. For a list of all
1727      * available xtypes, see the {@link Ext.Component} header. Example usage:
1728      * <pre><code>
1729 var t = new Ext.form.TextField();
1730 alert(t.getXType());  // alerts 'textfield'
1731 </code></pre>
1732      * @return {String} The xtype
1733      */
1734     getXType : function(){
1735         return this.constructor.xtype;
1736     },
1737
1738     /**
1739      * <p>Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended
1740      * from the xtype (default) or whether it is directly of the xtype specified (shallow = true).</p>
1741      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1742      * to participate in determination of inherited xtypes.</b></p>
1743      * <p>For a list of all available xtypes, see the {@link Ext.Component} header.</p>
1744      * <p>Example usage:</p>
1745      * <pre><code>
1746 var t = new Ext.form.TextField();
1747 var isText = t.isXType('textfield');        // true
1748 var isBoxSubclass = t.isXType('box');       // true, descended from BoxComponent
1749 var isBoxInstance = t.isXType('box', true); // false, not a direct BoxComponent instance
1750 </code></pre>
1751      * @param {String} xtype The xtype to check for this Component
1752      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
1753      * the default), or true to check whether this Component is directly of the specified xtype.
1754      * @return {Boolean} True if this component descends from the specified xtype, false otherwise.
1755      */
1756     isXType : function(xtype, shallow){
1757         //assume a string by default
1758         if (Ext.isFunction(xtype)){
1759             xtype = xtype.xtype; //handle being passed the class, e.g. Ext.Component
1760         }else if (Ext.isObject(xtype)){
1761             xtype = xtype.constructor.xtype; //handle being passed an instance
1762         }
1763
1764         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
1765     },
1766
1767     /**
1768      * <p>Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all
1769      * available xtypes, see the {@link Ext.Component} header.</p>
1770      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1771      * to participate in determination of inherited xtypes.</b></p>
1772      * <p>Example usage:</p>
1773      * <pre><code>
1774 var t = new Ext.form.TextField();
1775 alert(t.getXTypes());  // alerts 'component/box/field/textfield'
1776 </code></pre>
1777      * @return {String} The xtype hierarchy string
1778      */
1779     getXTypes : function(){
1780         var tc = this.constructor;
1781         if(!tc.xtypes){
1782             var c = [], sc = this;
1783             while(sc && sc.constructor.xtype){
1784                 c.unshift(sc.constructor.xtype);
1785                 sc = sc.constructor.superclass;
1786             }
1787             tc.xtypeChain = c;
1788             tc.xtypes = c.join('/');
1789         }
1790         return tc.xtypes;
1791     },
1792
1793     /**
1794      * Find a container above this component at any level by a custom function. If the passed function returns
1795      * true, the container will be returned.
1796      * @param {Function} fn The custom function to call with the arguments (container, this component).
1797      * @return {Ext.Container} The first Container for which the custom function returns true
1798      */
1799     findParentBy : function(fn) {
1800         for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
1801         return p || null;
1802     },
1803
1804     /**
1805      * Find a container above this component at any level by xtype or class
1806      * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
1807      * @return {Ext.Container} The first Container which matches the given xtype or class
1808      */
1809     findParentByType : function(xtype) {
1810         return Ext.isFunction(xtype) ?
1811             this.findParentBy(function(p){
1812                 return p.constructor === xtype;
1813             }) :
1814             this.findParentBy(function(p){
1815                 return p.constructor.xtype === xtype;
1816             });
1817     },
1818
1819     // protected
1820     getPositionEl : function(){
1821         return this.positionEl || this.el;
1822     },
1823
1824     // private
1825     purgeListeners : function(){
1826         Ext.Component.superclass.purgeListeners.call(this);
1827         if(this.mons){
1828             this.on('beforedestroy', this.clearMons, this, {single: true});
1829         }
1830     },
1831
1832     // private
1833     clearMons : function(){
1834         Ext.each(this.mons, function(m){
1835             m.item.un(m.ename, m.fn, m.scope);
1836         }, this);
1837         this.mons = [];
1838     },
1839
1840     // private
1841     createMons: function(){
1842         if(!this.mons){
1843             this.mons = [];
1844             this.on('beforedestroy', this.clearMons, this, {single: true});
1845         }
1846     },
1847
1848     /**
1849      * <p>Adds listeners to any Observable object (or Elements) which are automatically removed when this Component
1850      * is destroyed. Usage:</p><code><pre>
1851 myGridPanel.mon(myGridPanel.getSelectionModel(), 'selectionchange', handleSelectionChange, null, {buffer: 50});
1852 </pre></code>
1853      * <p>or:</p><code><pre>
1854 myGridPanel.mon(myGridPanel.getSelectionModel(), {
1855     selectionchange: handleSelectionChange,
1856     buffer: 50
1857 });
1858 </pre></code>
1859      * @param {Observable|Element} item The item to which to add a listener/listeners.
1860      * @param {Object|String} ename The event name, or an object containing event name properties.
1861      * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this
1862      * is the handler function.
1863      * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this
1864      * is the scope (<code>this</code> reference) in which the handler function is executed.
1865      * @param {Object} opt Optional. If the <code>ename</code> parameter was an event name, this
1866      * is the {@link Ext.util.Observable#addListener addListener} options.
1867      */
1868     mon : function(item, ename, fn, scope, opt){
1869         this.createMons();
1870         if(Ext.isObject(ename)){
1871             var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
1872
1873             var o = ename;
1874             for(var e in o){
1875                 if(propRe.test(e)){
1876                     continue;
1877                 }
1878                 if(Ext.isFunction(o[e])){
1879                     // shared options
1880                     this.mons.push({
1881                         item: item, ename: e, fn: o[e], scope: o.scope
1882                     });
1883                     item.on(e, o[e], o.scope, o);
1884                 }else{
1885                     // individual options
1886                     this.mons.push({
1887                         item: item, ename: e, fn: o[e], scope: o.scope
1888                     });
1889                     item.on(e, o[e]);
1890                 }
1891             }
1892             return;
1893         }
1894
1895         this.mons.push({
1896             item: item, ename: ename, fn: fn, scope: scope
1897         });
1898         item.on(ename, fn, scope, opt);
1899     },
1900
1901     /**
1902      * Removes listeners that were added by the {@link #mon} method.
1903      * @param {Observable|Element} item The item from which to remove a listener/listeners.
1904      * @param {Object|String} ename The event name, or an object containing event name properties.
1905      * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this
1906      * is the handler function.
1907      * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this
1908      * is the scope (<code>this</code> reference) in which the handler function is executed.
1909      */
1910     mun : function(item, ename, fn, scope){
1911         var found, mon;
1912         this.createMons();
1913         for(var i = 0, len = this.mons.length; i < len; ++i){
1914             mon = this.mons[i];
1915             if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){
1916                 this.mons.splice(i, 1);
1917                 item.un(ename, fn, scope);
1918                 found = true;
1919                 break;
1920             }
1921         }
1922         return found;
1923     },
1924
1925     /**
1926      * Returns the next component in the owning container
1927      * @return Ext.Component
1928      */
1929     nextSibling : function(){
1930         if(this.ownerCt){
1931             var index = this.ownerCt.items.indexOf(this);
1932             if(index != -1 && index+1 < this.ownerCt.items.getCount()){
1933                 return this.ownerCt.items.itemAt(index+1);
1934             }
1935         }
1936         return null;
1937     },
1938
1939     /**
1940      * Returns the previous component in the owning container
1941      * @return Ext.Component
1942      */
1943     previousSibling : function(){
1944         if(this.ownerCt){
1945             var index = this.ownerCt.items.indexOf(this);
1946             if(index > 0){
1947                 return this.ownerCt.items.itemAt(index-1);
1948             }
1949         }
1950         return null;
1951     },
1952
1953     /**
1954      * Provides the link for Observable's fireEvent method to bubble up the ownership hierarchy.
1955      * @return {Ext.Container} the Container which owns this Component.
1956      */
1957     getBubbleTarget : function(){
1958         return this.ownerCt;
1959     }
1960 });
1961
1962 Ext.reg('component', Ext.Component);/**
1963  * @class Ext.Action
1964  * <p>An Action is a piece of reusable functionality that can be abstracted out of any particular component so that it
1965  * can be usefully shared among multiple components.  Actions let you share handlers, configuration options and UI
1966  * updates across any components that support the Action interface (primarily {@link Ext.Toolbar}, {@link Ext.Button}
1967  * and {@link Ext.menu.Menu} components).</p>
1968  * <p>Aside from supporting the config object interface, any component that needs to use Actions must also support
1969  * the following method list, as these will be called as needed by the Action class: setText(string), setIconCls(string),
1970  * setDisabled(boolean), setVisible(boolean) and setHandler(function).</p>
1971  * Example usage:<br>
1972  * <pre><code>
1973 // Define the shared action.  Each component below will have the same
1974 // display text and icon, and will display the same message on click.
1975 var action = new Ext.Action({
1976     {@link #text}: 'Do something',
1977     {@link #handler}: function(){
1978         Ext.Msg.alert('Click', 'You did something.');
1979     },
1980     {@link #iconCls}: 'do-something',
1981     {@link #itemId}: 'myAction'
1982 });
1983
1984 var panel = new Ext.Panel({
1985     title: 'Actions',
1986     width: 500,
1987     height: 300,
1988     tbar: [
1989         // Add the action directly to a toolbar as a menu button
1990         action,
1991         {
1992             text: 'Action Menu',
1993             // Add the action to a menu as a text item
1994             menu: [action]
1995         }
1996     ],
1997     items: [
1998         // Add the action to the panel body as a standard button
1999         new Ext.Button(action)
2000     ],
2001     renderTo: Ext.getBody()
2002 });
2003
2004 // Change the text for all components using the action
2005 action.setText('Something else');
2006
2007 // Reference an action through a container using the itemId
2008 var btn = panel.getComponent('myAction');
2009 var aRef = btn.baseAction;
2010 aRef.setText('New text');
2011 </code></pre>
2012  * @constructor
2013  * @param {Object} config The configuration options
2014  */
2015 Ext.Action = Ext.extend(Object, {
2016     /**
2017      * @cfg {String} text The text to set for all components using this action (defaults to '').
2018      */
2019     /**
2020      * @cfg {String} iconCls
2021      * The CSS class selector that specifies a background image to be used as the header icon for
2022      * all components using this action (defaults to '').
2023      * <p>An example of specifying a custom icon class would be something like:
2024      * </p><pre><code>
2025 // specify the property in the config for the class:
2026      ...
2027      iconCls: 'do-something'
2028
2029 // css class that specifies background image to be used as the icon image:
2030 .do-something { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
2031 </code></pre>
2032      */
2033     /**
2034      * @cfg {Boolean} disabled True to disable all components using this action, false to enable them (defaults to false).
2035      */
2036     /**
2037      * @cfg {Boolean} hidden True to hide all components using this action, false to show them (defaults to false).
2038      */
2039     /**
2040      * @cfg {Function} handler The function that will be invoked by each component tied to this action
2041      * when the component's primary event is triggered (defaults to undefined).
2042      */
2043     /**
2044      * @cfg {String} itemId
2045      * See {@link Ext.Component}.{@link Ext.Component#itemId itemId}.
2046      */
2047     /**
2048      * @cfg {Object} scope The scope (<tt><b>this</b></tt> reference) in which the
2049      * <code>{@link #handler}</code> is executed. Defaults to this Button.
2050      */
2051
2052     constructor : function(config){
2053         this.initialConfig = config;
2054         this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
2055         this.items = [];
2056     },
2057     
2058     // private
2059     isAction : true,
2060
2061     /**
2062      * Sets the text to be displayed by all components using this action.
2063      * @param {String} text The text to display
2064      */
2065     setText : function(text){
2066         this.initialConfig.text = text;
2067         this.callEach('setText', [text]);
2068     },
2069
2070     /**
2071      * Gets the text currently displayed by all components using this action.
2072      */
2073     getText : function(){
2074         return this.initialConfig.text;
2075     },
2076
2077     /**
2078      * Sets the icon CSS class for all components using this action.  The class should supply
2079      * a background image that will be used as the icon image.
2080      * @param {String} cls The CSS class supplying the icon image
2081      */
2082     setIconClass : function(cls){
2083         this.initialConfig.iconCls = cls;
2084         this.callEach('setIconClass', [cls]);
2085     },
2086
2087     /**
2088      * Gets the icon CSS class currently used by all components using this action.
2089      */
2090     getIconClass : function(){
2091         return this.initialConfig.iconCls;
2092     },
2093
2094     /**
2095      * Sets the disabled state of all components using this action.  Shortcut method
2096      * for {@link #enable} and {@link #disable}.
2097      * @param {Boolean} disabled True to disable the component, false to enable it
2098      */
2099     setDisabled : function(v){
2100         this.initialConfig.disabled = v;
2101         this.callEach('setDisabled', [v]);
2102     },
2103
2104     /**
2105      * Enables all components using this action.
2106      */
2107     enable : function(){
2108         this.setDisabled(false);
2109     },
2110
2111     /**
2112      * Disables all components using this action.
2113      */
2114     disable : function(){
2115         this.setDisabled(true);
2116     },
2117
2118     /**
2119      * Returns true if the components using this action are currently disabled, else returns false.  
2120      */
2121     isDisabled : function(){
2122         return this.initialConfig.disabled;
2123     },
2124
2125     /**
2126      * Sets the hidden state of all components using this action.  Shortcut method
2127      * for <code>{@link #hide}</code> and <code>{@link #show}</code>.
2128      * @param {Boolean} hidden True to hide the component, false to show it
2129      */
2130     setHidden : function(v){
2131         this.initialConfig.hidden = v;
2132         this.callEach('setVisible', [!v]);
2133     },
2134
2135     /**
2136      * Shows all components using this action.
2137      */
2138     show : function(){
2139         this.setHidden(false);
2140     },
2141
2142     /**
2143      * Hides all components using this action.
2144      */
2145     hide : function(){
2146         this.setHidden(true);
2147     },
2148
2149     /**
2150      * Returns true if the components using this action are currently hidden, else returns false.  
2151      */
2152     isHidden : function(){
2153         return this.initialConfig.hidden;
2154     },
2155
2156     /**
2157      * Sets the function that will be called by each Component using this action when its primary event is triggered.
2158      * @param {Function} fn The function that will be invoked by the action's components.  The function
2159      * will be called with no arguments.
2160      * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed. Defaults to the Component firing the event.
2161      */
2162     setHandler : function(fn, scope){
2163         this.initialConfig.handler = fn;
2164         this.initialConfig.scope = scope;
2165         this.callEach('setHandler', [fn, scope]);
2166     },
2167
2168     /**
2169      * Executes the specified function once for each Component currently tied to this action.  The function passed
2170      * in should accept a single argument that will be an object that supports the basic Action config/method interface.
2171      * @param {Function} fn The function to execute for each component
2172      * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed.  Defaults to the Component.
2173      */
2174     each : function(fn, scope){
2175         Ext.each(this.items, fn, scope);
2176     },
2177
2178     // private
2179     callEach : function(fnName, args){
2180         var cs = this.items;
2181         for(var i = 0, len = cs.length; i < len; i++){
2182             cs[i][fnName].apply(cs[i], args);
2183         }
2184     },
2185
2186     // private
2187     addComponent : function(comp){
2188         this.items.push(comp);
2189         comp.on('destroy', this.removeComponent, this);
2190     },
2191
2192     // private
2193     removeComponent : function(comp){
2194         this.items.remove(comp);
2195     },
2196
2197     /**
2198      * Executes this action manually using the handler function specified in the original config object
2199      * or the handler function set with <code>{@link #setHandler}</code>.  Any arguments passed to this
2200      * function will be passed on to the handler function.
2201      * @param {Mixed} arg1 (optional) Variable number of arguments passed to the handler function
2202      * @param {Mixed} arg2 (optional)
2203      * @param {Mixed} etc... (optional)
2204      */
2205     execute : function(){
2206         this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
2207     }
2208 });
2209 /**
2210  * @class Ext.Layer
2211  * @extends Ext.Element
2212  * An extended {@link Ext.Element} object that supports a shadow and shim, constrain to viewport and
2213  * automatic maintaining of shadow/shim positions.
2214  * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true)
2215  * @cfg {String/Boolean} shadow True to automatically create an {@link Ext.Shadow}, or a string indicating the
2216  * shadow's display {@link Ext.Shadow#mode}. False to disable the shadow. (defaults to false)
2217  * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: 'div', cls: 'x-layer'}).
2218  * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true)
2219  * @cfg {String} cls CSS class to add to the element
2220  * @cfg {Number} zindex Starting z-index (defaults to 11000)
2221  * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 4)
2222  * @cfg {Boolean} useDisplay
2223  * Defaults to use css offsets to hide the Layer. Specify <tt>true</tt>
2224  * to use css style <tt>'display:none;'</tt> to hide the Layer.
2225  * @constructor
2226  * @param {Object} config An object with config options.
2227  * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element. If the element is not found it creates it.
2228  */
2229 (function(){
2230 Ext.Layer = function(config, existingEl){
2231     config = config || {};
2232     var dh = Ext.DomHelper;
2233     var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
2234     if(existingEl){
2235         this.dom = Ext.getDom(existingEl);
2236     }
2237     if(!this.dom){
2238         var o = config.dh || {tag: 'div', cls: 'x-layer'};
2239         this.dom = dh.append(pel, o);
2240     }
2241     if(config.cls){
2242         this.addClass(config.cls);
2243     }
2244     this.constrain = config.constrain !== false;
2245     this.setVisibilityMode(Ext.Element.VISIBILITY);
2246     if(config.id){
2247         this.id = this.dom.id = config.id;
2248     }else{
2249         this.id = Ext.id(this.dom);
2250     }
2251     this.zindex = config.zindex || this.getZIndex();
2252     this.position('absolute', this.zindex);
2253     if(config.shadow){
2254         this.shadowOffset = config.shadowOffset || 4;
2255         this.shadow = new Ext.Shadow({
2256             offset : this.shadowOffset,
2257             mode : config.shadow
2258         });
2259     }else{
2260         this.shadowOffset = 0;
2261     }
2262     this.useShim = config.shim !== false && Ext.useShims;
2263     this.useDisplay = config.useDisplay;
2264     this.hide();
2265 };
2266
2267 var supr = Ext.Element.prototype;
2268
2269 // shims are shared among layer to keep from having 100 iframes
2270 var shims = [];
2271
2272 Ext.extend(Ext.Layer, Ext.Element, {
2273
2274     getZIndex : function(){
2275         return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
2276     },
2277
2278     getShim : function(){
2279         if(!this.useShim){
2280             return null;
2281         }
2282         if(this.shim){
2283             return this.shim;
2284         }
2285         var shim = shims.shift();
2286         if(!shim){
2287             shim = this.createShim();
2288             shim.enableDisplayMode('block');
2289             shim.dom.style.display = 'none';
2290             shim.dom.style.visibility = 'visible';
2291         }
2292         var pn = this.dom.parentNode;
2293         if(shim.dom.parentNode != pn){
2294             pn.insertBefore(shim.dom, this.dom);
2295         }
2296         shim.setStyle('z-index', this.getZIndex()-2);
2297         this.shim = shim;
2298         return shim;
2299     },
2300
2301     hideShim : function(){
2302         if(this.shim){
2303             this.shim.setDisplayed(false);
2304             shims.push(this.shim);
2305             delete this.shim;
2306         }
2307     },
2308
2309     disableShadow : function(){
2310         if(this.shadow){
2311             this.shadowDisabled = true;
2312             this.shadow.hide();
2313             this.lastShadowOffset = this.shadowOffset;
2314             this.shadowOffset = 0;
2315         }
2316     },
2317
2318     enableShadow : function(show){
2319         if(this.shadow){
2320             this.shadowDisabled = false;
2321             this.shadowOffset = this.lastShadowOffset;
2322             delete this.lastShadowOffset;
2323             if(show){
2324                 this.sync(true);
2325             }
2326         }
2327     },
2328
2329     // private
2330     // this code can execute repeatedly in milliseconds (i.e. during a drag) so
2331     // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
2332     sync : function(doShow){
2333         var shadow = this.shadow;
2334         if(!this.updating && this.isVisible() && (shadow || this.useShim)){
2335             var shim = this.getShim(),
2336                 w = this.getWidth(),
2337                 h = this.getHeight(),
2338                 l = this.getLeft(true),
2339                 t = this.getTop(true);
2340
2341             if(shadow && !this.shadowDisabled){
2342                 if(doShow && !shadow.isVisible()){
2343                     shadow.show(this);
2344                 }else{
2345                     shadow.realign(l, t, w, h);
2346                 }
2347                 if(shim){
2348                     if(doShow){
2349                        shim.show();
2350                     }
2351                     // fit the shim behind the shadow, so it is shimmed too
2352                     var shadowAdj = shadow.el.getXY(), shimStyle = shim.dom.style,
2353                         shadowSize = shadow.el.getSize();
2354                     shimStyle.left = (shadowAdj[0])+'px';
2355                     shimStyle.top = (shadowAdj[1])+'px';
2356                     shimStyle.width = (shadowSize.width)+'px';
2357                     shimStyle.height = (shadowSize.height)+'px';
2358                 }
2359             }else if(shim){
2360                 if(doShow){
2361                    shim.show();
2362                 }
2363                 shim.setSize(w, h);
2364                 shim.setLeftTop(l, t);
2365             }
2366         }
2367     },
2368
2369     // private
2370     destroy : function(){
2371         this.hideShim();
2372         if(this.shadow){
2373             this.shadow.hide();
2374         }
2375         this.removeAllListeners();
2376         Ext.removeNode(this.dom);
2377         delete this.dom;
2378     },
2379
2380     remove : function(){
2381         this.destroy();
2382     },
2383
2384     // private
2385     beginUpdate : function(){
2386         this.updating = true;
2387     },
2388
2389     // private
2390     endUpdate : function(){
2391         this.updating = false;
2392         this.sync(true);
2393     },
2394
2395     // private
2396     hideUnders : function(negOffset){
2397         if(this.shadow){
2398             this.shadow.hide();
2399         }
2400         this.hideShim();
2401     },
2402
2403     // private
2404     constrainXY : function(){
2405         if(this.constrain){
2406             var vw = Ext.lib.Dom.getViewWidth(),
2407                 vh = Ext.lib.Dom.getViewHeight();
2408             var s = Ext.getDoc().getScroll();
2409
2410             var xy = this.getXY();
2411             var x = xy[0], y = xy[1];
2412             var so = this.shadowOffset;
2413             var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so;
2414             // only move it if it needs it
2415             var moved = false;
2416             // first validate right/bottom
2417             if((x + w) > vw+s.left){
2418                 x = vw - w - so;
2419                 moved = true;
2420             }
2421             if((y + h) > vh+s.top){
2422                 y = vh - h - so;
2423                 moved = true;
2424             }
2425             // then make sure top/left isn't negative
2426             if(x < s.left){
2427                 x = s.left;
2428                 moved = true;
2429             }
2430             if(y < s.top){
2431                 y = s.top;
2432                 moved = true;
2433             }
2434             if(moved){
2435                 if(this.avoidY){
2436                     var ay = this.avoidY;
2437                     if(y <= ay && (y+h) >= ay){
2438                         y = ay-h-5;
2439                     }
2440                 }
2441                 xy = [x, y];
2442                 this.storeXY(xy);
2443                 supr.setXY.call(this, xy);
2444                 this.sync();
2445             }
2446         }
2447         return this;
2448     },
2449
2450     isVisible : function(){
2451         return this.visible;
2452     },
2453
2454     // private
2455     showAction : function(){
2456         this.visible = true; // track visibility to prevent getStyle calls
2457         if(this.useDisplay === true){
2458             this.setDisplayed('');
2459         }else if(this.lastXY){
2460             supr.setXY.call(this, this.lastXY);
2461         }else if(this.lastLT){
2462             supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
2463         }
2464     },
2465
2466     // private
2467     hideAction : function(){
2468         this.visible = false;
2469         if(this.useDisplay === true){
2470             this.setDisplayed(false);
2471         }else{
2472             this.setLeftTop(-10000,-10000);
2473         }
2474     },
2475
2476     // overridden Element method
2477     setVisible : function(v, a, d, c, e){
2478         if(v){
2479             this.showAction();
2480         }
2481         if(a && v){
2482             var cb = function(){
2483                 this.sync(true);
2484                 if(c){
2485                     c();
2486                 }
2487             }.createDelegate(this);
2488             supr.setVisible.call(this, true, true, d, cb, e);
2489         }else{
2490             if(!v){
2491                 this.hideUnders(true);
2492             }
2493             var cb = c;
2494             if(a){
2495                 cb = function(){
2496                     this.hideAction();
2497                     if(c){
2498                         c();
2499                     }
2500                 }.createDelegate(this);
2501             }
2502             supr.setVisible.call(this, v, a, d, cb, e);
2503             if(v){
2504                 this.sync(true);
2505             }else if(!a){
2506                 this.hideAction();
2507             }
2508         }
2509         return this;
2510     },
2511
2512     storeXY : function(xy){
2513         delete this.lastLT;
2514         this.lastXY = xy;
2515     },
2516
2517     storeLeftTop : function(left, top){
2518         delete this.lastXY;
2519         this.lastLT = [left, top];
2520     },
2521
2522     // private
2523     beforeFx : function(){
2524         this.beforeAction();
2525         return Ext.Layer.superclass.beforeFx.apply(this, arguments);
2526     },
2527
2528     // private
2529     afterFx : function(){
2530         Ext.Layer.superclass.afterFx.apply(this, arguments);
2531         this.sync(this.isVisible());
2532     },
2533
2534     // private
2535     beforeAction : function(){
2536         if(!this.updating && this.shadow){
2537             this.shadow.hide();
2538         }
2539     },
2540
2541     // overridden Element method
2542     setLeft : function(left){
2543         this.storeLeftTop(left, this.getTop(true));
2544         supr.setLeft.apply(this, arguments);
2545         this.sync();
2546         return this;
2547     },
2548
2549     setTop : function(top){
2550         this.storeLeftTop(this.getLeft(true), top);
2551         supr.setTop.apply(this, arguments);
2552         this.sync();
2553         return this;
2554     },
2555
2556     setLeftTop : function(left, top){
2557         this.storeLeftTop(left, top);
2558         supr.setLeftTop.apply(this, arguments);
2559         this.sync();
2560         return this;
2561     },
2562
2563     setXY : function(xy, a, d, c, e){
2564         this.fixDisplay();
2565         this.beforeAction();
2566         this.storeXY(xy);
2567         var cb = this.createCB(c);
2568         supr.setXY.call(this, xy, a, d, cb, e);
2569         if(!a){
2570             cb();
2571         }
2572         return this;
2573     },
2574
2575     // private
2576     createCB : function(c){
2577         var el = this;
2578         return function(){
2579             el.constrainXY();
2580             el.sync(true);
2581             if(c){
2582                 c();
2583             }
2584         };
2585     },
2586
2587     // overridden Element method
2588     setX : function(x, a, d, c, e){
2589         this.setXY([x, this.getY()], a, d, c, e);
2590         return this;
2591     },
2592
2593     // overridden Element method
2594     setY : function(y, a, d, c, e){
2595         this.setXY([this.getX(), y], a, d, c, e);
2596         return this;
2597     },
2598
2599     // overridden Element method
2600     setSize : function(w, h, a, d, c, e){
2601         this.beforeAction();
2602         var cb = this.createCB(c);
2603         supr.setSize.call(this, w, h, a, d, cb, e);
2604         if(!a){
2605             cb();
2606         }
2607         return this;
2608     },
2609
2610     // overridden Element method
2611     setWidth : function(w, a, d, c, e){
2612         this.beforeAction();
2613         var cb = this.createCB(c);
2614         supr.setWidth.call(this, w, a, d, cb, e);
2615         if(!a){
2616             cb();
2617         }
2618         return this;
2619     },
2620
2621     // overridden Element method
2622     setHeight : function(h, a, d, c, e){
2623         this.beforeAction();
2624         var cb = this.createCB(c);
2625         supr.setHeight.call(this, h, a, d, cb, e);
2626         if(!a){
2627             cb();
2628         }
2629         return this;
2630     },
2631
2632     // overridden Element method
2633     setBounds : function(x, y, w, h, a, d, c, e){
2634         this.beforeAction();
2635         var cb = this.createCB(c);
2636         if(!a){
2637             this.storeXY([x, y]);
2638             supr.setXY.call(this, [x, y]);
2639             supr.setSize.call(this, w, h, a, d, cb, e);
2640             cb();
2641         }else{
2642             supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
2643         }
2644         return this;
2645     },
2646
2647     /**
2648      * Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
2649      * incremented by two more than the value passed in so that it always shows above any shadow or shim (the shadow
2650      * element, if any, will be assigned z-index + 1, and the shim element, if any, will be assigned the unmodified z-index).
2651      * @param {Number} zindex The new z-index to set
2652      * @return {this} The Layer
2653      */
2654     setZIndex : function(zindex){
2655         this.zindex = zindex;
2656         this.setStyle('z-index', zindex + 2);
2657         if(this.shadow){
2658             this.shadow.setZIndex(zindex + 1);
2659         }
2660         if(this.shim){
2661             this.shim.setStyle('z-index', zindex);
2662         }
2663         return this;
2664     }
2665 });
2666 })();
2667 /**
2668  * @class Ext.Shadow
2669  * Simple class that can provide a shadow effect for any element.  Note that the element MUST be absolutely positioned,
2670  * and the shadow does not provide any shimming.  This should be used only in simple cases -- for more advanced
2671  * functionality that can also provide the same shadow effect, see the {@link Ext.Layer} class.
2672  * @constructor
2673  * Create a new Shadow
2674  * @param {Object} config The config object
2675  */
2676 Ext.Shadow = function(config){
2677     Ext.apply(this, config);
2678     if(typeof this.mode != "string"){
2679         this.mode = this.defaultMode;
2680     }
2681     var o = this.offset, a = {h: 0};
2682     var rad = Math.floor(this.offset/2);
2683     switch(this.mode.toLowerCase()){ // all this hideous nonsense calculates the various offsets for shadows
2684         case "drop":
2685             a.w = 0;
2686             a.l = a.t = o;
2687             a.t -= 1;
2688             if(Ext.isIE){
2689                 a.l -= this.offset + rad;
2690                 a.t -= this.offset + rad;
2691                 a.w -= rad;
2692                 a.h -= rad;
2693                 a.t += 1;
2694             }
2695         break;
2696         case "sides":
2697             a.w = (o*2);
2698             a.l = -o;
2699             a.t = o-1;
2700             if(Ext.isIE){
2701                 a.l -= (this.offset - rad);
2702                 a.t -= this.offset + rad;
2703                 a.l += 1;
2704                 a.w -= (this.offset - rad)*2;
2705                 a.w -= rad + 1;
2706                 a.h -= 1;
2707             }
2708         break;
2709         case "frame":
2710             a.w = a.h = (o*2);
2711             a.l = a.t = -o;
2712             a.t += 1;
2713             a.h -= 2;
2714             if(Ext.isIE){
2715                 a.l -= (this.offset - rad);
2716                 a.t -= (this.offset - rad);
2717                 a.l += 1;
2718                 a.w -= (this.offset + rad + 1);
2719                 a.h -= (this.offset + rad);
2720                 a.h += 1;
2721             }
2722         break;
2723     };
2724
2725     this.adjusts = a;
2726 };
2727
2728 Ext.Shadow.prototype = {
2729     /**
2730      * @cfg {String} mode
2731      * The shadow display mode.  Supports the following options:<div class="mdetail-params"><ul>
2732      * <li><b><tt>sides</tt></b> : Shadow displays on both sides and bottom only</li>
2733      * <li><b><tt>frame</tt></b> : Shadow displays equally on all four sides</li>
2734      * <li><b><tt>drop</tt></b> : Traditional bottom-right drop shadow</li>
2735      * </ul></div>
2736      */
2737     /**
2738      * @cfg {String} offset
2739      * The number of pixels to offset the shadow from the element (defaults to <tt>4</tt>)
2740      */
2741     offset: 4,
2742
2743     // private
2744     defaultMode: "drop",
2745
2746     /**
2747      * Displays the shadow under the target element
2748      * @param {Mixed} targetEl The id or element under which the shadow should display
2749      */
2750     show : function(target){
2751         target = Ext.get(target);
2752         if(!this.el){
2753             this.el = Ext.Shadow.Pool.pull();
2754             if(this.el.dom.nextSibling != target.dom){
2755                 this.el.insertBefore(target);
2756             }
2757         }
2758         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
2759         if(Ext.isIE){
2760             this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
2761         }
2762         this.realign(
2763             target.getLeft(true),
2764             target.getTop(true),
2765             target.getWidth(),
2766             target.getHeight()
2767         );
2768         this.el.dom.style.display = "block";
2769     },
2770
2771     /**
2772      * Returns true if the shadow is visible, else false
2773      */
2774     isVisible : function(){
2775         return this.el ? true : false;  
2776     },
2777
2778     /**
2779      * Direct alignment when values are already available. Show must be called at least once before
2780      * calling this method to ensure it is initialized.
2781      * @param {Number} left The target element left position
2782      * @param {Number} top The target element top position
2783      * @param {Number} width The target element width
2784      * @param {Number} height The target element height
2785      */
2786     realign : function(l, t, w, h){
2787         if(!this.el){
2788             return;
2789         }
2790         var a = this.adjusts, d = this.el.dom, s = d.style;
2791         var iea = 0;
2792         s.left = (l+a.l)+"px";
2793         s.top = (t+a.t)+"px";
2794         var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
2795         if(s.width != sws || s.height != shs){
2796             s.width = sws;
2797             s.height = shs;
2798             if(!Ext.isIE){
2799                 var cn = d.childNodes;
2800                 var sww = Math.max(0, (sw-12))+"px";
2801                 cn[0].childNodes[1].style.width = sww;
2802                 cn[1].childNodes[1].style.width = sww;
2803                 cn[2].childNodes[1].style.width = sww;
2804                 cn[1].style.height = Math.max(0, (sh-12))+"px";
2805             }
2806         }
2807     },
2808
2809     /**
2810      * Hides this shadow
2811      */
2812     hide : function(){
2813         if(this.el){
2814             this.el.dom.style.display = "none";
2815             Ext.Shadow.Pool.push(this.el);
2816             delete this.el;
2817         }
2818     },
2819
2820     /**
2821      * Adjust the z-index of this shadow
2822      * @param {Number} zindex The new z-index
2823      */
2824     setZIndex : function(z){
2825         this.zIndex = z;
2826         if(this.el){
2827             this.el.setStyle("z-index", z);
2828         }
2829     }
2830 };
2831
2832 // Private utility class that manages the internal Shadow cache
2833 Ext.Shadow.Pool = function(){
2834     var p = [];
2835     var markup = Ext.isIE ?
2836                  '<div class="x-ie-shadow"></div>' :
2837                  '<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>';
2838     return {
2839         pull : function(){
2840             var sh = p.shift();
2841             if(!sh){
2842                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
2843                 sh.autoBoxAdjust = false;
2844             }
2845             return sh;
2846         },
2847
2848         push : function(sh){
2849             p.push(sh);
2850         }
2851     };
2852 }();/**
2853  * @class Ext.BoxComponent
2854  * @extends Ext.Component
2855  * <p>Base class for any {@link Ext.Component Component} that is to be sized as a box, using width and height.</p>
2856  * <p>BoxComponent provides automatic box model adjustments for sizing and positioning and will work correctly
2857  * within the Component rendering model.</p>
2858  * <p>A BoxComponent may be created as a custom Component which encapsulates any HTML element, either a pre-existing
2859  * element, or one that is created to your specifications at render time. Usually, to participate in layouts,
2860  * a Component will need to be a <b>Box</b>Component in order to have its width and height managed.</p>
2861  * <p>To use a pre-existing element as a BoxComponent, configure it so that you preset the <b>el</b> property to the
2862  * element to reference:<pre><code>
2863 var pageHeader = new Ext.BoxComponent({
2864     el: 'my-header-div'
2865 });</code></pre>
2866  * This may then be {@link Ext.Container#add added} to a {@link Ext.Container Container} as a child item.</p>
2867  * <p>To create a BoxComponent based around a HTML element to be created at render time, use the
2868  * {@link Ext.Component#autoEl autoEl} config option which takes the form of a
2869  * {@link Ext.DomHelper DomHelper} specification:<pre><code>
2870 var myImage = new Ext.BoxComponent({
2871     autoEl: {
2872         tag: 'img',
2873         src: '/images/my-image.jpg'
2874     }
2875 });</code></pre></p>
2876  * @constructor
2877  * @param {Ext.Element/String/Object} config The configuration options.
2878  * @xtype box
2879  */
2880 Ext.BoxComponent = Ext.extend(Ext.Component, {
2881
2882     // Configs below are used for all Components when rendered by BoxLayout.
2883     /**
2884      * @cfg {Number} flex
2885      * <p><b>Note</b>: this config is only used when this Component is rendered
2886      * by a Container which has been configured to use a <b>{@link Ext.layout.BoxLayout BoxLayout}.</b>
2887      * Each child Component with a <code>flex</code> property will be flexed either vertically (by a VBoxLayout)
2888      * or horizontally (by an HBoxLayout) according to the item's <b>relative</b> <code>flex</code> value
2889      * compared to the sum of all Components with <code>flex</flex> value specified. Any child items that have
2890      * either a <code>flex = 0</code> or <code>flex = undefined</code> will not be 'flexed' (the initial size will not be changed).
2891      */
2892     // Configs below are used for all Components when rendered by AnchorLayout.
2893     /**
2894      * @cfg {String} anchor <p><b>Note</b>: this config is only used when this Component is rendered
2895      * by a Container which has been configured to use an <b>{@link Ext.layout.AnchorLayout AnchorLayout} (or subclass thereof).</b>
2896      * based layout manager, for example:<div class="mdetail-params"><ul>
2897      * <li>{@link Ext.form.FormPanel}</li>
2898      * <li>specifying <code>layout: 'anchor' // or 'form', or 'absolute'</code></li>
2899      * </ul></div></p>
2900      * <p>See {@link Ext.layout.AnchorLayout}.{@link Ext.layout.AnchorLayout#anchor anchor} also.</p>
2901      */
2902     // tabTip config is used when a BoxComponent is a child of a TabPanel
2903     /**
2904      * @cfg {String} tabTip
2905      * <p><b>Note</b>: this config is only used when this BoxComponent is a child item of a TabPanel.</p>
2906      * A string to be used as innerHTML (html tags are accepted) to show in a tooltip when mousing over
2907      * the associated tab selector element. {@link Ext.QuickTips}.init()
2908      * must be called in order for the tips to render.
2909      */
2910     // Configs below are used for all Components when rendered by BorderLayout.
2911     /**
2912      * @cfg {String} region <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2913      * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2914      * layout manager (e.g. specifying <tt>layout:'border'</tt>).</p><br>
2915      * <p>See {@link Ext.layout.BorderLayout} also.</p>
2916      */
2917     // margins config is used when a BoxComponent is rendered by BorderLayout or BoxLayout.
2918     /**
2919      * @cfg {Object} margins <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2920      * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2921      * or one of the two <b>{@link Ext.layout.BoxLayout BoxLayout} subclasses.</b></p>
2922      * <p>An object containing margins to apply to this BoxComponent in the
2923      * format:</p><pre><code>
2924 {
2925     top: (top margin),
2926     right: (right margin),
2927     bottom: (bottom margin),
2928     left: (left margin)
2929 }</code></pre>
2930      * <p>May also be a string containing space-separated, numeric margin values. The order of the
2931      * sides associated with each value matches the way CSS processes margin values:</p>
2932      * <p><div class="mdetail-params"><ul>
2933      * <li>If there is only one value, it applies to all sides.</li>
2934      * <li>If there are two values, the top and bottom borders are set to the first value and the
2935      * right and left are set to the second.</li>
2936      * <li>If there are three values, the top is set to the first value, the left and right are set
2937      * to the second, and the bottom is set to the third.</li>
2938      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
2939      * </ul></div></p>
2940      * <p>Defaults to:</p><pre><code>
2941      * {top:0, right:0, bottom:0, left:0}
2942      * </code></pre>
2943      */
2944     /**
2945      * @cfg {Number} x
2946      * The local x (left) coordinate for this component if contained within a positioning container.
2947      */
2948     /**
2949      * @cfg {Number} y
2950      * The local y (top) coordinate for this component if contained within a positioning container.
2951      */
2952     /**
2953      * @cfg {Number} pageX
2954      * The page level x coordinate for this component if contained within a positioning container.
2955      */
2956     /**
2957      * @cfg {Number} pageY
2958      * The page level y coordinate for this component if contained within a positioning container.
2959      */
2960     /**
2961      * @cfg {Number} height
2962      * The height of this component in pixels (defaults to auto).
2963      * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
2964      */
2965     /**
2966      * @cfg {Number} width
2967      * The width of this component in pixels (defaults to auto).
2968      * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
2969      */
2970     /**
2971      * @cfg {Number} boxMinHeight
2972      * <p>The minimum value in pixels which this BoxComponent will set its height to.</p>
2973      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2974      */
2975     /**
2976      * @cfg {Number} boxMinWidth
2977      * <p>The minimum value in pixels which this BoxComponent will set its width to.</p>
2978      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2979      */
2980     /**
2981      * @cfg {Number} boxMaxHeight
2982      * <p>The maximum value in pixels which this BoxComponent will set its height to.</p>
2983      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2984      */
2985     /**
2986      * @cfg {Number} boxMaxWidth
2987      * <p>The maximum value in pixels which this BoxComponent will set its width to.</p>
2988      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2989      */
2990     /**
2991      * @cfg {Boolean} autoHeight
2992      * <p>True to use height:'auto', false to use fixed height (or allow it to be managed by its parent
2993      * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
2994      * <p><b>Note</b>: Although many components inherit this config option, not all will
2995      * function as expected with a height of 'auto'. Setting autoHeight:true means that the
2996      * browser will manage height based on the element's contents, and that Ext will not manage it at all.</p>
2997      * <p>If the <i>browser</i> is managing the height, be aware that resizes performed by the browser in response
2998      * to changes within the structure of the Component cannot be detected. Therefore changes to the height might
2999      * result in elements needing to be synchronized with the new height. Example:</p><pre><code>
3000 var w = new Ext.Window({
3001     title: 'Window',
3002     width: 600,
3003     autoHeight: true,
3004     items: {
3005         title: 'Collapse Me',
3006         height: 400,
3007         collapsible: true,
3008         border: false,
3009         listeners: {
3010             beforecollapse: function() {
3011                 w.el.shadow.hide();
3012             },
3013             beforeexpand: function() {
3014                 w.el.shadow.hide();
3015             },
3016             collapse: function() {
3017                 w.syncShadow();
3018             },
3019             expand: function() {
3020                 w.syncShadow();
3021             }
3022         }
3023     }
3024 }).show();
3025 </code></pre>
3026      */
3027     /**
3028      * @cfg {Boolean} autoWidth
3029      * <p>True to use width:'auto', false to use fixed width (or allow it to be managed by its parent
3030      * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
3031      * <p><b>Note</b>: Although many components  inherit this config option, not all will
3032      * function as expected with a width of 'auto'. Setting autoWidth:true means that the
3033      * browser will manage width based on the element's contents, and that Ext will not manage it at all.</p>
3034      * <p>If the <i>browser</i> is managing the width, be aware that resizes performed by the browser in response
3035      * to changes within the structure of the Component cannot be detected. Therefore changes to the width might
3036      * result in elements needing to be synchronized with the new width. For example, where the target element is:</p><pre><code>
3037 &lt;div id='grid-container' style='margin-left:25%;width:50%'>&lt;/div>
3038 </code></pre>
3039      * A Panel rendered into that target element must listen for browser window resize in order to relay its
3040       * child items when the browser changes its width:<pre><code>
3041 var myPanel = new Ext.Panel({
3042     renderTo: 'grid-container',
3043     monitorResize: true, // relay on browser resize
3044     title: 'Panel',
3045     height: 400,
3046     autoWidth: true,
3047     layout: 'hbox',
3048     layoutConfig: {
3049         align: 'stretch'
3050     },
3051     defaults: {
3052         flex: 1
3053     },
3054     items: [{
3055         title: 'Box 1',
3056     }, {
3057         title: 'Box 2'
3058     }, {
3059         title: 'Box 3'
3060     }],
3061 });
3062 </code></pre>
3063      */
3064     /**
3065      * @cfg {Boolean} autoScroll
3066      * <code>true</code> to use overflow:'auto' on the components layout element and show scroll bars automatically when
3067      * necessary, <code>false</code> to clip any overflowing content (defaults to <code>false</code>).
3068      */
3069
3070     /* // private internal config
3071      * {Boolean} deferHeight
3072      * True to defer height calculations to an external component, false to allow this component to set its own
3073      * height (defaults to false).
3074      */
3075
3076     // private
3077     initComponent : function(){
3078         Ext.BoxComponent.superclass.initComponent.call(this);
3079         this.addEvents(
3080             /**
3081              * @event resize
3082              * Fires after the component is resized.
3083              * @param {Ext.Component} this
3084              * @param {Number} adjWidth The box-adjusted width that was set
3085              * @param {Number} adjHeight The box-adjusted height that was set
3086              * @param {Number} rawWidth The width that was originally specified
3087              * @param {Number} rawHeight The height that was originally specified
3088              */
3089             'resize',
3090             /**
3091              * @event move
3092              * Fires after the component is moved.
3093              * @param {Ext.Component} this
3094              * @param {Number} x The new x position
3095              * @param {Number} y The new y position
3096              */
3097             'move'
3098         );
3099     },
3100
3101     // private, set in afterRender to signify that the component has been rendered
3102     boxReady : false,
3103     // private, used to defer height settings to subclasses
3104     deferHeight: false,
3105
3106     /**
3107      * Sets the width and height of this BoxComponent. This method fires the {@link #resize} event. This method can accept
3108      * either width and height as separate arguments, or you can pass a size object like <code>{width:10, height:20}</code>.
3109      * @param {Mixed} width The new width to set. This may be one of:<div class="mdetail-params"><ul>
3110      * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3111      * <li>A String used to set the CSS width style.</li>
3112      * <li>A size object in the format <code>{width: widthValue, height: heightValue}</code>.</li>
3113      * <li><code>undefined</code> to leave the width unchanged.</li>
3114      * </ul></div>
3115      * @param {Mixed} height The new height to set (not required if a size object is passed as the first arg).
3116      * This may be one of:<div class="mdetail-params"><ul>
3117      * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3118      * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
3119      * <li><code>undefined</code> to leave the height unchanged.</li>
3120      * </ul></div>
3121      * @return {Ext.BoxComponent} this
3122      */
3123     setSize : function(w, h){
3124
3125         // support for standard size objects
3126         if(typeof w == 'object'){
3127             h = w.height;
3128             w = w.width;
3129         }
3130         if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
3131             w = this.boxMinWidth;
3132         }
3133         if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) {
3134             h = this.boxMinHeight;
3135         }
3136         if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) {
3137             w = this.boxMaxWidth;
3138         }
3139         if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) {
3140             h = this.boxMaxHeight;
3141         }
3142         // not rendered
3143         if(!this.boxReady){
3144             this.width  = w;
3145             this.height = h;
3146             return this;
3147         }
3148
3149         // prevent recalcs when not needed
3150         if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
3151             return this;
3152         }
3153         this.lastSize = {width: w, height: h};
3154         var adj = this.adjustSize(w, h),
3155             aw = adj.width,
3156             ah = adj.height,
3157             rz;
3158         if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
3159             rz = this.getResizeEl();
3160             if(!this.deferHeight && aw !== undefined && ah !== undefined){
3161                 rz.setSize(aw, ah);
3162             }else if(!this.deferHeight && ah !== undefined){
3163                 rz.setHeight(ah);
3164             }else if(aw !== undefined){
3165                 rz.setWidth(aw);
3166             }
3167             this.onResize(aw, ah, w, h);
3168             this.fireEvent('resize', this, aw, ah, w, h);
3169         }
3170         return this;
3171     },
3172
3173     /**
3174      * Sets the width of the component.  This method fires the {@link #resize} event.
3175      * @param {Mixed} width The new width to set. This may be one of:<div class="mdetail-params"><ul>
3176      * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit defaultUnit}s (by default, pixels).</li>
3177      * <li>A String used to set the CSS width style.</li>
3178      * </ul></div>
3179      * @return {Ext.BoxComponent} this
3180      */
3181     setWidth : function(width){
3182         return this.setSize(width);
3183     },
3184
3185     /**
3186      * Sets the height of the component.  This method fires the {@link #resize} event.
3187      * @param {Mixed} height The new height to set. This may be one of:<div class="mdetail-params"><ul>
3188      * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit defaultUnit}s (by default, pixels).</li>
3189      * <li>A String used to set the CSS height style.</li>
3190      * <li><i>undefined</i> to leave the height unchanged.</li>
3191      * </ul></div>
3192      * @return {Ext.BoxComponent} this
3193      */
3194     setHeight : function(height){
3195         return this.setSize(undefined, height);
3196     },
3197
3198     /**
3199      * Gets the current size of the component's underlying element.
3200      * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
3201      */
3202     getSize : function(){
3203         return this.getResizeEl().getSize();
3204     },
3205
3206     /**
3207      * Gets the current width of the component's underlying element.
3208      * @return {Number}
3209      */
3210     getWidth : function(){
3211         return this.getResizeEl().getWidth();
3212     },
3213
3214     /**
3215      * Gets the current height of the component's underlying element.
3216      * @return {Number}
3217      */
3218     getHeight : function(){
3219         return this.getResizeEl().getHeight();
3220     },
3221
3222     /**
3223      * Gets the current size of the component's underlying element, including space taken by its margins.
3224      * @return {Object} An object containing the element's size {width: (element width + left/right margins), height: (element height + top/bottom margins)}
3225      */
3226     getOuterSize : function(){
3227         var el = this.getResizeEl();
3228         return {width: el.getWidth() + el.getMargins('lr'),
3229                 height: el.getHeight() + el.getMargins('tb')};
3230     },
3231
3232     /**
3233      * Gets the current XY position of the component's underlying element.
3234      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
3235      * @return {Array} The XY position of the element (e.g., [100, 200])
3236      */
3237     getPosition : function(local){
3238         var el = this.getPositionEl();
3239         if(local === true){
3240             return [el.getLeft(true), el.getTop(true)];
3241         }
3242         return this.xy || el.getXY();
3243     },
3244
3245     /**
3246      * Gets the current box measurements of the component's underlying element.
3247      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
3248      * @return {Object} box An object in the format {x, y, width, height}
3249      */
3250     getBox : function(local){
3251         var pos = this.getPosition(local);
3252         var s = this.getSize();
3253         s.x = pos[0];
3254         s.y = pos[1];
3255         return s;
3256     },
3257
3258     /**
3259      * Sets the current box measurements of the component's underlying element.
3260      * @param {Object} box An object in the format {x, y, width, height}
3261      * @return {Ext.BoxComponent} this
3262      */
3263     updateBox : function(box){
3264         this.setSize(box.width, box.height);
3265         this.setPagePosition(box.x, box.y);
3266         return this;
3267     },
3268
3269     /**
3270      * <p>Returns the outermost Element of this Component which defines the Components overall size.</p>
3271      * <p><i>Usually</i> this will return the same Element as <code>{@link #getEl}</code>,
3272      * but in some cases, a Component may have some more wrapping Elements around its main
3273      * active Element.</p>
3274      * <p>An example is a ComboBox. It is encased in a <i>wrapping</i> Element which
3275      * contains both the <code>&lt;input></code> Element (which is what would be returned
3276      * by its <code>{@link #getEl}</code> method, <i>and</i> the trigger button Element.
3277      * This Element is returned as the <code>resizeEl</code>.
3278      * @return {Ext.Element} The Element which is to be resized by size managing layouts.
3279      */
3280     getResizeEl : function(){
3281         return this.resizeEl || this.el;
3282     },
3283
3284     /**
3285      * Sets the overflow on the content element of the component.
3286      * @param {Boolean} scroll True to allow the Component to auto scroll.
3287      * @return {Ext.BoxComponent} this
3288      */
3289     setAutoScroll : function(scroll){
3290         if(this.rendered){
3291             this.getContentTarget().setOverflow(scroll ? 'auto' : '');
3292         }
3293         this.autoScroll = scroll;
3294         return this;
3295     },
3296
3297     /**
3298      * Sets the left and top of the component.  To set the page XY position instead, use {@link #setPagePosition}.
3299      * This method fires the {@link #move} event.
3300      * @param {Number} left The new left
3301      * @param {Number} top The new top
3302      * @return {Ext.BoxComponent} this
3303      */
3304     setPosition : function(x, y){
3305         if(x && typeof x[1] == 'number'){
3306             y = x[1];
3307             x = x[0];
3308         }
3309         this.x = x;
3310         this.y = y;
3311         if(!this.boxReady){
3312             return this;
3313         }
3314         var adj = this.adjustPosition(x, y);
3315         var ax = adj.x, ay = adj.y;
3316
3317         var el = this.getPositionEl();
3318         if(ax !== undefined || ay !== undefined){
3319             if(ax !== undefined && ay !== undefined){
3320                 el.setLeftTop(ax, ay);
3321             }else if(ax !== undefined){
3322                 el.setLeft(ax);
3323             }else if(ay !== undefined){
3324                 el.setTop(ay);
3325             }
3326             this.onPosition(ax, ay);
3327             this.fireEvent('move', this, ax, ay);
3328         }
3329         return this;
3330     },
3331
3332     /**
3333      * Sets the page XY position of the component.  To set the left and top instead, use {@link #setPosition}.
3334      * This method fires the {@link #move} event.
3335      * @param {Number} x The new x position
3336      * @param {Number} y The new y position
3337      * @return {Ext.BoxComponent} this
3338      */
3339     setPagePosition : function(x, y){
3340         if(x && typeof x[1] == 'number'){
3341             y = x[1];
3342             x = x[0];
3343         }
3344         this.pageX = x;
3345         this.pageY = y;
3346         if(!this.boxReady){
3347             return;
3348         }
3349         if(x === undefined || y === undefined){ // cannot translate undefined points
3350             return;
3351         }
3352         var p = this.getPositionEl().translatePoints(x, y);
3353         this.setPosition(p.left, p.top);
3354         return this;
3355     },
3356
3357     // private
3358     afterRender : function(){
3359         Ext.BoxComponent.superclass.afterRender.call(this);
3360         if(this.resizeEl){
3361             this.resizeEl = Ext.get(this.resizeEl);
3362         }
3363         if(this.positionEl){
3364             this.positionEl = Ext.get(this.positionEl);
3365         }
3366         this.boxReady = true;
3367         Ext.isDefined(this.autoScroll) && this.setAutoScroll(this.autoScroll);
3368         this.setSize(this.width, this.height);
3369         if(this.x || this.y){
3370             this.setPosition(this.x, this.y);
3371         }else if(this.pageX || this.pageY){
3372             this.setPagePosition(this.pageX, this.pageY);
3373         }
3374     },
3375
3376     /**
3377      * Force the component's size to recalculate based on the underlying element's current height and width.
3378      * @return {Ext.BoxComponent} this
3379      */
3380     syncSize : function(){
3381         delete this.lastSize;
3382         this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
3383         return this;
3384     },
3385
3386     /* // protected
3387      * Called after the component is resized, this method is empty by default but can be implemented by any
3388      * subclass that needs to perform custom logic after a resize occurs.
3389      * @param {Number} adjWidth The box-adjusted width that was set
3390      * @param {Number} adjHeight The box-adjusted height that was set
3391      * @param {Number} rawWidth The width that was originally specified
3392      * @param {Number} rawHeight The height that was originally specified
3393      */
3394     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
3395     },
3396
3397     /* // protected
3398      * Called after the component is moved, this method is empty by default but can be implemented by any
3399      * subclass that needs to perform custom logic after a move occurs.
3400      * @param {Number} x The new x position
3401      * @param {Number} y The new y position
3402      */
3403     onPosition : function(x, y){
3404
3405     },
3406
3407     // private
3408     adjustSize : function(w, h){
3409         if(this.autoWidth){
3410             w = 'auto';
3411         }
3412         if(this.autoHeight){
3413             h = 'auto';
3414         }
3415         return {width : w, height: h};
3416     },
3417
3418     // private
3419     adjustPosition : function(x, y){
3420         return {x : x, y: y};
3421     }
3422 });
3423 Ext.reg('box', Ext.BoxComponent);
3424
3425
3426 /**
3427  * @class Ext.Spacer
3428  * @extends Ext.BoxComponent
3429  * <p>Used to provide a sizable space in a layout.</p>
3430  * @constructor
3431  * @param {Object} config
3432  */
3433 Ext.Spacer = Ext.extend(Ext.BoxComponent, {
3434     autoEl:'div'
3435 });
3436 Ext.reg('spacer', Ext.Spacer);/**
3437  * @class Ext.SplitBar
3438  * @extends Ext.util.Observable
3439  * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).
3440  * <br><br>
3441  * Usage:
3442  * <pre><code>
3443 var split = new Ext.SplitBar("elementToDrag", "elementToSize",
3444                    Ext.SplitBar.HORIZONTAL, Ext.SplitBar.LEFT);
3445 split.setAdapter(new Ext.SplitBar.AbsoluteLayoutAdapter("container"));
3446 split.minSize = 100;
3447 split.maxSize = 600;
3448 split.animate = true;
3449 split.on('moved', splitterMoved);
3450 </code></pre>
3451  * @constructor
3452  * Create a new SplitBar
3453  * @param {Mixed} dragElement The element to be dragged and act as the SplitBar.
3454  * @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged
3455  * @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
3456  * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or
3457                         Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial
3458                         position of the SplitBar).
3459  */
3460 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
3461
3462     /** @private */
3463     this.el = Ext.get(dragElement, true);
3464     this.el.dom.unselectable = "on";
3465     /** @private */
3466     this.resizingEl = Ext.get(resizingElement, true);
3467
3468     /**
3469      * @private
3470      * The orientation of the split. Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
3471      * Note: If this is changed after creating the SplitBar, the placement property must be manually updated
3472      * @type Number
3473      */
3474     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
3475
3476     /**
3477      * The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.
3478      * @type Number
3479      * @property tickSize
3480      */
3481     /**
3482      * The minimum size of the resizing element. (Defaults to 0)
3483      * @type Number
3484      */
3485     this.minSize = 0;
3486
3487     /**
3488      * The maximum size of the resizing element. (Defaults to 2000)
3489      * @type Number
3490      */
3491     this.maxSize = 2000;
3492
3493     /**
3494      * Whether to animate the transition to the new size
3495      * @type Boolean
3496      */
3497     this.animate = false;
3498
3499     /**
3500      * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.
3501      * @type Boolean
3502      */
3503     this.useShim = false;
3504
3505     /** @private */
3506     this.shim = null;
3507
3508     if(!existingProxy){
3509         /** @private */
3510         this.proxy = Ext.SplitBar.createProxy(this.orientation);
3511     }else{
3512         this.proxy = Ext.get(existingProxy).dom;
3513     }
3514     /** @private */
3515     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
3516
3517     /** @private */
3518     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
3519
3520     /** @private */
3521     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
3522
3523     /** @private */
3524     this.dragSpecs = {};
3525
3526     /**
3527      * @private The adapter to use to positon and resize elements
3528      */
3529     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
3530     this.adapter.init(this);
3531
3532     if(this.orientation == Ext.SplitBar.HORIZONTAL){
3533         /** @private */
3534         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
3535         this.el.addClass("x-splitbar-h");
3536     }else{
3537         /** @private */
3538         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
3539         this.el.addClass("x-splitbar-v");
3540     }
3541
3542     this.addEvents(
3543         /**
3544          * @event resize
3545          * Fires when the splitter is moved (alias for {@link #moved})
3546          * @param {Ext.SplitBar} this
3547          * @param {Number} newSize the new width or height
3548          */
3549         "resize",
3550         /**
3551          * @event moved
3552          * Fires when the splitter is moved
3553          * @param {Ext.SplitBar} this
3554          * @param {Number} newSize the new width or height
3555          */
3556         "moved",
3557         /**
3558          * @event beforeresize
3559          * Fires before the splitter is dragged
3560          * @param {Ext.SplitBar} this
3561          */
3562         "beforeresize",
3563
3564         "beforeapply"
3565     );
3566
3567     Ext.SplitBar.superclass.constructor.call(this);
3568 };
3569
3570 Ext.extend(Ext.SplitBar, Ext.util.Observable, {
3571     onStartProxyDrag : function(x, y){
3572         this.fireEvent("beforeresize", this);
3573         this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);
3574         this.overlay.unselectable();
3575         this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
3576         this.overlay.show();
3577         Ext.get(this.proxy).setDisplayed("block");
3578         var size = this.adapter.getElementSize(this);
3579         this.activeMinSize = this.getMinimumSize();
3580         this.activeMaxSize = this.getMaximumSize();
3581         var c1 = size - this.activeMinSize;
3582         var c2 = Math.max(this.activeMaxSize - size, 0);
3583         if(this.orientation == Ext.SplitBar.HORIZONTAL){
3584             this.dd.resetConstraints();
3585             this.dd.setXConstraint(
3586                 this.placement == Ext.SplitBar.LEFT ? c1 : c2,
3587                 this.placement == Ext.SplitBar.LEFT ? c2 : c1,
3588                 this.tickSize
3589             );
3590             this.dd.setYConstraint(0, 0);
3591         }else{
3592             this.dd.resetConstraints();
3593             this.dd.setXConstraint(0, 0);
3594             this.dd.setYConstraint(
3595                 this.placement == Ext.SplitBar.TOP ? c1 : c2,
3596                 this.placement == Ext.SplitBar.TOP ? c2 : c1,
3597                 this.tickSize
3598             );
3599          }
3600         this.dragSpecs.startSize = size;
3601         this.dragSpecs.startPoint = [x, y];
3602         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
3603     },
3604
3605     /**
3606      * @private Called after the drag operation by the DDProxy
3607      */
3608     onEndProxyDrag : function(e){
3609         Ext.get(this.proxy).setDisplayed(false);
3610         var endPoint = Ext.lib.Event.getXY(e);
3611         if(this.overlay){
3612             Ext.destroy(this.overlay);
3613             delete this.overlay;
3614         }
3615         var newSize;
3616         if(this.orientation == Ext.SplitBar.HORIZONTAL){
3617             newSize = this.dragSpecs.startSize +
3618                 (this.placement == Ext.SplitBar.LEFT ?
3619                     endPoint[0] - this.dragSpecs.startPoint[0] :
3620                     this.dragSpecs.startPoint[0] - endPoint[0]
3621                 );
3622         }else{
3623             newSize = this.dragSpecs.startSize +
3624                 (this.placement == Ext.SplitBar.TOP ?
3625                     endPoint[1] - this.dragSpecs.startPoint[1] :
3626                     this.dragSpecs.startPoint[1] - endPoint[1]
3627                 );
3628         }
3629         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
3630         if(newSize != this.dragSpecs.startSize){
3631             if(this.fireEvent('beforeapply', this, newSize) !== false){
3632                 this.adapter.setElementSize(this, newSize);
3633                 this.fireEvent("moved", this, newSize);
3634                 this.fireEvent("resize", this, newSize);
3635             }
3636         }
3637     },
3638
3639     /**
3640      * Get the adapter this SplitBar uses
3641      * @return The adapter object
3642      */
3643     getAdapter : function(){
3644         return this.adapter;
3645     },
3646
3647     /**
3648      * Set the adapter this SplitBar uses
3649      * @param {Object} adapter A SplitBar adapter object
3650      */
3651     setAdapter : function(adapter){
3652         this.adapter = adapter;
3653         this.adapter.init(this);
3654     },
3655
3656     /**
3657      * Gets the minimum size for the resizing element
3658      * @return {Number} The minimum size
3659      */
3660     getMinimumSize : function(){
3661         return this.minSize;
3662     },
3663
3664     /**
3665      * Sets the minimum size for the resizing element
3666      * @param {Number} minSize The minimum size
3667      */
3668     setMinimumSize : function(minSize){
3669         this.minSize = minSize;
3670     },
3671
3672     /**
3673      * Gets the maximum size for the resizing element
3674      * @return {Number} The maximum size
3675      */
3676     getMaximumSize : function(){
3677         return this.maxSize;
3678     },
3679
3680     /**
3681      * Sets the maximum size for the resizing element
3682      * @param {Number} maxSize The maximum size
3683      */
3684     setMaximumSize : function(maxSize){
3685         this.maxSize = maxSize;
3686     },
3687
3688     /**
3689      * Sets the initialize size for the resizing element
3690      * @param {Number} size The initial size
3691      */
3692     setCurrentSize : function(size){
3693         var oldAnimate = this.animate;
3694         this.animate = false;
3695         this.adapter.setElementSize(this, size);
3696         this.animate = oldAnimate;
3697     },
3698
3699     /**
3700      * Destroy this splitbar.
3701      * @param {Boolean} removeEl True to remove the element
3702      */
3703     destroy : function(removeEl){
3704         Ext.destroy(this.shim, Ext.get(this.proxy));
3705         this.dd.unreg();
3706         if(removeEl){
3707             this.el.remove();
3708         }
3709         this.purgeListeners();
3710     }
3711 });
3712
3713 /**
3714  * @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.
3715  */
3716 Ext.SplitBar.createProxy = function(dir){
3717     var proxy = new Ext.Element(document.createElement("div"));
3718     document.body.appendChild(proxy.dom);
3719     proxy.unselectable();
3720     var cls = 'x-splitbar-proxy';
3721     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
3722     return proxy.dom;
3723 };
3724
3725 /**
3726  * @class Ext.SplitBar.BasicLayoutAdapter
3727  * Default Adapter. It assumes the splitter and resizing element are not positioned
3728  * elements and only gets/sets the width of the element. Generally used for table based layouts.
3729  */
3730 Ext.SplitBar.BasicLayoutAdapter = function(){
3731 };
3732
3733 Ext.SplitBar.BasicLayoutAdapter.prototype = {
3734     // do nothing for now
3735     init : function(s){
3736
3737     },
3738     /**
3739      * Called before drag operations to get the current size of the resizing element.
3740      * @param {Ext.SplitBar} s The SplitBar using this adapter
3741      */
3742      getElementSize : function(s){
3743         if(s.orientation == Ext.SplitBar.HORIZONTAL){
3744             return s.resizingEl.getWidth();
3745         }else{
3746             return s.resizingEl.getHeight();
3747         }
3748     },
3749
3750     /**
3751      * Called after drag operations to set the size of the resizing element.
3752      * @param {Ext.SplitBar} s The SplitBar using this adapter
3753      * @param {Number} newSize The new size to set
3754      * @param {Function} onComplete A function to be invoked when resizing is complete
3755      */
3756     setElementSize : function(s, newSize, onComplete){
3757         if(s.orientation == Ext.SplitBar.HORIZONTAL){
3758             if(!s.animate){
3759                 s.resizingEl.setWidth(newSize);
3760                 if(onComplete){
3761                     onComplete(s, newSize);
3762                 }
3763             }else{
3764                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
3765             }
3766         }else{
3767
3768             if(!s.animate){
3769                 s.resizingEl.setHeight(newSize);
3770                 if(onComplete){
3771                     onComplete(s, newSize);
3772                 }
3773             }else{
3774                 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
3775             }
3776         }
3777     }
3778 };
3779
3780 /**
3781  *@class Ext.SplitBar.AbsoluteLayoutAdapter
3782  * @extends Ext.SplitBar.BasicLayoutAdapter
3783  * Adapter that  moves the splitter element to align with the resized sizing element.
3784  * Used with an absolute positioned SplitBar.
3785  * @param {Mixed} container The container that wraps around the absolute positioned content. If it's
3786  * document.body, make sure you assign an id to the body element.
3787  */
3788 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
3789     this.basic = new Ext.SplitBar.BasicLayoutAdapter();
3790     this.container = Ext.get(container);
3791 };
3792
3793 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
3794     init : function(s){
3795         this.basic.init(s);
3796     },
3797
3798     getElementSize : function(s){
3799         return this.basic.getElementSize(s);
3800     },
3801
3802     setElementSize : function(s, newSize, onComplete){
3803         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
3804     },
3805
3806     moveSplitter : function(s){
3807         var yes = Ext.SplitBar;
3808         switch(s.placement){
3809             case yes.LEFT:
3810                 s.el.setX(s.resizingEl.getRight());
3811                 break;
3812             case yes.RIGHT:
3813                 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
3814                 break;
3815             case yes.TOP:
3816                 s.el.setY(s.resizingEl.getBottom());
3817                 break;
3818             case yes.BOTTOM:
3819                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
3820                 break;
3821         }
3822     }
3823 };
3824
3825 /**
3826  * Orientation constant - Create a vertical SplitBar
3827  * @static
3828  * @type Number
3829  */
3830 Ext.SplitBar.VERTICAL = 1;
3831
3832 /**
3833  * Orientation constant - Create a horizontal SplitBar
3834  * @static
3835  * @type Number
3836  */
3837 Ext.SplitBar.HORIZONTAL = 2;
3838
3839 /**
3840  * Placement constant - The resizing element is to the left of the splitter element
3841  * @static
3842  * @type Number
3843  */
3844 Ext.SplitBar.LEFT = 1;
3845
3846 /**
3847  * Placement constant - The resizing element is to the right of the splitter element
3848  * @static
3849  * @type Number
3850  */
3851 Ext.SplitBar.RIGHT = 2;
3852
3853 /**
3854  * Placement constant - The resizing element is positioned above the splitter element
3855  * @static
3856  * @type Number
3857  */
3858 Ext.SplitBar.TOP = 3;
3859
3860 /**
3861  * Placement constant - The resizing element is positioned under splitter element
3862  * @static
3863  * @type Number
3864  */
3865 Ext.SplitBar.BOTTOM = 4;
3866 /**
3867  * @class Ext.Container
3868  * @extends Ext.BoxComponent
3869  * <p>Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the
3870  * basic behavior of containing items, namely adding, inserting and removing items.</p>
3871  *
3872  * <p>The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}.
3873  * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight
3874  * Container to be encapsulated by an HTML element to your specifications by using the
3875  * <code><b>{@link Ext.Component#autoEl autoEl}</b></code> config option. This is a useful technique when creating
3876  * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels}
3877  * for example.</p>
3878  *
3879  * <p>The code below illustrates both how to explicitly create a Container, and how to implicitly
3880  * create one using the <b><code>'container'</code></b> xtype:<pre><code>
3881 // explicitly create a Container
3882 var embeddedColumns = new Ext.Container({
3883     autoEl: 'div',  // This is the default
3884     layout: 'column',
3885     defaults: {
3886         // implicitly create Container by specifying xtype
3887         xtype: 'container',
3888         autoEl: 'div', // This is the default.
3889         layout: 'form',
3890         columnWidth: 0.5,
3891         style: {
3892             padding: '10px'
3893         }
3894     },
3895 //  The two items below will be Ext.Containers, each encapsulated by a &lt;DIV> element.
3896     items: [{
3897         items: {
3898             xtype: 'datefield',
3899             name: 'startDate',
3900             fieldLabel: 'Start date'
3901         }
3902     }, {
3903         items: {
3904             xtype: 'datefield',
3905             name: 'endDate',
3906             fieldLabel: 'End date'
3907         }
3908     }]
3909 });</code></pre></p>
3910  *
3911  * <p><u><b>Layout</b></u></p>
3912  * <p>Container classes delegate the rendering of child Components to a layout
3913  * manager class which must be configured into the Container using the
3914  * <code><b>{@link #layout}</b></code> configuration property.</p>
3915  * <p>When either specifying child <code>{@link #items}</code> of a Container,
3916  * or dynamically {@link #add adding} Components to a Container, remember to
3917  * consider how you wish the Container to arrange those child elements, and
3918  * whether those child elements need to be sized using one of Ext's built-in
3919  * <b><code>{@link #layout}</code></b> schemes. By default, Containers use the
3920  * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only
3921  * renders child components, appending them one after the other inside the
3922  * Container, and <b>does not apply any sizing</b> at all.</p>
3923  * <p>A common mistake is when a developer neglects to specify a
3924  * <b><code>{@link #layout}</code></b> (e.g. widgets like GridPanels or
3925  * TreePanels are added to Containers for which no <code><b>{@link #layout}</b></code>
3926  * has been specified). If a Container is left to use the default
3927  * {@link Ext.layout.ContainerLayout ContainerLayout} scheme, none of its
3928  * child components will be resized, or changed in any way when the Container
3929  * is resized.</p>
3930  * <p>Certain layout managers allow dynamic addition of child components.
3931  * Those that do include {@link Ext.layout.CardLayout},
3932  * {@link Ext.layout.AnchorLayout}, {@link Ext.layout.FormLayout}, and
3933  * {@link Ext.layout.TableLayout}. For example:<pre><code>
3934 //  Create the GridPanel.
3935 var myNewGrid = new Ext.grid.GridPanel({
3936     store: myStore,
3937     columns: myColumnModel,
3938     title: 'Results', // the title becomes the title of the tab
3939 });
3940
3941 myTabPanel.add(myNewGrid); // {@link Ext.TabPanel} implicitly uses {@link Ext.layout.CardLayout CardLayout}
3942 myTabPanel.{@link Ext.TabPanel#setActiveTab setActiveTab}(myNewGrid);
3943  * </code></pre></p>
3944  * <p>The example above adds a newly created GridPanel to a TabPanel. Note that
3945  * a TabPanel uses {@link Ext.layout.CardLayout} as its layout manager which
3946  * means all its child items are sized to {@link Ext.layout.FitLayout fit}
3947  * exactly into its client area.
3948  * <p><b><u>Overnesting is a common problem</u></b>.
3949  * An example of overnesting occurs when a GridPanel is added to a TabPanel
3950  * by wrapping the GridPanel <i>inside</i> a wrapping Panel (that has no
3951  * <code><b>{@link #layout}</b></code> specified) and then add that wrapping Panel
3952  * to the TabPanel. The point to realize is that a GridPanel <b>is</b> a
3953  * Component which can be added directly to a Container. If the wrapping Panel
3954  * has no <code><b>{@link #layout}</b></code> configuration, then the overnested
3955  * GridPanel will not be sized as expected.<p>
3956  *
3957  * <p><u><b>Adding via remote configuration</b></u></p>
3958  *
3959  * <p>A server side script can be used to add Components which are generated dynamically on the server.
3960  * An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server
3961  * based on certain parameters:
3962  * </p><pre><code>
3963 // execute an Ajax request to invoke server side script:
3964 Ext.Ajax.request({
3965     url: 'gen-invoice-grid.php',
3966     // send additional parameters to instruct server script
3967     params: {
3968         startDate: Ext.getCmp('start-date').getValue(),
3969         endDate: Ext.getCmp('end-date').getValue()
3970     },
3971     // process the response object to add it to the TabPanel:
3972     success: function(xhr) {
3973         var newComponent = eval(xhr.responseText); // see discussion below
3974         myTabPanel.add(newComponent); // add the component to the TabPanel
3975         myTabPanel.setActiveTab(newComponent);
3976     },
3977     failure: function() {
3978         Ext.Msg.alert("Grid create failed", "Server communication failure");
3979     }
3980 });
3981 </code></pre>
3982  * <p>The server script needs to return an executable Javascript statement which, when processed
3983  * using <code>eval()</code>, will return either a config object with an {@link Ext.Component#xtype xtype},
3984  * or an instantiated Component. The server might return this for example:</p><pre><code>
3985 (function() {
3986     function formatDate(value){
3987         return value ? value.dateFormat('M d, Y') : '';
3988     };
3989
3990     var store = new Ext.data.Store({
3991         url: 'get-invoice-data.php',
3992         baseParams: {
3993             startDate: '01/01/2008',
3994             endDate: '01/31/2008'
3995         },
3996         reader: new Ext.data.JsonReader({
3997             record: 'transaction',
3998             idProperty: 'id',
3999             totalRecords: 'total'
4000         }, [
4001            'customer',
4002            'invNo',
4003            {name: 'date', type: 'date', dateFormat: 'm/d/Y'},
4004            {name: 'value', type: 'float'}
4005         ])
4006     });
4007
4008     var grid = new Ext.grid.GridPanel({
4009         title: 'Invoice Report',
4010         bbar: new Ext.PagingToolbar(store),
4011         store: store,
4012         columns: [
4013             {header: "Customer", width: 250, dataIndex: 'customer', sortable: true},
4014             {header: "Invoice Number", width: 120, dataIndex: 'invNo', sortable: true},
4015             {header: "Invoice Date", width: 100, dataIndex: 'date', renderer: formatDate, sortable: true},
4016             {header: "Value", width: 120, dataIndex: 'value', renderer: 'usMoney', sortable: true}
4017         ],
4018     });
4019     store.load();
4020     return grid;  // return instantiated component
4021 })();
4022 </code></pre>
4023  * <p>When the above code fragment is passed through the <code>eval</code> function in the success handler
4024  * of the Ajax request, the code is executed by the Javascript processor, and the anonymous function
4025  * runs, and returns the instantiated grid component.</p>
4026  * <p>Note: since the code above is <i>generated</i> by a server script, the <code>baseParams</code> for
4027  * the Store, the metadata to allow generation of the Record layout, and the ColumnModel
4028  * can all be generated into the code since these are all known on the server.</p>
4029  *
4030  * @xtype container
4031  */
4032 Ext.Container = Ext.extend(Ext.BoxComponent, {
4033     /**
4034      * @cfg {Boolean} monitorResize
4035      * True to automatically monitor window resize events to handle anything that is sensitive to the current size
4036      * of the viewport.  This value is typically managed by the chosen <code>{@link #layout}</code> and should not need
4037      * to be set manually.
4038      */
4039     /**
4040      * @cfg {String/Object} layout
4041      * <p><b>*Important</b>: In order for child items to be correctly sized and
4042      * positioned, typically a layout manager <b>must</b> be specified through
4043      * the <code>layout</code> configuration option.</p>
4044      * <br><p>The sizing and positioning of child {@link items} is the responsibility of
4045      * the Container's layout manager which creates and manages the type of layout
4046      * you have in mind.  For example:</p><pre><code>
4047 new Ext.Window({
4048     width:300, height: 300,
4049     layout: 'fit', // explicitly set layout manager: override the default (layout:'auto')
4050     items: [{
4051         title: 'Panel inside a Window'
4052     }]
4053 }).show();
4054      * </code></pre>
4055      * <p>If the {@link #layout} configuration is not explicitly specified for
4056      * a general purpose container (e.g. Container or Panel) the
4057      * {@link Ext.layout.ContainerLayout default layout manager} will be used
4058      * which does nothing but render child components sequentially into the
4059      * Container (no sizing or positioning will be performed in this situation).
4060      * Some container classes implicitly specify a default layout
4061      * (e.g. FormPanel specifies <code>layout:'form'</code>). Other specific
4062      * purpose classes internally specify/manage their internal layout (e.g.
4063      * GridPanel, TabPanel, TreePanel, Toolbar, Menu, etc.).</p>
4064      * <br><p><b><code>layout</code></b> may be specified as either as an Object or
4065      * as a String:</p><div><ul class="mdetail-params">
4066      *
4067      * <li><u>Specify as an Object</u></li>
4068      * <div><ul class="mdetail-params">
4069      * <li>Example usage:</li>
4070 <pre><code>
4071 layout: {
4072     type: 'vbox',
4073     padding: '5',
4074     align: 'left'
4075 }
4076 </code></pre>
4077      *
4078      * <li><code><b>type</b></code></li>
4079      * <br/><p>The layout type to be used for this container.  If not specified,
4080      * a default {@link Ext.layout.ContainerLayout} will be created and used.</p>
4081      * <br/><p>Valid layout <code>type</code> values are:</p>
4082      * <div class="sub-desc"><ul class="mdetail-params">
4083      * <li><code><b>{@link Ext.layout.AbsoluteLayout absolute}</b></code></li>
4084      * <li><code><b>{@link Ext.layout.AccordionLayout accordion}</b></code></li>
4085      * <li><code><b>{@link Ext.layout.AnchorLayout anchor}</b></code></li>
4086      * <li><code><b>{@link Ext.layout.ContainerLayout auto}</b></code> &nbsp;&nbsp;&nbsp; <b>Default</b></li>
4087      * <li><code><b>{@link Ext.layout.BorderLayout border}</b></code></li>
4088      * <li><code><b>{@link Ext.layout.CardLayout card}</b></code></li>
4089      * <li><code><b>{@link Ext.layout.ColumnLayout column}</b></code></li>
4090      * <li><code><b>{@link Ext.layout.FitLayout fit}</b></code></li>
4091      * <li><code><b>{@link Ext.layout.FormLayout form}</b></code></li>
4092      * <li><code><b>{@link Ext.layout.HBoxLayout hbox}</b></code></li>
4093      * <li><code><b>{@link Ext.layout.MenuLayout menu}</b></code></li>
4094      * <li><code><b>{@link Ext.layout.TableLayout table}</b></code></li>
4095      * <li><code><b>{@link Ext.layout.ToolbarLayout toolbar}</b></code></li>
4096      * <li><code><b>{@link Ext.layout.VBoxLayout vbox}</b></code></li>
4097      * </ul></div>
4098      *
4099      * <li>Layout specific configuration properties</li>
4100      * <br/><p>Additional layout specific configuration properties may also be
4101      * specified. For complete details regarding the valid config options for
4102      * each layout type, see the layout class corresponding to the <code>type</code>
4103      * specified.</p>
4104      *
4105      * </ul></div>
4106      *
4107      * <li><u>Specify as a String</u></li>
4108      * <div><ul class="mdetail-params">
4109      * <li>Example usage:</li>
4110 <pre><code>
4111 layout: 'vbox',
4112 layoutConfig: {
4113     padding: '5',
4114     align: 'left'
4115 }
4116 </code></pre>
4117      * <li><code><b>layout</b></code></li>
4118      * <br/><p>The layout <code>type</code> to be used for this container (see list
4119      * of valid layout type values above).</p><br/>
4120      * <li><code><b>{@link #layoutConfig}</b></code></li>
4121      * <br/><p>Additional layout specific configuration properties. For complete
4122      * details regarding the valid config options for each layout type, see the
4123      * layout class corresponding to the <code>layout</code> specified.</p>
4124      * </ul></div></ul></div>
4125      */
4126     /**
4127      * @cfg {Object} layoutConfig
4128      * This is a config object containing properties specific to the chosen
4129      * <b><code>{@link #layout}</code></b> if <b><code>{@link #layout}</code></b>
4130      * has been specified as a <i>string</i>.</p>
4131      */
4132     /**
4133      * @cfg {Boolean/Number} bufferResize
4134      * When set to true (50 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer
4135      * the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers
4136      * with a large quantity of sub-components for which frequent layout calls would be expensive. Defaults to <code>50</code>.
4137      */
4138     bufferResize: 50,
4139
4140     /**
4141      * @cfg {String/Number} activeItem
4142      * A string component id or the numeric index of the component that should be initially activated within the
4143      * container's layout on render.  For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first
4144      * item in the container's collection).  activeItem only applies to layout styles that can display
4145      * items one at a time (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout} and
4146      * {@link Ext.layout.FitLayout}).  Related to {@link Ext.layout.ContainerLayout#activeItem}.
4147      */
4148     /**
4149      * @cfg {Object/Array} items
4150      * <pre><b>** IMPORTANT</b>: be sure to <b>{@link #layout specify a <code>layout</code>} if needed ! **</b></pre>
4151      * <p>A single item, or an array of child Components to be added to this container,
4152      * for example:</p>
4153      * <pre><code>
4154 // specifying a single item
4155 items: {...},
4156 layout: 'fit',    // specify a layout!
4157
4158 // specifying multiple items
4159 items: [{...}, {...}],
4160 layout: 'anchor', // specify a layout!
4161      * </code></pre>
4162      * <p>Each item may be:</p>
4163      * <div><ul class="mdetail-params">
4164      * <li>any type of object based on {@link Ext.Component}</li>
4165      * <li>a fully instanciated object or</li>
4166      * <li>an object literal that:</li>
4167      * <div><ul class="mdetail-params">
4168      * <li>has a specified <code>{@link Ext.Component#xtype xtype}</code></li>
4169      * <li>the {@link Ext.Component#xtype} specified is associated with the Component
4170      * desired and should be chosen from one of the available xtypes as listed
4171      * in {@link Ext.Component}.</li>
4172      * <li>If an <code>{@link Ext.Component#xtype xtype}</code> is not explicitly
4173      * specified, the {@link #defaultType} for that Container is used.</li>
4174      * <li>will be "lazily instanciated", avoiding the overhead of constructing a fully
4175      * instanciated Component object</li>
4176      * </ul></div></ul></div>
4177      * <p><b>Notes</b>:</p>
4178      * <div><ul class="mdetail-params">
4179      * <li>Ext uses lazy rendering. Child Components will only be rendered
4180      * should it become necessary. Items are automatically laid out when they are first
4181      * shown (no sizing is done while hidden), or in response to a {@link #doLayout} call.</li>
4182      * <li>Do not specify <code>{@link Ext.Panel#contentEl contentEl}</code>/
4183      * <code>{@link Ext.Panel#html html}</code> with <code>items</code>.</li>
4184      * </ul></div>
4185      */
4186     /**
4187      * @cfg {Object|Function} defaults
4188      * <p>This option is a means of applying default settings to all added items whether added through the {@link #items}
4189      * config or via the {@link #add} or {@link #insert} methods.</p>
4190      * <p>If an added item is a config object, and <b>not</b> an instantiated Component, then the default properties are
4191      * unconditionally applied. If the added item <b>is</b> an instantiated Component, then the default properties are
4192      * applied conditionally so as not to override existing properties in the item.</p>
4193      * <p>If the defaults option is specified as a function, then the function will be called using this Container as the
4194      * scope (<code>this</code> reference) and passing the added item as the first parameter. Any resulting object
4195      * from that call is then applied to the item as default properties.</p>
4196      * <p>For example, to automatically apply padding to the body of each of a set of
4197      * contained {@link Ext.Panel} items, you could pass: <code>defaults: {bodyStyle:'padding:15px'}</code>.</p>
4198      * <p>Usage:</p><pre><code>
4199 defaults: {               // defaults are applied to items, not the container
4200     autoScroll:true
4201 },
4202 items: [
4203     {
4204         xtype: 'panel',   // defaults <b>do not</b> have precedence over
4205         id: 'panel1',     // options in config objects, so the defaults
4206         autoScroll: false // will not be applied here, panel1 will be autoScroll:false
4207     },
4208     new Ext.Panel({       // defaults <b>do</b> have precedence over options
4209         id: 'panel2',     // options in components, so the defaults
4210         autoScroll: false // will be applied here, panel2 will be autoScroll:true.
4211     })
4212 ]
4213      * </code></pre>
4214      */
4215
4216
4217     /** @cfg {Boolean} autoDestroy
4218      * If true the container will automatically destroy any contained component that is removed from it, else
4219      * destruction must be handled manually (defaults to true).
4220      */
4221     autoDestroy : true,
4222
4223     /** @cfg {Boolean} forceLayout
4224      * If true the container will force a layout initially even if hidden or collapsed. This option
4225      * is useful for forcing forms to render in collapsed or hidden containers. (defaults to false).
4226      */
4227     forceLayout: false,
4228
4229     /** @cfg {Boolean} hideBorders
4230      * True to hide the borders of each contained component, false to defer to the component's existing
4231      * border settings (defaults to false).
4232      */
4233     /** @cfg {String} defaultType
4234      * <p>The default {@link Ext.Component xtype} of child Components to create in this Container when
4235      * a child item is specified as a raw configuration object, rather than as an instantiated Component.</p>
4236      * <p>Defaults to <code>'panel'</code>, except {@link Ext.menu.Menu} which defaults to <code>'menuitem'</code>,
4237      * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to <code>'button'</code>.</p>
4238      */
4239     defaultType : 'panel',
4240
4241     /** @cfg {String} resizeEvent
4242      * The event to listen to for resizing in layouts. Defaults to <code>'resize'</code>.
4243      */
4244     resizeEvent: 'resize',
4245
4246     /**
4247      * @cfg {Array} bubbleEvents
4248      * <p>An array of events that, when fired, should be bubbled to any parent container.
4249      * See {@link Ext.util.Observable#enableBubble}.
4250      * Defaults to <code>['add', 'remove']</code>.
4251      */
4252     bubbleEvents: ['add', 'remove'],
4253
4254     // private
4255     initComponent : function(){
4256         Ext.Container.superclass.initComponent.call(this);
4257
4258         this.addEvents(
4259             /**
4260              * @event afterlayout
4261              * Fires when the components in this container are arranged by the associated layout manager.
4262              * @param {Ext.Container} this
4263              * @param {ContainerLayout} layout The ContainerLayout implementation for this container
4264              */
4265             'afterlayout',
4266             /**
4267              * @event beforeadd
4268              * Fires before any {@link Ext.Component} is added or inserted into the container.
4269              * A handler can return false to cancel the add.
4270              * @param {Ext.Container} this
4271              * @param {Ext.Component} component The component being added
4272              * @param {Number} index The index at which the component will be added to the container's items collection
4273              */
4274             'beforeadd',
4275             /**
4276              * @event beforeremove
4277              * Fires before any {@link Ext.Component} is removed from the container.  A handler can return
4278              * false to cancel the remove.
4279              * @param {Ext.Container} this
4280              * @param {Ext.Component} component The component being removed
4281              */
4282             'beforeremove',
4283             /**
4284              * @event add
4285              * @bubbles
4286              * Fires after any {@link Ext.Component} is added or inserted into the container.
4287              * @param {Ext.Container} this
4288              * @param {Ext.Component} component The component that was added
4289              * @param {Number} index The index at which the component was added to the container's items collection
4290              */
4291             'add',
4292             /**
4293              * @event remove
4294              * @bubbles
4295              * Fires after any {@link Ext.Component} is removed from the container.
4296              * @param {Ext.Container} this
4297              * @param {Ext.Component} component The component that was removed
4298              */
4299             'remove'
4300         );
4301
4302         /**
4303          * The collection of components in this container as a {@link Ext.util.MixedCollection}
4304          * @type MixedCollection
4305          * @property items
4306          */
4307         var items = this.items;
4308         if(items){
4309             delete this.items;
4310             this.add(items);
4311         }
4312     },
4313
4314     // private
4315     initItems : function(){
4316         if(!this.items){
4317             this.items = new Ext.util.MixedCollection(false, this.getComponentId);
4318             this.getLayout(); // initialize the layout
4319         }
4320     },
4321
4322     // private
4323     setLayout : function(layout){
4324         if(this.layout && this.layout != layout){
4325             this.layout.setContainer(null);
4326         }
4327         this.layout = layout;
4328         this.initItems();
4329         layout.setContainer(this);
4330     },
4331
4332     afterRender: function(){
4333         // Render this Container, this should be done before setLayout is called which
4334         // will hook onResize
4335         Ext.Container.superclass.afterRender.call(this);
4336         if(!this.layout){
4337             this.layout = 'auto';
4338         }
4339         if(Ext.isObject(this.layout) && !this.layout.layout){
4340             this.layoutConfig = this.layout;
4341             this.layout = this.layoutConfig.type;
4342         }
4343         if(Ext.isString(this.layout)){
4344             this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
4345         }
4346         this.setLayout(this.layout);
4347
4348         // If a CardLayout, the active item set
4349         if(this.activeItem !== undefined){
4350             var item = this.activeItem;
4351             delete this.activeItem;
4352             this.layout.setActiveItem(item);
4353         }
4354
4355         // If we have no ownerCt, render and size all children
4356         if(!this.ownerCt){
4357             this.doLayout(false, true);
4358         }
4359
4360         // This is a manually configured flag set by users in conjunction with renderTo.
4361         // Not to be confused with the flag by the same name used in Layouts.
4362         if(this.monitorResize === true){
4363             Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
4364         }
4365     },
4366
4367     /**
4368      * <p>Returns the Element to be used to contain the child Components of this Container.</p>
4369      * <p>An implementation is provided which returns the Container's {@link #getEl Element}, but
4370      * if there is a more complex structure to a Container, this may be overridden to return
4371      * the element into which the {@link #layout layout} renders child Components.</p>
4372      * @return {Ext.Element} The Element to render child Components into.
4373      */
4374     getLayoutTarget : function(){
4375         return this.el;
4376     },
4377
4378     // private - used as the key lookup function for the items collection
4379     getComponentId : function(comp){
4380         return comp.getItemId();
4381     },
4382
4383     /**
4384      * <p>Adds {@link Ext.Component Component}(s) to this Container.</p>
4385      * <br><p><b>Description</b></u> :
4386      * <div><ul class="mdetail-params">
4387      * <li>Fires the {@link #beforeadd} event before adding</li>
4388      * <li>The Container's {@link #defaults default config values} will be applied
4389      * accordingly (see <code>{@link #defaults}</code> for details).</li>
4390      * <li>Fires the {@link #add} event after the component has been added.</li>
4391      * </ul></div>
4392      * <br><p><b>Notes</b></u> :
4393      * <div><ul class="mdetail-params">
4394      * <li>If the Container is <i>already rendered</i> when <code>add</code>
4395      * is called, you may need to call {@link #doLayout} to refresh the view which causes
4396      * any unrendered child Components to be rendered. This is required so that you can
4397      * <code>add</code> multiple child components if needed while only refreshing the layout
4398      * once. For example:<pre><code>
4399 var tb = new {@link Ext.Toolbar}();
4400 tb.render(document.body);  // toolbar is rendered
4401 tb.add({text:'Button 1'}); // add multiple items ({@link #defaultType} for {@link Ext.Toolbar Toolbar} is 'button')
4402 tb.add({text:'Button 2'});
4403 tb.{@link #doLayout}();             // refresh the layout
4404      * </code></pre></li>
4405      * <li><i>Warning:</i> Containers directly managed by the BorderLayout layout manager
4406      * may not be removed or added.  See the Notes for {@link Ext.layout.BorderLayout BorderLayout}
4407      * for more details.</li>
4408      * </ul></div>
4409      * @param {...Object/Array} component
4410      * <p>Either one or more Components to add or an Array of Components to add.  See
4411      * <code>{@link #items}</code> for additional information.</p>
4412      * @return {Ext.Component/Array} The Components that were added.
4413      */
4414     add : function(comp){
4415         this.initItems();
4416         var args = arguments.length > 1;
4417         if(args || Ext.isArray(comp)){
4418             var result = [];
4419             Ext.each(args ? arguments : comp, function(c){
4420                 result.push(this.add(c));
4421             }, this);
4422             return result;
4423         }
4424         var c = this.lookupComponent(this.applyDefaults(comp));
4425         var index = this.items.length;
4426         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
4427             this.items.add(c);
4428             // *onAdded
4429             c.onAdded(this, index);
4430             this.onAdd(c);
4431             this.fireEvent('add', this, c, index);
4432         }
4433         return c;
4434     },
4435
4436     onAdd : function(c){
4437         // Empty template method
4438     },
4439
4440     // private
4441     onAdded : function(container, pos) {
4442         //overridden here so we can cascade down, not worth creating a template method.
4443         this.ownerCt = container;
4444         this.initRef();
4445         //initialize references for child items
4446         this.cascade(function(c){
4447             c.initRef();
4448         });
4449         this.fireEvent('added', this, container, pos);
4450     },
4451
4452     /**
4453      * Inserts a Component into this Container at a specified index. Fires the
4454      * {@link #beforeadd} event before inserting, then fires the {@link #add} event after the
4455      * Component has been inserted.
4456      * @param {Number} index The index at which the Component will be inserted
4457      * into the Container's items collection
4458      * @param {Ext.Component} component The child Component to insert.<br><br>
4459      * Ext uses lazy rendering, and will only render the inserted Component should
4460      * it become necessary.<br><br>
4461      * A Component config object may be passed in order to avoid the overhead of
4462      * constructing a real Component object if lazy rendering might mean that the
4463      * inserted Component will not be rendered immediately. To take advantage of
4464      * this 'lazy instantiation', set the {@link Ext.Component#xtype} config
4465      * property to the registered type of the Component wanted.<br><br>
4466      * For a list of all available xtypes, see {@link Ext.Component}.
4467      * @return {Ext.Component} component The Component (or config object) that was
4468      * inserted with the Container's default config values applied.
4469      */
4470     insert : function(index, comp){
4471         this.initItems();
4472         var a = arguments, len = a.length;
4473         if(len > 2){
4474             var result = [];
4475             for(var i = len-1; i >= 1; --i) {
4476                 result.push(this.insert(index, a[i]));
4477             }
4478             return result;
4479         }
4480         var c = this.lookupComponent(this.applyDefaults(comp));
4481         index = Math.min(index, this.items.length);
4482         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
4483             if(c.ownerCt == this){
4484                 this.items.remove(c);
4485             }
4486             this.items.insert(index, c);
4487             c.onAdded(this, index);
4488             this.onAdd(c);
4489             this.fireEvent('add', this, c, index);
4490         }
4491         return c;
4492     },
4493
4494     // private
4495     applyDefaults : function(c){
4496         var d = this.defaults;
4497         if(d){
4498             if(Ext.isFunction(d)){
4499                 d = d.call(this, c);
4500             }
4501             if(Ext.isString(c)){
4502                 c = Ext.ComponentMgr.get(c);
4503                 Ext.apply(c, d);
4504             }else if(!c.events){
4505                 Ext.applyIf(c, d);
4506             }else{
4507                 Ext.apply(c, d);
4508             }
4509         }
4510         return c;
4511     },
4512
4513     // private
4514     onBeforeAdd : function(item){
4515         if(item.ownerCt){
4516             item.ownerCt.remove(item, false);
4517         }
4518         if(this.hideBorders === true){
4519             item.border = (item.border === true);
4520         }
4521     },
4522
4523     /**
4524      * Removes a component from this container.  Fires the {@link #beforeremove} event before removing, then fires
4525      * the {@link #remove} event after the component has been removed.
4526      * @param {Component/String} component The component reference or id to remove.
4527      * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
4528      * Defaults to the value of this Container's {@link #autoDestroy} config.
4529      * @return {Ext.Component} component The Component that was removed.
4530      */
4531     remove : function(comp, autoDestroy){
4532         this.initItems();
4533         var c = this.getComponent(comp);
4534         if(c && this.fireEvent('beforeremove', this, c) !== false){
4535             this.doRemove(c, autoDestroy);
4536             this.fireEvent('remove', this, c);
4537         }
4538         return c;
4539     },
4540
4541     onRemove: function(c){
4542         // Empty template method
4543     },
4544
4545     // private
4546     doRemove: function(c, autoDestroy){
4547         var l = this.layout,
4548             hasLayout = l && this.rendered;
4549
4550         if(hasLayout){
4551             l.onRemove(c);
4552         }
4553         this.items.remove(c);
4554         c.onRemoved();
4555         this.onRemove(c);
4556         if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
4557             c.destroy();
4558         }
4559         if(hasLayout){
4560             l.afterRemove(c);
4561         }
4562     },
4563
4564     /**
4565      * Removes all components from this container.
4566      * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
4567      * Defaults to the value of this Container's {@link #autoDestroy} config.
4568      * @return {Array} Array of the destroyed components
4569      */
4570     removeAll: function(autoDestroy){
4571         this.initItems();
4572         var item, rem = [], items = [];
4573         this.items.each(function(i){
4574             rem.push(i);
4575         });
4576         for (var i = 0, len = rem.length; i < len; ++i){
4577             item = rem[i];
4578             this.remove(item, autoDestroy);
4579             if(item.ownerCt !== this){
4580                 items.push(item);
4581             }
4582         }
4583         return items;
4584     },
4585
4586     /**
4587      * Examines this container's <code>{@link #items}</code> <b>property</b>
4588      * and gets a direct child component of this container.
4589      * @param {String/Number} comp This parameter may be any of the following:
4590      * <div><ul class="mdetail-params">
4591      * <li>a <b><code>String</code></b> : representing the <code>{@link Ext.Component#itemId itemId}</code>
4592      * or <code>{@link Ext.Component#id id}</code> of the child component </li>
4593      * <li>a <b><code>Number</code></b> : representing the position of the child component
4594      * within the <code>{@link #items}</code> <b>property</b></li>
4595      * </ul></div>
4596      * <p>For additional information see {@link Ext.util.MixedCollection#get}.
4597      * @return Ext.Component The component (if found).
4598      */
4599     getComponent : function(comp){
4600         if(Ext.isObject(comp)){
4601             comp = comp.getItemId();
4602         }
4603         return this.items.get(comp);
4604     },
4605
4606     // private
4607     lookupComponent : function(comp){
4608         if(Ext.isString(comp)){
4609             return Ext.ComponentMgr.get(comp);
4610         }else if(!comp.events){
4611             return this.createComponent(comp);
4612         }
4613         return comp;
4614     },
4615
4616     // private
4617     createComponent : function(config, defaultType){
4618         if (config.render) {
4619             return config;
4620         }
4621         // add in ownerCt at creation time but then immediately
4622         // remove so that onBeforeAdd can handle it
4623         var c = Ext.create(Ext.apply({
4624             ownerCt: this
4625         }, config), defaultType || this.defaultType);
4626         delete c.initialConfig.ownerCt;
4627         delete c.ownerCt;
4628         return c;
4629     },
4630
4631     /**
4632      * @private
4633      * We can only lay out if there is a view area in which to layout.
4634      * display:none on the layout target, *or any of its parent elements* will mean it has no view area.
4635      */
4636     canLayout : function() {
4637         var el = this.getVisibilityEl();
4638         return el && el.dom && !el.isStyle("display", "none");
4639     },
4640
4641     /**
4642      * Force this container's layout to be recalculated. A call to this function is required after adding a new component
4643      * to an already rendered container, or possibly after changing sizing/position properties of child components.
4644      * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto
4645      * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer)
4646      * @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden.
4647      * @return {Ext.Container} this
4648      */
4649
4650     doLayout : function(shallow, force){
4651         var rendered = this.rendered,
4652             forceLayout = force || this.forceLayout;
4653
4654         if(this.collapsed || !this.canLayout()){
4655             this.deferLayout = this.deferLayout || !shallow;
4656             if(!forceLayout){
4657                 return;
4658             }
4659             shallow = shallow && !this.deferLayout;
4660         } else {
4661             delete this.deferLayout;
4662         }
4663         if(rendered && this.layout){
4664             this.layout.layout();
4665         }
4666         if(shallow !== true && this.items){
4667             var cs = this.items.items;
4668             for(var i = 0, len = cs.length; i < len; i++){
4669                 var c = cs[i];
4670                 if(c.doLayout){
4671                     c.doLayout(false, forceLayout);
4672                 }
4673             }
4674         }
4675         if(rendered){
4676             this.onLayout(shallow, forceLayout);
4677         }
4678         // Initial layout completed
4679         this.hasLayout = true;
4680         delete this.forceLayout;
4681     },
4682
4683     onLayout : Ext.emptyFn,
4684
4685     // private
4686     shouldBufferLayout: function(){
4687         /*
4688          * Returns true if the container should buffer a layout.
4689          * This is true only if the container has previously been laid out
4690          * and has a parent container that is pending a layout.
4691          */
4692         var hl = this.hasLayout;
4693         if(this.ownerCt){
4694             // Only ever buffer if we've laid out the first time and we have one pending.
4695             return hl ? !this.hasLayoutPending() : false;
4696         }
4697         // Never buffer initial layout
4698         return hl;
4699     },
4700
4701     // private
4702     hasLayoutPending: function(){
4703         // Traverse hierarchy to see if any parent container has a pending layout.
4704         var pending = false;
4705         this.ownerCt.bubble(function(c){
4706             if(c.layoutPending){
4707                 pending = true;
4708                 return false;
4709             }
4710         });
4711         return pending;
4712     },
4713
4714     onShow : function(){
4715         // removes css classes that were added to hide
4716         Ext.Container.superclass.onShow.call(this);
4717         // If we were sized during the time we were hidden, layout.
4718         if(Ext.isDefined(this.deferLayout)){
4719             delete this.deferLayout;
4720             this.doLayout(true);
4721         }
4722     },
4723
4724     /**
4725      * Returns the layout currently in use by the container.  If the container does not currently have a layout
4726      * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout.
4727      * @return {ContainerLayout} layout The container's layout
4728      */
4729     getLayout : function(){
4730         if(!this.layout){
4731             var layout = new Ext.layout.AutoLayout(this.layoutConfig);
4732             this.setLayout(layout);
4733         }
4734         return this.layout;
4735     },
4736
4737     // private
4738     beforeDestroy : function(){
4739         var c;
4740         if(this.items){
4741             while(c = this.items.first()){
4742                 this.doRemove(c, true);
4743             }
4744         }
4745         if(this.monitorResize){
4746             Ext.EventManager.removeResizeListener(this.doLayout, this);
4747         }
4748         Ext.destroy(this.layout);
4749         Ext.Container.superclass.beforeDestroy.call(this);
4750     },
4751
4752     /**
4753      * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of
4754      * function call will be the scope provided or the current component. The arguments to the function
4755      * will be the args provided or the current component. If the function returns false at any point,
4756      * the bubble is stopped.
4757      * @param {Function} fn The function to call
4758      * @param {Object} scope (optional) The scope of the function (defaults to current node)
4759      * @param {Array} args (optional) The args to call the function with (default to passing the current component)
4760      * @return {Ext.Container} this
4761      */
4762     bubble : function(fn, scope, args){
4763         var p = this;
4764         while(p){
4765             if(fn.apply(scope || p, args || [p]) === false){
4766                 break;
4767             }
4768             p = p.ownerCt;
4769         }
4770         return this;
4771     },
4772
4773     /**
4774      * Cascades down the component/container heirarchy from this component (called first), calling the specified function with
4775      * each component. The scope (<i>this</i>) of
4776      * function call will be the scope provided or the current component. The arguments to the function
4777      * will be the args provided or the current component. If the function returns false at any point,
4778      * the cascade is stopped on that branch.
4779      * @param {Function} fn The function to call
4780      * @param {Object} scope (optional) The scope of the function (defaults to current component)
4781      * @param {Array} args (optional) The args to call the function with (defaults to passing the current component)
4782      * @return {Ext.Container} this
4783      */
4784     cascade : function(fn, scope, args){
4785         if(fn.apply(scope || this, args || [this]) !== false){
4786             if(this.items){
4787                 var cs = this.items.items;
4788                 for(var i = 0, len = cs.length; i < len; i++){
4789                     if(cs[i].cascade){
4790                         cs[i].cascade(fn, scope, args);
4791                     }else{
4792                         fn.apply(scope || cs[i], args || [cs[i]]);
4793                     }
4794                 }
4795             }
4796         }
4797         return this;
4798     },
4799
4800     /**
4801      * Find a component under this container at any level by id
4802      * @param {String} id
4803      * @return Ext.Component
4804      */
4805     findById : function(id){
4806         var m, ct = this;
4807         this.cascade(function(c){
4808             if(ct != c && c.id === id){
4809                 m = c;
4810                 return false;
4811             }
4812         });
4813         return m || null;
4814     },
4815
4816     /**
4817      * Find a component under this container at any level by xtype or class
4818      * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
4819      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
4820      * the default), or true to check whether this Component is directly of the specified xtype.
4821      * @return {Array} Array of Ext.Components
4822      */
4823     findByType : function(xtype, shallow){
4824         return this.findBy(function(c){
4825             return c.isXType(xtype, shallow);
4826         });
4827     },
4828
4829     /**
4830      * Find a component under this container at any level by property
4831      * @param {String} prop
4832      * @param {String} value
4833      * @return {Array} Array of Ext.Components
4834      */
4835     find : function(prop, value){
4836         return this.findBy(function(c){
4837             return c[prop] === value;
4838         });
4839     },
4840
4841     /**
4842      * Find a component under this container at any level by a custom function. If the passed function returns
4843      * true, the component will be included in the results. The passed function is called with the arguments (component, this container).
4844      * @param {Function} fn The function to call
4845      * @param {Object} scope (optional)
4846      * @return {Array} Array of Ext.Components
4847      */
4848     findBy : function(fn, scope){
4849         var m = [], ct = this;
4850         this.cascade(function(c){
4851             if(ct != c && fn.call(scope || c, c, ct) === true){
4852                 m.push(c);
4853             }
4854         });
4855         return m;
4856     },
4857
4858     /**
4859      * Get a component contained by this container (alias for items.get(key))
4860      * @param {String/Number} key The index or id of the component
4861      * @return {Ext.Component} Ext.Component
4862      */
4863     get : function(key){
4864         return this.items.get(key);
4865     }
4866 });
4867
4868 Ext.Container.LAYOUTS = {};
4869 Ext.reg('container', Ext.Container);
4870 /**
4871  * @class Ext.layout.ContainerLayout
4872  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
4873  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
4874  */
4875 Ext.layout.ContainerLayout = Ext.extend(Object, {
4876     /**
4877      * @cfg {String} extraCls
4878      * <p>An optional extra CSS class that will be added to the container. This can be useful for adding
4879      * customized styles to the container or any of its children using standard CSS rules. See
4880      * {@link Ext.Component}.{@link Ext.Component#ctCls ctCls} also.</p>
4881      * <p><b>Note</b>: <tt>extraCls</tt> defaults to <tt>''</tt> except for the following classes
4882      * which assign a value by default:
4883      * <div class="mdetail-params"><ul>
4884      * <li>{@link Ext.layout.AbsoluteLayout Absolute Layout} : <tt>'x-abs-layout-item'</tt></li>
4885      * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-item'</tt></li>
4886      * <li>{@link Ext.layout.ColumnLayout Column Layout} : <tt>'x-column'</tt></li>
4887      * </ul></div>
4888      * To configure the above Classes with an extra CSS class append to the default.  For example,
4889      * for ColumnLayout:<pre><code>
4890      * extraCls: 'x-column custom-class'
4891      * </code></pre>
4892      * </p>
4893      */
4894     /**
4895      * @cfg {Boolean} renderHidden
4896      * True to hide each contained item on render (defaults to false).
4897      */
4898
4899     /**
4900      * A reference to the {@link Ext.Component} that is active.  For example, <pre><code>
4901      * if(myPanel.layout.activeItem.id == 'item-1') { ... }
4902      * </code></pre>
4903      * <tt>activeItem</tt> only applies to layout styles that can display items one at a time
4904      * (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout}
4905      * and {@link Ext.layout.FitLayout}).  Read-only.  Related to {@link Ext.Container#activeItem}.
4906      * @type {Ext.Component}
4907      * @property activeItem
4908      */
4909
4910     // private
4911     monitorResize:false,
4912     // private
4913     activeItem : null,
4914
4915     constructor : function(config){
4916         this.id = Ext.id(null, 'ext-layout-');
4917         Ext.apply(this, config);
4918     },
4919
4920     type: 'container',
4921
4922     /* Workaround for how IE measures autoWidth elements.  It prefers bottom-up measurements
4923       whereas other browser prefer top-down.  We will hide all target child elements before we measure and
4924       put them back to get an accurate measurement.
4925     */
4926     IEMeasureHack : function(target, viewFlag) {
4927         var tChildren = target.dom.childNodes, tLen = tChildren.length, c, d = [], e, i, ret;
4928         for (i = 0 ; i < tLen ; i++) {
4929             c = tChildren[i];
4930             e = Ext.get(c);
4931             if (e) {
4932                 d[i] = e.getStyle('display');
4933                 e.setStyle({display: 'none'});
4934             }
4935         }
4936         ret = target ? target.getViewSize(viewFlag) : {};
4937         for (i = 0 ; i < tLen ; i++) {
4938             c = tChildren[i];
4939             e = Ext.get(c);
4940             if (e) {
4941                 e.setStyle({display: d[i]});
4942             }
4943         }
4944         return ret;
4945     },
4946
4947     // Placeholder for the derived layouts
4948     getLayoutTargetSize : Ext.EmptyFn,
4949
4950     // private
4951     layout : function(){
4952         var ct = this.container, target = ct.getLayoutTarget();
4953         if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
4954             target.addClass(this.targetCls);
4955         }
4956         this.onLayout(ct, target);
4957         ct.fireEvent('afterlayout', ct, this);
4958     },
4959
4960     // private
4961     onLayout : function(ct, target){
4962         this.renderAll(ct, target);
4963     },
4964
4965     // private
4966     isValidParent : function(c, target){
4967         return target && c.getPositionEl().dom.parentNode == (target.dom || target);
4968     },
4969
4970     // private
4971     renderAll : function(ct, target){
4972         var items = ct.items.items, i, c, len = items.length;
4973         for(i = 0; i < len; i++) {
4974             c = items[i];
4975             if(c && (!c.rendered || !this.isValidParent(c, target))){
4976                 this.renderItem(c, i, target);
4977             }
4978         }
4979     },
4980
4981     /**
4982      * @private
4983      * Renders the given Component into the target Element. If the Component is already rendered,
4984      * it is moved to the provided target instead.
4985      * @param {Ext.Component} c The Component to render
4986      * @param {Number} position The position within the target to render the item to
4987      * @param {Ext.Element} target The target Element
4988      */
4989     renderItem : function(c, position, target){
4990         if (c) {
4991             if (!c.rendered) {
4992                 c.render(target, position);
4993                 this.configureItem(c, position);
4994             } else if (!this.isValidParent(c, target)) {
4995                 if (Ext.isNumber(position)) {
4996                     position = target.dom.childNodes[position];
4997                 }
4998                 
4999                 target.dom.insertBefore(c.getPositionEl().dom, position || null);
5000                 c.container = target;
5001                 this.configureItem(c, position);
5002             }
5003         }
5004     },
5005
5006     // private.
5007     // Get all rendered items to lay out.
5008     getRenderedItems: function(ct){
5009         var t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = [];
5010         for (i = 0; i < len; i++) {
5011             if((c = cti[i]).rendered && this.isValidParent(c, t)){
5012                 items.push(c);
5013             }
5014         };
5015         return items;
5016     },
5017
5018     /**
5019      * @private
5020      * Applies extraCls and hides the item if renderHidden is true
5021      */
5022     configureItem: function(c, position){
5023         if (this.extraCls) {
5024             var t = c.getPositionEl ? c.getPositionEl() : c;
5025             t.addClass(this.extraCls);
5026         }
5027         
5028         // If we are forcing a layout, do so *before* we hide so elements have height/width
5029         if (c.doLayout && this.forceLayout) {
5030             c.doLayout();
5031         }
5032         if (this.renderHidden && c != this.activeItem) {
5033             c.hide();
5034         }
5035     },
5036
5037     onRemove: function(c){
5038         if(this.activeItem == c){
5039             delete this.activeItem;
5040         }
5041         if(c.rendered && this.extraCls){
5042             var t = c.getPositionEl ? c.getPositionEl() : c;
5043             t.removeClass(this.extraCls);
5044         }
5045     },
5046
5047     afterRemove: function(c){
5048         if(c.removeRestore){
5049             c.removeMode = 'container';
5050             delete c.removeRestore;
5051         }
5052     },
5053
5054     // private
5055     onResize: function(){
5056         var ct = this.container,
5057             b;
5058         if(ct.collapsed){
5059             return;
5060         }
5061         if(b = ct.bufferResize && ct.shouldBufferLayout()){
5062             if(!this.resizeTask){
5063                 this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
5064                 this.resizeBuffer = Ext.isNumber(b) ? b : 50;
5065             }
5066             ct.layoutPending = true;
5067             this.resizeTask.delay(this.resizeBuffer);
5068         }else{
5069             this.runLayout();
5070         }
5071     },
5072
5073     runLayout: function(){
5074         var ct = this.container;
5075         this.layout();
5076         ct.onLayout();
5077         delete ct.layoutPending;
5078     },
5079
5080     // private
5081     setContainer : function(ct){
5082         /**
5083          * This monitorResize flag will be renamed soon as to avoid confusion
5084          * with the Container version which hooks onWindowResize to doLayout
5085          *
5086          * monitorResize flag in this context attaches the resize event between
5087          * a container and it's layout
5088          */
5089         if(this.monitorResize && ct != this.container){
5090             var old = this.container;
5091             if(old){
5092                 old.un(old.resizeEvent, this.onResize, this);
5093             }
5094             if(ct){
5095                 ct.on(ct.resizeEvent, this.onResize, this);
5096             }
5097         }
5098         this.container = ct;
5099     },
5100
5101     /**
5102      * Parses a number or string representing margin sizes into an object. Supports CSS-style margin declarations
5103      * (e.g. 10, "10", "10 10", "10 10 10" and "10 10 10 10" are all valid options and would return the same result)
5104      * @param {Number|String} v The encoded margins
5105      * @return {Object} An object with margin sizes for top, right, bottom and left
5106      */
5107     parseMargins : function(v){
5108         if (Ext.isNumber(v)) {
5109             v = v.toString();
5110         }
5111         var ms  = v.split(' '),
5112             len = ms.length;
5113             
5114         if (len == 1) {
5115             ms[1] = ms[2] = ms[3] = ms[0];
5116         } else if(len == 2) {
5117             ms[2] = ms[0];
5118             ms[3] = ms[1];
5119         } else if(len == 3) {
5120             ms[3] = ms[1];
5121         }
5122         
5123         return {
5124             top   :parseInt(ms[0], 10) || 0,
5125             right :parseInt(ms[1], 10) || 0,
5126             bottom:parseInt(ms[2], 10) || 0,
5127             left  :parseInt(ms[3], 10) || 0
5128         };
5129     },
5130
5131     /**
5132      * The {@link Ext.Template Ext.Template} used by Field rendering layout classes (such as
5133      * {@link Ext.layout.FormLayout}) to create the DOM structure of a fully wrapped,
5134      * labeled and styled form Field. A default Template is supplied, but this may be
5135      * overriden to create custom field structures. The template processes values returned from
5136      * {@link Ext.layout.FormLayout#getTemplateArgs}.
5137      * @property fieldTpl
5138      * @type Ext.Template
5139      */
5140     fieldTpl: (function() {
5141         var t = new Ext.Template(
5142             '<div class="x-form-item {itemCls}" tabIndex="-1">',
5143                 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
5144                 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
5145                 '</div><div class="{clearCls}"></div>',
5146             '</div>'
5147         );
5148         t.disableFormats = true;
5149         return t.compile();
5150     })(),
5151
5152     /*
5153      * Destroys this layout. This is a template method that is empty by default, but should be implemented
5154      * by subclasses that require explicit destruction to purge event handlers or remove DOM nodes.
5155      * @protected
5156      */
5157     destroy : function(){
5158         // Stop any buffered layout tasks
5159         if(this.resizeTask && this.resizeTask.cancel){
5160             this.resizeTask.cancel();
5161         }
5162         if(!Ext.isEmpty(this.targetCls)){
5163             var target = this.container.getLayoutTarget();
5164             if(target){
5165                 target.removeClass(this.targetCls);
5166             }
5167         }
5168     }
5169 });/**
5170  * @class Ext.layout.AutoLayout
5171  * <p>The AutoLayout is the default layout manager delegated by {@link Ext.Container} to
5172  * render any child Components when no <tt>{@link Ext.Container#layout layout}</tt> is configured into
5173  * a {@link Ext.Container Container}.</tt>.  AutoLayout provides only a passthrough of any layout calls
5174  * to any child containers.</p>
5175  */
5176 Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
5177     type: 'auto',
5178
5179     monitorResize: true,
5180
5181     onLayout : function(ct, target){
5182         Ext.layout.AutoLayout.superclass.onLayout.call(this, ct, target);
5183         var cs = this.getRenderedItems(ct), len = cs.length, i, c;
5184         for(i = 0; i < len; i++){
5185             c = cs[i];
5186             if (c.doLayout){
5187                 // Shallow layout children
5188                 c.doLayout(true);
5189             }
5190         }
5191     }
5192 });
5193
5194 Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
5195 /**
5196  * @class Ext.layout.FitLayout
5197  * @extends Ext.layout.ContainerLayout
5198  * <p>This is a base class for layouts that contain <b>a single item</b> that automatically expands to fill the layout's
5199  * container.  This class is intended to be extended or created via the <tt>layout:'fit'</tt> {@link Ext.Container#layout}
5200  * config, and should generally not need to be created directly via the new keyword.</p>
5201  * <p>FitLayout does not have any direct config options (other than inherited ones).  To fit a panel to a container
5202  * using FitLayout, simply set layout:'fit' on the container and add a single panel to it.  If the container has
5203  * multiple panels, only the first one will be displayed.  Example usage:</p>
5204  * <pre><code>
5205 var p = new Ext.Panel({
5206     title: 'Fit Layout',
5207     layout:'fit',
5208     items: {
5209         title: 'Inner Panel',
5210         html: '&lt;p&gt;This is the inner panel content&lt;/p&gt;',
5211         border: false
5212     }
5213 });
5214 </code></pre>
5215  */
5216 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
5217     // private
5218     monitorResize:true,
5219
5220     type: 'fit',
5221
5222     getLayoutTargetSize : function() {
5223         var target = this.container.getLayoutTarget();
5224         if (!target) {
5225             return {};
5226         }
5227         // Style Sized (scrollbars not included)
5228         return target.getStyleSize();
5229     },
5230
5231     // private
5232     onLayout : function(ct, target){
5233         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
5234         if(!ct.collapsed){
5235             this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());
5236         }
5237     },
5238
5239     // private
5240     setItemSize : function(item, size){
5241         if(item && size.height > 0){ // display none?
5242             item.setSize(size);
5243         }
5244     }
5245 });
5246 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;/**
5247  * @class Ext.layout.CardLayout
5248  * @extends Ext.layout.FitLayout
5249  * <p>This layout manages multiple child Components, each fitted to the Container, where only a single child Component can be
5250  * visible at any given time.  This layout style is most commonly used for wizards, tab implementations, etc.
5251  * This class is intended to be extended or created via the layout:'card' {@link Ext.Container#layout} config,
5252  * and should generally not need to be created directly via the new keyword.</p>
5253  * <p>The CardLayout's focal method is {@link #setActiveItem}.  Since only one panel is displayed at a time,
5254  * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of
5255  * the next panel to display.  The layout itself does not provide a user interface for handling this navigation,
5256  * so that functionality must be provided by the developer.</p>
5257  * <p>In the following example, a simplistic wizard setup is demonstrated.  A button bar is added
5258  * to the footer of the containing panel to provide navigation buttons.  The buttons will be handled by a
5259  * common navigation routine -- for this example, the implementation of that routine has been ommitted since
5260  * it can be any type of custom logic.  Note that other uses of a CardLayout (like a tab control) would require a
5261  * completely different implementation.  For serious implementations, a better approach would be to extend
5262  * CardLayout to provide the custom functionality needed.  Example usage:</p>
5263  * <pre><code>
5264 var navHandler = function(direction){
5265     // This routine could contain business logic required to manage the navigation steps.
5266     // It would call setActiveItem as needed, manage navigation button state, handle any
5267     // branching logic that might be required, handle alternate actions like cancellation
5268     // or finalization, etc.  A complete wizard implementation could get pretty
5269     // sophisticated depending on the complexity required, and should probably be
5270     // done as a subclass of CardLayout in a real-world implementation.
5271 };
5272
5273 var card = new Ext.Panel({
5274     title: 'Example Wizard',
5275     layout:'card',
5276     activeItem: 0, // make sure the active item is set on the container config!
5277     bodyStyle: 'padding:15px',
5278     defaults: {
5279         // applied to each contained panel
5280         border:false
5281     },
5282     // just an example of one possible navigation scheme, using buttons
5283     bbar: [
5284         {
5285             id: 'move-prev',
5286             text: 'Back',
5287             handler: navHandler.createDelegate(this, [-1]),
5288             disabled: true
5289         },
5290         '->', // greedy spacer so that the buttons are aligned to each side
5291         {
5292             id: 'move-next',
5293             text: 'Next',
5294             handler: navHandler.createDelegate(this, [1])
5295         }
5296     ],
5297     // the panels (or "cards") within the layout
5298     items: [{
5299         id: 'card-0',
5300         html: '&lt;h1&gt;Welcome to the Wizard!&lt;/h1&gt;&lt;p&gt;Step 1 of 3&lt;/p&gt;'
5301     },{
5302         id: 'card-1',
5303         html: '&lt;p&gt;Step 2 of 3&lt;/p&gt;'
5304     },{
5305         id: 'card-2',
5306         html: '&lt;h1&gt;Congratulations!&lt;/h1&gt;&lt;p&gt;Step 3 of 3 - Complete&lt;/p&gt;'
5307     }]
5308 });
5309 </code></pre>
5310  */
5311 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
5312     /**
5313      * @cfg {Boolean} deferredRender
5314      * True to render each contained item at the time it becomes active, false to render all contained items
5315      * as soon as the layout is rendered (defaults to false).  If there is a significant amount of content or
5316      * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to
5317      * true might improve performance.
5318      */
5319     deferredRender : false,
5320
5321     /**
5322      * @cfg {Boolean} layoutOnCardChange
5323      * True to force a layout of the active item when the active card is changed. Defaults to false.
5324      */
5325     layoutOnCardChange : false,
5326
5327     /**
5328      * @cfg {Boolean} renderHidden @hide
5329      */
5330     // private
5331     renderHidden : true,
5332
5333     type: 'card',
5334
5335     /**
5336      * Sets the active (visible) item in the layout.
5337      * @param {String/Number} item The string component id or numeric index of the item to activate
5338      */
5339     setActiveItem : function(item){
5340         var ai = this.activeItem,
5341             ct = this.container;
5342         item = ct.getComponent(item);
5343
5344         // Is this a valid, different card?
5345         if(item && ai != item){
5346
5347             // Changing cards, hide the current one
5348             if(ai){
5349                 ai.hide();
5350                 if (ai.hidden !== true) {
5351                     return false;
5352                 }
5353                 ai.fireEvent('deactivate', ai);
5354             }
5355
5356             var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);
5357
5358             // Change activeItem reference
5359             this.activeItem = item;
5360
5361             // The container is about to get a recursive layout, remove any deferLayout reference
5362             // because it will trigger a redundant layout.
5363             delete item.deferLayout;
5364
5365             // Show the new component
5366             item.show();
5367
5368             this.layout();
5369
5370             if(layout){
5371                 item.doLayout();
5372             }
5373             item.fireEvent('activate', item);
5374         }
5375     },
5376
5377     // private
5378     renderAll : function(ct, target){
5379         if(this.deferredRender){
5380             this.renderItem(this.activeItem, undefined, target);
5381         }else{
5382             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
5383         }
5384     }
5385 });
5386 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;
5387 /**
5388  * @class Ext.layout.AnchorLayout
5389  * @extends Ext.layout.ContainerLayout
5390  * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.
5391  * If the container is resized, all anchored items are automatically rerendered according to their
5392  * <b><tt>{@link #anchor}</tt></b> rules.</p>
5393  * <p>This class is intended to be extended or created via the layout:'anchor' {@link Ext.Container#layout}
5394  * config, and should generally not need to be created directly via the new keyword.</p>
5395  * <p>AnchorLayout does not have any direct config options (other than inherited ones). By default,
5396  * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the
5397  * container using the AnchorLayout can supply an anchoring-specific config property of <b>anchorSize</b>.
5398  * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating
5399  * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring
5400  * logic if necessary.  For example:</p>
5401  * <pre><code>
5402 var viewport = new Ext.Viewport({
5403     layout:'anchor',
5404     anchorSize: {width:800, height:600},
5405     items:[{
5406         title:'Item 1',
5407         html:'Content 1',
5408         width:800,
5409         anchor:'right 20%'
5410     },{
5411         title:'Item 2',
5412         html:'Content 2',
5413         width:300,
5414         anchor:'50% 30%'
5415     },{
5416         title:'Item 3',
5417         html:'Content 3',
5418         width:600,
5419         anchor:'-100 50%'
5420     }]
5421 });
5422  * </code></pre>
5423  */
5424 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
5425     /**
5426      * @cfg {String} anchor
5427      * <p>This configuation option is to be applied to <b>child <tt>items</tt></b> of a container managed by
5428      * this layout (ie. configured with <tt>layout:'anchor'</tt>).</p><br/>
5429      *
5430      * <p>This value is what tells the layout how an item should be anchored to the container. <tt>items</tt>
5431      * added to an AnchorLayout accept an anchoring-specific config property of <b>anchor</b> which is a string
5432      * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').
5433      * The following types of anchor values are supported:<div class="mdetail-params"><ul>
5434      *
5435      * <li><b>Percentage</b> : Any value between 1 and 100, expressed as a percentage.<div class="sub-desc">
5436      * The first anchor is the percentage width that the item should take up within the container, and the
5437      * second is the percentage height.  For example:<pre><code>
5438 // two values specified
5439 anchor: '100% 50%' // render item complete width of the container and
5440                    // 1/2 height of the container
5441 // one value specified
5442 anchor: '100%'     // the width value; the height will default to auto
5443      * </code></pre></div></li>
5444      *
5445      * <li><b>Offsets</b> : Any positive or negative integer value.<div class="sub-desc">
5446      * This is a raw adjustment where the first anchor is the offset from the right edge of the container,
5447      * and the second is the offset from the bottom edge. For example:<pre><code>
5448 // two values specified
5449 anchor: '-50 -100' // render item the complete width of the container
5450                    // minus 50 pixels and
5451                    // the complete height minus 100 pixels.
5452 // one value specified
5453 anchor: '-50'      // anchor value is assumed to be the right offset value
5454                    // bottom offset will default to 0
5455      * </code></pre></div></li>
5456      *
5457      * <li><b>Sides</b> : Valid values are <tt>'right'</tt> (or <tt>'r'</tt>) and <tt>'bottom'</tt>
5458      * (or <tt>'b'</tt>).<div class="sub-desc">
5459      * Either the container must have a fixed size or an anchorSize config value defined at render time in
5460      * order for these to have any effect.</div></li>
5461      *
5462      * <li><b>Mixed</b> : <div class="sub-desc">
5463      * Anchor values can also be mixed as needed.  For example, to render the width offset from the container
5464      * right edge by 50 pixels and 75% of the container's height use:
5465      * <pre><code>
5466 anchor: '-50 75%'
5467      * </code></pre></div></li>
5468      *
5469      *
5470      * </ul></div>
5471      */
5472
5473     // private
5474     monitorResize : true,
5475
5476     type : 'anchor',
5477
5478     /**
5479      * @cfg {String} defaultAnchor
5480      *
5481      * default anchor for all child container items applied if no anchor or specific width is set on the child item.  Defaults to '100%'.
5482      *
5483      */
5484     defaultAnchor : '100%',
5485
5486     parseAnchorRE : /^(r|right|b|bottom)$/i,
5487
5488     getLayoutTargetSize : function() {
5489         var target = this.container.getLayoutTarget();
5490         if (!target) {
5491             return {};
5492         }
5493         // Style Sized (scrollbars not included)
5494         return target.getStyleSize();
5495     },
5496
5497     // private
5498     onLayout : function(ct, target){
5499         Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
5500         var size = this.getLayoutTargetSize();
5501
5502         var w = size.width, h = size.height;
5503
5504         if(w < 20 && h < 20){
5505             return;
5506         }
5507
5508         // find the container anchoring size
5509         var aw, ah;
5510         if(ct.anchorSize){
5511             if(typeof ct.anchorSize == 'number'){
5512                 aw = ct.anchorSize;
5513             }else{
5514                 aw = ct.anchorSize.width;
5515                 ah = ct.anchorSize.height;
5516             }
5517         }else{
5518             aw = ct.initialConfig.width;
5519             ah = ct.initialConfig.height;
5520         }
5521
5522         var cs = this.getRenderedItems(ct), len = cs.length, i, c, a, cw, ch, el, vs, boxes = [];
5523         for(i = 0; i < len; i++){
5524             c = cs[i];
5525             el = c.getPositionEl();
5526
5527             // If a child container item has no anchor and no specific width, set the child to the default anchor size
5528             if (!c.anchor && c.items && !Ext.isNumber(c.width) && !(Ext.isIE6 && Ext.isStrict)){
5529                 c.anchor = this.defaultAnchor;
5530             }
5531
5532             if(c.anchor){
5533                 a = c.anchorSpec;
5534                 if(!a){ // cache all anchor values
5535                     vs = c.anchor.split(' ');
5536                     c.anchorSpec = a = {
5537                         right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
5538                         bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
5539                     };
5540                 }
5541                 cw = a.right ? this.adjustWidthAnchor(a.right(w) - el.getMargins('lr'), c) : undefined;
5542                 ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h) - el.getMargins('tb'), c) : undefined;
5543
5544                 if(cw || ch){
5545                     boxes.push({
5546                         comp: c,
5547                         width: cw || undefined,
5548                         height: ch || undefined
5549                     });
5550                 }
5551             }
5552         }
5553         for (i = 0, len = boxes.length; i < len; i++) {
5554             c = boxes[i];
5555             c.comp.setSize(c.width, c.height);
5556         }
5557     },
5558
5559     // private
5560     parseAnchor : function(a, start, cstart){
5561         if(a && a != 'none'){
5562             var last;
5563             // standard anchor
5564             if(this.parseAnchorRE.test(a)){
5565                 var diff = cstart - start;
5566                 return function(v){
5567                     if(v !== last){
5568                         last = v;
5569                         return v - diff;
5570                     }
5571                 }
5572             // percentage
5573             }else if(a.indexOf('%') != -1){
5574                 var ratio = parseFloat(a.replace('%', ''))*.01;
5575                 return function(v){
5576                     if(v !== last){
5577                         last = v;
5578                         return Math.floor(v*ratio);
5579                     }
5580                 }
5581             // simple offset adjustment
5582             }else{
5583                 a = parseInt(a, 10);
5584                 if(!isNaN(a)){
5585                     return function(v){
5586                         if(v !== last){
5587                             last = v;
5588                             return v + a;
5589                         }
5590                     }
5591                 }
5592             }
5593         }
5594         return false;
5595     },
5596
5597     // private
5598     adjustWidthAnchor : function(value, comp){
5599         return value;
5600     },
5601
5602     // private
5603     adjustHeightAnchor : function(value, comp){
5604         return value;
5605     }
5606
5607     /**
5608      * @property activeItem
5609      * @hide
5610      */
5611 });
5612 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
5613 /**
5614  * @class Ext.layout.ColumnLayout
5615  * @extends Ext.layout.ContainerLayout
5616  * <p>This is the layout style of choice for creating structural layouts in a multi-column format where the width of
5617  * each column can be specified as a percentage or fixed width, but the height is allowed to vary based on the content.
5618  * This class is intended to be extended or created via the layout:'column' {@link Ext.Container#layout} config,
5619  * and should generally not need to be created directly via the new keyword.</p>
5620  * <p>ColumnLayout does not have any direct config options (other than inherited ones), but it does support a
5621  * specific config property of <b><tt>columnWidth</tt></b> that can be included in the config of any panel added to it.  The
5622  * layout will use the columnWidth (if present) or width of each panel during layout to determine how to size each panel.
5623  * If width or columnWidth is not specified for a given panel, its width will default to the panel's width (or auto).</p>
5624  * <p>The width property is always evaluated as pixels, and must be a number greater than or equal to 1.
5625  * The columnWidth property is always evaluated as a percentage, and must be a decimal value greater than 0 and
5626  * less than 1 (e.g., .25).</p>
5627  * <p>The basic rules for specifying column widths are pretty simple.  The logic makes two passes through the
5628  * set of contained panels.  During the first layout pass, all panels that either have a fixed width or none
5629  * specified (auto) are skipped, but their widths are subtracted from the overall container width.  During the second
5630  * pass, all panels with columnWidths are assigned pixel widths in proportion to their percentages based on
5631  * the total <b>remaining</b> container width.  In other words, percentage width panels are designed to fill the space
5632  * left over by all the fixed-width and/or auto-width panels.  Because of this, while you can specify any number of columns
5633  * with different percentages, the columnWidths must always add up to 1 (or 100%) when added together, otherwise your
5634  * layout may not render as expected.  Example usage:</p>
5635  * <pre><code>
5636 // All columns are percentages -- they must add up to 1
5637 var p = new Ext.Panel({
5638     title: 'Column Layout - Percentage Only',
5639     layout:'column',
5640     items: [{
5641         title: 'Column 1',
5642         columnWidth: .25
5643     },{
5644         title: 'Column 2',
5645         columnWidth: .6
5646     },{
5647         title: 'Column 3',
5648         columnWidth: .15
5649     }]
5650 });
5651
5652 // Mix of width and columnWidth -- all columnWidth values must add up
5653 // to 1. The first column will take up exactly 120px, and the last two
5654 // columns will fill the remaining container width.
5655 var p = new Ext.Panel({
5656     title: 'Column Layout - Mixed',
5657     layout:'column',
5658     items: [{
5659         title: 'Column 1',
5660         width: 120
5661     },{
5662         title: 'Column 2',
5663         columnWidth: .8
5664     },{
5665         title: 'Column 3',
5666         columnWidth: .2
5667     }]
5668 });
5669 </code></pre>
5670  */
5671 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
5672     // private
5673     monitorResize:true,
5674
5675     type: 'column',
5676
5677     extraCls: 'x-column',
5678
5679     scrollOffset : 0,
5680
5681     // private
5682
5683     targetCls: 'x-column-layout-ct',
5684
5685     isValidParent : function(c, target){
5686         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
5687     },
5688
5689     getLayoutTargetSize : function() {
5690         var target = this.container.getLayoutTarget(), ret;
5691         if (target) {
5692             ret = target.getViewSize();
5693
5694             // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
5695             // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
5696             // with getViewSize
5697             if (Ext.isIE && Ext.isStrict && ret.width == 0){
5698                 ret =  target.getStyleSize();
5699             }
5700
5701             ret.width -= target.getPadding('lr');
5702             ret.height -= target.getPadding('tb');
5703         }
5704         return ret;
5705     },
5706
5707     renderAll : function(ct, target) {
5708         if(!this.innerCt){
5709             // the innerCt prevents wrapping and shuffling while
5710             // the container is resizing
5711             this.innerCt = target.createChild({cls:'x-column-inner'});
5712             this.innerCt.createChild({cls:'x-clear'});
5713         }
5714         Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);
5715     },
5716
5717     // private
5718     onLayout : function(ct, target){
5719         var cs = ct.items.items,
5720             len = cs.length,
5721             c,
5722             i,
5723             m,
5724             margins = [];
5725
5726         this.renderAll(ct, target);
5727
5728         var size = this.getLayoutTargetSize();
5729
5730         if(size.width < 1 && size.height < 1){ // display none?
5731             return;
5732         }
5733
5734         var w = size.width - this.scrollOffset,
5735             h = size.height,
5736             pw = w;
5737
5738         this.innerCt.setWidth(w);
5739
5740         // some columns can be percentages while others are fixed
5741         // so we need to make 2 passes
5742
5743         for(i = 0; i < len; i++){
5744             c = cs[i];
5745             m = c.getPositionEl().getMargins('lr');
5746             margins[i] = m;
5747             if(!c.columnWidth){
5748                 pw -= (c.getWidth() + m);
5749             }
5750         }
5751
5752         pw = pw < 0 ? 0 : pw;
5753
5754         for(i = 0; i < len; i++){
5755             c = cs[i];
5756             m = margins[i];
5757             if(c.columnWidth){
5758                 c.setSize(Math.floor(c.columnWidth * pw) - m);
5759             }
5760         }
5761
5762         // Browsers differ as to when they account for scrollbars.  We need to re-measure to see if the scrollbar
5763         // spaces were accounted for properly.  If not, re-layout.
5764         if (Ext.isIE) {
5765             if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
5766                 var ts = this.getLayoutTargetSize();
5767                 if (ts.width != size.width){
5768                     this.adjustmentPass = true;
5769                     this.onLayout(ct, target);
5770                 }
5771             }
5772         }
5773         delete this.adjustmentPass;
5774     }
5775
5776     /**
5777      * @property activeItem
5778      * @hide
5779      */
5780 });
5781
5782 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;
5783 /**
5784  * @class Ext.layout.BorderLayout
5785  * @extends Ext.layout.ContainerLayout
5786  * <p>This is a multi-pane, application-oriented UI layout style that supports multiple
5787  * nested panels, automatic {@link Ext.layout.BorderLayout.Region#split split} bars between
5788  * {@link Ext.layout.BorderLayout.Region#BorderLayout.Region regions} and built-in
5789  * {@link Ext.layout.BorderLayout.Region#collapsible expanding and collapsing} of regions.</p>
5790  * <p>This class is intended to be extended or created via the <tt>layout:'border'</tt>
5791  * {@link Ext.Container#layout} config, and should generally not need to be created directly
5792  * via the new keyword.</p>
5793  * <p>BorderLayout does not have any direct config options (other than inherited ones).
5794  * All configuration options available for customizing the BorderLayout are at the
5795  * {@link Ext.layout.BorderLayout.Region} and {@link Ext.layout.BorderLayout.SplitRegion}
5796  * levels.</p>
5797  * <p>Example usage:</p>
5798  * <pre><code>
5799 var myBorderPanel = new Ext.Panel({
5800     {@link Ext.Component#renderTo renderTo}: document.body,
5801     {@link Ext.BoxComponent#width width}: 700,
5802     {@link Ext.BoxComponent#height height}: 500,
5803     {@link Ext.Panel#title title}: 'Border Layout',
5804     {@link Ext.Container#layout layout}: 'border',
5805     {@link Ext.Container#items items}: [{
5806         {@link Ext.Panel#title title}: 'South Region is resizable',
5807         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south',     // position for region
5808         {@link Ext.BoxComponent#height height}: 100,
5809         {@link Ext.layout.BorderLayout.Region#split split}: true,         // enable resizing
5810         {@link Ext.SplitBar#minSize minSize}: 75,         // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50}
5811         {@link Ext.SplitBar#maxSize maxSize}: 150,
5812         {@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5'
5813     },{
5814         // xtype: 'panel' implied by default
5815         {@link Ext.Panel#title title}: 'West Region is collapsible',
5816         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}:'west',
5817         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 0 0 5',
5818         {@link Ext.BoxComponent#width width}: 200,
5819         {@link Ext.layout.BorderLayout.Region#collapsible collapsible}: true,   // make collapsible
5820         {@link Ext.layout.BorderLayout.Region#cmargins cmargins}: '5 5 0 5', // adjust top margin when collapsed
5821         {@link Ext.Component#id id}: 'west-region-container',
5822         {@link Ext.Container#layout layout}: 'fit',
5823         {@link Ext.Panel#unstyled unstyled}: true
5824     },{
5825         {@link Ext.Panel#title title}: 'Center Region',
5826         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'center',     // center region is required, no width/height specified
5827         {@link Ext.Component#xtype xtype}: 'container',
5828         {@link Ext.Container#layout layout}: 'fit',
5829         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 5 0 0'
5830     }]
5831 });
5832 </code></pre>
5833  * <p><b><u>Notes</u></b>:</p><div class="mdetail-params"><ul>
5834  * <li>Any container using the BorderLayout <b>must</b> have a child item with <tt>region:'center'</tt>.
5835  * The child item in the center region will always be resized to fill the remaining space not used by
5836  * the other regions in the layout.</li>
5837  * <li>Any child items with a region of <tt>west</tt> or <tt>east</tt> must have <tt>width</tt> defined
5838  * (an integer representing the number of pixels that the region should take up).</li>
5839  * <li>Any child items with a region of <tt>north</tt> or <tt>south</tt> must have <tt>height</tt> defined.</li>
5840  * <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
5841  * Components within a BorderLayout, have them wrapped by an additional Container which is directly
5842  * managed by the BorderLayout.  If the region is to be collapsible, the Container used directly
5843  * by the BorderLayout manager should be a Panel.  In the following example a Container (an Ext.Panel)
5844  * is added to the west region:
5845  * <div style="margin-left:16px"><pre><code>
5846 wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container');
5847 wrc.{@link Ext.Panel#removeAll removeAll}();
5848 wrc.{@link Ext.Container#add add}({
5849     title: 'Added Panel',
5850     html: 'Some content'
5851 });
5852 wrc.{@link Ext.Container#doLayout doLayout}();
5853  * </code></pre></div>
5854  * </li>
5855  * <li> To reference a {@link Ext.layout.BorderLayout.Region Region}:
5856  * <div style="margin-left:16px"><pre><code>
5857 wr = myBorderPanel.layout.west;
5858  * </code></pre></div>
5859  * </li>
5860  * </ul></div>
5861  */
5862 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
5863     // private
5864     monitorResize:true,
5865     // private
5866     rendered : false,
5867
5868     type: 'border',
5869
5870     targetCls: 'x-border-layout-ct',
5871
5872     getLayoutTargetSize : function() {
5873         var target = this.container.getLayoutTarget();
5874         return target ? target.getViewSize() : {};
5875     },
5876
5877     // private
5878     onLayout : function(ct, target){
5879         var collapsed, i, c, pos, items = ct.items.items, len = items.length;
5880         if(!this.rendered){
5881             collapsed = [];
5882             for(i = 0; i < len; i++) {
5883                 c = items[i];
5884                 pos = c.region;
5885                 if(c.collapsed){
5886                     collapsed.push(c);
5887                 }
5888                 c.collapsed = false;
5889                 if(!c.rendered){
5890                     c.render(target, i);
5891                     c.getPositionEl().addClass('x-border-panel');
5892                 }
5893                 this[pos] = pos != 'center' && c.split ?
5894                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
5895                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
5896                 this[pos].render(target, c);
5897             }
5898             this.rendered = true;
5899         }
5900
5901         var size = this.getLayoutTargetSize();
5902         if(size.width < 20 || size.height < 20){ // display none?
5903             if(collapsed){
5904                 this.restoreCollapsed = collapsed;
5905             }
5906             return;
5907         }else if(this.restoreCollapsed){
5908             collapsed = this.restoreCollapsed;
5909             delete this.restoreCollapsed;
5910         }
5911
5912         var w = size.width, h = size.height,
5913             centerW = w, centerH = h, centerY = 0, centerX = 0,
5914             n = this.north, s = this.south, west = this.west, e = this.east, c = this.center,
5915             b, m, totalWidth, totalHeight;
5916         if(!c && Ext.layout.BorderLayout.WARN !== false){
5917             throw 'No center region defined in BorderLayout ' + ct.id;
5918         }
5919
5920         if(n && n.isVisible()){
5921             b = n.getSize();
5922             m = n.getMargins();
5923             b.width = w - (m.left+m.right);
5924             b.x = m.left;
5925             b.y = m.top;
5926             centerY = b.height + b.y + m.bottom;
5927             centerH -= centerY;
5928             n.applyLayout(b);
5929         }
5930         if(s && s.isVisible()){
5931             b = s.getSize();
5932             m = s.getMargins();
5933             b.width = w - (m.left+m.right);
5934             b.x = m.left;
5935             totalHeight = (b.height + m.top + m.bottom);
5936             b.y = h - totalHeight + m.top;
5937             centerH -= totalHeight;
5938             s.applyLayout(b);
5939         }
5940         if(west && west.isVisible()){
5941             b = west.getSize();
5942             m = west.getMargins();
5943             b.height = centerH - (m.top+m.bottom);
5944             b.x = m.left;
5945             b.y = centerY + m.top;
5946             totalWidth = (b.width + m.left + m.right);
5947             centerX += totalWidth;
5948             centerW -= totalWidth;
5949             west.applyLayout(b);
5950         }
5951         if(e && e.isVisible()){
5952             b = e.getSize();
5953             m = e.getMargins();
5954             b.height = centerH - (m.top+m.bottom);
5955             totalWidth = (b.width + m.left + m.right);
5956             b.x = w - totalWidth + m.left;
5957             b.y = centerY + m.top;
5958             centerW -= totalWidth;
5959             e.applyLayout(b);
5960         }
5961         if(c){
5962             m = c.getMargins();
5963             var centerBox = {
5964                 x: centerX + m.left,
5965                 y: centerY + m.top,
5966                 width: centerW - (m.left+m.right),
5967                 height: centerH - (m.top+m.bottom)
5968             };
5969             c.applyLayout(centerBox);
5970         }
5971         if(collapsed){
5972             for(i = 0, len = collapsed.length; i < len; i++){
5973                 collapsed[i].collapse(false);
5974             }
5975         }
5976         if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue
5977             target.repaint();
5978         }
5979         // Putting a border layout into an overflowed container is NOT correct and will make a second layout pass necessary.
5980         if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
5981             var ts = this.getLayoutTargetSize();
5982             if (ts.width != size.width || ts.height != size.height){
5983                 this.adjustmentPass = true;
5984                 this.onLayout(ct, target);
5985             }
5986         }
5987         delete this.adjustmentPass;
5988     },
5989
5990     destroy: function() {
5991         var r = ['north', 'south', 'east', 'west'], i, region;
5992         for (i = 0; i < r.length; i++) {
5993             region = this[r[i]];
5994             if(region){
5995                 if(region.destroy){
5996                     region.destroy();
5997                 }else if (region.split){
5998                     region.split.destroy(true);
5999                 }
6000             }
6001         }
6002         Ext.layout.BorderLayout.superclass.destroy.call(this);
6003     }
6004
6005     /**
6006      * @property activeItem
6007      * @hide
6008      */
6009 });
6010
6011 /**
6012  * @class Ext.layout.BorderLayout.Region
6013  * <p>This is a region of a {@link Ext.layout.BorderLayout BorderLayout} that acts as a subcontainer
6014  * within the layout.  Each region has its own {@link Ext.layout.ContainerLayout layout} that is
6015  * independent of other regions and the containing BorderLayout, and can be any of the
6016  * {@link Ext.layout.ContainerLayout valid Ext layout types}.</p>
6017  * <p>Region size is managed automatically and cannot be changed by the user -- for
6018  * {@link #split resizable regions}, see {@link Ext.layout.BorderLayout.SplitRegion}.</p>
6019  * @constructor
6020  * Create a new Region.
6021  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
6022  * @param {Object} config The configuration options
6023  * @param {String} position The region position.  Valid values are: <tt>north</tt>, <tt>south</tt>,
6024  * <tt>east</tt>, <tt>west</tt> and <tt>center</tt>.  Every {@link Ext.layout.BorderLayout BorderLayout}
6025  * <b>must have a center region</b> for the primary content -- all other regions are optional.
6026  */
6027 Ext.layout.BorderLayout.Region = function(layout, config, pos){
6028     Ext.apply(this, config);
6029     this.layout = layout;
6030     this.position = pos;
6031     this.state = {};
6032     if(typeof this.margins == 'string'){
6033         this.margins = this.layout.parseMargins(this.margins);
6034     }
6035     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
6036     if(this.collapsible){
6037         if(typeof this.cmargins == 'string'){
6038             this.cmargins = this.layout.parseMargins(this.cmargins);
6039         }
6040         if(this.collapseMode == 'mini' && !this.cmargins){
6041             this.cmargins = {left:0,top:0,right:0,bottom:0};
6042         }else{
6043             this.cmargins = Ext.applyIf(this.cmargins || {},
6044                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
6045         }
6046     }
6047 };
6048
6049 Ext.layout.BorderLayout.Region.prototype = {
6050     /**
6051      * @cfg {Boolean} animFloat
6052      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
6053      * panel that will close again once the user mouses out of that panel (or clicks out if
6054      * <tt>{@link #autoHide} = false</tt>).  Setting <tt>{@link #animFloat} = false</tt> will
6055      * prevent the open and close of these floated panels from being animated (defaults to <tt>true</tt>).
6056      */
6057     /**
6058      * @cfg {Boolean} autoHide
6059      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
6060      * panel.  If <tt>autoHide = true</tt>, the panel will automatically hide after the user mouses
6061      * out of the panel.  If <tt>autoHide = false</tt>, the panel will continue to display until the
6062      * user clicks outside of the panel (defaults to <tt>true</tt>).
6063      */
6064     /**
6065      * @cfg {String} collapseMode
6066      * <tt>collapseMode</tt> supports two configuration values:<div class="mdetail-params"><ul>
6067      * <li><b><tt>undefined</tt></b> (default)<div class="sub-desc">By default, {@link #collapsible}
6068      * regions are collapsed by clicking the expand/collapse tool button that renders into the region's
6069      * title bar.</div></li>
6070      * <li><b><tt>'mini'</tt></b><div class="sub-desc">Optionally, when <tt>collapseMode</tt> is set to
6071      * <tt>'mini'</tt> the region's split bar will also display a small collapse button in the center of
6072      * the bar. In <tt>'mini'</tt> mode the region will collapse to a thinner bar than in normal mode.
6073      * </div></li>
6074      * </ul></div></p>
6075      * <p><b>Note</b>: if a collapsible region does not have a title bar, then set <tt>collapseMode =
6076      * 'mini'</tt> and <tt>{@link #split} = true</tt> in order for the region to be {@link #collapsible}
6077      * by the user as the expand/collapse tool button (that would go in the title bar) will not be rendered.</p>
6078      * <p>See also <tt>{@link #cmargins}</tt>.</p>
6079      */
6080     /**
6081      * @cfg {Object} margins
6082      * An object containing margins to apply to the region when in the expanded state in the
6083      * format:<pre><code>
6084 {
6085     top: (top margin),
6086     right: (right margin),
6087     bottom: (bottom margin),
6088     left: (left margin)
6089 }</code></pre>
6090      * <p>May also be a string containing space-separated, numeric margin values. The order of the
6091      * sides associated with each value matches the way CSS processes margin values:</p>
6092      * <p><div class="mdetail-params"><ul>
6093      * <li>If there is only one value, it applies to all sides.</li>
6094      * <li>If there are two values, the top and bottom borders are set to the first value and the
6095      * right and left are set to the second.</li>
6096      * <li>If there are three values, the top is set to the first value, the left and right are set
6097      * to the second, and the bottom is set to the third.</li>
6098      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
6099      * </ul></div></p>
6100      * <p>Defaults to:</p><pre><code>
6101      * {top:0, right:0, bottom:0, left:0}
6102      * </code></pre>
6103      */
6104     /**
6105      * @cfg {Object} cmargins
6106      * An object containing margins to apply to the region when in the collapsed state in the
6107      * format:<pre><code>
6108 {
6109     top: (top margin),
6110     right: (right margin),
6111     bottom: (bottom margin),
6112     left: (left margin)
6113 }</code></pre>
6114      * <p>May also be a string containing space-separated, numeric margin values. The order of the
6115      * sides associated with each value matches the way CSS processes margin values.</p>
6116      * <p><ul>
6117      * <li>If there is only one value, it applies to all sides.</li>
6118      * <li>If there are two values, the top and bottom borders are set to the first value and the
6119      * right and left are set to the second.</li>
6120      * <li>If there are three values, the top is set to the first value, the left and right are set
6121      * to the second, and the bottom is set to the third.</li>
6122      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
6123      * </ul></p>
6124      */
6125     /**
6126      * @cfg {Boolean} collapsible
6127      * <p><tt>true</tt> to allow the user to collapse this region (defaults to <tt>false</tt>).  If
6128      * <tt>true</tt>, an expand/collapse tool button will automatically be rendered into the title
6129      * bar of the region, otherwise the button will not be shown.</p>
6130      * <p><b>Note</b>: that a title bar is required to display the collapse/expand toggle button -- if
6131      * no <tt>title</tt> is specified for the region's panel, the region will only be collapsible if
6132      * <tt>{@link #collapseMode} = 'mini'</tt> and <tt>{@link #split} = true</tt>.
6133      */
6134     collapsible : false,
6135     /**
6136      * @cfg {Boolean} split
6137      * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and
6138      * display a 5px wide {@link Ext.SplitBar} between this region and its neighbor, allowing the user to
6139      * resize the regions dynamically.  Defaults to <tt>false</tt> creating a
6140      * {@link Ext.layout.BorderLayout.Region Region}.</p><br>
6141      * <p><b>Notes</b>:</p><div class="mdetail-params"><ul>
6142      * <li>this configuration option is ignored if <tt>region='center'</tt></li>
6143      * <li>when <tt>split == true</tt>, it is common to specify a
6144      * <tt>{@link Ext.SplitBar#minSize minSize}</tt> and <tt>{@link Ext.SplitBar#maxSize maxSize}</tt>
6145      * for the {@link Ext.BoxComponent BoxComponent} representing the region. These are not native
6146      * configs of {@link Ext.BoxComponent BoxComponent}, and are used only by this class.</li>
6147      * <li>if <tt>{@link #collapseMode} = 'mini'</tt> requires <tt>split = true</tt> to reserve space
6148      * for the collapse tool</tt></li>
6149      * </ul></div>
6150      */
6151     split:false,
6152     /**
6153      * @cfg {Boolean} floatable
6154      * <tt>true</tt> to allow clicking a collapsed region's bar to display the region's panel floated
6155      * above the layout, <tt>false</tt> to force the user to fully expand a collapsed region by
6156      * clicking the expand button to see it again (defaults to <tt>true</tt>).
6157      */
6158     floatable: true,
6159     /**
6160      * @cfg {Number} minWidth
6161      * <p>The minimum allowable width in pixels for this region (defaults to <tt>50</tt>).
6162      * <tt>maxWidth</tt> may also be specified.</p><br>
6163      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
6164      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
6165      * <tt>minWidth</tt> / <tt>maxWidth</tt>.</p>
6166      */
6167     minWidth:50,
6168     /**
6169      * @cfg {Number} minHeight
6170      * The minimum allowable height in pixels for this region (defaults to <tt>50</tt>)
6171      * <tt>maxHeight</tt> may also be specified.</p><br>
6172      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
6173      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
6174      * <tt>minHeight</tt> / <tt>maxHeight</tt>.</p>
6175      */
6176     minHeight:50,
6177
6178     // private
6179     defaultMargins : {left:0,top:0,right:0,bottom:0},
6180     // private
6181     defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
6182     // private
6183     defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
6184     floatingZIndex: 100,
6185
6186     /**
6187      * True if this region is collapsed. Read-only.
6188      * @type Boolean
6189      * @property
6190      */
6191     isCollapsed : false,
6192
6193     /**
6194      * This region's panel.  Read-only.
6195      * @type Ext.Panel
6196      * @property panel
6197      */
6198     /**
6199      * This region's layout.  Read-only.
6200      * @type Layout
6201      * @property layout
6202      */
6203     /**
6204      * This region's layout position (north, south, east, west or center).  Read-only.
6205      * @type String
6206      * @property position
6207      */
6208
6209     // private
6210     render : function(ct, p){
6211         this.panel = p;
6212         p.el.enableDisplayMode();
6213         this.targetEl = ct;
6214         this.el = p.el;
6215
6216         var gs = p.getState, ps = this.position;
6217         p.getState = function(){
6218             return Ext.apply(gs.call(p) || {}, this.state);
6219         }.createDelegate(this);
6220
6221         if(ps != 'center'){
6222             p.allowQueuedExpand = false;
6223             p.on({
6224                 beforecollapse: this.beforeCollapse,
6225                 collapse: this.onCollapse,
6226                 beforeexpand: this.beforeExpand,
6227                 expand: this.onExpand,
6228                 hide: this.onHide,
6229                 show: this.onShow,
6230                 scope: this
6231             });
6232             if(this.collapsible || this.floatable){
6233                 p.collapseEl = 'el';
6234                 p.slideAnchor = this.getSlideAnchor();
6235             }
6236             if(p.tools && p.tools.toggle){
6237                 p.tools.toggle.addClass('x-tool-collapse-'+ps);
6238                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
6239             }
6240         }
6241     },
6242
6243     // private
6244     getCollapsedEl : function(){
6245         if(!this.collapsedEl){
6246             if(!this.toolTemplate){
6247                 var tt = new Ext.Template(
6248                      '<div class="x-tool x-tool-{id}">&#160;</div>'
6249                 );
6250                 tt.disableFormats = true;
6251                 tt.compile();
6252                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
6253             }
6254             this.collapsedEl = this.targetEl.createChild({
6255                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
6256                 id: this.panel.id + '-xcollapsed'
6257             });
6258             this.collapsedEl.enableDisplayMode('block');
6259
6260             if(this.collapseMode == 'mini'){
6261                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
6262                 this.miniCollapsedEl = this.collapsedEl.createChild({
6263                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
6264                 });
6265                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
6266                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
6267                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
6268             }else {
6269                 if(this.collapsible !== false && !this.hideCollapseTool) {
6270                     var t = this.toolTemplate.append(
6271                             this.collapsedEl.dom,
6272                             {id:'expand-'+this.position}, true);
6273                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
6274                     t.on('click', this.onExpandClick, this, {stopEvent:true});
6275                 }
6276                 if(this.floatable !== false || this.titleCollapse){
6277                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
6278                    this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
6279                 }
6280             }
6281         }
6282         return this.collapsedEl;
6283     },
6284
6285     // private
6286     onExpandClick : function(e){
6287         if(this.isSlid){
6288             this.panel.expand(false);
6289         }else{
6290             this.panel.expand();
6291         }
6292     },
6293
6294     // private
6295     onCollapseClick : function(e){
6296         this.panel.collapse();
6297     },
6298
6299     // private
6300     beforeCollapse : function(p, animate){
6301         this.lastAnim = animate;
6302         if(this.splitEl){
6303             this.splitEl.hide();
6304         }
6305         this.getCollapsedEl().show();
6306         var el = this.panel.getEl();
6307         this.originalZIndex = el.getStyle('z-index');
6308         el.setStyle('z-index', 100);
6309         this.isCollapsed = true;
6310         this.layout.layout();
6311     },
6312
6313     // private
6314     onCollapse : function(animate){
6315         this.panel.el.setStyle('z-index', 1);
6316         if(this.lastAnim === false || this.panel.animCollapse === false){
6317             this.getCollapsedEl().dom.style.visibility = 'visible';
6318         }else{
6319             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
6320         }
6321         this.state.collapsed = true;
6322         this.panel.saveState();
6323     },
6324
6325     // private
6326     beforeExpand : function(animate){
6327         if(this.isSlid){
6328             this.afterSlideIn();
6329         }
6330         var c = this.getCollapsedEl();
6331         this.el.show();
6332         if(this.position == 'east' || this.position == 'west'){
6333             this.panel.setSize(undefined, c.getHeight());
6334         }else{
6335             this.panel.setSize(c.getWidth(), undefined);
6336         }
6337         c.hide();
6338         c.dom.style.visibility = 'hidden';
6339         this.panel.el.setStyle('z-index', this.floatingZIndex);
6340     },
6341
6342     // private
6343     onExpand : function(){
6344         this.isCollapsed = false;
6345         if(this.splitEl){
6346             this.splitEl.show();
6347         }
6348         this.layout.layout();
6349         this.panel.el.setStyle('z-index', this.originalZIndex);
6350         this.state.collapsed = false;
6351         this.panel.saveState();
6352     },
6353
6354     // private
6355     collapseClick : function(e){
6356         if(this.isSlid){
6357            e.stopPropagation();
6358            this.slideIn();
6359         }else{
6360            e.stopPropagation();
6361            this.slideOut();
6362         }
6363     },
6364
6365     // private
6366     onHide : function(){
6367         if(this.isCollapsed){
6368             this.getCollapsedEl().hide();
6369         }else if(this.splitEl){
6370             this.splitEl.hide();
6371         }
6372     },
6373
6374     // private
6375     onShow : function(){
6376         if(this.isCollapsed){
6377             this.getCollapsedEl().show();
6378         }else if(this.splitEl){
6379             this.splitEl.show();
6380         }
6381     },
6382
6383     /**
6384      * True if this region is currently visible, else false.
6385      * @return {Boolean}
6386      */
6387     isVisible : function(){
6388         return !this.panel.hidden;
6389     },
6390
6391     /**
6392      * Returns the current margins for this region.  If the region is collapsed, the
6393      * {@link #cmargins} (collapsed margins) value will be returned, otherwise the
6394      * {@link #margins} value will be returned.
6395      * @return {Object} An object containing the element's margins: <tt>{left: (left
6396      * margin), top: (top margin), right: (right margin), bottom: (bottom margin)}</tt>
6397      */
6398     getMargins : function(){
6399         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
6400     },
6401
6402     /**
6403      * Returns the current size of this region.  If the region is collapsed, the size of the
6404      * collapsedEl will be returned, otherwise the size of the region's panel will be returned.
6405      * @return {Object} An object containing the element's size: <tt>{width: (element width),
6406      * height: (element height)}</tt>
6407      */
6408     getSize : function(){
6409         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
6410     },
6411
6412     /**
6413      * Sets the specified panel as the container element for this region.
6414      * @param {Ext.Panel} panel The new panel
6415      */
6416     setPanel : function(panel){
6417         this.panel = panel;
6418     },
6419
6420     /**
6421      * Returns the minimum allowable width for this region.
6422      * @return {Number} The minimum width
6423      */
6424     getMinWidth: function(){
6425         return this.minWidth;
6426     },
6427
6428     /**
6429      * Returns the minimum allowable height for this region.
6430      * @return {Number} The minimum height
6431      */
6432     getMinHeight: function(){
6433         return this.minHeight;
6434     },
6435
6436     // private
6437     applyLayoutCollapsed : function(box){
6438         var ce = this.getCollapsedEl();
6439         ce.setLeftTop(box.x, box.y);
6440         ce.setSize(box.width, box.height);
6441     },
6442
6443     // private
6444     applyLayout : function(box){
6445         if(this.isCollapsed){
6446             this.applyLayoutCollapsed(box);
6447         }else{
6448             this.panel.setPosition(box.x, box.y);
6449             this.panel.setSize(box.width, box.height);
6450         }
6451     },
6452
6453     // private
6454     beforeSlide: function(){
6455         this.panel.beforeEffect();
6456     },
6457
6458     // private
6459     afterSlide : function(){
6460         this.panel.afterEffect();
6461     },
6462
6463     // private
6464     initAutoHide : function(){
6465         if(this.autoHide !== false){
6466             if(!this.autoHideHd){
6467                 this.autoHideSlideTask = new Ext.util.DelayedTask(this.slideIn, this);
6468                 this.autoHideHd = {
6469                     "mouseout": function(e){
6470                         if(!e.within(this.el, true)){
6471                             this.autoHideSlideTask.delay(500);
6472                         }
6473                     },
6474                     "mouseover" : function(e){
6475                         this.autoHideSlideTask.cancel();
6476                     },
6477                     scope : this
6478                 };
6479             }
6480             this.el.on(this.autoHideHd);
6481             this.collapsedEl.on(this.autoHideHd);
6482         }
6483     },
6484
6485     // private
6486     clearAutoHide : function(){
6487         if(this.autoHide !== false){
6488             this.el.un("mouseout", this.autoHideHd.mouseout);
6489             this.el.un("mouseover", this.autoHideHd.mouseover);
6490             this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
6491             this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
6492         }
6493     },
6494
6495     // private
6496     clearMonitor : function(){
6497         Ext.getDoc().un("click", this.slideInIf, this);
6498     },
6499
6500     /**
6501      * If this Region is {@link #floatable}, this method slides this Region into full visibility <i>over the top
6502      * of the center Region</i> where it floats until either {@link #slideIn} is called, or other regions of the layout
6503      * are clicked, or the mouse exits the Region.
6504      */
6505     slideOut : function(){
6506         if(this.isSlid || this.el.hasActiveFx()){
6507             return;
6508         }
6509         this.isSlid = true;
6510         var ts = this.panel.tools, dh, pc;
6511         if(ts && ts.toggle){
6512             ts.toggle.hide();
6513         }
6514         this.el.show();
6515
6516         // Temporarily clear the collapsed flag so we can onResize the panel on the slide
6517         pc = this.panel.collapsed;
6518         this.panel.collapsed = false;
6519
6520         if(this.position == 'east' || this.position == 'west'){
6521             // Temporarily clear the deferHeight flag so we can size the height on the slide
6522             dh = this.panel.deferHeight;
6523             this.panel.deferHeight = false;
6524
6525             this.panel.setSize(undefined, this.collapsedEl.getHeight());
6526
6527             // Put the deferHeight flag back after setSize
6528             this.panel.deferHeight = dh;
6529         }else{
6530             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
6531         }
6532
6533         // Put the collapsed flag back after onResize
6534         this.panel.collapsed = pc;
6535
6536         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
6537         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
6538         this.el.setStyle("z-index", this.floatingZIndex+2);
6539         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
6540         if(this.animFloat !== false){
6541             this.beforeSlide();
6542             this.el.slideIn(this.getSlideAnchor(), {
6543                 callback: function(){
6544                     this.afterSlide();
6545                     this.initAutoHide();
6546                     Ext.getDoc().on("click", this.slideInIf, this);
6547                 },
6548                 scope: this,
6549                 block: true
6550             });
6551         }else{
6552             this.initAutoHide();
6553              Ext.getDoc().on("click", this.slideInIf, this);
6554         }
6555     },
6556
6557     // private
6558     afterSlideIn : function(){
6559         this.clearAutoHide();
6560         this.isSlid = false;
6561         this.clearMonitor();
6562         this.el.setStyle("z-index", "");
6563         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
6564         this.el.dom.style.left = this.restoreLT[0];
6565         this.el.dom.style.top = this.restoreLT[1];
6566
6567         var ts = this.panel.tools;
6568         if(ts && ts.toggle){
6569             ts.toggle.show();
6570         }
6571     },
6572
6573     /**
6574      * If this Region is {@link #floatable}, and this Region has been slid into floating visibility, then this method slides
6575      * this region back into its collapsed state.
6576      */
6577     slideIn : function(cb){
6578         if(!this.isSlid || this.el.hasActiveFx()){
6579             Ext.callback(cb);
6580             return;
6581         }
6582         this.isSlid = false;
6583         if(this.animFloat !== false){
6584             this.beforeSlide();
6585             this.el.slideOut(this.getSlideAnchor(), {
6586                 callback: function(){
6587                     this.el.hide();
6588                     this.afterSlide();
6589                     this.afterSlideIn();
6590                     Ext.callback(cb);
6591                 },
6592                 scope: this,
6593                 block: true
6594             });
6595         }else{
6596             this.el.hide();
6597             this.afterSlideIn();
6598         }
6599     },
6600
6601     // private
6602     slideInIf : function(e){
6603         if(!e.within(this.el)){
6604             this.slideIn();
6605         }
6606     },
6607
6608     // private
6609     anchors : {
6610         "west" : "left",
6611         "east" : "right",
6612         "north" : "top",
6613         "south" : "bottom"
6614     },
6615
6616     // private
6617     sanchors : {
6618         "west" : "l",
6619         "east" : "r",
6620         "north" : "t",
6621         "south" : "b"
6622     },
6623
6624     // private
6625     canchors : {
6626         "west" : "tl-tr",
6627         "east" : "tr-tl",
6628         "north" : "tl-bl",
6629         "south" : "bl-tl"
6630     },
6631
6632     // private
6633     getAnchor : function(){
6634         return this.anchors[this.position];
6635     },
6636
6637     // private
6638     getCollapseAnchor : function(){
6639         return this.canchors[this.position];
6640     },
6641
6642     // private
6643     getSlideAnchor : function(){
6644         return this.sanchors[this.position];
6645     },
6646
6647     // private
6648     getAlignAdj : function(){
6649         var cm = this.cmargins;
6650         switch(this.position){
6651             case "west":
6652                 return [0, 0];
6653             break;
6654             case "east":
6655                 return [0, 0];
6656             break;
6657             case "north":
6658                 return [0, 0];
6659             break;
6660             case "south":
6661                 return [0, 0];
6662             break;
6663         }
6664     },
6665
6666     // private
6667     getExpandAdj : function(){
6668         var c = this.collapsedEl, cm = this.cmargins;
6669         switch(this.position){
6670             case "west":
6671                 return [-(cm.right+c.getWidth()+cm.left), 0];
6672             break;
6673             case "east":
6674                 return [cm.right+c.getWidth()+cm.left, 0];
6675             break;
6676             case "north":
6677                 return [0, -(cm.top+cm.bottom+c.getHeight())];
6678             break;
6679             case "south":
6680                 return [0, cm.top+cm.bottom+c.getHeight()];
6681             break;
6682         }
6683     },
6684
6685     destroy : function(){
6686         if (this.autoHideSlideTask && this.autoHideSlideTask.cancel){
6687             this.autoHideSlideTask.cancel();
6688         }
6689         Ext.destroy(this.miniCollapsedEl, this.collapsedEl);
6690     }
6691 };
6692
6693 /**
6694  * @class Ext.layout.BorderLayout.SplitRegion
6695  * @extends Ext.layout.BorderLayout.Region
6696  * <p>This is a specialized type of {@link Ext.layout.BorderLayout.Region BorderLayout region} that
6697  * has a built-in {@link Ext.SplitBar} for user resizing of regions.  The movement of the split bar
6698  * is configurable to move either {@link #tickSize smooth or incrementally}.</p>
6699  * @constructor
6700  * Create a new SplitRegion.
6701  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
6702  * @param {Object} config The configuration options
6703  * @param {String} position The region position.  Valid values are: north, south, east, west and center.  Every
6704  * BorderLayout must have a center region for the primary content -- all other regions are optional.
6705  */
6706 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
6707     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
6708     // prevent switch
6709     this.applyLayout = this.applyFns[pos];
6710 };
6711
6712 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
6713     /**
6714      * @cfg {Number} tickSize
6715      * The increment, in pixels by which to move this Region's {@link Ext.SplitBar SplitBar}.
6716      * By default, the {@link Ext.SplitBar SplitBar} moves smoothly.
6717      */
6718     /**
6719      * @cfg {String} splitTip
6720      * The tooltip to display when the user hovers over a
6721      * {@link Ext.layout.BorderLayout.Region#collapsible non-collapsible} region's split bar
6722      * (defaults to <tt>"Drag to resize."</tt>).  Only applies if
6723      * <tt>{@link #useSplitTips} = true</tt>.
6724      */
6725     splitTip : "Drag to resize.",
6726     /**
6727      * @cfg {String} collapsibleSplitTip
6728      * The tooltip to display when the user hovers over a
6729      * {@link Ext.layout.BorderLayout.Region#collapsible collapsible} region's split bar
6730      * (defaults to "Drag to resize. Double click to hide."). Only applies if
6731      * <tt>{@link #useSplitTips} = true</tt>.
6732      */
6733     collapsibleSplitTip : "Drag to resize. Double click to hide.",
6734     /**
6735      * @cfg {Boolean} useSplitTips
6736      * <tt>true</tt> to display a tooltip when the user hovers over a region's split bar
6737      * (defaults to <tt>false</tt>).  The tooltip text will be the value of either
6738      * <tt>{@link #splitTip}</tt> or <tt>{@link #collapsibleSplitTip}</tt> as appropriate.
6739      */
6740     useSplitTips : false,
6741
6742     // private
6743     splitSettings : {
6744         north : {
6745             orientation: Ext.SplitBar.VERTICAL,
6746             placement: Ext.SplitBar.TOP,
6747             maxFn : 'getVMaxSize',
6748             minProp: 'minHeight',
6749             maxProp: 'maxHeight'
6750         },
6751         south : {
6752             orientation: Ext.SplitBar.VERTICAL,
6753             placement: Ext.SplitBar.BOTTOM,
6754             maxFn : 'getVMaxSize',
6755             minProp: 'minHeight',
6756             maxProp: 'maxHeight'
6757         },
6758         east : {
6759             orientation: Ext.SplitBar.HORIZONTAL,
6760             placement: Ext.SplitBar.RIGHT,
6761             maxFn : 'getHMaxSize',
6762             minProp: 'minWidth',
6763             maxProp: 'maxWidth'
6764         },
6765         west : {
6766             orientation: Ext.SplitBar.HORIZONTAL,
6767             placement: Ext.SplitBar.LEFT,
6768             maxFn : 'getHMaxSize',
6769             minProp: 'minWidth',
6770             maxProp: 'maxWidth'
6771         }
6772     },
6773
6774     // private
6775     applyFns : {
6776         west : function(box){
6777             if(this.isCollapsed){
6778                 return this.applyLayoutCollapsed(box);
6779             }
6780             var sd = this.splitEl.dom, s = sd.style;
6781             this.panel.setPosition(box.x, box.y);
6782             var sw = sd.offsetWidth;
6783             s.left = (box.x+box.width-sw)+'px';
6784             s.top = (box.y)+'px';
6785             s.height = Math.max(0, box.height)+'px';
6786             this.panel.setSize(box.width-sw, box.height);
6787         },
6788         east : function(box){
6789             if(this.isCollapsed){
6790                 return this.applyLayoutCollapsed(box);
6791             }
6792             var sd = this.splitEl.dom, s = sd.style;
6793             var sw = sd.offsetWidth;
6794             this.panel.setPosition(box.x+sw, box.y);
6795             s.left = (box.x)+'px';
6796             s.top = (box.y)+'px';
6797             s.height = Math.max(0, box.height)+'px';
6798             this.panel.setSize(box.width-sw, box.height);
6799         },
6800         north : function(box){
6801             if(this.isCollapsed){
6802                 return this.applyLayoutCollapsed(box);
6803             }
6804             var sd = this.splitEl.dom, s = sd.style;
6805             var sh = sd.offsetHeight;
6806             this.panel.setPosition(box.x, box.y);
6807             s.left = (box.x)+'px';
6808             s.top = (box.y+box.height-sh)+'px';
6809             s.width = Math.max(0, box.width)+'px';
6810             this.panel.setSize(box.width, box.height-sh);
6811         },
6812         south : function(box){
6813             if(this.isCollapsed){
6814                 return this.applyLayoutCollapsed(box);
6815             }
6816             var sd = this.splitEl.dom, s = sd.style;
6817             var sh = sd.offsetHeight;
6818             this.panel.setPosition(box.x, box.y+sh);
6819             s.left = (box.x)+'px';
6820             s.top = (box.y)+'px';
6821             s.width = Math.max(0, box.width)+'px';
6822             this.panel.setSize(box.width, box.height-sh);
6823         }
6824     },
6825
6826     // private
6827     render : function(ct, p){
6828         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
6829
6830         var ps = this.position;
6831
6832         this.splitEl = ct.createChild({
6833             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
6834             id: this.panel.id + '-xsplit'
6835         });
6836
6837         if(this.collapseMode == 'mini'){
6838             this.miniSplitEl = this.splitEl.createChild({
6839                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
6840             });
6841             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
6842             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
6843         }
6844
6845         var s = this.splitSettings[ps];
6846
6847         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
6848         this.split.tickSize = this.tickSize;
6849         this.split.placement = s.placement;
6850         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
6851         this.split.minSize = this.minSize || this[s.minProp];
6852         this.split.on("beforeapply", this.onSplitMove, this);
6853         this.split.useShim = this.useShim === true;
6854         this.maxSize = this.maxSize || this[s.maxProp];
6855
6856         if(p.hidden){
6857             this.splitEl.hide();
6858         }
6859
6860         if(this.useSplitTips){
6861             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
6862         }
6863         if(this.collapsible){
6864             this.splitEl.on("dblclick", this.onCollapseClick,  this);
6865         }
6866     },
6867
6868     //docs inherit from superclass
6869     getSize : function(){
6870         if(this.isCollapsed){
6871             return this.collapsedEl.getSize();
6872         }
6873         var s = this.panel.getSize();
6874         if(this.position == 'north' || this.position == 'south'){
6875             s.height += this.splitEl.dom.offsetHeight;
6876         }else{
6877             s.width += this.splitEl.dom.offsetWidth;
6878         }
6879         return s;
6880     },
6881
6882     // private
6883     getHMaxSize : function(){
6884          var cmax = this.maxSize || 10000;
6885          var center = this.layout.center;
6886          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
6887     },
6888
6889     // private
6890     getVMaxSize : function(){
6891         var cmax = this.maxSize || 10000;
6892         var center = this.layout.center;
6893         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
6894     },
6895
6896     // private
6897     onSplitMove : function(split, newSize){
6898         var s = this.panel.getSize();
6899         this.lastSplitSize = newSize;
6900         if(this.position == 'north' || this.position == 'south'){
6901             this.panel.setSize(s.width, newSize);
6902             this.state.height = newSize;
6903         }else{
6904             this.panel.setSize(newSize, s.height);
6905             this.state.width = newSize;
6906         }
6907         this.layout.layout();
6908         this.panel.saveState();
6909         return false;
6910     },
6911
6912     /**
6913      * Returns a reference to the split bar in use by this region.
6914      * @return {Ext.SplitBar} The split bar
6915      */
6916     getSplitBar : function(){
6917         return this.split;
6918     },
6919
6920     // inherit docs
6921     destroy : function() {
6922         Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
6923         Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
6924     }
6925 });
6926
6927 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;/**
6928  * @class Ext.layout.FormLayout
6929  * @extends Ext.layout.AnchorLayout
6930  * <p>This layout manager is specifically designed for rendering and managing child Components of
6931  * {@link Ext.form.FormPanel forms}. It is responsible for rendering the labels of
6932  * {@link Ext.form.Field Field}s.</p>
6933  *
6934  * <p>This layout manager is used when a Container is configured with the <tt>layout:'form'</tt>
6935  * {@link Ext.Container#layout layout} config option, and should generally not need to be created directly
6936  * via the new keyword. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
6937  *
6938  * <p>In an application, it will usually be preferrable to use a {@link Ext.form.FormPanel FormPanel}
6939  * (which is configured with FormLayout as its layout class by default) since it also provides built-in
6940  * functionality for {@link Ext.form.BasicForm#doAction loading, validating and submitting} the form.</p>
6941  *
6942  * <p>A {@link Ext.Container Container} <i>using</i> the FormLayout layout manager (e.g.
6943  * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) can also accept the following
6944  * layout-specific config properties:<div class="mdetail-params"><ul>
6945  * <li><b><tt>{@link Ext.form.FormPanel#hideLabels hideLabels}</tt></b></li>
6946  * <li><b><tt>{@link Ext.form.FormPanel#labelAlign labelAlign}</tt></b></li>
6947  * <li><b><tt>{@link Ext.form.FormPanel#labelPad labelPad}</tt></b></li>
6948  * <li><b><tt>{@link Ext.form.FormPanel#labelSeparator labelSeparator}</tt></b></li>
6949  * <li><b><tt>{@link Ext.form.FormPanel#labelWidth labelWidth}</tt></b></li>
6950  * </ul></div></p>
6951  *
6952  * <p>Any Component (including Fields) managed by FormLayout accepts the following as a config option:
6953  * <div class="mdetail-params"><ul>
6954  * <li><b><tt>{@link Ext.Component#anchor anchor}</tt></b></li>
6955  * </ul></div></p>
6956  *
6957  * <p>Any Component managed by FormLayout may be rendered as a form field (with an associated label) by
6958  * configuring it with a non-null <b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b>. Components configured
6959  * in this way may be configured with the following options which affect the way the FormLayout renders them:
6960  * <div class="mdetail-params"><ul>
6961  * <li><b><tt>{@link Ext.Component#clearCls clearCls}</tt></b></li>
6962  * <li><b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b></li>
6963  * <li><b><tt>{@link Ext.Component#hideLabel hideLabel}</tt></b></li>
6964  * <li><b><tt>{@link Ext.Component#itemCls itemCls}</tt></b></li>
6965  * <li><b><tt>{@link Ext.Component#labelSeparator labelSeparator}</tt></b></li>
6966  * <li><b><tt>{@link Ext.Component#labelStyle labelStyle}</tt></b></li>
6967  * </ul></div></p>
6968  *
6969  * <p>Example usage:</p>
6970  * <pre><code>
6971 // Required if showing validation messages
6972 Ext.QuickTips.init();
6973
6974 // While you can create a basic Panel with layout:'form', practically
6975 // you should usually use a FormPanel to also get its form functionality
6976 // since it already creates a FormLayout internally.
6977 var form = new Ext.form.FormPanel({
6978     title: 'Form Layout',
6979     bodyStyle: 'padding:15px',
6980     width: 350,
6981     defaultType: 'textfield',
6982     defaults: {
6983         // applied to each contained item
6984         width: 230,
6985         msgTarget: 'side'
6986     },
6987     items: [{
6988             fieldLabel: 'First Name',
6989             name: 'first',
6990             allowBlank: false,
6991             {@link Ext.Component#labelSeparator labelSeparator}: ':' // override labelSeparator layout config
6992         },{
6993             fieldLabel: 'Last Name',
6994             name: 'last'
6995         },{
6996             fieldLabel: 'Email',
6997             name: 'email',
6998             vtype:'email'
6999         }, {
7000             xtype: 'textarea',
7001             hideLabel: true,     // override hideLabels layout config
7002             name: 'msg',
7003             anchor: '100% -53'
7004         }
7005     ],
7006     buttons: [
7007         {text: 'Save'},
7008         {text: 'Cancel'}
7009     ],
7010     layoutConfig: {
7011         {@link #labelSeparator}: '~' // superseded by assignment below
7012     },
7013     // config options applicable to container when layout='form':
7014     hideLabels: false,
7015     labelAlign: 'left',   // or 'right' or 'top'
7016     {@link Ext.form.FormPanel#labelSeparator labelSeparator}: '>>', // takes precedence over layoutConfig value
7017     labelWidth: 65,       // defaults to 100
7018     labelPad: 8           // defaults to 5, must specify labelWidth to be honored
7019 });
7020 </code></pre>
7021  */
7022 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
7023
7024     /**
7025      * @cfg {String} labelSeparator
7026      * See {@link Ext.form.FormPanel}.{@link Ext.form.FormPanel#labelSeparator labelSeparator}.  Configuration
7027      * of this property at the <b>container</b> level takes precedence.
7028      */
7029     labelSeparator : ':',
7030
7031     /**
7032      * Read only. The CSS style specification string added to field labels in this layout if not
7033      * otherwise {@link Ext.Component#labelStyle specified by each contained field}.
7034      * @type String
7035      * @property labelStyle
7036      */
7037
7038     /**
7039      * @cfg {Boolean} trackLabels
7040      * True to show/hide the field label when the field is hidden. Defaults to <tt>false</tt>.
7041      */
7042     trackLabels: false,
7043
7044     type: 'form',
7045
7046     onRemove: function(c){
7047         Ext.layout.FormLayout.superclass.onRemove.call(this, c);
7048         if(this.trackLabels){
7049             c.un('show', this.onFieldShow, this);
7050             c.un('hide', this.onFieldHide, this);
7051         }
7052         // check for itemCt, since we may be removing a fieldset or something similar
7053         var el = c.getPositionEl(),
7054             ct = c.getItemCt && c.getItemCt();
7055         if (c.rendered && ct) {
7056             if (el && el.dom) {
7057                 el.insertAfter(ct);
7058             }
7059             Ext.destroy(ct);
7060             Ext.destroyMembers(c, 'label', 'itemCt');
7061             if (c.customItemCt) {
7062                 Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
7063             }
7064         }
7065     },
7066
7067     // private
7068     setContainer : function(ct){
7069         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
7070         if(ct.labelAlign){
7071             ct.addClass('x-form-label-'+ct.labelAlign);
7072         }
7073
7074         if(ct.hideLabels){
7075             Ext.apply(this, {
7076                 labelStyle: 'display:none',
7077                 elementStyle: 'padding-left:0;',
7078                 labelAdjust: 0
7079             });
7080         }else{
7081             this.labelSeparator = ct.labelSeparator || this.labelSeparator;
7082             ct.labelWidth = ct.labelWidth || 100;
7083             if(Ext.isNumber(ct.labelWidth)){
7084                 var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
7085                 Ext.apply(this, {
7086                     labelAdjust: ct.labelWidth + pad,
7087                     labelStyle: 'width:' + ct.labelWidth + 'px;',
7088                     elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
7089                 });
7090             }
7091             if(ct.labelAlign == 'top'){
7092                 Ext.apply(this, {
7093                     labelStyle: 'width:auto;',
7094                     labelAdjust: 0,
7095                     elementStyle: 'padding-left:0;'
7096                 });
7097             }
7098         }
7099     },
7100
7101     // private
7102     isHide: function(c){
7103         return c.hideLabel || this.container.hideLabels;
7104     },
7105
7106     onFieldShow: function(c){
7107         c.getItemCt().removeClass('x-hide-' + c.hideMode);
7108
7109         // Composite fields will need to layout after the container is made visible
7110         if (c.isComposite) {
7111             c.doLayout();
7112         }
7113     },
7114
7115     onFieldHide: function(c){
7116         c.getItemCt().addClass('x-hide-' + c.hideMode);
7117     },
7118
7119     //private
7120     getLabelStyle: function(s){
7121         var ls = '', items = [this.labelStyle, s];
7122         for (var i = 0, len = items.length; i < len; ++i){
7123             if (items[i]){
7124                 ls += items[i];
7125                 if (ls.substr(-1, 1) != ';'){
7126                     ls += ';';
7127                 }
7128             }
7129         }
7130         return ls;
7131     },
7132
7133     /**
7134      * @cfg {Ext.Template} fieldTpl
7135      * A {@link Ext.Template#compile compile}d {@link Ext.Template} for rendering
7136      * the fully wrapped, labeled and styled form Field. Defaults to:</p><pre><code>
7137 new Ext.Template(
7138     &#39;&lt;div class="x-form-item {itemCls}" tabIndex="-1">&#39;,
7139         &#39;&lt;&#108;abel for="{id}" style="{labelStyle}" class="x-form-item-&#108;abel">{&#108;abel}{labelSeparator}&lt;/&#108;abel>&#39;,
7140         &#39;&lt;div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">&#39;,
7141         &#39;&lt;/div>&lt;div class="{clearCls}">&lt;/div>&#39;,
7142     '&lt;/div>'
7143 );
7144 </code></pre>
7145      * <p>This may be specified to produce a different DOM structure when rendering form Fields.</p>
7146      * <p>A description of the properties within the template follows:</p><div class="mdetail-params"><ul>
7147      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
7148      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
7149      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
7150      * supplied at the container level.</div></li>
7151      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
7152      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
7153      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
7154      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
7155      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
7156      * field (defaults to <tt>''</tt>)</div></li>
7157      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
7158      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
7159      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
7160      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
7161      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
7162      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
7163      * </ul></div>
7164      * <p>Also see <tt>{@link #getTemplateArgs}</tt></p>
7165      */
7166
7167     /**
7168      * @private
7169      *
7170      */
7171     renderItem : function(c, position, target){
7172         if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
7173             var args = this.getTemplateArgs(c);
7174             if(Ext.isNumber(position)){
7175                 position = target.dom.childNodes[position] || null;
7176             }
7177             if(position){
7178                 c.itemCt = this.fieldTpl.insertBefore(position, args, true);
7179             }else{
7180                 c.itemCt = this.fieldTpl.append(target, args, true);
7181             }
7182             if(!c.getItemCt){
7183                 // Non form fields don't have getItemCt, apply it here
7184                 // This will get cleaned up in onRemove
7185                 Ext.apply(c, {
7186                     getItemCt: function(){
7187                         return c.itemCt;
7188                     },
7189                     customItemCt: true
7190                 });
7191             }
7192             c.label = c.getItemCt().child('label.x-form-item-label');
7193             if(!c.rendered){
7194                 c.render('x-form-el-' + c.id);
7195             }else if(!this.isValidParent(c, target)){
7196                 Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
7197             }
7198             if(this.trackLabels){
7199                 if(c.hidden){
7200                     this.onFieldHide(c);
7201                 }
7202                 c.on({
7203                     scope: this,
7204                     show: this.onFieldShow,
7205                     hide: this.onFieldHide
7206                 });
7207             }
7208             this.configureItem(c);
7209         }else {
7210             Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
7211         }
7212     },
7213
7214     /**
7215      * <p>Provides template arguments for rendering the fully wrapped, labeled and styled form Field.</p>
7216      * <p>This method returns an object hash containing properties used by the layout's {@link #fieldTpl}
7217      * to create a correctly wrapped, labeled and styled form Field. This may be overriden to
7218      * create custom layouts. The properties which must be returned are:</p><div class="mdetail-params"><ul>
7219      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
7220      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
7221      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
7222      * supplied at the container level.</div></li>
7223      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
7224      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
7225      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
7226      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
7227      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
7228      * field (defaults to the field's configured fieldLabel property)</div></li>
7229      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
7230      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
7231      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
7232      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
7233      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
7234      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
7235      * </ul></div>
7236      * @param (Ext.form.Field} field The {@link Ext.form.Field Field} being rendered.
7237      * @return {Object} An object hash containing the properties required to render the Field.
7238      */
7239     getTemplateArgs: function(field) {
7240         var noLabelSep = !field.fieldLabel || field.hideLabel;
7241
7242         return {
7243             id            : field.id,
7244             label         : field.fieldLabel,
7245             itemCls       : (field.itemCls || this.container.itemCls || '') + (field.hideLabel ? ' x-hide-label' : ''),
7246             clearCls      : field.clearCls || 'x-form-clear-left',
7247             labelStyle    : this.getLabelStyle(field.labelStyle),
7248             elementStyle  : this.elementStyle || '',
7249             labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator)
7250         };
7251     },
7252
7253     // private
7254     adjustWidthAnchor: function(value, c){
7255         if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){
7256             var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
7257             return value - this.labelAdjust + (adjust ? -3 : 0);
7258         }
7259         return value;
7260     },
7261
7262     adjustHeightAnchor : function(value, c){
7263         if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
7264             return value - c.label.getHeight();
7265         }
7266         return value;
7267     },
7268
7269     // private
7270     isValidParent : function(c, target){
7271         return target && this.container.getEl().contains(c.getPositionEl());
7272     }
7273
7274     /**
7275      * @property activeItem
7276      * @hide
7277      */
7278 });
7279
7280 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
7281 /**
7282  * @class Ext.layout.AccordionLayout
7283  * @extends Ext.layout.FitLayout
7284  * <p>This is a layout that manages multiple Panels in an expandable accordion style such that only
7285  * <b>one Panel can be expanded at any given time</b>. Each Panel has built-in support for expanding and collapsing.</p>
7286  * <p>Note: Only Ext.Panels <b>and all subclasses of Ext.Panel</b> may be used in an accordion layout Container.</p>
7287  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
7288  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
7289  * <p>Example usage:</p>
7290  * <pre><code>
7291 var accordion = new Ext.Panel({
7292     title: 'Accordion Layout',
7293     layout:'accordion',
7294     defaults: {
7295         // applied to each contained panel
7296         bodyStyle: 'padding:15px'
7297     },
7298     layoutConfig: {
7299         // layout-specific configs go here
7300         titleCollapse: false,
7301         animate: true,
7302         activeOnTop: true
7303     },
7304     items: [{
7305         title: 'Panel 1',
7306         html: '&lt;p&gt;Panel content!&lt;/p&gt;'
7307     },{
7308         title: 'Panel 2',
7309         html: '&lt;p&gt;Panel content!&lt;/p&gt;'
7310     },{
7311         title: 'Panel 3',
7312         html: '&lt;p&gt;Panel content!&lt;/p&gt;'
7313     }]
7314 });
7315 </code></pre>
7316  */
7317 Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
7318     /**
7319      * @cfg {Boolean} fill
7320      * True to adjust the active item's height to fill the available space in the container, false to use the
7321      * item's current height, or auto height if not explicitly set (defaults to true).
7322      */
7323     fill : true,
7324     /**
7325      * @cfg {Boolean} autoWidth
7326      * True to set each contained item's width to 'auto', false to use the item's current width (defaults to true).
7327      * Note that some components, in particular the {@link Ext.grid.GridPanel grid}, will not function properly within
7328      * layouts if they have auto width, so in such cases this config should be set to false.
7329      */
7330     autoWidth : true,
7331     /**
7332      * @cfg {Boolean} titleCollapse
7333      * True to allow expand/collapse of each contained panel by clicking anywhere on the title bar, false to allow
7334      * expand/collapse only when the toggle tool button is clicked (defaults to true).  When set to false,
7335      * {@link #hideCollapseTool} should be false also.
7336      */
7337     titleCollapse : true,
7338     /**
7339      * @cfg {Boolean} hideCollapseTool
7340      * True to hide the contained panels' collapse/expand toggle buttons, false to display them (defaults to false).
7341      * When set to true, {@link #titleCollapse} should be true also.
7342      */
7343     hideCollapseTool : false,
7344     /**
7345      * @cfg {Boolean} collapseFirst
7346      * True to make sure the collapse/expand toggle button always renders first (to the left of) any other tools
7347      * in the contained panels' title bars, false to render it last (defaults to false).
7348      */
7349     collapseFirst : false,
7350     /**
7351      * @cfg {Boolean} animate
7352      * True to slide the contained panels open and closed during expand/collapse using animation, false to open and
7353      * close directly with no animation (defaults to false).  Note: to defer to the specific config setting of each
7354      * contained panel for this property, set this to undefined at the layout level.
7355      */
7356     animate : false,
7357     /**
7358      * @cfg {Boolean} sequence
7359      * <b>Experimental</b>. If animate is set to true, this will result in each animation running in sequence.
7360      */
7361     sequence : false,
7362     /**
7363      * @cfg {Boolean} activeOnTop
7364      * True to swap the position of each panel as it is expanded so that it becomes the first item in the container,
7365      * false to keep the panels in the rendered order. <b>This is NOT compatible with "animate:true"</b> (defaults to false).
7366      */
7367     activeOnTop : false,
7368
7369     type: 'accordion',
7370
7371     renderItem : function(c){
7372         if(this.animate === false){
7373             c.animCollapse = false;
7374         }
7375         c.collapsible = true;
7376         if(this.autoWidth){
7377             c.autoWidth = true;
7378         }
7379         if(this.titleCollapse){
7380             c.titleCollapse = true;
7381         }
7382         if(this.hideCollapseTool){
7383             c.hideCollapseTool = true;
7384         }
7385         if(this.collapseFirst !== undefined){
7386             c.collapseFirst = this.collapseFirst;
7387         }
7388         if(!this.activeItem && !c.collapsed){
7389             this.setActiveItem(c, true);
7390         }else if(this.activeItem && this.activeItem != c){
7391             c.collapsed = true;
7392         }
7393         Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
7394         c.header.addClass('x-accordion-hd');
7395         c.on('beforeexpand', this.beforeExpand, this);
7396     },
7397
7398     onRemove: function(c){
7399         Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
7400         if(c.rendered){
7401             c.header.removeClass('x-accordion-hd');
7402         }
7403         c.un('beforeexpand', this.beforeExpand, this);
7404     },
7405
7406     // private
7407     beforeExpand : function(p, anim){
7408         var ai = this.activeItem;
7409         if(ai){
7410             if(this.sequence){
7411                 delete this.activeItem;
7412                 if (!ai.collapsed){
7413                     ai.collapse({callback:function(){
7414                         p.expand(anim || true);
7415                     }, scope: this});
7416                     return false;
7417                 }
7418             }else{
7419                 ai.collapse(this.animate);
7420             }
7421         }
7422         this.setActive(p);
7423         if(this.activeOnTop){
7424             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
7425         }
7426         // Items have been hidden an possibly rearranged, we need to get the container size again.
7427         this.layout();
7428     },
7429
7430     // private
7431     setItemSize : function(item, size){
7432         if(this.fill && item){
7433             var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;
7434             // Add up all the header heights
7435             for (i = 0; i < len; i++) {
7436                 if((p = ct[i]) != item && !p.hidden){
7437                     hh += p.header.getHeight();
7438                 }
7439             };
7440             // Subtract the header heights from the container size
7441             size.height -= hh;
7442             // Call setSize on the container to set the correct height.  For Panels, deferedHeight
7443             // will simply store this size for when the expansion is done.
7444             item.setSize(size);
7445         }
7446     },
7447
7448     /**
7449      * Sets the active (expanded) item in the layout.
7450      * @param {String/Number} item The string component id or numeric index of the item to activate
7451      */
7452     setActiveItem : function(item){
7453         this.setActive(item, true);
7454     },
7455
7456     // private
7457     setActive : function(item, expand){
7458         var ai = this.activeItem;
7459         item = this.container.getComponent(item);
7460         if(ai != item){
7461             if(item.rendered && item.collapsed && expand){
7462                 item.expand();
7463             }else{
7464                 if(ai){
7465                    ai.fireEvent('deactivate', ai);
7466                 }
7467                 this.activeItem = item;
7468                 item.fireEvent('activate', item);
7469             }
7470         }
7471     }
7472 });
7473 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
7474
7475 //backwards compat
7476 Ext.layout.Accordion = Ext.layout.AccordionLayout;/**
7477  * @class Ext.layout.TableLayout
7478  * @extends Ext.layout.ContainerLayout
7479  * <p>This layout allows you to easily render content into an HTML table.  The total number of columns can be
7480  * specified, and rowspan and colspan can be used to create complex layouts within the table.
7481  * This class is intended to be extended or created via the layout:'table' {@link Ext.Container#layout} config,
7482  * and should generally not need to be created directly via the new keyword.</p>
7483  * <p>Note that when creating a layout via config, the layout-specific config properties must be passed in via
7484  * the {@link Ext.Container#layoutConfig} object which will then be applied internally to the layout.  In the
7485  * case of TableLayout, the only valid layout config property is {@link #columns}.  However, the items added to a
7486  * TableLayout can supply the following table-specific config properties:</p>
7487  * <ul>
7488  * <li><b>rowspan</b> Applied to the table cell containing the item.</li>
7489  * <li><b>colspan</b> Applied to the table cell containing the item.</li>
7490  * <li><b>cellId</b> An id applied to the table cell containing the item.</li>
7491  * <li><b>cellCls</b> A CSS class name added to the table cell containing the item.</li>
7492  * </ul>
7493  * <p>The basic concept of building up a TableLayout is conceptually very similar to building up a standard
7494  * HTML table.  You simply add each panel (or "cell") that you want to include along with any span attributes
7495  * specified as the special config properties of rowspan and colspan which work exactly like their HTML counterparts.
7496  * Rather than explicitly creating and nesting rows and columns as you would in HTML, you simply specify the
7497  * total column count in the layoutConfig and start adding panels in their natural order from left to right,
7498  * top to bottom.  The layout will automatically figure out, based on the column count, rowspans and colspans,
7499  * how to position each panel within the table.  Just like with HTML tables, your rowspans and colspans must add
7500  * up correctly in your overall layout or you'll end up with missing and/or extra cells!  Example usage:</p>
7501  * <pre><code>
7502 // This code will generate a layout table that is 3 columns by 2 rows
7503 // with some spanning included.  The basic layout will be:
7504 // +--------+-----------------+
7505 // |   A    |   B             |
7506 // |        |--------+--------|
7507 // |        |   C    |   D    |
7508 // +--------+--------+--------+
7509 var table = new Ext.Panel({
7510     title: 'Table Layout',
7511     layout:'table',
7512     defaults: {
7513         // applied to each contained panel
7514         bodyStyle:'padding:20px'
7515     },
7516     layoutConfig: {
7517         // The total column count must be specified here
7518         columns: 3
7519     },
7520     items: [{
7521         html: '&lt;p&gt;Cell A content&lt;/p&gt;',
7522         rowspan: 2
7523     },{
7524         html: '&lt;p&gt;Cell B content&lt;/p&gt;',
7525         colspan: 2
7526     },{
7527         html: '&lt;p&gt;Cell C content&lt;/p&gt;',
7528         cellCls: 'highlight'
7529     },{
7530         html: '&lt;p&gt;Cell D content&lt;/p&gt;'
7531     }]
7532 });
7533 </code></pre>
7534  */
7535 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
7536     /**
7537      * @cfg {Number} columns
7538      * The total number of columns to create in the table for this layout.  If not specified, all Components added to
7539      * this layout will be rendered into a single row using one column per Component.
7540      */
7541
7542     // private
7543     monitorResize:false,
7544
7545     type: 'table',
7546
7547     targetCls: 'x-table-layout-ct',
7548
7549     /**
7550      * @cfg {Object} tableAttrs
7551      * <p>An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification
7552      * used to create the layout's <tt>&lt;table&gt;</tt> element. Example:</p><pre><code>
7553 {
7554     xtype: 'panel',
7555     layout: 'table',
7556     layoutConfig: {
7557         tableAttrs: {
7558             style: {
7559                 width: '100%'
7560             }
7561         },
7562         columns: 3
7563     }
7564 }</code></pre>
7565      */
7566     tableAttrs:null,
7567
7568     // private
7569     setContainer : function(ct){
7570         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
7571
7572         this.currentRow = 0;
7573         this.currentColumn = 0;
7574         this.cells = [];
7575     },
7576     
7577     // private
7578     onLayout : function(ct, target){
7579         var cs = ct.items.items, len = cs.length, c, i;
7580
7581         if(!this.table){
7582             target.addClass('x-table-layout-ct');
7583
7584             this.table = target.createChild(
7585                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
7586         }
7587         this.renderAll(ct, target);
7588     },
7589
7590     // private
7591     getRow : function(index){
7592         var row = this.table.tBodies[0].childNodes[index];
7593         if(!row){
7594             row = document.createElement('tr');
7595             this.table.tBodies[0].appendChild(row);
7596         }
7597         return row;
7598     },
7599
7600     // private
7601     getNextCell : function(c){
7602         var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
7603         var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
7604         for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
7605             if(!this.cells[rowIndex]){
7606                 this.cells[rowIndex] = [];
7607             }
7608             for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
7609                 this.cells[rowIndex][colIndex] = true;
7610             }
7611         }
7612         var td = document.createElement('td');
7613         if(c.cellId){
7614             td.id = c.cellId;
7615         }
7616         var cls = 'x-table-layout-cell';
7617         if(c.cellCls){
7618             cls += ' ' + c.cellCls;
7619         }
7620         td.className = cls;
7621         if(c.colspan){
7622             td.colSpan = c.colspan;
7623         }
7624         if(c.rowspan){
7625             td.rowSpan = c.rowspan;
7626         }
7627         this.getRow(curRow).appendChild(td);
7628         return td;
7629     },
7630
7631     // private
7632     getNextNonSpan: function(colIndex, rowIndex){
7633         var cols = this.columns;
7634         while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
7635             if(cols && colIndex >= cols){
7636                 rowIndex++;
7637                 colIndex = 0;
7638             }else{
7639                 colIndex++;
7640             }
7641         }
7642         return [colIndex, rowIndex];
7643     },
7644
7645     // private
7646     renderItem : function(c, position, target){
7647         // Ensure we have our inner table to get cells to render into.
7648         if(!this.table){
7649             this.table = target.createChild(
7650                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
7651         }
7652         if(c && !c.rendered){
7653             c.render(this.getNextCell(c));
7654             this.configureItem(c, position);
7655         }else if(c && !this.isValidParent(c, target)){
7656             var container = this.getNextCell(c);
7657             container.insertBefore(c.getPositionEl().dom, null);
7658             c.container = Ext.get(container);
7659             this.configureItem(c, position);
7660         }
7661     },
7662
7663     // private
7664     isValidParent : function(c, target){
7665         return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);
7666     }
7667
7668     /**
7669      * @property activeItem
7670      * @hide
7671      */
7672 });
7673
7674 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;/**
7675  * @class Ext.layout.AbsoluteLayout
7676  * @extends Ext.layout.AnchorLayout
7677  * <p>This is a layout that inherits the anchoring of <b>{@link Ext.layout.AnchorLayout}</b> and adds the
7678  * ability for x/y positioning using the standard x and y component config options.</p>
7679  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
7680  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
7681  * <p>Example usage:</p>
7682  * <pre><code>
7683 var form = new Ext.form.FormPanel({
7684     title: 'Absolute Layout',
7685     layout:'absolute',
7686     layoutConfig: {
7687         // layout-specific configs go here
7688         extraCls: 'x-abs-layout-item',
7689     },
7690     baseCls: 'x-plain',
7691     url:'save-form.php',
7692     defaultType: 'textfield',
7693     items: [{
7694         x: 0,
7695         y: 5,
7696         xtype:'label',
7697         text: 'Send To:'
7698     },{
7699         x: 60,
7700         y: 0,
7701         name: 'to',
7702         anchor:'100%'  // anchor width by percentage
7703     },{
7704         x: 0,
7705         y: 35,
7706         xtype:'label',
7707         text: 'Subject:'
7708     },{
7709         x: 60,
7710         y: 30,
7711         name: 'subject',
7712         anchor: '100%'  // anchor width by percentage
7713     },{
7714         x:0,
7715         y: 60,
7716         xtype: 'textarea',
7717         name: 'msg',
7718         anchor: '100% 100%'  // anchor width and height
7719     }]
7720 });
7721 </code></pre>
7722  */
7723 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
7724
7725     extraCls: 'x-abs-layout-item',
7726
7727     type: 'absolute',
7728
7729     onLayout : function(ct, target){
7730         target.position();
7731         this.paddingLeft = target.getPadding('l');
7732         this.paddingTop = target.getPadding('t');
7733         Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
7734     },
7735
7736     // private
7737     adjustWidthAnchor : function(value, comp){
7738         return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
7739     },
7740
7741     // private
7742     adjustHeightAnchor : function(value, comp){
7743         return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
7744     }
7745     /**
7746      * @property activeItem
7747      * @hide
7748      */
7749 });
7750 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
7751 /**
7752  * @class Ext.layout.BoxLayout
7753  * @extends Ext.layout.ContainerLayout
7754  * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
7755  */
7756 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
7757     /**
7758      * @cfg {Object} defaultMargins
7759      * <p>If the individual contained items do not have a <tt>margins</tt>
7760      * property specified, the default margins from this property will be
7761      * applied to each item.</p>
7762      * <br><p>This property may be specified as an object containing margins
7763      * to apply in the format:</p><pre><code>
7764 {
7765     top: (top margin),
7766     right: (right margin),
7767     bottom: (bottom margin),
7768     left: (left margin)
7769 }</code></pre>
7770      * <p>This property may also be specified as a string containing
7771      * space-separated, numeric margin values. The order of the sides associated
7772      * with each value matches the way CSS processes margin values:</p>
7773      * <div class="mdetail-params"><ul>
7774      * <li>If there is only one value, it applies to all sides.</li>
7775      * <li>If there are two values, the top and bottom borders are set to the
7776      * first value and the right and left are set to the second.</li>
7777      * <li>If there are three values, the top is set to the first value, the left
7778      * and right are set to the second, and the bottom is set to the third.</li>
7779      * <li>If there are four values, they apply to the top, right, bottom, and
7780      * left, respectively.</li>
7781      * </ul></div>
7782      * <p>Defaults to:</p><pre><code>
7783      * {top:0, right:0, bottom:0, left:0}
7784      * </code></pre>
7785      */
7786     defaultMargins : {left:0,top:0,right:0,bottom:0},
7787     /**
7788      * @cfg {String} padding
7789      * <p>Sets the padding to be applied to all child items managed by this layout.</p>
7790      * <p>This property must be specified as a string containing
7791      * space-separated, numeric padding values. The order of the sides associated
7792      * with each value matches the way CSS processes padding values:</p>
7793      * <div class="mdetail-params"><ul>
7794      * <li>If there is only one value, it applies to all sides.</li>
7795      * <li>If there are two values, the top and bottom borders are set to the
7796      * first value and the right and left are set to the second.</li>
7797      * <li>If there are three values, the top is set to the first value, the left
7798      * and right are set to the second, and the bottom is set to the third.</li>
7799      * <li>If there are four values, they apply to the top, right, bottom, and
7800      * left, respectively.</li>
7801      * </ul></div>
7802      * <p>Defaults to: <code>"0"</code></p>
7803      */
7804     padding : '0',
7805     // documented in subclasses
7806     pack : 'start',
7807
7808     // private
7809     monitorResize : true,
7810     type: 'box',
7811     scrollOffset : 0,
7812     extraCls : 'x-box-item',
7813     targetCls : 'x-box-layout-ct',
7814     innerCls : 'x-box-inner',
7815
7816     constructor : function(config){
7817         Ext.layout.BoxLayout.superclass.constructor.call(this, config);
7818
7819         if (Ext.isString(this.defaultMargins)) {
7820             this.defaultMargins = this.parseMargins(this.defaultMargins);
7821         }
7822     },
7823
7824     /**
7825      * @private
7826      * Runs the child box calculations and caches them in childBoxCache. Subclasses can used these cached values
7827      * when laying out
7828      */
7829     onLayout: function(container, target) {
7830         Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);
7831
7832         var items = this.getVisibleItems(container),
7833             tSize = this.getLayoutTargetSize();
7834
7835         /**
7836          * @private
7837          * @property layoutTargetLastSize
7838          * @type Object
7839          * Private cache of the last measured size of the layout target. This should never be used except by
7840          * BoxLayout subclasses during their onLayout run.
7841          */
7842         this.layoutTargetLastSize = tSize;
7843
7844         /**
7845          * @private
7846          * @property childBoxCache
7847          * @type Array
7848          * Array of the last calculated height, width, top and left positions of each visible rendered component
7849          * within the Box layout.
7850          */
7851         this.childBoxCache = this.calculateChildBoxes(items, tSize);
7852
7853         this.updateInnerCtSize(tSize, this.childBoxCache);
7854         this.updateChildBoxes(this.childBoxCache.boxes);
7855
7856         // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
7857         this.handleTargetOverflow(tSize, container, target);
7858     },
7859
7860     /**
7861      * Resizes and repositions each child component
7862      * @param {Array} boxes The box measurements
7863      */
7864     updateChildBoxes: function(boxes) {
7865         for (var i = 0, length = boxes.length; i < length; i++) {
7866             var box  = boxes[i],
7867                 comp = box.component;
7868
7869             if (box.dirtySize) {
7870                 comp.setSize(box.width, box.height);
7871             }
7872             // Don't set positions to NaN
7873             if (isNaN(box.left) || isNaN(box.top)) {
7874                 continue;
7875             }
7876             comp.setPosition(box.left, box.top);
7877         }
7878     },
7879
7880     /**
7881      * @private
7882      * Called by onRender just before the child components are sized and positioned. This resizes the innerCt
7883      * to make sure all child items fit within it. We call this before sizing the children because if our child
7884      * items are larger than the previous innerCt size the browser will insert scrollbars and then remove them
7885      * again immediately afterwards, giving a performance hit.
7886      * Subclasses should provide an implementation.
7887      * @param {Object} currentSize The current height and width of the innerCt
7888      * @param {Array} calculations The new box calculations of all items to be laid out
7889      */
7890     updateInnerCtSize: Ext.emptyFn,
7891
7892     /**
7893      * @private
7894      * This should be called after onLayout of any BoxLayout subclass. If the target's overflow is not set to 'hidden',
7895      * we need to lay out a second time because the scrollbars may have modified the height and width of the layout
7896      * target. Having a Box layout inside such a target is therefore not recommended.
7897      * @param {Object} previousTargetSize The size and height of the layout target before we just laid out
7898      * @param {Ext.Container} container The container
7899      * @param {Ext.Element} target The target element
7900      */
7901     handleTargetOverflow: function(previousTargetSize, container, target) {
7902         var overflow = target.getStyle('overflow');
7903
7904         if (overflow && overflow != 'hidden' &&!this.adjustmentPass) {
7905             var newTargetSize = this.getLayoutTargetSize();
7906             if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){
7907                 this.adjustmentPass = true;
7908                 this.onLayout(container, target);
7909             }
7910         }
7911
7912         delete this.adjustmentPass;
7913     },
7914
7915     // private
7916     isValidParent : function(c, target){
7917         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
7918     },
7919
7920     /**
7921      * @private
7922      * Returns all items that are both rendered and visible
7923      * @return {Array} All matching items
7924      */
7925     getVisibleItems: function(ct) {
7926         var ct  = ct || this.container,
7927             t   = ct.getLayoutTarget(),
7928             cti = ct.items.items,
7929             len = cti.length,
7930
7931             i, c, items = [];
7932
7933         for (i = 0; i < len; i++) {
7934             if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true  && c.collapsed !== true){
7935                 items.push(c);
7936             }
7937         }
7938
7939         return items;
7940     },
7941
7942     // private
7943     renderAll : function(ct, target){
7944         if(!this.innerCt){
7945             // the innerCt prevents wrapping and shuffling while
7946             // the container is resizing
7947             this.innerCt = target.createChild({cls:this.innerCls});
7948             this.padding = this.parseMargins(this.padding);
7949         }
7950         Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
7951     },
7952
7953     getLayoutTargetSize : function(){
7954         var target = this.container.getLayoutTarget(), ret;
7955         if (target) {
7956             ret = target.getViewSize();
7957
7958             // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
7959             // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
7960             // with getViewSize
7961             if (Ext.isIE && Ext.isStrict && ret.width == 0){
7962                 ret =  target.getStyleSize();
7963             }
7964
7965             ret.width -= target.getPadding('lr');
7966             ret.height -= target.getPadding('tb');
7967         }
7968         return ret;
7969     },
7970
7971     // private
7972     renderItem : function(c){
7973         if(Ext.isString(c.margins)){
7974             c.margins = this.parseMargins(c.margins);
7975         }else if(!c.margins){
7976             c.margins = this.defaultMargins;
7977         }
7978         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
7979     }
7980 });
7981
7982 /**
7983  * @class Ext.layout.VBoxLayout
7984  * @extends Ext.layout.BoxLayout
7985  * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical
7986  * space between child items containing a numeric <code>flex</code> configuration.</p>
7987  * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option.
7988  */
7989 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
7990     /**
7991      * @cfg {String} align
7992      * Controls how the child items of the container are aligned. Acceptable configuration values for this
7993      * property are:
7994      * <div class="mdetail-params"><ul>
7995      * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally
7996      * at the <b>left</b> side of the container</div></li>
7997      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the
7998      * <b>mid-width</b> of the container</div></li>
7999      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill
8000      * the width of the container</div></li>
8001      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to
8002      * the size of the largest item.</div></li>
8003      * </ul></div>
8004      */
8005     align : 'left', // left, center, stretch, strechmax
8006     type: 'vbox',
8007
8008     /**
8009      * @cfg {String} pack
8010      * Controls how the child items of the container are packed together. Acceptable configuration values
8011      * for this property are:
8012      * <div class="mdetail-params"><ul>
8013      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
8014      * <b>top</b> side of container</div></li>
8015      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
8016      * <b>mid-height</b> of container</div></li>
8017      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>
8018      * side of container</div></li>
8019      * </ul></div>
8020      */
8021
8022     /**
8023      * @cfg {Number} flex
8024      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
8025      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>
8026      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
8027      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
8028      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
8029      */
8030
8031     /**
8032      * @private
8033      * See parent documentation
8034      */
8035     updateInnerCtSize: function(tSize, calcs) {
8036         var innerCtHeight = tSize.height,
8037             innerCtWidth  = calcs.meta.maxWidth + this.padding.left + this.padding.right;
8038
8039         if (this.align == 'stretch') {
8040             innerCtWidth = tSize.width;
8041         } else if (this.align == 'center') {
8042             innerCtWidth = Math.max(tSize.width, innerCtWidth);
8043         }
8044
8045         //we set the innerCt size first because if our child items are larger than the previous innerCt size
8046         //the browser will insert scrollbars and then remove them again immediately afterwards
8047         this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
8048     },
8049
8050     /**
8051      * @private
8052      * Calculates the size and positioning of each item in the VBox. This iterates over all of the rendered,
8053      * visible items and returns a height, width, top and left for each, as well as a reference to each. Also
8054      * returns meta data such as maxHeight which are useful when resizing layout wrappers such as this.innerCt.
8055      * @param {Array} visibleItems The array of all rendered, visible items to be calculated for
8056      * @param {Object} targetSize Object containing target size and height
8057      * @return {Object} Object containing box measurements for each child, plus meta data
8058      */
8059     calculateChildBoxes: function(visibleItems, targetSize) {
8060         var visibleCount = visibleItems.length,
8061
8062             padding      = this.padding,
8063             topOffset    = padding.top,
8064             leftOffset   = padding.left,
8065             paddingVert  = topOffset  + padding.bottom,
8066             paddingHoriz = leftOffset + padding.right,
8067
8068             width        = targetSize.width - this.scrollOffset,
8069             height       = targetSize.height,
8070             availWidth   = Math.max(0, width - paddingHoriz),
8071
8072             isStart      = this.pack == 'start',
8073             isCenter     = this.pack == 'center',
8074             isEnd        = this.pack == 'end',
8075
8076             nonFlexHeight= 0,
8077             maxWidth     = 0,
8078             totalFlex    = 0,
8079
8080             //used to cache the calculated size and position values for each child item
8081             boxes        = [],
8082
8083             //used in the for loops below, just declared here for brevity
8084             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedHeight, horizMargins, stretchWidth;
8085
8086             //gather the total flex of all flexed items and the width taken up by fixed width items
8087             for (i = 0; i < visibleCount; i++) {
8088                 child = visibleItems[i];
8089                 childHeight = child.height;
8090                 childWidth  = child.width;
8091                 canLayout   = !child.hasLayout && Ext.isFunction(child.doLayout);
8092
8093
8094                 // Static height (numeric) requires no calcs
8095                 if (!Ext.isNumber(childHeight)) {
8096
8097                     // flex and not 'auto' height
8098                     if (child.flex && !childHeight) {
8099                         totalFlex += child.flex;
8100
8101                     // Not flexed or 'auto' height or undefined height
8102                     } else {
8103                         //Render and layout sub-containers without a flex or width defined, as otherwise we
8104                         //don't know how wide the sub-container should be and cannot calculate flexed widths
8105                         if (!childHeight && canLayout) {
8106                             child.doLayout();
8107                         }
8108
8109                         childSize = child.getSize();
8110                         childWidth = childSize.width;
8111                         childHeight = childSize.height;
8112                     }
8113                 }
8114
8115                 childMargins = child.margins;
8116
8117                 nonFlexHeight += (childHeight || 0) + childMargins.top + childMargins.bottom;
8118
8119                 // Max width for align - force layout of non-layed out subcontainers without a numeric width
8120                 if (!Ext.isNumber(childWidth)) {
8121                     if (canLayout) {
8122                         child.doLayout();
8123                     }
8124                     childWidth = child.getWidth();
8125                 }
8126
8127                 maxWidth = Math.max(maxWidth, childWidth + childMargins.left + childMargins.right);
8128
8129                 //cache the size of each child component
8130                 boxes.push({
8131                     component: child,
8132                     height   : childHeight || undefined,
8133                     width    : childWidth || undefined
8134                 });
8135             }
8136
8137             //the height available to the flexed items
8138             var availableHeight = Math.max(0, (height - nonFlexHeight - paddingVert));
8139
8140             if (isCenter) {
8141                 topOffset += availableHeight / 2;
8142             } else if (isEnd) {
8143                 topOffset += availableHeight;
8144             }
8145
8146             //temporary variables used in the flex height calculations below
8147             var remainingHeight = availableHeight,
8148                 remainingFlex   = totalFlex;
8149
8150             //calculate the height of each flexed item, and the left + top positions of every item
8151             for (i = 0; i < visibleCount; i++) {
8152                 child = visibleItems[i];
8153                 calcs = boxes[i];
8154
8155                 childMargins = child.margins;
8156                 horizMargins = childMargins.left + childMargins.right;
8157
8158                 topOffset   += childMargins.top;
8159
8160                 if (isStart && child.flex && !child.height) {
8161                     flexedHeight     = Math.ceil((child.flex / remainingFlex) * remainingHeight);
8162                     remainingHeight -= flexedHeight;
8163                     remainingFlex   -= child.flex;
8164
8165                     calcs.height = flexedHeight;
8166                     calcs.dirtySize = true;
8167                 }
8168
8169                 calcs.left = leftOffset + childMargins.left;
8170                 calcs.top  = topOffset;
8171
8172                 switch (this.align) {
8173                     case 'stretch':
8174                         stretchWidth = availWidth - horizMargins;
8175                         calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
8176                         calcs.dirtySize = true;
8177                         break;
8178                     case 'stretchmax':
8179                         stretchWidth = maxWidth - horizMargins;
8180                         calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
8181                         calcs.dirtySize = true;
8182                         break;
8183                     case 'center':
8184                         var diff = availWidth - calcs.width - horizMargins;
8185                         if (diff > 0) {
8186                             calcs.left = leftOffset + horizMargins + (diff / 2);
8187                         }
8188                 }
8189
8190                 topOffset += calcs.height + childMargins.bottom;
8191             }
8192
8193         return {
8194             boxes: boxes,
8195             meta : {
8196                 maxWidth: maxWidth
8197             }
8198         };
8199     }
8200 });
8201
8202 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
8203
8204 /**
8205  * @class Ext.layout.HBoxLayout
8206  * @extends Ext.layout.BoxLayout
8207  * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal
8208  * space between child items containing a numeric <code>flex</code> configuration.</p>
8209  * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option.
8210  */
8211 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
8212     /**
8213      * @cfg {String} align
8214      * Controls how the child items of the container are aligned. Acceptable configuration values for this
8215      * property are:
8216      * <div class="mdetail-params"><ul>
8217      * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically
8218      * at the <b>top</b> of the container</div></li>
8219      * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically in the
8220      * <b>middle</b> of the container</div></li>
8221      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill
8222      * the height of the container</div></li>
8223      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to
8224      * the height of the largest item.</div></li>
8225      */
8226     align: 'top', // top, middle, stretch, strechmax
8227
8228     type : 'hbox',
8229
8230     /**
8231      * @private
8232      * See parent documentation
8233      */
8234     updateInnerCtSize: function(tSize, calcs) {
8235         var innerCtWidth  = tSize.width,
8236             innerCtHeight = calcs.meta.maxHeight + this.padding.top + this.padding.bottom;
8237
8238         if (this.align == 'stretch') {
8239             innerCtHeight = tSize.height;
8240         } else if (this.align == 'middle') {
8241             innerCtHeight = Math.max(tSize.height, innerCtHeight);
8242         }
8243
8244         this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
8245     },
8246
8247     /**
8248      * @cfg {String} pack
8249      * Controls how the child items of the container are packed together. Acceptable configuration values
8250      * for this property are:
8251      * <div class="mdetail-params"><ul>
8252      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
8253      * <b>left</b> side of container</div></li>
8254      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
8255      * <b>mid-width</b> of container</div></li>
8256      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>
8257      * side of container</div></li>
8258      * </ul></div>
8259      */
8260     /**
8261      * @cfg {Number} flex
8262      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
8263      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>
8264      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
8265      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
8266      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
8267      */
8268
8269     /**
8270      * @private
8271      * Calculates the size and positioning of each item in the HBox. This iterates over all of the rendered,
8272      * visible items and returns a height, width, top and left for each, as well as a reference to each. Also
8273      * returns meta data such as maxHeight which are useful when resizing layout wrappers such as this.innerCt.
8274      * @param {Array} visibleItems The array of all rendered, visible items to be calculated for
8275      * @param {Object} targetSize Object containing target size and height
8276      * @return {Object} Object containing box measurements for each child, plus meta data
8277      */
8278     calculateChildBoxes: function(visibleItems, targetSize) {
8279         var visibleCount = visibleItems.length,
8280
8281             padding      = this.padding,
8282             topOffset    = padding.top,
8283             leftOffset   = padding.left,
8284             paddingVert  = topOffset  + padding.bottom,
8285             paddingHoriz = leftOffset + padding.right,
8286
8287             width        = targetSize.width - this.scrollOffset,
8288             height       = targetSize.height,
8289             availHeight  = Math.max(0, height - paddingVert),
8290
8291             isStart      = this.pack == 'start',
8292             isCenter     = this.pack == 'center',
8293             isEnd        = this.pack == 'end',
8294             // isRestore    = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
8295
8296             nonFlexWidth = 0,
8297             maxHeight    = 0,
8298             totalFlex    = 0,
8299
8300             //used to cache the calculated size and position values for each child item
8301             boxes        = [],
8302
8303             //used in the for loops below, just declared here for brevity
8304             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, vertMargins, stretchHeight;
8305
8306             //gather the total flex of all flexed items and the width taken up by fixed width items
8307             for (i = 0; i < visibleCount; i++) {
8308                 child       = visibleItems[i];
8309                 childHeight = child.height;
8310                 childWidth  = child.width;
8311                 canLayout   = !child.hasLayout && Ext.isFunction(child.doLayout);
8312
8313                 // Static width (numeric) requires no calcs
8314                 if (!Ext.isNumber(childWidth)) {
8315
8316                     // flex and not 'auto' width
8317                     if (child.flex && !childWidth) {
8318                         totalFlex += child.flex;
8319
8320                     // Not flexed or 'auto' width or undefined width
8321                     } else {
8322                         //Render and layout sub-containers without a flex or width defined, as otherwise we
8323                         //don't know how wide the sub-container should be and cannot calculate flexed widths
8324                         if (!childWidth && canLayout) {
8325                             child.doLayout();
8326                         }
8327
8328                         childSize   = child.getSize();
8329                         childWidth  = childSize.width;
8330                         childHeight = childSize.height;
8331                     }
8332                 }
8333
8334                 childMargins = child.margins;
8335
8336                 nonFlexWidth += (childWidth || 0) + childMargins.left + childMargins.right;
8337
8338                 // Max height for align - force layout of non-layed out subcontainers without a numeric height
8339                 if (!Ext.isNumber(childHeight)) {
8340                     if (canLayout) {
8341                         child.doLayout();
8342                     }
8343                     childHeight = child.getHeight();
8344                 }
8345
8346                 maxHeight = Math.max(maxHeight, childHeight + childMargins.top + childMargins.bottom);
8347
8348                 //cache the size of each child component
8349                 boxes.push({
8350                     component: child,
8351                     height   : childHeight || undefined,
8352                     width    : childWidth || undefined
8353                 });
8354             }
8355
8356             //the width available to the flexed items
8357             var availableWidth = Math.max(0, (width - nonFlexWidth - paddingHoriz));
8358
8359             if (isCenter) {
8360                 leftOffset += availableWidth / 2;
8361             } else if (isEnd) {
8362                 leftOffset += availableWidth;
8363             }
8364
8365             //temporary variables used in the flex width calculations below
8366             var remainingWidth = availableWidth,
8367                 remainingFlex  = totalFlex;
8368
8369             //calculate the widths of each flexed item, and the left + top positions of every item
8370             for (i = 0; i < visibleCount; i++) {
8371                 child = visibleItems[i];
8372                 calcs = boxes[i];
8373
8374                 childMargins = child.margins;
8375                 vertMargins  = childMargins.top + childMargins.bottom;
8376
8377                 leftOffset  += childMargins.left;
8378
8379                 if (isStart && child.flex && !child.width) {
8380                     flexedWidth     = Math.ceil((child.flex / remainingFlex) * remainingWidth);
8381                     remainingWidth -= flexedWidth;
8382                     remainingFlex  -= child.flex;
8383
8384                     calcs.width = flexedWidth;
8385                     calcs.dirtySize = true;
8386                 }
8387
8388                 calcs.left = leftOffset;
8389                 calcs.top  = topOffset + childMargins.top;
8390
8391                 switch (this.align) {
8392                     case 'stretch':
8393                         stretchHeight = availHeight - vertMargins;
8394                         calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
8395                         calcs.dirtySize = true;
8396                         break;
8397                     case 'stretchmax':
8398                         stretchHeight = maxHeight - vertMargins;
8399                         calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
8400                         calcs.dirtySize = true;
8401                         break;
8402                     case 'middle':
8403                         var diff = availHeight - calcs.height - vertMargins;
8404                         if (diff > 0) {
8405                             calcs.top = topOffset + vertMargins + (diff / 2);
8406                         }
8407                 }
8408                 leftOffset += calcs.width + childMargins.right;
8409             }
8410
8411         return {
8412             boxes: boxes,
8413             meta : {
8414                 maxHeight: maxHeight
8415             }
8416         };
8417     }
8418 });
8419
8420 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
8421 /**
8422  * @class Ext.layout.ToolbarLayout
8423  * @extends Ext.layout.ContainerLayout
8424  * Layout manager used by Ext.Toolbar. This is highly specialised for use by Toolbars and would not
8425  * usually be used by any other class.
8426  */
8427 Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
8428     monitorResize : true,
8429
8430     type: 'toolbar',
8431
8432     /**
8433      * @property triggerWidth
8434      * @type Number
8435      * The width allocated for the menu trigger at the extreme right end of the Toolbar
8436      */
8437     triggerWidth: 18,
8438
8439     /**
8440      * @property noItemsMenuText
8441      * @type String
8442      * HTML fragment to render into the toolbar overflow menu if there are no items to display
8443      */
8444     noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
8445
8446     /**
8447      * @private
8448      * @property lastOverflow
8449      * @type Boolean
8450      * Used internally to record whether the last layout caused an overflow or not
8451      */
8452     lastOverflow: false,
8453
8454     /**
8455      * @private
8456      * @property tableHTML
8457      * @type String
8458      * String used to build the HTML injected to support the Toolbar's layout. The align property is
8459      * injected into this string inside the td.x-toolbar-left element during onLayout.
8460      */
8461     tableHTML: [
8462         '<table cellspacing="0" class="x-toolbar-ct">',
8463             '<tbody>',
8464                 '<tr>',
8465                     '<td class="x-toolbar-left" align="{0}">',
8466                         '<table cellspacing="0">',
8467                             '<tbody>',
8468                                 '<tr class="x-toolbar-left-row"></tr>',
8469                             '</tbody>',
8470                         '</table>',
8471                     '</td>',
8472                     '<td class="x-toolbar-right" align="right">',
8473                         '<table cellspacing="0" class="x-toolbar-right-ct">',
8474                             '<tbody>',
8475                                 '<tr>',
8476                                     '<td>',
8477                                         '<table cellspacing="0">',
8478                                             '<tbody>',
8479                                                 '<tr class="x-toolbar-right-row"></tr>',
8480                                             '</tbody>',
8481                                         '</table>',
8482                                     '</td>',
8483                                     '<td>',
8484                                         '<table cellspacing="0">',
8485                                             '<tbody>',
8486                                                 '<tr class="x-toolbar-extras-row"></tr>',
8487                                             '</tbody>',
8488                                         '</table>',
8489                                     '</td>',
8490                                 '</tr>',
8491                             '</tbody>',
8492                         '</table>',
8493                     '</td>',
8494                 '</tr>',
8495             '</tbody>',
8496         '</table>'
8497     ].join(""),
8498
8499     /**
8500      * @private
8501      * Create the wrapping Toolbar HTML and render/move all the items into the correct places
8502      */
8503     onLayout : function(ct, target) {
8504         //render the Toolbar <table> HTML if it's not already present
8505         if (!this.leftTr) {
8506             var align = ct.buttonAlign == 'center' ? 'center' : 'left';
8507
8508             target.addClass('x-toolbar-layout-ct');
8509             target.insertHtml('beforeEnd', String.format(this.tableHTML, align));
8510
8511             this.leftTr   = target.child('tr.x-toolbar-left-row', true);
8512             this.rightTr  = target.child('tr.x-toolbar-right-row', true);
8513             this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
8514
8515             if (this.hiddenItem == undefined) {
8516                 /**
8517                  * @property hiddenItems
8518                  * @type Array
8519                  * Holds all items that are currently hidden due to there not being enough space to render them
8520                  * These items will appear on the expand menu.
8521                  */
8522                 this.hiddenItems = [];
8523             }
8524         }
8525
8526         var side     = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
8527             items    = ct.items.items,
8528             position = 0;
8529
8530         //render each item if not already rendered, place it into the correct (left or right) target
8531         for (var i = 0, len = items.length, c; i < len; i++, position++) {
8532             c = items[i];
8533
8534             if (c.isFill) {
8535                 side   = this.rightTr;
8536                 position = -1;
8537             } else if (!c.rendered) {
8538                 c.render(this.insertCell(c, side, position));
8539             } else {
8540                 if (!c.xtbHidden && !this.isValidParent(c, side.childNodes[position])) {
8541                     var td = this.insertCell(c, side, position);
8542                     td.appendChild(c.getPositionEl().dom);
8543                     c.container = Ext.get(td);
8544                 }
8545             }
8546         }
8547
8548         //strip extra empty cells
8549         this.cleanup(this.leftTr);
8550         this.cleanup(this.rightTr);
8551         this.cleanup(this.extrasTr);
8552         this.fitToSize(target);
8553     },
8554
8555     /**
8556      * @private
8557      * Removes any empty nodes from the given element
8558      * @param {Ext.Element} el The element to clean up
8559      */
8560     cleanup : function(el) {
8561         var cn = el.childNodes, i, c;
8562
8563         for (i = cn.length-1; i >= 0 && (c = cn[i]); i--) {
8564             if (!c.firstChild) {
8565                 el.removeChild(c);
8566             }
8567         }
8568     },
8569
8570     /**
8571      * @private
8572      * Inserts the given Toolbar item into the given element
8573      * @param {Ext.Component} c The component to add
8574      * @param {Ext.Element} target The target to add the component to
8575      * @param {Number} position The position to add the component at
8576      */
8577     insertCell : function(c, target, position) {
8578         var td = document.createElement('td');
8579         td.className = 'x-toolbar-cell';
8580
8581         target.insertBefore(td, target.childNodes[position] || null);
8582
8583         return td;
8584     },
8585
8586     /**
8587      * @private
8588      * Hides an item because it will not fit in the available width. The item will be unhidden again
8589      * if the Toolbar is resized to be large enough to show it
8590      * @param {Ext.Component} item The item to hide
8591      */
8592     hideItem : function(item) {
8593         this.hiddenItems.push(item);
8594
8595         item.xtbHidden = true;
8596         item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
8597         item.hide();
8598     },
8599
8600     /**
8601      * @private
8602      * Unhides an item that was previously hidden due to there not being enough space left on the Toolbar
8603      * @param {Ext.Component} item The item to show
8604      */
8605     unhideItem : function(item) {
8606         item.show();
8607         item.xtbHidden = false;
8608         this.hiddenItems.remove(item);
8609     },
8610
8611     /**
8612      * @private
8613      * Returns the width of the given toolbar item. If the item is currently hidden because there
8614      * is not enough room to render it, its previous width is returned
8615      * @param {Ext.Component} c The component to measure
8616      * @return {Number} The width of the item
8617      */
8618     getItemWidth : function(c) {
8619         return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
8620     },
8621
8622     /**
8623      * @private
8624      * Called at the end of onLayout. At this point the Toolbar has already been resized, so we need
8625      * to fit the items into the available width. We add up the width required by all of the items in
8626      * the toolbar - if we don't have enough space we hide the extra items and render the expand menu
8627      * trigger.
8628      * @param {Ext.Element} target The Element the Toolbar is currently laid out within
8629      */
8630     fitToSize : function(target) {
8631         if (this.container.enableOverflow === false) {
8632             return;
8633         }
8634
8635         var width       = target.dom.clientWidth,
8636             tableWidth  = target.dom.firstChild.offsetWidth,
8637             clipWidth   = width - this.triggerWidth,
8638             lastWidth   = this.lastWidth || 0,
8639
8640             hiddenItems = this.hiddenItems,
8641             hasHiddens  = hiddenItems.length != 0,
8642             isLarger    = width >= lastWidth;
8643
8644         this.lastWidth  = width;
8645
8646         if (tableWidth > width || (hasHiddens && isLarger)) {
8647             var items     = this.container.items.items,
8648                 len       = items.length,
8649                 loopWidth = 0,
8650                 item;
8651
8652             for (var i = 0; i < len; i++) {
8653                 item = items[i];
8654
8655                 if (!item.isFill) {
8656                     loopWidth += this.getItemWidth(item);
8657                     if (loopWidth > clipWidth) {
8658                         if (!(item.hidden || item.xtbHidden)) {
8659                             this.hideItem(item);
8660                         }
8661                     } else if (item.xtbHidden) {
8662                         this.unhideItem(item);
8663                     }
8664                 }
8665             }
8666         }
8667
8668         //test for number of hidden items again here because they may have changed above
8669         hasHiddens = hiddenItems.length != 0;
8670
8671         if (hasHiddens) {
8672             this.initMore();
8673
8674             if (!this.lastOverflow) {
8675                 this.container.fireEvent('overflowchange', this.container, true);
8676                 this.lastOverflow = true;
8677             }
8678         } else if (this.more) {
8679             this.clearMenu();
8680             this.more.destroy();
8681             delete this.more;
8682
8683             if (this.lastOverflow) {
8684                 this.container.fireEvent('overflowchange', this.container, false);
8685                 this.lastOverflow = false;
8686             }
8687         }
8688     },
8689
8690     /**
8691      * @private
8692      * Returns a menu config for a given component. This config is used to create a menu item
8693      * to be added to the expander menu
8694      * @param {Ext.Component} component The component to create the config for
8695      * @param {Boolean} hideOnClick Passed through to the menu item
8696      */
8697     createMenuConfig : function(component, hideOnClick){
8698         var config = Ext.apply({}, component.initialConfig),
8699             group  = component.toggleGroup;
8700
8701         Ext.copyTo(config, component, [
8702             'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
8703         ]);
8704
8705         Ext.apply(config, {
8706             text       : component.overflowText || component.text,
8707             hideOnClick: hideOnClick
8708         });
8709
8710         if (group || component.enableToggle) {
8711             Ext.apply(config, {
8712                 group  : group,
8713                 checked: component.pressed,
8714                 listeners: {
8715                     checkchange: function(item, checked){
8716                         component.toggle(checked);
8717                     }
8718                 }
8719             });
8720         }
8721
8722         delete config.ownerCt;
8723         delete config.xtype;
8724         delete config.id;
8725
8726         return config;
8727     },
8728
8729     /**
8730      * @private
8731      * Adds the given Toolbar item to the given menu. Buttons inside a buttongroup are added individually.
8732      * @param {Ext.menu.Menu} menu The menu to add to
8733      * @param {Ext.Component} component The component to add
8734      */
8735     addComponentToMenu : function(menu, component) {
8736         if (component instanceof Ext.Toolbar.Separator) {
8737             menu.add('-');
8738
8739         } else if (Ext.isFunction(component.isXType)) {
8740             if (component.isXType('splitbutton')) {
8741                 menu.add(this.createMenuConfig(component, true));
8742
8743             } else if (component.isXType('button')) {
8744                 menu.add(this.createMenuConfig(component, !component.menu));
8745
8746             } else if (component.isXType('buttongroup')) {
8747                 component.items.each(function(item){
8748                      this.addComponentToMenu(menu, item);
8749                 }, this);
8750             }
8751         }
8752     },
8753
8754     /**
8755      * @private
8756      * Deletes the sub-menu of each item in the expander menu. Submenus are created for items such as
8757      * splitbuttons and buttongroups, where the Toolbar item cannot be represented by a single menu item
8758      */
8759     clearMenu : function(){
8760         var menu = this.moreMenu;
8761         if (menu && menu.items) {
8762             menu.items.each(function(item){
8763                 delete item.menu;
8764             });
8765         }
8766     },
8767
8768     /**
8769      * @private
8770      * Called before the expand menu is shown, this rebuilds the menu since it was last shown because
8771      * it is possible that the items hidden due to space limitations on the Toolbar have changed since.
8772      * @param {Ext.menu.Menu} m The menu
8773      */
8774     beforeMoreShow : function(menu) {
8775         var items = this.container.items.items,
8776             len   = items.length,
8777             item,
8778             prev;
8779
8780         var needsSep = function(group, item){
8781             return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
8782         };
8783
8784         this.clearMenu();
8785         menu.removeAll();
8786         for (var i = 0; i < len; i++) {
8787             item = items[i];
8788             if (item.xtbHidden) {
8789                 if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
8790                     menu.add('-');
8791                 }
8792                 this.addComponentToMenu(menu, item);
8793                 prev = item;
8794             }
8795         }
8796
8797         // put something so the menu isn't empty if no compatible items found
8798         if (menu.items.length < 1) {
8799             menu.add(this.noItemsMenuText);
8800         }
8801     },
8802
8803     /**
8804      * @private
8805      * Creates the expand trigger and menu, adding them to the <tr> at the extreme right of the
8806      * Toolbar table
8807      */
8808     initMore : function(){
8809         if (!this.more) {
8810             /**
8811              * @private
8812              * @property moreMenu
8813              * @type Ext.menu.Menu
8814              * The expand menu - holds items for every Toolbar item that cannot be shown
8815              * because the Toolbar is currently not wide enough.
8816              */
8817             this.moreMenu = new Ext.menu.Menu({
8818                 ownerCt : this.container,
8819                 listeners: {
8820                     beforeshow: this.beforeMoreShow,
8821                     scope: this
8822                 }
8823             });
8824
8825             /**
8826              * @private
8827              * @property more
8828              * @type Ext.Button
8829              * The expand button which triggers the overflow menu to be shown
8830              */
8831             this.more = new Ext.Button({
8832                 iconCls: 'x-toolbar-more-icon',
8833                 cls    : 'x-toolbar-more',
8834                 menu   : this.moreMenu,
8835                 ownerCt: this.container
8836             });
8837
8838             var td = this.insertCell(this.more, this.extrasTr, 100);
8839             this.more.render(td);
8840         }
8841     },
8842
8843     destroy : function(){
8844         Ext.destroy(this.more, this.moreMenu);
8845         delete this.leftTr;
8846         delete this.rightTr;
8847         delete this.extrasTr;
8848         Ext.layout.ToolbarLayout.superclass.destroy.call(this);
8849     }
8850 });
8851
8852 Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;
8853 /**
8854  * @class Ext.layout.MenuLayout
8855  * @extends Ext.layout.ContainerLayout
8856  * <p>Layout manager used by {@link Ext.menu.Menu}. Generally this class should not need to be used directly.</p>
8857  */
8858  Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
8859     monitorResize : true,
8860
8861     type: 'menu',
8862
8863     setContainer : function(ct){
8864         this.monitorResize = !ct.floating;
8865         // This event is only fired by the menu in IE, used so we don't couple
8866         // the menu with the layout.
8867         ct.on('autosize', this.doAutoSize, this);
8868         Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
8869     },
8870
8871     renderItem : function(c, position, target){
8872         if (!this.itemTpl) {
8873             this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
8874                 '<li id="{itemId}" class="{itemCls}">',
8875                     '<tpl if="needsIcon">',
8876                         '<img src="{icon}" class="{iconCls}"/>',
8877                     '</tpl>',
8878                 '</li>'
8879             );
8880         }
8881
8882         if(c && !c.rendered){
8883             if(Ext.isNumber(position)){
8884                 position = target.dom.childNodes[position];
8885             }
8886             var a = this.getItemArgs(c);
8887
8888 //          The Component's positionEl is the <li> it is rendered into
8889             c.render(c.positionEl = position ?
8890                 this.itemTpl.insertBefore(position, a, true) :
8891                 this.itemTpl.append(target, a, true));
8892
8893 //          Link the containing <li> to the item.
8894             c.positionEl.menuItemId = c.getItemId();
8895
8896 //          If rendering a regular Component, and it needs an icon,
8897 //          move the Component rightwards.
8898             if (!a.isMenuItem && a.needsIcon) {
8899                 c.positionEl.addClass('x-menu-list-item-indent');
8900             }
8901             this.configureItem(c, position);
8902         }else if(c && !this.isValidParent(c, target)){
8903             if(Ext.isNumber(position)){
8904                 position = target.dom.childNodes[position];
8905             }
8906             target.dom.insertBefore(c.getActionEl().dom, position || null);
8907         }
8908     },
8909
8910     getItemArgs : function(c) {
8911         var isMenuItem = c instanceof Ext.menu.Item;
8912         return {
8913             isMenuItem: isMenuItem,
8914             needsIcon: !isMenuItem && (c.icon || c.iconCls),
8915             icon: c.icon || Ext.BLANK_IMAGE_URL,
8916             iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
8917             itemId: 'x-menu-el-' + c.id,
8918             itemCls: 'x-menu-list-item '
8919         };
8920     },
8921
8922     //  Valid if the Component is in a <li> which is part of our target <ul>
8923     isValidParent : function(c, target) {
8924         return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
8925     },
8926
8927     onLayout : function(ct, target){
8928         Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
8929         this.doAutoSize();
8930     },
8931
8932     doAutoSize : function(){
8933         var ct = this.container, w = ct.width;
8934         if(ct.floating){
8935             if(w){
8936                 ct.setWidth(w);
8937             }else if(Ext.isIE){
8938                 ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
8939                 var el = ct.getEl(), t = el.dom.offsetWidth; // force recalc
8940                 ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
8941             }
8942         }
8943     }
8944 });
8945 Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;
8946 /**
8947  * @class Ext.Viewport
8948  * @extends Ext.Container
8949  * <p>A specialized container representing the viewable application area (the browser viewport).</p>
8950  * <p>The Viewport renders itself to the document body, and automatically sizes itself to the size of
8951  * the browser viewport and manages window resizing. There may only be one Viewport created
8952  * in a page. Inner layouts are available by virtue of the fact that all {@link Ext.Panel Panel}s
8953  * added to the Viewport, either through its {@link #items}, or through the items, or the {@link #add}
8954  * method of any of its child Panels may themselves have a layout.</p>
8955  * <p>The Viewport does not provide scrolling, so child Panels within the Viewport should provide
8956  * for scrolling if needed using the {@link #autoScroll} config.</p>
8957  * <p>An example showing a classic application border layout:</p><pre><code>
8958 new Ext.Viewport({
8959     layout: 'border',
8960     items: [{
8961         region: 'north',
8962         html: '&lt;h1 class="x-panel-header">Page Title&lt;/h1>',
8963         autoHeight: true,
8964         border: false,
8965         margins: '0 0 5 0'
8966     }, {
8967         region: 'west',
8968         collapsible: true,
8969         title: 'Navigation',
8970         width: 200
8971         // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout}
8972     }, {
8973         region: 'south',
8974         title: 'Title for Panel',
8975         collapsible: true,
8976         html: 'Information goes here',
8977         split: true,
8978         height: 100,
8979         minHeight: 100
8980     }, {
8981         region: 'east',
8982         title: 'Title for the Grid Panel',
8983         collapsible: true,
8984         split: true,
8985         width: 200,
8986         xtype: 'grid',
8987         // remaining grid configuration not shown ...
8988         // notice that the GridPanel is added directly as the region
8989         // it is not "overnested" inside another Panel
8990     }, {
8991         region: 'center',
8992         xtype: 'tabpanel', // TabPanel itself has no title
8993         items: {
8994             title: 'Default Tab',
8995             html: 'The first tab\'s content. Others may be added dynamically'
8996         }
8997     }]
8998 });
8999 </code></pre>
9000  * @constructor
9001  * Create a new Viewport
9002  * @param {Object} config The config object
9003  * @xtype viewport
9004  */
9005 Ext.Viewport = Ext.extend(Ext.Container, {
9006     /*
9007      * Privatize config options which, if used, would interfere with the
9008      * correct operation of the Viewport as the sole manager of the
9009      * layout of the document body.
9010      */
9011     /**
9012      * @cfg {Mixed} applyTo @hide
9013      */
9014     /**
9015      * @cfg {Boolean} allowDomMove @hide
9016      */
9017     /**
9018      * @cfg {Boolean} hideParent @hide
9019      */
9020     /**
9021      * @cfg {Mixed} renderTo @hide
9022      */
9023     /**
9024      * @cfg {Boolean} hideParent @hide
9025      */
9026     /**
9027      * @cfg {Number} height @hide
9028      */
9029     /**
9030      * @cfg {Number} width @hide
9031      */
9032     /**
9033      * @cfg {Boolean} autoHeight @hide
9034      */
9035     /**
9036      * @cfg {Boolean} autoWidth @hide
9037      */
9038     /**
9039      * @cfg {Boolean} deferHeight @hide
9040      */
9041     /**
9042      * @cfg {Boolean} monitorResize @hide
9043      */
9044
9045     initComponent : function() {
9046         Ext.Viewport.superclass.initComponent.call(this);
9047         document.getElementsByTagName('html')[0].className += ' x-viewport';
9048         this.el = Ext.getBody();
9049         this.el.setHeight = Ext.emptyFn;
9050         this.el.setWidth = Ext.emptyFn;
9051         this.el.setSize = Ext.emptyFn;
9052         this.el.dom.scroll = 'no';
9053         this.allowDomMove = false;
9054         this.autoWidth = true;
9055         this.autoHeight = true;
9056         Ext.EventManager.onWindowResize(this.fireResize, this);
9057         this.renderTo = this.el;
9058     },
9059
9060     fireResize : function(w, h){
9061         this.fireEvent('resize', this, w, h, w, h);
9062     }
9063 });
9064 Ext.reg('viewport', Ext.Viewport);
9065 /**
9066  * @class Ext.Panel
9067  * @extends Ext.Container
9068  * <p>Panel is a container that has specific functionality and structural components that make
9069  * it the perfect building block for application-oriented user interfaces.</p>
9070  * <p>Panels are, by virtue of their inheritance from {@link Ext.Container}, capable
9071  * of being configured with a {@link Ext.Container#layout layout}, and containing child Components.</p>
9072  * <p>When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.Container#add adding} Components
9073  * to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether
9074  * 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
9075  * default, Panels use the {@link Ext.layout.ContainerLayout ContainerLayout} scheme. This simply renders
9076  * child components, appending them one after the other inside the Container, and <b>does not apply any sizing</b>
9077  * at all.</p>
9078  * <p>A Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate
9079  * {@link #header}, {@link #footer} and {@link #body} sections (see {@link #frame} for additional
9080  * information).</p>
9081  * <p>Panel also provides built-in {@link #collapsible expandable and collapsible behavior}, along with
9082  * a variety of {@link #tools prebuilt tool buttons} that can be wired up to provide other customized
9083  * behavior.  Panels can be easily dropped into any {@link Ext.Container Container} or layout, and the
9084  * layout and rendering pipeline is {@link Ext.Container#add completely managed by the framework}.</p>
9085  * @constructor
9086  * @param {Object} config The config object
9087  * @xtype panel
9088  */
9089 Ext.Panel = Ext.extend(Ext.Container, {
9090     /**
9091      * The Panel's header {@link Ext.Element Element}. Read-only.
9092      * <p>This Element is used to house the {@link #title} and {@link #tools}</p>
9093      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
9094      * @type Ext.Element
9095      * @property header
9096      */
9097     /**
9098      * The Panel's body {@link Ext.Element Element} which may be used to contain HTML content.
9099      * The content may be specified in the {@link #html} config, or it may be loaded using the
9100      * {@link autoLoad} config, or through the Panel's {@link #getUpdater Updater}. Read-only.
9101      * <p>If this is used to load visible HTML elements in either way, then
9102      * the Panel may not be used as a Layout for hosting nested Panels.</p>
9103      * <p>If this Panel is intended to be used as the host of a Layout (See {@link #layout}
9104      * then the body Element must not be loaded or changed - it is under the control
9105      * of the Panel's Layout.
9106      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
9107      * @type Ext.Element
9108      * @property body
9109      */
9110     /**
9111      * The Panel's bwrap {@link Ext.Element Element} used to contain other Panel elements
9112      * (tbar, body, bbar, footer). See {@link #bodyCfg}. Read-only.
9113      * @type Ext.Element
9114      * @property bwrap
9115      */
9116     /**
9117      * True if this panel is collapsed. Read-only.
9118      * @type Boolean
9119      * @property collapsed
9120      */
9121     /**
9122      * @cfg {Object} bodyCfg
9123      * <p>A {@link Ext.DomHelper DomHelper} element specification object may be specified for any
9124      * Panel Element.</p>
9125      * <p>By default, the Default element in the table below will be used for the html markup to
9126      * create a child element with the commensurate Default class name (<code>baseCls</code> will be
9127      * replaced by <code>{@link #baseCls}</code>):</p>
9128      * <pre>
9129      * Panel      Default  Default             Custom      Additional       Additional
9130      * Element    element  class               element     class            style
9131      * ========   ==========================   =========   ==============   ===========
9132      * {@link #header}     div      {@link #baseCls}+'-header'   {@link #headerCfg}   headerCssClass   headerStyle
9133      * {@link #bwrap}      div      {@link #baseCls}+'-bwrap'     {@link #bwrapCfg}    bwrapCssClass    bwrapStyle
9134      * + tbar     div      {@link #baseCls}+'-tbar'       {@link #tbarCfg}     tbarCssClass     tbarStyle
9135      * + {@link #body}     div      {@link #baseCls}+'-body'       {@link #bodyCfg}     {@link #bodyCssClass}     {@link #bodyStyle}
9136      * + bbar     div      {@link #baseCls}+'-bbar'       {@link #bbarCfg}     bbarCssClass     bbarStyle
9137      * + {@link #footer}   div      {@link #baseCls}+'-footer'   {@link #footerCfg}   footerCssClass   footerStyle
9138      * </pre>
9139      * <p>Configuring a Custom element may be used, for example, to force the {@link #body} Element
9140      * to use a different form of markup than is created by default. An example of this might be
9141      * to {@link Ext.Element#createChild create a child} Panel containing a custom content, such as
9142      * a header, or forcing centering of all Panel content by having the body be a &lt;center&gt;
9143      * element:</p>
9144      * <pre><code>
9145 new Ext.Panel({
9146     title: 'Message Title',
9147     renderTo: Ext.getBody(),
9148     width: 200, height: 130,
9149     <b>bodyCfg</b>: {
9150         tag: 'center',
9151         cls: 'x-panel-body',  // Default class not applied if Custom element specified
9152         html: 'Message'
9153     },
9154     footerCfg: {
9155         tag: 'h2',
9156         cls: 'x-panel-footer'        // same as the Default class
9157         html: 'footer html'
9158     },
9159     footerCssClass: 'custom-footer', // additional css class, see {@link Ext.element#addClass addClass}
9160     footerStyle:    'background-color:red' // see {@link #bodyStyle}
9161 });
9162      * </code></pre>
9163      * <p>The example above also explicitly creates a <code>{@link #footer}</code> with custom markup and
9164      * styling applied.</p>
9165      */
9166     /**
9167      * @cfg {Object} headerCfg
9168      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
9169      * of this Panel's {@link #header} Element.  See <code>{@link #bodyCfg}</code> also.</p>
9170      */
9171     /**
9172      * @cfg {Object} bwrapCfg
9173      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
9174      * of this Panel's {@link #bwrap} Element.  See <code>{@link #bodyCfg}</code> also.</p>
9175      */
9176     /**
9177      * @cfg {Object} tbarCfg
9178      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
9179      * of this Panel's {@link #tbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
9180      */
9181     /**
9182      * @cfg {Object} bbarCfg
9183      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
9184      * of this Panel's {@link #bbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
9185      */
9186     /**
9187      * @cfg {Object} footerCfg
9188      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
9189      * of this Panel's {@link #footer} Element.  See <code>{@link #bodyCfg}</code> also.</p>
9190      */
9191     /**
9192      * @cfg {Boolean} closable
9193      * Panels themselves do not directly support being closed, but some Panel subclasses do (like
9194      * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}.  Specify <code>true</code>
9195      * to enable closing in such situations. Defaults to <code>false</code>.
9196      */
9197     /**
9198      * The Panel's footer {@link Ext.Element Element}. Read-only.
9199      * <p>This Element is used to house the Panel's <code>{@link #buttons}</code> or <code>{@link #fbar}</code>.</p>
9200      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
9201      * @type Ext.Element
9202      * @property footer
9203      */
9204     /**
9205      * @cfg {Mixed} applyTo
9206      * <p>The id of the node, a DOM node or an existing Element corresponding to a DIV that is already present in
9207      * the document that specifies some panel-specific structural markup.  When <code>applyTo</code> is used,
9208      * constituent parts of the panel can be specified by CSS class name within the main element, and the panel
9209      * will automatically create those components from that markup. Any required components not specified in the
9210      * markup will be autogenerated if necessary.</p>
9211      * <p>The following class names are supported (baseCls will be replaced by {@link #baseCls}):</p>
9212      * <ul><li>baseCls + '-header'</li>
9213      * <li>baseCls + '-header-text'</li>
9214      * <li>baseCls + '-bwrap'</li>
9215      * <li>baseCls + '-tbar'</li>
9216      * <li>baseCls + '-body'</li>
9217      * <li>baseCls + '-bbar'</li>
9218      * <li>baseCls + '-footer'</li></ul>
9219      * <p>Using this config, a call to render() is not required.  If applyTo is specified, any value passed for
9220      * {@link #renderTo} will be ignored and the target element's parent node will automatically be used as the
9221      * panel's container.</p>
9222      */
9223     /**
9224      * @cfg {Object/Array} tbar
9225      * <p>The top toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
9226      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
9227      * To access the top toolbar after render, use {@link #getTopToolbar}.</p>
9228      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
9229      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
9230      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
9231      * submission parameters are collected from the DOM tree.</p>
9232      */
9233     /**
9234      * @cfg {Object/Array} bbar
9235      * <p>The bottom toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
9236      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
9237      * To access the bottom toolbar after render, use {@link #getBottomToolbar}.</p>
9238      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
9239      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
9240      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
9241      * submission parameters are collected from the DOM tree.</p>
9242      */
9243     /** @cfg {Object/Array} fbar
9244      * <p>A {@link Ext.Toolbar Toolbar} object, a Toolbar config, or an array of
9245      * {@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>
9246      * <p>After render, the <code>fbar</code> property will be an {@link Ext.Toolbar Toolbar} instance.</p>
9247      * <p>If <code>{@link #buttons}</code> are specified, they will supersede the <code>fbar</code> configuration property.</p>
9248      * The Panel's <code>{@link #buttonAlign}</code> configuration affects the layout of these items, for example:
9249      * <pre><code>
9250 var w = new Ext.Window({
9251     height: 250,
9252     width: 500,
9253     bbar: new Ext.Toolbar({
9254         items: [{
9255             text: 'bbar Left'
9256         },'->',{
9257             text: 'bbar Right'
9258         }]
9259     }),
9260     {@link #buttonAlign}: 'left', // anything but 'center' or 'right' and you can use '-', and '->'
9261                                   // to control the alignment of fbar items
9262     fbar: [{
9263         text: 'fbar Left'
9264     },'->',{
9265         text: 'fbar Right'
9266     }]
9267 }).show();
9268      * </code></pre>
9269      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
9270      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
9271      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
9272      * submission parameters are collected from the DOM tree.</p>
9273      */
9274     /**
9275      * @cfg {Boolean} header
9276      * <code>true</code> to create the Panel's header element explicitly, <code>false</code> to skip creating
9277      * it.  If a <code>{@link #title}</code> is set the header will be created automatically, otherwise it will not.
9278      * If a <code>{@link #title}</code> is set but <code>header</code> is explicitly set to <code>false</code>, the header
9279      * will not be rendered.
9280      */
9281     /**
9282      * @cfg {Boolean} footer
9283      * <code>true</code> to create the footer element explicitly, false to skip creating it. The footer
9284      * will be created automatically if <code>{@link #buttons}</code> or a <code>{@link #fbar}</code> have
9285      * been configured.  See <code>{@link #bodyCfg}</code> for an example.
9286      */
9287     /**
9288      * @cfg {String} title
9289      * The title text to be used as innerHTML (html tags are accepted) to display in the panel
9290      * <code>{@link #header}</code> (defaults to ''). When a <code>title</code> is specified the
9291      * <code>{@link #header}</code> element will automatically be created and displayed unless
9292      * {@link #header} is explicitly set to <code>false</code>.  If you do not want to specify a
9293      * <code>title</code> at config time, but you may want one later, you must either specify a non-empty
9294      * <code>title</code> (a blank space ' ' will do) or <code>header:true</code> so that the container
9295      * element will get created.
9296      */
9297     /**
9298      * @cfg {Array} buttons
9299      * <code>buttons</code> will be used as <code>{@link Ext.Container#items items}</code> for the toolbar in
9300      * the footer (<code>{@link #fbar}</code>). Typically the value of this configuration property will be
9301      * an array of {@link Ext.Button}s or {@link Ext.Button} configuration objects.
9302      * If an item is configured with <code>minWidth</code> or the Panel is configured with <code>minButtonWidth</code>,
9303      * that width will be applied to the item.
9304      */
9305     /**
9306      * @cfg {Object/String/Function} autoLoad
9307      * A valid url spec according to the Updater {@link Ext.Updater#update} method.
9308      * If autoLoad is not null, the panel will attempt to load its contents
9309      * immediately upon render.<p>
9310      * The URL will become the default URL for this panel's {@link #body} element,
9311      * so it may be {@link Ext.Element#refresh refresh}ed at any time.</p>
9312      */
9313     /**
9314      * @cfg {Boolean} frame
9315      * <code>false</code> by default to render with plain 1px square borders. <code>true</code> to render with
9316      * 9 elements, complete with custom rounded corners (also see {@link Ext.Element#boxWrap}).
9317      * <p>The template generated for each condition is depicted below:</p><pre><code>
9318      *
9319 // frame = false
9320 &lt;div id="developer-specified-id-goes-here" class="x-panel">
9321
9322     &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:false)&lt;/span>&lt;/div>
9323
9324     &lt;div class="x-panel-bwrap">
9325         &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
9326     &lt;/div>
9327 &lt;/div>
9328
9329 // frame = true (create 9 elements)
9330 &lt;div id="developer-specified-id-goes-here" class="x-panel">
9331     &lt;div class="x-panel-tl">&lt;div class="x-panel-tr">&lt;div class="x-panel-tc">
9332         &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:true)&lt;/span>&lt;/div>
9333     &lt;/div>&lt;/div>&lt;/div>
9334
9335     &lt;div class="x-panel-bwrap">
9336         &lt;div class="x-panel-ml">&lt;div class="x-panel-mr">&lt;div class="x-panel-mc">
9337             &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
9338         &lt;/div>&lt;/div>&lt;/div>
9339
9340         &lt;div class="x-panel-bl">&lt;div class="x-panel-br">&lt;div class="x-panel-bc"/>
9341         &lt;/div>&lt;/div>&lt;/div>
9342 &lt;/div>
9343      * </code></pre>
9344      */
9345     /**
9346      * @cfg {Boolean} border
9347      * True to display the borders of the panel's body element, false to hide them (defaults to true).  By default,
9348      * the border is a 2px wide inset border, but this can be further altered by setting {@link #bodyBorder} to false.
9349      */
9350     /**
9351      * @cfg {Boolean} bodyBorder
9352      * True to display an interior border on the body element of the panel, false to hide it (defaults to true).
9353      * This only applies when {@link #border} == true.  If border == true and bodyBorder == false, the border will display
9354      * as a 1px wide inset border, giving the entire body element an inset appearance.
9355      */
9356     /**
9357      * @cfg {String/Object/Function} bodyCssClass
9358      * Additional css class selector to be applied to the {@link #body} element in the format expected by
9359      * {@link Ext.Element#addClass} (defaults to null). See {@link #bodyCfg}.
9360      */
9361     /**
9362      * @cfg {String/Object/Function} bodyStyle
9363      * Custom CSS styles to be applied to the {@link #body} element in the format expected by
9364      * {@link Ext.Element#applyStyles} (defaults to null). See {@link #bodyCfg}.
9365      */
9366     /**
9367      * @cfg {String} iconCls
9368      * The CSS class selector that specifies a background image to be used as the header icon (defaults to '').
9369      * <p>An example of specifying a custom icon class would be something like:
9370      * </p><pre><code>
9371 // specify the property in the config for the class:
9372      ...
9373      iconCls: 'my-icon'
9374
9375 // css class that specifies background image to be used as the icon image:
9376 .my-icon { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
9377 </code></pre>
9378      */
9379     /**
9380      * @cfg {Boolean} collapsible
9381      * True to make the panel collapsible and have the expand/collapse toggle button automatically rendered into
9382      * the header tool button area, false to keep the panel statically sized with no button (defaults to false).
9383      */
9384     /**
9385      * @cfg {Array} tools
9386      * An array of tool button configs to be added to the header tool area. When rendered, each tool is
9387      * stored as an {@link Ext.Element Element} referenced by a public property called <code><b></b>tools.<i>&lt;tool-type&gt;</i></code>
9388      * <p>Each tool config may contain the following properties:
9389      * <div class="mdetail-params"><ul>
9390      * <li><b>id</b> : String<div class="sub-desc"><b>Required.</b> The type
9391      * 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
9392      * resulting tool Element. Ext provides CSS rules, and an icon sprite containing images for the tool types listed below.
9393      * The developer may implement custom tools by supplying alternate CSS rules and background images:
9394      * <ul>
9395      * <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>
9396      * <div class="x-tool x-tool-close" style="float:left; margin-right:5;"> </div><div><code> close</code></div>
9397      * <div class="x-tool x-tool-minimize" style="float:left; margin-right:5;"> </div><div><code> minimize</code></div>
9398      * <div class="x-tool x-tool-maximize" style="float:left; margin-right:5;"> </div><div><code> maximize</code></div>
9399      * <div class="x-tool x-tool-restore" style="float:left; margin-right:5;"> </div><div><code> restore</code></div>
9400      * <div class="x-tool x-tool-gear" style="float:left; margin-right:5;"> </div><div><code> gear</code></div>
9401      * <div class="x-tool x-tool-pin" style="float:left; margin-right:5;"> </div><div><code> pin</code></div>
9402      * <div class="x-tool x-tool-unpin" style="float:left; margin-right:5;"> </div><div><code> unpin</code></div>
9403      * <div class="x-tool x-tool-right" style="float:left; margin-right:5;"> </div><div><code> right</code></div>
9404      * <div class="x-tool x-tool-left" style="float:left; margin-right:5;"> </div><div><code> left</code></div>
9405      * <div class="x-tool x-tool-up" style="float:left; margin-right:5;"> </div><div><code> up</code></div>
9406      * <div class="x-tool x-tool-down" style="float:left; margin-right:5;"> </div><div><code> down</code></div>
9407      * <div class="x-tool x-tool-refresh" style="float:left; margin-right:5;"> </div><div><code> refresh</code></div>
9408      * <div class="x-tool x-tool-minus" style="float:left; margin-right:5;"> </div><div><code> minus</code></div>
9409      * <div class="x-tool x-tool-plus" style="float:left; margin-right:5;"> </div><div><code> plus</code></div>
9410      * <div class="x-tool x-tool-help" style="float:left; margin-right:5;"> </div><div><code> help</code></div>
9411      * <div class="x-tool x-tool-search" style="float:left; margin-right:5;"> </div><div><code> search</code></div>
9412      * <div class="x-tool x-tool-save" style="float:left; margin-right:5;"> </div><div><code> save</code></div>
9413      * <div class="x-tool x-tool-print" style="float:left; margin-right:5;"> </div><div><code> print</code></div>
9414      * </ul></div></li>
9415      * <li><b>handler</b> : Function<div class="sub-desc"><b>Required.</b> The function to
9416      * call when clicked. Arguments passed are:<ul>
9417      * <li><b>event</b> : Ext.EventObject<div class="sub-desc">The click event.</div></li>
9418      * <li><b>toolEl</b> : Ext.Element<div class="sub-desc">The tool Element.</div></li>
9419      * <li><b>panel</b> : Ext.Panel<div class="sub-desc">The host Panel</div></li>
9420      * <li><b>tc</b> : Object<div class="sub-desc">The tool configuration object</div></li>
9421      * </ul></div></li>
9422      * <li><b>stopEvent</b> : Boolean<div class="sub-desc">Defaults to true. Specify as false to allow click event to propagate.</div></li>
9423      * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the handler.</div></li>
9424      * <li><b>qtip</b> : String/Object<div class="sub-desc">A tip string, or
9425      * a config argument to {@link Ext.QuickTip#register}</div></li>
9426      * <li><b>hidden</b> : Boolean<div class="sub-desc">True to initially render hidden.</div></li>
9427      * <li><b>on</b> : Object<div class="sub-desc">A listener config object specifiying
9428      * event listeners in the format of an argument to {@link #addListener}</div></li>
9429      * </ul></div>
9430      * <p>Note that, apart from the toggle tool which is provided when a panel is collapsible, these
9431      * tools only provide the visual button. Any required functionality must be provided by adding
9432      * handlers that implement the necessary behavior.</p>
9433      * <p>Example usage:</p>
9434      * <pre><code>
9435 tools:[{
9436     id:'refresh',
9437     qtip: 'Refresh form Data',
9438     // hidden:true,
9439     handler: function(event, toolEl, panel){
9440         // refresh logic
9441     }
9442 },
9443 {
9444     id:'help',
9445     qtip: 'Get Help',
9446     handler: function(event, toolEl, panel){
9447         // whatever
9448     }
9449 }]
9450 </code></pre>
9451      * <p>For the custom id of <code>'help'</code> define two relevant css classes with a link to
9452      * a 15x15 image:</p>
9453      * <pre><code>
9454 .x-tool-help {background-image: url(images/help.png);}
9455 .x-tool-help-over {background-image: url(images/help_over.png);}
9456 // if using an image sprite:
9457 .x-tool-help {background-image: url(images/help.png) no-repeat 0 0;}
9458 .x-tool-help-over {background-position:-15px 0;}
9459 </code></pre>
9460      */
9461     /**
9462      * @cfg {Ext.Template/Ext.XTemplate} toolTemplate
9463      * <p>A Template used to create {@link #tools} in the {@link #header} Element. Defaults to:</p><pre><code>
9464 new Ext.Template('&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>')</code></pre>
9465      * <p>This may may be overridden to provide a custom DOM structure for tools based upon a more
9466      * complex XTemplate. The template's data is a single tool configuration object (Not the entire Array)
9467      * as specified in {@link #tools}.  In the following example an &lt;a> tag is used to provide a
9468      * visual indication when hovering over the tool:</p><pre><code>
9469 var win = new Ext.Window({
9470     tools: [{
9471         id: 'download',
9472         href: '/MyPdfDoc.pdf'
9473     }],
9474     toolTemplate: new Ext.XTemplate(
9475         '&lt;tpl if="id==\'download\'">',
9476             '&lt;a class="x-tool x-tool-pdf" href="{href}">&lt;/a>',
9477         '&lt;/tpl>',
9478         '&lt;tpl if="id!=\'download\'">',
9479             '&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>',
9480         '&lt;/tpl>'
9481     ),
9482     width:500,
9483     height:300,
9484     closeAction:'hide'
9485 });</code></pre>
9486      * <p>Note that the CSS class 'x-tool-pdf' should have an associated style rule which provides an
9487      * appropriate background image, something like:</p>
9488     <pre><code>
9489     a.x-tool-pdf {background-image: url(../shared/extjs/images/pdf.gif)!important;}
9490     </code></pre>
9491      */
9492     /**
9493      * @cfg {Boolean} hideCollapseTool
9494      * <code>true</code> to hide the expand/collapse toggle button when <code>{@link #collapsible} == true</code>,
9495      * <code>false</code> to display it (defaults to <code>false</code>).
9496      */
9497     /**
9498      * @cfg {Boolean} titleCollapse
9499      * <code>true</code> to allow expanding and collapsing the panel (when <code>{@link #collapsible} = true</code>)
9500      * by clicking anywhere in the header bar, <code>false</code>) to allow it only by clicking to tool button
9501      * (defaults to <code>false</code>)). If this panel is a child item of a border layout also see the
9502      * {@link Ext.layout.BorderLayout.Region BorderLayout.Region}
9503      * <code>{@link Ext.layout.BorderLayout.Region#floatable floatable}</code> config option.
9504      */
9505
9506     /**
9507      * @cfg {Mixed} floating
9508      * <p>This property is used to configure the underlying {@link Ext.Layer}. Acceptable values for this
9509      * configuration property are:</p><div class="mdetail-params"><ul>
9510      * <li><b><code>false</code></b> : <b>Default.</b><div class="sub-desc">Display the panel inline where it is
9511      * rendered.</div></li>
9512      * <li><b><code>true</code></b> : <div class="sub-desc">Float the panel (absolute position it with automatic
9513      * shimming and shadow).<ul>
9514      * <div class="sub-desc">Setting floating to true will create an Ext.Layer for this panel and display the
9515      * panel at negative offsets so that it is hidden.</div>
9516      * <div class="sub-desc">Since the panel will be absolute positioned, the position must be set explicitly
9517      * <i>after</i> render (e.g., <code>myPanel.setPosition(100,100);</code>).</div>
9518      * <div class="sub-desc"><b>Note</b>: when floating a panel you should always assign a fixed width,
9519      * otherwise it will be auto width and will expand to fill to the right edge of the viewport.</div>
9520      * </ul></div></li>
9521      * <li><b><code>{@link Ext.Layer object}</code></b> : <div class="sub-desc">The specified object will be used
9522      * as the configuration object for the {@link Ext.Layer} that will be created.</div></li>
9523      * </ul></div>
9524      */
9525     /**
9526      * @cfg {Boolean/String} shadow
9527      * <code>true</code> (or a valid Ext.Shadow {@link Ext.Shadow#mode} value) to display a shadow behind the
9528      * panel, <code>false</code> to display no shadow (defaults to <code>'sides'</code>).  Note that this option
9529      * only applies when <code>{@link #floating} = true</code>.
9530      */
9531     /**
9532      * @cfg {Number} shadowOffset
9533      * The number of pixels to offset the shadow if displayed (defaults to <code>4</code>). Note that this
9534      * option only applies when <code>{@link #floating} = true</code>.
9535      */
9536     /**
9537      * @cfg {Boolean} shim
9538      * <code>false</code> to disable the iframe shim in browsers which need one (defaults to <code>true</code>).
9539      * Note that this option only applies when <code>{@link #floating} = true</code>.
9540      */
9541     /**
9542      * @cfg {Object/Array} keys
9543      * A {@link Ext.KeyMap} config object (in the format expected by {@link Ext.KeyMap#addBinding}
9544      * used to assign custom key handling to this panel (defaults to <code>null</code>).
9545      */
9546     /**
9547      * @cfg {Boolean/Object} draggable
9548      * <p><code>true</code> to enable dragging of this Panel (defaults to <code>false</code>).</p>
9549      * <p>For custom drag/drop implementations, an <b>Ext.Panel.DD</b> config could also be passed
9550      * in this config instead of <code>true</code>. Ext.Panel.DD is an internal, undocumented class which
9551      * moves a proxy Element around in place of the Panel's element, but provides no other behaviour
9552      * during dragging or on drop. It is a subclass of {@link Ext.dd.DragSource}, so behaviour may be
9553      * added by implementing the interface methods of {@link Ext.dd.DragDrop} e.g.:
9554      * <pre><code>
9555 new Ext.Panel({
9556     title: 'Drag me',
9557     x: 100,
9558     y: 100,
9559     renderTo: Ext.getBody(),
9560     floating: true,
9561     frame: true,
9562     width: 400,
9563     height: 200,
9564     draggable: {
9565 //      Config option of Ext.Panel.DD class.
9566 //      It&#39;s a floating Panel, so do not show a placeholder proxy in the original position.
9567         insertProxy: false,
9568
9569 //      Called for each mousemove event while dragging the DD object.
9570         onDrag : function(e){
9571 //          Record the x,y position of the drag proxy so that we can
9572 //          position the Panel at end of drag.
9573             var pel = this.proxy.getEl();
9574             this.x = pel.getLeft(true);
9575             this.y = pel.getTop(true);
9576
9577 //          Keep the Shadow aligned if there is one.
9578             var s = this.panel.getEl().shadow;
9579             if (s) {
9580                 s.realign(this.x, this.y, pel.getWidth(), pel.getHeight());
9581             }
9582         },
9583
9584 //      Called on the mouseup event.
9585         endDrag : function(e){
9586             this.panel.setPosition(this.x, this.y);
9587         }
9588     }
9589 }).show();
9590 </code></pre>
9591      */
9592     /**
9593      * @cfg {Boolean} disabled
9594      * Render this panel disabled (default is <code>false</code>). An important note when using the disabled
9595      * config on panels is that IE will often fail to initialize the disabled mask element correectly if
9596      * the panel's layout has not yet completed by the time the Panel is disabled during the render process.
9597      * If you experience this issue, you may need to instead use the {@link #afterlayout} event to initialize
9598      * the disabled state:
9599      * <pre><code>
9600 new Ext.Panel({
9601     ...
9602     listeners: {
9603         'afterlayout': {
9604             fn: function(p){
9605                 p.disable();
9606             },
9607             single: true // important, as many layouts can occur
9608         }
9609     }
9610 });
9611 </code></pre>
9612      */
9613     /**
9614      * @cfg {Boolean} autoHeight
9615      * <code>true</code> to use height:'auto', <code>false</code> to use fixed height (defaults to <code>false</code>).
9616      * <b>Note</b>: Setting <code>autoHeight: true</code> means that the browser will manage the panel's height
9617      * based on its contents, and that Ext will not manage it at all. If the panel is within a layout that
9618      * manages dimensions (<code>fit</code>, <code>border</code>, etc.) then setting <code>autoHeight: true</code>
9619      * can cause issues with scrolling and will not generally work as expected since the panel will take
9620      * on the height of its contents rather than the height required by the Ext layout.
9621      */
9622
9623
9624     /**
9625      * @cfg {String} baseCls
9626      * The base CSS class to apply to this panel's element (defaults to <code>'x-panel'</code>).
9627      * <p>Another option available by default is to specify <code>'x-plain'</code> which strips all styling
9628      * except for required attributes for Ext layouts to function (e.g. overflow:hidden).
9629      * See <code>{@link #unstyled}</code> also.</p>
9630      */
9631     baseCls : 'x-panel',
9632     /**
9633      * @cfg {String} collapsedCls
9634      * A CSS class to add to the panel's element after it has been collapsed (defaults to
9635      * <code>'x-panel-collapsed'</code>).
9636      */
9637     collapsedCls : 'x-panel-collapsed',
9638     /**
9639      * @cfg {Boolean} maskDisabled
9640      * <code>true</code> to mask the panel when it is {@link #disabled}, <code>false</code> to not mask it (defaults
9641      * to <code>true</code>).  Either way, the panel will always tell its contained elements to disable themselves
9642      * when it is disabled, but masking the panel can provide an additional visual cue that the panel is
9643      * disabled.
9644      */
9645     maskDisabled : true,
9646     /**
9647      * @cfg {Boolean} animCollapse
9648      * <code>true</code> to animate the transition when the panel is collapsed, <code>false</code> to skip the
9649      * animation (defaults to <code>true</code> if the {@link Ext.Fx} class is available, otherwise <code>false</code>).
9650      */
9651     animCollapse : Ext.enableFx,
9652     /**
9653      * @cfg {Boolean} headerAsText
9654      * <code>true</code> to display the panel <code>{@link #title}</code> in the <code>{@link #header}</code>,
9655      * <code>false</code> to hide it (defaults to <code>true</code>).
9656      */
9657     headerAsText : true,
9658     /**
9659      * @cfg {String} buttonAlign
9660      * The alignment of any {@link #buttons} added to this panel.  Valid values are <code>'right'</code>,
9661      * <code>'left'</code> and <code>'center'</code> (defaults to <code>'right'</code>).
9662      */
9663     buttonAlign : 'right',
9664     /**
9665      * @cfg {Boolean} collapsed
9666      * <code>true</code> to render the panel collapsed, <code>false</code> to render it expanded (defaults to
9667      * <code>false</code>).
9668      */
9669     collapsed : false,
9670     /**
9671      * @cfg {Boolean} collapseFirst
9672      * <code>true</code> to make sure the collapse/expand toggle button always renders first (to the left of)
9673      * any other tools in the panel's title bar, <code>false</code> to render it last (defaults to <code>true</code>).
9674      */
9675     collapseFirst : true,
9676     /**
9677      * @cfg {Number} minButtonWidth
9678      * Minimum width in pixels of all {@link #buttons} in this panel (defaults to <code>75</code>)
9679      */
9680     minButtonWidth : 75,
9681     /**
9682      * @cfg {Boolean} unstyled
9683      * Overrides the <code>{@link #baseCls}</code> setting to <code>{@link #baseCls} = 'x-plain'</code> which renders
9684      * the panel unstyled except for required attributes for Ext layouts to function (e.g. overflow:hidden).
9685      */
9686     /**
9687      * @cfg {String} elements
9688      * A comma-delimited list of panel elements to initialize when the panel is rendered.  Normally, this list will be
9689      * generated automatically based on the items added to the panel at config time, but sometimes it might be useful to
9690      * make sure a structural element is rendered even if not specified at config time (for example, you may want
9691      * to add a button or toolbar dynamically after the panel has been rendered).  Adding those elements to this
9692      * list will allocate the required placeholders in the panel when it is rendered.  Valid values are<div class="mdetail-params"><ul>
9693      * <li><code>header</code></li>
9694      * <li><code>tbar</code> (top bar)</li>
9695      * <li><code>body</code></li>
9696      * <li><code>bbar</code> (bottom bar)</li>
9697      * <li><code>footer</code></li>
9698      * </ul></div>
9699      * Defaults to '<code>body</code>'.
9700      */
9701     elements : 'body',
9702     /**
9703      * @cfg {Boolean} preventBodyReset
9704      * Defaults to <code>false</code>.  When set to <code>true</code>, an extra css class <code>'x-panel-normal'</code>
9705      * will be added to the panel's element, effectively applying css styles suggested by the W3C
9706      * (see http://www.w3.org/TR/CSS21/sample.html) to the Panel's <b>body</b> element (not the header,
9707      * footer, etc.).
9708      */
9709     preventBodyReset : false,
9710
9711     /**
9712      * @cfg {Number/String} padding
9713      * A shortcut for setting a padding style on the body element. The value can either be
9714      * a number to be applied to all sides, or a normal css string describing padding.
9715      * Defaults to <tt>undefined</tt>.
9716      *
9717      */
9718     padding: undefined,
9719
9720     /** @cfg {String} resizeEvent
9721      * The event to listen to for resizing in layouts. Defaults to <tt>'bodyresize'</tt>.
9722      */
9723     resizeEvent: 'bodyresize',
9724
9725     // protected - these could be used to customize the behavior of the window,
9726     // but changing them would not be useful without further mofifications and
9727     // could lead to unexpected or undesirable results.
9728     toolTarget : 'header',
9729     collapseEl : 'bwrap',
9730     slideAnchor : 't',
9731     disabledClass : '',
9732
9733     // private, notify box this class will handle heights
9734     deferHeight : true,
9735     // private
9736     expandDefaults: {
9737         duration : 0.25
9738     },
9739     // private
9740     collapseDefaults : {
9741         duration : 0.25
9742     },
9743
9744     // private
9745     initComponent : function(){
9746         Ext.Panel.superclass.initComponent.call(this);
9747
9748         this.addEvents(
9749             /**
9750              * @event bodyresize
9751              * Fires after the Panel has been resized.
9752              * @param {Ext.Panel} p the Panel which has been resized.
9753              * @param {Number} width The Panel body's new width.
9754              * @param {Number} height The Panel body's new height.
9755              */
9756             'bodyresize',
9757             /**
9758              * @event titlechange
9759              * Fires after the Panel title has been {@link #title set} or {@link #setTitle changed}.
9760              * @param {Ext.Panel} p the Panel which has had its title changed.
9761              * @param {String} The new title.
9762              */
9763             'titlechange',
9764             /**
9765              * @event iconchange
9766              * Fires after the Panel icon class has been {@link #iconCls set} or {@link #setIconClass changed}.
9767              * @param {Ext.Panel} p the Panel which has had its {@link #iconCls icon class} changed.
9768              * @param {String} The new icon class.
9769              * @param {String} The old icon class.
9770              */
9771             'iconchange',
9772             /**
9773              * @event collapse
9774              * Fires after the Panel has been collapsed.
9775              * @param {Ext.Panel} p the Panel that has been collapsed.
9776              */
9777             'collapse',
9778             /**
9779              * @event expand
9780              * Fires after the Panel has been expanded.
9781              * @param {Ext.Panel} p The Panel that has been expanded.
9782              */
9783             'expand',
9784             /**
9785              * @event beforecollapse
9786              * Fires before the Panel is collapsed.  A handler can return false to cancel the collapse.
9787              * @param {Ext.Panel} p the Panel being collapsed.
9788              * @param {Boolean} animate True if the collapse is animated, else false.
9789              */
9790             'beforecollapse',
9791             /**
9792              * @event beforeexpand
9793              * Fires before the Panel is expanded.  A handler can return false to cancel the expand.
9794              * @param {Ext.Panel} p The Panel being expanded.
9795              * @param {Boolean} animate True if the expand is animated, else false.
9796              */
9797             'beforeexpand',
9798             /**
9799              * @event beforeclose
9800              * Fires before the Panel is closed.  Note that Panels do not directly support being closed, but some
9801              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.  This event only
9802              * applies to such subclasses.
9803              * A handler can return false to cancel the close.
9804              * @param {Ext.Panel} p The Panel being closed.
9805              */
9806             'beforeclose',
9807             /**
9808              * @event close
9809              * Fires after the Panel is closed.  Note that Panels do not directly support being closed, but some
9810              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.
9811              * @param {Ext.Panel} p The Panel that has been closed.
9812              */
9813             'close',
9814             /**
9815              * @event activate
9816              * Fires after the Panel has been visually activated.
9817              * Note that Panels do not directly support being activated, but some Panel subclasses
9818              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
9819              * activate and deactivate events under the control of the TabPanel.
9820              * @param {Ext.Panel} p The Panel that has been activated.
9821              */
9822             'activate',
9823             /**
9824              * @event deactivate
9825              * Fires after the Panel has been visually deactivated.
9826              * Note that Panels do not directly support being deactivated, but some Panel subclasses
9827              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
9828              * activate and deactivate events under the control of the TabPanel.
9829              * @param {Ext.Panel} p The Panel that has been deactivated.
9830              */
9831             'deactivate'
9832         );
9833
9834         if(this.unstyled){
9835             this.baseCls = 'x-plain';
9836         }
9837
9838
9839         this.toolbars = [];
9840         // shortcuts
9841         if(this.tbar){
9842             this.elements += ',tbar';
9843             this.topToolbar = this.createToolbar(this.tbar);
9844             this.tbar = null;
9845
9846         }
9847         if(this.bbar){
9848             this.elements += ',bbar';
9849             this.bottomToolbar = this.createToolbar(this.bbar);
9850             this.bbar = null;
9851         }
9852
9853         if(this.header === true){
9854             this.elements += ',header';
9855             this.header = null;
9856         }else if(this.headerCfg || (this.title && this.header !== false)){
9857             this.elements += ',header';
9858         }
9859
9860         if(this.footerCfg || this.footer === true){
9861             this.elements += ',footer';
9862             this.footer = null;
9863         }
9864
9865         if(this.buttons){
9866             this.fbar = this.buttons;
9867             this.buttons = null;
9868         }
9869         if(this.fbar){
9870             this.createFbar(this.fbar);
9871         }
9872         if(this.autoLoad){
9873             this.on('render', this.doAutoLoad, this, {delay:10});
9874         }
9875     },
9876
9877     // private
9878     createFbar : function(fbar){
9879         var min = this.minButtonWidth;
9880         this.elements += ',footer';
9881         this.fbar = this.createToolbar(fbar, {
9882             buttonAlign: this.buttonAlign,
9883             toolbarCls: 'x-panel-fbar',
9884             enableOverflow: false,
9885             defaults: function(c){
9886                 return {
9887                     minWidth: c.minWidth || min
9888                 };
9889             }
9890         });
9891         // @compat addButton and buttons could possibly be removed
9892         // @target 4.0
9893         /**
9894          * This Panel's Array of buttons as created from the <code>{@link #buttons}</code>
9895          * config property. Read only.
9896          * @type Array
9897          * @property buttons
9898          */
9899         this.fbar.items.each(function(c){
9900             c.minWidth = c.minWidth || this.minButtonWidth;
9901         }, this);
9902         this.buttons = this.fbar.items.items;
9903     },
9904
9905     // private
9906     createToolbar: function(tb, options){
9907         var result;
9908         // Convert array to proper toolbar config
9909         if(Ext.isArray(tb)){
9910             tb = {
9911                 items: tb
9912             };
9913         }
9914         result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
9915         this.toolbars.push(result);
9916         return result;
9917     },
9918
9919     // private
9920     createElement : function(name, pnode){
9921         if(this[name]){
9922             pnode.appendChild(this[name].dom);
9923             return;
9924         }
9925
9926         if(name === 'bwrap' || this.elements.indexOf(name) != -1){
9927             if(this[name+'Cfg']){
9928                 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
9929             }else{
9930                 var el = document.createElement('div');
9931                 el.className = this[name+'Cls'];
9932                 this[name] = Ext.get(pnode.appendChild(el));
9933             }
9934             if(this[name+'CssClass']){
9935                 this[name].addClass(this[name+'CssClass']);
9936             }
9937             if(this[name+'Style']){
9938                 this[name].applyStyles(this[name+'Style']);
9939             }
9940         }
9941     },
9942
9943     // private
9944     onRender : function(ct, position){
9945         Ext.Panel.superclass.onRender.call(this, ct, position);
9946         this.createClasses();
9947
9948         var el = this.el,
9949             d = el.dom,
9950             bw,
9951             ts;
9952
9953
9954         if(this.collapsible && !this.hideCollapseTool){
9955             this.tools = this.tools ? this.tools.slice(0) : [];
9956             this.tools[this.collapseFirst?'unshift':'push']({
9957                 id: 'toggle',
9958                 handler : this.toggleCollapse,
9959                 scope: this
9960             });
9961         }
9962
9963         if(this.tools){
9964             ts = this.tools;
9965             this.elements += (this.header !== false) ? ',header' : '';
9966         }
9967         this.tools = {};
9968
9969         el.addClass(this.baseCls);
9970         if(d.firstChild){ // existing markup
9971             this.header = el.down('.'+this.headerCls);
9972             this.bwrap = el.down('.'+this.bwrapCls);
9973             var cp = this.bwrap ? this.bwrap : el;
9974             this.tbar = cp.down('.'+this.tbarCls);
9975             this.body = cp.down('.'+this.bodyCls);
9976             this.bbar = cp.down('.'+this.bbarCls);
9977             this.footer = cp.down('.'+this.footerCls);
9978             this.fromMarkup = true;
9979         }
9980         if (this.preventBodyReset === true) {
9981             el.addClass('x-panel-reset');
9982         }
9983         if(this.cls){
9984             el.addClass(this.cls);
9985         }
9986
9987         if(this.buttons){
9988             this.elements += ',footer';
9989         }
9990
9991         // This block allows for maximum flexibility and performance when using existing markup
9992
9993         // framing requires special markup
9994         if(this.frame){
9995             el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
9996
9997             this.createElement('header', d.firstChild.firstChild.firstChild);
9998             this.createElement('bwrap', d);
9999
10000             // append the mid and bottom frame to the bwrap
10001             bw = this.bwrap.dom;
10002             var ml = d.childNodes[1], bl = d.childNodes[2];
10003             bw.appendChild(ml);
10004             bw.appendChild(bl);
10005
10006             var mc = bw.firstChild.firstChild.firstChild;
10007             this.createElement('tbar', mc);
10008             this.createElement('body', mc);
10009             this.createElement('bbar', mc);
10010             this.createElement('footer', bw.lastChild.firstChild.firstChild);
10011
10012             if(!this.footer){
10013                 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
10014             }
10015             /*
10016              * Store a reference to this element so:
10017              * a) We aren't looking it up all the time
10018              * b) The last element is reported incorrectly when using a loadmask
10019              */
10020             this.ft = Ext.get(this.bwrap.dom.lastChild);
10021             this.mc = Ext.get(mc);
10022         }else{
10023             this.createElement('header', d);
10024             this.createElement('bwrap', d);
10025
10026             // append the mid and bottom frame to the bwrap
10027             bw = this.bwrap.dom;
10028             this.createElement('tbar', bw);
10029             this.createElement('body', bw);
10030             this.createElement('bbar', bw);
10031             this.createElement('footer', bw);
10032
10033             if(!this.header){
10034                 this.body.addClass(this.bodyCls + '-noheader');
10035                 if(this.tbar){
10036                     this.tbar.addClass(this.tbarCls + '-noheader');
10037                 }
10038             }
10039         }
10040
10041         if(Ext.isDefined(this.padding)){
10042             this.body.setStyle('padding', this.body.addUnits(this.padding));
10043         }
10044
10045         if(this.border === false){
10046             this.el.addClass(this.baseCls + '-noborder');
10047             this.body.addClass(this.bodyCls + '-noborder');
10048             if(this.header){
10049                 this.header.addClass(this.headerCls + '-noborder');
10050             }
10051             if(this.footer){
10052                 this.footer.addClass(this.footerCls + '-noborder');
10053             }
10054             if(this.tbar){
10055                 this.tbar.addClass(this.tbarCls + '-noborder');
10056             }
10057             if(this.bbar){
10058                 this.bbar.addClass(this.bbarCls + '-noborder');
10059             }
10060         }
10061
10062         if(this.bodyBorder === false){
10063            this.body.addClass(this.bodyCls + '-noborder');
10064         }
10065
10066         this.bwrap.enableDisplayMode('block');
10067
10068         if(this.header){
10069             this.header.unselectable();
10070
10071             // for tools, we need to wrap any existing header markup
10072             if(this.headerAsText){
10073                 this.header.dom.innerHTML =
10074                     '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
10075
10076                 if(this.iconCls){
10077                     this.setIconClass(this.iconCls);
10078                 }
10079             }
10080         }
10081
10082         if(this.floating){
10083             this.makeFloating(this.floating);
10084         }
10085
10086         if(this.collapsible && this.titleCollapse && this.header){
10087             this.mon(this.header, 'click', this.toggleCollapse, this);
10088             this.header.setStyle('cursor', 'pointer');
10089         }
10090         if(ts){
10091             this.addTool.apply(this, ts);
10092         }
10093
10094         // Render Toolbars.
10095         if(this.fbar){
10096             this.footer.addClass('x-panel-btns');
10097             this.fbar.ownerCt = this;
10098             this.fbar.render(this.footer);
10099             this.footer.createChild({cls:'x-clear'});
10100         }
10101         if(this.tbar && this.topToolbar){
10102             this.topToolbar.ownerCt = this;
10103             this.topToolbar.render(this.tbar);
10104         }
10105         if(this.bbar && this.bottomToolbar){
10106             this.bottomToolbar.ownerCt = this;
10107             this.bottomToolbar.render(this.bbar);
10108         }
10109     },
10110
10111     /**
10112      * Sets the CSS class that provides the icon image for this panel.  This method will replace any existing
10113      * icon class if one has already been set and fire the {@link #iconchange} event after completion.
10114      * @param {String} cls The new CSS class name
10115      */
10116     setIconClass : function(cls){
10117         var old = this.iconCls;
10118         this.iconCls = cls;
10119         if(this.rendered && this.header){
10120             if(this.frame){
10121                 this.header.addClass('x-panel-icon');
10122                 this.header.replaceClass(old, this.iconCls);
10123             }else{
10124                 var hd = this.header,
10125                     img = hd.child('img.x-panel-inline-icon');
10126                 if(img){
10127                     Ext.fly(img).replaceClass(old, this.iconCls);
10128                 }else{
10129                     var hdspan = hd.child('span.' + this.headerTextCls);
10130                     if (hdspan) {
10131                         Ext.DomHelper.insertBefore(hdspan.dom, {
10132                             tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
10133                         });
10134                     }
10135                  }
10136             }
10137         }
10138         this.fireEvent('iconchange', this, cls, old);
10139     },
10140
10141     // private
10142     makeFloating : function(cfg){
10143         this.floating = true;
10144         this.el = new Ext.Layer(Ext.apply({}, cfg, {
10145             shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
10146             shadowOffset: this.shadowOffset,
10147             constrain:false,
10148             shim: this.shim === false ? false : undefined
10149         }), this.el);
10150     },
10151
10152     /**
10153      * Returns the {@link Ext.Toolbar toolbar} from the top (<code>{@link #tbar}</code>) section of the panel.
10154      * @return {Ext.Toolbar} The toolbar
10155      */
10156     getTopToolbar : function(){
10157         return this.topToolbar;
10158     },
10159
10160     /**
10161      * Returns the {@link Ext.Toolbar toolbar} from the bottom (<code>{@link #bbar}</code>) section of the panel.
10162      * @return {Ext.Toolbar} The toolbar
10163      */
10164     getBottomToolbar : function(){
10165         return this.bottomToolbar;
10166     },
10167
10168     /**
10169      * Returns the {@link Ext.Toolbar toolbar} from the footer (<code>{@link #fbar}</code>) section of the panel.
10170      * @return {Ext.Toolbar} The toolbar
10171      */
10172     getFooterToolbar : function() {
10173         return this.fbar;
10174     },
10175
10176     /**
10177      * Adds a button to this panel.  Note that this method must be called prior to rendering.  The preferred
10178      * approach is to add buttons via the {@link #buttons} config.
10179      * @param {String/Object} config A valid {@link Ext.Button} config.  A string will become the text for a default
10180      * button config, an object will be treated as a button config object.
10181      * @param {Function} handler The function to be called on button {@link Ext.Button#click}
10182      * @param {Object} scope The scope (<code>this</code> reference) in which the button handler function is executed. Defaults to the Button.
10183      * @return {Ext.Button} The button that was added
10184      */
10185     addButton : function(config, handler, scope){
10186         if(!this.fbar){
10187             this.createFbar([]);
10188         }
10189         if(handler){
10190             if(Ext.isString(config)){
10191                 config = {text: config};
10192             }
10193             config = Ext.apply({
10194                 handler: handler,
10195                 scope: scope
10196             }, config);
10197         }
10198         return this.fbar.add(config);
10199     },
10200
10201     // private
10202     addTool : function(){
10203         if(!this.rendered){
10204             if(!this.tools){
10205                 this.tools = [];
10206             }
10207             Ext.each(arguments, function(arg){
10208                 this.tools.push(arg);
10209             }, this);
10210             return;
10211         }
10212          // nowhere to render tools!
10213         if(!this[this.toolTarget]){
10214             return;
10215         }
10216         if(!this.toolTemplate){
10217             // initialize the global tool template on first use
10218             var tt = new Ext.Template(
10219                  '<div class="x-tool x-tool-{id}">&#160;</div>'
10220             );
10221             tt.disableFormats = true;
10222             tt.compile();
10223             Ext.Panel.prototype.toolTemplate = tt;
10224         }
10225         for(var i = 0, a = arguments, len = a.length; i < len; i++) {
10226             var tc = a[i];
10227             if(!this.tools[tc.id]){
10228                 var overCls = 'x-tool-'+tc.id+'-over';
10229                 var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
10230                 this.tools[tc.id] = t;
10231                 t.enableDisplayMode('block');
10232                 this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
10233                 if(tc.on){
10234                     this.mon(t, tc.on);
10235                 }
10236                 if(tc.hidden){
10237                     t.hide();
10238                 }
10239                 if(tc.qtip){
10240                     if(Ext.isObject(tc.qtip)){
10241                         Ext.QuickTips.register(Ext.apply({
10242                               target: t.id
10243                         }, tc.qtip));
10244                     } else {
10245                         t.dom.qtip = tc.qtip;
10246                     }
10247                 }
10248                 t.addClassOnOver(overCls);
10249             }
10250         }
10251     },
10252
10253     onLayout : function(shallow, force){
10254         Ext.Panel.superclass.onLayout.apply(this, arguments);
10255         if(this.hasLayout && this.toolbars.length > 0){
10256             Ext.each(this.toolbars, function(tb){
10257                 tb.doLayout(undefined, force);
10258             });
10259             this.syncHeight();
10260         }
10261     },
10262
10263     syncHeight : function(){
10264         var h = this.toolbarHeight,
10265                 bd = this.body,
10266                 lsh = this.lastSize.height,
10267                 sz;
10268
10269         if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
10270             return;
10271         }
10272
10273
10274         if(h != this.getToolbarHeight()){
10275             h = Math.max(0, lsh - this.getFrameHeight());
10276             bd.setHeight(h);
10277             sz = bd.getSize();
10278             this.toolbarHeight = this.getToolbarHeight();
10279             this.onBodyResize(sz.width, sz.height);
10280         }
10281     },
10282
10283     // private
10284     onShow : function(){
10285         if(this.floating){
10286             return this.el.show();
10287         }
10288         Ext.Panel.superclass.onShow.call(this);
10289     },
10290
10291     // private
10292     onHide : function(){
10293         if(this.floating){
10294             return this.el.hide();
10295         }
10296         Ext.Panel.superclass.onHide.call(this);
10297     },
10298
10299     // private
10300     createToolHandler : function(t, tc, overCls, panel){
10301         return function(e){
10302             t.removeClass(overCls);
10303             if(tc.stopEvent !== false){
10304                 e.stopEvent();
10305             }
10306             if(tc.handler){
10307                 tc.handler.call(tc.scope || t, e, t, panel, tc);
10308             }
10309         };
10310     },
10311
10312     // private
10313     afterRender : function(){
10314         if(this.floating && !this.hidden){
10315             this.el.show();
10316         }
10317         if(this.title){
10318             this.setTitle(this.title);
10319         }
10320         Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
10321         if (this.collapsed) {
10322             this.collapsed = false;
10323             this.collapse(false);
10324         }
10325         this.initEvents();
10326     },
10327
10328     // private
10329     getKeyMap : function(){
10330         if(!this.keyMap){
10331             this.keyMap = new Ext.KeyMap(this.el, this.keys);
10332         }
10333         return this.keyMap;
10334     },
10335
10336     // private
10337     initEvents : function(){
10338         if(this.keys){
10339             this.getKeyMap();
10340         }
10341         if(this.draggable){
10342             this.initDraggable();
10343         }
10344         if(this.toolbars.length > 0){
10345             Ext.each(this.toolbars, function(tb){
10346                 tb.doLayout();
10347                 tb.on({
10348                     scope: this,
10349                     afterlayout: this.syncHeight,
10350                     remove: this.syncHeight
10351                 });
10352             }, this);
10353             this.syncHeight();
10354         }
10355
10356     },
10357
10358     // private
10359     initDraggable : function(){
10360         /**
10361          * <p>If this Panel is configured {@link #draggable}, this property will contain
10362          * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.</p>
10363          * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource}
10364          * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
10365          * @type Ext.dd.DragSource.
10366          * @property dd
10367          */
10368         this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
10369     },
10370
10371     // private
10372     beforeEffect : function(anim){
10373         if(this.floating){
10374             this.el.beforeAction();
10375         }
10376         if(anim !== false){
10377             this.el.addClass('x-panel-animated');
10378         }
10379     },
10380
10381     // private
10382     afterEffect : function(anim){
10383         this.syncShadow();
10384         this.el.removeClass('x-panel-animated');
10385     },
10386
10387     // private - wraps up an animation param with internal callbacks
10388     createEffect : function(a, cb, scope){
10389         var o = {
10390             scope:scope,
10391             block:true
10392         };
10393         if(a === true){
10394             o.callback = cb;
10395             return o;
10396         }else if(!a.callback){
10397             o.callback = cb;
10398         }else { // wrap it up
10399             o.callback = function(){
10400                 cb.call(scope);
10401                 Ext.callback(a.callback, a.scope);
10402             };
10403         }
10404         return Ext.applyIf(o, a);
10405     },
10406
10407     /**
10408      * Collapses the panel body so that it becomes hidden.  Fires the {@link #beforecollapse} event which will
10409      * cancel the collapse action if it returns false.
10410      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
10411      * {@link #animCollapse} panel config)
10412      * @return {Ext.Panel} this
10413      */
10414     collapse : function(animate){
10415         if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
10416             return;
10417         }
10418         var doAnim = animate === true || (animate !== false && this.animCollapse);
10419         this.beforeEffect(doAnim);
10420         this.onCollapse(doAnim, animate);
10421         return this;
10422     },
10423
10424     // private
10425     onCollapse : function(doAnim, animArg){
10426         if(doAnim){
10427             this[this.collapseEl].slideOut(this.slideAnchor,
10428                     Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
10429                         this.collapseDefaults));
10430         }else{
10431             this[this.collapseEl].hide(this.hideMode);
10432             this.afterCollapse(false);
10433         }
10434     },
10435
10436     // private
10437     afterCollapse : function(anim){
10438         this.collapsed = true;
10439         this.el.addClass(this.collapsedCls);
10440         if(anim !== false){
10441             this[this.collapseEl].hide(this.hideMode);
10442         }
10443         this.afterEffect(anim);
10444
10445         // Reset lastSize of all sub-components so they KNOW they are in a collapsed container
10446         this.cascade(function(c) {
10447             if (c.lastSize) {
10448                 c.lastSize = { width: undefined, height: undefined };
10449             }
10450         });
10451         this.fireEvent('collapse', this);
10452     },
10453
10454     /**
10455      * Expands the panel body so that it becomes visible.  Fires the {@link #beforeexpand} event which will
10456      * cancel the expand action if it returns false.
10457      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
10458      * {@link #animCollapse} panel config)
10459      * @return {Ext.Panel} this
10460      */
10461     expand : function(animate){
10462         if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
10463             return;
10464         }
10465         var doAnim = animate === true || (animate !== false && this.animCollapse);
10466         this.el.removeClass(this.collapsedCls);
10467         this.beforeEffect(doAnim);
10468         this.onExpand(doAnim, animate);
10469         return this;
10470     },
10471
10472     // private
10473     onExpand : function(doAnim, animArg){
10474         if(doAnim){
10475             this[this.collapseEl].slideIn(this.slideAnchor,
10476                     Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
10477                         this.expandDefaults));
10478         }else{
10479             this[this.collapseEl].show(this.hideMode);
10480             this.afterExpand(false);
10481         }
10482     },
10483
10484     // private
10485     afterExpand : function(anim){
10486         this.collapsed = false;
10487         if(anim !== false){
10488             this[this.collapseEl].show(this.hideMode);
10489         }
10490         this.afterEffect(anim);
10491         if (this.deferLayout) {
10492             delete this.deferLayout;
10493             this.doLayout(true);
10494         }
10495         this.fireEvent('expand', this);
10496     },
10497
10498     /**
10499      * Shortcut for performing an {@link #expand} or {@link #collapse} based on the current state of the panel.
10500      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
10501      * {@link #animCollapse} panel config)
10502      * @return {Ext.Panel} this
10503      */
10504     toggleCollapse : function(animate){
10505         this[this.collapsed ? 'expand' : 'collapse'](animate);
10506         return this;
10507     },
10508
10509     // private
10510     onDisable : function(){
10511         if(this.rendered && this.maskDisabled){
10512             this.el.mask();
10513         }
10514         Ext.Panel.superclass.onDisable.call(this);
10515     },
10516
10517     // private
10518     onEnable : function(){
10519         if(this.rendered && this.maskDisabled){
10520             this.el.unmask();
10521         }
10522         Ext.Panel.superclass.onEnable.call(this);
10523     },
10524
10525     // private
10526     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
10527         var w = adjWidth,
10528             h = adjHeight;
10529
10530         if(Ext.isDefined(w) || Ext.isDefined(h)){
10531             if(!this.collapsed){
10532                 // First, set the the Panel's body width.
10533                 // If we have auto-widthed it, get the resulting full offset width so we can size the Toolbars to match
10534                 // The Toolbars must not buffer this resize operation because we need to know their heights.
10535
10536                 if(Ext.isNumber(w)){
10537                     this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
10538                 } else if (w == 'auto') {
10539                     w = this.body.setWidth('auto').dom.offsetWidth;
10540                 } else {
10541                     w = this.body.dom.offsetWidth;
10542                 }
10543
10544                 if(this.tbar){
10545                     this.tbar.setWidth(w);
10546                     if(this.topToolbar){
10547                         this.topToolbar.setSize(w);
10548                     }
10549                 }
10550                 if(this.bbar){
10551                     this.bbar.setWidth(w);
10552                     if(this.bottomToolbar){
10553                         this.bottomToolbar.setSize(w);
10554                         // The bbar does not move on resize without this.
10555                         if (Ext.isIE) {
10556                             this.bbar.setStyle('position', 'static');
10557                             this.bbar.setStyle('position', '');
10558                         }
10559                     }
10560                 }
10561                 if(this.footer){
10562                     this.footer.setWidth(w);
10563                     if(this.fbar){
10564                         this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
10565                     }
10566                 }
10567
10568                 // At this point, the Toolbars must be layed out for getFrameHeight to find a result.
10569                 if(Ext.isNumber(h)){
10570                     h = Math.max(0, h - this.getFrameHeight());
10571                     //h = Math.max(0, h - (this.getHeight() - this.body.getHeight()));
10572                     this.body.setHeight(h);
10573                 }else if(h == 'auto'){
10574                     this.body.setHeight(h);
10575                 }
10576
10577                 if(this.disabled && this.el._mask){
10578                     this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
10579                 }
10580             }else{
10581                 // Adds an event to set the correct height afterExpand.  This accounts for the deferHeight flag in panel
10582                 this.queuedBodySize = {width: w, height: h};
10583                 if(!this.queuedExpand && this.allowQueuedExpand !== false){
10584                     this.queuedExpand = true;
10585                     this.on('expand', function(){
10586                         delete this.queuedExpand;
10587                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
10588                     }, this, {single:true});
10589                 }
10590             }
10591             this.onBodyResize(w, h);
10592         }
10593         this.syncShadow();
10594         Ext.Panel.superclass.onResize.call(this, adjWidth, adjHeight, rawWidth, rawHeight);
10595
10596     },
10597
10598     // private
10599     onBodyResize: function(w, h){
10600         this.fireEvent('bodyresize', this, w, h);
10601     },
10602
10603     // private
10604     getToolbarHeight: function(){
10605         var h = 0;
10606         if(this.rendered){
10607             Ext.each(this.toolbars, function(tb){
10608                 h += tb.getHeight();
10609             }, this);
10610         }
10611         return h;
10612     },
10613
10614     // deprecate
10615     adjustBodyHeight : function(h){
10616         return h;
10617     },
10618
10619     // private
10620     adjustBodyWidth : function(w){
10621         return w;
10622     },
10623
10624     // private
10625     onPosition : function(){
10626         this.syncShadow();
10627     },
10628
10629     /**
10630      * Returns the width in pixels of the framing elements of this panel (not including the body width).  To
10631      * retrieve the body width see {@link #getInnerWidth}.
10632      * @return {Number} The frame width
10633      */
10634     getFrameWidth : function(){
10635         var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
10636
10637         if(this.frame){
10638             var l = this.bwrap.dom.firstChild;
10639             w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
10640             w += this.mc.getFrameWidth('lr');
10641         }
10642         return w;
10643     },
10644
10645     /**
10646      * Returns the height in pixels of the framing elements of this panel (including any top and bottom bars and
10647      * header and footer elements, but not including the body height).  To retrieve the body height see {@link #getInnerHeight}.
10648      * @return {Number} The frame height
10649      */
10650     getFrameHeight : function() {
10651         var h = Math.max(0, this.getHeight() - this.body.getHeight());
10652
10653         if (isNaN(h)) {
10654             h = 0;
10655         }
10656         return h;
10657
10658         /* Deprecate
10659             var h  = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
10660             h += (this.tbar ? this.tbar.getHeight() : 0) +
10661                  (this.bbar ? this.bbar.getHeight() : 0);
10662
10663             if(this.frame){
10664                 h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
10665             }else{
10666                 h += (this.header ? this.header.getHeight() : 0) +
10667                     (this.footer ? this.footer.getHeight() : 0);
10668             }
10669             return h;
10670         */
10671     },
10672
10673     /**
10674      * Returns the width in pixels of the body element (not including the width of any framing elements).
10675      * For the frame width see {@link #getFrameWidth}.
10676      * @return {Number} The body width
10677      */
10678     getInnerWidth : function(){
10679         return this.getSize().width - this.getFrameWidth();
10680     },
10681
10682     /**
10683      * Returns the height in pixels of the body element (not including the height of any framing elements).
10684      * For the frame height see {@link #getFrameHeight}.
10685      * @return {Number} The body height
10686      */
10687     getInnerHeight : function(){
10688         return this.body.getHeight();
10689         /* Deprecate
10690             return this.getSize().height - this.getFrameHeight();
10691         */
10692     },
10693
10694     // private
10695     syncShadow : function(){
10696         if(this.floating){
10697             this.el.sync(true);
10698         }
10699     },
10700
10701     // private
10702     getLayoutTarget : function(){
10703         return this.body;
10704     },
10705
10706     // private
10707     getContentTarget : function(){
10708         return this.body;
10709     },
10710
10711     /**
10712      * <p>Sets the title text for the panel and optionally the {@link #iconCls icon class}.</p>
10713      * <p>In order to be able to set the title, a header element must have been created
10714      * for the Panel. This is triggered either by configuring the Panel with a non-blank <code>{@link #title}</code>,
10715      * or configuring it with <code><b>{@link #header}: true</b></code>.</p>
10716      * @param {String} title The title text to set
10717      * @param {String} iconCls (optional) {@link #iconCls iconCls} A user-defined CSS class that provides the icon image for this panel
10718      */
10719     setTitle : function(title, iconCls){
10720         this.title = title;
10721         if(this.header && this.headerAsText){
10722             this.header.child('span').update(title);
10723         }
10724         if(iconCls){
10725             this.setIconClass(iconCls);
10726         }
10727         this.fireEvent('titlechange', this, title);
10728         return this;
10729     },
10730
10731     /**
10732      * Get the {@link Ext.Updater} for this panel. Enables you to perform Ajax updates of this panel's body.
10733      * @return {Ext.Updater} The Updater
10734      */
10735     getUpdater : function(){
10736         return this.body.getUpdater();
10737     },
10738
10739      /**
10740      * Loads this content panel immediately with content returned from an XHR call.
10741      * @param {Object/String/Function} config A config object containing any of the following options:
10742 <pre><code>
10743 panel.load({
10744     url: 'your-url.php',
10745     params: {param1: 'foo', param2: 'bar'}, // or a URL encoded string
10746     callback: yourFunction,
10747     scope: yourObject, // optional scope for the callback
10748     discardUrl: false,
10749     nocache: false,
10750     text: 'Loading...',
10751     timeout: 30,
10752     scripts: false
10753 });
10754 </code></pre>
10755      * The only required property is url. The optional properties nocache, text and scripts
10756      * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their
10757      * associated property on this panel Updater instance.
10758      * @return {Ext.Panel} this
10759      */
10760     load : function(){
10761         var um = this.body.getUpdater();
10762         um.update.apply(um, arguments);
10763         return this;
10764     },
10765
10766     // private
10767     beforeDestroy : function(){
10768         Ext.Panel.superclass.beforeDestroy.call(this);
10769         if(this.header){
10770             this.header.removeAllListeners();
10771         }
10772         if(this.tools){
10773             for(var k in this.tools){
10774                 Ext.destroy(this.tools[k]);
10775             }
10776         }
10777         if(this.toolbars.length > 0){
10778             Ext.each(this.toolbars, function(tb){
10779                 tb.un('afterlayout', this.syncHeight, this);
10780                 tb.un('remove', this.syncHeight, this);
10781             }, this);
10782         }
10783         if(Ext.isArray(this.buttons)){
10784             while(this.buttons.length) {
10785                 Ext.destroy(this.buttons[0]);
10786             }
10787         }
10788         if(this.rendered){
10789             Ext.destroy(
10790                 this.ft,
10791                 this.header,
10792                 this.footer,
10793                 this.tbar,
10794                 this.bbar,
10795                 this.body,
10796                 this.mc,
10797                 this.bwrap,
10798                 this.dd
10799             );
10800             if (this.fbar) {
10801                 Ext.destroy(
10802                     this.fbar,
10803                     this.fbar.el
10804                 );
10805             }
10806         }
10807         Ext.destroy(this.toolbars);
10808     },
10809
10810     // private
10811     createClasses : function(){
10812         this.headerCls = this.baseCls + '-header';
10813         this.headerTextCls = this.baseCls + '-header-text';
10814         this.bwrapCls = this.baseCls + '-bwrap';
10815         this.tbarCls = this.baseCls + '-tbar';
10816         this.bodyCls = this.baseCls + '-body';
10817         this.bbarCls = this.baseCls + '-bbar';
10818         this.footerCls = this.baseCls + '-footer';
10819     },
10820
10821     // private
10822     createGhost : function(cls, useShim, appendTo){
10823         var el = document.createElement('div');
10824         el.className = 'x-panel-ghost ' + (cls ? cls : '');
10825         if(this.header){
10826             el.appendChild(this.el.dom.firstChild.cloneNode(true));
10827         }
10828         Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
10829         el.style.width = this.el.dom.offsetWidth + 'px';;
10830         if(!appendTo){
10831             this.container.dom.appendChild(el);
10832         }else{
10833             Ext.getDom(appendTo).appendChild(el);
10834         }
10835         if(useShim !== false && this.el.useShim !== false){
10836             var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
10837             layer.show();
10838             return layer;
10839         }else{
10840             return new Ext.Element(el);
10841         }
10842     },
10843
10844     // private
10845     doAutoLoad : function(){
10846         var u = this.body.getUpdater();
10847         if(this.renderer){
10848             u.setRenderer(this.renderer);
10849         }
10850         u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
10851     },
10852
10853     /**
10854      * Retrieve a tool by id.
10855      * @param {String} id
10856      * @return {Object} tool
10857      */
10858     getTool : function(id) {
10859         return this.tools[id];
10860     }
10861
10862 /**
10863  * @cfg {String} autoEl @hide
10864  */
10865 });
10866 Ext.reg('panel', Ext.Panel);
10867 /**
10868  * @class Ext.Editor
10869  * @extends Ext.Component
10870  * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
10871  * @constructor
10872  * Create a new Editor
10873  * @param {Object} config The config object
10874  * @xtype editor
10875  */
10876 Ext.Editor = function(field, config){
10877     if(field.field){
10878         this.field = Ext.create(field.field, 'textfield');
10879         config = Ext.apply({}, field); // copy so we don't disturb original config
10880         delete config.field;
10881     }else{
10882         this.field = field;
10883     }
10884     Ext.Editor.superclass.constructor.call(this, config);
10885 };
10886
10887 Ext.extend(Ext.Editor, Ext.Component, {
10888     /**
10889     * @cfg {Ext.form.Field} field
10890     * The Field object (or descendant) or config object for field
10891     */
10892     /**
10893      * @cfg {Boolean} allowBlur
10894      * True to {@link #completeEdit complete the editing process} if in edit mode when the
10895      * field is blurred. Defaults to <tt>true</tt>.
10896      */
10897     allowBlur: true,
10898     /**
10899      * @cfg {Boolean/String} autoSize
10900      * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only,
10901      * or "height" to adopt the height only, "none" to always use the field dimensions. (defaults to false)
10902      */
10903     /**
10904      * @cfg {Boolean} revertInvalid
10905      * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
10906      * validation fails (defaults to true)
10907      */
10908     /**
10909      * @cfg {Boolean} ignoreNoChange
10910      * True to skip the edit completion process (no save, no events fired) if the user completes an edit and
10911      * the value has not changed (defaults to false).  Applies only to string values - edits for other data types
10912      * will never be ignored.
10913      */
10914     /**
10915      * @cfg {Boolean} hideEl
10916      * False to keep the bound element visible while the editor is displayed (defaults to true)
10917      */
10918     /**
10919      * @cfg {Mixed} value
10920      * The data value of the underlying field (defaults to "")
10921      */
10922     value : "",
10923     /**
10924      * @cfg {String} alignment
10925      * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?").
10926      */
10927     alignment: "c-c?",
10928     /**
10929      * @cfg {Array} offsets
10930      * The offsets to use when aligning (see {@link Ext.Element#alignTo} for more details. Defaults to <tt>[0, 0]</tt>.
10931      */
10932     offsets: [0, 0],
10933     /**
10934      * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
10935      * for bottom-right shadow (defaults to "frame")
10936      */
10937     shadow : "frame",
10938     /**
10939      * @cfg {Boolean} constrain True to constrain the editor to the viewport
10940      */
10941     constrain : false,
10942     /**
10943      * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true)
10944      */
10945     swallowKeys : true,
10946     /**
10947      * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed. Defaults to <tt>true</tt>.
10948      */
10949     completeOnEnter : true,
10950     /**
10951      * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed. Defaults to <tt>true</tt>.
10952      */
10953     cancelOnEsc : true,
10954     /**
10955      * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
10956      */
10957     updateEl : false,
10958
10959     initComponent : function(){
10960         Ext.Editor.superclass.initComponent.call(this);
10961         this.addEvents(
10962             /**
10963              * @event beforestartedit
10964              * Fires when editing is initiated, but before the value changes.  Editing can be canceled by returning
10965              * false from the handler of this event.
10966              * @param {Editor} this
10967              * @param {Ext.Element} boundEl The underlying element bound to this editor
10968              * @param {Mixed} value The field value being set
10969              */
10970             "beforestartedit",
10971             /**
10972              * @event startedit
10973              * Fires when this editor is displayed
10974              * @param {Ext.Element} boundEl The underlying element bound to this editor
10975              * @param {Mixed} value The starting field value
10976              */
10977             "startedit",
10978             /**
10979              * @event beforecomplete
10980              * Fires after a change has been made to the field, but before the change is reflected in the underlying
10981              * field.  Saving the change to the field can be canceled by returning false from the handler of this event.
10982              * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
10983              * event will not fire since no edit actually occurred.
10984              * @param {Editor} this
10985              * @param {Mixed} value The current field value
10986              * @param {Mixed} startValue The original field value
10987              */
10988             "beforecomplete",
10989             /**
10990              * @event complete
10991              * Fires after editing is complete and any changed value has been written to the underlying field.
10992              * @param {Editor} this
10993              * @param {Mixed} value The current field value
10994              * @param {Mixed} startValue The original field value
10995              */
10996             "complete",
10997             /**
10998              * @event canceledit
10999              * Fires after editing has been canceled and the editor's value has been reset.
11000              * @param {Editor} this
11001              * @param {Mixed} value The user-entered field value that was discarded
11002              * @param {Mixed} startValue The original field value that was set back into the editor after cancel
11003              */
11004             "canceledit",
11005             /**
11006              * @event specialkey
11007              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
11008              * {@link Ext.EventObject#getKey} to determine which key was pressed.
11009              * @param {Ext.form.Field} this
11010              * @param {Ext.EventObject} e The event object
11011              */
11012             "specialkey"
11013         );
11014     },
11015
11016     // private
11017     onRender : function(ct, position){
11018         this.el = new Ext.Layer({
11019             shadow: this.shadow,
11020             cls: "x-editor",
11021             parentEl : ct,
11022             shim : this.shim,
11023             shadowOffset: this.shadowOffset || 4,
11024             id: this.id,
11025             constrain: this.constrain
11026         });
11027         if(this.zIndex){
11028             this.el.setZIndex(this.zIndex);
11029         }
11030         this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
11031         if(this.field.msgTarget != 'title'){
11032             this.field.msgTarget = 'qtip';
11033         }
11034         this.field.inEditor = true;
11035         this.mon(this.field, {
11036             scope: this,
11037             blur: this.onBlur,
11038             specialkey: this.onSpecialKey
11039         });
11040         if(this.field.grow){
11041             this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
11042         }
11043         this.field.render(this.el).show();
11044         this.field.getEl().dom.name = '';
11045         if(this.swallowKeys){
11046             this.field.el.swallowEvent([
11047                 'keypress', // *** Opera
11048                 'keydown'   // *** all other browsers
11049             ]);
11050         }
11051     },
11052
11053     // private
11054     onSpecialKey : function(field, e){
11055         var key = e.getKey(),
11056             complete = this.completeOnEnter && key == e.ENTER,
11057             cancel = this.cancelOnEsc && key == e.ESC;
11058         if(complete || cancel){
11059             e.stopEvent();
11060             if(complete){
11061                 this.completeEdit();
11062             }else{
11063                 this.cancelEdit();
11064             }
11065             if(field.triggerBlur){
11066                 field.triggerBlur();
11067             }
11068         }
11069         this.fireEvent('specialkey', field, e);
11070     },
11071
11072     /**
11073      * Starts the editing process and shows the editor.
11074      * @param {Mixed} el The element to edit
11075      * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
11076       * to the innerHTML of el.
11077      */
11078     startEdit : function(el, value){
11079         if(this.editing){
11080             this.completeEdit();
11081         }
11082         this.boundEl = Ext.get(el);
11083         var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
11084         if(!this.rendered){
11085             this.render(this.parentEl || document.body);
11086         }
11087         if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
11088             this.startValue = v;
11089             this.field.reset();
11090             this.field.setValue(v);
11091             this.realign(true);
11092             this.editing = true;
11093             this.show();
11094         }
11095     },
11096
11097     // private
11098     doAutoSize : function(){
11099         if(this.autoSize){
11100             var sz = this.boundEl.getSize(),
11101                 fs = this.field.getSize();
11102
11103             switch(this.autoSize){
11104                 case "width":
11105                     this.setSize(sz.width, fs.height);
11106                     break;
11107                 case "height":
11108                     this.setSize(fs.width, sz.height);
11109                     break;
11110                 case "none":
11111                     this.setSize(fs.width, fs.height);
11112                     break;
11113                 default:
11114                     this.setSize(sz.width, sz.height);
11115             }
11116         }
11117     },
11118
11119     /**
11120      * Sets the height and width of this editor.
11121      * @param {Number} width The new width
11122      * @param {Number} height The new height
11123      */
11124     setSize : function(w, h){
11125         delete this.field.lastSize;
11126         this.field.setSize(w, h);
11127         if(this.el){
11128             if(Ext.isGecko2 || Ext.isOpera){
11129                 // prevent layer scrollbars
11130                 this.el.setSize(w, h);
11131             }
11132             this.el.sync();
11133         }
11134     },
11135
11136     /**
11137      * Realigns the editor to the bound field based on the current alignment config value.
11138      * @param {Boolean} autoSize (optional) True to size the field to the dimensions of the bound element.
11139      */
11140     realign : function(autoSize){
11141         if(autoSize === true){
11142             this.doAutoSize();
11143         }
11144         this.el.alignTo(this.boundEl, this.alignment, this.offsets);
11145     },
11146
11147     /**
11148      * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
11149      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
11150      */
11151     completeEdit : function(remainVisible){
11152         if(!this.editing){
11153             return;
11154         }
11155         // Assert combo values first
11156         if (this.field.assertValue) {
11157             this.field.assertValue();
11158         }
11159         var v = this.getValue();
11160         if(!this.field.isValid()){
11161             if(this.revertInvalid !== false){
11162                 this.cancelEdit(remainVisible);
11163             }
11164             return;
11165         }
11166         if(String(v) === String(this.startValue) && this.ignoreNoChange){
11167             this.hideEdit(remainVisible);
11168             return;
11169         }
11170         if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
11171             v = this.getValue();
11172             if(this.updateEl && this.boundEl){
11173                 this.boundEl.update(v);
11174             }
11175             this.hideEdit(remainVisible);
11176             this.fireEvent("complete", this, v, this.startValue);
11177         }
11178     },
11179
11180     // private
11181     onShow : function(){
11182         this.el.show();
11183         if(this.hideEl !== false){
11184             this.boundEl.hide();
11185         }
11186         this.field.show().focus(false, true);
11187         this.fireEvent("startedit", this.boundEl, this.startValue);
11188     },
11189
11190     /**
11191      * Cancels the editing process and hides the editor without persisting any changes.  The field value will be
11192      * reverted to the original starting value.
11193      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
11194      * cancel (defaults to false)
11195      */
11196     cancelEdit : function(remainVisible){
11197         if(this.editing){
11198             var v = this.getValue();
11199             this.setValue(this.startValue);
11200             this.hideEdit(remainVisible);
11201             this.fireEvent("canceledit", this, v, this.startValue);
11202         }
11203     },
11204
11205     // private
11206     hideEdit: function(remainVisible){
11207         if(remainVisible !== true){
11208             this.editing = false;
11209             this.hide();
11210         }
11211     },
11212
11213     // private
11214     onBlur : function(){
11215         // selectSameEditor flag allows the same editor to be started without onBlur firing on itself
11216         if(this.allowBlur === true && this.editing && this.selectSameEditor !== true){
11217             this.completeEdit();
11218         }
11219     },
11220
11221     // private
11222     onHide : function(){
11223         if(this.editing){
11224             this.completeEdit();
11225             return;
11226         }
11227         this.field.blur();
11228         if(this.field.collapse){
11229             this.field.collapse();
11230         }
11231         this.el.hide();
11232         if(this.hideEl !== false){
11233             this.boundEl.show();
11234         }
11235     },
11236
11237     /**
11238      * Sets the data value of the editor
11239      * @param {Mixed} value Any valid value supported by the underlying field
11240      */
11241     setValue : function(v){
11242         this.field.setValue(v);
11243     },
11244
11245     /**
11246      * Gets the data value of the editor
11247      * @return {Mixed} The data value
11248      */
11249     getValue : function(){
11250         return this.field.getValue();
11251     },
11252
11253     beforeDestroy : function(){
11254         Ext.destroyMembers(this, 'field');
11255
11256         delete this.parentEl;
11257         delete this.boundEl;
11258     }
11259 });
11260 Ext.reg('editor', Ext.Editor);
11261 /**
11262  * @class Ext.ColorPalette
11263  * @extends Ext.Component
11264  * Simple color palette class for choosing colors.  The palette can be rendered to any container.<br />
11265  * Here's an example of typical usage:
11266  * <pre><code>
11267 var cp = new Ext.ColorPalette({value:'993300'});  // initial selected color
11268 cp.render('my-div');
11269
11270 cp.on('select', function(palette, selColor){
11271     // do something with selColor
11272 });
11273 </code></pre>
11274  * @constructor
11275  * Create a new ColorPalette
11276  * @param {Object} config The config object
11277  * @xtype colorpalette
11278  */
11279 Ext.ColorPalette = Ext.extend(Ext.Component, {
11280         /**
11281          * @cfg {String} tpl An existing XTemplate instance to be used in place of the default template for rendering the component.
11282          */
11283     /**
11284      * @cfg {String} itemCls
11285      * The CSS class to apply to the containing element (defaults to 'x-color-palette')
11286      */
11287     itemCls : 'x-color-palette',
11288     /**
11289      * @cfg {String} value
11290      * The initial color to highlight (should be a valid 6-digit color hex code without the # symbol).  Note that
11291      * the hex codes are case-sensitive.
11292      */
11293     value : null,
11294     /**
11295      * @cfg {String} clickEvent
11296      * The DOM event that will cause a color to be selected. This can be any valid event name (dblclick, contextmenu). 
11297      * Defaults to <tt>'click'</tt>.
11298      */
11299     clickEvent :'click',
11300     // private
11301     ctype : 'Ext.ColorPalette',
11302
11303     /**
11304      * @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the {@link #select} event
11305      */
11306     allowReselect : false,
11307
11308     /**
11309      * <p>An array of 6-digit color hex code strings (without the # symbol).  This array can contain any number
11310      * of colors, and each hex code should be unique.  The width of the palette is controlled via CSS by adjusting
11311      * the width property of the 'x-color-palette' class (or assigning a custom class), so you can balance the number
11312      * of colors with the width setting until the box is symmetrical.</p>
11313      * <p>You can override individual colors if needed:</p>
11314      * <pre><code>
11315 var cp = new Ext.ColorPalette();
11316 cp.colors[0] = 'FF0000';  // change the first box to red
11317 </code></pre>
11318
11319 Or you can provide a custom array of your own for complete control:
11320 <pre><code>
11321 var cp = new Ext.ColorPalette();
11322 cp.colors = ['000000', '993300', '333300'];
11323 </code></pre>
11324      * @type Array
11325      */
11326     colors : [
11327         '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
11328         '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
11329         'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
11330         'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
11331         'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
11332     ],
11333
11334     /**
11335      * @cfg {Function} handler
11336      * Optional. A function that will handle the select event of this palette.
11337      * The handler is passed the following parameters:<div class="mdetail-params"><ul>
11338      * <li><code>palette</code> : ColorPalette<div class="sub-desc">The {@link #palette Ext.ColorPalette}.</div></li>
11339      * <li><code>color</code> : String<div class="sub-desc">The 6-digit color hex code (without the # symbol).</div></li>
11340      * </ul></div>
11341      */
11342     /**
11343      * @cfg {Object} scope
11344      * The scope (<tt><b>this</b></tt> reference) in which the <code>{@link #handler}</code>
11345      * function will be called.  Defaults to this ColorPalette instance.
11346      */
11347     
11348     // private
11349     initComponent : function(){
11350         Ext.ColorPalette.superclass.initComponent.call(this);
11351         this.addEvents(
11352             /**
11353              * @event select
11354              * Fires when a color is selected
11355              * @param {ColorPalette} this
11356              * @param {String} color The 6-digit color hex code (without the # symbol)
11357              */
11358             'select'
11359         );
11360
11361         if(this.handler){
11362             this.on('select', this.handler, this.scope, true);
11363         }    
11364     },
11365
11366     // private
11367     onRender : function(container, position){
11368         this.autoEl = {
11369             tag: 'div',
11370             cls: this.itemCls
11371         };
11372         Ext.ColorPalette.superclass.onRender.call(this, container, position);
11373         var t = this.tpl || new Ext.XTemplate(
11374             '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
11375         );
11376         t.overwrite(this.el, this.colors);
11377         this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
11378         if(this.clickEvent != 'click'){
11379                 this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
11380         }
11381     },
11382
11383     // private
11384     afterRender : function(){
11385         Ext.ColorPalette.superclass.afterRender.call(this);
11386         if(this.value){
11387             var s = this.value;
11388             this.value = null;
11389             this.select(s, true);
11390         }
11391     },
11392
11393     // private
11394     handleClick : function(e, t){
11395         e.preventDefault();
11396         if(!this.disabled){
11397             var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
11398             this.select(c.toUpperCase());
11399         }
11400     },
11401
11402     /**
11403      * Selects the specified color in the palette (fires the {@link #select} event)
11404      * @param {String} color A valid 6-digit color hex code (# will be stripped if included)
11405      * @param {Boolean} suppressEvent (optional) True to stop the select event from firing. Defaults to <tt>false</tt>.
11406      */
11407     select : function(color, suppressEvent){
11408         color = color.replace('#', '');
11409         if(color != this.value || this.allowReselect){
11410             var el = this.el;
11411             if(this.value){
11412                 el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
11413             }
11414             el.child('a.color-'+color).addClass('x-color-palette-sel');
11415             this.value = color;
11416             if(suppressEvent !== true){
11417                 this.fireEvent('select', this, color);
11418             }
11419         }
11420     }
11421
11422     /**
11423      * @cfg {String} autoEl @hide
11424      */
11425 });
11426 Ext.reg('colorpalette', Ext.ColorPalette);/**
11427  * @class Ext.DatePicker
11428  * @extends Ext.Component
11429  * <p>A popup date picker. This class is used by the {@link Ext.form.DateField DateField} class
11430  * to allow browsing and selection of valid dates.</p>
11431  * <p>All the string values documented below may be overridden by including an Ext locale file in
11432  * your page.</p>
11433  * @constructor
11434  * Create a new DatePicker
11435  * @param {Object} config The config object
11436  * @xtype datepicker
11437  */
11438 Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
11439     /**
11440      * @cfg {String} todayText
11441      * The text to display on the button that selects the current date (defaults to <code>'Today'</code>)
11442      */
11443     todayText : 'Today',
11444     /**
11445      * @cfg {String} okText
11446      * The text to display on the ok button (defaults to <code>'&#160;OK&#160;'</code> to give the user extra clicking room)
11447      */
11448     okText : '&#160;OK&#160;',
11449     /**
11450      * @cfg {String} cancelText
11451      * The text to display on the cancel button (defaults to <code>'Cancel'</code>)
11452      */
11453     cancelText : 'Cancel',
11454     /**
11455      * @cfg {Function} handler
11456      * Optional. A function that will handle the select event of this picker.
11457      * The handler is passed the following parameters:<div class="mdetail-params"><ul>
11458      * <li><code>picker</code> : DatePicker<div class="sub-desc">This DatePicker.</div></li>
11459      * <li><code>date</code> : Date<div class="sub-desc">The selected date.</div></li>
11460      * </ul></div>
11461      */
11462     /**
11463      * @cfg {Object} scope
11464      * The scope (<code><b>this</b></code> reference) in which the <code>{@link #handler}</code>
11465      * function will be called.  Defaults to this DatePicker instance.
11466      */
11467     /**
11468      * @cfg {String} todayTip
11469      * A string used to format the message for displaying in a tooltip over the button that
11470      * selects the current date. Defaults to <code>'{0} (Spacebar)'</code> where
11471      * the <code>{0}</code> token is replaced by today's date.
11472      */
11473     todayTip : '{0} (Spacebar)',
11474     /**
11475      * @cfg {String} minText
11476      * The error text to display if the minDate validation fails (defaults to <code>'This date is before the minimum date'</code>)
11477      */
11478     minText : 'This date is before the minimum date',
11479     /**
11480      * @cfg {String} maxText
11481      * The error text to display if the maxDate validation fails (defaults to <code>'This date is after the maximum date'</code>)
11482      */
11483     maxText : 'This date is after the maximum date',
11484     /**
11485      * @cfg {String} format
11486      * The default date format string which can be overriden for localization support.  The format must be
11487      * valid according to {@link Date#parseDate} (defaults to <code>'m/d/y'</code>).
11488      */
11489     format : 'm/d/y',
11490     /**
11491      * @cfg {String} disabledDaysText
11492      * The tooltip to display when the date falls on a disabled day (defaults to <code>'Disabled'</code>)
11493      */
11494     disabledDaysText : 'Disabled',
11495     /**
11496      * @cfg {String} disabledDatesText
11497      * The tooltip text to display when the date falls on a disabled date (defaults to <code>'Disabled'</code>)
11498      */
11499     disabledDatesText : 'Disabled',
11500     /**
11501      * @cfg {Array} monthNames
11502      * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
11503      */
11504     monthNames : Date.monthNames,
11505     /**
11506      * @cfg {Array} dayNames
11507      * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
11508      */
11509     dayNames : Date.dayNames,
11510     /**
11511      * @cfg {String} nextText
11512      * The next month navigation button tooltip (defaults to <code>'Next Month (Control+Right)'</code>)
11513      */
11514     nextText : 'Next Month (Control+Right)',
11515     /**
11516      * @cfg {String} prevText
11517      * The previous month navigation button tooltip (defaults to <code>'Previous Month (Control+Left)'</code>)
11518      */
11519     prevText : 'Previous Month (Control+Left)',
11520     /**
11521      * @cfg {String} monthYearText
11522      * The header month selector tooltip (defaults to <code>'Choose a month (Control+Up/Down to move years)'</code>)
11523      */
11524     monthYearText : 'Choose a month (Control+Up/Down to move years)',
11525     /**
11526      * @cfg {Number} startDay
11527      * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
11528      */
11529     startDay : 0,
11530     /**
11531      * @cfg {Boolean} showToday
11532      * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar
11533      * that selects the current date (defaults to <code>true</code>).
11534      */
11535     showToday : true,
11536     /**
11537      * @cfg {Date} minDate
11538      * Minimum allowable date (JavaScript date object, defaults to null)
11539      */
11540     /**
11541      * @cfg {Date} maxDate
11542      * Maximum allowable date (JavaScript date object, defaults to null)
11543      */
11544     /**
11545      * @cfg {Array} disabledDays
11546      * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
11547      */
11548     /**
11549      * @cfg {RegExp} disabledDatesRE
11550      * JavaScript regular expression used to disable a pattern of dates (defaults to null).  The {@link #disabledDates}
11551      * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the
11552      * disabledDates value.
11553      */
11554     /**
11555      * @cfg {Array} disabledDates
11556      * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular
11557      * expression so they are very powerful. Some examples:
11558      * <ul>
11559      * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>
11560      * <li>['03/08', '09/16'] would disable those days for every year</li>
11561      * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>
11562      * <li>['03/../2006'] would disable every day in March 2006</li>
11563      * <li>['^03'] would disable every day in every March</li>
11564      * </ul>
11565      * Note that the format of the dates included in the array should exactly match the {@link #format} config.
11566      * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to
11567      * escape the dot when restricting dates. For example: ['03\\.08\\.03'].
11568      */
11569
11570     // private
11571     // Set by other components to stop the picker focus being updated when the value changes.
11572     focusOnSelect: true,
11573
11574     // default value used to initialise each date in the DatePicker
11575     // (note: 12 noon was chosen because it steers well clear of all DST timezone changes)
11576     initHour: 12, // 24-hour format
11577
11578     // private
11579     initComponent : function(){
11580         Ext.DatePicker.superclass.initComponent.call(this);
11581
11582         this.value = this.value ?
11583                  this.value.clearTime(true) : new Date().clearTime();
11584
11585         this.addEvents(
11586             /**
11587              * @event select
11588              * Fires when a date is selected
11589              * @param {DatePicker} this DatePicker
11590              * @param {Date} date The selected date
11591              */
11592             'select'
11593         );
11594
11595         if(this.handler){
11596             this.on('select', this.handler,  this.scope || this);
11597         }
11598
11599         this.initDisabledDays();
11600     },
11601
11602     // private
11603     initDisabledDays : function(){
11604         if(!this.disabledDatesRE && this.disabledDates){
11605             var dd = this.disabledDates,
11606                 len = dd.length - 1,
11607                 re = '(?:';
11608
11609             Ext.each(dd, function(d, i){
11610                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
11611                 if(i != len){
11612                     re += '|';
11613                 }
11614             }, this);
11615             this.disabledDatesRE = new RegExp(re + ')');
11616         }
11617     },
11618
11619     /**
11620      * Replaces any existing disabled dates with new values and refreshes the DatePicker.
11621      * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config
11622      * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.
11623      */
11624     setDisabledDates : function(dd){
11625         if(Ext.isArray(dd)){
11626             this.disabledDates = dd;
11627             this.disabledDatesRE = null;
11628         }else{
11629             this.disabledDatesRE = dd;
11630         }
11631         this.initDisabledDays();
11632         this.update(this.value, true);
11633     },
11634
11635     /**
11636      * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.
11637      * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config
11638      * for details on supported values.
11639      */
11640     setDisabledDays : function(dd){
11641         this.disabledDays = dd;
11642         this.update(this.value, true);
11643     },
11644
11645     /**
11646      * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
11647      * @param {Date} value The minimum date that can be selected
11648      */
11649     setMinDate : function(dt){
11650         this.minDate = dt;
11651         this.update(this.value, true);
11652     },
11653
11654     /**
11655      * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
11656      * @param {Date} value The maximum date that can be selected
11657      */
11658     setMaxDate : function(dt){
11659         this.maxDate = dt;
11660         this.update(this.value, true);
11661     },
11662
11663     /**
11664      * Sets the value of the date field
11665      * @param {Date} value The date to set
11666      */
11667     setValue : function(value){
11668         this.value = value.clearTime(true);
11669         this.update(this.value);
11670     },
11671
11672     /**
11673      * Gets the current selected value of the date field
11674      * @return {Date} The selected date
11675      */
11676     getValue : function(){
11677         return this.value;
11678     },
11679
11680     // private
11681     focus : function(){
11682         this.update(this.activeDate);
11683     },
11684
11685     // private
11686     onEnable: function(initial){
11687         Ext.DatePicker.superclass.onEnable.call(this);
11688         this.doDisabled(false);
11689         this.update(initial ? this.value : this.activeDate);
11690         if(Ext.isIE){
11691             this.el.repaint();
11692         }
11693
11694     },
11695
11696     // private
11697     onDisable : function(){
11698         Ext.DatePicker.superclass.onDisable.call(this);
11699         this.doDisabled(true);
11700         if(Ext.isIE && !Ext.isIE8){
11701             /* Really strange problem in IE6/7, when disabled, have to explicitly
11702              * repaint each of the nodes to get them to display correctly, simply
11703              * calling repaint on the main element doesn't appear to be enough.
11704              */
11705              Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
11706                  Ext.fly(el).repaint();
11707              });
11708         }
11709     },
11710
11711     // private
11712     doDisabled : function(disabled){
11713         this.keyNav.setDisabled(disabled);
11714         this.prevRepeater.setDisabled(disabled);
11715         this.nextRepeater.setDisabled(disabled);
11716         if(this.showToday){
11717             this.todayKeyListener.setDisabled(disabled);
11718             this.todayBtn.setDisabled(disabled);
11719         }
11720     },
11721
11722     // private
11723     onRender : function(container, position){
11724         var m = [
11725              '<table cellspacing="0">',
11726                 '<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>',
11727                 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
11728                 dn = this.dayNames,
11729                 i;
11730         for(i = 0; i < 7; i++){
11731             var d = this.startDay+i;
11732             if(d > 6){
11733                 d = d-7;
11734             }
11735             m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
11736         }
11737         m[m.length] = '</tr></thead><tbody><tr>';
11738         for(i = 0; i < 42; i++) {
11739             if(i % 7 === 0 && i !== 0){
11740                 m[m.length] = '</tr><tr>';
11741             }
11742             m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
11743         }
11744         m.push('</tr></tbody></table></td></tr>',
11745                 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
11746                 '</table><div class="x-date-mp"></div>');
11747
11748         var el = document.createElement('div');
11749         el.className = 'x-date-picker';
11750         el.innerHTML = m.join('');
11751
11752         container.dom.insertBefore(el, position);
11753
11754         this.el = Ext.get(el);
11755         this.eventEl = Ext.get(el.firstChild);
11756
11757         this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
11758             handler: this.showPrevMonth,
11759             scope: this,
11760             preventDefault:true,
11761             stopDefault:true
11762         });
11763
11764         this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
11765             handler: this.showNextMonth,
11766             scope: this,
11767             preventDefault:true,
11768             stopDefault:true
11769         });
11770
11771         this.monthPicker = this.el.down('div.x-date-mp');
11772         this.monthPicker.enableDisplayMode('block');
11773
11774         this.keyNav = new Ext.KeyNav(this.eventEl, {
11775             'left' : function(e){
11776                 if(e.ctrlKey){
11777                     this.showPrevMonth();
11778                 }else{
11779                     this.update(this.activeDate.add('d', -1));
11780                 }
11781             },
11782
11783             'right' : function(e){
11784                 if(e.ctrlKey){
11785                     this.showNextMonth();
11786                 }else{
11787                     this.update(this.activeDate.add('d', 1));
11788                 }
11789             },
11790
11791             'up' : function(e){
11792                 if(e.ctrlKey){
11793                     this.showNextYear();
11794                 }else{
11795                     this.update(this.activeDate.add('d', -7));
11796                 }
11797             },
11798
11799             'down' : function(e){
11800                 if(e.ctrlKey){
11801                     this.showPrevYear();
11802                 }else{
11803                     this.update(this.activeDate.add('d', 7));
11804                 }
11805             },
11806
11807             'pageUp' : function(e){
11808                 this.showNextMonth();
11809             },
11810
11811             'pageDown' : function(e){
11812                 this.showPrevMonth();
11813             },
11814
11815             'enter' : function(e){
11816                 e.stopPropagation();
11817                 return true;
11818             },
11819
11820             scope : this
11821         });
11822
11823         this.el.unselectable();
11824
11825         this.cells = this.el.select('table.x-date-inner tbody td');
11826         this.textNodes = this.el.query('table.x-date-inner tbody span');
11827
11828         this.mbtn = new Ext.Button({
11829             text: '&#160;',
11830             tooltip: this.monthYearText,
11831             renderTo: this.el.child('td.x-date-middle', true)
11832         });
11833         this.mbtn.el.child('em').addClass('x-btn-arrow');
11834
11835         if(this.showToday){
11836             this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
11837             var today = (new Date()).dateFormat(this.format);
11838             this.todayBtn = new Ext.Button({
11839                 renderTo: this.el.child('td.x-date-bottom', true),
11840                 text: String.format(this.todayText, today),
11841                 tooltip: String.format(this.todayTip, today),
11842                 handler: this.selectToday,
11843                 scope: this
11844             });
11845         }
11846         this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
11847         this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
11848         this.mon(this.mbtn, 'click', this.showMonthPicker, this);
11849         this.onEnable(true);
11850     },
11851
11852     // private
11853     createMonthPicker : function(){
11854         if(!this.monthPicker.dom.firstChild){
11855             var buf = ['<table border="0" cellspacing="0">'];
11856             for(var i = 0; i < 6; i++){
11857                 buf.push(
11858                     '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
11859                     '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
11860                     i === 0 ?
11861                     '<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>' :
11862                     '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
11863                 );
11864             }
11865             buf.push(
11866                 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
11867                     this.okText,
11868                     '</button><button type="button" class="x-date-mp-cancel">',
11869                     this.cancelText,
11870                     '</button></td></tr>',
11871                 '</table>'
11872             );
11873             this.monthPicker.update(buf.join(''));
11874
11875             this.mon(this.monthPicker, 'click', this.onMonthClick, this);
11876             this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
11877
11878             this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
11879             this.mpYears = this.monthPicker.select('td.x-date-mp-year');
11880
11881             this.mpMonths.each(function(m, a, i){
11882                 i += 1;
11883                 if((i%2) === 0){
11884                     m.dom.xmonth = 5 + Math.round(i * 0.5);
11885                 }else{
11886                     m.dom.xmonth = Math.round((i-1) * 0.5);
11887                 }
11888             });
11889         }
11890     },
11891
11892     // private
11893     showMonthPicker : function(){
11894         if(!this.disabled){
11895             this.createMonthPicker();
11896             var size = this.el.getSize();
11897             this.monthPicker.setSize(size);
11898             this.monthPicker.child('table').setSize(size);
11899
11900             this.mpSelMonth = (this.activeDate || this.value).getMonth();
11901             this.updateMPMonth(this.mpSelMonth);
11902             this.mpSelYear = (this.activeDate || this.value).getFullYear();
11903             this.updateMPYear(this.mpSelYear);
11904
11905             this.monthPicker.slideIn('t', {duration:0.2});
11906         }
11907     },
11908
11909     // private
11910     updateMPYear : function(y){
11911         this.mpyear = y;
11912         var ys = this.mpYears.elements;
11913         for(var i = 1; i <= 10; i++){
11914             var td = ys[i-1], y2;
11915             if((i%2) === 0){
11916                 y2 = y + Math.round(i * 0.5);
11917                 td.firstChild.innerHTML = y2;
11918                 td.xyear = y2;
11919             }else{
11920                 y2 = y - (5-Math.round(i * 0.5));
11921                 td.firstChild.innerHTML = y2;
11922                 td.xyear = y2;
11923             }
11924             this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
11925         }
11926     },
11927
11928     // private
11929     updateMPMonth : function(sm){
11930         this.mpMonths.each(function(m, a, i){
11931             m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
11932         });
11933     },
11934
11935     // private
11936     selectMPMonth : function(m){
11937
11938     },
11939
11940     // private
11941     onMonthClick : function(e, t){
11942         e.stopEvent();
11943         var el = new Ext.Element(t), pn;
11944         if(el.is('button.x-date-mp-cancel')){
11945             this.hideMonthPicker();
11946         }
11947         else if(el.is('button.x-date-mp-ok')){
11948             var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
11949             if(d.getMonth() != this.mpSelMonth){
11950                 // 'fix' the JS rolling date conversion if needed
11951                 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
11952             }
11953             this.update(d);
11954             this.hideMonthPicker();
11955         }
11956         else if((pn = el.up('td.x-date-mp-month', 2))){
11957             this.mpMonths.removeClass('x-date-mp-sel');
11958             pn.addClass('x-date-mp-sel');
11959             this.mpSelMonth = pn.dom.xmonth;
11960         }
11961         else if((pn = el.up('td.x-date-mp-year', 2))){
11962             this.mpYears.removeClass('x-date-mp-sel');
11963             pn.addClass('x-date-mp-sel');
11964             this.mpSelYear = pn.dom.xyear;
11965         }
11966         else if(el.is('a.x-date-mp-prev')){
11967             this.updateMPYear(this.mpyear-10);
11968         }
11969         else if(el.is('a.x-date-mp-next')){
11970             this.updateMPYear(this.mpyear+10);
11971         }
11972     },
11973
11974     // private
11975     onMonthDblClick : function(e, t){
11976         e.stopEvent();
11977         var el = new Ext.Element(t), pn;
11978         if((pn = el.up('td.x-date-mp-month', 2))){
11979             this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
11980             this.hideMonthPicker();
11981         }
11982         else if((pn = el.up('td.x-date-mp-year', 2))){
11983             this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
11984             this.hideMonthPicker();
11985         }
11986     },
11987
11988     // private
11989     hideMonthPicker : function(disableAnim){
11990         if(this.monthPicker){
11991             if(disableAnim === true){
11992                 this.monthPicker.hide();
11993             }else{
11994                 this.monthPicker.slideOut('t', {duration:0.2});
11995             }
11996         }
11997     },
11998
11999     // private
12000     showPrevMonth : function(e){
12001         this.update(this.activeDate.add('mo', -1));
12002     },
12003
12004     // private
12005     showNextMonth : function(e){
12006         this.update(this.activeDate.add('mo', 1));
12007     },
12008
12009     // private
12010     showPrevYear : function(){
12011         this.update(this.activeDate.add('y', -1));
12012     },
12013
12014     // private
12015     showNextYear : function(){
12016         this.update(this.activeDate.add('y', 1));
12017     },
12018
12019     // private
12020     handleMouseWheel : function(e){
12021         e.stopEvent();
12022         if(!this.disabled){
12023             var delta = e.getWheelDelta();
12024             if(delta > 0){
12025                 this.showPrevMonth();
12026             } else if(delta < 0){
12027                 this.showNextMonth();
12028             }
12029         }
12030     },
12031
12032     // private
12033     handleDateClick : function(e, t){
12034         e.stopEvent();
12035         if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
12036             this.cancelFocus = this.focusOnSelect === false;
12037             this.setValue(new Date(t.dateValue));
12038             delete this.cancelFocus;
12039             this.fireEvent('select', this, this.value);
12040         }
12041     },
12042
12043     // private
12044     selectToday : function(){
12045         if(this.todayBtn && !this.todayBtn.disabled){
12046             this.setValue(new Date().clearTime());
12047             this.fireEvent('select', this, this.value);
12048         }
12049     },
12050
12051     // private
12052     update : function(date, forceRefresh){
12053         if(this.rendered){
12054             var vd = this.activeDate, vis = this.isVisible();
12055             this.activeDate = date;
12056             if(!forceRefresh && vd && this.el){
12057                 var t = date.getTime();
12058                 if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
12059                     this.cells.removeClass('x-date-selected');
12060                     this.cells.each(function(c){
12061                        if(c.dom.firstChild.dateValue == t){
12062                            c.addClass('x-date-selected');
12063                            if(vis && !this.cancelFocus){
12064                                Ext.fly(c.dom.firstChild).focus(50);
12065                            }
12066                            return false;
12067                        }
12068                     }, this);
12069                     return;
12070                 }
12071             }
12072             var days = date.getDaysInMonth(),
12073                 firstOfMonth = date.getFirstDateOfMonth(),
12074                 startingPos = firstOfMonth.getDay()-this.startDay;
12075
12076             if(startingPos < 0){
12077                 startingPos += 7;
12078             }
12079             days += startingPos;
12080
12081             var pm = date.add('mo', -1),
12082                 prevStart = pm.getDaysInMonth()-startingPos,
12083                 cells = this.cells.elements,
12084                 textEls = this.textNodes,
12085                 // convert everything to numbers so it's fast
12086                 d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart, this.initHour)),
12087                 today = new Date().clearTime().getTime(),
12088                 sel = date.clearTime(true).getTime(),
12089                 min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
12090                 max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
12091                 ddMatch = this.disabledDatesRE,
12092                 ddText = this.disabledDatesText,
12093                 ddays = this.disabledDays ? this.disabledDays.join('') : false,
12094                 ddaysText = this.disabledDaysText,
12095                 format = this.format;
12096
12097             if(this.showToday){
12098                 var td = new Date().clearTime(),
12099                     disable = (td < min || td > max ||
12100                     (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
12101                     (ddays && ddays.indexOf(td.getDay()) != -1));
12102
12103                 if(!this.disabled){
12104                     this.todayBtn.setDisabled(disable);
12105                     this.todayKeyListener[disable ? 'disable' : 'enable']();
12106                 }
12107             }
12108
12109             var setCellClass = function(cal, cell){
12110                 cell.title = '';
12111                 var t = d.clearTime(true).getTime();
12112                 cell.firstChild.dateValue = t;
12113                 if(t == today){
12114                     cell.className += ' x-date-today';
12115                     cell.title = cal.todayText;
12116                 }
12117                 if(t == sel){
12118                     cell.className += ' x-date-selected';
12119                     if(vis){
12120                         Ext.fly(cell.firstChild).focus(50);
12121                     }
12122                 }
12123                 // disabling
12124                 if(t < min) {
12125                     cell.className = ' x-date-disabled';
12126                     cell.title = cal.minText;
12127                     return;
12128                 }
12129                 if(t > max) {
12130                     cell.className = ' x-date-disabled';
12131                     cell.title = cal.maxText;
12132                     return;
12133                 }
12134                 if(ddays){
12135                     if(ddays.indexOf(d.getDay()) != -1){
12136                         cell.title = ddaysText;
12137                         cell.className = ' x-date-disabled';
12138                     }
12139                 }
12140                 if(ddMatch && format){
12141                     var fvalue = d.dateFormat(format);
12142                     if(ddMatch.test(fvalue)){
12143                         cell.title = ddText.replace('%0', fvalue);
12144                         cell.className = ' x-date-disabled';
12145                     }
12146                 }
12147             };
12148
12149             var i = 0;
12150             for(; i < startingPos; i++) {
12151                 textEls[i].innerHTML = (++prevStart);
12152                 d.setDate(d.getDate()+1);
12153                 cells[i].className = 'x-date-prevday';
12154                 setCellClass(this, cells[i]);
12155             }
12156             for(; i < days; i++){
12157                 var intDay = i - startingPos + 1;
12158                 textEls[i].innerHTML = (intDay);
12159                 d.setDate(d.getDate()+1);
12160                 cells[i].className = 'x-date-active';
12161                 setCellClass(this, cells[i]);
12162             }
12163             var extraDays = 0;
12164             for(; i < 42; i++) {
12165                  textEls[i].innerHTML = (++extraDays);
12166                  d.setDate(d.getDate()+1);
12167                  cells[i].className = 'x-date-nextday';
12168                  setCellClass(this, cells[i]);
12169             }
12170
12171             this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
12172
12173             if(!this.internalRender){
12174                 var main = this.el.dom.firstChild,
12175                     w = main.offsetWidth;
12176                 this.el.setWidth(w + this.el.getBorderWidth('lr'));
12177                 Ext.fly(main).setWidth(w);
12178                 this.internalRender = true;
12179                 // opera does not respect the auto grow header center column
12180                 // then, after it gets a width opera refuses to recalculate
12181                 // without a second pass
12182                 if(Ext.isOpera && !this.secondPass){
12183                     main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
12184                     this.secondPass = true;
12185                     this.update.defer(10, this, [date]);
12186                 }
12187             }
12188         }
12189     },
12190
12191     // private
12192     beforeDestroy : function() {
12193         if(this.rendered){
12194             Ext.destroy(
12195                 this.keyNav,
12196                 this.monthPicker,
12197                 this.eventEl,
12198                 this.mbtn,
12199                 this.nextRepeater,
12200                 this.prevRepeater,
12201                 this.cells.el,
12202                 this.todayBtn
12203             );
12204             delete this.textNodes;
12205             delete this.cells.elements;
12206         }
12207     }
12208
12209     /**
12210      * @cfg {String} autoEl @hide
12211      */
12212 });
12213
12214 Ext.reg('datepicker', Ext.DatePicker);
12215 /**
12216  * @class Ext.LoadMask
12217  * A simple utility class for generically masking elements while loading data.  If the {@link #store}
12218  * config option is specified, the masking will be automatically synchronized with the store's loading
12219  * process and the mask element will be cached for reuse.  For all other elements, this mask will replace the
12220  * element's Updater load indicator and will be destroyed after the initial load.
12221  * <p>Example usage:</p>
12222  *<pre><code>
12223 // Basic mask:
12224 var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
12225 myMask.show();
12226 </code></pre>
12227  * @constructor
12228  * Create a new LoadMask
12229  * @param {Mixed} el The element or DOM node, or its id
12230  * @param {Object} config The config object
12231  */
12232 Ext.LoadMask = function(el, config){
12233     this.el = Ext.get(el);
12234     Ext.apply(this, config);
12235     if(this.store){
12236         this.store.on({
12237             scope: this,
12238             beforeload: this.onBeforeLoad,
12239             load: this.onLoad,
12240             exception: this.onLoad
12241         });
12242         this.removeMask = Ext.value(this.removeMask, false);
12243     }else{
12244         var um = this.el.getUpdater();
12245         um.showLoadIndicator = false; // disable the default indicator
12246         um.on({
12247             scope: this,
12248             beforeupdate: this.onBeforeLoad,
12249             update: this.onLoad,
12250             failure: this.onLoad
12251         });
12252         this.removeMask = Ext.value(this.removeMask, true);
12253     }
12254 };
12255
12256 Ext.LoadMask.prototype = {
12257     /**
12258      * @cfg {Ext.data.Store} store
12259      * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and
12260      * hidden on either load sucess, or load fail.
12261      */
12262     /**
12263      * @cfg {Boolean} removeMask
12264      * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
12265      * False to persist the mask element reference for multiple uses (e.g., for paged data widgets).  Defaults to false.
12266      */
12267     /**
12268      * @cfg {String} msg
12269      * The text to display in a centered loading message box (defaults to 'Loading...')
12270      */
12271     msg : 'Loading...',
12272     /**
12273      * @cfg {String} msgCls
12274      * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
12275      */
12276     msgCls : 'x-mask-loading',
12277
12278     /**
12279      * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
12280      * @type Boolean
12281      */
12282     disabled: false,
12283
12284     /**
12285      * Disables the mask to prevent it from being displayed
12286      */
12287     disable : function(){
12288        this.disabled = true;
12289     },
12290
12291     /**
12292      * Enables the mask so that it can be displayed
12293      */
12294     enable : function(){
12295         this.disabled = false;
12296     },
12297
12298     // private
12299     onLoad : function(){
12300         this.el.unmask(this.removeMask);
12301     },
12302
12303     // private
12304     onBeforeLoad : function(){
12305         if(!this.disabled){
12306             this.el.mask(this.msg, this.msgCls);
12307         }
12308     },
12309
12310     /**
12311      * Show this LoadMask over the configured Element.
12312      */
12313     show: function(){
12314         this.onBeforeLoad();
12315     },
12316
12317     /**
12318      * Hide this LoadMask.
12319      */
12320     hide: function(){
12321         this.onLoad();
12322     },
12323
12324     // private
12325     destroy : function(){
12326         if(this.store){
12327             this.store.un('beforeload', this.onBeforeLoad, this);
12328             this.store.un('load', this.onLoad, this);
12329             this.store.un('exception', this.onLoad, this);
12330         }else{
12331             var um = this.el.getUpdater();
12332             um.un('beforeupdate', this.onBeforeLoad, this);
12333             um.un('update', this.onLoad, this);
12334             um.un('failure', this.onLoad, this);
12335         }
12336     }
12337 };Ext.ns('Ext.slider');
12338
12339 /**
12340  * @class Ext.slider.Thumb
12341  * @extends Object
12342  * Represents a single thumb element on a Slider. This would not usually be created manually and would instead
12343  * be created internally by an {@link Ext.slider.MultiSlider Ext.Slider}.
12344  */
12345 Ext.slider.Thumb = Ext.extend(Object, {
12346
12347     /**
12348      * @constructor
12349      * @cfg {Ext.slider.MultiSlider} slider The Slider to render to (required)
12350      */
12351     constructor: function(config) {
12352         /**
12353          * @property slider
12354          * @type Ext.slider.MultiSlider
12355          * The slider this thumb is contained within
12356          */
12357         Ext.apply(this, config || {}, {
12358             cls: 'x-slider-thumb',
12359
12360             /**
12361              * @cfg {Boolean} constrain True to constrain the thumb so that it cannot overlap its siblings
12362              */
12363             constrain: false
12364         });
12365
12366         Ext.slider.Thumb.superclass.constructor.call(this, config);
12367
12368         if (this.slider.vertical) {
12369             Ext.apply(this, Ext.slider.Thumb.Vertical);
12370         }
12371     },
12372
12373     /**
12374      * Renders the thumb into a slider
12375      */
12376     render: function() {
12377         this.el = this.slider.innerEl.insertFirst({cls: this.cls});
12378
12379         this.initEvents();
12380     },
12381
12382     /**
12383      * Enables the thumb if it is currently disabled
12384      */
12385     enable: function() {
12386         this.disabled = false;
12387         this.el.removeClass(this.slider.disabledClass);
12388     },
12389
12390     /**
12391      * Disables the thumb if it is currently enabled
12392      */
12393     disable: function() {
12394         this.disabled = true;
12395         this.el.addClass(this.slider.disabledClass);
12396     },
12397
12398     /**
12399      * Sets up an Ext.dd.DragTracker for this thumb
12400      */
12401     initEvents: function() {
12402         var el = this.el;
12403
12404         el.addClassOnOver('x-slider-thumb-over');
12405
12406         this.tracker = new Ext.dd.DragTracker({
12407             onBeforeStart: this.onBeforeDragStart.createDelegate(this),
12408             onStart      : this.onDragStart.createDelegate(this),
12409             onDrag       : this.onDrag.createDelegate(this),
12410             onEnd        : this.onDragEnd.createDelegate(this),
12411             tolerance    : 3,
12412             autoStart    : 300
12413         });
12414
12415         this.tracker.initEl(el);
12416     },
12417
12418     /**
12419      * @private
12420      * This is tied into the internal Ext.dd.DragTracker. If the slider is currently disabled,
12421      * this returns false to disable the DragTracker too.
12422      * @return {Boolean} False if the slider is currently disabled
12423      */
12424     onBeforeDragStart : function(e) {
12425         if (this.disabled) {
12426             return false;
12427         } else {
12428             this.slider.promoteThumb(this);
12429             return true;
12430         }
12431     },
12432
12433     /**
12434      * @private
12435      * This is tied into the internal Ext.dd.DragTracker's onStart template method. Adds the drag CSS class
12436      * to the thumb and fires the 'dragstart' event
12437      */
12438     onDragStart: function(e){
12439         this.el.addClass('x-slider-thumb-drag');
12440         this.dragging = true;
12441         this.dragStartValue = this.value;
12442
12443         this.slider.fireEvent('dragstart', this.slider, e, this);
12444     },
12445
12446     /**
12447      * @private
12448      * This is tied into the internal Ext.dd.DragTracker's onDrag template method. This is called every time
12449      * the DragTracker detects a drag movement. It updates the Slider's value using the position of the drag
12450      */
12451     onDrag: function(e) {
12452         var slider   = this.slider,
12453             index    = this.index,
12454             newValue = this.getNewValue();
12455
12456         if (this.constrain) {
12457             var above = slider.thumbs[index + 1],
12458                 below = slider.thumbs[index - 1];
12459
12460             if (below != undefined && newValue <= below.value) newValue = below.value;
12461             if (above != undefined && newValue >= above.value) newValue = above.value;
12462         }
12463
12464         slider.setValue(index, newValue, false);
12465         slider.fireEvent('drag', slider, e, this);
12466     },
12467
12468     getNewValue: function() {
12469         var slider   = this.slider,
12470             pos      = slider.innerEl.translatePoints(this.tracker.getXY());
12471
12472         return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
12473     },
12474
12475     /**
12476      * @private
12477      * This is tied to the internal Ext.dd.DragTracker's onEnd template method. Removes the drag CSS class and
12478      * fires the 'changecomplete' event with the new value
12479      */
12480     onDragEnd: function(e) {
12481         var slider = this.slider,
12482             value  = this.value;
12483
12484         this.el.removeClass('x-slider-thumb-drag');
12485
12486         this.dragging = false;
12487         slider.fireEvent('dragend', slider, e);
12488
12489         if (this.dragStartValue != value) {
12490             slider.fireEvent('changecomplete', slider, value, this);
12491         }
12492     }
12493 });
12494
12495 /**
12496  * @class Ext.slider.MultiSlider
12497  * @extends Ext.BoxComponent
12498  * Slider which supports vertical or horizontal orientation, keyboard adjustments, configurable snapping, axis clicking and animation. Can be added as an item to any container. Example usage:
12499 <pre>
12500 new Ext.Slider({
12501     renderTo: Ext.getBody(),
12502     width: 200,
12503     value: 50,
12504     increment: 10,
12505     minValue: 0,
12506     maxValue: 100
12507 });
12508 </pre>
12509  * Sliders can be created with more than one thumb handle by passing an array of values instead of a single one:
12510 <pre>
12511 new Ext.Slider({
12512     renderTo: Ext.getBody(),
12513     width: 200,
12514     values: [25, 50, 75],
12515     minValue: 0,
12516     maxValue: 100,
12517
12518     //this defaults to true, setting to false allows the thumbs to pass each other
12519     {@link #constrainThumbs}: false
12520 });
12521 </pre>
12522  */
12523 Ext.slider.MultiSlider = Ext.extend(Ext.BoxComponent, {
12524     /**
12525      * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.
12526      */
12527     /**
12528      * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.
12529      */
12530     vertical: false,
12531     /**
12532      * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.
12533      */
12534     minValue: 0,
12535     /**
12536      * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.
12537      */
12538     maxValue: 100,
12539     /**
12540      * @cfg {Number/Boolean} decimalPrecision.
12541      * <p>The number of decimal places to which to round the Slider's value. Defaults to 0.</p>
12542      * <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>
12543      */
12544     decimalPrecision: 0,
12545     /**
12546      * @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.
12547      */
12548     keyIncrement: 1,
12549     /**
12550      * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.
12551      */
12552     increment: 0,
12553
12554     /**
12555      * @private
12556      * @property clickRange
12557      * @type Array
12558      * Determines whether or not a click to the slider component is considered to be a user request to change the value. Specified as an array of [top, bottom],
12559      * the click event's 'top' property is compared to these numbers and the click only considered a change request if it falls within them. e.g. if the 'top'
12560      * value of the click event is 4 or 16, the click is not considered a change request as it falls outside of the [5, 15] range
12561      */
12562     clickRange: [5,15],
12563
12564     /**
12565      * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true
12566      */
12567     clickToChange : true,
12568     /**
12569      * @cfg {Boolean} animate Turn on or off animation. Defaults to true
12570      */
12571     animate: true,
12572
12573     /**
12574      * True while the thumb is in a drag operation
12575      * @type Boolean
12576      */
12577     dragging: false,
12578
12579     /**
12580      * @cfg {Boolean} constrainThumbs True to disallow thumbs from overlapping one another. Defaults to true
12581      */
12582     constrainThumbs: true,
12583
12584     /**
12585      * @private
12586      * @property topThumbZIndex
12587      * @type Number
12588      * The number used internally to set the z index of the top thumb (see promoteThumb for details)
12589      */
12590     topThumbZIndex: 10000,
12591
12592     // private override
12593     initComponent : function(){
12594         if(!Ext.isDefined(this.value)){
12595             this.value = this.minValue;
12596         }
12597
12598         /**
12599          * @property thumbs
12600          * @type Array
12601          * Array containing references to each thumb
12602          */
12603         this.thumbs = [];
12604
12605         Ext.slider.MultiSlider.superclass.initComponent.call(this);
12606
12607         this.keyIncrement = Math.max(this.increment, this.keyIncrement);
12608         this.addEvents(
12609             /**
12610              * @event beforechange
12611              * Fires before the slider value is changed. By returning false from an event handler,
12612              * you can cancel the event and prevent the slider from changing.
12613              * @param {Ext.Slider} slider The slider
12614              * @param {Number} newValue The new value which the slider is being changed to.
12615              * @param {Number} oldValue The old value which the slider was previously.
12616              */
12617             'beforechange',
12618
12619             /**
12620              * @event change
12621              * Fires when the slider value is changed.
12622              * @param {Ext.Slider} slider The slider
12623              * @param {Number} newValue The new value which the slider has been changed to.
12624              * @param {Ext.slider.Thumb} thumb The thumb that was changed
12625              */
12626             'change',
12627
12628             /**
12629              * @event changecomplete
12630              * Fires when the slider value is changed by the user and any drag operations have completed.
12631              * @param {Ext.Slider} slider The slider
12632              * @param {Number} newValue The new value which the slider has been changed to.
12633              * @param {Ext.slider.Thumb} thumb The thumb that was changed
12634              */
12635             'changecomplete',
12636
12637             /**
12638              * @event dragstart
12639              * Fires after a drag operation has started.
12640              * @param {Ext.Slider} slider The slider
12641              * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
12642              */
12643             'dragstart',
12644
12645             /**
12646              * @event drag
12647              * Fires continuously during the drag operation while the mouse is moving.
12648              * @param {Ext.Slider} slider The slider
12649              * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
12650              */
12651             'drag',
12652
12653             /**
12654              * @event dragend
12655              * Fires after the drag operation has completed.
12656              * @param {Ext.Slider} slider The slider
12657              * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
12658              */
12659             'dragend'
12660         );
12661
12662         /**
12663          * @property values
12664          * @type Array
12665          * Array of values to initalize the thumbs with
12666          */
12667         if (this.values == undefined || Ext.isEmpty(this.values)) this.values = [0];
12668
12669         var values = this.values;
12670
12671         for (var i=0; i < values.length; i++) {
12672             this.addThumb(values[i]);
12673         }
12674
12675         if(this.vertical){
12676             Ext.apply(this, Ext.slider.Vertical);
12677         }
12678     },
12679
12680     /**
12681      * Creates a new thumb and adds it to the slider
12682      * @param {Number} value The initial value to set on the thumb. Defaults to 0
12683      */
12684     addThumb: function(value) {
12685         var thumb = new Ext.slider.Thumb({
12686             value    : value,
12687             slider   : this,
12688             index    : this.thumbs.length,
12689             constrain: this.constrainThumbs
12690         });
12691         this.thumbs.push(thumb);
12692
12693         //render the thumb now if needed
12694         if (this.rendered) thumb.render();
12695     },
12696
12697     /**
12698      * @private
12699      * Moves the given thumb above all other by increasing its z-index. This is called when as drag
12700      * any thumb, so that the thumb that was just dragged is always at the highest z-index. This is
12701      * required when the thumbs are stacked on top of each other at one of the ends of the slider's
12702      * range, which can result in the user not being able to move any of them.
12703      * @param {Ext.slider.Thumb} topThumb The thumb to move to the top
12704      */
12705     promoteThumb: function(topThumb) {
12706         var thumbs = this.thumbs,
12707             zIndex, thumb;
12708
12709         for (var i = 0, j = thumbs.length; i < j; i++) {
12710             thumb = thumbs[i];
12711
12712             if (thumb == topThumb) {
12713                 zIndex = this.topThumbZIndex;
12714             } else {
12715                 zIndex = '';
12716             }
12717
12718             thumb.el.setStyle('zIndex', zIndex);
12719         }
12720     },
12721
12722     // private override
12723     onRender : function() {
12724         this.autoEl = {
12725             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
12726             cn : {
12727                 cls: 'x-slider-end',
12728                 cn : {
12729                     cls:'x-slider-inner',
12730                     cn : [{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]
12731                 }
12732             }
12733         };
12734
12735         Ext.slider.MultiSlider.superclass.onRender.apply(this, arguments);
12736
12737         this.endEl   = this.el.first();
12738         this.innerEl = this.endEl.first();
12739         this.focusEl = this.innerEl.child('.x-slider-focus');
12740
12741         //render each thumb
12742         for (var i=0; i < this.thumbs.length; i++) {
12743             this.thumbs[i].render();
12744         }
12745
12746         //calculate the size of half a thumb
12747         var thumb      = this.innerEl.child('.x-slider-thumb');
12748         this.halfThumb = (this.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
12749
12750         this.initEvents();
12751     },
12752
12753     /**
12754      * @private
12755      * Adds keyboard and mouse listeners on this.el. Ignores click events on the internal focus element.
12756      * Creates a new DragTracker which is used to control what happens when the user drags the thumb around.
12757      */
12758     initEvents : function(){
12759         this.mon(this.el, {
12760             scope    : this,
12761             mousedown: this.onMouseDown,
12762             keydown  : this.onKeyDown
12763         });
12764
12765         this.focusEl.swallowEvent("click", true);
12766     },
12767
12768     /**
12769      * @private
12770      * Mousedown handler for the slider. If the clickToChange is enabled and the click was not on the draggable 'thumb',
12771      * this calculates the new value of the slider and tells the implementation (Horizontal or Vertical) to move the thumb
12772      * @param {Ext.EventObject} e The click event
12773      */
12774     onMouseDown : function(e){
12775         if(this.disabled){
12776             return;
12777         }
12778
12779         //see if the click was on any of the thumbs
12780         var thumbClicked = false;
12781         for (var i=0; i < this.thumbs.length; i++) {
12782             thumbClicked = thumbClicked || e.target == this.thumbs[i].el.dom;
12783         }
12784
12785         if (this.clickToChange && !thumbClicked) {
12786             var local = this.innerEl.translatePoints(e.getXY());
12787             this.onClickChange(local);
12788         }
12789         this.focus();
12790     },
12791
12792     /**
12793      * @private
12794      * Moves the thumb to the indicated position. Note that a Vertical implementation is provided in Ext.slider.Vertical.
12795      * Only changes the value if the click was within this.clickRange.
12796      * @param {Object} local Object containing top and left values for the click event.
12797      */
12798     onClickChange : function(local) {
12799         if (local.top > this.clickRange[0] && local.top < this.clickRange[1]) {
12800             //find the nearest thumb to the click event
12801             var thumb = this.getNearest(local, 'left'),
12802                 index = thumb.index;
12803
12804             this.setValue(index, Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
12805         }
12806     },
12807
12808     /**
12809      * @private
12810      * Returns the nearest thumb to a click event, along with its distance
12811      * @param {Object} local Object containing top and left values from a click event
12812      * @param {String} prop The property of local to compare on. Use 'left' for horizontal sliders, 'top' for vertical ones
12813      * @return {Object} The closest thumb object and its distance from the click event
12814      */
12815     getNearest: function(local, prop) {
12816         var localValue = prop == 'top' ? this.innerEl.getHeight() - local[prop] : local[prop],
12817             clickValue = this.reverseValue(localValue),
12818             nearestDistance = (this.maxValue - this.minValue) + 5, //add a small fudge for the end of the slider 
12819             index = 0,
12820             nearest = null;
12821
12822         for (var i=0; i < this.thumbs.length; i++) {
12823             var thumb = this.thumbs[i],
12824                 value = thumb.value,
12825                 dist  = Math.abs(value - clickValue);
12826
12827             if (Math.abs(dist <= nearestDistance)) {
12828                 nearest = thumb;
12829                 index = i;
12830                 nearestDistance = dist;
12831             }
12832         }
12833         return nearest;
12834     },
12835
12836     /**
12837      * @private
12838      * Handler for any keypresses captured by the slider. If the key is UP or RIGHT, the thumb is moved along to the right
12839      * by this.keyIncrement. If DOWN or LEFT it is moved left. Pressing CTRL moves the slider to the end in either direction
12840      * @param {Ext.EventObject} e The Event object
12841      */
12842     onKeyDown : function(e){
12843         /*
12844          * The behaviour for keyboard handling with multiple thumbs is currently undefined.
12845          * There's no real sane default for it, so leave it like this until we come up
12846          * with a better way of doing it.
12847          */
12848         if(this.disabled || this.thumbs.length !== 1){
12849             e.preventDefault();
12850             return;
12851         }
12852         var k = e.getKey(),
12853             val;
12854         switch(k){
12855             case e.UP:
12856             case e.RIGHT:
12857                 e.stopEvent();
12858                 val = e.ctrlKey ? this.maxValue : this.getValue(0) + this.keyIncrement;
12859                 this.setValue(0, val, undefined, true);
12860             break;
12861             case e.DOWN:
12862             case e.LEFT:
12863                 e.stopEvent();
12864                 val = e.ctrlKey ? this.minValue : this.getValue(0) - this.keyIncrement;
12865                 this.setValue(0, val, undefined, true);
12866             break;
12867             default:
12868                 e.preventDefault();
12869         }
12870     },
12871
12872     /**
12873      * @private
12874      * If using snapping, this takes a desired new value and returns the closest snapped
12875      * value to it
12876      * @param {Number} value The unsnapped value
12877      * @return {Number} The value of the nearest snap target
12878      */
12879     doSnap : function(value){
12880         if (!(this.increment && value)) {
12881             return value;
12882         }
12883         var newValue = value,
12884             inc = this.increment,
12885             m = value % inc;
12886         if (m != 0) {
12887             newValue -= m;
12888             if (m * 2 >= inc) {
12889                 newValue += inc;
12890             } else if (m * 2 < -inc) {
12891                 newValue -= inc;
12892             }
12893         }
12894         return newValue.constrain(this.minValue,  this.maxValue);
12895     },
12896
12897     // private
12898     afterRender : function(){
12899         Ext.slider.MultiSlider.superclass.afterRender.apply(this, arguments);
12900
12901         for (var i=0; i < this.thumbs.length; i++) {
12902             var thumb = this.thumbs[i];
12903
12904             if (thumb.value !== undefined) {
12905                 var v = this.normalizeValue(thumb.value);
12906
12907                 if (v !== thumb.value) {
12908                     // delete this.value;
12909                     this.setValue(i, v, false);
12910                 } else {
12911                     this.moveThumb(i, this.translateValue(v), false);
12912                 }
12913             }
12914         };
12915     },
12916
12917     /**
12918      * @private
12919      * Returns the ratio of pixels to mapped values. e.g. if the slider is 200px wide and maxValue - minValue is 100,
12920      * the ratio is 2
12921      * @return {Number} The ratio of pixels to mapped values
12922      */
12923     getRatio : function(){
12924         var w = this.innerEl.getWidth(),
12925             v = this.maxValue - this.minValue;
12926         return v == 0 ? w : (w/v);
12927     },
12928
12929     /**
12930      * @private
12931      * Returns a snapped, constrained value when given a desired value
12932      * @param {Number} value Raw number value
12933      * @return {Number} The raw value rounded to the correct d.p. and constrained within the set max and min values
12934      */
12935     normalizeValue : function(v){
12936         v = this.doSnap(v);
12937         v = Ext.util.Format.round(v, this.decimalPrecision);
12938         v = v.constrain(this.minValue, this.maxValue);
12939         return v;
12940     },
12941
12942     /**
12943      * Sets the minimum value for the slider instance. If the current value is less than the
12944      * minimum value, the current value will be changed.
12945      * @param {Number} val The new minimum value
12946      */
12947     setMinValue : function(val){
12948         this.minValue = val;
12949         var i = 0,
12950             thumbs = this.thumbs,
12951             len = thumbs.length,
12952             t;
12953             
12954         for(; i < len; ++i){
12955             t = thumbs[i];
12956             t.value = t.value < val ? val : t.value;
12957         }
12958         this.syncThumb();
12959     },
12960
12961     /**
12962      * Sets the maximum value for the slider instance. If the current value is more than the
12963      * maximum value, the current value will be changed.
12964      * @param {Number} val The new maximum value
12965      */
12966     setMaxValue : function(val){
12967         this.maxValue = val;
12968         var i = 0,
12969             thumbs = this.thumbs,
12970             len = thumbs.length,
12971             t;
12972             
12973         for(; i < len; ++i){
12974             t = thumbs[i];
12975             t.value = t.value > val ? val : t.value;
12976         }
12977         this.syncThumb();
12978     },
12979
12980     /**
12981      * Programmatically sets the value of the Slider. Ensures that the value is constrained within
12982      * the minValue and maxValue.
12983      * @param {Number} index Index of the thumb to move
12984      * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)
12985      * @param {Boolean} animate Turn on or off animation, defaults to true
12986      */
12987     setValue : function(index, v, animate, changeComplete) {
12988         var thumb = this.thumbs[index],
12989             el    = thumb.el;
12990
12991         v = this.normalizeValue(v);
12992
12993         if (v !== thumb.value && this.fireEvent('beforechange', this, v, thumb.value, thumb) !== false) {
12994             thumb.value = v;
12995             if(this.rendered){
12996                 this.moveThumb(index, this.translateValue(v), animate !== false);
12997                 this.fireEvent('change', this, v, thumb);
12998                 if(changeComplete){
12999                     this.fireEvent('changecomplete', this, v, thumb);
13000                 }
13001             }
13002         }
13003     },
13004
13005     /**
13006      * @private
13007      */
13008     translateValue : function(v) {
13009         var ratio = this.getRatio();
13010         return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
13011     },
13012
13013     /**
13014      * @private
13015      * Given a pixel location along the slider, returns the mapped slider value for that pixel.
13016      * E.g. if we have a slider 200px wide with minValue = 100 and maxValue = 500, reverseValue(50)
13017      * returns 200
13018      * @param {Number} pos The position along the slider to return a mapped value for
13019      * @return {Number} The mapped value for the given position
13020      */
13021     reverseValue : function(pos){
13022         var ratio = this.getRatio();
13023         return (pos + (this.minValue * ratio)) / ratio;
13024     },
13025
13026     /**
13027      * @private
13028      * @param {Number} index Index of the thumb to move
13029      */
13030     moveThumb: function(index, v, animate){
13031         var thumb = this.thumbs[index].el;
13032
13033         if(!animate || this.animate === false){
13034             thumb.setLeft(v);
13035         }else{
13036             thumb.shift({left: v, stopFx: true, duration:.35});
13037         }
13038     },
13039
13040     // private
13041     focus : function(){
13042         this.focusEl.focus(10);
13043     },
13044
13045     // private
13046     onResize : function(w, h){
13047         var thumbs = this.thumbs,
13048             len = thumbs.length,
13049             i = 0;
13050             
13051         /*
13052          * If we happen to be animating during a resize, the position of the thumb will likely be off
13053          * when the animation stops. As such, just stop any animations before syncing the thumbs.
13054          */
13055         for(; i < len; ++i){
13056             thumbs[i].el.stopFx();    
13057         }
13058         this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
13059         this.syncThumb();
13060         Ext.slider.MultiSlider.superclass.onResize.apply(this, arguments);
13061     },
13062
13063     //private
13064     onDisable: function(){
13065         Ext.slider.MultiSlider.superclass.onDisable.call(this);
13066
13067         for (var i=0; i < this.thumbs.length; i++) {
13068             var thumb = this.thumbs[i],
13069                 el    = thumb.el;
13070
13071             thumb.disable();
13072
13073             if(Ext.isIE){
13074                 //IE breaks when using overflow visible and opacity other than 1.
13075                 //Create a place holder for the thumb and display it.
13076                 var xy = el.getXY();
13077                 el.hide();
13078
13079                 this.innerEl.addClass(this.disabledClass).dom.disabled = true;
13080
13081                 if (!this.thumbHolder) {
13082                     this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});
13083                 }
13084
13085                 this.thumbHolder.show().setXY(xy);
13086             }
13087         }
13088     },
13089
13090     //private
13091     onEnable: function(){
13092         Ext.slider.MultiSlider.superclass.onEnable.call(this);
13093
13094         for (var i=0; i < this.thumbs.length; i++) {
13095             var thumb = this.thumbs[i],
13096                 el    = thumb.el;
13097
13098             thumb.enable();
13099
13100             if (Ext.isIE) {
13101                 this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
13102
13103                 if (this.thumbHolder) this.thumbHolder.hide();
13104
13105                 el.show();
13106                 this.syncThumb();
13107             }
13108         }
13109     },
13110
13111     /**
13112      * Synchronizes the thumb position to the proper proportion of the total component width based
13113      * on the current slider {@link #value}.  This will be called automatically when the Slider
13114      * is resized by a layout, but if it is rendered auto width, this method can be called from
13115      * another resize handler to sync the Slider if necessary.
13116      */
13117     syncThumb : function() {
13118         if (this.rendered) {
13119             for (var i=0; i < this.thumbs.length; i++) {
13120                 this.moveThumb(i, this.translateValue(this.thumbs[i].value));
13121             }
13122         }
13123     },
13124
13125     /**
13126      * Returns the current value of the slider
13127      * @param {Number} index The index of the thumb to return a value for
13128      * @return {Number} The current value of the slider
13129      */
13130     getValue : function(index) {
13131         return this.thumbs[index].value;
13132     },
13133
13134     /**
13135      * Returns an array of values - one for the location of each thumb
13136      * @return {Array} The set of thumb values
13137      */
13138     getValues: function() {
13139         var values = [];
13140
13141         for (var i=0; i < this.thumbs.length; i++) {
13142             values.push(this.thumbs[i].value);
13143         }
13144
13145         return values;
13146     },
13147
13148     // private
13149     beforeDestroy : function(){
13150         Ext.destroyMembers(this, 'endEl', 'innerEl', 'thumb', 'halfThumb', 'focusEl', 'tracker', 'thumbHolder');
13151         Ext.slider.MultiSlider.superclass.beforeDestroy.call(this);
13152     }
13153 });
13154
13155 Ext.reg('multislider', Ext.slider.MultiSlider);
13156
13157 /**
13158  * @class Ext.slider.SingleSlider
13159  * @extends Ext.slider.MultiSlider
13160  * Slider which supports vertical or horizontal orientation, keyboard adjustments,
13161  * configurable snapping, axis clicking and animation. Can be added as an item to
13162  * any container. Example usage:
13163 <pre><code>
13164 new Ext.slider.SingleSlider({
13165     renderTo: Ext.getBody(),
13166     width: 200,
13167     value: 50,
13168     increment: 10,
13169     minValue: 0,
13170     maxValue: 100
13171 });
13172 </code></pre>
13173  * The class Ext.slider.SingleSlider is aliased to Ext.Slider for backwards compatibility.
13174  */
13175 Ext.slider.SingleSlider = Ext.extend(Ext.slider.MultiSlider, {
13176     constructor: function(config) {
13177       config = config || {};
13178
13179       Ext.applyIf(config, {
13180           values: [config.value || 0]
13181       });
13182
13183       Ext.slider.SingleSlider.superclass.constructor.call(this, config);
13184     },
13185
13186     /**
13187      * Returns the current value of the slider
13188      * @return {Number} The current value of the slider
13189      */
13190     getValue: function() {
13191         //just returns the value of the first thumb, which should be the only one in a single slider
13192         return Ext.slider.SingleSlider.superclass.getValue.call(this, 0);
13193     },
13194
13195     /**
13196      * Programmatically sets the value of the Slider. Ensures that the value is constrained within
13197      * the minValue and maxValue.
13198      * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)
13199      * @param {Boolean} animate Turn on or off animation, defaults to true
13200      */
13201     setValue: function(value, animate) {
13202         var args = Ext.toArray(arguments),
13203             len  = args.length;
13204
13205         //this is to maintain backwards compatiblity for sliders with only one thunb. Usually you must pass the thumb
13206         //index to setValue, but if we only have one thumb we inject the index here first if given the multi-slider
13207         //signature without the required index. The index will always be 0 for a single slider
13208         if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
13209             args.unshift(0);
13210         }
13211
13212         return Ext.slider.SingleSlider.superclass.setValue.apply(this, args);
13213     },
13214
13215     /**
13216      * Synchronizes the thumb position to the proper proportion of the total component width based
13217      * on the current slider {@link #value}.  This will be called automatically when the Slider
13218      * is resized by a layout, but if it is rendered auto width, this method can be called from
13219      * another resize handler to sync the Slider if necessary.
13220      */
13221     syncThumb : function() {
13222         return Ext.slider.SingleSlider.superclass.syncThumb.apply(this, [0].concat(arguments));
13223     },
13224     
13225     // private
13226     getNearest : function(){
13227         // Since there's only 1 thumb, it's always the nearest
13228         return this.thumbs[0];    
13229     }
13230 });
13231
13232 //backwards compatibility
13233 Ext.Slider = Ext.slider.SingleSlider;
13234
13235 Ext.reg('slider', Ext.slider.SingleSlider);
13236
13237 // private class to support vertical sliders
13238 Ext.slider.Vertical = {
13239     onResize : function(w, h){
13240         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
13241         this.syncThumb();
13242     },
13243
13244     getRatio : function(){
13245         var h = this.innerEl.getHeight(),
13246             v = this.maxValue - this.minValue;
13247         return h/v;
13248     },
13249
13250     moveThumb: function(index, v, animate) {
13251         var thumb = this.thumbs[index],
13252             el    = thumb.el;
13253
13254         if (!animate || this.animate === false) {
13255             el.setBottom(v);
13256         } else {
13257             el.shift({bottom: v, stopFx: true, duration:.35});
13258         }
13259     },
13260
13261     onClickChange : function(local) {
13262         if (local.left > this.clickRange[0] && local.left < this.clickRange[1]) {
13263             var thumb = this.getNearest(local, 'top'),
13264                 index = thumb.index,
13265                 value = this.minValue + this.reverseValue(this.innerEl.getHeight() - local.top);
13266
13267             this.setValue(index, Ext.util.Format.round(value, this.decimalPrecision), undefined, true);
13268         }
13269     }
13270 };
13271
13272 //private class to support vertical dragging of thumbs within a slider
13273 Ext.slider.Thumb.Vertical = {
13274     getNewValue: function() {
13275         var slider   = this.slider,
13276             innerEl  = slider.innerEl,
13277             pos      = innerEl.translatePoints(this.tracker.getXY()),
13278             bottom   = innerEl.getHeight() - pos.top;
13279
13280         return slider.minValue + Ext.util.Format.round(bottom / slider.getRatio(), slider.decimalPrecision);
13281     }
13282 };
13283 /**
13284  * @class Ext.ProgressBar
13285  * @extends Ext.BoxComponent
13286  * <p>An updateable progress bar component.  The progress bar supports two different modes: manual and automatic.</p>
13287  * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the
13288  * progress bar as needed from your own code.  This method is most appropriate when you want to show progress
13289  * throughout an operation that has predictable points of interest at which you can update the control.</p>
13290  * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it
13291  * once the operation is complete.  You can optionally have the progress bar wait for a specific amount of time
13292  * and then clear itself.  Automatic mode is most appropriate for timed operations or asynchronous operations in
13293  * which you have no need for indicating intermediate progress.</p>
13294  * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0)
13295  * @cfg {String} text The progress bar text (defaults to '')
13296  * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress
13297  * bar's internal text element)
13298  * @cfg {String} id The progress bar element's id (defaults to an auto-generated id)
13299  * @xtype progress
13300  */
13301 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
13302    /**
13303     * @cfg {String} baseCls
13304     * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress')
13305     */
13306     baseCls : 'x-progress',
13307     
13308     /**
13309     * @cfg {Boolean} animate
13310     * True to animate the progress bar during transitions (defaults to false)
13311     */
13312     animate : false,
13313
13314     // private
13315     waitTimer : null,
13316
13317     // private
13318     initComponent : function(){
13319         Ext.ProgressBar.superclass.initComponent.call(this);
13320         this.addEvents(
13321             /**
13322              * @event update
13323              * Fires after each update interval
13324              * @param {Ext.ProgressBar} this
13325              * @param {Number} The current progress value
13326              * @param {String} The current progress text
13327              */
13328             "update"
13329         );
13330     },
13331
13332     // private
13333     onRender : function(ct, position){
13334         var tpl = new Ext.Template(
13335             '<div class="{cls}-wrap">',
13336                 '<div class="{cls}-inner">',
13337                     '<div class="{cls}-bar">',
13338                         '<div class="{cls}-text">',
13339                             '<div>&#160;</div>',
13340                         '</div>',
13341                     '</div>',
13342                     '<div class="{cls}-text {cls}-text-back">',
13343                         '<div>&#160;</div>',
13344                     '</div>',
13345                 '</div>',
13346             '</div>'
13347         );
13348
13349         this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
13350             : tpl.append(ct, {cls: this.baseCls}, true);
13351                 
13352         if(this.id){
13353             this.el.dom.id = this.id;
13354         }
13355         var inner = this.el.dom.firstChild;
13356         this.progressBar = Ext.get(inner.firstChild);
13357
13358         if(this.textEl){
13359             //use an external text el
13360             this.textEl = Ext.get(this.textEl);
13361             delete this.textTopEl;
13362         }else{
13363             //setup our internal layered text els
13364             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
13365             var textBackEl = Ext.get(inner.childNodes[1]);
13366             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
13367             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
13368             this.textEl.setWidth(inner.offsetWidth);
13369         }
13370         this.progressBar.setHeight(inner.offsetHeight);
13371     },
13372     
13373     // private
13374     afterRender : function(){
13375         Ext.ProgressBar.superclass.afterRender.call(this);
13376         if(this.value){
13377             this.updateProgress(this.value, this.text);
13378         }else{
13379             this.updateText(this.text);
13380         }
13381     },
13382
13383     /**
13384      * Updates the progress bar value, and optionally its text.  If the text argument is not specified,
13385      * any existing text value will be unchanged.  To blank out existing text, pass ''.  Note that even
13386      * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for
13387      * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control.
13388      * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0)
13389      * @param {String} text (optional) The string to display in the progress text element (defaults to '')
13390      * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is
13391      * not specified, the default for the class is used (default to false)
13392      * @return {Ext.ProgressBar} this
13393      */
13394     updateProgress : function(value, text, animate){
13395         this.value = value || 0;
13396         if(text){
13397             this.updateText(text);
13398         }
13399         if(this.rendered && !this.isDestroyed){
13400             var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
13401             this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
13402             if(this.textTopEl){
13403                 //textTopEl should be the same width as the bar so overflow will clip as the bar moves
13404                 this.textTopEl.removeClass('x-hidden').setWidth(w);
13405             }
13406         }
13407         this.fireEvent('update', this, value, text);
13408         return this;
13409     },
13410
13411     /**
13412      * Initiates an auto-updating progress bar.  A duration can be specified, in which case the progress
13413      * bar will automatically reset after a fixed amount of time and optionally call a callback function
13414      * if specified.  If no duration is passed in, then the progress bar will run indefinitely and must
13415      * be manually cleared by calling {@link #reset}.  The wait method accepts a config object with
13416      * the following properties:
13417      * <pre>
13418 Property   Type          Description
13419 ---------- ------------  ----------------------------------------------------------------------
13420 duration   Number        The length of time in milliseconds that the progress bar should
13421                          run before resetting itself (defaults to undefined, in which case it
13422                          will run indefinitely until reset is called)
13423 interval   Number        The length of time in milliseconds between each progress update
13424                          (defaults to 1000 ms)
13425 animate    Boolean       Whether to animate the transition of the progress bar. If this value is
13426                          not specified, the default for the class is used.                                                   
13427 increment  Number        The number of progress update segments to display within the progress
13428                          bar (defaults to 10).  If the bar reaches the end and is still
13429                          updating, it will automatically wrap back to the beginning.
13430 text       String        Optional text to display in the progress bar element (defaults to '').
13431 fn         Function      A callback function to execute after the progress bar finishes auto-
13432                          updating.  The function will be called with no arguments.  This function
13433                          will be ignored if duration is not specified since in that case the
13434                          progress bar can only be stopped programmatically, so any required function
13435                          should be called by the same code after it resets the progress bar.
13436 scope      Object        The scope that is passed to the callback function (only applies when
13437                          duration and fn are both passed).
13438 </pre>
13439          *
13440          * Example usage:
13441          * <pre><code>
13442 var p = new Ext.ProgressBar({
13443    renderTo: 'my-el'
13444 });
13445
13446 //Wait for 5 seconds, then update the status el (progress bar will auto-reset)
13447 p.wait({
13448    interval: 100, //bar will move fast!
13449    duration: 5000,
13450    increment: 15,
13451    text: 'Updating...',
13452    scope: this,
13453    fn: function(){
13454       Ext.fly('status').update('Done!');
13455    }
13456 });
13457
13458 //Or update indefinitely until some async action completes, then reset manually
13459 p.wait();
13460 myAction.on('complete', function(){
13461     p.reset();
13462     Ext.fly('status').update('Done!');
13463 });
13464 </code></pre>
13465      * @param {Object} config (optional) Configuration options
13466      * @return {Ext.ProgressBar} this
13467      */
13468     wait : function(o){
13469         if(!this.waitTimer){
13470             var scope = this;
13471             o = o || {};
13472             this.updateText(o.text);
13473             this.waitTimer = Ext.TaskMgr.start({
13474                 run: function(i){
13475                     var inc = o.increment || 10;
13476                     i -= 1;
13477                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
13478                 },
13479                 interval: o.interval || 1000,
13480                 duration: o.duration,
13481                 onStop: function(){
13482                     if(o.fn){
13483                         o.fn.apply(o.scope || this);
13484                     }
13485                     this.reset();
13486                 },
13487                 scope: scope
13488             });
13489         }
13490         return this;
13491     },
13492
13493     /**
13494      * Returns true if the progress bar is currently in a {@link #wait} operation
13495      * @return {Boolean} True if waiting, else false
13496      */
13497     isWaiting : function(){
13498         return this.waitTimer !== null;
13499     },
13500
13501     /**
13502      * Updates the progress bar text.  If specified, textEl will be updated, otherwise the progress
13503      * bar itself will display the updated text.
13504      * @param {String} text (optional) The string to display in the progress text element (defaults to '')
13505      * @return {Ext.ProgressBar} this
13506      */
13507     updateText : function(text){
13508         this.text = text || '&#160;';
13509         if(this.rendered){
13510             this.textEl.update(this.text);
13511         }
13512         return this;
13513     },
13514     
13515     /**
13516      * Synchronizes the inner bar width to the proper proportion of the total componet width based
13517      * on the current progress {@link #value}.  This will be called automatically when the ProgressBar
13518      * is resized by a layout, but if it is rendered auto width, this method can be called from
13519      * another resize handler to sync the ProgressBar if necessary.
13520      */
13521     syncProgressBar : function(){
13522         if(this.value){
13523             this.updateProgress(this.value, this.text);
13524         }
13525         return this;
13526     },
13527
13528     /**
13529      * Sets the size of the progress bar.
13530      * @param {Number} width The new width in pixels
13531      * @param {Number} height The new height in pixels
13532      * @return {Ext.ProgressBar} this
13533      */
13534     setSize : function(w, h){
13535         Ext.ProgressBar.superclass.setSize.call(this, w, h);
13536         if(this.textTopEl){
13537             var inner = this.el.dom.firstChild;
13538             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
13539         }
13540         this.syncProgressBar();
13541         return this;
13542     },
13543
13544     /**
13545      * Resets the progress bar value to 0 and text to empty string.  If hide = true, the progress
13546      * bar will also be hidden (using the {@link #hideMode} property internally).
13547      * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false)
13548      * @return {Ext.ProgressBar} this
13549      */
13550     reset : function(hide){
13551         this.updateProgress(0);
13552         if(this.textTopEl){
13553             this.textTopEl.addClass('x-hidden');
13554         }
13555         this.clearTimer();
13556         if(hide === true){
13557             this.hide();
13558         }
13559         return this;
13560     },
13561     
13562     // private
13563     clearTimer : function(){
13564         if(this.waitTimer){
13565             this.waitTimer.onStop = null; //prevent recursion
13566             Ext.TaskMgr.stop(this.waitTimer);
13567             this.waitTimer = null;
13568         }
13569     },
13570     
13571     onDestroy: function(){
13572         this.clearTimer();
13573         if(this.rendered){
13574             if(this.textEl.isComposite){
13575                 this.textEl.clear();
13576             }
13577             Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
13578         }
13579         Ext.ProgressBar.superclass.onDestroy.call(this);
13580     }
13581 });
13582 Ext.reg('progress', Ext.ProgressBar);