Upgrade to ExtJS 3.2.0 - Released 03/30/2010
[extjs.git] / pkgs / cmp-foundation-debug.js
1 /*!
2  * Ext JS Library 3.2.0
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.initItems();
4328         this.layout = layout;
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     * We can only lay out if there is a view area in which to layout.
4633     * display:none on the layout target, *or any of its parent elements* will mean it has no view area.
4634     */
4635
4636     // private
4637     canLayout : function() {
4638         var el = this.getVisibilityEl();
4639         return el && el.dom && !el.isStyle("display", "none");
4640     },
4641
4642     /**
4643      * Force this container's layout to be recalculated. A call to this function is required after adding a new component
4644      * to an already rendered container, or possibly after changing sizing/position properties of child components.
4645      * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto
4646      * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer)
4647      * @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden.
4648      * @return {Ext.Container} this
4649      */
4650
4651     doLayout : function(shallow, force){
4652         var rendered = this.rendered,
4653             forceLayout = force || this.forceLayout;
4654
4655         if(this.collapsed || !this.canLayout()){
4656             this.deferLayout = this.deferLayout || !shallow;
4657             if(!forceLayout){
4658                 return;
4659             }
4660             shallow = shallow && !this.deferLayout;
4661         } else {
4662             delete this.deferLayout;
4663         }
4664         if(rendered && this.layout){
4665             this.layout.layout();
4666         }
4667         if(shallow !== true && this.items){
4668             var cs = this.items.items;
4669             for(var i = 0, len = cs.length; i < len; i++){
4670                 var c = cs[i];
4671                 if(c.doLayout){
4672                     c.doLayout(false, forceLayout);
4673                 }
4674             }
4675         }
4676         if(rendered){
4677             this.onLayout(shallow, forceLayout);
4678         }
4679         // Initial layout completed
4680         this.hasLayout = true;
4681         delete this.forceLayout;
4682     },
4683
4684     onLayout : Ext.emptyFn,
4685
4686     // private
4687     shouldBufferLayout: function(){
4688         /*
4689          * Returns true if the container should buffer a layout.
4690          * This is true only if the container has previously been laid out
4691          * and has a parent container that is pending a layout.
4692          */
4693         var hl = this.hasLayout;
4694         if(this.ownerCt){
4695             // Only ever buffer if we've laid out the first time and we have one pending.
4696             return hl ? !this.hasLayoutPending() : false;
4697         }
4698         // Never buffer initial layout
4699         return hl;
4700     },
4701
4702     // private
4703     hasLayoutPending: function(){
4704         // Traverse hierarchy to see if any parent container has a pending layout.
4705         var pending = false;
4706         this.ownerCt.bubble(function(c){
4707             if(c.layoutPending){
4708                 pending = true;
4709                 return false;
4710             }
4711         });
4712         return pending;
4713     },
4714
4715     onShow : function(){
4716         // removes css classes that were added to hide
4717         Ext.Container.superclass.onShow.call(this);
4718         // If we were sized during the time we were hidden, layout.
4719         if(Ext.isDefined(this.deferLayout)){
4720             delete this.deferLayout;
4721             this.doLayout(true);
4722         }
4723     },
4724
4725     /**
4726      * Returns the layout currently in use by the container.  If the container does not currently have a layout
4727      * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout.
4728      * @return {ContainerLayout} layout The container's layout
4729      */
4730     getLayout : function(){
4731         if(!this.layout){
4732             var layout = new Ext.layout.AutoLayout(this.layoutConfig);
4733             this.setLayout(layout);
4734         }
4735         return this.layout;
4736     },
4737
4738     // private
4739     beforeDestroy : function(){
4740         var c;
4741         if(this.items){
4742             while(c = this.items.first()){
4743                 this.doRemove(c, true);
4744             }
4745         }
4746         if(this.monitorResize){
4747             Ext.EventManager.removeResizeListener(this.doLayout, this);
4748         }
4749         Ext.destroy(this.layout);
4750         Ext.Container.superclass.beforeDestroy.call(this);
4751     },
4752
4753     /**
4754      * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of
4755      * function call will be the scope provided or the current component. The arguments to the function
4756      * will be the args provided or the current component. If the function returns false at any point,
4757      * the bubble is stopped.
4758      * @param {Function} fn The function to call
4759      * @param {Object} scope (optional) The scope of the function (defaults to current node)
4760      * @param {Array} args (optional) The args to call the function with (default to passing the current component)
4761      * @return {Ext.Container} this
4762      */
4763     bubble : function(fn, scope, args){
4764         var p = this;
4765         while(p){
4766             if(fn.apply(scope || p, args || [p]) === false){
4767                 break;
4768             }
4769             p = p.ownerCt;
4770         }
4771         return this;
4772     },
4773
4774     /**
4775      * Cascades down the component/container heirarchy from this component (called first), calling the specified function with
4776      * each component. The scope (<i>this</i>) of
4777      * function call will be the scope provided or the current component. The arguments to the function
4778      * will be the args provided or the current component. If the function returns false at any point,
4779      * the cascade is stopped on that branch.
4780      * @param {Function} fn The function to call
4781      * @param {Object} scope (optional) The scope of the function (defaults to current component)
4782      * @param {Array} args (optional) The args to call the function with (defaults to passing the current component)
4783      * @return {Ext.Container} this
4784      */
4785     cascade : function(fn, scope, args){
4786         if(fn.apply(scope || this, args || [this]) !== false){
4787             if(this.items){
4788                 var cs = this.items.items;
4789                 for(var i = 0, len = cs.length; i < len; i++){
4790                     if(cs[i].cascade){
4791                         cs[i].cascade(fn, scope, args);
4792                     }else{
4793                         fn.apply(scope || cs[i], args || [cs[i]]);
4794                     }
4795                 }
4796             }
4797         }
4798         return this;
4799     },
4800
4801     /**
4802      * Find a component under this container at any level by id
4803      * @param {String} id
4804      * @return Ext.Component
4805      */
4806     findById : function(id){
4807         var m, ct = this;
4808         this.cascade(function(c){
4809             if(ct != c && c.id === id){
4810                 m = c;
4811                 return false;
4812             }
4813         });
4814         return m || null;
4815     },
4816
4817     /**
4818      * Find a component under this container at any level by xtype or class
4819      * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
4820      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
4821      * the default), or true to check whether this Component is directly of the specified xtype.
4822      * @return {Array} Array of Ext.Components
4823      */
4824     findByType : function(xtype, shallow){
4825         return this.findBy(function(c){
4826             return c.isXType(xtype, shallow);
4827         });
4828     },
4829
4830     /**
4831      * Find a component under this container at any level by property
4832      * @param {String} prop
4833      * @param {String} value
4834      * @return {Array} Array of Ext.Components
4835      */
4836     find : function(prop, value){
4837         return this.findBy(function(c){
4838             return c[prop] === value;
4839         });
4840     },
4841
4842     /**
4843      * Find a component under this container at any level by a custom function. If the passed function returns
4844      * true, the component will be included in the results. The passed function is called with the arguments (component, this container).
4845      * @param {Function} fn The function to call
4846      * @param {Object} scope (optional)
4847      * @return {Array} Array of Ext.Components
4848      */
4849     findBy : function(fn, scope){
4850         var m = [], ct = this;
4851         this.cascade(function(c){
4852             if(ct != c && fn.call(scope || c, c, ct) === true){
4853                 m.push(c);
4854             }
4855         });
4856         return m;
4857     },
4858
4859     /**
4860      * Get a component contained by this container (alias for items.get(key))
4861      * @param {String/Number} key The index or id of the component
4862      * @return {Ext.Component} Ext.Component
4863      */
4864     get : function(key){
4865         return this.items.get(key);
4866     }
4867 });
4868
4869 Ext.Container.LAYOUTS = {};
4870 Ext.reg('container', Ext.Container);
4871 /**
4872  * @class Ext.layout.ContainerLayout
4873  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
4874  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
4875  */
4876 Ext.layout.ContainerLayout = Ext.extend(Object, {
4877     /**
4878      * @cfg {String} extraCls
4879      * <p>An optional extra CSS class that will be added to the container. This can be useful for adding
4880      * customized styles to the container or any of its children using standard CSS rules. See
4881      * {@link Ext.Component}.{@link Ext.Component#ctCls ctCls} also.</p>
4882      * <p><b>Note</b>: <tt>extraCls</tt> defaults to <tt>''</tt> except for the following classes
4883      * which assign a value by default:
4884      * <div class="mdetail-params"><ul>
4885      * <li>{@link Ext.layout.AbsoluteLayout Absolute Layout} : <tt>'x-abs-layout-item'</tt></li>
4886      * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-item'</tt></li>
4887      * <li>{@link Ext.layout.ColumnLayout Column Layout} : <tt>'x-column'</tt></li>
4888      * </ul></div>
4889      * To configure the above Classes with an extra CSS class append to the default.  For example,
4890      * for ColumnLayout:<pre><code>
4891      * extraCls: 'x-column custom-class'
4892      * </code></pre>
4893      * </p>
4894      */
4895     /**
4896      * @cfg {Boolean} renderHidden
4897      * True to hide each contained item on render (defaults to false).
4898      */
4899
4900     /**
4901      * A reference to the {@link Ext.Component} that is active.  For example, <pre><code>
4902      * if(myPanel.layout.activeItem.id == 'item-1') { ... }
4903      * </code></pre>
4904      * <tt>activeItem</tt> only applies to layout styles that can display items one at a time
4905      * (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout}
4906      * and {@link Ext.layout.FitLayout}).  Read-only.  Related to {@link Ext.Container#activeItem}.
4907      * @type {Ext.Component}
4908      * @property activeItem
4909      */
4910
4911     // private
4912     monitorResize:false,
4913     // private
4914     activeItem : null,
4915
4916     constructor : function(config){
4917         this.id = Ext.id(null, 'ext-layout-');
4918         Ext.apply(this, config);
4919     },
4920
4921     type: 'container',
4922
4923     /* Workaround for how IE measures autoWidth elements.  It prefers bottom-up measurements
4924       whereas other browser prefer top-down.  We will hide all target child elements before we measure and
4925       put them back to get an accurate measurement.
4926     */
4927     IEMeasureHack : function(target, viewFlag) {
4928         var tChildren = target.dom.childNodes, tLen = tChildren.length, c, d = [], e, i, ret;
4929         for (i = 0 ; i < tLen ; i++) {
4930             c = tChildren[i];
4931             e = Ext.get(c);
4932             if (e) {
4933                 d[i] = e.getStyle('display');
4934                 e.setStyle({display: 'none'});
4935             }
4936         }
4937         ret = target ? target.getViewSize(viewFlag) : {};
4938         for (i = 0 ; i < tLen ; i++) {
4939             c = tChildren[i];
4940             e = Ext.get(c);
4941             if (e) {
4942                 e.setStyle({display: d[i]});
4943             }
4944         }
4945         return ret;
4946     },
4947
4948     // Placeholder for the derived layouts
4949     getLayoutTargetSize : Ext.EmptyFn,
4950
4951     // private
4952     layout : function(){
4953         var ct = this.container, target = ct.getLayoutTarget();
4954         if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
4955             target.addClass(this.targetCls);
4956         }
4957         this.onLayout(ct, target);
4958         ct.fireEvent('afterlayout', ct, this);
4959     },
4960
4961     // private
4962     onLayout : function(ct, target){
4963         this.renderAll(ct, target);
4964     },
4965
4966     // private
4967     isValidParent : function(c, target){
4968         return target && c.getPositionEl().dom.parentNode == (target.dom || target);
4969     },
4970
4971     // private
4972     renderAll : function(ct, target){
4973         var items = ct.items.items, i, c, len = items.length;
4974         for(i = 0; i < len; i++) {
4975             c = items[i];
4976             if(c && (!c.rendered || !this.isValidParent(c, target))){
4977                 this.renderItem(c, i, target);
4978             }
4979         }
4980     },
4981
4982     /**
4983      * @private
4984      * Renders the given Component into the target Element. If the Component is already rendered,
4985      * it is moved to the provided target instead.
4986      * @param {Ext.Component} c The Component to render
4987      * @param {Number} position The position within the target to render the item to
4988      * @param {Ext.Element} target The target Element
4989      */
4990     renderItem : function(c, position, target){
4991         if (c) {
4992             if (!c.rendered) {
4993                 c.render(target, position);
4994                 this.configureItem(c, position);
4995             } else if (!this.isValidParent(c, target)) {
4996                 if (Ext.isNumber(position)) {
4997                     position = target.dom.childNodes[position];
4998                 }
4999                 
5000                 target.dom.insertBefore(c.getPositionEl().dom, position || null);
5001                 c.container = target;
5002                 this.configureItem(c, position);
5003             }
5004         }
5005     },
5006
5007     // private.
5008     // Get all rendered items to lay out.
5009     getRenderedItems: function(ct){
5010         var t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = [];
5011         for (i = 0; i < len; i++) {
5012             if((c = cti[i]).rendered && this.isValidParent(c, t)){
5013                 items.push(c);
5014             }
5015         };
5016         return items;
5017     },
5018
5019     /**
5020      * @private
5021      * Applies extraCls and hides the item if renderHidden is true
5022      */
5023     configureItem: function(c, position){
5024         if (this.extraCls) {
5025             var t = c.getPositionEl ? c.getPositionEl() : c;
5026             t.addClass(this.extraCls);
5027         }
5028         
5029         // If we are forcing a layout, do so *before* we hide so elements have height/width
5030         if (c.doLayout && this.forceLayout) {
5031             c.doLayout();
5032         }
5033         if (this.renderHidden && c != this.activeItem) {
5034             c.hide();
5035         }
5036     },
5037
5038     onRemove: function(c){
5039         if(this.activeItem == c){
5040             delete this.activeItem;
5041         }
5042         if(c.rendered && this.extraCls){
5043             var t = c.getPositionEl ? c.getPositionEl() : c;
5044             t.removeClass(this.extraCls);
5045         }
5046     },
5047
5048     afterRemove: function(c){
5049         if(c.removeRestore){
5050             c.removeMode = 'container';
5051             delete c.removeRestore;
5052         }
5053     },
5054
5055     // private
5056     onResize: function(){
5057         var ct = this.container,
5058             b;
5059         if(ct.collapsed){
5060             return;
5061         }
5062         if(b = ct.bufferResize && ct.shouldBufferLayout()){
5063             if(!this.resizeTask){
5064                 this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
5065                 this.resizeBuffer = Ext.isNumber(b) ? b : 50;
5066             }
5067             ct.layoutPending = true;
5068             this.resizeTask.delay(this.resizeBuffer);
5069         }else{
5070             this.runLayout();
5071         }
5072     },
5073
5074     runLayout: function(){
5075         var ct = this.container;
5076         this.layout();
5077         ct.onLayout();
5078         delete ct.layoutPending;
5079     },
5080
5081     // private
5082     setContainer : function(ct){
5083         /**
5084          * This monitorResize flag will be renamed soon as to avoid confusion
5085          * with the Container version which hooks onWindowResize to doLayout
5086          *
5087          * monitorResize flag in this context attaches the resize event between
5088          * a container and it's layout
5089          */
5090         if(this.monitorResize && ct != this.container){
5091             var old = this.container;
5092             if(old){
5093                 old.un(old.resizeEvent, this.onResize, this);
5094             }
5095             if(ct){
5096                 ct.on(ct.resizeEvent, this.onResize, this);
5097             }
5098         }
5099         this.container = ct;
5100     },
5101
5102     /**
5103      * Parses a number or string representing margin sizes into an object. Supports CSS-style margin declarations
5104      * (e.g. 10, "10", "10 10", "10 10 10" and "10 10 10 10" are all valid options and would return the same result)
5105      * @param {Number|String} v The encoded margins
5106      * @return {Object} An object with margin sizes for top, right, bottom and left
5107      */
5108     parseMargins : function(v){
5109         if (Ext.isNumber(v)) {
5110             v = v.toString();
5111         }
5112         var ms  = v.split(' '),
5113             len = ms.length;
5114             
5115         if (len == 1) {
5116             ms[1] = ms[2] = ms[3] = ms[0];
5117         } else if(len == 2) {
5118             ms[2] = ms[0];
5119             ms[3] = ms[1];
5120         } else if(len == 3) {
5121             ms[3] = ms[1];
5122         }
5123         
5124         return {
5125             top   :parseInt(ms[0], 10) || 0,
5126             right :parseInt(ms[1], 10) || 0,
5127             bottom:parseInt(ms[2], 10) || 0,
5128             left  :parseInt(ms[3], 10) || 0
5129         };
5130     },
5131
5132     /**
5133      * The {@link Ext.Template Ext.Template} used by Field rendering layout classes (such as
5134      * {@link Ext.layout.FormLayout}) to create the DOM structure of a fully wrapped,
5135      * labeled and styled form Field. A default Template is supplied, but this may be
5136      * overriden to create custom field structures. The template processes values returned from
5137      * {@link Ext.layout.FormLayout#getTemplateArgs}.
5138      * @property fieldTpl
5139      * @type Ext.Template
5140      */
5141     fieldTpl: (function() {
5142         var t = new Ext.Template(
5143             '<div class="x-form-item {itemCls}" tabIndex="-1">',
5144                 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
5145                 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
5146                 '</div><div class="{clearCls}"></div>',
5147             '</div>'
5148         );
5149         t.disableFormats = true;
5150         return t.compile();
5151     })(),
5152
5153     /*
5154      * Destroys this layout. This is a template method that is empty by default, but should be implemented
5155      * by subclasses that require explicit destruction to purge event handlers or remove DOM nodes.
5156      * @protected
5157      */
5158     destroy : function(){
5159         // Stop any buffered layout tasks
5160         if(this.resizeTask && this.resizeTask.cancel){
5161             this.resizeTask.cancel();
5162         }
5163         if(!Ext.isEmpty(this.targetCls)){
5164             var target = this.container.getLayoutTarget();
5165             if(target){
5166                 target.removeClass(this.targetCls);
5167             }
5168         }
5169     }
5170 });/**
5171  * @class Ext.layout.AutoLayout
5172  * <p>The AutoLayout is the default layout manager delegated by {@link Ext.Container} to
5173  * render any child Components when no <tt>{@link Ext.Container#layout layout}</tt> is configured into
5174  * a {@link Ext.Container Container}.</tt>.  AutoLayout provides only a passthrough of any layout calls
5175  * to any child containers.</p>
5176  */
5177 Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
5178     type: 'auto',
5179
5180     monitorResize: true,
5181
5182     onLayout : function(ct, target){
5183         Ext.layout.AutoLayout.superclass.onLayout.call(this, ct, target);
5184         var cs = this.getRenderedItems(ct), len = cs.length, i, c;
5185         for(i = 0; i < len; i++){
5186             c = cs[i];
5187             if (c.doLayout){
5188                 // Shallow layout children
5189                 c.doLayout(true);
5190             }
5191         }
5192     }
5193 });
5194
5195 Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
5196 /**
5197  * @class Ext.layout.FitLayout
5198  * @extends Ext.layout.ContainerLayout
5199  * <p>This is a base class for layouts that contain <b>a single item</b> that automatically expands to fill the layout's
5200  * container.  This class is intended to be extended or created via the <tt>layout:'fit'</tt> {@link Ext.Container#layout}
5201  * config, and should generally not need to be created directly via the new keyword.</p>
5202  * <p>FitLayout does not have any direct config options (other than inherited ones).  To fit a panel to a container
5203  * using FitLayout, simply set layout:'fit' on the container and add a single panel to it.  If the container has
5204  * multiple panels, only the first one will be displayed.  Example usage:</p>
5205  * <pre><code>
5206 var p = new Ext.Panel({
5207     title: 'Fit Layout',
5208     layout:'fit',
5209     items: {
5210         title: 'Inner Panel',
5211         html: '&lt;p&gt;This is the inner panel content&lt;/p&gt;',
5212         border: false
5213     }
5214 });
5215 </code></pre>
5216  */
5217 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
5218     // private
5219     monitorResize:true,
5220
5221     type: 'fit',
5222
5223     getLayoutTargetSize : function() {
5224         var target = this.container.getLayoutTarget();
5225         if (!target) {
5226             return {};
5227         }
5228         // Style Sized (scrollbars not included)
5229         return target.getStyleSize();
5230     },
5231
5232     // private
5233     onLayout : function(ct, target){
5234         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
5235         if(!ct.collapsed){
5236             this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());
5237         }
5238     },
5239
5240     // private
5241     setItemSize : function(item, size){
5242         if(item && size.height > 0){ // display none?
5243             item.setSize(size);
5244         }
5245     }
5246 });
5247 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;/**
5248  * @class Ext.layout.CardLayout
5249  * @extends Ext.layout.FitLayout
5250  * <p>This layout manages multiple child Components, each fitted to the Container, where only a single child Component can be
5251  * visible at any given time.  This layout style is most commonly used for wizards, tab implementations, etc.
5252  * This class is intended to be extended or created via the layout:'card' {@link Ext.Container#layout} config,
5253  * and should generally not need to be created directly via the new keyword.</p>
5254  * <p>The CardLayout's focal method is {@link #setActiveItem}.  Since only one panel is displayed at a time,
5255  * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of
5256  * the next panel to display.  The layout itself does not provide a user interface for handling this navigation,
5257  * so that functionality must be provided by the developer.</p>
5258  * <p>In the following example, a simplistic wizard setup is demonstrated.  A button bar is added
5259  * to the footer of the containing panel to provide navigation buttons.  The buttons will be handled by a
5260  * common navigation routine -- for this example, the implementation of that routine has been ommitted since
5261  * it can be any type of custom logic.  Note that other uses of a CardLayout (like a tab control) would require a
5262  * completely different implementation.  For serious implementations, a better approach would be to extend
5263  * CardLayout to provide the custom functionality needed.  Example usage:</p>
5264  * <pre><code>
5265 var navHandler = function(direction){
5266     // This routine could contain business logic required to manage the navigation steps.
5267     // It would call setActiveItem as needed, manage navigation button state, handle any
5268     // branching logic that might be required, handle alternate actions like cancellation
5269     // or finalization, etc.  A complete wizard implementation could get pretty
5270     // sophisticated depending on the complexity required, and should probably be
5271     // done as a subclass of CardLayout in a real-world implementation.
5272 };
5273
5274 var card = new Ext.Panel({
5275     title: 'Example Wizard',
5276     layout:'card',
5277     activeItem: 0, // make sure the active item is set on the container config!
5278     bodyStyle: 'padding:15px',
5279     defaults: {
5280         // applied to each contained panel
5281         border:false
5282     },
5283     // just an example of one possible navigation scheme, using buttons
5284     bbar: [
5285         {
5286             id: 'move-prev',
5287             text: 'Back',
5288             handler: navHandler.createDelegate(this, [-1]),
5289             disabled: true
5290         },
5291         '->', // greedy spacer so that the buttons are aligned to each side
5292         {
5293             id: 'move-next',
5294             text: 'Next',
5295             handler: navHandler.createDelegate(this, [1])
5296         }
5297     ],
5298     // the panels (or "cards") within the layout
5299     items: [{
5300         id: 'card-0',
5301         html: '&lt;h1&gt;Welcome to the Wizard!&lt;/h1&gt;&lt;p&gt;Step 1 of 3&lt;/p&gt;'
5302     },{
5303         id: 'card-1',
5304         html: '&lt;p&gt;Step 2 of 3&lt;/p&gt;'
5305     },{
5306         id: 'card-2',
5307         html: '&lt;h1&gt;Congratulations!&lt;/h1&gt;&lt;p&gt;Step 3 of 3 - Complete&lt;/p&gt;'
5308     }]
5309 });
5310 </code></pre>
5311  */
5312 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
5313     /**
5314      * @cfg {Boolean} deferredRender
5315      * True to render each contained item at the time it becomes active, false to render all contained items
5316      * as soon as the layout is rendered (defaults to false).  If there is a significant amount of content or
5317      * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to
5318      * true might improve performance.
5319      */
5320     deferredRender : false,
5321
5322     /**
5323      * @cfg {Boolean} layoutOnCardChange
5324      * True to force a layout of the active item when the active card is changed. Defaults to false.
5325      */
5326     layoutOnCardChange : false,
5327
5328     /**
5329      * @cfg {Boolean} renderHidden @hide
5330      */
5331     // private
5332     renderHidden : true,
5333
5334     type: 'card',
5335
5336     /**
5337      * Sets the active (visible) item in the layout.
5338      * @param {String/Number} item The string component id or numeric index of the item to activate
5339      */
5340     setActiveItem : function(item){
5341         var ai = this.activeItem,
5342             ct = this.container;
5343         item = ct.getComponent(item);
5344
5345         // Is this a valid, different card?
5346         if(item && ai != item){
5347
5348             // Changing cards, hide the current one
5349             if(ai){
5350                 ai.hide();
5351                 if (ai.hidden !== true) {
5352                     return false;
5353                 }
5354                 ai.fireEvent('deactivate', ai);
5355             }
5356
5357             var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);
5358
5359             // Change activeItem reference
5360             this.activeItem = item;
5361
5362             // The container is about to get a recursive layout, remove any deferLayout reference
5363             // because it will trigger a redundant layout.
5364             delete item.deferLayout;
5365
5366             // Show the new component
5367             item.show();
5368
5369             this.layout();
5370
5371             if(layout){
5372                 item.doLayout();
5373             }
5374             item.fireEvent('activate', item);
5375         }
5376     },
5377
5378     // private
5379     renderAll : function(ct, target){
5380         if(this.deferredRender){
5381             this.renderItem(this.activeItem, undefined, target);
5382         }else{
5383             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
5384         }
5385     }
5386 });
5387 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;
5388 /**
5389  * @class Ext.layout.AnchorLayout
5390  * @extends Ext.layout.ContainerLayout
5391  * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.
5392  * If the container is resized, all anchored items are automatically rerendered according to their
5393  * <b><tt>{@link #anchor}</tt></b> rules.</p>
5394  * <p>This class is intended to be extended or created via the layout:'anchor' {@link Ext.Container#layout}
5395  * config, and should generally not need to be created directly via the new keyword.</p>
5396  * <p>AnchorLayout does not have any direct config options (other than inherited ones). By default,
5397  * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the
5398  * container using the AnchorLayout can supply an anchoring-specific config property of <b>anchorSize</b>.
5399  * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating
5400  * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring
5401  * logic if necessary.  For example:</p>
5402  * <pre><code>
5403 var viewport = new Ext.Viewport({
5404     layout:'anchor',
5405     anchorSize: {width:800, height:600},
5406     items:[{
5407         title:'Item 1',
5408         html:'Content 1',
5409         width:800,
5410         anchor:'right 20%'
5411     },{
5412         title:'Item 2',
5413         html:'Content 2',
5414         width:300,
5415         anchor:'50% 30%'
5416     },{
5417         title:'Item 3',
5418         html:'Content 3',
5419         width:600,
5420         anchor:'-100 50%'
5421     }]
5422 });
5423  * </code></pre>
5424  */
5425 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
5426     /**
5427      * @cfg {String} anchor
5428      * <p>This configuation option is to be applied to <b>child <tt>items</tt></b> of a container managed by
5429      * this layout (ie. configured with <tt>layout:'anchor'</tt>).</p><br/>
5430      *
5431      * <p>This value is what tells the layout how an item should be anchored to the container. <tt>items</tt>
5432      * added to an AnchorLayout accept an anchoring-specific config property of <b>anchor</b> which is a string
5433      * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').
5434      * The following types of anchor values are supported:<div class="mdetail-params"><ul>
5435      *
5436      * <li><b>Percentage</b> : Any value between 1 and 100, expressed as a percentage.<div class="sub-desc">
5437      * The first anchor is the percentage width that the item should take up within the container, and the
5438      * second is the percentage height.  For example:<pre><code>
5439 // two values specified
5440 anchor: '100% 50%' // render item complete width of the container and
5441                    // 1/2 height of the container
5442 // one value specified
5443 anchor: '100%'     // the width value; the height will default to auto
5444      * </code></pre></div></li>
5445      *
5446      * <li><b>Offsets</b> : Any positive or negative integer value.<div class="sub-desc">
5447      * This is a raw adjustment where the first anchor is the offset from the right edge of the container,
5448      * and the second is the offset from the bottom edge. For example:<pre><code>
5449 // two values specified
5450 anchor: '-50 -100' // render item the complete width of the container
5451                    // minus 50 pixels and
5452                    // the complete height minus 100 pixels.
5453 // one value specified
5454 anchor: '-50'      // anchor value is assumed to be the right offset value
5455                    // bottom offset will default to 0
5456      * </code></pre></div></li>
5457      *
5458      * <li><b>Sides</b> : Valid values are <tt>'right'</tt> (or <tt>'r'</tt>) and <tt>'bottom'</tt>
5459      * (or <tt>'b'</tt>).<div class="sub-desc">
5460      * Either the container must have a fixed size or an anchorSize config value defined at render time in
5461      * order for these to have any effect.</div></li>
5462      *
5463      * <li><b>Mixed</b> : <div class="sub-desc">
5464      * Anchor values can also be mixed as needed.  For example, to render the width offset from the container
5465      * right edge by 50 pixels and 75% of the container's height use:
5466      * <pre><code>
5467 anchor: '-50 75%'
5468      * </code></pre></div></li>
5469      *
5470      *
5471      * </ul></div>
5472      */
5473
5474     // private
5475     monitorResize : true,
5476
5477     type : 'anchor',
5478
5479     /**
5480      * @cfg {String} defaultAnchor
5481      *
5482      * default anchor for all child container items applied if no anchor or specific width is set on the child item.  Defaults to '100%'.
5483      *
5484      */
5485     defaultAnchor : '100%',
5486
5487     parseAnchorRE : /^(r|right|b|bottom)$/i,
5488
5489     getLayoutTargetSize : function() {
5490         var target = this.container.getLayoutTarget();
5491         if (!target) {
5492             return {};
5493         }
5494         // Style Sized (scrollbars not included)
5495         return target.getStyleSize();
5496     },
5497
5498     // private
5499     onLayout : function(ct, target){
5500         Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
5501         var size = this.getLayoutTargetSize();
5502
5503         var w = size.width, h = size.height;
5504
5505         if(w < 20 && h < 20){
5506             return;
5507         }
5508
5509         // find the container anchoring size
5510         var aw, ah;
5511         if(ct.anchorSize){
5512             if(typeof ct.anchorSize == 'number'){
5513                 aw = ct.anchorSize;
5514             }else{
5515                 aw = ct.anchorSize.width;
5516                 ah = ct.anchorSize.height;
5517             }
5518         }else{
5519             aw = ct.initialConfig.width;
5520             ah = ct.initialConfig.height;
5521         }
5522
5523         var cs = this.getRenderedItems(ct), len = cs.length, i, c, a, cw, ch, el, vs, boxes = [];
5524         for(i = 0; i < len; i++){
5525             c = cs[i];
5526             el = c.getPositionEl();
5527
5528             // If a child container item has no anchor and no specific width, set the child to the default anchor size
5529             if (!c.anchor && c.items && !Ext.isNumber(c.width) && !(Ext.isIE6 && Ext.isStrict)){
5530                 c.anchor = this.defaultAnchor;
5531             }
5532
5533             if(c.anchor){
5534                 a = c.anchorSpec;
5535                 if(!a){ // cache all anchor values
5536                     vs = c.anchor.split(' ');
5537                     c.anchorSpec = a = {
5538                         right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
5539                         bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
5540                     };
5541                 }
5542                 cw = a.right ? this.adjustWidthAnchor(a.right(w) - el.getMargins('lr'), c) : undefined;
5543                 ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h) - el.getMargins('tb'), c) : undefined;
5544
5545                 if(cw || ch){
5546                     boxes.push({
5547                         comp: c,
5548                         width: cw || undefined,
5549                         height: ch || undefined
5550                     });
5551                 }
5552             }
5553         }
5554         for (i = 0, len = boxes.length; i < len; i++) {
5555             c = boxes[i];
5556             c.comp.setSize(c.width, c.height);
5557         }
5558     },
5559
5560     // private
5561     parseAnchor : function(a, start, cstart){
5562         if(a && a != 'none'){
5563             var last;
5564             // standard anchor
5565             if(this.parseAnchorRE.test(a)){
5566                 var diff = cstart - start;
5567                 return function(v){
5568                     if(v !== last){
5569                         last = v;
5570                         return v - diff;
5571                     }
5572                 }
5573             // percentage
5574             }else if(a.indexOf('%') != -1){
5575                 var ratio = parseFloat(a.replace('%', ''))*.01;
5576                 return function(v){
5577                     if(v !== last){
5578                         last = v;
5579                         return Math.floor(v*ratio);
5580                     }
5581                 }
5582             // simple offset adjustment
5583             }else{
5584                 a = parseInt(a, 10);
5585                 if(!isNaN(a)){
5586                     return function(v){
5587                         if(v !== last){
5588                             last = v;
5589                             return v + a;
5590                         }
5591                     }
5592                 }
5593             }
5594         }
5595         return false;
5596     },
5597
5598     // private
5599     adjustWidthAnchor : function(value, comp){
5600         return value;
5601     },
5602
5603     // private
5604     adjustHeightAnchor : function(value, comp){
5605         return value;
5606     }
5607
5608     /**
5609      * @property activeItem
5610      * @hide
5611      */
5612 });
5613 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
5614 /**
5615  * @class Ext.layout.ColumnLayout
5616  * @extends Ext.layout.ContainerLayout
5617  * <p>This is the layout style of choice for creating structural layouts in a multi-column format where the width of
5618  * each column can be specified as a percentage or fixed width, but the height is allowed to vary based on the content.
5619  * This class is intended to be extended or created via the layout:'column' {@link Ext.Container#layout} config,
5620  * and should generally not need to be created directly via the new keyword.</p>
5621  * <p>ColumnLayout does not have any direct config options (other than inherited ones), but it does support a
5622  * specific config property of <b><tt>columnWidth</tt></b> that can be included in the config of any panel added to it.  The
5623  * layout will use the columnWidth (if present) or width of each panel during layout to determine how to size each panel.
5624  * If width or columnWidth is not specified for a given panel, its width will default to the panel's width (or auto).</p>
5625  * <p>The width property is always evaluated as pixels, and must be a number greater than or equal to 1.
5626  * The columnWidth property is always evaluated as a percentage, and must be a decimal value greater than 0 and
5627  * less than 1 (e.g., .25).</p>
5628  * <p>The basic rules for specifying column widths are pretty simple.  The logic makes two passes through the
5629  * set of contained panels.  During the first layout pass, all panels that either have a fixed width or none
5630  * specified (auto) are skipped, but their widths are subtracted from the overall container width.  During the second
5631  * pass, all panels with columnWidths are assigned pixel widths in proportion to their percentages based on
5632  * the total <b>remaining</b> container width.  In other words, percentage width panels are designed to fill the space
5633  * left over by all the fixed-width and/or auto-width panels.  Because of this, while you can specify any number of columns
5634  * with different percentages, the columnWidths must always add up to 1 (or 100%) when added together, otherwise your
5635  * layout may not render as expected.  Example usage:</p>
5636  * <pre><code>
5637 // All columns are percentages -- they must add up to 1
5638 var p = new Ext.Panel({
5639     title: 'Column Layout - Percentage Only',
5640     layout:'column',
5641     items: [{
5642         title: 'Column 1',
5643         columnWidth: .25
5644     },{
5645         title: 'Column 2',
5646         columnWidth: .6
5647     },{
5648         title: 'Column 3',
5649         columnWidth: .15
5650     }]
5651 });
5652
5653 // Mix of width and columnWidth -- all columnWidth values must add up
5654 // to 1. The first column will take up exactly 120px, and the last two
5655 // columns will fill the remaining container width.
5656 var p = new Ext.Panel({
5657     title: 'Column Layout - Mixed',
5658     layout:'column',
5659     items: [{
5660         title: 'Column 1',
5661         width: 120
5662     },{
5663         title: 'Column 2',
5664         columnWidth: .8
5665     },{
5666         title: 'Column 3',
5667         columnWidth: .2
5668     }]
5669 });
5670 </code></pre>
5671  */
5672 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
5673     // private
5674     monitorResize:true,
5675
5676     type: 'column',
5677
5678     extraCls: 'x-column',
5679
5680     scrollOffset : 0,
5681
5682     // private
5683
5684     targetCls: 'x-column-layout-ct',
5685
5686     isValidParent : function(c, target){
5687         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
5688     },
5689
5690     getLayoutTargetSize : function() {
5691         var target = this.container.getLayoutTarget(), ret;
5692         if (target) {
5693             ret = target.getViewSize();
5694
5695             // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
5696             // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
5697             // with getViewSize
5698             if (Ext.isIE && Ext.isStrict && ret.width == 0){
5699                 ret =  target.getStyleSize();
5700             }
5701
5702             ret.width -= target.getPadding('lr');
5703             ret.height -= target.getPadding('tb');
5704         }
5705         return ret;
5706     },
5707
5708     renderAll : function(ct, target) {
5709         if(!this.innerCt){
5710             // the innerCt prevents wrapping and shuffling while
5711             // the container is resizing
5712             this.innerCt = target.createChild({cls:'x-column-inner'});
5713             this.innerCt.createChild({cls:'x-clear'});
5714         }
5715         Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);
5716     },
5717
5718     // private
5719     onLayout : function(ct, target){
5720         var cs = ct.items.items,
5721             len = cs.length,
5722             c,
5723             i,
5724             m,
5725             margins = [];
5726
5727         this.renderAll(ct, target);
5728
5729         var size = this.getLayoutTargetSize();
5730
5731         if(size.width < 1 && size.height < 1){ // display none?
5732             return;
5733         }
5734
5735         var w = size.width - this.scrollOffset,
5736             h = size.height,
5737             pw = w;
5738
5739         this.innerCt.setWidth(w);
5740
5741         // some columns can be percentages while others are fixed
5742         // so we need to make 2 passes
5743
5744         for(i = 0; i < len; i++){
5745             c = cs[i];
5746             m = c.getPositionEl().getMargins('lr');
5747             margins[i] = m;
5748             if(!c.columnWidth){
5749                 pw -= (c.getWidth() + m);
5750             }
5751         }
5752
5753         pw = pw < 0 ? 0 : pw;
5754
5755         for(i = 0; i < len; i++){
5756             c = cs[i];
5757             m = margins[i];
5758             if(c.columnWidth){
5759                 c.setSize(Math.floor(c.columnWidth * pw) - m);
5760             }
5761         }
5762
5763         // Browsers differ as to when they account for scrollbars.  We need to re-measure to see if the scrollbar
5764         // spaces were accounted for properly.  If not, re-layout.
5765         if (Ext.isIE) {
5766             if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
5767                 var ts = this.getLayoutTargetSize();
5768                 if (ts.width != size.width){
5769                     this.adjustmentPass = true;
5770                     this.onLayout(ct, target);
5771                 }
5772             }
5773         }
5774         delete this.adjustmentPass;
5775     }
5776
5777     /**
5778      * @property activeItem
5779      * @hide
5780      */
5781 });
5782
5783 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;
5784 /**
5785  * @class Ext.layout.BorderLayout
5786  * @extends Ext.layout.ContainerLayout
5787  * <p>This is a multi-pane, application-oriented UI layout style that supports multiple
5788  * nested panels, automatic {@link Ext.layout.BorderLayout.Region#split split} bars between
5789  * {@link Ext.layout.BorderLayout.Region#BorderLayout.Region regions} and built-in
5790  * {@link Ext.layout.BorderLayout.Region#collapsible expanding and collapsing} of regions.</p>
5791  * <p>This class is intended to be extended or created via the <tt>layout:'border'</tt>
5792  * {@link Ext.Container#layout} config, and should generally not need to be created directly
5793  * via the new keyword.</p>
5794  * <p>BorderLayout does not have any direct config options (other than inherited ones).
5795  * All configuration options available for customizing the BorderLayout are at the
5796  * {@link Ext.layout.BorderLayout.Region} and {@link Ext.layout.BorderLayout.SplitRegion}
5797  * levels.</p>
5798  * <p>Example usage:</p>
5799  * <pre><code>
5800 var myBorderPanel = new Ext.Panel({
5801     {@link Ext.Component#renderTo renderTo}: document.body,
5802     {@link Ext.BoxComponent#width width}: 700,
5803     {@link Ext.BoxComponent#height height}: 500,
5804     {@link Ext.Panel#title title}: 'Border Layout',
5805     {@link Ext.Container#layout layout}: 'border',
5806     {@link Ext.Container#items items}: [{
5807         {@link Ext.Panel#title title}: 'South Region is resizable',
5808         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south',     // position for region
5809         {@link Ext.BoxComponent#height height}: 100,
5810         {@link Ext.layout.BorderLayout.Region#split split}: true,         // enable resizing
5811         {@link Ext.SplitBar#minSize minSize}: 75,         // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50}
5812         {@link Ext.SplitBar#maxSize maxSize}: 150,
5813         {@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5'
5814     },{
5815         // xtype: 'panel' implied by default
5816         {@link Ext.Panel#title title}: 'West Region is collapsible',
5817         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}:'west',
5818         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 0 0 5',
5819         {@link Ext.BoxComponent#width width}: 200,
5820         {@link Ext.layout.BorderLayout.Region#collapsible collapsible}: true,   // make collapsible
5821         {@link Ext.layout.BorderLayout.Region#cmargins cmargins}: '5 5 0 5', // adjust top margin when collapsed
5822         {@link Ext.Component#id id}: 'west-region-container',
5823         {@link Ext.Container#layout layout}: 'fit',
5824         {@link Ext.Panel#unstyled unstyled}: true
5825     },{
5826         {@link Ext.Panel#title title}: 'Center Region',
5827         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'center',     // center region is required, no width/height specified
5828         {@link Ext.Component#xtype xtype}: 'container',
5829         {@link Ext.Container#layout layout}: 'fit',
5830         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 5 0 0'
5831     }]
5832 });
5833 </code></pre>
5834  * <p><b><u>Notes</u></b>:</p><div class="mdetail-params"><ul>
5835  * <li>Any container using the BorderLayout <b>must</b> have a child item with <tt>region:'center'</tt>.
5836  * The child item in the center region will always be resized to fill the remaining space not used by
5837  * the other regions in the layout.</li>
5838  * <li>Any child items with a region of <tt>west</tt> or <tt>east</tt> must have <tt>width</tt> defined
5839  * (an integer representing the number of pixels that the region should take up).</li>
5840  * <li>Any child items with a region of <tt>north</tt> or <tt>south</tt> must have <tt>height</tt> defined.</li>
5841  * <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
5842  * Components within a BorderLayout, have them wrapped by an additional Container which is directly
5843  * managed by the BorderLayout.  If the region is to be collapsible, the Container used directly
5844  * by the BorderLayout manager should be a Panel.  In the following example a Container (an Ext.Panel)
5845  * is added to the west region:
5846  * <div style="margin-left:16px"><pre><code>
5847 wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container');
5848 wrc.{@link Ext.Panel#removeAll removeAll}();
5849 wrc.{@link Ext.Container#add add}({
5850     title: 'Added Panel',
5851     html: 'Some content'
5852 });
5853 wrc.{@link Ext.Container#doLayout doLayout}();
5854  * </code></pre></div>
5855  * </li>
5856  * <li> To reference a {@link Ext.layout.BorderLayout.Region Region}:
5857  * <div style="margin-left:16px"><pre><code>
5858 wr = myBorderPanel.layout.west;
5859  * </code></pre></div>
5860  * </li>
5861  * </ul></div>
5862  */
5863 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
5864     // private
5865     monitorResize:true,
5866     // private
5867     rendered : false,
5868
5869     type: 'border',
5870
5871     targetCls: 'x-border-layout-ct',
5872
5873     getLayoutTargetSize : function() {
5874         var target = this.container.getLayoutTarget();
5875         return target ? target.getViewSize() : {};
5876     },
5877
5878     // private
5879     onLayout : function(ct, target){
5880         var collapsed, i, c, pos, items = ct.items.items, len = items.length;
5881         if(!this.rendered){
5882             collapsed = [];
5883             for(i = 0; i < len; i++) {
5884                 c = items[i];
5885                 pos = c.region;
5886                 if(c.collapsed){
5887                     collapsed.push(c);
5888                 }
5889                 c.collapsed = false;
5890                 if(!c.rendered){
5891                     c.render(target, i);
5892                     c.getPositionEl().addClass('x-border-panel');
5893                 }
5894                 this[pos] = pos != 'center' && c.split ?
5895                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
5896                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
5897                 this[pos].render(target, c);
5898             }
5899             this.rendered = true;
5900         }
5901
5902         var size = this.getLayoutTargetSize();
5903         if(size.width < 20 || size.height < 20){ // display none?
5904             if(collapsed){
5905                 this.restoreCollapsed = collapsed;
5906             }
5907             return;
5908         }else if(this.restoreCollapsed){
5909             collapsed = this.restoreCollapsed;
5910             delete this.restoreCollapsed;
5911         }
5912
5913         var w = size.width, h = size.height,
5914             centerW = w, centerH = h, centerY = 0, centerX = 0,
5915             n = this.north, s = this.south, west = this.west, e = this.east, c = this.center,
5916             b, m, totalWidth, totalHeight;
5917         if(!c && Ext.layout.BorderLayout.WARN !== false){
5918             throw 'No center region defined in BorderLayout ' + ct.id;
5919         }
5920
5921         if(n && n.isVisible()){
5922             b = n.getSize();
5923             m = n.getMargins();
5924             b.width = w - (m.left+m.right);
5925             b.x = m.left;
5926             b.y = m.top;
5927             centerY = b.height + b.y + m.bottom;
5928             centerH -= centerY;
5929             n.applyLayout(b);
5930         }
5931         if(s && s.isVisible()){
5932             b = s.getSize();
5933             m = s.getMargins();
5934             b.width = w - (m.left+m.right);
5935             b.x = m.left;
5936             totalHeight = (b.height + m.top + m.bottom);
5937             b.y = h - totalHeight + m.top;
5938             centerH -= totalHeight;
5939             s.applyLayout(b);
5940         }
5941         if(west && west.isVisible()){
5942             b = west.getSize();
5943             m = west.getMargins();
5944             b.height = centerH - (m.top+m.bottom);
5945             b.x = m.left;
5946             b.y = centerY + m.top;
5947             totalWidth = (b.width + m.left + m.right);
5948             centerX += totalWidth;
5949             centerW -= totalWidth;
5950             west.applyLayout(b);
5951         }
5952         if(e && e.isVisible()){
5953             b = e.getSize();
5954             m = e.getMargins();
5955             b.height = centerH - (m.top+m.bottom);
5956             totalWidth = (b.width + m.left + m.right);
5957             b.x = w - totalWidth + m.left;
5958             b.y = centerY + m.top;
5959             centerW -= totalWidth;
5960             e.applyLayout(b);
5961         }
5962         if(c){
5963             m = c.getMargins();
5964             var centerBox = {
5965                 x: centerX + m.left,
5966                 y: centerY + m.top,
5967                 width: centerW - (m.left+m.right),
5968                 height: centerH - (m.top+m.bottom)
5969             };
5970             c.applyLayout(centerBox);
5971         }
5972         if(collapsed){
5973             for(i = 0, len = collapsed.length; i < len; i++){
5974                 collapsed[i].collapse(false);
5975             }
5976         }
5977         if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue
5978             target.repaint();
5979         }
5980         // Putting a border layout into an overflowed container is NOT correct and will make a second layout pass necessary.
5981         if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
5982             var ts = this.getLayoutTargetSize();
5983             if (ts.width != size.width || ts.height != size.height){
5984                 this.adjustmentPass = true;
5985                 this.onLayout(ct, target);
5986             }
5987         }
5988         delete this.adjustmentPass;
5989     },
5990
5991     destroy: function() {
5992         var r = ['north', 'south', 'east', 'west'], i, region;
5993         for (i = 0; i < r.length; i++) {
5994             region = this[r[i]];
5995             if(region){
5996                 if(region.destroy){
5997                     region.destroy();
5998                 }else if (region.split){
5999                     region.split.destroy(true);
6000                 }
6001             }
6002         }
6003         Ext.layout.BorderLayout.superclass.destroy.call(this);
6004     }
6005
6006     /**
6007      * @property activeItem
6008      * @hide
6009      */
6010 });
6011
6012 /**
6013  * @class Ext.layout.BorderLayout.Region
6014  * <p>This is a region of a {@link Ext.layout.BorderLayout BorderLayout} that acts as a subcontainer
6015  * within the layout.  Each region has its own {@link Ext.layout.ContainerLayout layout} that is
6016  * independent of other regions and the containing BorderLayout, and can be any of the
6017  * {@link Ext.layout.ContainerLayout valid Ext layout types}.</p>
6018  * <p>Region size is managed automatically and cannot be changed by the user -- for
6019  * {@link #split resizable regions}, see {@link Ext.layout.BorderLayout.SplitRegion}.</p>
6020  * @constructor
6021  * Create a new Region.
6022  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
6023  * @param {Object} config The configuration options
6024  * @param {String} position The region position.  Valid values are: <tt>north</tt>, <tt>south</tt>,
6025  * <tt>east</tt>, <tt>west</tt> and <tt>center</tt>.  Every {@link Ext.layout.BorderLayout BorderLayout}
6026  * <b>must have a center region</b> for the primary content -- all other regions are optional.
6027  */
6028 Ext.layout.BorderLayout.Region = function(layout, config, pos){
6029     Ext.apply(this, config);
6030     this.layout = layout;
6031     this.position = pos;
6032     this.state = {};
6033     if(typeof this.margins == 'string'){
6034         this.margins = this.layout.parseMargins(this.margins);
6035     }
6036     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
6037     if(this.collapsible){
6038         if(typeof this.cmargins == 'string'){
6039             this.cmargins = this.layout.parseMargins(this.cmargins);
6040         }
6041         if(this.collapseMode == 'mini' && !this.cmargins){
6042             this.cmargins = {left:0,top:0,right:0,bottom:0};
6043         }else{
6044             this.cmargins = Ext.applyIf(this.cmargins || {},
6045                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
6046         }
6047     }
6048 };
6049
6050 Ext.layout.BorderLayout.Region.prototype = {
6051     /**
6052      * @cfg {Boolean} animFloat
6053      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
6054      * panel that will close again once the user mouses out of that panel (or clicks out if
6055      * <tt>{@link #autoHide} = false</tt>).  Setting <tt>{@link #animFloat} = false</tt> will
6056      * prevent the open and close of these floated panels from being animated (defaults to <tt>true</tt>).
6057      */
6058     /**
6059      * @cfg {Boolean} autoHide
6060      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
6061      * panel.  If <tt>autoHide = true</tt>, the panel will automatically hide after the user mouses
6062      * out of the panel.  If <tt>autoHide = false</tt>, the panel will continue to display until the
6063      * user clicks outside of the panel (defaults to <tt>true</tt>).
6064      */
6065     /**
6066      * @cfg {String} collapseMode
6067      * <tt>collapseMode</tt> supports two configuration values:<div class="mdetail-params"><ul>
6068      * <li><b><tt>undefined</tt></b> (default)<div class="sub-desc">By default, {@link #collapsible}
6069      * regions are collapsed by clicking the expand/collapse tool button that renders into the region's
6070      * title bar.</div></li>
6071      * <li><b><tt>'mini'</tt></b><div class="sub-desc">Optionally, when <tt>collapseMode</tt> is set to
6072      * <tt>'mini'</tt> the region's split bar will also display a small collapse button in the center of
6073      * the bar. In <tt>'mini'</tt> mode the region will collapse to a thinner bar than in normal mode.
6074      * </div></li>
6075      * </ul></div></p>
6076      * <p><b>Note</b>: if a collapsible region does not have a title bar, then set <tt>collapseMode =
6077      * 'mini'</tt> and <tt>{@link #split} = true</tt> in order for the region to be {@link #collapsible}
6078      * by the user as the expand/collapse tool button (that would go in the title bar) will not be rendered.</p>
6079      * <p>See also <tt>{@link #cmargins}</tt>.</p>
6080      */
6081     /**
6082      * @cfg {Object} margins
6083      * An object containing margins to apply to the region when in the expanded state in the
6084      * format:<pre><code>
6085 {
6086     top: (top margin),
6087     right: (right margin),
6088     bottom: (bottom margin),
6089     left: (left margin)
6090 }</code></pre>
6091      * <p>May also be a string containing space-separated, numeric margin values. The order of the
6092      * sides associated with each value matches the way CSS processes margin values:</p>
6093      * <p><div class="mdetail-params"><ul>
6094      * <li>If there is only one value, it applies to all sides.</li>
6095      * <li>If there are two values, the top and bottom borders are set to the first value and the
6096      * right and left are set to the second.</li>
6097      * <li>If there are three values, the top is set to the first value, the left and right are set
6098      * to the second, and the bottom is set to the third.</li>
6099      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
6100      * </ul></div></p>
6101      * <p>Defaults to:</p><pre><code>
6102      * {top:0, right:0, bottom:0, left:0}
6103      * </code></pre>
6104      */
6105     /**
6106      * @cfg {Object} cmargins
6107      * An object containing margins to apply to the region when in the collapsed state in the
6108      * format:<pre><code>
6109 {
6110     top: (top margin),
6111     right: (right margin),
6112     bottom: (bottom margin),
6113     left: (left margin)
6114 }</code></pre>
6115      * <p>May also be a string containing space-separated, numeric margin values. The order of the
6116      * sides associated with each value matches the way CSS processes margin values.</p>
6117      * <p><ul>
6118      * <li>If there is only one value, it applies to all sides.</li>
6119      * <li>If there are two values, the top and bottom borders are set to the first value and the
6120      * right and left are set to the second.</li>
6121      * <li>If there are three values, the top is set to the first value, the left and right are set
6122      * to the second, and the bottom is set to the third.</li>
6123      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
6124      * </ul></p>
6125      */
6126     /**
6127      * @cfg {Boolean} collapsible
6128      * <p><tt>true</tt> to allow the user to collapse this region (defaults to <tt>false</tt>).  If
6129      * <tt>true</tt>, an expand/collapse tool button will automatically be rendered into the title
6130      * bar of the region, otherwise the button will not be shown.</p>
6131      * <p><b>Note</b>: that a title bar is required to display the collapse/expand toggle button -- if
6132      * no <tt>title</tt> is specified for the region's panel, the region will only be collapsible if
6133      * <tt>{@link #collapseMode} = 'mini'</tt> and <tt>{@link #split} = true</tt>.
6134      */
6135     collapsible : false,
6136     /**
6137      * @cfg {Boolean} split
6138      * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and
6139      * display a 5px wide {@link Ext.SplitBar} between this region and its neighbor, allowing the user to
6140      * resize the regions dynamically.  Defaults to <tt>false</tt> creating a
6141      * {@link Ext.layout.BorderLayout.Region Region}.</p><br>
6142      * <p><b>Notes</b>:</p><div class="mdetail-params"><ul>
6143      * <li>this configuration option is ignored if <tt>region='center'</tt></li>
6144      * <li>when <tt>split == true</tt>, it is common to specify a
6145      * <tt>{@link Ext.SplitBar#minSize minSize}</tt> and <tt>{@link Ext.SplitBar#maxSize maxSize}</tt>
6146      * for the {@link Ext.BoxComponent BoxComponent} representing the region. These are not native
6147      * configs of {@link Ext.BoxComponent BoxComponent}, and are used only by this class.</li>
6148      * <li>if <tt>{@link #collapseMode} = 'mini'</tt> requires <tt>split = true</tt> to reserve space
6149      * for the collapse tool</tt></li>
6150      * </ul></div>
6151      */
6152     split:false,
6153     /**
6154      * @cfg {Boolean} floatable
6155      * <tt>true</tt> to allow clicking a collapsed region's bar to display the region's panel floated
6156      * above the layout, <tt>false</tt> to force the user to fully expand a collapsed region by
6157      * clicking the expand button to see it again (defaults to <tt>true</tt>).
6158      */
6159     floatable: true,
6160     /**
6161      * @cfg {Number} minWidth
6162      * <p>The minimum allowable width in pixels for this region (defaults to <tt>50</tt>).
6163      * <tt>maxWidth</tt> may also be specified.</p><br>
6164      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
6165      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
6166      * <tt>minWidth</tt> / <tt>maxWidth</tt>.</p>
6167      */
6168     minWidth:50,
6169     /**
6170      * @cfg {Number} minHeight
6171      * The minimum allowable height in pixels for this region (defaults to <tt>50</tt>)
6172      * <tt>maxHeight</tt> may also be specified.</p><br>
6173      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
6174      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
6175      * <tt>minHeight</tt> / <tt>maxHeight</tt>.</p>
6176      */
6177     minHeight:50,
6178
6179     // private
6180     defaultMargins : {left:0,top:0,right:0,bottom:0},
6181     // private
6182     defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
6183     // private
6184     defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
6185     floatingZIndex: 100,
6186
6187     /**
6188      * True if this region is collapsed. Read-only.
6189      * @type Boolean
6190      * @property
6191      */
6192     isCollapsed : false,
6193
6194     /**
6195      * This region's panel.  Read-only.
6196      * @type Ext.Panel
6197      * @property panel
6198      */
6199     /**
6200      * This region's layout.  Read-only.
6201      * @type Layout
6202      * @property layout
6203      */
6204     /**
6205      * This region's layout position (north, south, east, west or center).  Read-only.
6206      * @type String
6207      * @property position
6208      */
6209
6210     // private
6211     render : function(ct, p){
6212         this.panel = p;
6213         p.el.enableDisplayMode();
6214         this.targetEl = ct;
6215         this.el = p.el;
6216
6217         var gs = p.getState, ps = this.position;
6218         p.getState = function(){
6219             return Ext.apply(gs.call(p) || {}, this.state);
6220         }.createDelegate(this);
6221
6222         if(ps != 'center'){
6223             p.allowQueuedExpand = false;
6224             p.on({
6225                 beforecollapse: this.beforeCollapse,
6226                 collapse: this.onCollapse,
6227                 beforeexpand: this.beforeExpand,
6228                 expand: this.onExpand,
6229                 hide: this.onHide,
6230                 show: this.onShow,
6231                 scope: this
6232             });
6233             if(this.collapsible || this.floatable){
6234                 p.collapseEl = 'el';
6235                 p.slideAnchor = this.getSlideAnchor();
6236             }
6237             if(p.tools && p.tools.toggle){
6238                 p.tools.toggle.addClass('x-tool-collapse-'+ps);
6239                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
6240             }
6241         }
6242     },
6243
6244     // private
6245     getCollapsedEl : function(){
6246         if(!this.collapsedEl){
6247             if(!this.toolTemplate){
6248                 var tt = new Ext.Template(
6249                      '<div class="x-tool x-tool-{id}">&#160;</div>'
6250                 );
6251                 tt.disableFormats = true;
6252                 tt.compile();
6253                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
6254             }
6255             this.collapsedEl = this.targetEl.createChild({
6256                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
6257                 id: this.panel.id + '-xcollapsed'
6258             });
6259             this.collapsedEl.enableDisplayMode('block');
6260
6261             if(this.collapseMode == 'mini'){
6262                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
6263                 this.miniCollapsedEl = this.collapsedEl.createChild({
6264                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
6265                 });
6266                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
6267                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
6268                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
6269             }else {
6270                 if(this.collapsible !== false && !this.hideCollapseTool) {
6271                     var t = this.toolTemplate.append(
6272                             this.collapsedEl.dom,
6273                             {id:'expand-'+this.position}, true);
6274                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
6275                     t.on('click', this.onExpandClick, this, {stopEvent:true});
6276                 }
6277                 if(this.floatable !== false || this.titleCollapse){
6278                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
6279                    this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
6280                 }
6281             }
6282         }
6283         return this.collapsedEl;
6284     },
6285
6286     // private
6287     onExpandClick : function(e){
6288         if(this.isSlid){
6289             this.panel.expand(false);
6290         }else{
6291             this.panel.expand();
6292         }
6293     },
6294
6295     // private
6296     onCollapseClick : function(e){
6297         this.panel.collapse();
6298     },
6299
6300     // private
6301     beforeCollapse : function(p, animate){
6302         this.lastAnim = animate;
6303         if(this.splitEl){
6304             this.splitEl.hide();
6305         }
6306         this.getCollapsedEl().show();
6307         var el = this.panel.getEl();
6308         this.originalZIndex = el.getStyle('z-index');
6309         el.setStyle('z-index', 100);
6310         this.isCollapsed = true;
6311         this.layout.layout();
6312     },
6313
6314     // private
6315     onCollapse : function(animate){
6316         this.panel.el.setStyle('z-index', 1);
6317         if(this.lastAnim === false || this.panel.animCollapse === false){
6318             this.getCollapsedEl().dom.style.visibility = 'visible';
6319         }else{
6320             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
6321         }
6322         this.state.collapsed = true;
6323         this.panel.saveState();
6324     },
6325
6326     // private
6327     beforeExpand : function(animate){
6328         if(this.isSlid){
6329             this.afterSlideIn();
6330         }
6331         var c = this.getCollapsedEl();
6332         this.el.show();
6333         if(this.position == 'east' || this.position == 'west'){
6334             this.panel.setSize(undefined, c.getHeight());
6335         }else{
6336             this.panel.setSize(c.getWidth(), undefined);
6337         }
6338         c.hide();
6339         c.dom.style.visibility = 'hidden';
6340         this.panel.el.setStyle('z-index', this.floatingZIndex);
6341     },
6342
6343     // private
6344     onExpand : function(){
6345         this.isCollapsed = false;
6346         if(this.splitEl){
6347             this.splitEl.show();
6348         }
6349         this.layout.layout();
6350         this.panel.el.setStyle('z-index', this.originalZIndex);
6351         this.state.collapsed = false;
6352         this.panel.saveState();
6353     },
6354
6355     // private
6356     collapseClick : function(e){
6357         if(this.isSlid){
6358            e.stopPropagation();
6359            this.slideIn();
6360         }else{
6361            e.stopPropagation();
6362            this.slideOut();
6363         }
6364     },
6365
6366     // private
6367     onHide : function(){
6368         if(this.isCollapsed){
6369             this.getCollapsedEl().hide();
6370         }else if(this.splitEl){
6371             this.splitEl.hide();
6372         }
6373     },
6374
6375     // private
6376     onShow : function(){
6377         if(this.isCollapsed){
6378             this.getCollapsedEl().show();
6379         }else if(this.splitEl){
6380             this.splitEl.show();
6381         }
6382     },
6383
6384     /**
6385      * True if this region is currently visible, else false.
6386      * @return {Boolean}
6387      */
6388     isVisible : function(){
6389         return !this.panel.hidden;
6390     },
6391
6392     /**
6393      * Returns the current margins for this region.  If the region is collapsed, the
6394      * {@link #cmargins} (collapsed margins) value will be returned, otherwise the
6395      * {@link #margins} value will be returned.
6396      * @return {Object} An object containing the element's margins: <tt>{left: (left
6397      * margin), top: (top margin), right: (right margin), bottom: (bottom margin)}</tt>
6398      */
6399     getMargins : function(){
6400         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
6401     },
6402
6403     /**
6404      * Returns the current size of this region.  If the region is collapsed, the size of the
6405      * collapsedEl will be returned, otherwise the size of the region's panel will be returned.
6406      * @return {Object} An object containing the element's size: <tt>{width: (element width),
6407      * height: (element height)}</tt>
6408      */
6409     getSize : function(){
6410         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
6411     },
6412
6413     /**
6414      * Sets the specified panel as the container element for this region.
6415      * @param {Ext.Panel} panel The new panel
6416      */
6417     setPanel : function(panel){
6418         this.panel = panel;
6419     },
6420
6421     /**
6422      * Returns the minimum allowable width for this region.
6423      * @return {Number} The minimum width
6424      */
6425     getMinWidth: function(){
6426         return this.minWidth;
6427     },
6428
6429     /**
6430      * Returns the minimum allowable height for this region.
6431      * @return {Number} The minimum height
6432      */
6433     getMinHeight: function(){
6434         return this.minHeight;
6435     },
6436
6437     // private
6438     applyLayoutCollapsed : function(box){
6439         var ce = this.getCollapsedEl();
6440         ce.setLeftTop(box.x, box.y);
6441         ce.setSize(box.width, box.height);
6442     },
6443
6444     // private
6445     applyLayout : function(box){
6446         if(this.isCollapsed){
6447             this.applyLayoutCollapsed(box);
6448         }else{
6449             this.panel.setPosition(box.x, box.y);
6450             this.panel.setSize(box.width, box.height);
6451         }
6452     },
6453
6454     // private
6455     beforeSlide: function(){
6456         this.panel.beforeEffect();
6457     },
6458
6459     // private
6460     afterSlide : function(){
6461         this.panel.afterEffect();
6462     },
6463
6464     // private
6465     initAutoHide : function(){
6466         if(this.autoHide !== false){
6467             if(!this.autoHideHd){
6468                 this.autoHideSlideTask = new Ext.util.DelayedTask(this.slideIn, this);
6469                 this.autoHideHd = {
6470                     "mouseout": function(e){
6471                         if(!e.within(this.el, true)){
6472                             this.autoHideSlideTask.delay(500);
6473                         }
6474                     },
6475                     "mouseover" : function(e){
6476                         this.autoHideSlideTask.cancel();
6477                     },
6478                     scope : this
6479                 };
6480             }
6481             this.el.on(this.autoHideHd);
6482             this.collapsedEl.on(this.autoHideHd);
6483         }
6484     },
6485
6486     // private
6487     clearAutoHide : function(){
6488         if(this.autoHide !== false){
6489             this.el.un("mouseout", this.autoHideHd.mouseout);
6490             this.el.un("mouseover", this.autoHideHd.mouseover);
6491             this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
6492             this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
6493         }
6494     },
6495
6496     // private
6497     clearMonitor : function(){
6498         Ext.getDoc().un("click", this.slideInIf, this);
6499     },
6500
6501     /**
6502      * If this Region is {@link #floatable}, this method slides this Region into full visibility <i>over the top
6503      * of the center Region</i> where it floats until either {@link #slideIn} is called, or other regions of the layout
6504      * are clicked, or the mouse exits the Region.
6505      */
6506     slideOut : function(){
6507         if(this.isSlid || this.el.hasActiveFx()){
6508             return;
6509         }
6510         this.isSlid = true;
6511         var ts = this.panel.tools, dh, pc;
6512         if(ts && ts.toggle){
6513             ts.toggle.hide();
6514         }
6515         this.el.show();
6516
6517         // Temporarily clear the collapsed flag so we can onResize the panel on the slide
6518         pc = this.panel.collapsed;
6519         this.panel.collapsed = false;
6520
6521         if(this.position == 'east' || this.position == 'west'){
6522             // Temporarily clear the deferHeight flag so we can size the height on the slide
6523             dh = this.panel.deferHeight;
6524             this.panel.deferHeight = false;
6525
6526             this.panel.setSize(undefined, this.collapsedEl.getHeight());
6527
6528             // Put the deferHeight flag back after setSize
6529             this.panel.deferHeight = dh;
6530         }else{
6531             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
6532         }
6533
6534         // Put the collapsed flag back after onResize
6535         this.panel.collapsed = pc;
6536
6537         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
6538         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
6539         this.el.setStyle("z-index", this.floatingZIndex+2);
6540         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
6541         if(this.animFloat !== false){
6542             this.beforeSlide();
6543             this.el.slideIn(this.getSlideAnchor(), {
6544                 callback: function(){
6545                     this.afterSlide();
6546                     this.initAutoHide();
6547                     Ext.getDoc().on("click", this.slideInIf, this);
6548                 },
6549                 scope: this,
6550                 block: true
6551             });
6552         }else{
6553             this.initAutoHide();
6554              Ext.getDoc().on("click", this.slideInIf, this);
6555         }
6556     },
6557
6558     // private
6559     afterSlideIn : function(){
6560         this.clearAutoHide();
6561         this.isSlid = false;
6562         this.clearMonitor();
6563         this.el.setStyle("z-index", "");
6564         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
6565         this.el.dom.style.left = this.restoreLT[0];
6566         this.el.dom.style.top = this.restoreLT[1];
6567
6568         var ts = this.panel.tools;
6569         if(ts && ts.toggle){
6570             ts.toggle.show();
6571         }
6572     },
6573
6574     /**
6575      * If this Region is {@link #floatable}, and this Region has been slid into floating visibility, then this method slides
6576      * this region back into its collapsed state.
6577      */
6578     slideIn : function(cb){
6579         if(!this.isSlid || this.el.hasActiveFx()){
6580             Ext.callback(cb);
6581             return;
6582         }
6583         this.isSlid = false;
6584         if(this.animFloat !== false){
6585             this.beforeSlide();
6586             this.el.slideOut(this.getSlideAnchor(), {
6587                 callback: function(){
6588                     this.el.hide();
6589                     this.afterSlide();
6590                     this.afterSlideIn();
6591                     Ext.callback(cb);
6592                 },
6593                 scope: this,
6594                 block: true
6595             });
6596         }else{
6597             this.el.hide();
6598             this.afterSlideIn();
6599         }
6600     },
6601
6602     // private
6603     slideInIf : function(e){
6604         if(!e.within(this.el)){
6605             this.slideIn();
6606         }
6607     },
6608
6609     // private
6610     anchors : {
6611         "west" : "left",
6612         "east" : "right",
6613         "north" : "top",
6614         "south" : "bottom"
6615     },
6616
6617     // private
6618     sanchors : {
6619         "west" : "l",
6620         "east" : "r",
6621         "north" : "t",
6622         "south" : "b"
6623     },
6624
6625     // private
6626     canchors : {
6627         "west" : "tl-tr",
6628         "east" : "tr-tl",
6629         "north" : "tl-bl",
6630         "south" : "bl-tl"
6631     },
6632
6633     // private
6634     getAnchor : function(){
6635         return this.anchors[this.position];
6636     },
6637
6638     // private
6639     getCollapseAnchor : function(){
6640         return this.canchors[this.position];
6641     },
6642
6643     // private
6644     getSlideAnchor : function(){
6645         return this.sanchors[this.position];
6646     },
6647
6648     // private
6649     getAlignAdj : function(){
6650         var cm = this.cmargins;
6651         switch(this.position){
6652             case "west":
6653                 return [0, 0];
6654             break;
6655             case "east":
6656                 return [0, 0];
6657             break;
6658             case "north":
6659                 return [0, 0];
6660             break;
6661             case "south":
6662                 return [0, 0];
6663             break;
6664         }
6665     },
6666
6667     // private
6668     getExpandAdj : function(){
6669         var c = this.collapsedEl, cm = this.cmargins;
6670         switch(this.position){
6671             case "west":
6672                 return [-(cm.right+c.getWidth()+cm.left), 0];
6673             break;
6674             case "east":
6675                 return [cm.right+c.getWidth()+cm.left, 0];
6676             break;
6677             case "north":
6678                 return [0, -(cm.top+cm.bottom+c.getHeight())];
6679             break;
6680             case "south":
6681                 return [0, cm.top+cm.bottom+c.getHeight()];
6682             break;
6683         }
6684     },
6685
6686     destroy : function(){
6687         if (this.autoHideSlideTask && this.autoHideSlideTask.cancel){
6688             this.autoHideSlideTask.cancel();
6689         }
6690         Ext.destroy(this.miniCollapsedEl, this.collapsedEl);
6691     }
6692 };
6693
6694 /**
6695  * @class Ext.layout.BorderLayout.SplitRegion
6696  * @extends Ext.layout.BorderLayout.Region
6697  * <p>This is a specialized type of {@link Ext.layout.BorderLayout.Region BorderLayout region} that
6698  * has a built-in {@link Ext.SplitBar} for user resizing of regions.  The movement of the split bar
6699  * is configurable to move either {@link #tickSize smooth or incrementally}.</p>
6700  * @constructor
6701  * Create a new SplitRegion.
6702  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
6703  * @param {Object} config The configuration options
6704  * @param {String} position The region position.  Valid values are: north, south, east, west and center.  Every
6705  * BorderLayout must have a center region for the primary content -- all other regions are optional.
6706  */
6707 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
6708     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
6709     // prevent switch
6710     this.applyLayout = this.applyFns[pos];
6711 };
6712
6713 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
6714     /**
6715      * @cfg {Number} tickSize
6716      * The increment, in pixels by which to move this Region's {@link Ext.SplitBar SplitBar}.
6717      * By default, the {@link Ext.SplitBar SplitBar} moves smoothly.
6718      */
6719     /**
6720      * @cfg {String} splitTip
6721      * The tooltip to display when the user hovers over a
6722      * {@link Ext.layout.BorderLayout.Region#collapsible non-collapsible} region's split bar
6723      * (defaults to <tt>"Drag to resize."</tt>).  Only applies if
6724      * <tt>{@link #useSplitTips} = true</tt>.
6725      */
6726     splitTip : "Drag to resize.",
6727     /**
6728      * @cfg {String} collapsibleSplitTip
6729      * The tooltip to display when the user hovers over a
6730      * {@link Ext.layout.BorderLayout.Region#collapsible collapsible} region's split bar
6731      * (defaults to "Drag to resize. Double click to hide."). Only applies if
6732      * <tt>{@link #useSplitTips} = true</tt>.
6733      */
6734     collapsibleSplitTip : "Drag to resize. Double click to hide.",
6735     /**
6736      * @cfg {Boolean} useSplitTips
6737      * <tt>true</tt> to display a tooltip when the user hovers over a region's split bar
6738      * (defaults to <tt>false</tt>).  The tooltip text will be the value of either
6739      * <tt>{@link #splitTip}</tt> or <tt>{@link #collapsibleSplitTip}</tt> as appropriate.
6740      */
6741     useSplitTips : false,
6742
6743     // private
6744     splitSettings : {
6745         north : {
6746             orientation: Ext.SplitBar.VERTICAL,
6747             placement: Ext.SplitBar.TOP,
6748             maxFn : 'getVMaxSize',
6749             minProp: 'minHeight',
6750             maxProp: 'maxHeight'
6751         },
6752         south : {
6753             orientation: Ext.SplitBar.VERTICAL,
6754             placement: Ext.SplitBar.BOTTOM,
6755             maxFn : 'getVMaxSize',
6756             minProp: 'minHeight',
6757             maxProp: 'maxHeight'
6758         },
6759         east : {
6760             orientation: Ext.SplitBar.HORIZONTAL,
6761             placement: Ext.SplitBar.RIGHT,
6762             maxFn : 'getHMaxSize',
6763             minProp: 'minWidth',
6764             maxProp: 'maxWidth'
6765         },
6766         west : {
6767             orientation: Ext.SplitBar.HORIZONTAL,
6768             placement: Ext.SplitBar.LEFT,
6769             maxFn : 'getHMaxSize',
6770             minProp: 'minWidth',
6771             maxProp: 'maxWidth'
6772         }
6773     },
6774
6775     // private
6776     applyFns : {
6777         west : function(box){
6778             if(this.isCollapsed){
6779                 return this.applyLayoutCollapsed(box);
6780             }
6781             var sd = this.splitEl.dom, s = sd.style;
6782             this.panel.setPosition(box.x, box.y);
6783             var sw = sd.offsetWidth;
6784             s.left = (box.x+box.width-sw)+'px';
6785             s.top = (box.y)+'px';
6786             s.height = Math.max(0, box.height)+'px';
6787             this.panel.setSize(box.width-sw, box.height);
6788         },
6789         east : function(box){
6790             if(this.isCollapsed){
6791                 return this.applyLayoutCollapsed(box);
6792             }
6793             var sd = this.splitEl.dom, s = sd.style;
6794             var sw = sd.offsetWidth;
6795             this.panel.setPosition(box.x+sw, box.y);
6796             s.left = (box.x)+'px';
6797             s.top = (box.y)+'px';
6798             s.height = Math.max(0, box.height)+'px';
6799             this.panel.setSize(box.width-sw, box.height);
6800         },
6801         north : function(box){
6802             if(this.isCollapsed){
6803                 return this.applyLayoutCollapsed(box);
6804             }
6805             var sd = this.splitEl.dom, s = sd.style;
6806             var sh = sd.offsetHeight;
6807             this.panel.setPosition(box.x, box.y);
6808             s.left = (box.x)+'px';
6809             s.top = (box.y+box.height-sh)+'px';
6810             s.width = Math.max(0, box.width)+'px';
6811             this.panel.setSize(box.width, box.height-sh);
6812         },
6813         south : function(box){
6814             if(this.isCollapsed){
6815                 return this.applyLayoutCollapsed(box);
6816             }
6817             var sd = this.splitEl.dom, s = sd.style;
6818             var sh = sd.offsetHeight;
6819             this.panel.setPosition(box.x, box.y+sh);
6820             s.left = (box.x)+'px';
6821             s.top = (box.y)+'px';
6822             s.width = Math.max(0, box.width)+'px';
6823             this.panel.setSize(box.width, box.height-sh);
6824         }
6825     },
6826
6827     // private
6828     render : function(ct, p){
6829         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
6830
6831         var ps = this.position;
6832
6833         this.splitEl = ct.createChild({
6834             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
6835             id: this.panel.id + '-xsplit'
6836         });
6837
6838         if(this.collapseMode == 'mini'){
6839             this.miniSplitEl = this.splitEl.createChild({
6840                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
6841             });
6842             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
6843             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
6844         }
6845
6846         var s = this.splitSettings[ps];
6847
6848         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
6849         this.split.tickSize = this.tickSize;
6850         this.split.placement = s.placement;
6851         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
6852         this.split.minSize = this.minSize || this[s.minProp];
6853         this.split.on("beforeapply", this.onSplitMove, this);
6854         this.split.useShim = this.useShim === true;
6855         this.maxSize = this.maxSize || this[s.maxProp];
6856
6857         if(p.hidden){
6858             this.splitEl.hide();
6859         }
6860
6861         if(this.useSplitTips){
6862             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
6863         }
6864         if(this.collapsible){
6865             this.splitEl.on("dblclick", this.onCollapseClick,  this);
6866         }
6867     },
6868
6869     //docs inherit from superclass
6870     getSize : function(){
6871         if(this.isCollapsed){
6872             return this.collapsedEl.getSize();
6873         }
6874         var s = this.panel.getSize();
6875         if(this.position == 'north' || this.position == 'south'){
6876             s.height += this.splitEl.dom.offsetHeight;
6877         }else{
6878             s.width += this.splitEl.dom.offsetWidth;
6879         }
6880         return s;
6881     },
6882
6883     // private
6884     getHMaxSize : function(){
6885          var cmax = this.maxSize || 10000;
6886          var center = this.layout.center;
6887          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
6888     },
6889
6890     // private
6891     getVMaxSize : function(){
6892         var cmax = this.maxSize || 10000;
6893         var center = this.layout.center;
6894         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
6895     },
6896
6897     // private
6898     onSplitMove : function(split, newSize){
6899         var s = this.panel.getSize();
6900         this.lastSplitSize = newSize;
6901         if(this.position == 'north' || this.position == 'south'){
6902             this.panel.setSize(s.width, newSize);
6903             this.state.height = newSize;
6904         }else{
6905             this.panel.setSize(newSize, s.height);
6906             this.state.width = newSize;
6907         }
6908         this.layout.layout();
6909         this.panel.saveState();
6910         return false;
6911     },
6912
6913     /**
6914      * Returns a reference to the split bar in use by this region.
6915      * @return {Ext.SplitBar} The split bar
6916      */
6917     getSplitBar : function(){
6918         return this.split;
6919     },
6920
6921     // inherit docs
6922     destroy : function() {
6923         Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
6924         Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
6925     }
6926 });
6927
6928 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;/**
6929  * @class Ext.layout.FormLayout
6930  * @extends Ext.layout.AnchorLayout
6931  * <p>This layout manager is specifically designed for rendering and managing child Components of
6932  * {@link Ext.form.FormPanel forms}. It is responsible for rendering the labels of
6933  * {@link Ext.form.Field Field}s.</p>
6934  *
6935  * <p>This layout manager is used when a Container is configured with the <tt>layout:'form'</tt>
6936  * {@link Ext.Container#layout layout} config option, and should generally not need to be created directly
6937  * via the new keyword. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
6938  *
6939  * <p>In an application, it will usually be preferrable to use a {@link Ext.form.FormPanel FormPanel}
6940  * (which is configured with FormLayout as its layout class by default) since it also provides built-in
6941  * functionality for {@link Ext.form.BasicForm#doAction loading, validating and submitting} the form.</p>
6942  *
6943  * <p>A {@link Ext.Container Container} <i>using</i> the FormLayout layout manager (e.g.
6944  * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) can also accept the following
6945  * layout-specific config properties:<div class="mdetail-params"><ul>
6946  * <li><b><tt>{@link Ext.form.FormPanel#hideLabels hideLabels}</tt></b></li>
6947  * <li><b><tt>{@link Ext.form.FormPanel#labelAlign labelAlign}</tt></b></li>
6948  * <li><b><tt>{@link Ext.form.FormPanel#labelPad labelPad}</tt></b></li>
6949  * <li><b><tt>{@link Ext.form.FormPanel#labelSeparator labelSeparator}</tt></b></li>
6950  * <li><b><tt>{@link Ext.form.FormPanel#labelWidth labelWidth}</tt></b></li>
6951  * </ul></div></p>
6952  *
6953  * <p>Any Component (including Fields) managed by FormLayout accepts the following as a config option:
6954  * <div class="mdetail-params"><ul>
6955  * <li><b><tt>{@link Ext.Component#anchor anchor}</tt></b></li>
6956  * </ul></div></p>
6957  *
6958  * <p>Any Component managed by FormLayout may be rendered as a form field (with an associated label) by
6959  * configuring it with a non-null <b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b>. Components configured
6960  * in this way may be configured with the following options which affect the way the FormLayout renders them:
6961  * <div class="mdetail-params"><ul>
6962  * <li><b><tt>{@link Ext.Component#clearCls clearCls}</tt></b></li>
6963  * <li><b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b></li>
6964  * <li><b><tt>{@link Ext.Component#hideLabel hideLabel}</tt></b></li>
6965  * <li><b><tt>{@link Ext.Component#itemCls itemCls}</tt></b></li>
6966  * <li><b><tt>{@link Ext.Component#labelSeparator labelSeparator}</tt></b></li>
6967  * <li><b><tt>{@link Ext.Component#labelStyle labelStyle}</tt></b></li>
6968  * </ul></div></p>
6969  *
6970  * <p>Example usage:</p>
6971  * <pre><code>
6972 // Required if showing validation messages
6973 Ext.QuickTips.init();
6974
6975 // While you can create a basic Panel with layout:'form', practically
6976 // you should usually use a FormPanel to also get its form functionality
6977 // since it already creates a FormLayout internally.
6978 var form = new Ext.form.FormPanel({
6979     title: 'Form Layout',
6980     bodyStyle: 'padding:15px',
6981     width: 350,
6982     defaultType: 'textfield',
6983     defaults: {
6984         // applied to each contained item
6985         width: 230,
6986         msgTarget: 'side'
6987     },
6988     items: [{
6989             fieldLabel: 'First Name',
6990             name: 'first',
6991             allowBlank: false,
6992             {@link Ext.Component#labelSeparator labelSeparator}: ':' // override labelSeparator layout config
6993         },{
6994             fieldLabel: 'Last Name',
6995             name: 'last'
6996         },{
6997             fieldLabel: 'Email',
6998             name: 'email',
6999             vtype:'email'
7000         }, {
7001             xtype: 'textarea',
7002             hideLabel: true,     // override hideLabels layout config
7003             name: 'msg',
7004             anchor: '100% -53'
7005         }
7006     ],
7007     buttons: [
7008         {text: 'Save'},
7009         {text: 'Cancel'}
7010     ],
7011     layoutConfig: {
7012         {@link #labelSeparator}: '~' // superseded by assignment below
7013     },
7014     // config options applicable to container when layout='form':
7015     hideLabels: false,
7016     labelAlign: 'left',   // or 'right' or 'top'
7017     {@link Ext.form.FormPanel#labelSeparator labelSeparator}: '>>', // takes precedence over layoutConfig value
7018     labelWidth: 65,       // defaults to 100
7019     labelPad: 8           // defaults to 5, must specify labelWidth to be honored
7020 });
7021 </code></pre>
7022  */
7023 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
7024
7025     /**
7026      * @cfg {String} labelSeparator
7027      * See {@link Ext.form.FormPanel}.{@link Ext.form.FormPanel#labelSeparator labelSeparator}.  Configuration
7028      * of this property at the <b>container</b> level takes precedence.
7029      */
7030     labelSeparator : ':',
7031
7032     /**
7033      * Read only. The CSS style specification string added to field labels in this layout if not
7034      * otherwise {@link Ext.Component#labelStyle specified by each contained field}.
7035      * @type String
7036      * @property labelStyle
7037      */
7038
7039     /**
7040      * @cfg {Boolean} trackLabels
7041      * True to show/hide the field label when the field is hidden. Defaults to <tt>false</tt>.
7042      */
7043     trackLabels: false,
7044
7045     type: 'form',
7046
7047     onRemove: function(c){
7048         Ext.layout.FormLayout.superclass.onRemove.call(this, c);
7049         if(this.trackLabels){
7050             c.un('show', this.onFieldShow, this);
7051             c.un('hide', this.onFieldHide, this);
7052         }
7053         // check for itemCt, since we may be removing a fieldset or something similar
7054         var el = c.getPositionEl(),
7055             ct = c.getItemCt && c.getItemCt();
7056         if (c.rendered && ct) {
7057             if (el && el.dom) {
7058                 el.insertAfter(ct);
7059             }
7060             Ext.destroy(ct);
7061             Ext.destroyMembers(c, 'label', 'itemCt');
7062             if (c.customItemCt) {
7063                 Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
7064             }
7065         }
7066     },
7067
7068     // private
7069     setContainer : function(ct){
7070         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
7071         if(ct.labelAlign){
7072             ct.addClass('x-form-label-'+ct.labelAlign);
7073         }
7074
7075         if(ct.hideLabels){
7076             Ext.apply(this, {
7077                 labelStyle: 'display:none',
7078                 elementStyle: 'padding-left:0;',
7079                 labelAdjust: 0
7080             });
7081         }else{
7082             this.labelSeparator = ct.labelSeparator || this.labelSeparator;
7083             ct.labelWidth = ct.labelWidth || 100;
7084             if(Ext.isNumber(ct.labelWidth)){
7085                 var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
7086                 Ext.apply(this, {
7087                     labelAdjust: ct.labelWidth + pad,
7088                     labelStyle: 'width:' + ct.labelWidth + 'px;',
7089                     elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
7090                 });
7091             }
7092             if(ct.labelAlign == 'top'){
7093                 Ext.apply(this, {
7094                     labelStyle: 'width:auto;',
7095                     labelAdjust: 0,
7096                     elementStyle: 'padding-left:0;'
7097                 });
7098             }
7099         }
7100     },
7101
7102     // private
7103     isHide: function(c){
7104         return c.hideLabel || this.container.hideLabels;
7105     },
7106
7107     onFieldShow: function(c){
7108         c.getItemCt().removeClass('x-hide-' + c.hideMode);
7109     },
7110
7111     onFieldHide: function(c){
7112         c.getItemCt().addClass('x-hide-' + c.hideMode);
7113     },
7114
7115     //private
7116     getLabelStyle: function(s){
7117         var ls = '', items = [this.labelStyle, s];
7118         for (var i = 0, len = items.length; i < len; ++i){
7119             if (items[i]){
7120                 ls += items[i];
7121                 if (ls.substr(-1, 1) != ';'){
7122                     ls += ';';
7123                 }
7124             }
7125         }
7126         return ls;
7127     },
7128
7129     /**
7130      * @cfg {Ext.Template} fieldTpl
7131      * A {@link Ext.Template#compile compile}d {@link Ext.Template} for rendering
7132      * the fully wrapped, labeled and styled form Field. Defaults to:</p><pre><code>
7133 new Ext.Template(
7134     &#39;&lt;div class="x-form-item {itemCls}" tabIndex="-1">&#39;,
7135         &#39;&lt;&#108;abel for="{id}" style="{labelStyle}" class="x-form-item-&#108;abel">{&#108;abel}{labelSeparator}&lt;/&#108;abel>&#39;,
7136         &#39;&lt;div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">&#39;,
7137         &#39;&lt;/div>&lt;div class="{clearCls}">&lt;/div>&#39;,
7138     '&lt;/div>'
7139 );
7140 </code></pre>
7141      * <p>This may be specified to produce a different DOM structure when rendering form Fields.</p>
7142      * <p>A description of the properties within the template follows:</p><div class="mdetail-params"><ul>
7143      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
7144      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
7145      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
7146      * supplied at the container level.</div></li>
7147      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
7148      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
7149      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
7150      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
7151      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
7152      * field (defaults to <tt>''</tt>)</div></li>
7153      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
7154      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
7155      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
7156      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
7157      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
7158      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
7159      * </ul></div>
7160      * <p>Also see <tt>{@link #getTemplateArgs}</tt></p>
7161      */
7162
7163     /**
7164      * @private
7165      * 
7166      */
7167     renderItem : function(c, position, target){
7168         if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
7169             var args = this.getTemplateArgs(c);
7170             if(Ext.isNumber(position)){
7171                 position = target.dom.childNodes[position] || null;
7172             }
7173             if(position){
7174                 c.itemCt = this.fieldTpl.insertBefore(position, args, true);
7175             }else{
7176                 c.itemCt = this.fieldTpl.append(target, args, true);
7177             }
7178             if(!c.getItemCt){
7179                 // Non form fields don't have getItemCt, apply it here
7180                 // This will get cleaned up in onRemove
7181                 Ext.apply(c, {
7182                     getItemCt: function(){
7183                         return c.itemCt;
7184                     },
7185                     customItemCt: true
7186                 });
7187             }
7188             c.label = c.getItemCt().child('label.x-form-item-label');
7189             if(!c.rendered){
7190                 c.render('x-form-el-' + c.id);
7191             }else if(!this.isValidParent(c, target)){
7192                 Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
7193             }
7194             if(this.trackLabels){
7195                 if(c.hidden){
7196                     this.onFieldHide(c);
7197                 }
7198                 c.on({
7199                     scope: this,
7200                     show: this.onFieldShow,
7201                     hide: this.onFieldHide
7202                 });
7203             }
7204             this.configureItem(c);
7205         }else {
7206             Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
7207         }
7208     },
7209
7210     /**
7211      * <p>Provides template arguments for rendering the fully wrapped, labeled and styled form Field.</p>
7212      * <p>This method returns an object hash containing properties used by the layout's {@link #fieldTpl}
7213      * to create a correctly wrapped, labeled and styled form Field. This may be overriden to
7214      * create custom layouts. The properties which must be returned are:</p><div class="mdetail-params"><ul>
7215      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
7216      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
7217      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
7218      * supplied at the container level.</div></li>
7219      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
7220      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
7221      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
7222      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
7223      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
7224      * field (defaults to the field's configured fieldLabel property)</div></li>
7225      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
7226      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
7227      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
7228      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
7229      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
7230      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
7231      * </ul></div>
7232      * @param (Ext.form.Field} field The {@link Ext.form.Field Field} being rendered.
7233      * @return {Object} An object hash containing the properties required to render the Field.
7234      */
7235     getTemplateArgs: function(field) {
7236         var noLabelSep = !field.fieldLabel || field.hideLabel;
7237         
7238         return {
7239             id            : field.id,
7240             label         : field.fieldLabel,
7241             itemCls       : (field.itemCls || this.container.itemCls || '') + (field.hideLabel ? ' x-hide-label' : ''),
7242             clearCls      : field.clearCls || 'x-form-clear-left',
7243             labelStyle    : this.getLabelStyle(field.labelStyle),
7244             elementStyle  : this.elementStyle || '',
7245             labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator)
7246         };
7247     },
7248
7249     // private
7250     adjustWidthAnchor: function(value, c){
7251         if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){
7252             var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
7253             return value - this.labelAdjust + (adjust ? -3 : 0);
7254         }
7255         return value;
7256     },
7257
7258     adjustHeightAnchor : function(value, c){
7259         if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
7260             return value - c.label.getHeight();
7261         }
7262         return value;
7263     },
7264
7265     // private
7266     isValidParent : function(c, target){
7267         return target && this.container.getEl().contains(c.getPositionEl());
7268     }
7269
7270     /**
7271      * @property activeItem
7272      * @hide
7273      */
7274 });
7275
7276 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
7277 /**
7278  * @class Ext.layout.AccordionLayout
7279  * @extends Ext.layout.FitLayout
7280  * <p>This is a layout that manages multiple Panels in an expandable accordion style such that only
7281  * <b>one Panel can be expanded at any given time</b>. Each Panel has built-in support for expanding and collapsing.</p>
7282  * <p>Note: Only Ext.Panels <b>and all subclasses of Ext.Panel</b> may be used in an accordion layout Container.</p>
7283  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
7284  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
7285  * <p>Example usage:</p>
7286  * <pre><code>
7287 var accordion = new Ext.Panel({
7288     title: 'Accordion Layout',
7289     layout:'accordion',
7290     defaults: {
7291         // applied to each contained panel
7292         bodyStyle: 'padding:15px'
7293     },
7294     layoutConfig: {
7295         // layout-specific configs go here
7296         titleCollapse: false,
7297         animate: true,
7298         activeOnTop: true
7299     },
7300     items: [{
7301         title: 'Panel 1',
7302         html: '&lt;p&gt;Panel content!&lt;/p&gt;'
7303     },{
7304         title: 'Panel 2',
7305         html: '&lt;p&gt;Panel content!&lt;/p&gt;'
7306     },{
7307         title: 'Panel 3',
7308         html: '&lt;p&gt;Panel content!&lt;/p&gt;'
7309     }]
7310 });
7311 </code></pre>
7312  */
7313 Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
7314     /**
7315      * @cfg {Boolean} fill
7316      * True to adjust the active item's height to fill the available space in the container, false to use the
7317      * item's current height, or auto height if not explicitly set (defaults to true).
7318      */
7319     fill : true,
7320     /**
7321      * @cfg {Boolean} autoWidth
7322      * True to set each contained item's width to 'auto', false to use the item's current width (defaults to true).
7323      * Note that some components, in particular the {@link Ext.grid.GridPanel grid}, will not function properly within
7324      * layouts if they have auto width, so in such cases this config should be set to false.
7325      */
7326     autoWidth : true,
7327     /**
7328      * @cfg {Boolean} titleCollapse
7329      * True to allow expand/collapse of each contained panel by clicking anywhere on the title bar, false to allow
7330      * expand/collapse only when the toggle tool button is clicked (defaults to true).  When set to false,
7331      * {@link #hideCollapseTool} should be false also.
7332      */
7333     titleCollapse : true,
7334     /**
7335      * @cfg {Boolean} hideCollapseTool
7336      * True to hide the contained panels' collapse/expand toggle buttons, false to display them (defaults to false).
7337      * When set to true, {@link #titleCollapse} should be true also.
7338      */
7339     hideCollapseTool : false,
7340     /**
7341      * @cfg {Boolean} collapseFirst
7342      * True to make sure the collapse/expand toggle button always renders first (to the left of) any other tools
7343      * in the contained panels' title bars, false to render it last (defaults to false).
7344      */
7345     collapseFirst : false,
7346     /**
7347      * @cfg {Boolean} animate
7348      * True to slide the contained panels open and closed during expand/collapse using animation, false to open and
7349      * close directly with no animation (defaults to false).  Note: to defer to the specific config setting of each
7350      * contained panel for this property, set this to undefined at the layout level.
7351      */
7352     animate : false,
7353     /**
7354      * @cfg {Boolean} sequence
7355      * <b>Experimental</b>. If animate is set to true, this will result in each animation running in sequence.
7356      */
7357     sequence : false,
7358     /**
7359      * @cfg {Boolean} activeOnTop
7360      * True to swap the position of each panel as it is expanded so that it becomes the first item in the container,
7361      * false to keep the panels in the rendered order. <b>This is NOT compatible with "animate:true"</b> (defaults to false).
7362      */
7363     activeOnTop : false,
7364
7365     type: 'accordion',
7366
7367     renderItem : function(c){
7368         if(this.animate === false){
7369             c.animCollapse = false;
7370         }
7371         c.collapsible = true;
7372         if(this.autoWidth){
7373             c.autoWidth = true;
7374         }
7375         if(this.titleCollapse){
7376             c.titleCollapse = true;
7377         }
7378         if(this.hideCollapseTool){
7379             c.hideCollapseTool = true;
7380         }
7381         if(this.collapseFirst !== undefined){
7382             c.collapseFirst = this.collapseFirst;
7383         }
7384         if(!this.activeItem && !c.collapsed){
7385             this.setActiveItem(c, true);
7386         }else if(this.activeItem && this.activeItem != c){
7387             c.collapsed = true;
7388         }
7389         Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
7390         c.header.addClass('x-accordion-hd');
7391         c.on('beforeexpand', this.beforeExpand, this);
7392     },
7393
7394     onRemove: function(c){
7395         Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
7396         if(c.rendered){
7397             c.header.removeClass('x-accordion-hd');
7398         }
7399         c.un('beforeexpand', this.beforeExpand, this);
7400     },
7401
7402     // private
7403     beforeExpand : function(p, anim){
7404         var ai = this.activeItem;
7405         if(ai){
7406             if(this.sequence){
7407                 delete this.activeItem;
7408                 if (!ai.collapsed){
7409                     ai.collapse({callback:function(){
7410                         p.expand(anim || true);
7411                     }, scope: this});
7412                     return false;
7413                 }
7414             }else{
7415                 ai.collapse(this.animate);
7416             }
7417         }
7418         this.setActive(p);
7419         if(this.activeOnTop){
7420             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
7421         }
7422         // Items have been hidden an possibly rearranged, we need to get the container size again.
7423         this.layout();
7424     },
7425
7426     // private
7427     setItemSize : function(item, size){
7428         if(this.fill && item){
7429             var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;
7430             // Add up all the header heights
7431             for (i = 0; i < len; i++) {
7432                 if((p = ct[i]) != item){
7433                     hh += p.header.getHeight();
7434                 }
7435             };
7436             // Subtract the header heights from the container size
7437             size.height -= hh;
7438             // Call setSize on the container to set the correct height.  For Panels, deferedHeight
7439             // will simply store this size for when the expansion is done.
7440             item.setSize(size);
7441         }
7442     },
7443
7444     /**
7445      * Sets the active (expanded) item in the layout.
7446      * @param {String/Number} item The string component id or numeric index of the item to activate
7447      */
7448     setActiveItem : function(item){
7449         this.setActive(item, true);
7450     },
7451
7452     // private
7453     setActive : function(item, expand){
7454         var ai = this.activeItem;
7455         item = this.container.getComponent(item);
7456         if(ai != item){
7457             if(item.rendered && item.collapsed && expand){
7458                 item.expand();
7459             }else{
7460                 if(ai){
7461                    ai.fireEvent('deactivate', ai);
7462                 }
7463                 this.activeItem = item;
7464                 item.fireEvent('activate', item);
7465             }
7466         }
7467     }
7468 });
7469 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
7470
7471 //backwards compat
7472 Ext.layout.Accordion = Ext.layout.AccordionLayout;/**
7473  * @class Ext.layout.TableLayout
7474  * @extends Ext.layout.ContainerLayout
7475  * <p>This layout allows you to easily render content into an HTML table.  The total number of columns can be
7476  * specified, and rowspan and colspan can be used to create complex layouts within the table.
7477  * This class is intended to be extended or created via the layout:'table' {@link Ext.Container#layout} config,
7478  * and should generally not need to be created directly via the new keyword.</p>
7479  * <p>Note that when creating a layout via config, the layout-specific config properties must be passed in via
7480  * the {@link Ext.Container#layoutConfig} object which will then be applied internally to the layout.  In the
7481  * case of TableLayout, the only valid layout config property is {@link #columns}.  However, the items added to a
7482  * TableLayout can supply the following table-specific config properties:</p>
7483  * <ul>
7484  * <li><b>rowspan</b> Applied to the table cell containing the item.</li>
7485  * <li><b>colspan</b> Applied to the table cell containing the item.</li>
7486  * <li><b>cellId</b> An id applied to the table cell containing the item.</li>
7487  * <li><b>cellCls</b> A CSS class name added to the table cell containing the item.</li>
7488  * </ul>
7489  * <p>The basic concept of building up a TableLayout is conceptually very similar to building up a standard
7490  * HTML table.  You simply add each panel (or "cell") that you want to include along with any span attributes
7491  * specified as the special config properties of rowspan and colspan which work exactly like their HTML counterparts.
7492  * Rather than explicitly creating and nesting rows and columns as you would in HTML, you simply specify the
7493  * total column count in the layoutConfig and start adding panels in their natural order from left to right,
7494  * top to bottom.  The layout will automatically figure out, based on the column count, rowspans and colspans,
7495  * how to position each panel within the table.  Just like with HTML tables, your rowspans and colspans must add
7496  * up correctly in your overall layout or you'll end up with missing and/or extra cells!  Example usage:</p>
7497  * <pre><code>
7498 // This code will generate a layout table that is 3 columns by 2 rows
7499 // with some spanning included.  The basic layout will be:
7500 // +--------+-----------------+
7501 // |   A    |   B             |
7502 // |        |--------+--------|
7503 // |        |   C    |   D    |
7504 // +--------+--------+--------+
7505 var table = new Ext.Panel({
7506     title: 'Table Layout',
7507     layout:'table',
7508     defaults: {
7509         // applied to each contained panel
7510         bodyStyle:'padding:20px'
7511     },
7512     layoutConfig: {
7513         // The total column count must be specified here
7514         columns: 3
7515     },
7516     items: [{
7517         html: '&lt;p&gt;Cell A content&lt;/p&gt;',
7518         rowspan: 2
7519     },{
7520         html: '&lt;p&gt;Cell B content&lt;/p&gt;',
7521         colspan: 2
7522     },{
7523         html: '&lt;p&gt;Cell C content&lt;/p&gt;',
7524         cellCls: 'highlight'
7525     },{
7526         html: '&lt;p&gt;Cell D content&lt;/p&gt;'
7527     }]
7528 });
7529 </code></pre>
7530  */
7531 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
7532     /**
7533      * @cfg {Number} columns
7534      * The total number of columns to create in the table for this layout.  If not specified, all Components added to
7535      * this layout will be rendered into a single row using one column per Component.
7536      */
7537
7538     // private
7539     monitorResize:false,
7540
7541     type: 'table',
7542
7543     targetCls: 'x-table-layout-ct',
7544
7545     /**
7546      * @cfg {Object} tableAttrs
7547      * <p>An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification
7548      * used to create the layout's <tt>&lt;table&gt;</tt> element. Example:</p><pre><code>
7549 {
7550     xtype: 'panel',
7551     layout: 'table',
7552     layoutConfig: {
7553         tableAttrs: {
7554             style: {
7555                 width: '100%'
7556             }
7557         },
7558         columns: 3
7559     }
7560 }</code></pre>
7561      */
7562     tableAttrs:null,
7563
7564     // private
7565     setContainer : function(ct){
7566         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
7567
7568         this.currentRow = 0;
7569         this.currentColumn = 0;
7570         this.cells = [];
7571     },
7572     
7573     // private
7574     onLayout : function(ct, target){
7575         var cs = ct.items.items, len = cs.length, c, i;
7576
7577         if(!this.table){
7578             target.addClass('x-table-layout-ct');
7579
7580             this.table = target.createChild(
7581                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
7582         }
7583         this.renderAll(ct, target);
7584     },
7585
7586     // private
7587     getRow : function(index){
7588         var row = this.table.tBodies[0].childNodes[index];
7589         if(!row){
7590             row = document.createElement('tr');
7591             this.table.tBodies[0].appendChild(row);
7592         }
7593         return row;
7594     },
7595
7596     // private
7597     getNextCell : function(c){
7598         var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
7599         var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
7600         for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
7601             if(!this.cells[rowIndex]){
7602                 this.cells[rowIndex] = [];
7603             }
7604             for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
7605                 this.cells[rowIndex][colIndex] = true;
7606             }
7607         }
7608         var td = document.createElement('td');
7609         if(c.cellId){
7610             td.id = c.cellId;
7611         }
7612         var cls = 'x-table-layout-cell';
7613         if(c.cellCls){
7614             cls += ' ' + c.cellCls;
7615         }
7616         td.className = cls;
7617         if(c.colspan){
7618             td.colSpan = c.colspan;
7619         }
7620         if(c.rowspan){
7621             td.rowSpan = c.rowspan;
7622         }
7623         this.getRow(curRow).appendChild(td);
7624         return td;
7625     },
7626
7627     // private
7628     getNextNonSpan: function(colIndex, rowIndex){
7629         var cols = this.columns;
7630         while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
7631             if(cols && colIndex >= cols){
7632                 rowIndex++;
7633                 colIndex = 0;
7634             }else{
7635                 colIndex++;
7636             }
7637         }
7638         return [colIndex, rowIndex];
7639     },
7640
7641     // private
7642     renderItem : function(c, position, target){
7643         // Ensure we have our inner table to get cells to render into.
7644         if(!this.table){
7645             this.table = target.createChild(
7646                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
7647         }
7648         if(c && !c.rendered){
7649             c.render(this.getNextCell(c));
7650             this.configureItem(c, position);
7651         }else if(c && !this.isValidParent(c, target)){
7652             var container = this.getNextCell(c);
7653             container.insertBefore(c.getPositionEl().dom, null);
7654             c.container = Ext.get(container);
7655             this.configureItem(c, position);
7656         }
7657     },
7658
7659     // private
7660     isValidParent : function(c, target){
7661         return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);
7662     }
7663
7664     /**
7665      * @property activeItem
7666      * @hide
7667      */
7668 });
7669
7670 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;/**
7671  * @class Ext.layout.AbsoluteLayout
7672  * @extends Ext.layout.AnchorLayout
7673  * <p>This is a layout that inherits the anchoring of <b>{@link Ext.layout.AnchorLayout}</b> and adds the
7674  * ability for x/y positioning using the standard x and y component config options.</p>
7675  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
7676  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
7677  * <p>Example usage:</p>
7678  * <pre><code>
7679 var form = new Ext.form.FormPanel({
7680     title: 'Absolute Layout',
7681     layout:'absolute',
7682     layoutConfig: {
7683         // layout-specific configs go here
7684         extraCls: 'x-abs-layout-item',
7685     },
7686     baseCls: 'x-plain',
7687     url:'save-form.php',
7688     defaultType: 'textfield',
7689     items: [{
7690         x: 0,
7691         y: 5,
7692         xtype:'label',
7693         text: 'Send To:'
7694     },{
7695         x: 60,
7696         y: 0,
7697         name: 'to',
7698         anchor:'100%'  // anchor width by percentage
7699     },{
7700         x: 0,
7701         y: 35,
7702         xtype:'label',
7703         text: 'Subject:'
7704     },{
7705         x: 60,
7706         y: 30,
7707         name: 'subject',
7708         anchor: '100%'  // anchor width by percentage
7709     },{
7710         x:0,
7711         y: 60,
7712         xtype: 'textarea',
7713         name: 'msg',
7714         anchor: '100% 100%'  // anchor width and height
7715     }]
7716 });
7717 </code></pre>
7718  */
7719 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
7720
7721     extraCls: 'x-abs-layout-item',
7722
7723     type: 'absolute',
7724
7725     onLayout : function(ct, target){
7726         target.position();
7727         this.paddingLeft = target.getPadding('l');
7728         this.paddingTop = target.getPadding('t');
7729         Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
7730     },
7731
7732     // private
7733     adjustWidthAnchor : function(value, comp){
7734         return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
7735     },
7736
7737     // private
7738     adjustHeightAnchor : function(value, comp){
7739         return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
7740     }
7741     /**
7742      * @property activeItem
7743      * @hide
7744      */
7745 });
7746 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
7747 /**
7748  * @class Ext.layout.BoxLayout
7749  * @extends Ext.layout.ContainerLayout
7750  * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
7751  */
7752 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
7753     /**
7754      * @cfg {Object} defaultMargins
7755      * <p>If the individual contained items do not have a <tt>margins</tt>
7756      * property specified, the default margins from this property will be
7757      * applied to each item.</p>
7758      * <br><p>This property may be specified as an object containing margins
7759      * to apply in the format:</p><pre><code>
7760 {
7761     top: (top margin),
7762     right: (right margin),
7763     bottom: (bottom margin),
7764     left: (left margin)
7765 }</code></pre>
7766      * <p>This property may also be specified as a string containing
7767      * space-separated, numeric margin values. The order of the sides associated
7768      * with each value matches the way CSS processes margin values:</p>
7769      * <div class="mdetail-params"><ul>
7770      * <li>If there is only one value, it applies to all sides.</li>
7771      * <li>If there are two values, the top and bottom borders are set to the
7772      * first value and the right and left are set to the second.</li>
7773      * <li>If there are three values, the top is set to the first value, the left
7774      * and right are set to the second, and the bottom is set to the third.</li>
7775      * <li>If there are four values, they apply to the top, right, bottom, and
7776      * left, respectively.</li>
7777      * </ul></div>
7778      * <p>Defaults to:</p><pre><code>
7779      * {top:0, right:0, bottom:0, left:0}
7780      * </code></pre>
7781      */
7782     defaultMargins : {left:0,top:0,right:0,bottom:0},
7783     /**
7784      * @cfg {String} padding
7785      * <p>Sets the padding to be applied to all child items managed by this layout.</p>
7786      * <p>This property must be specified as a string containing
7787      * space-separated, numeric padding values. The order of the sides associated
7788      * with each value matches the way CSS processes padding values:</p>
7789      * <div class="mdetail-params"><ul>
7790      * <li>If there is only one value, it applies to all sides.</li>
7791      * <li>If there are two values, the top and bottom borders are set to the
7792      * first value and the right and left are set to the second.</li>
7793      * <li>If there are three values, the top is set to the first value, the left
7794      * and right are set to the second, and the bottom is set to the third.</li>
7795      * <li>If there are four values, they apply to the top, right, bottom, and
7796      * left, respectively.</li>
7797      * </ul></div>
7798      * <p>Defaults to: <code>"0"</code></p>
7799      */
7800     padding : '0',
7801     // documented in subclasses
7802     pack : 'start',
7803
7804     // private
7805     monitorResize : true,
7806     type: 'box',
7807     scrollOffset : 0,
7808     extraCls : 'x-box-item',
7809     targetCls : 'x-box-layout-ct',
7810     innerCls : 'x-box-inner',
7811
7812     constructor : function(config){
7813         Ext.layout.BoxLayout.superclass.constructor.call(this, config);
7814
7815         if (Ext.isString(this.defaultMargins)) {
7816             this.defaultMargins = this.parseMargins(this.defaultMargins);
7817         }
7818     },
7819
7820     /**
7821      * @private
7822      * Runs the child box calculations and caches them in childBoxCache. Subclasses can used these cached values
7823      * when laying out
7824      */
7825     onLayout: function(container, target) {
7826         Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);
7827
7828         var items = this.getVisibleItems(container),
7829             tSize = this.getLayoutTargetSize();
7830
7831         /**
7832          * @private
7833          * @property layoutTargetLastSize
7834          * @type Object
7835          * Private cache of the last measured size of the layout target. This should never be used except by
7836          * BoxLayout subclasses during their onLayout run.
7837          */
7838         this.layoutTargetLastSize = tSize;
7839
7840         /**
7841          * @private
7842          * @property childBoxCache
7843          * @type Array
7844          * Array of the last calculated height, width, top and left positions of each visible rendered component
7845          * within the Box layout.
7846          */
7847         this.childBoxCache = this.calculateChildBoxes(items, tSize);
7848
7849         this.updateInnerCtSize(tSize, this.childBoxCache);
7850         this.updateChildBoxes(this.childBoxCache.boxes);
7851
7852         // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
7853         this.handleTargetOverflow(tSize, container, target);
7854     },
7855
7856     /**
7857      * Resizes and repositions each child component
7858      * @param {Array} boxes The box measurements
7859      */
7860     updateChildBoxes: function(boxes) {
7861         for (var i = 0, length = boxes.length; i < length; i++) {
7862             var box  = boxes[i],
7863                 comp = box.component;
7864
7865             if (box.dirtySize) {
7866                 comp.setSize(box.width, box.height);
7867             }
7868             // Don't set positions to NaN
7869             if (isNaN(box.left) || isNaN(box.top)) {
7870                 continue;
7871             }
7872             comp.setPosition(box.left, box.top);
7873         }
7874     },
7875
7876     /**
7877      * @private
7878      * Called by onRender just before the child components are sized and positioned. This resizes the innerCt
7879      * to make sure all child items fit within it. We call this before sizing the children because if our child
7880      * items are larger than the previous innerCt size the browser will insert scrollbars and then remove them
7881      * again immediately afterwards, giving a performance hit.
7882      * Subclasses should provide an implementation.
7883      * @param {Object} currentSize The current height and width of the innerCt
7884      * @param {Array} calculations The new box calculations of all items to be laid out
7885      */
7886     updateInnerCtSize: Ext.emptyFn,
7887
7888     /**
7889      * @private
7890      * This should be called after onLayout of any BoxLayout subclass. If the target's overflow is not set to 'hidden',
7891      * we need to lay out a second time because the scrollbars may have modified the height and width of the layout
7892      * target. Having a Box layout inside such a target is therefore not recommended.
7893      * @param {Object} previousTargetSize The size and height of the layout target before we just laid out
7894      * @param {Ext.Container} container The container
7895      * @param {Ext.Element} target The target element
7896      */
7897     handleTargetOverflow: function(previousTargetSize, container, target) {
7898         var overflow = target.getStyle('overflow');
7899
7900         if (overflow && overflow != 'hidden' &&!this.adjustmentPass) {
7901             var newTargetSize = this.getLayoutTargetSize();
7902             if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){
7903                 this.adjustmentPass = true;
7904                 this.onLayout(container, target);
7905             }
7906         }
7907
7908         delete this.adjustmentPass;
7909     },
7910
7911     // private
7912     isValidParent : function(c, target){
7913         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
7914     },
7915
7916     /**
7917      * @private
7918      * Returns all items that are both rendered and visible
7919      * @return {Array} All matching items
7920      */
7921     getVisibleItems: function(ct) {
7922         var ct  = ct || this.container,
7923             t   = ct.getLayoutTarget(),
7924             cti = ct.items.items,
7925             len = cti.length,
7926
7927             i, c, items = [];
7928
7929         for (i = 0; i < len; i++) {
7930             if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true  && c.collapsed !== true){
7931                 items.push(c);
7932             }
7933         }
7934
7935         return items;
7936     },
7937
7938     // private
7939     renderAll : function(ct, target){
7940         if(!this.innerCt){
7941             // the innerCt prevents wrapping and shuffling while
7942             // the container is resizing
7943             this.innerCt = target.createChild({cls:this.innerCls});
7944             this.padding = this.parseMargins(this.padding);
7945         }
7946         Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
7947     },
7948
7949     getLayoutTargetSize : function(){
7950         var target = this.container.getLayoutTarget(), ret;
7951         if (target) {
7952             ret = target.getViewSize();
7953
7954             // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
7955             // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
7956             // with getViewSize
7957             if (Ext.isIE && Ext.isStrict && ret.width == 0){
7958                 ret =  target.getStyleSize();
7959             }
7960
7961             ret.width -= target.getPadding('lr');
7962             ret.height -= target.getPadding('tb');
7963         }
7964         return ret;
7965     },
7966
7967     // private
7968     renderItem : function(c){
7969         if(Ext.isString(c.margins)){
7970             c.margins = this.parseMargins(c.margins);
7971         }else if(!c.margins){
7972             c.margins = this.defaultMargins;
7973         }
7974         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
7975     }
7976 });
7977
7978 /**
7979  * @class Ext.layout.VBoxLayout
7980  * @extends Ext.layout.BoxLayout
7981  * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical
7982  * space between child items containing a numeric <code>flex</code> configuration.</p>
7983  * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option.
7984  */
7985 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
7986     /**
7987      * @cfg {String} align
7988      * Controls how the child items of the container are aligned. Acceptable configuration values for this
7989      * property are:
7990      * <div class="mdetail-params"><ul>
7991      * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally
7992      * at the <b>left</b> side of the container</div></li>
7993      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the
7994      * <b>mid-width</b> of the container</div></li>
7995      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill
7996      * the width of the container</div></li>
7997      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to
7998      * the size of the largest item.</div></li>
7999      * </ul></div>
8000      */
8001     align : 'left', // left, center, stretch, strechmax
8002     type: 'vbox',
8003
8004     /**
8005      * @cfg {String} pack
8006      * Controls how the child items of the container are packed together. Acceptable configuration values
8007      * for this property are:
8008      * <div class="mdetail-params"><ul>
8009      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
8010      * <b>top</b> side of container</div></li>
8011      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
8012      * <b>mid-height</b> of container</div></li>
8013      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>
8014      * side of container</div></li>
8015      * </ul></div>
8016      */
8017
8018     /**
8019      * @cfg {Number} flex
8020      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
8021      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>
8022      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
8023      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
8024      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
8025      */
8026
8027     /**
8028      * @private
8029      * See parent documentation
8030      */
8031     updateInnerCtSize: function(tSize, calcs) {
8032         var innerCtHeight = tSize.height,
8033             innerCtWidth  = calcs.meta.maxWidth + this.padding.left + this.padding.right;
8034
8035         if (this.align == 'stretch') {
8036             innerCtWidth = tSize.width;
8037         } else if (this.align == 'center') {
8038             innerCtWidth = Math.max(tSize.width, innerCtWidth);
8039         }
8040
8041         //we set the innerCt size first because if our child items are larger than the previous innerCt size
8042         //the browser will insert scrollbars and then remove them again immediately afterwards
8043         this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
8044     },
8045
8046     /**
8047      * @private
8048      * Calculates the size and positioning of each item in the VBox. This iterates over all of the rendered,
8049      * visible items and returns a height, width, top and left for each, as well as a reference to each. Also
8050      * returns meta data such as maxHeight which are useful when resizing layout wrappers such as this.innerCt.
8051      * @param {Array} visibleItems The array of all rendered, visible items to be calculated for
8052      * @param {Object} targetSize Object containing target size and height
8053      * @return {Object} Object containing box measurements for each child, plus meta data
8054      */
8055     calculateChildBoxes: function(visibleItems, targetSize) {
8056         var visibleCount = visibleItems.length,
8057
8058             padding      = this.padding,
8059             topOffset    = padding.top,
8060             leftOffset   = padding.left,
8061             paddingVert  = topOffset  + padding.bottom,
8062             paddingHoriz = leftOffset + padding.right,
8063
8064             width        = targetSize.width - this.scrollOffset,
8065             height       = targetSize.height,
8066             availWidth   = Math.max(0, width - paddingHoriz),
8067
8068             isStart      = this.pack == 'start',
8069             isCenter     = this.pack == 'center',
8070             isEnd        = this.pack == 'end',
8071
8072             nonFlexHeight= 0,
8073             maxWidth     = 0,
8074             totalFlex    = 0,
8075
8076             //used to cache the calculated size and position values for each child item
8077             boxes        = [],
8078
8079             //used in the for loops below, just declared here for brevity
8080             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedHeight, horizMargins, stretchWidth;
8081
8082             //gather the total flex of all flexed items and the width taken up by fixed width items
8083             for (i = 0; i < visibleCount; i++) {
8084                 child = visibleItems[i];
8085                 childHeight = child.height;
8086                 childWidth  = child.width;
8087                 canLayout   = !child.hasLayout && Ext.isFunction(child.doLayout);
8088
8089
8090                 // Static height (numeric) requires no calcs
8091                 if (!Ext.isNumber(childHeight)) {
8092
8093                     // flex and not 'auto' height
8094                     if (child.flex && !childHeight) {
8095                         totalFlex += child.flex;
8096
8097                     // Not flexed or 'auto' height or undefined height
8098                     } else {
8099                         //Render and layout sub-containers without a flex or width defined, as otherwise we
8100                         //don't know how wide the sub-container should be and cannot calculate flexed widths
8101                         if (!childHeight && canLayout) {
8102                             child.doLayout();
8103                         }
8104
8105                         childSize = child.getSize();
8106                         childWidth = childSize.width;
8107                         childHeight = childSize.height;
8108                     }
8109                 }
8110
8111                 childMargins = child.margins;
8112
8113                 nonFlexHeight += (childHeight || 0) + childMargins.top + childMargins.bottom;
8114
8115                 // Max width for align - force layout of non-layed out subcontainers without a numeric width
8116                 if (!Ext.isNumber(childWidth)) {
8117                     if (canLayout) {
8118                         child.doLayout();
8119                     }
8120                     childWidth = child.getWidth();
8121                 }
8122
8123                 maxWidth = Math.max(maxWidth, childWidth + childMargins.left + childMargins.right);
8124
8125                 //cache the size of each child component
8126                 boxes.push({
8127                     component: child,
8128                     height   : childHeight || undefined,
8129                     width    : childWidth || undefined
8130                 });
8131             }
8132
8133             //the height available to the flexed items
8134             var availableHeight = Math.max(0, (height - nonFlexHeight - paddingVert));
8135
8136             if (isCenter) {
8137                 topOffset += availableHeight / 2;
8138             } else if (isEnd) {
8139                 topOffset += availableHeight;
8140             }
8141
8142             //temporary variables used in the flex height calculations below
8143             var remainingHeight = availableHeight,
8144                 remainingFlex   = totalFlex;
8145
8146             //calculate the height of each flexed item, and the left + top positions of every item
8147             for (i = 0; i < visibleCount; i++) {
8148                 child = visibleItems[i];
8149                 calcs = boxes[i];
8150
8151                 childMargins = child.margins;
8152                 horizMargins = childMargins.left + childMargins.right;
8153
8154                 topOffset   += childMargins.top;
8155
8156                 if (isStart && child.flex && !child.height) {
8157                     flexedHeight     = Math.ceil((child.flex / remainingFlex) * remainingHeight);
8158                     remainingHeight -= flexedHeight;
8159                     remainingFlex   -= child.flex;
8160
8161                     calcs.height = flexedHeight;
8162                     calcs.dirtySize = true;
8163                 }
8164
8165                 calcs.left = leftOffset + childMargins.left;
8166                 calcs.top  = topOffset;
8167
8168                 switch (this.align) {
8169                     case 'stretch':
8170                         stretchWidth = availWidth - horizMargins;
8171                         calcs.width  = stretchWidth.constrain(child.minHeight || 0, child.maxWidth || 1000000);
8172                         calcs.dirtySize = true;
8173                         break;
8174                     case 'stretchmax':
8175                         stretchWidth = maxWidth - horizMargins;
8176                         calcs.width  = stretchWidth.constrain(child.minHeight || 0, child.maxWidth || 1000000);
8177                         calcs.dirtySize = true;
8178                         break;
8179                     case 'center':
8180                         var diff = availWidth - calcs.width - horizMargins;
8181                         if (diff > 0) {
8182                             calcs.left = leftOffset + horizMargins + (diff / 2);
8183                         }
8184                 }
8185
8186                 topOffset += calcs.height + childMargins.bottom;
8187             }
8188
8189         return {
8190             boxes: boxes,
8191             meta : {
8192                 maxWidth: maxWidth
8193             }
8194         };
8195     }
8196 });
8197
8198 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
8199
8200 /**
8201  * @class Ext.layout.HBoxLayout
8202  * @extends Ext.layout.BoxLayout
8203  * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal
8204  * space between child items containing a numeric <code>flex</code> configuration.</p>
8205  * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option.
8206  */
8207 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
8208     /**
8209      * @cfg {String} align
8210      * Controls how the child items of the container are aligned. Acceptable configuration values for this
8211      * property are:
8212      * <div class="mdetail-params"><ul>
8213      * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically
8214      * at the <b>top</b> of the container</div></li>
8215      * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically in the
8216      * <b>middle</b> of the container</div></li>
8217      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill
8218      * the height of the container</div></li>
8219      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to
8220      * the height of the largest item.</div></li>
8221      */
8222     align: 'top', // top, middle, stretch, strechmax
8223
8224     type : 'hbox',
8225
8226     /**
8227      * @private
8228      * See parent documentation
8229      */
8230     updateInnerCtSize: function(tSize, calcs) {
8231         var innerCtWidth  = tSize.width,
8232             innerCtHeight = calcs.meta.maxHeight + this.padding.top + this.padding.bottom;
8233
8234         if (this.align == 'stretch') {
8235             innerCtHeight = tSize.height;
8236         } else if (this.align == 'middle') {
8237             innerCtHeight = Math.max(tSize.height, innerCtHeight);
8238         }
8239
8240         this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
8241     },
8242
8243     /**
8244      * @cfg {String} pack
8245      * Controls how the child items of the container are packed together. Acceptable configuration values
8246      * for this property are:
8247      * <div class="mdetail-params"><ul>
8248      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
8249      * <b>left</b> side of container</div></li>
8250      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
8251      * <b>mid-width</b> of container</div></li>
8252      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>
8253      * side of container</div></li>
8254      * </ul></div>
8255      */
8256     /**
8257      * @cfg {Number} flex
8258      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
8259      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>
8260      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
8261      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
8262      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
8263      */
8264
8265     /**
8266      * @private
8267      * Calculates the size and positioning of each item in the HBox. This iterates over all of the rendered,
8268      * visible items and returns a height, width, top and left for each, as well as a reference to each. Also
8269      * returns meta data such as maxHeight which are useful when resizing layout wrappers such as this.innerCt.
8270      * @param {Array} visibleItems The array of all rendered, visible items to be calculated for
8271      * @param {Object} targetSize Object containing target size and height
8272      * @return {Object} Object containing box measurements for each child, plus meta data
8273      */
8274     calculateChildBoxes: function(visibleItems, targetSize) {
8275         var visibleCount = visibleItems.length,
8276
8277             padding      = this.padding,
8278             topOffset    = padding.top,
8279             leftOffset   = padding.left,
8280             paddingVert  = topOffset  + padding.bottom,
8281             paddingHoriz = leftOffset + padding.right,
8282
8283             width        = targetSize.width - this.scrollOffset,
8284             height       = targetSize.height,
8285             availHeight  = Math.max(0, height - paddingVert),
8286
8287             isStart      = this.pack == 'start',
8288             isCenter     = this.pack == 'center',
8289             isEnd        = this.pack == 'end',
8290             // isRestore    = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
8291
8292             nonFlexWidth = 0,
8293             maxHeight    = 0,
8294             totalFlex    = 0,
8295
8296             //used to cache the calculated size and position values for each child item
8297             boxes        = [],
8298
8299             //used in the for loops below, just declared here for brevity
8300             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, vertMargins, stretchHeight;
8301
8302             //gather the total flex of all flexed items and the width taken up by fixed width items
8303             for (i = 0; i < visibleCount; i++) {
8304                 child       = visibleItems[i];
8305                 childHeight = child.height;
8306                 childWidth  = child.width;
8307                 canLayout   = !child.hasLayout && Ext.isFunction(child.doLayout);
8308
8309                 // Static width (numeric) requires no calcs
8310                 if (!Ext.isNumber(childWidth)) {
8311
8312                     // flex and not 'auto' width
8313                     if (child.flex && !childWidth) {
8314                         totalFlex += child.flex;
8315
8316                     // Not flexed or 'auto' width or undefined width
8317                     } else {
8318                         //Render and layout sub-containers without a flex or width defined, as otherwise we
8319                         //don't know how wide the sub-container should be and cannot calculate flexed widths
8320                         if (!childWidth && canLayout) {
8321                             child.doLayout();
8322                         }
8323
8324                         childSize   = child.getSize();
8325                         childWidth  = childSize.width;
8326                         childHeight = childSize.height;
8327                     }
8328                 }
8329
8330                 childMargins = child.margins;
8331
8332                 nonFlexWidth += (childWidth || 0) + childMargins.left + childMargins.right;
8333
8334                 // Max height for align - force layout of non-layed out subcontainers without a numeric height
8335                 if (!Ext.isNumber(childHeight)) {
8336                     if (canLayout) {
8337                         child.doLayout();
8338                     }
8339                     childHeight = child.getHeight();
8340                 }
8341
8342                 maxHeight = Math.max(maxHeight, childHeight + childMargins.top + childMargins.bottom);
8343
8344                 //cache the size of each child component
8345                 boxes.push({
8346                     component: child,
8347                     height   : childHeight || undefined,
8348                     width    : childWidth || undefined
8349                 });
8350             }
8351
8352             //the width available to the flexed items
8353             var availableWidth = Math.max(0, (width - nonFlexWidth - paddingHoriz));
8354
8355             if (isCenter) {
8356                 leftOffset += availableWidth / 2;
8357             } else if (isEnd) {
8358                 leftOffset += availableWidth;
8359             }
8360
8361             //temporary variables used in the flex width calculations below
8362             var remainingWidth = availableWidth,
8363                 remainingFlex  = totalFlex;
8364
8365             //calculate the widths of each flexed item, and the left + top positions of every item
8366             for (i = 0; i < visibleCount; i++) {
8367                 child = visibleItems[i];
8368                 calcs = boxes[i];
8369
8370                 childMargins = child.margins;
8371                 vertMargins  = childMargins.top + childMargins.bottom;
8372
8373                 leftOffset  += childMargins.left;
8374
8375                 if (isStart && child.flex && !child.width) {
8376                     flexedWidth     = Math.ceil((child.flex / remainingFlex) * remainingWidth);
8377                     remainingWidth -= flexedWidth;
8378                     remainingFlex  -= child.flex;
8379
8380                     calcs.width = flexedWidth;
8381                     calcs.dirtySize = true;
8382                 }
8383
8384                 calcs.left = leftOffset;
8385                 calcs.top  = topOffset + childMargins.top;
8386
8387                 switch (this.align) {
8388                     case 'stretch':
8389                         stretchHeight = availHeight - vertMargins;
8390                         calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
8391                         calcs.dirtySize = true;
8392                         break;
8393                     case 'stretchmax':
8394                         stretchHeight = maxHeight - vertMargins;
8395                         calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
8396                         calcs.dirtySize = true;
8397                         break;
8398                     case 'middle':
8399                         var diff = availHeight - calcs.height - vertMargins;
8400                         if (diff > 0) {
8401                             calcs.top = topOffset + vertMargins + (diff / 2);
8402                         }
8403                 }
8404                 leftOffset += calcs.width + childMargins.right;
8405             }
8406
8407         return {
8408             boxes: boxes,
8409             meta : {
8410                 maxHeight: maxHeight
8411             }
8412         };
8413     }
8414 });
8415
8416 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
8417 /**
8418  * @class Ext.layout.ToolbarLayout
8419  * @extends Ext.layout.ContainerLayout
8420  * Layout manager used by Ext.Toolbar. This is highly specialised for use by Toolbars and would not
8421  * usually be used by any other class.
8422  */
8423 Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
8424     monitorResize : true,
8425
8426     type: 'toolbar',
8427
8428     /**
8429      * @property triggerWidth
8430      * @type Number
8431      * The width allocated for the menu trigger at the extreme right end of the Toolbar
8432      */
8433     triggerWidth: 18,
8434
8435     /**
8436      * @property noItemsMenuText
8437      * @type String
8438      * HTML fragment to render into the toolbar overflow menu if there are no items to display
8439      */
8440     noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
8441
8442     /**
8443      * @private
8444      * @property lastOverflow
8445      * @type Boolean
8446      * Used internally to record whether the last layout caused an overflow or not
8447      */
8448     lastOverflow: false,
8449
8450     /**
8451      * @private
8452      * @property tableHTML
8453      * @type String
8454      * String used to build the HTML injected to support the Toolbar's layout. The align property is
8455      * injected into this string inside the td.x-toolbar-left element during onLayout.
8456      */
8457     tableHTML: [
8458         '<table cellspacing="0" class="x-toolbar-ct">',
8459             '<tbody>',
8460                 '<tr>',
8461                     '<td class="x-toolbar-left" align="{0}">',
8462                         '<table cellspacing="0">',
8463                             '<tbody>',
8464                                 '<tr class="x-toolbar-left-row"></tr>',
8465                             '</tbody>',
8466                         '</table>',
8467                     '</td>',
8468                     '<td class="x-toolbar-right" align="right">',
8469                         '<table cellspacing="0" class="x-toolbar-right-ct">',
8470                             '<tbody>',
8471                                 '<tr>',
8472                                     '<td>',
8473                                         '<table cellspacing="0">',
8474                                             '<tbody>',
8475                                                 '<tr class="x-toolbar-right-row"></tr>',
8476                                             '</tbody>',
8477                                         '</table>',
8478                                     '</td>',
8479                                     '<td>',
8480                                         '<table cellspacing="0">',
8481                                             '<tbody>',
8482                                                 '<tr class="x-toolbar-extras-row"></tr>',
8483                                             '</tbody>',
8484                                         '</table>',
8485                                     '</td>',
8486                                 '</tr>',
8487                             '</tbody>',
8488                         '</table>',
8489                     '</td>',
8490                 '</tr>',
8491             '</tbody>',
8492         '</table>'
8493     ].join(""),
8494
8495     /**
8496      * @private
8497      * Create the wrapping Toolbar HTML and render/move all the items into the correct places
8498      */
8499     onLayout : function(ct, target) {
8500         //render the Toolbar <table> HTML if it's not already present
8501         if (!this.leftTr) {
8502             var align = ct.buttonAlign == 'center' ? 'center' : 'left';
8503
8504             target.addClass('x-toolbar-layout-ct');
8505             target.insertHtml('beforeEnd', String.format(this.tableHTML, align));
8506
8507             this.leftTr   = target.child('tr.x-toolbar-left-row', true);
8508             this.rightTr  = target.child('tr.x-toolbar-right-row', true);
8509             this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
8510
8511             if (this.hiddenItem == undefined) {
8512                 /**
8513                  * @property hiddenItems
8514                  * @type Array
8515                  * Holds all items that are currently hidden due to there not being enough space to render them
8516                  * These items will appear on the expand menu.
8517                  */
8518                 this.hiddenItems = [];
8519             }
8520         }
8521
8522         var side     = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
8523             items    = ct.items.items,
8524             position = 0;
8525
8526         //render each item if not already rendered, place it into the correct (left or right) target
8527         for (var i = 0, len = items.length, c; i < len; i++, position++) {
8528             c = items[i];
8529
8530             if (c.isFill) {
8531                 side   = this.rightTr;
8532                 position = -1;
8533             } else if (!c.rendered) {
8534                 c.render(this.insertCell(c, side, position));
8535             } else {
8536                 if (!c.xtbHidden && !this.isValidParent(c, side.childNodes[position])) {
8537                     var td = this.insertCell(c, side, position);
8538                     td.appendChild(c.getPositionEl().dom);
8539                     c.container = Ext.get(td);
8540                 }
8541             }
8542         }
8543
8544         //strip extra empty cells
8545         this.cleanup(this.leftTr);
8546         this.cleanup(this.rightTr);
8547         this.cleanup(this.extrasTr);
8548         this.fitToSize(target);
8549     },
8550
8551     /**
8552      * @private
8553      * Removes any empty nodes from the given element
8554      * @param {Ext.Element} el The element to clean up
8555      */
8556     cleanup : function(el) {
8557         var cn = el.childNodes, i, c;
8558
8559         for (i = cn.length-1; i >= 0 && (c = cn[i]); i--) {
8560             if (!c.firstChild) {
8561                 el.removeChild(c);
8562             }
8563         }
8564     },
8565
8566     /**
8567      * @private
8568      * Inserts the given Toolbar item into the given element
8569      * @param {Ext.Component} c The component to add
8570      * @param {Ext.Element} target The target to add the component to
8571      * @param {Number} position The position to add the component at
8572      */
8573     insertCell : function(c, target, position) {
8574         var td = document.createElement('td');
8575         td.className = 'x-toolbar-cell';
8576
8577         target.insertBefore(td, target.childNodes[position] || null);
8578
8579         return td;
8580     },
8581
8582     /**
8583      * @private
8584      * Hides an item because it will not fit in the available width. The item will be unhidden again
8585      * if the Toolbar is resized to be large enough to show it
8586      * @param {Ext.Component} item The item to hide
8587      */
8588     hideItem : function(item) {
8589         this.hiddenItems.push(item);
8590
8591         item.xtbHidden = true;
8592         item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
8593         item.hide();
8594     },
8595
8596     /**
8597      * @private
8598      * Unhides an item that was previously hidden due to there not being enough space left on the Toolbar
8599      * @param {Ext.Component} item The item to show
8600      */
8601     unhideItem : function(item) {
8602         item.show();
8603         item.xtbHidden = false;
8604         this.hiddenItems.remove(item);
8605     },
8606
8607     /**
8608      * @private
8609      * Returns the width of the given toolbar item. If the item is currently hidden because there
8610      * is not enough room to render it, its previous width is returned
8611      * @param {Ext.Component} c The component to measure
8612      * @return {Number} The width of the item
8613      */
8614     getItemWidth : function(c) {
8615         return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
8616     },
8617
8618     /**
8619      * @private
8620      * Called at the end of onLayout. At this point the Toolbar has already been resized, so we need
8621      * to fit the items into the available width. We add up the width required by all of the items in
8622      * the toolbar - if we don't have enough space we hide the extra items and render the expand menu
8623      * trigger.
8624      * @param {Ext.Element} target The Element the Toolbar is currently laid out within
8625      */
8626     fitToSize : function(target) {
8627         if (this.container.enableOverflow === false) {
8628             return;
8629         }
8630
8631         var width       = target.dom.clientWidth,
8632             tableWidth  = target.dom.firstChild.offsetWidth,
8633             clipWidth   = width - this.triggerWidth,
8634             lastWidth   = this.lastWidth || 0,
8635
8636             hiddenItems = this.hiddenItems,
8637             hasHiddens  = hiddenItems.length != 0,
8638             isLarger    = width >= lastWidth;
8639
8640         this.lastWidth  = width;
8641
8642         if (tableWidth > width || (hasHiddens && isLarger)) {
8643             var items     = this.container.items.items,
8644                 len       = items.length,
8645                 loopWidth = 0,
8646                 item;
8647
8648             for (var i = 0; i < len; i++) {
8649                 item = items[i];
8650
8651                 if (!item.isFill) {
8652                     loopWidth += this.getItemWidth(item);
8653                     if (loopWidth > clipWidth) {
8654                         if (!(item.hidden || item.xtbHidden)) {
8655                             this.hideItem(item);
8656                         }
8657                     } else if (item.xtbHidden) {
8658                         this.unhideItem(item);
8659                     }
8660                 }
8661             }
8662         }
8663
8664         //test for number of hidden items again here because they may have changed above
8665         hasHiddens = hiddenItems.length != 0;
8666
8667         if (hasHiddens) {
8668             this.initMore();
8669
8670             if (!this.lastOverflow) {
8671                 this.container.fireEvent('overflowchange', this.container, true);
8672                 this.lastOverflow = true;
8673             }
8674         } else if (this.more) {
8675             this.clearMenu();
8676             this.more.destroy();
8677             delete this.more;
8678
8679             if (this.lastOverflow) {
8680                 this.container.fireEvent('overflowchange', this.container, false);
8681                 this.lastOverflow = false;
8682             }
8683         }
8684     },
8685
8686     /**
8687      * @private
8688      * Returns a menu config for a given component. This config is used to create a menu item
8689      * to be added to the expander menu
8690      * @param {Ext.Component} component The component to create the config for
8691      * @param {Boolean} hideOnClick Passed through to the menu item
8692      */
8693     createMenuConfig : function(component, hideOnClick){
8694         var config = Ext.apply({}, component.initialConfig),
8695             group  = component.toggleGroup;
8696
8697         Ext.copyTo(config, component, [
8698             'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
8699         ]);
8700
8701         Ext.apply(config, {
8702             text       : component.overflowText || component.text,
8703             hideOnClick: hideOnClick
8704         });
8705
8706         if (group || component.enableToggle) {
8707             Ext.apply(config, {
8708                 group  : group,
8709                 checked: component.pressed,
8710                 listeners: {
8711                     checkchange: function(item, checked){
8712                         component.toggle(checked);
8713                     }
8714                 }
8715             });
8716         }
8717
8718         delete config.ownerCt;
8719         delete config.xtype;
8720         delete config.id;
8721
8722         return config;
8723     },
8724
8725     /**
8726      * @private
8727      * Adds the given Toolbar item to the given menu. Buttons inside a buttongroup are added individually.
8728      * @param {Ext.menu.Menu} menu The menu to add to
8729      * @param {Ext.Component} component The component to add
8730      */
8731     addComponentToMenu : function(menu, component) {
8732         if (component instanceof Ext.Toolbar.Separator) {
8733             menu.add('-');
8734
8735         } else if (Ext.isFunction(component.isXType)) {
8736             if (component.isXType('splitbutton')) {
8737                 menu.add(this.createMenuConfig(component, true));
8738
8739             } else if (component.isXType('button')) {
8740                 menu.add(this.createMenuConfig(component, !component.menu));
8741
8742             } else if (component.isXType('buttongroup')) {
8743                 component.items.each(function(item){
8744                      this.addComponentToMenu(menu, item);
8745                 }, this);
8746             }
8747         }
8748     },
8749
8750     /**
8751      * @private
8752      * Deletes the sub-menu of each item in the expander menu. Submenus are created for items such as
8753      * splitbuttons and buttongroups, where the Toolbar item cannot be represented by a single menu item
8754      */
8755     clearMenu : function(){
8756         var menu = this.moreMenu;
8757         if (menu && menu.items) {
8758             menu.items.each(function(item){
8759                 delete item.menu;
8760             });
8761         }
8762     },
8763
8764     /**
8765      * @private
8766      * Called before the expand menu is shown, this rebuilds the menu since it was last shown because
8767      * it is possible that the items hidden due to space limitations on the Toolbar have changed since.
8768      * @param {Ext.menu.Menu} m The menu
8769      */
8770     beforeMoreShow : function(menu) {
8771         var items = this.container.items.items,
8772             len   = items.length,
8773             item,
8774             prev;
8775
8776         var needsSep = function(group, item){
8777             return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
8778         };
8779
8780         this.clearMenu();
8781         menu.removeAll();
8782         for (var i = 0; i < len; i++) {
8783             item = items[i];
8784             if (item.xtbHidden) {
8785                 if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
8786                     menu.add('-');
8787                 }
8788                 this.addComponentToMenu(menu, item);
8789                 prev = item;
8790             }
8791         }
8792
8793         // put something so the menu isn't empty if no compatible items found
8794         if (menu.items.length < 1) {
8795             menu.add(this.noItemsMenuText);
8796         }
8797     },
8798
8799     /**
8800      * @private
8801      * Creates the expand trigger and menu, adding them to the <tr> at the extreme right of the
8802      * Toolbar table
8803      */
8804     initMore : function(){
8805         if (!this.more) {
8806             /**
8807              * @private
8808              * @property moreMenu
8809              * @type Ext.menu.Menu
8810              * The expand menu - holds items for every Toolbar item that cannot be shown
8811              * because the Toolbar is currently not wide enough.
8812              */
8813             this.moreMenu = new Ext.menu.Menu({
8814                 ownerCt : this.container,
8815                 listeners: {
8816                     beforeshow: this.beforeMoreShow,
8817                     scope: this
8818                 }
8819             });
8820
8821             /**
8822              * @private
8823              * @property more
8824              * @type Ext.Button
8825              * The expand button which triggers the overflow menu to be shown
8826              */
8827             this.more = new Ext.Button({
8828                 iconCls: 'x-toolbar-more-icon',
8829                 cls    : 'x-toolbar-more',
8830                 menu   : this.moreMenu,
8831                 ownerCt: this.container
8832             });
8833
8834             var td = this.insertCell(this.more, this.extrasTr, 100);
8835             this.more.render(td);
8836         }
8837     },
8838
8839     destroy : function(){
8840         Ext.destroy(this.more, this.moreMenu);
8841         delete this.leftTr;
8842         delete this.rightTr;
8843         delete this.extrasTr;
8844         Ext.layout.ToolbarLayout.superclass.destroy.call(this);
8845     }
8846 });
8847
8848 Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;
8849 /**
8850  * @class Ext.layout.MenuLayout
8851  * @extends Ext.layout.ContainerLayout
8852  * <p>Layout manager used by {@link Ext.menu.Menu}. Generally this class should not need to be used directly.</p>
8853  */
8854  Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
8855     monitorResize : true,
8856
8857     type: 'menu',
8858
8859     setContainer : function(ct){
8860         this.monitorResize = !ct.floating;
8861         // This event is only fired by the menu in IE, used so we don't couple
8862         // the menu with the layout.
8863         ct.on('autosize', this.doAutoSize, this);
8864         Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
8865     },
8866
8867     renderItem : function(c, position, target){
8868         if (!this.itemTpl) {
8869             this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
8870                 '<li id="{itemId}" class="{itemCls}">',
8871                     '<tpl if="needsIcon">',
8872                         '<img src="{icon}" class="{iconCls}"/>',
8873                     '</tpl>',
8874                 '</li>'
8875             );
8876         }
8877
8878         if(c && !c.rendered){
8879             if(Ext.isNumber(position)){
8880                 position = target.dom.childNodes[position];
8881             }
8882             var a = this.getItemArgs(c);
8883
8884 //          The Component's positionEl is the <li> it is rendered into
8885             c.render(c.positionEl = position ?
8886                 this.itemTpl.insertBefore(position, a, true) :
8887                 this.itemTpl.append(target, a, true));
8888
8889 //          Link the containing <li> to the item.
8890             c.positionEl.menuItemId = c.getItemId();
8891
8892 //          If rendering a regular Component, and it needs an icon,
8893 //          move the Component rightwards.
8894             if (!a.isMenuItem && a.needsIcon) {
8895                 c.positionEl.addClass('x-menu-list-item-indent');
8896             }
8897             this.configureItem(c, position);
8898         }else if(c && !this.isValidParent(c, target)){
8899             if(Ext.isNumber(position)){
8900                 position = target.dom.childNodes[position];
8901             }
8902             target.dom.insertBefore(c.getActionEl().dom, position || null);
8903         }
8904     },
8905
8906     getItemArgs : function(c) {
8907         var isMenuItem = c instanceof Ext.menu.Item;
8908         return {
8909             isMenuItem: isMenuItem,
8910             needsIcon: !isMenuItem && (c.icon || c.iconCls),
8911             icon: c.icon || Ext.BLANK_IMAGE_URL,
8912             iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
8913             itemId: 'x-menu-el-' + c.id,
8914             itemCls: 'x-menu-list-item '
8915         };
8916     },
8917
8918     //  Valid if the Component is in a <li> which is part of our target <ul>
8919     isValidParent : function(c, target) {
8920         return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
8921     },
8922
8923     onLayout : function(ct, target){
8924         Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
8925         this.doAutoSize();
8926     },
8927
8928     doAutoSize : function(){
8929         var ct = this.container, w = ct.width;
8930         if(ct.floating){
8931             if(w){
8932                 ct.setWidth(w);
8933             }else if(Ext.isIE){
8934                 ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
8935                 var el = ct.getEl(), t = el.dom.offsetWidth; // force recalc
8936                 ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
8937             }
8938         }
8939     }
8940 });
8941 Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;
8942 /**
8943  * @class Ext.Viewport
8944  * @extends Ext.Container
8945  * <p>A specialized container representing the viewable application area (the browser viewport).</p>
8946  * <p>The Viewport renders itself to the document body, and automatically sizes itself to the size of
8947  * the browser viewport and manages window resizing. There may only be one Viewport created
8948  * in a page. Inner layouts are available by virtue of the fact that all {@link Ext.Panel Panel}s
8949  * added to the Viewport, either through its {@link #items}, or through the items, or the {@link #add}
8950  * method of any of its child Panels may themselves have a layout.</p>
8951  * <p>The Viewport does not provide scrolling, so child Panels within the Viewport should provide
8952  * for scrolling if needed using the {@link #autoScroll} config.</p>
8953  * <p>An example showing a classic application border layout:</p><pre><code>
8954 new Ext.Viewport({
8955     layout: 'border',
8956     items: [{
8957         region: 'north',
8958         html: '&lt;h1 class="x-panel-header">Page Title&lt;/h1>',
8959         autoHeight: true,
8960         border: false,
8961         margins: '0 0 5 0'
8962     }, {
8963         region: 'west',
8964         collapsible: true,
8965         title: 'Navigation',
8966         width: 200
8967         // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout}
8968     }, {
8969         region: 'south',
8970         title: 'Title for Panel',
8971         collapsible: true,
8972         html: 'Information goes here',
8973         split: true,
8974         height: 100,
8975         minHeight: 100
8976     }, {
8977         region: 'east',
8978         title: 'Title for the Grid Panel',
8979         collapsible: true,
8980         split: true,
8981         width: 200,
8982         xtype: 'grid',
8983         // remaining grid configuration not shown ...
8984         // notice that the GridPanel is added directly as the region
8985         // it is not "overnested" inside another Panel
8986     }, {
8987         region: 'center',
8988         xtype: 'tabpanel', // TabPanel itself has no title
8989         items: {
8990             title: 'Default Tab',
8991             html: 'The first tab\'s content. Others may be added dynamically'
8992         }
8993     }]
8994 });
8995 </code></pre>
8996  * @constructor
8997  * Create a new Viewport
8998  * @param {Object} config The config object
8999  * @xtype viewport
9000  */
9001 Ext.Viewport = Ext.extend(Ext.Container, {
9002     /*
9003      * Privatize config options which, if used, would interfere with the
9004      * correct operation of the Viewport as the sole manager of the
9005      * layout of the document body.
9006      */
9007     /**
9008      * @cfg {Mixed} applyTo @hide
9009      */
9010     /**
9011      * @cfg {Boolean} allowDomMove @hide
9012      */
9013     /**
9014      * @cfg {Boolean} hideParent @hide
9015      */
9016     /**
9017      * @cfg {Mixed} renderTo @hide
9018      */
9019     /**
9020      * @cfg {Boolean} hideParent @hide
9021      */
9022     /**
9023      * @cfg {Number} height @hide
9024      */
9025     /**
9026      * @cfg {Number} width @hide
9027      */
9028     /**
9029      * @cfg {Boolean} autoHeight @hide
9030      */
9031     /**
9032      * @cfg {Boolean} autoWidth @hide
9033      */
9034     /**
9035      * @cfg {Boolean} deferHeight @hide
9036      */
9037     /**
9038      * @cfg {Boolean} monitorResize @hide
9039      */
9040
9041     initComponent : function() {
9042         Ext.Viewport.superclass.initComponent.call(this);
9043         document.getElementsByTagName('html')[0].className += ' x-viewport';
9044         this.el = Ext.getBody();
9045         this.el.setHeight = Ext.emptyFn;
9046         this.el.setWidth = Ext.emptyFn;
9047         this.el.setSize = Ext.emptyFn;
9048         this.el.dom.scroll = 'no';
9049         this.allowDomMove = false;
9050         this.autoWidth = true;
9051         this.autoHeight = true;
9052         Ext.EventManager.onWindowResize(this.fireResize, this);
9053         this.renderTo = this.el;
9054     },
9055
9056     fireResize : function(w, h){
9057         this.fireEvent('resize', this, w, h, w, h);
9058     }
9059 });
9060 Ext.reg('viewport', Ext.Viewport);
9061 /**
9062  * @class Ext.Panel
9063  * @extends Ext.Container
9064  * <p>Panel is a container that has specific functionality and structural components that make
9065  * it the perfect building block for application-oriented user interfaces.</p>
9066  * <p>Panels are, by virtue of their inheritance from {@link Ext.Container}, capable
9067  * of being configured with a {@link Ext.Container#layout layout}, and containing child Components.</p>
9068  * <p>When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.Container#add adding} Components
9069  * to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether
9070  * 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
9071  * default, Panels use the {@link Ext.layout.ContainerLayout ContainerLayout} scheme. This simply renders
9072  * child components, appending them one after the other inside the Container, and <b>does not apply any sizing</b>
9073  * at all.</p>
9074  * <p>A Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate
9075  * {@link #header}, {@link #footer} and {@link #body} sections (see {@link #frame} for additional
9076  * information).</p>
9077  * <p>Panel also provides built-in {@link #collapsible expandable and collapsible behavior}, along with
9078  * a variety of {@link #tools prebuilt tool buttons} that can be wired up to provide other customized
9079  * behavior.  Panels can be easily dropped into any {@link Ext.Container Container} or layout, and the
9080  * layout and rendering pipeline is {@link Ext.Container#add completely managed by the framework}.</p>
9081  * @constructor
9082  * @param {Object} config The config object
9083  * @xtype panel
9084  */
9085 Ext.Panel = Ext.extend(Ext.Container, {
9086     /**
9087      * The Panel's header {@link Ext.Element Element}. Read-only.
9088      * <p>This Element is used to house the {@link #title} and {@link #tools}</p>
9089      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
9090      * @type Ext.Element
9091      * @property header
9092      */
9093     /**
9094      * The Panel's body {@link Ext.Element Element} which may be used to contain HTML content.
9095      * The content may be specified in the {@link #html} config, or it may be loaded using the
9096      * {@link autoLoad} config, or through the Panel's {@link #getUpdater Updater}. Read-only.
9097      * <p>If this is used to load visible HTML elements in either way, then
9098      * the Panel may not be used as a Layout for hosting nested Panels.</p>
9099      * <p>If this Panel is intended to be used as the host of a Layout (See {@link #layout}
9100      * then the body Element must not be loaded or changed - it is under the control
9101      * of the Panel's Layout.
9102      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
9103      * @type Ext.Element
9104      * @property body
9105      */
9106     /**
9107      * The Panel's bwrap {@link Ext.Element Element} used to contain other Panel elements
9108      * (tbar, body, bbar, footer). See {@link #bodyCfg}. Read-only.
9109      * @type Ext.Element
9110      * @property bwrap
9111      */
9112     /**
9113      * True if this panel is collapsed. Read-only.
9114      * @type Boolean
9115      * @property collapsed
9116      */
9117     /**
9118      * @cfg {Object} bodyCfg
9119      * <p>A {@link Ext.DomHelper DomHelper} element specification object may be specified for any
9120      * Panel Element.</p>
9121      * <p>By default, the Default element in the table below will be used for the html markup to
9122      * create a child element with the commensurate Default class name (<code>baseCls</code> will be
9123      * replaced by <code>{@link #baseCls}</code>):</p>
9124      * <pre>
9125      * Panel      Default  Default             Custom      Additional       Additional
9126      * Element    element  class               element     class            style
9127      * ========   ==========================   =========   ==============   ===========
9128      * {@link #header}     div      {@link #baseCls}+'-header'   {@link #headerCfg}   headerCssClass   headerStyle
9129      * {@link #bwrap}      div      {@link #baseCls}+'-bwrap'     {@link #bwrapCfg}    bwrapCssClass    bwrapStyle
9130      * + tbar     div      {@link #baseCls}+'-tbar'       {@link #tbarCfg}     tbarCssClass     tbarStyle
9131      * + {@link #body}     div      {@link #baseCls}+'-body'       {@link #bodyCfg}     {@link #bodyCssClass}     {@link #bodyStyle}
9132      * + bbar     div      {@link #baseCls}+'-bbar'       {@link #bbarCfg}     bbarCssClass     bbarStyle
9133      * + {@link #footer}   div      {@link #baseCls}+'-footer'   {@link #footerCfg}   footerCssClass   footerStyle
9134      * </pre>
9135      * <p>Configuring a Custom element may be used, for example, to force the {@link #body} Element
9136      * to use a different form of markup than is created by default. An example of this might be
9137      * to {@link Ext.Element#createChild create a child} Panel containing a custom content, such as
9138      * a header, or forcing centering of all Panel content by having the body be a &lt;center&gt;
9139      * element:</p>
9140      * <pre><code>
9141 new Ext.Panel({
9142     title: 'Message Title',
9143     renderTo: Ext.getBody(),
9144     width: 200, height: 130,
9145     <b>bodyCfg</b>: {
9146         tag: 'center',
9147         cls: 'x-panel-body',  // Default class not applied if Custom element specified
9148         html: 'Message'
9149     },
9150     footerCfg: {
9151         tag: 'h2',
9152         cls: 'x-panel-footer'        // same as the Default class
9153         html: 'footer html'
9154     },
9155     footerCssClass: 'custom-footer', // additional css class, see {@link Ext.element#addClass addClass}
9156     footerStyle:    'background-color:red' // see {@link #bodyStyle}
9157 });
9158      * </code></pre>
9159      * <p>The example above also explicitly creates a <code>{@link #footer}</code> with custom markup and
9160      * styling applied.</p>
9161      */
9162     /**
9163      * @cfg {Object} headerCfg
9164      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
9165      * of this Panel's {@link #header} Element.  See <code>{@link #bodyCfg}</code> also.</p>
9166      */
9167     /**
9168      * @cfg {Object} bwrapCfg
9169      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
9170      * of this Panel's {@link #bwrap} Element.  See <code>{@link #bodyCfg}</code> also.</p>
9171      */
9172     /**
9173      * @cfg {Object} tbarCfg
9174      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
9175      * of this Panel's {@link #tbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
9176      */
9177     /**
9178      * @cfg {Object} bbarCfg
9179      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
9180      * of this Panel's {@link #bbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
9181      */
9182     /**
9183      * @cfg {Object} footerCfg
9184      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
9185      * of this Panel's {@link #footer} Element.  See <code>{@link #bodyCfg}</code> also.</p>
9186      */
9187     /**
9188      * @cfg {Boolean} closable
9189      * Panels themselves do not directly support being closed, but some Panel subclasses do (like
9190      * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}.  Specify <code>true</code>
9191      * to enable closing in such situations. Defaults to <code>false</code>.
9192      */
9193     /**
9194      * The Panel's footer {@link Ext.Element Element}. Read-only.
9195      * <p>This Element is used to house the Panel's <code>{@link #buttons}</code> or <code>{@link #fbar}</code>.</p>
9196      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
9197      * @type Ext.Element
9198      * @property footer
9199      */
9200     /**
9201      * @cfg {Mixed} applyTo
9202      * <p>The id of the node, a DOM node or an existing Element corresponding to a DIV that is already present in
9203      * the document that specifies some panel-specific structural markup.  When <code>applyTo</code> is used,
9204      * constituent parts of the panel can be specified by CSS class name within the main element, and the panel
9205      * will automatically create those components from that markup. Any required components not specified in the
9206      * markup will be autogenerated if necessary.</p>
9207      * <p>The following class names are supported (baseCls will be replaced by {@link #baseCls}):</p>
9208      * <ul><li>baseCls + '-header'</li>
9209      * <li>baseCls + '-header-text'</li>
9210      * <li>baseCls + '-bwrap'</li>
9211      * <li>baseCls + '-tbar'</li>
9212      * <li>baseCls + '-body'</li>
9213      * <li>baseCls + '-bbar'</li>
9214      * <li>baseCls + '-footer'</li></ul>
9215      * <p>Using this config, a call to render() is not required.  If applyTo is specified, any value passed for
9216      * {@link #renderTo} will be ignored and the target element's parent node will automatically be used as the
9217      * panel's container.</p>
9218      */
9219     /**
9220      * @cfg {Object/Array} tbar
9221      * <p>The top toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
9222      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
9223      * To access the top toolbar after render, use {@link #getTopToolbar}.</p>
9224      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
9225      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
9226      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
9227      * submission parameters are collected from the DOM tree.</p>
9228      */
9229     /**
9230      * @cfg {Object/Array} bbar
9231      * <p>The bottom toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
9232      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
9233      * To access the bottom toolbar after render, use {@link #getBottomToolbar}.</p>
9234      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
9235      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
9236      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
9237      * submission parameters are collected from the DOM tree.</p>
9238      */
9239     /** @cfg {Object/Array} fbar
9240      * <p>A {@link Ext.Toolbar Toolbar} object, a Toolbar config, or an array of
9241      * {@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>
9242      * <p>After render, the <code>fbar</code> property will be an {@link Ext.Toolbar Toolbar} instance.</p>
9243      * <p>If <code>{@link #buttons}</code> are specified, they will supersede the <code>fbar</code> configuration property.</p>
9244      * The Panel's <code>{@link #buttonAlign}</code> configuration affects the layout of these items, for example:
9245      * <pre><code>
9246 var w = new Ext.Window({
9247     height: 250,
9248     width: 500,
9249     bbar: new Ext.Toolbar({
9250         items: [{
9251             text: 'bbar Left'
9252         },'->',{
9253             text: 'bbar Right'
9254         }]
9255     }),
9256     {@link #buttonAlign}: 'left', // anything but 'center' or 'right' and you can use '-', and '->'
9257                                   // to control the alignment of fbar items
9258     fbar: [{
9259         text: 'fbar Left'
9260     },'->',{
9261         text: 'fbar Right'
9262     }]
9263 }).show();
9264      * </code></pre>
9265      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
9266      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
9267      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
9268      * submission parameters are collected from the DOM tree.</p>
9269      */
9270     /**
9271      * @cfg {Boolean} header
9272      * <code>true</code> to create the Panel's header element explicitly, <code>false</code> to skip creating
9273      * it.  If a <code>{@link #title}</code> is set the header will be created automatically, otherwise it will not.
9274      * If a <code>{@link #title}</code> is set but <code>header</code> is explicitly set to <code>false</code>, the header
9275      * will not be rendered.
9276      */
9277     /**
9278      * @cfg {Boolean} footer
9279      * <code>true</code> to create the footer element explicitly, false to skip creating it. The footer
9280      * will be created automatically if <code>{@link #buttons}</code> or a <code>{@link #fbar}</code> have
9281      * been configured.  See <code>{@link #bodyCfg}</code> for an example.
9282      */
9283     /**
9284      * @cfg {String} title
9285      * The title text to be used as innerHTML (html tags are accepted) to display in the panel
9286      * <code>{@link #header}</code> (defaults to ''). When a <code>title</code> is specified the
9287      * <code>{@link #header}</code> element will automatically be created and displayed unless
9288      * {@link #header} is explicitly set to <code>false</code>.  If you do not want to specify a
9289      * <code>title</code> at config time, but you may want one later, you must either specify a non-empty
9290      * <code>title</code> (a blank space ' ' will do) or <code>header:true</code> so that the container
9291      * element will get created.
9292      */
9293     /**
9294      * @cfg {Array} buttons
9295      * <code>buttons</code> will be used as <code>{@link Ext.Container#items items}</code> for the toolbar in
9296      * the footer (<code>{@link #fbar}</code>). Typically the value of this configuration property will be
9297      * an array of {@link Ext.Button}s or {@link Ext.Button} configuration objects.
9298      * If an item is configured with <code>minWidth</code> or the Panel is configured with <code>minButtonWidth</code>,
9299      * that width will be applied to the item.
9300      */
9301     /**
9302      * @cfg {Object/String/Function} autoLoad
9303      * A valid url spec according to the Updater {@link Ext.Updater#update} method.
9304      * If autoLoad is not null, the panel will attempt to load its contents
9305      * immediately upon render.<p>
9306      * The URL will become the default URL for this panel's {@link #body} element,
9307      * so it may be {@link Ext.Element#refresh refresh}ed at any time.</p>
9308      */
9309     /**
9310      * @cfg {Boolean} frame
9311      * <code>false</code> by default to render with plain 1px square borders. <code>true</code> to render with
9312      * 9 elements, complete with custom rounded corners (also see {@link Ext.Element#boxWrap}).
9313      * <p>The template generated for each condition is depicted below:</p><pre><code>
9314      *
9315 // frame = false
9316 &lt;div id="developer-specified-id-goes-here" class="x-panel">
9317
9318     &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:false)&lt;/span>&lt;/div>
9319
9320     &lt;div class="x-panel-bwrap">
9321         &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
9322     &lt;/div>
9323 &lt;/div>
9324
9325 // frame = true (create 9 elements)
9326 &lt;div id="developer-specified-id-goes-here" class="x-panel">
9327     &lt;div class="x-panel-tl">&lt;div class="x-panel-tr">&lt;div class="x-panel-tc">
9328         &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:true)&lt;/span>&lt;/div>
9329     &lt;/div>&lt;/div>&lt;/div>
9330
9331     &lt;div class="x-panel-bwrap">
9332         &lt;div class="x-panel-ml">&lt;div class="x-panel-mr">&lt;div class="x-panel-mc">
9333             &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
9334         &lt;/div>&lt;/div>&lt;/div>
9335
9336         &lt;div class="x-panel-bl">&lt;div class="x-panel-br">&lt;div class="x-panel-bc"/>
9337         &lt;/div>&lt;/div>&lt;/div>
9338 &lt;/div>
9339      * </code></pre>
9340      */
9341     /**
9342      * @cfg {Boolean} border
9343      * True to display the borders of the panel's body element, false to hide them (defaults to true).  By default,
9344      * the border is a 2px wide inset border, but this can be further altered by setting {@link #bodyBorder} to false.
9345      */
9346     /**
9347      * @cfg {Boolean} bodyBorder
9348      * True to display an interior border on the body element of the panel, false to hide it (defaults to true).
9349      * This only applies when {@link #border} == true.  If border == true and bodyBorder == false, the border will display
9350      * as a 1px wide inset border, giving the entire body element an inset appearance.
9351      */
9352     /**
9353      * @cfg {String/Object/Function} bodyCssClass
9354      * Additional css class selector to be applied to the {@link #body} element in the format expected by
9355      * {@link Ext.Element#addClass} (defaults to null). See {@link #bodyCfg}.
9356      */
9357     /**
9358      * @cfg {String/Object/Function} bodyStyle
9359      * Custom CSS styles to be applied to the {@link #body} element in the format expected by
9360      * {@link Ext.Element#applyStyles} (defaults to null). See {@link #bodyCfg}.
9361      */
9362     /**
9363      * @cfg {String} iconCls
9364      * The CSS class selector that specifies a background image to be used as the header icon (defaults to '').
9365      * <p>An example of specifying a custom icon class would be something like:
9366      * </p><pre><code>
9367 // specify the property in the config for the class:
9368      ...
9369      iconCls: 'my-icon'
9370
9371 // css class that specifies background image to be used as the icon image:
9372 .my-icon { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
9373 </code></pre>
9374      */
9375     /**
9376      * @cfg {Boolean} collapsible
9377      * True to make the panel collapsible and have the expand/collapse toggle button automatically rendered into
9378      * the header tool button area, false to keep the panel statically sized with no button (defaults to false).
9379      */
9380     /**
9381      * @cfg {Array} tools
9382      * An array of tool button configs to be added to the header tool area. When rendered, each tool is
9383      * stored as an {@link Ext.Element Element} referenced by a public property called <code><b></b>tools.<i>&lt;tool-type&gt;</i></code>
9384      * <p>Each tool config may contain the following properties:
9385      * <div class="mdetail-params"><ul>
9386      * <li><b>id</b> : String<div class="sub-desc"><b>Required.</b> The type
9387      * 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
9388      * resulting tool Element. Ext provides CSS rules, and an icon sprite containing images for the tool types listed below.
9389      * The developer may implement custom tools by supplying alternate CSS rules and background images:
9390      * <ul>
9391      * <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>
9392      * <div class="x-tool x-tool-close" style="float:left; margin-right:5;"> </div><div><code> close</code></div>
9393      * <div class="x-tool x-tool-minimize" style="float:left; margin-right:5;"> </div><div><code> minimize</code></div>
9394      * <div class="x-tool x-tool-maximize" style="float:left; margin-right:5;"> </div><div><code> maximize</code></div>
9395      * <div class="x-tool x-tool-restore" style="float:left; margin-right:5;"> </div><div><code> restore</code></div>
9396      * <div class="x-tool x-tool-gear" style="float:left; margin-right:5;"> </div><div><code> gear</code></div>
9397      * <div class="x-tool x-tool-pin" style="float:left; margin-right:5;"> </div><div><code> pin</code></div>
9398      * <div class="x-tool x-tool-unpin" style="float:left; margin-right:5;"> </div><div><code> unpin</code></div>
9399      * <div class="x-tool x-tool-right" style="float:left; margin-right:5;"> </div><div><code> right</code></div>
9400      * <div class="x-tool x-tool-left" style="float:left; margin-right:5;"> </div><div><code> left</code></div>
9401      * <div class="x-tool x-tool-up" style="float:left; margin-right:5;"> </div><div><code> up</code></div>
9402      * <div class="x-tool x-tool-down" style="float:left; margin-right:5;"> </div><div><code> down</code></div>
9403      * <div class="x-tool x-tool-refresh" style="float:left; margin-right:5;"> </div><div><code> refresh</code></div>
9404      * <div class="x-tool x-tool-minus" style="float:left; margin-right:5;"> </div><div><code> minus</code></div>
9405      * <div class="x-tool x-tool-plus" style="float:left; margin-right:5;"> </div><div><code> plus</code></div>
9406      * <div class="x-tool x-tool-help" style="float:left; margin-right:5;"> </div><div><code> help</code></div>
9407      * <div class="x-tool x-tool-search" style="float:left; margin-right:5;"> </div><div><code> search</code></div>
9408      * <div class="x-tool x-tool-save" style="float:left; margin-right:5;"> </div><div><code> save</code></div>
9409      * <div class="x-tool x-tool-print" style="float:left; margin-right:5;"> </div><div><code> print</code></div>
9410      * </ul></div></li>
9411      * <li><b>handler</b> : Function<div class="sub-desc"><b>Required.</b> The function to
9412      * call when clicked. Arguments passed are:<ul>
9413      * <li><b>event</b> : Ext.EventObject<div class="sub-desc">The click event.</div></li>
9414      * <li><b>toolEl</b> : Ext.Element<div class="sub-desc">The tool Element.</div></li>
9415      * <li><b>panel</b> : Ext.Panel<div class="sub-desc">The host Panel</div></li>
9416      * <li><b>tc</b> : Object<div class="sub-desc">The tool configuration object</div></li>
9417      * </ul></div></li>
9418      * <li><b>stopEvent</b> : Boolean<div class="sub-desc">Defaults to true. Specify as false to allow click event to propagate.</div></li>
9419      * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the handler.</div></li>
9420      * <li><b>qtip</b> : String/Object<div class="sub-desc">A tip string, or
9421      * a config argument to {@link Ext.QuickTip#register}</div></li>
9422      * <li><b>hidden</b> : Boolean<div class="sub-desc">True to initially render hidden.</div></li>
9423      * <li><b>on</b> : Object<div class="sub-desc">A listener config object specifiying
9424      * event listeners in the format of an argument to {@link #addListener}</div></li>
9425      * </ul></div>
9426      * <p>Note that, apart from the toggle tool which is provided when a panel is collapsible, these
9427      * tools only provide the visual button. Any required functionality must be provided by adding
9428      * handlers that implement the necessary behavior.</p>
9429      * <p>Example usage:</p>
9430      * <pre><code>
9431 tools:[{
9432     id:'refresh',
9433     qtip: 'Refresh form Data',
9434     // hidden:true,
9435     handler: function(event, toolEl, panel){
9436         // refresh logic
9437     }
9438 },
9439 {
9440     id:'help',
9441     qtip: 'Get Help',
9442     handler: function(event, toolEl, panel){
9443         // whatever
9444     }
9445 }]
9446 </code></pre>
9447      * <p>For the custom id of <code>'help'</code> define two relevant css classes with a link to
9448      * a 15x15 image:</p>
9449      * <pre><code>
9450 .x-tool-help {background-image: url(images/help.png);}
9451 .x-tool-help-over {background-image: url(images/help_over.png);}
9452 // if using an image sprite:
9453 .x-tool-help {background-image: url(images/help.png) no-repeat 0 0;}
9454 .x-tool-help-over {background-position:-15px 0;}
9455 </code></pre>
9456      */
9457     /**
9458      * @cfg {Ext.Template/Ext.XTemplate} toolTemplate
9459      * <p>A Template used to create {@link #tools} in the {@link #header} Element. Defaults to:</p><pre><code>
9460 new Ext.Template('&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>')</code></pre>
9461      * <p>This may may be overridden to provide a custom DOM structure for tools based upon a more
9462      * complex XTemplate. The template's data is a single tool configuration object (Not the entire Array)
9463      * as specified in {@link #tools}.  In the following example an &lt;a> tag is used to provide a
9464      * visual indication when hovering over the tool:</p><pre><code>
9465 var win = new Ext.Window({
9466     tools: [{
9467         id: 'download',
9468         href: '/MyPdfDoc.pdf'
9469     }],
9470     toolTemplate: new Ext.XTemplate(
9471         '&lt;tpl if="id==\'download\'">',
9472             '&lt;a class="x-tool x-tool-pdf" href="{href}">&lt;/a>',
9473         '&lt;/tpl>',
9474         '&lt;tpl if="id!=\'download\'">',
9475             '&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>',
9476         '&lt;/tpl>'
9477     ),
9478     width:500,
9479     height:300,
9480     closeAction:'hide'
9481 });</code></pre>
9482      * <p>Note that the CSS class 'x-tool-pdf' should have an associated style rule which provides an
9483      * appropriate background image, something like:</p>
9484     <pre><code>
9485     a.x-tool-pdf {background-image: url(../shared/extjs/images/pdf.gif)!important;}
9486     </code></pre>
9487      */
9488     /**
9489      * @cfg {Boolean} hideCollapseTool
9490      * <code>true</code> to hide the expand/collapse toggle button when <code>{@link #collapsible} == true</code>,
9491      * <code>false</code> to display it (defaults to <code>false</code>).
9492      */
9493     /**
9494      * @cfg {Boolean} titleCollapse
9495      * <code>true</code> to allow expanding and collapsing the panel (when <code>{@link #collapsible} = true</code>)
9496      * by clicking anywhere in the header bar, <code>false</code>) to allow it only by clicking to tool button
9497      * (defaults to <code>false</code>)). If this panel is a child item of a border layout also see the
9498      * {@link Ext.layout.BorderLayout.Region BorderLayout.Region}
9499      * <code>{@link Ext.layout.BorderLayout.Region#floatable floatable}</code> config option.
9500      */
9501
9502     /**
9503      * @cfg {Mixed} floating
9504      * <p>This property is used to configure the underlying {@link Ext.Layer}. Acceptable values for this
9505      * configuration property are:</p><div class="mdetail-params"><ul>
9506      * <li><b><code>false</code></b> : <b>Default.</b><div class="sub-desc">Display the panel inline where it is
9507      * rendered.</div></li>
9508      * <li><b><code>true</code></b> : <div class="sub-desc">Float the panel (absolute position it with automatic
9509      * shimming and shadow).<ul>
9510      * <div class="sub-desc">Setting floating to true will create an Ext.Layer for this panel and display the
9511      * panel at negative offsets so that it is hidden.</div>
9512      * <div class="sub-desc">Since the panel will be absolute positioned, the position must be set explicitly
9513      * <i>after</i> render (e.g., <code>myPanel.setPosition(100,100);</code>).</div>
9514      * <div class="sub-desc"><b>Note</b>: when floating a panel you should always assign a fixed width,
9515      * otherwise it will be auto width and will expand to fill to the right edge of the viewport.</div>
9516      * </ul></div></li>
9517      * <li><b><code>{@link Ext.Layer object}</code></b> : <div class="sub-desc">The specified object will be used
9518      * as the configuration object for the {@link Ext.Layer} that will be created.</div></li>
9519      * </ul></div>
9520      */
9521     /**
9522      * @cfg {Boolean/String} shadow
9523      * <code>true</code> (or a valid Ext.Shadow {@link Ext.Shadow#mode} value) to display a shadow behind the
9524      * panel, <code>false</code> to display no shadow (defaults to <code>'sides'</code>).  Note that this option
9525      * only applies when <code>{@link #floating} = true</code>.
9526      */
9527     /**
9528      * @cfg {Number} shadowOffset
9529      * The number of pixels to offset the shadow if displayed (defaults to <code>4</code>). Note that this
9530      * option only applies when <code>{@link #floating} = true</code>.
9531      */
9532     /**
9533      * @cfg {Boolean} shim
9534      * <code>false</code> to disable the iframe shim in browsers which need one (defaults to <code>true</code>).
9535      * Note that this option only applies when <code>{@link #floating} = true</code>.
9536      */
9537     /**
9538      * @cfg {Object/Array} keys
9539      * A {@link Ext.KeyMap} config object (in the format expected by {@link Ext.KeyMap#addBinding}
9540      * used to assign custom key handling to this panel (defaults to <code>null</code>).
9541      */
9542     /**
9543      * @cfg {Boolean/Object} draggable
9544      * <p><code>true</code> to enable dragging of this Panel (defaults to <code>false</code>).</p>
9545      * <p>For custom drag/drop implementations, an <b>Ext.Panel.DD</b> config could also be passed
9546      * in this config instead of <code>true</code>. Ext.Panel.DD is an internal, undocumented class which
9547      * moves a proxy Element around in place of the Panel's element, but provides no other behaviour
9548      * during dragging or on drop. It is a subclass of {@link Ext.dd.DragSource}, so behaviour may be
9549      * added by implementing the interface methods of {@link Ext.dd.DragDrop} e.g.:
9550      * <pre><code>
9551 new Ext.Panel({
9552     title: 'Drag me',
9553     x: 100,
9554     y: 100,
9555     renderTo: Ext.getBody(),
9556     floating: true,
9557     frame: true,
9558     width: 400,
9559     height: 200,
9560     draggable: {
9561 //      Config option of Ext.Panel.DD class.
9562 //      It&#39;s a floating Panel, so do not show a placeholder proxy in the original position.
9563         insertProxy: false,
9564
9565 //      Called for each mousemove event while dragging the DD object.
9566         onDrag : function(e){
9567 //          Record the x,y position of the drag proxy so that we can
9568 //          position the Panel at end of drag.
9569             var pel = this.proxy.getEl();
9570             this.x = pel.getLeft(true);
9571             this.y = pel.getTop(true);
9572
9573 //          Keep the Shadow aligned if there is one.
9574             var s = this.panel.getEl().shadow;
9575             if (s) {
9576                 s.realign(this.x, this.y, pel.getWidth(), pel.getHeight());
9577             }
9578         },
9579
9580 //      Called on the mouseup event.
9581         endDrag : function(e){
9582             this.panel.setPosition(this.x, this.y);
9583         }
9584     }
9585 }).show();
9586 </code></pre>
9587      */
9588     /**
9589      * @cfg {Boolean} disabled
9590      * Render this panel disabled (default is <code>false</code>). An important note when using the disabled
9591      * config on panels is that IE will often fail to initialize the disabled mask element correectly if
9592      * the panel's layout has not yet completed by the time the Panel is disabled during the render process.
9593      * If you experience this issue, you may need to instead use the {@link #afterlayout} event to initialize
9594      * the disabled state:
9595      * <pre><code>
9596 new Ext.Panel({
9597     ...
9598     listeners: {
9599         'afterlayout': {
9600             fn: function(p){
9601                 p.disable();
9602             },
9603             single: true // important, as many layouts can occur
9604         }
9605     }
9606 });
9607 </code></pre>
9608      */
9609     /**
9610      * @cfg {Boolean} autoHeight
9611      * <code>true</code> to use height:'auto', <code>false</code> to use fixed height (defaults to <code>false</code>).
9612      * <b>Note</b>: Setting <code>autoHeight: true</code> means that the browser will manage the panel's height
9613      * based on its contents, and that Ext will not manage it at all. If the panel is within a layout that
9614      * manages dimensions (<code>fit</code>, <code>border</code>, etc.) then setting <code>autoHeight: true</code>
9615      * can cause issues with scrolling and will not generally work as expected since the panel will take
9616      * on the height of its contents rather than the height required by the Ext layout.
9617      */
9618
9619
9620     /**
9621      * @cfg {String} baseCls
9622      * The base CSS class to apply to this panel's element (defaults to <code>'x-panel'</code>).
9623      * <p>Another option available by default is to specify <code>'x-plain'</code> which strips all styling
9624      * except for required attributes for Ext layouts to function (e.g. overflow:hidden).
9625      * See <code>{@link #unstyled}</code> also.</p>
9626      */
9627     baseCls : 'x-panel',
9628     /**
9629      * @cfg {String} collapsedCls
9630      * A CSS class to add to the panel's element after it has been collapsed (defaults to
9631      * <code>'x-panel-collapsed'</code>).
9632      */
9633     collapsedCls : 'x-panel-collapsed',
9634     /**
9635      * @cfg {Boolean} maskDisabled
9636      * <code>true</code> to mask the panel when it is {@link #disabled}, <code>false</code> to not mask it (defaults
9637      * to <code>true</code>).  Either way, the panel will always tell its contained elements to disable themselves
9638      * when it is disabled, but masking the panel can provide an additional visual cue that the panel is
9639      * disabled.
9640      */
9641     maskDisabled : true,
9642     /**
9643      * @cfg {Boolean} animCollapse
9644      * <code>true</code> to animate the transition when the panel is collapsed, <code>false</code> to skip the
9645      * animation (defaults to <code>true</code> if the {@link Ext.Fx} class is available, otherwise <code>false</code>).
9646      */
9647     animCollapse : Ext.enableFx,
9648     /**
9649      * @cfg {Boolean} headerAsText
9650      * <code>true</code> to display the panel <code>{@link #title}</code> in the <code>{@link #header}</code>,
9651      * <code>false</code> to hide it (defaults to <code>true</code>).
9652      */
9653     headerAsText : true,
9654     /**
9655      * @cfg {String} buttonAlign
9656      * The alignment of any {@link #buttons} added to this panel.  Valid values are <code>'right'</code>,
9657      * <code>'left'</code> and <code>'center'</code> (defaults to <code>'right'</code>).
9658      */
9659     buttonAlign : 'right',
9660     /**
9661      * @cfg {Boolean} collapsed
9662      * <code>true</code> to render the panel collapsed, <code>false</code> to render it expanded (defaults to
9663      * <code>false</code>).
9664      */
9665     collapsed : false,
9666     /**
9667      * @cfg {Boolean} collapseFirst
9668      * <code>true</code> to make sure the collapse/expand toggle button always renders first (to the left of)
9669      * any other tools in the panel's title bar, <code>false</code> to render it last (defaults to <code>true</code>).
9670      */
9671     collapseFirst : true,
9672     /**
9673      * @cfg {Number} minButtonWidth
9674      * Minimum width in pixels of all {@link #buttons} in this panel (defaults to <code>75</code>)
9675      */
9676     minButtonWidth : 75,
9677     /**
9678      * @cfg {Boolean} unstyled
9679      * Overrides the <code>{@link #baseCls}</code> setting to <code>{@link #baseCls} = 'x-plain'</code> which renders
9680      * the panel unstyled except for required attributes for Ext layouts to function (e.g. overflow:hidden).
9681      */
9682     /**
9683      * @cfg {String} elements
9684      * A comma-delimited list of panel elements to initialize when the panel is rendered.  Normally, this list will be
9685      * generated automatically based on the items added to the panel at config time, but sometimes it might be useful to
9686      * make sure a structural element is rendered even if not specified at config time (for example, you may want
9687      * to add a button or toolbar dynamically after the panel has been rendered).  Adding those elements to this
9688      * list will allocate the required placeholders in the panel when it is rendered.  Valid values are<div class="mdetail-params"><ul>
9689      * <li><code>header</code></li>
9690      * <li><code>tbar</code> (top bar)</li>
9691      * <li><code>body</code></li>
9692      * <li><code>bbar</code> (bottom bar)</li>
9693      * <li><code>footer</code></li>
9694      * </ul></div>
9695      * Defaults to '<code>body</code>'.
9696      */
9697     elements : 'body',
9698     /**
9699      * @cfg {Boolean} preventBodyReset
9700      * Defaults to <code>false</code>.  When set to <code>true</code>, an extra css class <code>'x-panel-normal'</code>
9701      * will be added to the panel's element, effectively applying css styles suggested by the W3C
9702      * (see http://www.w3.org/TR/CSS21/sample.html) to the Panel's <b>body</b> element (not the header,
9703      * footer, etc.).
9704      */
9705     preventBodyReset : false,
9706
9707     /**
9708      * @cfg {Number/String} padding
9709      * A shortcut for setting a padding style on the body element. The value can either be
9710      * a number to be applied to all sides, or a normal css string describing padding.
9711      * Defaults to <tt>undefined</tt>.
9712      *
9713      */
9714     padding: undefined,
9715
9716     /** @cfg {String} resizeEvent
9717      * The event to listen to for resizing in layouts. Defaults to <tt>'bodyresize'</tt>.
9718      */
9719     resizeEvent: 'bodyresize',
9720
9721     // protected - these could be used to customize the behavior of the window,
9722     // but changing them would not be useful without further mofifications and
9723     // could lead to unexpected or undesirable results.
9724     toolTarget : 'header',
9725     collapseEl : 'bwrap',
9726     slideAnchor : 't',
9727     disabledClass : '',
9728
9729     // private, notify box this class will handle heights
9730     deferHeight : true,
9731     // private
9732     expandDefaults: {
9733         duration : 0.25
9734     },
9735     // private
9736     collapseDefaults : {
9737         duration : 0.25
9738     },
9739
9740     // private
9741     initComponent : function(){
9742         Ext.Panel.superclass.initComponent.call(this);
9743
9744         this.addEvents(
9745             /**
9746              * @event bodyresize
9747              * Fires after the Panel has been resized.
9748              * @param {Ext.Panel} p the Panel which has been resized.
9749              * @param {Number} width The Panel body's new width.
9750              * @param {Number} height The Panel body's new height.
9751              */
9752             'bodyresize',
9753             /**
9754              * @event titlechange
9755              * Fires after the Panel title has been {@link #title set} or {@link #setTitle changed}.
9756              * @param {Ext.Panel} p the Panel which has had its title changed.
9757              * @param {String} The new title.
9758              */
9759             'titlechange',
9760             /**
9761              * @event iconchange
9762              * Fires after the Panel icon class has been {@link #iconCls set} or {@link #setIconClass changed}.
9763              * @param {Ext.Panel} p the Panel which has had its {@link #iconCls icon class} changed.
9764              * @param {String} The new icon class.
9765              * @param {String} The old icon class.
9766              */
9767             'iconchange',
9768             /**
9769              * @event collapse
9770              * Fires after the Panel has been collapsed.
9771              * @param {Ext.Panel} p the Panel that has been collapsed.
9772              */
9773             'collapse',
9774             /**
9775              * @event expand
9776              * Fires after the Panel has been expanded.
9777              * @param {Ext.Panel} p The Panel that has been expanded.
9778              */
9779             'expand',
9780             /**
9781              * @event beforecollapse
9782              * Fires before the Panel is collapsed.  A handler can return false to cancel the collapse.
9783              * @param {Ext.Panel} p the Panel being collapsed.
9784              * @param {Boolean} animate True if the collapse is animated, else false.
9785              */
9786             'beforecollapse',
9787             /**
9788              * @event beforeexpand
9789              * Fires before the Panel is expanded.  A handler can return false to cancel the expand.
9790              * @param {Ext.Panel} p The Panel being expanded.
9791              * @param {Boolean} animate True if the expand is animated, else false.
9792              */
9793             'beforeexpand',
9794             /**
9795              * @event beforeclose
9796              * Fires before the Panel is closed.  Note that Panels do not directly support being closed, but some
9797              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.  This event only
9798              * applies to such subclasses.
9799              * A handler can return false to cancel the close.
9800              * @param {Ext.Panel} p The Panel being closed.
9801              */
9802             'beforeclose',
9803             /**
9804              * @event close
9805              * Fires after the Panel is closed.  Note that Panels do not directly support being closed, but some
9806              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.
9807              * @param {Ext.Panel} p The Panel that has been closed.
9808              */
9809             'close',
9810             /**
9811              * @event activate
9812              * Fires after the Panel has been visually activated.
9813              * Note that Panels do not directly support being activated, but some Panel subclasses
9814              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
9815              * activate and deactivate events under the control of the TabPanel.
9816              * @param {Ext.Panel} p The Panel that has been activated.
9817              */
9818             'activate',
9819             /**
9820              * @event deactivate
9821              * Fires after the Panel has been visually deactivated.
9822              * Note that Panels do not directly support being deactivated, but some Panel subclasses
9823              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
9824              * activate and deactivate events under the control of the TabPanel.
9825              * @param {Ext.Panel} p The Panel that has been deactivated.
9826              */
9827             'deactivate'
9828         );
9829
9830         if(this.unstyled){
9831             this.baseCls = 'x-plain';
9832         }
9833
9834
9835         this.toolbars = [];
9836         // shortcuts
9837         if(this.tbar){
9838             this.elements += ',tbar';
9839             this.topToolbar = this.createToolbar(this.tbar);
9840             this.tbar = null;
9841
9842         }
9843         if(this.bbar){
9844             this.elements += ',bbar';
9845             this.bottomToolbar = this.createToolbar(this.bbar);
9846             this.bbar = null;
9847         }
9848
9849         if(this.header === true){
9850             this.elements += ',header';
9851             this.header = null;
9852         }else if(this.headerCfg || (this.title && this.header !== false)){
9853             this.elements += ',header';
9854         }
9855
9856         if(this.footerCfg || this.footer === true){
9857             this.elements += ',footer';
9858             this.footer = null;
9859         }
9860
9861         if(this.buttons){
9862             this.fbar = this.buttons;
9863             this.buttons = null;
9864         }
9865         if(this.fbar){
9866             this.createFbar(this.fbar);
9867         }
9868         if(this.autoLoad){
9869             this.on('render', this.doAutoLoad, this, {delay:10});
9870         }
9871     },
9872
9873     // private
9874     createFbar : function(fbar){
9875         var min = this.minButtonWidth;
9876         this.elements += ',footer';
9877         this.fbar = this.createToolbar(fbar, {
9878             buttonAlign: this.buttonAlign,
9879             toolbarCls: 'x-panel-fbar',
9880             enableOverflow: false,
9881             defaults: function(c){
9882                 return {
9883                     minWidth: c.minWidth || min
9884                 };
9885             }
9886         });
9887         // @compat addButton and buttons could possibly be removed
9888         // @target 4.0
9889         /**
9890          * This Panel's Array of buttons as created from the <code>{@link #buttons}</code>
9891          * config property. Read only.
9892          * @type Array
9893          * @property buttons
9894          */
9895         this.fbar.items.each(function(c){
9896             c.minWidth = c.minWidth || this.minButtonWidth;
9897         }, this);
9898         this.buttons = this.fbar.items.items;
9899     },
9900
9901     // private
9902     createToolbar: function(tb, options){
9903         var result;
9904         // Convert array to proper toolbar config
9905         if(Ext.isArray(tb)){
9906             tb = {
9907                 items: tb
9908             };
9909         }
9910         result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
9911         this.toolbars.push(result);
9912         return result;
9913     },
9914
9915     // private
9916     createElement : function(name, pnode){
9917         if(this[name]){
9918             pnode.appendChild(this[name].dom);
9919             return;
9920         }
9921
9922         if(name === 'bwrap' || this.elements.indexOf(name) != -1){
9923             if(this[name+'Cfg']){
9924                 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
9925             }else{
9926                 var el = document.createElement('div');
9927                 el.className = this[name+'Cls'];
9928                 this[name] = Ext.get(pnode.appendChild(el));
9929             }
9930             if(this[name+'CssClass']){
9931                 this[name].addClass(this[name+'CssClass']);
9932             }
9933             if(this[name+'Style']){
9934                 this[name].applyStyles(this[name+'Style']);
9935             }
9936         }
9937     },
9938
9939     // private
9940     onRender : function(ct, position){
9941         Ext.Panel.superclass.onRender.call(this, ct, position);
9942         this.createClasses();
9943
9944         var el = this.el,
9945             d = el.dom,
9946             bw,
9947             ts;
9948
9949
9950         if(this.collapsible && !this.hideCollapseTool){
9951             this.tools = this.tools ? this.tools.slice(0) : [];
9952             this.tools[this.collapseFirst?'unshift':'push']({
9953                 id: 'toggle',
9954                 handler : this.toggleCollapse,
9955                 scope: this
9956             });
9957         }
9958
9959         if(this.tools){
9960             ts = this.tools;
9961             this.elements += (this.header !== false) ? ',header' : '';
9962         }
9963         this.tools = {};
9964
9965         el.addClass(this.baseCls);
9966         if(d.firstChild){ // existing markup
9967             this.header = el.down('.'+this.headerCls);
9968             this.bwrap = el.down('.'+this.bwrapCls);
9969             var cp = this.bwrap ? this.bwrap : el;
9970             this.tbar = cp.down('.'+this.tbarCls);
9971             this.body = cp.down('.'+this.bodyCls);
9972             this.bbar = cp.down('.'+this.bbarCls);
9973             this.footer = cp.down('.'+this.footerCls);
9974             this.fromMarkup = true;
9975         }
9976         if (this.preventBodyReset === true) {
9977             el.addClass('x-panel-reset');
9978         }
9979         if(this.cls){
9980             el.addClass(this.cls);
9981         }
9982
9983         if(this.buttons){
9984             this.elements += ',footer';
9985         }
9986
9987         // This block allows for maximum flexibility and performance when using existing markup
9988
9989         // framing requires special markup
9990         if(this.frame){
9991             el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
9992
9993             this.createElement('header', d.firstChild.firstChild.firstChild);
9994             this.createElement('bwrap', d);
9995
9996             // append the mid and bottom frame to the bwrap
9997             bw = this.bwrap.dom;
9998             var ml = d.childNodes[1], bl = d.childNodes[2];
9999             bw.appendChild(ml);
10000             bw.appendChild(bl);
10001
10002             var mc = bw.firstChild.firstChild.firstChild;
10003             this.createElement('tbar', mc);
10004             this.createElement('body', mc);
10005             this.createElement('bbar', mc);
10006             this.createElement('footer', bw.lastChild.firstChild.firstChild);
10007
10008             if(!this.footer){
10009                 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
10010             }
10011             /*
10012              * Store a reference to this element so:
10013              * a) We aren't looking it up all the time
10014              * b) The last element is reported incorrectly when using a loadmask
10015              */
10016             this.ft = Ext.get(this.bwrap.dom.lastChild);
10017             this.mc = Ext.get(mc);
10018         }else{
10019             this.createElement('header', d);
10020             this.createElement('bwrap', d);
10021
10022             // append the mid and bottom frame to the bwrap
10023             bw = this.bwrap.dom;
10024             this.createElement('tbar', bw);
10025             this.createElement('body', bw);
10026             this.createElement('bbar', bw);
10027             this.createElement('footer', bw);
10028
10029             if(!this.header){
10030                 this.body.addClass(this.bodyCls + '-noheader');
10031                 if(this.tbar){
10032                     this.tbar.addClass(this.tbarCls + '-noheader');
10033                 }
10034             }
10035         }
10036
10037         if(Ext.isDefined(this.padding)){
10038             this.body.setStyle('padding', this.body.addUnits(this.padding));
10039         }
10040
10041         if(this.border === false){
10042             this.el.addClass(this.baseCls + '-noborder');
10043             this.body.addClass(this.bodyCls + '-noborder');
10044             if(this.header){
10045                 this.header.addClass(this.headerCls + '-noborder');
10046             }
10047             if(this.footer){
10048                 this.footer.addClass(this.footerCls + '-noborder');
10049             }
10050             if(this.tbar){
10051                 this.tbar.addClass(this.tbarCls + '-noborder');
10052             }
10053             if(this.bbar){
10054                 this.bbar.addClass(this.bbarCls + '-noborder');
10055             }
10056         }
10057
10058         if(this.bodyBorder === false){
10059            this.body.addClass(this.bodyCls + '-noborder');
10060         }
10061
10062         this.bwrap.enableDisplayMode('block');
10063
10064         if(this.header){
10065             this.header.unselectable();
10066
10067             // for tools, we need to wrap any existing header markup
10068             if(this.headerAsText){
10069                 this.header.dom.innerHTML =
10070                     '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
10071
10072                 if(this.iconCls){
10073                     this.setIconClass(this.iconCls);
10074                 }
10075             }
10076         }
10077
10078         if(this.floating){
10079             this.makeFloating(this.floating);
10080         }
10081
10082         if(this.collapsible && this.titleCollapse && this.header){
10083             this.mon(this.header, 'click', this.toggleCollapse, this);
10084             this.header.setStyle('cursor', 'pointer');
10085         }
10086         if(ts){
10087             this.addTool.apply(this, ts);
10088         }
10089
10090         // Render Toolbars.
10091         if(this.fbar){
10092             this.footer.addClass('x-panel-btns');
10093             this.fbar.ownerCt = this;
10094             this.fbar.render(this.footer);
10095             this.footer.createChild({cls:'x-clear'});
10096         }
10097         if(this.tbar && this.topToolbar){
10098             this.topToolbar.ownerCt = this;
10099             this.topToolbar.render(this.tbar);
10100         }
10101         if(this.bbar && this.bottomToolbar){
10102             this.bottomToolbar.ownerCt = this;
10103             this.bottomToolbar.render(this.bbar);
10104         }
10105     },
10106
10107     /**
10108      * Sets the CSS class that provides the icon image for this panel.  This method will replace any existing
10109      * icon class if one has already been set and fire the {@link #iconchange} event after completion.
10110      * @param {String} cls The new CSS class name
10111      */
10112     setIconClass : function(cls){
10113         var old = this.iconCls;
10114         this.iconCls = cls;
10115         if(this.rendered && this.header){
10116             if(this.frame){
10117                 this.header.addClass('x-panel-icon');
10118                 this.header.replaceClass(old, this.iconCls);
10119             }else{
10120                 var hd = this.header,
10121                     img = hd.child('img.x-panel-inline-icon');
10122                 if(img){
10123                     Ext.fly(img).replaceClass(old, this.iconCls);
10124                 }else{
10125                     var hdspan = hd.child('span.' + this.headerTextCls);
10126                     if (hdspan) {
10127                         Ext.DomHelper.insertBefore(hdspan.dom, {
10128                             tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
10129                         });
10130                     }
10131                  }
10132             }
10133         }
10134         this.fireEvent('iconchange', this, cls, old);
10135     },
10136
10137     // private
10138     makeFloating : function(cfg){
10139         this.floating = true;
10140         this.el = new Ext.Layer(Ext.apply({}, cfg, {
10141             shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
10142             shadowOffset: this.shadowOffset,
10143             constrain:false,
10144             shim: this.shim === false ? false : undefined
10145         }), this.el);
10146     },
10147
10148     /**
10149      * Returns the {@link Ext.Toolbar toolbar} from the top (<code>{@link #tbar}</code>) section of the panel.
10150      * @return {Ext.Toolbar} The toolbar
10151      */
10152     getTopToolbar : function(){
10153         return this.topToolbar;
10154     },
10155
10156     /**
10157      * Returns the {@link Ext.Toolbar toolbar} from the bottom (<code>{@link #bbar}</code>) section of the panel.
10158      * @return {Ext.Toolbar} The toolbar
10159      */
10160     getBottomToolbar : function(){
10161         return this.bottomToolbar;
10162     },
10163     
10164     /**
10165      * Returns the {@link Ext.Toolbar toolbar} from the footer (<code>{@link #fbar}</code>) section of the panel.
10166      * @return {Ext.Toolbar} The toolbar
10167      */
10168     getFooterToolbar : function() {
10169         return this.fbar;
10170     },
10171
10172     /**
10173      * Adds a button to this panel.  Note that this method must be called prior to rendering.  The preferred
10174      * approach is to add buttons via the {@link #buttons} config.
10175      * @param {String/Object} config A valid {@link Ext.Button} config.  A string will become the text for a default
10176      * button config, an object will be treated as a button config object.
10177      * @param {Function} handler The function to be called on button {@link Ext.Button#click}
10178      * @param {Object} scope The scope (<code>this</code> reference) in which the button handler function is executed. Defaults to the Button.
10179      * @return {Ext.Button} The button that was added
10180      */
10181     addButton : function(config, handler, scope){
10182         if(!this.fbar){
10183             this.createFbar([]);
10184         }
10185         if(handler){
10186             if(Ext.isString(config)){
10187                 config = {text: config};
10188             }
10189             config = Ext.apply({
10190                 handler: handler,
10191                 scope: scope
10192             }, config);
10193         }
10194         return this.fbar.add(config);
10195     },
10196
10197     // private
10198     addTool : function(){
10199         if(!this.rendered){
10200             if(!this.tools){
10201                 this.tools = [];
10202             }
10203             Ext.each(arguments, function(arg){
10204                 this.tools.push(arg);
10205             }, this);
10206             return;
10207         }
10208          // nowhere to render tools!
10209         if(!this[this.toolTarget]){
10210             return;
10211         }
10212         if(!this.toolTemplate){
10213             // initialize the global tool template on first use
10214             var tt = new Ext.Template(
10215                  '<div class="x-tool x-tool-{id}">&#160;</div>'
10216             );
10217             tt.disableFormats = true;
10218             tt.compile();
10219             Ext.Panel.prototype.toolTemplate = tt;
10220         }
10221         for(var i = 0, a = arguments, len = a.length; i < len; i++) {
10222             var tc = a[i];
10223             if(!this.tools[tc.id]){
10224                 var overCls = 'x-tool-'+tc.id+'-over';
10225                 var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
10226                 this.tools[tc.id] = t;
10227                 t.enableDisplayMode('block');
10228                 this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
10229                 if(tc.on){
10230                     this.mon(t, tc.on);
10231                 }
10232                 if(tc.hidden){
10233                     t.hide();
10234                 }
10235                 if(tc.qtip){
10236                     if(Ext.isObject(tc.qtip)){
10237                         Ext.QuickTips.register(Ext.apply({
10238                               target: t.id
10239                         }, tc.qtip));
10240                     } else {
10241                         t.dom.qtip = tc.qtip;
10242                     }
10243                 }
10244                 t.addClassOnOver(overCls);
10245             }
10246         }
10247     },
10248
10249     onLayout : function(shallow, force){
10250         Ext.Panel.superclass.onLayout.apply(this, arguments);
10251         if(this.hasLayout && this.toolbars.length > 0){
10252             Ext.each(this.toolbars, function(tb){
10253                 tb.doLayout(undefined, force);
10254             });
10255             this.syncHeight();
10256         }
10257     },
10258
10259     syncHeight : function(){
10260         var h = this.toolbarHeight,
10261                 bd = this.body,
10262                 lsh = this.lastSize.height,
10263                 sz;
10264
10265         if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
10266             return;
10267         }
10268
10269
10270         if(h != this.getToolbarHeight()){
10271             h = Math.max(0, lsh - this.getFrameHeight());
10272             bd.setHeight(h);
10273             sz = bd.getSize();
10274             this.toolbarHeight = this.getToolbarHeight();
10275             this.onBodyResize(sz.width, sz.height);
10276         }
10277     },
10278
10279     // private
10280     onShow : function(){
10281         if(this.floating){
10282             return this.el.show();
10283         }
10284         Ext.Panel.superclass.onShow.call(this);
10285     },
10286
10287     // private
10288     onHide : function(){
10289         if(this.floating){
10290             return this.el.hide();
10291         }
10292         Ext.Panel.superclass.onHide.call(this);
10293     },
10294
10295     // private
10296     createToolHandler : function(t, tc, overCls, panel){
10297         return function(e){
10298             t.removeClass(overCls);
10299             if(tc.stopEvent !== false){
10300                 e.stopEvent();
10301             }
10302             if(tc.handler){
10303                 tc.handler.call(tc.scope || t, e, t, panel, tc);
10304             }
10305         };
10306     },
10307
10308     // private
10309     afterRender : function(){
10310         if(this.floating && !this.hidden){
10311             this.el.show();
10312         }
10313         if(this.title){
10314             this.setTitle(this.title);
10315         }
10316         Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
10317         if (this.collapsed) {
10318             this.collapsed = false;
10319             this.collapse(false);
10320         }
10321         this.initEvents();
10322     },
10323
10324     // private
10325     getKeyMap : function(){
10326         if(!this.keyMap){
10327             this.keyMap = new Ext.KeyMap(this.el, this.keys);
10328         }
10329         return this.keyMap;
10330     },
10331
10332     // private
10333     initEvents : function(){
10334         if(this.keys){
10335             this.getKeyMap();
10336         }
10337         if(this.draggable){
10338             this.initDraggable();
10339         }
10340         if(this.toolbars.length > 0){
10341             Ext.each(this.toolbars, function(tb){
10342                 tb.doLayout();
10343                 tb.on({
10344                     scope: this,
10345                     afterlayout: this.syncHeight,
10346                     remove: this.syncHeight
10347                 });
10348             }, this);
10349             this.syncHeight();
10350         }
10351
10352     },
10353
10354     // private
10355     initDraggable : function(){
10356         /**
10357          * <p>If this Panel is configured {@link #draggable}, this property will contain
10358          * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.</p>
10359          * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource}
10360          * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
10361          * @type Ext.dd.DragSource.
10362          * @property dd
10363          */
10364         this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
10365     },
10366
10367     // private
10368     beforeEffect : function(anim){
10369         if(this.floating){
10370             this.el.beforeAction();
10371         }
10372         if(anim !== false){
10373             this.el.addClass('x-panel-animated');
10374         }
10375     },
10376
10377     // private
10378     afterEffect : function(anim){
10379         this.syncShadow();
10380         this.el.removeClass('x-panel-animated');
10381     },
10382
10383     // private - wraps up an animation param with internal callbacks
10384     createEffect : function(a, cb, scope){
10385         var o = {
10386             scope:scope,
10387             block:true
10388         };
10389         if(a === true){
10390             o.callback = cb;
10391             return o;
10392         }else if(!a.callback){
10393             o.callback = cb;
10394         }else { // wrap it up
10395             o.callback = function(){
10396                 cb.call(scope);
10397                 Ext.callback(a.callback, a.scope);
10398             };
10399         }
10400         return Ext.applyIf(o, a);
10401     },
10402
10403     /**
10404      * Collapses the panel body so that it becomes hidden.  Fires the {@link #beforecollapse} event which will
10405      * cancel the collapse action if it returns false.
10406      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
10407      * {@link #animCollapse} panel config)
10408      * @return {Ext.Panel} this
10409      */
10410     collapse : function(animate){
10411         if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
10412             return;
10413         }
10414         var doAnim = animate === true || (animate !== false && this.animCollapse);
10415         this.beforeEffect(doAnim);
10416         this.onCollapse(doAnim, animate);
10417         return this;
10418     },
10419
10420     // private
10421     onCollapse : function(doAnim, animArg){
10422         if(doAnim){
10423             this[this.collapseEl].slideOut(this.slideAnchor,
10424                     Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
10425                         this.collapseDefaults));
10426         }else{
10427             this[this.collapseEl].hide(this.hideMode);
10428             this.afterCollapse(false);
10429         }
10430     },
10431
10432     // private
10433     afterCollapse : function(anim){
10434         this.collapsed = true;
10435         this.el.addClass(this.collapsedCls);
10436         if(anim !== false){
10437             this[this.collapseEl].hide(this.hideMode);
10438         }
10439         this.afterEffect(anim);
10440
10441         // Reset lastSize of all sub-components so they KNOW they are in a collapsed container
10442         this.cascade(function(c) {
10443             if (c.lastSize) {
10444                 c.lastSize = { width: 0, height: 0 };
10445             }
10446         });
10447         this.fireEvent('collapse', this);
10448     },
10449
10450     /**
10451      * Expands the panel body so that it becomes visible.  Fires the {@link #beforeexpand} event which will
10452      * cancel the expand action if it returns false.
10453      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
10454      * {@link #animCollapse} panel config)
10455      * @return {Ext.Panel} this
10456      */
10457     expand : function(animate){
10458         if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
10459             return;
10460         }
10461         var doAnim = animate === true || (animate !== false && this.animCollapse);
10462         this.el.removeClass(this.collapsedCls);
10463         this.beforeEffect(doAnim);
10464         this.onExpand(doAnim, animate);
10465         return this;
10466     },
10467
10468     // private
10469     onExpand : function(doAnim, animArg){
10470         if(doAnim){
10471             this[this.collapseEl].slideIn(this.slideAnchor,
10472                     Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
10473                         this.expandDefaults));
10474         }else{
10475             this[this.collapseEl].show(this.hideMode);
10476             this.afterExpand(false);
10477         }
10478     },
10479
10480     // private
10481     afterExpand : function(anim){
10482         this.collapsed = false;
10483         if(anim !== false){
10484             this[this.collapseEl].show(this.hideMode);
10485         }
10486         this.afterEffect(anim);
10487         if (this.deferLayout) {
10488             delete this.deferLayout;
10489             this.doLayout(true);
10490         }
10491         this.fireEvent('expand', this);
10492     },
10493
10494     /**
10495      * Shortcut for performing an {@link #expand} or {@link #collapse} based on the current state of the panel.
10496      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
10497      * {@link #animCollapse} panel config)
10498      * @return {Ext.Panel} this
10499      */
10500     toggleCollapse : function(animate){
10501         this[this.collapsed ? 'expand' : 'collapse'](animate);
10502         return this;
10503     },
10504
10505     // private
10506     onDisable : function(){
10507         if(this.rendered && this.maskDisabled){
10508             this.el.mask();
10509         }
10510         Ext.Panel.superclass.onDisable.call(this);
10511     },
10512
10513     // private
10514     onEnable : function(){
10515         if(this.rendered && this.maskDisabled){
10516             this.el.unmask();
10517         }
10518         Ext.Panel.superclass.onEnable.call(this);
10519     },
10520
10521     // private
10522     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
10523         var w = adjWidth,
10524             h = adjHeight;
10525
10526         if(Ext.isDefined(w) || Ext.isDefined(h)){
10527             if(!this.collapsed){
10528                 // First, set the the Panel's body width.
10529                 // If we have auto-widthed it, get the resulting full offset width so we can size the Toolbars to match
10530                 // The Toolbars must not buffer this resize operation because we need to know their heights.
10531
10532                 if(Ext.isNumber(w)){
10533                     this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
10534                 } else if (w == 'auto') {
10535                     w = this.body.setWidth('auto').dom.offsetWidth;
10536                 } else {
10537                     w = this.body.dom.offsetWidth;
10538                 }
10539
10540                 if(this.tbar){
10541                     this.tbar.setWidth(w);
10542                     if(this.topToolbar){
10543                         this.topToolbar.setSize(w);
10544                     }
10545                 }
10546                 if(this.bbar){
10547                     this.bbar.setWidth(w);
10548                     if(this.bottomToolbar){
10549                         this.bottomToolbar.setSize(w);
10550                         // The bbar does not move on resize without this.
10551                         if (Ext.isIE) {
10552                             this.bbar.setStyle('position', 'static');
10553                             this.bbar.setStyle('position', '');
10554                         }
10555                     }
10556                 }
10557                 if(this.footer){
10558                     this.footer.setWidth(w);
10559                     if(this.fbar){
10560                         this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
10561                     }
10562                 }
10563
10564                 // At this point, the Toolbars must be layed out for getFrameHeight to find a result.
10565                 if(Ext.isNumber(h)){
10566                     h = Math.max(0, h - this.getFrameHeight());
10567                     //h = Math.max(0, h - (this.getHeight() - this.body.getHeight()));
10568                     this.body.setHeight(h);
10569                 }else if(h == 'auto'){
10570                     this.body.setHeight(h);
10571                 }
10572
10573                 if(this.disabled && this.el._mask){
10574                     this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
10575                 }
10576             }else{
10577                 // Adds an event to set the correct height afterExpand.  This accounts for the deferHeight flag in panel
10578                 this.queuedBodySize = {width: w, height: h};
10579                 if(!this.queuedExpand && this.allowQueuedExpand !== false){
10580                     this.queuedExpand = true;
10581                     this.on('expand', function(){
10582                         delete this.queuedExpand;
10583                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
10584                     }, this, {single:true});
10585                 }
10586             }
10587             this.onBodyResize(w, h);
10588         }
10589         this.syncShadow();
10590         Ext.Panel.superclass.onResize.call(this, adjWidth, adjHeight, rawWidth, rawHeight);
10591
10592     },
10593
10594     // private
10595     onBodyResize: function(w, h){
10596         this.fireEvent('bodyresize', this, w, h);
10597     },
10598
10599     // private
10600     getToolbarHeight: function(){
10601         var h = 0;
10602         if(this.rendered){
10603             Ext.each(this.toolbars, function(tb){
10604                 h += tb.getHeight();
10605             }, this);
10606         }
10607         return h;
10608     },
10609
10610     // deprecate
10611     adjustBodyHeight : function(h){
10612         return h;
10613     },
10614
10615     // private
10616     adjustBodyWidth : function(w){
10617         return w;
10618     },
10619
10620     // private
10621     onPosition : function(){
10622         this.syncShadow();
10623     },
10624
10625     /**
10626      * Returns the width in pixels of the framing elements of this panel (not including the body width).  To
10627      * retrieve the body width see {@link #getInnerWidth}.
10628      * @return {Number} The frame width
10629      */
10630     getFrameWidth : function(){
10631         var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
10632
10633         if(this.frame){
10634             var l = this.bwrap.dom.firstChild;
10635             w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
10636             w += this.mc.getFrameWidth('lr');
10637         }
10638         return w;
10639     },
10640
10641     /**
10642      * Returns the height in pixels of the framing elements of this panel (including any top and bottom bars and
10643      * header and footer elements, but not including the body height).  To retrieve the body height see {@link #getInnerHeight}.
10644      * @return {Number} The frame height
10645      */
10646     getFrameHeight : function() {
10647         var h = Math.max(0, this.getHeight() - this.body.getHeight());
10648
10649         if (isNaN(h)) {
10650             h = 0;
10651         }
10652         return h;
10653
10654         /* Deprecate
10655             var h  = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
10656             h += (this.tbar ? this.tbar.getHeight() : 0) +
10657                  (this.bbar ? this.bbar.getHeight() : 0);
10658
10659             if(this.frame){
10660                 h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
10661             }else{
10662                 h += (this.header ? this.header.getHeight() : 0) +
10663                     (this.footer ? this.footer.getHeight() : 0);
10664             }
10665             return h;
10666         */
10667     },
10668
10669     /**
10670      * Returns the width in pixels of the body element (not including the width of any framing elements).
10671      * For the frame width see {@link #getFrameWidth}.
10672      * @return {Number} The body width
10673      */
10674     getInnerWidth : function(){
10675         return this.getSize().width - this.getFrameWidth();
10676     },
10677
10678     /**
10679      * Returns the height in pixels of the body element (not including the height of any framing elements).
10680      * For the frame height see {@link #getFrameHeight}.
10681      * @return {Number} The body height
10682      */
10683     getInnerHeight : function(){
10684         return this.body.getHeight();
10685         /* Deprecate
10686             return this.getSize().height - this.getFrameHeight();
10687         */
10688     },
10689
10690     // private
10691     syncShadow : function(){
10692         if(this.floating){
10693             this.el.sync(true);
10694         }
10695     },
10696
10697     // private
10698     getLayoutTarget : function(){
10699         return this.body;
10700     },
10701
10702     // private
10703     getContentTarget : function(){
10704         return this.body;
10705     },
10706
10707     /**
10708      * <p>Sets the title text for the panel and optionally the {@link #iconCls icon class}.</p>
10709      * <p>In order to be able to set the title, a header element must have been created
10710      * for the Panel. This is triggered either by configuring the Panel with a non-blank <code>{@link #title}</code>,
10711      * or configuring it with <code><b>{@link #header}: true</b></code>.</p>
10712      * @param {String} title The title text to set
10713      * @param {String} iconCls (optional) {@link #iconCls iconCls} A user-defined CSS class that provides the icon image for this panel
10714      */
10715     setTitle : function(title, iconCls){
10716         this.title = title;
10717         if(this.header && this.headerAsText){
10718             this.header.child('span').update(title);
10719         }
10720         if(iconCls){
10721             this.setIconClass(iconCls);
10722         }
10723         this.fireEvent('titlechange', this, title);
10724         return this;
10725     },
10726
10727     /**
10728      * Get the {@link Ext.Updater} for this panel. Enables you to perform Ajax updates of this panel's body.
10729      * @return {Ext.Updater} The Updater
10730      */
10731     getUpdater : function(){
10732         return this.body.getUpdater();
10733     },
10734
10735      /**
10736      * Loads this content panel immediately with content returned from an XHR call.
10737      * @param {Object/String/Function} config A config object containing any of the following options:
10738 <pre><code>
10739 panel.load({
10740     url: 'your-url.php',
10741     params: {param1: 'foo', param2: 'bar'}, // or a URL encoded string
10742     callback: yourFunction,
10743     scope: yourObject, // optional scope for the callback
10744     discardUrl: false,
10745     nocache: false,
10746     text: 'Loading...',
10747     timeout: 30,
10748     scripts: false
10749 });
10750 </code></pre>
10751      * The only required property is url. The optional properties nocache, text and scripts
10752      * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their
10753      * associated property on this panel Updater instance.
10754      * @return {Ext.Panel} this
10755      */
10756     load : function(){
10757         var um = this.body.getUpdater();
10758         um.update.apply(um, arguments);
10759         return this;
10760     },
10761
10762     // private
10763     beforeDestroy : function(){
10764         Ext.Panel.superclass.beforeDestroy.call(this);
10765         if(this.header){
10766             this.header.removeAllListeners();
10767         }
10768         if(this.tools){
10769             for(var k in this.tools){
10770                 Ext.destroy(this.tools[k]);
10771             }
10772         }
10773         if(this.toolbars.length > 0){
10774             Ext.each(this.toolbars, function(tb){
10775                 tb.un('afterlayout', this.syncHeight, this);
10776                 tb.un('remove', this.syncHeight, this);
10777             }, this);
10778         }
10779         if(Ext.isArray(this.buttons)){
10780             while(this.buttons.length) {
10781                 Ext.destroy(this.buttons[0]);
10782             }
10783         }
10784         if(this.rendered){
10785             Ext.destroy(
10786                 this.ft,
10787                 this.header,
10788                 this.footer,
10789                 this.toolbars,
10790                 this.tbar,
10791                 this.bbar,
10792                 this.body,
10793                 this.mc,
10794                 this.bwrap
10795             );
10796             if (this.fbar) {
10797                 Ext.destroy(
10798                     this.fbar,
10799                     this.fbar.el
10800                 );
10801             }
10802         }else{
10803             Ext.destroy(
10804                 this.topToolbar,
10805                 this.bottomToolbar
10806             );
10807         }
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);
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      */
11406     select : function(color){
11407         color = color.replace('#', '');
11408         if(color != this.value || this.allowReselect){
11409             var el = this.el;
11410             if(this.value){
11411                 el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
11412             }
11413             el.child('a.color-'+color).addClass('x-color-palette-sel');
11414             this.value = color;
11415             this.fireEvent('select', this, color);
11416         }
11417     }
11418
11419     /**
11420      * @cfg {String} autoEl @hide
11421      */
11422 });
11423 Ext.reg('colorpalette', Ext.ColorPalette);
11424 /**
11425  * @class Ext.DatePicker
11426  * @extends Ext.Component
11427  * <p>A popup date picker. This class is used by the {@link Ext.form.DateField DateField} class
11428  * to allow browsing and selection of valid dates.</p>
11429  * <p>All the string values documented below may be overridden by including an Ext locale file in
11430  * your page.</p>
11431  * @constructor
11432  * Create a new DatePicker
11433  * @param {Object} config The config object
11434  * @xtype datepicker
11435  */
11436 Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
11437     /**
11438      * @cfg {String} todayText
11439      * The text to display on the button that selects the current date (defaults to <code>'Today'</code>)
11440      */
11441     todayText : 'Today',
11442     /**
11443      * @cfg {String} okText
11444      * The text to display on the ok button (defaults to <code>'&#160;OK&#160;'</code> to give the user extra clicking room)
11445      */
11446     okText : '&#160;OK&#160;',
11447     /**
11448      * @cfg {String} cancelText
11449      * The text to display on the cancel button (defaults to <code>'Cancel'</code>)
11450      */
11451     cancelText : 'Cancel',
11452     /**
11453      * @cfg {Function} handler
11454      * Optional. A function that will handle the select event of this picker.
11455      * The handler is passed the following parameters:<div class="mdetail-params"><ul>
11456      * <li><code>picker</code> : DatePicker<div class="sub-desc">This DatePicker.</div></li>
11457      * <li><code>date</code> : Date<div class="sub-desc">The selected date.</div></li>
11458      * </ul></div>
11459      */
11460     /**
11461      * @cfg {Object} scope
11462      * The scope (<code><b>this</b></code> reference) in which the <code>{@link #handler}</code>
11463      * function will be called.  Defaults to this DatePicker instance.
11464      */
11465     /**
11466      * @cfg {String} todayTip
11467      * A string used to format the message for displaying in a tooltip over the button that
11468      * selects the current date. Defaults to <code>'{0} (Spacebar)'</code> where
11469      * the <code>{0}</code> token is replaced by today's date.
11470      */
11471     todayTip : '{0} (Spacebar)',
11472     /**
11473      * @cfg {String} minText
11474      * The error text to display if the minDate validation fails (defaults to <code>'This date is before the minimum date'</code>)
11475      */
11476     minText : 'This date is before the minimum date',
11477     /**
11478      * @cfg {String} maxText
11479      * The error text to display if the maxDate validation fails (defaults to <code>'This date is after the maximum date'</code>)
11480      */
11481     maxText : 'This date is after the maximum date',
11482     /**
11483      * @cfg {String} format
11484      * The default date format string which can be overriden for localization support.  The format must be
11485      * valid according to {@link Date#parseDate} (defaults to <code>'m/d/y'</code>).
11486      */
11487     format : 'm/d/y',
11488     /**
11489      * @cfg {String} disabledDaysText
11490      * The tooltip to display when the date falls on a disabled day (defaults to <code>'Disabled'</code>)
11491      */
11492     disabledDaysText : 'Disabled',
11493     /**
11494      * @cfg {String} disabledDatesText
11495      * The tooltip text to display when the date falls on a disabled date (defaults to <code>'Disabled'</code>)
11496      */
11497     disabledDatesText : 'Disabled',
11498     /**
11499      * @cfg {Array} monthNames
11500      * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
11501      */
11502     monthNames : Date.monthNames,
11503     /**
11504      * @cfg {Array} dayNames
11505      * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
11506      */
11507     dayNames : Date.dayNames,
11508     /**
11509      * @cfg {String} nextText
11510      * The next month navigation button tooltip (defaults to <code>'Next Month (Control+Right)'</code>)
11511      */
11512     nextText : 'Next Month (Control+Right)',
11513     /**
11514      * @cfg {String} prevText
11515      * The previous month navigation button tooltip (defaults to <code>'Previous Month (Control+Left)'</code>)
11516      */
11517     prevText : 'Previous Month (Control+Left)',
11518     /**
11519      * @cfg {String} monthYearText
11520      * The header month selector tooltip (defaults to <code>'Choose a month (Control+Up/Down to move years)'</code>)
11521      */
11522     monthYearText : 'Choose a month (Control+Up/Down to move years)',
11523     /**
11524      * @cfg {Number} startDay
11525      * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
11526      */
11527     startDay : 0,
11528     /**
11529      * @cfg {Boolean} showToday
11530      * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar
11531      * that selects the current date (defaults to <code>true</code>).
11532      */
11533     showToday : true,
11534     /**
11535      * @cfg {Date} minDate
11536      * Minimum allowable date (JavaScript date object, defaults to null)
11537      */
11538     /**
11539      * @cfg {Date} maxDate
11540      * Maximum allowable date (JavaScript date object, defaults to null)
11541      */
11542     /**
11543      * @cfg {Array} disabledDays
11544      * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
11545      */
11546     /**
11547      * @cfg {RegExp} disabledDatesRE
11548      * JavaScript regular expression used to disable a pattern of dates (defaults to null).  The {@link #disabledDates}
11549      * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the
11550      * disabledDates value.
11551      */
11552     /**
11553      * @cfg {Array} disabledDates
11554      * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular
11555      * expression so they are very powerful. Some examples:
11556      * <ul>
11557      * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>
11558      * <li>['03/08', '09/16'] would disable those days for every year</li>
11559      * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>
11560      * <li>['03/../2006'] would disable every day in March 2006</li>
11561      * <li>['^03'] would disable every day in every March</li>
11562      * </ul>
11563      * Note that the format of the dates included in the array should exactly match the {@link #format} config.
11564      * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to
11565      * escape the dot when restricting dates. For example: ['03\\.08\\.03'].
11566      */
11567
11568     // private
11569     // Set by other components to stop the picker focus being updated when the value changes.
11570     focusOnSelect: true,
11571
11572     // default value used to initialise each date in the DatePicker
11573     // (note: 12 noon was chosen because it steers well clear of all DST timezone changes)
11574     initHour: 12, // 24-hour format
11575
11576     // private
11577     initComponent : function(){
11578         Ext.DatePicker.superclass.initComponent.call(this);
11579
11580         this.value = this.value ?
11581                  this.value.clearTime(true) : new Date().clearTime();
11582
11583         this.addEvents(
11584             /**
11585              * @event select
11586              * Fires when a date is selected
11587              * @param {DatePicker} this DatePicker
11588              * @param {Date} date The selected date
11589              */
11590             'select'
11591         );
11592
11593         if(this.handler){
11594             this.on('select', this.handler,  this.scope || this);
11595         }
11596
11597         this.initDisabledDays();
11598     },
11599
11600     // private
11601     initDisabledDays : function(){
11602         if(!this.disabledDatesRE && this.disabledDates){
11603             var dd = this.disabledDates,
11604                 len = dd.length - 1,
11605                 re = '(?:';
11606
11607             Ext.each(dd, function(d, i){
11608                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
11609                 if(i != len){
11610                     re += '|';
11611                 }
11612             }, this);
11613             this.disabledDatesRE = new RegExp(re + ')');
11614         }
11615     },
11616
11617     /**
11618      * Replaces any existing disabled dates with new values and refreshes the DatePicker.
11619      * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config
11620      * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.
11621      */
11622     setDisabledDates : function(dd){
11623         if(Ext.isArray(dd)){
11624             this.disabledDates = dd;
11625             this.disabledDatesRE = null;
11626         }else{
11627             this.disabledDatesRE = dd;
11628         }
11629         this.initDisabledDays();
11630         this.update(this.value, true);
11631     },
11632
11633     /**
11634      * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.
11635      * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config
11636      * for details on supported values.
11637      */
11638     setDisabledDays : function(dd){
11639         this.disabledDays = dd;
11640         this.update(this.value, true);
11641     },
11642
11643     /**
11644      * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
11645      * @param {Date} value The minimum date that can be selected
11646      */
11647     setMinDate : function(dt){
11648         this.minDate = dt;
11649         this.update(this.value, true);
11650     },
11651
11652     /**
11653      * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
11654      * @param {Date} value The maximum date that can be selected
11655      */
11656     setMaxDate : function(dt){
11657         this.maxDate = dt;
11658         this.update(this.value, true);
11659     },
11660
11661     /**
11662      * Sets the value of the date field
11663      * @param {Date} value The date to set
11664      */
11665     setValue : function(value){
11666         this.value = value.clearTime(true);
11667         this.update(this.value);
11668     },
11669
11670     /**
11671      * Gets the current selected value of the date field
11672      * @return {Date} The selected date
11673      */
11674     getValue : function(){
11675         return this.value;
11676     },
11677
11678     // private
11679     focus : function(){
11680         this.update(this.activeDate);
11681     },
11682
11683     // private
11684     onEnable: function(initial){
11685         Ext.DatePicker.superclass.onEnable.call(this);
11686         this.doDisabled(false);
11687         this.update(initial ? this.value : this.activeDate);
11688         if(Ext.isIE){
11689             this.el.repaint();
11690         }
11691
11692     },
11693
11694     // private
11695     onDisable : function(){
11696         Ext.DatePicker.superclass.onDisable.call(this);
11697         this.doDisabled(true);
11698         if(Ext.isIE && !Ext.isIE8){
11699             /* Really strange problem in IE6/7, when disabled, have to explicitly
11700              * repaint each of the nodes to get them to display correctly, simply
11701              * calling repaint on the main element doesn't appear to be enough.
11702              */
11703              Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
11704                  Ext.fly(el).repaint();
11705              });
11706         }
11707     },
11708
11709     // private
11710     doDisabled : function(disabled){
11711         this.keyNav.setDisabled(disabled);
11712         this.prevRepeater.setDisabled(disabled);
11713         this.nextRepeater.setDisabled(disabled);
11714         if(this.showToday){
11715             this.todayKeyListener.setDisabled(disabled);
11716             this.todayBtn.setDisabled(disabled);
11717         }
11718     },
11719
11720     // private
11721     onRender : function(container, position){
11722         var m = [
11723              '<table cellspacing="0">',
11724                 '<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>',
11725                 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
11726                 dn = this.dayNames,
11727                 i;
11728         for(i = 0; i < 7; i++){
11729             var d = this.startDay+i;
11730             if(d > 6){
11731                 d = d-7;
11732             }
11733             m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
11734         }
11735         m[m.length] = '</tr></thead><tbody><tr>';
11736         for(i = 0; i < 42; i++) {
11737             if(i % 7 === 0 && i !== 0){
11738                 m[m.length] = '</tr><tr>';
11739             }
11740             m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
11741         }
11742         m.push('</tr></tbody></table></td></tr>',
11743                 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
11744                 '</table><div class="x-date-mp"></div>');
11745
11746         var el = document.createElement('div');
11747         el.className = 'x-date-picker';
11748         el.innerHTML = m.join('');
11749
11750         container.dom.insertBefore(el, position);
11751
11752         this.el = Ext.get(el);
11753         this.eventEl = Ext.get(el.firstChild);
11754
11755         this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
11756             handler: this.showPrevMonth,
11757             scope: this,
11758             preventDefault:true,
11759             stopDefault:true
11760         });
11761
11762         this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
11763             handler: this.showNextMonth,
11764             scope: this,
11765             preventDefault:true,
11766             stopDefault:true
11767         });
11768
11769         this.monthPicker = this.el.down('div.x-date-mp');
11770         this.monthPicker.enableDisplayMode('block');
11771
11772         this.keyNav = new Ext.KeyNav(this.eventEl, {
11773             'left' : function(e){
11774                 if(e.ctrlKey){
11775                     this.showPrevMonth();
11776                 }else{
11777                     this.update(this.activeDate.add('d', -1));
11778                 }
11779             },
11780
11781             'right' : function(e){
11782                 if(e.ctrlKey){
11783                     this.showNextMonth();
11784                 }else{
11785                     this.update(this.activeDate.add('d', 1));
11786                 }
11787             },
11788
11789             'up' : function(e){
11790                 if(e.ctrlKey){
11791                     this.showNextYear();
11792                 }else{
11793                     this.update(this.activeDate.add('d', -7));
11794                 }
11795             },
11796
11797             'down' : function(e){
11798                 if(e.ctrlKey){
11799                     this.showPrevYear();
11800                 }else{
11801                     this.update(this.activeDate.add('d', 7));
11802                 }
11803             },
11804
11805             'pageUp' : function(e){
11806                 this.showNextMonth();
11807             },
11808
11809             'pageDown' : function(e){
11810                 this.showPrevMonth();
11811             },
11812
11813             'enter' : function(e){
11814                 e.stopPropagation();
11815                 return true;
11816             },
11817
11818             scope : this
11819         });
11820
11821         this.el.unselectable();
11822
11823         this.cells = this.el.select('table.x-date-inner tbody td');
11824         this.textNodes = this.el.query('table.x-date-inner tbody span');
11825
11826         this.mbtn = new Ext.Button({
11827             text: '&#160;',
11828             tooltip: this.monthYearText,
11829             renderTo: this.el.child('td.x-date-middle', true)
11830         });
11831         this.mbtn.el.child('em').addClass('x-btn-arrow');
11832
11833         if(this.showToday){
11834             this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
11835             var today = (new Date()).dateFormat(this.format);
11836             this.todayBtn = new Ext.Button({
11837                 renderTo: this.el.child('td.x-date-bottom', true),
11838                 text: String.format(this.todayText, today),
11839                 tooltip: String.format(this.todayTip, today),
11840                 handler: this.selectToday,
11841                 scope: this
11842             });
11843         }
11844         this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
11845         this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
11846         this.mon(this.mbtn, 'click', this.showMonthPicker, this);
11847         this.onEnable(true);
11848     },
11849
11850     // private
11851     createMonthPicker : function(){
11852         if(!this.monthPicker.dom.firstChild){
11853             var buf = ['<table border="0" cellspacing="0">'];
11854             for(var i = 0; i < 6; i++){
11855                 buf.push(
11856                     '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
11857                     '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
11858                     i === 0 ?
11859                     '<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>' :
11860                     '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
11861                 );
11862             }
11863             buf.push(
11864                 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
11865                     this.okText,
11866                     '</button><button type="button" class="x-date-mp-cancel">',
11867                     this.cancelText,
11868                     '</button></td></tr>',
11869                 '</table>'
11870             );
11871             this.monthPicker.update(buf.join(''));
11872
11873             this.mon(this.monthPicker, 'click', this.onMonthClick, this);
11874             this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
11875
11876             this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
11877             this.mpYears = this.monthPicker.select('td.x-date-mp-year');
11878
11879             this.mpMonths.each(function(m, a, i){
11880                 i += 1;
11881                 if((i%2) === 0){
11882                     m.dom.xmonth = 5 + Math.round(i * 0.5);
11883                 }else{
11884                     m.dom.xmonth = Math.round((i-1) * 0.5);
11885                 }
11886             });
11887         }
11888     },
11889
11890     // private
11891     showMonthPicker : function(){
11892         if(!this.disabled){
11893             this.createMonthPicker();
11894             var size = this.el.getSize();
11895             this.monthPicker.setSize(size);
11896             this.monthPicker.child('table').setSize(size);
11897
11898             this.mpSelMonth = (this.activeDate || this.value).getMonth();
11899             this.updateMPMonth(this.mpSelMonth);
11900             this.mpSelYear = (this.activeDate || this.value).getFullYear();
11901             this.updateMPYear(this.mpSelYear);
11902
11903             this.monthPicker.slideIn('t', {duration:0.2});
11904         }
11905     },
11906
11907     // private
11908     updateMPYear : function(y){
11909         this.mpyear = y;
11910         var ys = this.mpYears.elements;
11911         for(var i = 1; i <= 10; i++){
11912             var td = ys[i-1], y2;
11913             if((i%2) === 0){
11914                 y2 = y + Math.round(i * 0.5);
11915                 td.firstChild.innerHTML = y2;
11916                 td.xyear = y2;
11917             }else{
11918                 y2 = y - (5-Math.round(i * 0.5));
11919                 td.firstChild.innerHTML = y2;
11920                 td.xyear = y2;
11921             }
11922             this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
11923         }
11924     },
11925
11926     // private
11927     updateMPMonth : function(sm){
11928         this.mpMonths.each(function(m, a, i){
11929             m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
11930         });
11931     },
11932
11933     // private
11934     selectMPMonth : function(m){
11935
11936     },
11937
11938     // private
11939     onMonthClick : function(e, t){
11940         e.stopEvent();
11941         var el = new Ext.Element(t), pn;
11942         if(el.is('button.x-date-mp-cancel')){
11943             this.hideMonthPicker();
11944         }
11945         else if(el.is('button.x-date-mp-ok')){
11946             var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
11947             if(d.getMonth() != this.mpSelMonth){
11948                 // 'fix' the JS rolling date conversion if needed
11949                 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
11950             }
11951             this.update(d);
11952             this.hideMonthPicker();
11953         }
11954         else if((pn = el.up('td.x-date-mp-month', 2))){
11955             this.mpMonths.removeClass('x-date-mp-sel');
11956             pn.addClass('x-date-mp-sel');
11957             this.mpSelMonth = pn.dom.xmonth;
11958         }
11959         else if((pn = el.up('td.x-date-mp-year', 2))){
11960             this.mpYears.removeClass('x-date-mp-sel');
11961             pn.addClass('x-date-mp-sel');
11962             this.mpSelYear = pn.dom.xyear;
11963         }
11964         else if(el.is('a.x-date-mp-prev')){
11965             this.updateMPYear(this.mpyear-10);
11966         }
11967         else if(el.is('a.x-date-mp-next')){
11968             this.updateMPYear(this.mpyear+10);
11969         }
11970     },
11971
11972     // private
11973     onMonthDblClick : function(e, t){
11974         e.stopEvent();
11975         var el = new Ext.Element(t), pn;
11976         if((pn = el.up('td.x-date-mp-month', 2))){
11977             this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
11978             this.hideMonthPicker();
11979         }
11980         else if((pn = el.up('td.x-date-mp-year', 2))){
11981             this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
11982             this.hideMonthPicker();
11983         }
11984     },
11985
11986     // private
11987     hideMonthPicker : function(disableAnim){
11988         if(this.monthPicker){
11989             if(disableAnim === true){
11990                 this.monthPicker.hide();
11991             }else{
11992                 this.monthPicker.slideOut('t', {duration:0.2});
11993             }
11994         }
11995     },
11996
11997     // private
11998     showPrevMonth : function(e){
11999         this.update(this.activeDate.add('mo', -1));
12000     },
12001
12002     // private
12003     showNextMonth : function(e){
12004         this.update(this.activeDate.add('mo', 1));
12005     },
12006
12007     // private
12008     showPrevYear : function(){
12009         this.update(this.activeDate.add('y', -1));
12010     },
12011
12012     // private
12013     showNextYear : function(){
12014         this.update(this.activeDate.add('y', 1));
12015     },
12016
12017     // private
12018     handleMouseWheel : function(e){
12019         e.stopEvent();
12020         if(!this.disabled){
12021             var delta = e.getWheelDelta();
12022             if(delta > 0){
12023                 this.showPrevMonth();
12024             } else if(delta < 0){
12025                 this.showNextMonth();
12026             }
12027         }
12028     },
12029
12030     // private
12031     handleDateClick : function(e, t){
12032         e.stopEvent();
12033         if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
12034             this.cancelFocus = this.focusOnSelect === false;
12035             this.setValue(new Date(t.dateValue));
12036             delete this.cancelFocus;
12037             this.fireEvent('select', this, this.value);
12038         }
12039     },
12040
12041     // private
12042     selectToday : function(){
12043         if(this.todayBtn && !this.todayBtn.disabled){
12044             this.setValue(new Date().clearTime());
12045             this.fireEvent('select', this, this.value);
12046         }
12047     },
12048
12049     // private
12050     update : function(date, forceRefresh){
12051         if(this.rendered){
12052             var vd = this.activeDate, vis = this.isVisible();
12053             this.activeDate = date;
12054             if(!forceRefresh && vd && this.el){
12055                 var t = date.getTime();
12056                 if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
12057                     this.cells.removeClass('x-date-selected');
12058                     this.cells.each(function(c){
12059                        if(c.dom.firstChild.dateValue == t){
12060                            c.addClass('x-date-selected');
12061                            if(vis && !this.cancelFocus){
12062                                Ext.fly(c.dom.firstChild).focus(50);
12063                            }
12064                            return false;
12065                        }
12066                     }, this);
12067                     return;
12068                 }
12069             }
12070             var days = date.getDaysInMonth(),
12071                 firstOfMonth = date.getFirstDateOfMonth(),
12072                 startingPos = firstOfMonth.getDay()-this.startDay;
12073
12074             if(startingPos < 0){
12075                 startingPos += 7;
12076             }
12077             days += startingPos;
12078
12079             var pm = date.add('mo', -1),
12080                 prevStart = pm.getDaysInMonth()-startingPos,
12081                 cells = this.cells.elements,
12082                 textEls = this.textNodes,
12083                 // convert everything to numbers so it's fast
12084                 d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart, this.initHour)),
12085                 today = new Date().clearTime().getTime(),
12086                 sel = date.clearTime(true).getTime(),
12087                 min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
12088                 max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
12089                 ddMatch = this.disabledDatesRE,
12090                 ddText = this.disabledDatesText,
12091                 ddays = this.disabledDays ? this.disabledDays.join('') : false,
12092                 ddaysText = this.disabledDaysText,
12093                 format = this.format;
12094
12095             if(this.showToday){
12096                 var td = new Date().clearTime(),
12097                     disable = (td < min || td > max ||
12098                     (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
12099                     (ddays && ddays.indexOf(td.getDay()) != -1));
12100
12101                 if(!this.disabled){
12102                     this.todayBtn.setDisabled(disable);
12103                     this.todayKeyListener[disable ? 'disable' : 'enable']();
12104                 }
12105             }
12106
12107             var setCellClass = function(cal, cell){
12108                 cell.title = '';
12109                 var t = d.clearTime(true).getTime();
12110                 cell.firstChild.dateValue = t;
12111                 if(t == today){
12112                     cell.className += ' x-date-today';
12113                     cell.title = cal.todayText;
12114                 }
12115                 if(t == sel){
12116                     cell.className += ' x-date-selected';
12117                     if(vis){
12118                         Ext.fly(cell.firstChild).focus(50);
12119                     }
12120                 }
12121                 // disabling
12122                 if(t < min) {
12123                     cell.className = ' x-date-disabled';
12124                     cell.title = cal.minText;
12125                     return;
12126                 }
12127                 if(t > max) {
12128                     cell.className = ' x-date-disabled';
12129                     cell.title = cal.maxText;
12130                     return;
12131                 }
12132                 if(ddays){
12133                     if(ddays.indexOf(d.getDay()) != -1){
12134                         cell.title = ddaysText;
12135                         cell.className = ' x-date-disabled';
12136                     }
12137                 }
12138                 if(ddMatch && format){
12139                     var fvalue = d.dateFormat(format);
12140                     if(ddMatch.test(fvalue)){
12141                         cell.title = ddText.replace('%0', fvalue);
12142                         cell.className = ' x-date-disabled';
12143                     }
12144                 }
12145             };
12146
12147             var i = 0;
12148             for(; i < startingPos; i++) {
12149                 textEls[i].innerHTML = (++prevStart);
12150                 d.setDate(d.getDate()+1);
12151                 cells[i].className = 'x-date-prevday';
12152                 setCellClass(this, cells[i]);
12153             }
12154             for(; i < days; i++){
12155                 var intDay = i - startingPos + 1;
12156                 textEls[i].innerHTML = (intDay);
12157                 d.setDate(d.getDate()+1);
12158                 cells[i].className = 'x-date-active';
12159                 setCellClass(this, cells[i]);
12160             }
12161             var extraDays = 0;
12162             for(; i < 42; i++) {
12163                  textEls[i].innerHTML = (++extraDays);
12164                  d.setDate(d.getDate()+1);
12165                  cells[i].className = 'x-date-nextday';
12166                  setCellClass(this, cells[i]);
12167             }
12168
12169             this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
12170
12171             if(!this.internalRender){
12172                 var main = this.el.dom.firstChild,
12173                     w = main.offsetWidth;
12174                 this.el.setWidth(w + this.el.getBorderWidth('lr'));
12175                 Ext.fly(main).setWidth(w);
12176                 this.internalRender = true;
12177                 // opera does not respect the auto grow header center column
12178                 // then, after it gets a width opera refuses to recalculate
12179                 // without a second pass
12180                 if(Ext.isOpera && !this.secondPass){
12181                     main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
12182                     this.secondPass = true;
12183                     this.update.defer(10, this, [date]);
12184                 }
12185             }
12186         }
12187     },
12188
12189     // private
12190     beforeDestroy : function() {
12191         if(this.rendered){
12192             Ext.destroy(
12193                 this.keyNav,
12194                 this.monthPicker,
12195                 this.eventEl,
12196                 this.mbtn,
12197                 this.nextRepeater,
12198                 this.prevRepeater,
12199                 this.cells.el,
12200                 this.todayBtn
12201             );
12202             delete this.textNodes;
12203             delete this.cells.elements;
12204         }
12205     }
12206
12207     /**
12208      * @cfg {String} autoEl @hide
12209      */
12210 });
12211
12212 Ext.reg('datepicker', Ext.DatePicker);
12213 /**
12214  * @class Ext.LoadMask
12215  * A simple utility class for generically masking elements while loading data.  If the {@link #store}
12216  * config option is specified, the masking will be automatically synchronized with the store's loading
12217  * process and the mask element will be cached for reuse.  For all other elements, this mask will replace the
12218  * element's Updater load indicator and will be destroyed after the initial load.
12219  * <p>Example usage:</p>
12220  *<pre><code>
12221 // Basic mask:
12222 var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
12223 myMask.show();
12224 </code></pre>
12225  * @constructor
12226  * Create a new LoadMask
12227  * @param {Mixed} el The element or DOM node, or its id
12228  * @param {Object} config The config object
12229  */
12230 Ext.LoadMask = function(el, config){
12231     this.el = Ext.get(el);
12232     Ext.apply(this, config);
12233     if(this.store){
12234         this.store.on({
12235             scope: this,
12236             beforeload: this.onBeforeLoad,
12237             load: this.onLoad,
12238             exception: this.onLoad
12239         });
12240         this.removeMask = Ext.value(this.removeMask, false);
12241     }else{
12242         var um = this.el.getUpdater();
12243         um.showLoadIndicator = false; // disable the default indicator
12244         um.on({
12245             scope: this,
12246             beforeupdate: this.onBeforeLoad,
12247             update: this.onLoad,
12248             failure: this.onLoad
12249         });
12250         this.removeMask = Ext.value(this.removeMask, true);
12251     }
12252 };
12253
12254 Ext.LoadMask.prototype = {
12255     /**
12256      * @cfg {Ext.data.Store} store
12257      * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and
12258      * hidden on either load sucess, or load fail.
12259      */
12260     /**
12261      * @cfg {Boolean} removeMask
12262      * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
12263      * False to persist the mask element reference for multiple uses (e.g., for paged data widgets).  Defaults to false.
12264      */
12265     /**
12266      * @cfg {String} msg
12267      * The text to display in a centered loading message box (defaults to 'Loading...')
12268      */
12269     msg : 'Loading...',
12270     /**
12271      * @cfg {String} msgCls
12272      * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
12273      */
12274     msgCls : 'x-mask-loading',
12275
12276     /**
12277      * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
12278      * @type Boolean
12279      */
12280     disabled: false,
12281
12282     /**
12283      * Disables the mask to prevent it from being displayed
12284      */
12285     disable : function(){
12286        this.disabled = true;
12287     },
12288
12289     /**
12290      * Enables the mask so that it can be displayed
12291      */
12292     enable : function(){
12293         this.disabled = false;
12294     },
12295
12296     // private
12297     onLoad : function(){
12298         this.el.unmask(this.removeMask);
12299     },
12300
12301     // private
12302     onBeforeLoad : function(){
12303         if(!this.disabled){
12304             this.el.mask(this.msg, this.msgCls);
12305         }
12306     },
12307
12308     /**
12309      * Show this LoadMask over the configured Element.
12310      */
12311     show: function(){
12312         this.onBeforeLoad();
12313     },
12314
12315     /**
12316      * Hide this LoadMask.
12317      */
12318     hide: function(){
12319         this.onLoad();
12320     },
12321
12322     // private
12323     destroy : function(){
12324         if(this.store){
12325             this.store.un('beforeload', this.onBeforeLoad, this);
12326             this.store.un('load', this.onLoad, this);
12327             this.store.un('exception', this.onLoad, this);
12328         }else{
12329             var um = this.el.getUpdater();
12330             um.un('beforeupdate', this.onBeforeLoad, this);
12331             um.un('update', this.onLoad, this);
12332             um.un('failure', this.onLoad, this);
12333         }
12334     }
12335 };Ext.ns('Ext.slider');
12336
12337 /**
12338  * @class Ext.slider.Thumb
12339  * @extends Object
12340  * Represents a single thumb element on a Slider. This would not usually be created manually and would instead
12341  * be created internally by an {@link Ext.slider.MultiSlider Ext.Slider}.
12342  */
12343 Ext.slider.Thumb = Ext.extend(Object, {
12344
12345     /**
12346      * @constructor
12347      * @cfg {Ext.slider.MultiSlider} slider The Slider to render to (required)
12348      */
12349     constructor: function(config) {
12350         /**
12351          * @property slider
12352          * @type Ext.slider.MultiSlider
12353          * The slider this thumb is contained within
12354          */
12355         Ext.apply(this, config || {}, {
12356             cls: 'x-slider-thumb',
12357
12358             /**
12359              * @cfg {Boolean} constrain True to constrain the thumb so that it cannot overlap its siblings
12360              */
12361             constrain: false
12362         });
12363
12364         Ext.slider.Thumb.superclass.constructor.call(this, config);
12365
12366         if (this.slider.vertical) {
12367             Ext.apply(this, Ext.slider.Thumb.Vertical);
12368         }
12369     },
12370
12371     /**
12372      * Renders the thumb into a slider
12373      */
12374     render: function() {
12375         this.el = this.slider.innerEl.insertFirst({cls: this.cls});
12376
12377         this.initEvents();
12378     },
12379
12380     /**
12381      * Enables the thumb if it is currently disabled
12382      */
12383     enable: function() {
12384         this.disabled = false;
12385         this.el.removeClass(this.slider.disabledClass);
12386     },
12387
12388     /**
12389      * Disables the thumb if it is currently enabled
12390      */
12391     disable: function() {
12392         this.disabled = true;
12393         this.el.addClass(this.slider.disabledClass);
12394     },
12395
12396     /**
12397      * Sets up an Ext.dd.DragTracker for this thumb
12398      */
12399     initEvents: function() {
12400         var el = this.el;
12401
12402         el.addClassOnOver('x-slider-thumb-over');
12403
12404         this.tracker = new Ext.dd.DragTracker({
12405             onBeforeStart: this.onBeforeDragStart.createDelegate(this),
12406             onStart      : this.onDragStart.createDelegate(this),
12407             onDrag       : this.onDrag.createDelegate(this),
12408             onEnd        : this.onDragEnd.createDelegate(this),
12409             tolerance    : 3,
12410             autoStart    : 300
12411         });
12412
12413         this.tracker.initEl(el);
12414     },
12415
12416     /**
12417      * @private
12418      * This is tied into the internal Ext.dd.DragTracker. If the slider is currently disabled,
12419      * this returns false to disable the DragTracker too.
12420      * @return {Boolean} False if the slider is currently disabled
12421      */
12422     onBeforeDragStart : function(e) {
12423         if (this.disabled) {
12424             return false;
12425         } else {
12426             this.slider.promoteThumb(this);
12427             return true;
12428         }
12429     },
12430
12431     /**
12432      * @private
12433      * This is tied into the internal Ext.dd.DragTracker's onStart template method. Adds the drag CSS class
12434      * to the thumb and fires the 'dragstart' event
12435      */
12436     onDragStart: function(e){
12437         this.el.addClass('x-slider-thumb-drag');
12438         this.dragging = true;
12439         this.dragStartValue = this.value;
12440
12441         this.slider.fireEvent('dragstart', this.slider, e, this);
12442     },
12443
12444     /**
12445      * @private
12446      * This is tied into the internal Ext.dd.DragTracker's onDrag template method. This is called every time
12447      * the DragTracker detects a drag movement. It updates the Slider's value using the position of the drag
12448      */
12449     onDrag: function(e) {
12450         var slider   = this.slider,
12451             index    = this.index,
12452             newValue = this.getNewValue();
12453
12454         if (this.constrain) {
12455             var above = slider.thumbs[index + 1],
12456                 below = slider.thumbs[index - 1];
12457
12458             if (below != undefined && newValue <= below.value) newValue = below.value;
12459             if (above != undefined && newValue >= above.value) newValue = above.value;
12460         }
12461
12462         slider.setValue(index, newValue, false);
12463         slider.fireEvent('drag', slider, e, this);
12464     },
12465
12466     getNewValue: function() {
12467         var slider   = this.slider,
12468             pos      = slider.innerEl.translatePoints(this.tracker.getXY());
12469
12470         return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
12471     },
12472
12473     /**
12474      * @private
12475      * This is tied to the internal Ext.dd.DragTracker's onEnd template method. Removes the drag CSS class and
12476      * fires the 'changecomplete' event with the new value
12477      */
12478     onDragEnd: function(e) {
12479         var slider = this.slider,
12480             value  = this.value;
12481
12482         this.el.removeClass('x-slider-thumb-drag');
12483
12484         this.dragging = false;
12485         slider.fireEvent('dragend', slider, e);
12486
12487         if (this.dragStartValue != value) {
12488             slider.fireEvent('changecomplete', slider, value, this);
12489         }
12490     }
12491 });
12492
12493 /**
12494  * @class Ext.slider.MultiSlider
12495  * @extends Ext.BoxComponent
12496  * 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:
12497 <pre>
12498 new Ext.Slider({
12499     renderTo: Ext.getBody(),
12500     width: 200,
12501     value: 50,
12502     increment: 10,
12503     minValue: 0,
12504     maxValue: 100
12505 });
12506 </pre>
12507  * Sliders can be created with more than one thumb handle by passing an array of values instead of a single one:
12508 <pre>
12509 new Ext.Slider({
12510     renderTo: Ext.getBody(),
12511     width: 200,
12512     values: [25, 50, 75],
12513     minValue: 0,
12514     maxValue: 100,
12515
12516     //this defaults to true, setting to false allows the thumbs to pass each other
12517     {@link #constrainThumbs}: false
12518 });
12519 </pre>
12520  */
12521 Ext.slider.MultiSlider = Ext.extend(Ext.BoxComponent, {
12522     /**
12523      * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.
12524      */
12525     /**
12526      * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.
12527      */
12528     vertical: false,
12529     /**
12530      * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.
12531      */
12532     minValue: 0,
12533     /**
12534      * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.
12535      */
12536     maxValue: 100,
12537     /**
12538      * @cfg {Number/Boolean} decimalPrecision.
12539      * <p>The number of decimal places to which to round the Slider's value. Defaults to 0.</p>
12540      * <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>
12541      */
12542     decimalPrecision: 0,
12543     /**
12544      * @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.
12545      */
12546     keyIncrement: 1,
12547     /**
12548      * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.
12549      */
12550     increment: 0,
12551
12552     /**
12553      * @private
12554      * @property clickRange
12555      * @type Array
12556      * 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],
12557      * 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'
12558      * 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
12559      */
12560     clickRange: [5,15],
12561
12562     /**
12563      * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true
12564      */
12565     clickToChange : true,
12566     /**
12567      * @cfg {Boolean} animate Turn on or off animation. Defaults to true
12568      */
12569     animate: true,
12570
12571     /**
12572      * True while the thumb is in a drag operation
12573      * @type Boolean
12574      */
12575     dragging: false,
12576
12577     /**
12578      * @cfg {Boolean} constrainThumbs True to disallow thumbs from overlapping one another. Defaults to true
12579      */
12580     constrainThumbs: true,
12581
12582     /**
12583      * @private
12584      * @property topThumbZIndex
12585      * @type Number
12586      * The number used internally to set the z index of the top thumb (see promoteThumb for details)
12587      */
12588     topThumbZIndex: 10000,
12589
12590     // private override
12591     initComponent : function(){
12592         if(!Ext.isDefined(this.value)){
12593             this.value = this.minValue;
12594         }
12595
12596         /**
12597          * @property thumbs
12598          * @type Array
12599          * Array containing references to each thumb
12600          */
12601         this.thumbs = [];
12602
12603         Ext.slider.MultiSlider.superclass.initComponent.call(this);
12604
12605         this.keyIncrement = Math.max(this.increment, this.keyIncrement);
12606         this.addEvents(
12607             /**
12608              * @event beforechange
12609              * Fires before the slider value is changed. By returning false from an event handler,
12610              * you can cancel the event and prevent the slider from changing.
12611              * @param {Ext.Slider} slider The slider
12612              * @param {Number} newValue The new value which the slider is being changed to.
12613              * @param {Number} oldValue The old value which the slider was previously.
12614              */
12615             'beforechange',
12616
12617             /**
12618              * @event change
12619              * Fires when the slider value is changed.
12620              * @param {Ext.Slider} slider The slider
12621              * @param {Number} newValue The new value which the slider has been changed to.
12622              * @param {Ext.slider.Thumb} thumb The thumb that was changed
12623              */
12624             'change',
12625
12626             /**
12627              * @event changecomplete
12628              * Fires when the slider value is changed by the user and any drag operations have completed.
12629              * @param {Ext.Slider} slider The slider
12630              * @param {Number} newValue The new value which the slider has been changed to.
12631              * @param {Ext.slider.Thumb} thumb The thumb that was changed
12632              */
12633             'changecomplete',
12634
12635             /**
12636              * @event dragstart
12637              * Fires after a drag operation has started.
12638              * @param {Ext.Slider} slider The slider
12639              * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
12640              */
12641             'dragstart',
12642
12643             /**
12644              * @event drag
12645              * Fires continuously during the drag operation while the mouse is moving.
12646              * @param {Ext.Slider} slider The slider
12647              * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
12648              */
12649             'drag',
12650
12651             /**
12652              * @event dragend
12653              * Fires after the drag operation has completed.
12654              * @param {Ext.Slider} slider The slider
12655              * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
12656              */
12657             'dragend'
12658         );
12659
12660         /**
12661          * @property values
12662          * @type Array
12663          * Array of values to initalize the thumbs with
12664          */
12665         if (this.values == undefined || Ext.isEmpty(this.values)) this.values = [0];
12666
12667         var values = this.values;
12668
12669         for (var i=0; i < values.length; i++) {
12670             this.addThumb(values[i]);
12671         }
12672
12673         if(this.vertical){
12674             Ext.apply(this, Ext.slider.Vertical);
12675         }
12676     },
12677
12678     /**
12679      * Creates a new thumb and adds it to the slider
12680      * @param {Number} value The initial value to set on the thumb. Defaults to 0
12681      */
12682     addThumb: function(value) {
12683         var thumb = new Ext.slider.Thumb({
12684             value    : value,
12685             slider   : this,
12686             index    : this.thumbs.length,
12687             constrain: this.constrainThumbs
12688         });
12689         this.thumbs.push(thumb);
12690
12691         //render the thumb now if needed
12692         if (this.rendered) thumb.render();
12693     },
12694
12695     /**
12696      * @private
12697      * Moves the given thumb above all other by increasing its z-index. This is called when as drag
12698      * any thumb, so that the thumb that was just dragged is always at the highest z-index. This is
12699      * required when the thumbs are stacked on top of each other at one of the ends of the slider's
12700      * range, which can result in the user not being able to move any of them.
12701      * @param {Ext.slider.Thumb} topThumb The thumb to move to the top
12702      */
12703     promoteThumb: function(topThumb) {
12704         var thumbs = this.thumbs,
12705             zIndex, thumb;
12706
12707         for (var i = 0, j = thumbs.length; i < j; i++) {
12708             thumb = thumbs[i];
12709
12710             if (thumb == topThumb) {
12711                 zIndex = this.topThumbZIndex;
12712             } else {
12713                 zIndex = '';
12714             }
12715
12716             thumb.el.setStyle('zIndex', zIndex);
12717         }
12718     },
12719
12720     // private override
12721     onRender : function() {
12722         this.autoEl = {
12723             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
12724             cn : {
12725                 cls: 'x-slider-end',
12726                 cn : {
12727                     cls:'x-slider-inner',
12728                     cn : [{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]
12729                 }
12730             }
12731         };
12732
12733         Ext.slider.MultiSlider.superclass.onRender.apply(this, arguments);
12734
12735         this.endEl   = this.el.first();
12736         this.innerEl = this.endEl.first();
12737         this.focusEl = this.innerEl.child('.x-slider-focus');
12738
12739         //render each thumb
12740         for (var i=0; i < this.thumbs.length; i++) {
12741             this.thumbs[i].render();
12742         }
12743
12744         //calculate the size of half a thumb
12745         var thumb      = this.innerEl.child('.x-slider-thumb');
12746         this.halfThumb = (this.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
12747
12748         this.initEvents();
12749     },
12750
12751     /**
12752      * @private
12753      * Adds keyboard and mouse listeners on this.el. Ignores click events on the internal focus element.
12754      * Creates a new DragTracker which is used to control what happens when the user drags the thumb around.
12755      */
12756     initEvents : function(){
12757         this.mon(this.el, {
12758             scope    : this,
12759             mousedown: this.onMouseDown,
12760             keydown  : this.onKeyDown
12761         });
12762
12763         this.focusEl.swallowEvent("click", true);
12764     },
12765
12766     /**
12767      * @private
12768      * Mousedown handler for the slider. If the clickToChange is enabled and the click was not on the draggable 'thumb',
12769      * this calculates the new value of the slider and tells the implementation (Horizontal or Vertical) to move the thumb
12770      * @param {Ext.EventObject} e The click event
12771      */
12772     onMouseDown : function(e){
12773         if(this.disabled){
12774             return;
12775         }
12776
12777         //see if the click was on any of the thumbs
12778         var thumbClicked = false;
12779         for (var i=0; i < this.thumbs.length; i++) {
12780             thumbClicked = thumbClicked || e.target == this.thumbs[i].el.dom;
12781         }
12782
12783         if (this.clickToChange && !thumbClicked) {
12784             var local = this.innerEl.translatePoints(e.getXY());
12785             this.onClickChange(local);
12786         }
12787         this.focus();
12788     },
12789
12790     /**
12791      * @private
12792      * Moves the thumb to the indicated position. Note that a Vertical implementation is provided in Ext.slider.Vertical.
12793      * Only changes the value if the click was within this.clickRange.
12794      * @param {Object} local Object containing top and left values for the click event.
12795      */
12796     onClickChange : function(local) {
12797         if (local.top > this.clickRange[0] && local.top < this.clickRange[1]) {
12798             //find the nearest thumb to the click event
12799             var thumb = this.getNearest(local, 'left'),
12800                 index = thumb.index;
12801
12802             this.setValue(index, Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
12803         }
12804     },
12805
12806     /**
12807      * @private
12808      * Returns the nearest thumb to a click event, along with its distance
12809      * @param {Object} local Object containing top and left values from a click event
12810      * @param {String} prop The property of local to compare on. Use 'left' for horizontal sliders, 'top' for vertical ones
12811      * @return {Object} The closest thumb object and its distance from the click event
12812      */
12813     getNearest: function(local, prop) {
12814         var localValue = prop == 'top' ? this.innerEl.getHeight() - local[prop] : local[prop],
12815             clickValue = this.reverseValue(localValue),
12816             nearestDistance = (this.maxValue - this.minValue) + 5, //add a small fudge for the end of the slider 
12817             index = 0,
12818             nearest = null;
12819
12820         for (var i=0; i < this.thumbs.length; i++) {
12821             var thumb = this.thumbs[i],
12822                 value = thumb.value,
12823                 dist  = Math.abs(value - clickValue);
12824
12825             if (Math.abs(dist <= nearestDistance)) {
12826                 nearest = thumb;
12827                 index = i;
12828                 nearestDistance = dist;
12829             }
12830         }
12831         return nearest;
12832     },
12833
12834     /**
12835      * @private
12836      * Handler for any keypresses captured by the slider. If the key is UP or RIGHT, the thumb is moved along to the right
12837      * by this.keyIncrement. If DOWN or LEFT it is moved left. Pressing CTRL moves the slider to the end in either direction
12838      * @param {Ext.EventObject} e The Event object
12839      */
12840     onKeyDown : function(e){
12841         if(this.disabled){e.preventDefault();return;}
12842         var k = e.getKey();
12843         switch(k){
12844             case e.UP:
12845             case e.RIGHT:
12846                 e.stopEvent();
12847                 if(e.ctrlKey){
12848                     this.setValue(this.maxValue, undefined, true);
12849                 }else{
12850                     this.setValue(this.value+this.keyIncrement, undefined, true);
12851                 }
12852             break;
12853             case e.DOWN:
12854             case e.LEFT:
12855                 e.stopEvent();
12856                 if(e.ctrlKey){
12857                     this.setValue(this.minValue, undefined, true);
12858                 }else{
12859                     this.setValue(this.value-this.keyIncrement, undefined, true);
12860                 }
12861             break;
12862             default:
12863                 e.preventDefault();
12864         }
12865     },
12866
12867     /**
12868      * @private
12869      * If using snapping, this takes a desired new value and returns the closest snapped
12870      * value to it
12871      * @param {Number} value The unsnapped value
12872      * @return {Number} The value of the nearest snap target
12873      */
12874     doSnap : function(value){
12875         if (!(this.increment && value)) {
12876             return value;
12877         }
12878         var newValue = value,
12879             inc = this.increment,
12880             m = value % inc;
12881         if (m != 0) {
12882             newValue -= m;
12883             if (m * 2 >= inc) {
12884                 newValue += inc;
12885             } else if (m * 2 < -inc) {
12886                 newValue -= inc;
12887             }
12888         }
12889         return newValue.constrain(this.minValue,  this.maxValue);
12890     },
12891
12892     // private
12893     afterRender : function(){
12894         Ext.slider.MultiSlider.superclass.afterRender.apply(this, arguments);
12895
12896         for (var i=0; i < this.thumbs.length; i++) {
12897             var thumb = this.thumbs[i];
12898
12899             if (thumb.value !== undefined) {
12900                 var v = this.normalizeValue(thumb.value);
12901
12902                 if (v !== thumb.value) {
12903                     // delete this.value;
12904                     this.setValue(i, v, false);
12905                 } else {
12906                     this.moveThumb(i, this.translateValue(v), false);
12907                 }
12908             }
12909         };
12910     },
12911
12912     /**
12913      * @private
12914      * Returns the ratio of pixels to mapped values. e.g. if the slider is 200px wide and maxValue - minValue is 100,
12915      * the ratio is 2
12916      * @return {Number} The ratio of pixels to mapped values
12917      */
12918     getRatio : function(){
12919         var w = this.innerEl.getWidth(),
12920             v = this.maxValue - this.minValue;
12921         return v == 0 ? w : (w/v);
12922     },
12923
12924     /**
12925      * @private
12926      * Returns a snapped, constrained value when given a desired value
12927      * @param {Number} value Raw number value
12928      * @return {Number} The raw value rounded to the correct d.p. and constrained within the set max and min values
12929      */
12930     normalizeValue : function(v){
12931         v = this.doSnap(v);
12932         v = Ext.util.Format.round(v, this.decimalPrecision);
12933         v = v.constrain(this.minValue, this.maxValue);
12934         return v;
12935     },
12936
12937     /**
12938      * Sets the minimum value for the slider instance. If the current value is less than the
12939      * minimum value, the current value will be changed.
12940      * @param {Number} val The new minimum value
12941      */
12942     setMinValue : function(val){
12943         this.minValue = val;
12944         this.syncThumb();
12945
12946         for (var i=0, j = this.thumbs.length; i < j; i++) {
12947             if (this.thumbs[i].value < val) this.thumbs[i].value = val;
12948         }
12949     },
12950
12951     /**
12952      * Sets the maximum value for the slider instance. If the current value is more than the
12953      * maximum value, the current value will be changed.
12954      * @param {Number} val The new maximum value
12955      */
12956     setMaxValue : function(val){
12957         this.maxValue = val;
12958         this.syncThumb();
12959
12960         for (var i=0; i < this.thumbs.length; i++) {
12961             if (this.thumbs[i].value > val) this.thumbs[i].value = val;
12962         }
12963     },
12964
12965     /**
12966      * Programmatically sets the value of the Slider. Ensures that the value is constrained within
12967      * the minValue and maxValue.
12968      * @param {Number} index Index of the thumb to move
12969      * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)
12970      * @param {Boolean} animate Turn on or off animation, defaults to true
12971      */
12972     setValue : function(index, v, animate, changeComplete) {
12973         var thumb = this.thumbs[index],
12974             el    = thumb.el;
12975
12976         v = this.normalizeValue(v);
12977
12978         if (v !== thumb.value && this.fireEvent('beforechange', this, v, thumb.value) !== false) {
12979             thumb.value = v;
12980             this.moveThumb(index, this.translateValue(v), animate !== false);
12981             this.fireEvent('change', this, v, thumb);
12982             if(changeComplete){
12983                 this.fireEvent('changecomplete', this, v, thumb);
12984             }
12985         }
12986     },
12987
12988     /**
12989      * @private
12990      */
12991     translateValue : function(v) {
12992         var ratio = this.getRatio();
12993         return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
12994     },
12995
12996     /**
12997      * @private
12998      * Given a pixel location along the slider, returns the mapped slider value for that pixel.
12999      * E.g. if we have a slider 200px wide with minValue = 100 and maxValue = 500, reverseValue(50)
13000      * returns 200
13001      * @param {Number} pos The position along the slider to return a mapped value for
13002      * @return {Number} The mapped value for the given position
13003      */
13004     reverseValue : function(pos){
13005         var ratio = this.getRatio();
13006         return (pos + (this.minValue * ratio)) / ratio;
13007     },
13008
13009     /**
13010      * @private
13011      * @param {Number} index Index of the thumb to move
13012      */
13013     moveThumb: function(index, v, animate){
13014         var thumb = this.thumbs[index].el;
13015
13016         if(!animate || this.animate === false){
13017             thumb.setLeft(v);
13018         }else{
13019             thumb.shift({left: v, stopFx: true, duration:.35});
13020         }
13021     },
13022
13023     // private
13024     focus : function(){
13025         this.focusEl.focus(10);
13026     },
13027
13028     // private
13029     onResize : function(w, h){
13030         var thumbs = this.thumbs,
13031             len = thumbs.length,
13032             i = 0;
13033             
13034         /*
13035          * If we happen to be animating during a resize, the position of the thumb will likely be off
13036          * when the animation stops. As such, just stop any animations before syncing the thumbs.
13037          */
13038         for(; i < len; ++i){
13039             thumbs[i].el.stopFx();    
13040         }
13041         this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
13042         this.syncThumb();
13043         Ext.slider.MultiSlider.superclass.onResize.apply(this, arguments);
13044     },
13045
13046     //private
13047     onDisable: function(){
13048         Ext.slider.MultiSlider.superclass.onDisable.call(this);
13049
13050         for (var i=0; i < this.thumbs.length; i++) {
13051             var thumb = this.thumbs[i],
13052                 el    = thumb.el;
13053
13054             thumb.disable();
13055
13056             if(Ext.isIE){
13057                 //IE breaks when using overflow visible and opacity other than 1.
13058                 //Create a place holder for the thumb and display it.
13059                 var xy = el.getXY();
13060                 el.hide();
13061
13062                 this.innerEl.addClass(this.disabledClass).dom.disabled = true;
13063
13064                 if (!this.thumbHolder) {
13065                     this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});
13066                 }
13067
13068                 this.thumbHolder.show().setXY(xy);
13069             }
13070         }
13071     },
13072
13073     //private
13074     onEnable: function(){
13075         Ext.slider.MultiSlider.superclass.onEnable.call(this);
13076
13077         for (var i=0; i < this.thumbs.length; i++) {
13078             var thumb = this.thumbs[i],
13079                 el    = thumb.el;
13080
13081             thumb.enable();
13082
13083             if (Ext.isIE) {
13084                 this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
13085
13086                 if (this.thumbHolder) this.thumbHolder.hide();
13087
13088                 el.show();
13089                 this.syncThumb();
13090             }
13091         }
13092     },
13093
13094     /**
13095      * Synchronizes the thumb position to the proper proportion of the total component width based
13096      * on the current slider {@link #value}.  This will be called automatically when the Slider
13097      * is resized by a layout, but if it is rendered auto width, this method can be called from
13098      * another resize handler to sync the Slider if necessary.
13099      */
13100     syncThumb : function() {
13101         if (this.rendered) {
13102             for (var i=0; i < this.thumbs.length; i++) {
13103                 this.moveThumb(i, this.translateValue(this.thumbs[i].value));
13104             }
13105         }
13106     },
13107
13108     /**
13109      * Returns the current value of the slider
13110      * @param {Number} index The index of the thumb to return a value for
13111      * @return {Number} The current value of the slider
13112      */
13113     getValue : function(index) {
13114         return this.thumbs[index].value;
13115     },
13116
13117     /**
13118      * Returns an array of values - one for the location of each thumb
13119      * @return {Array} The set of thumb values
13120      */
13121     getValues: function() {
13122         var values = [];
13123
13124         for (var i=0; i < this.thumbs.length; i++) {
13125             values.push(this.thumbs[i].value);
13126         }
13127
13128         return values;
13129     },
13130
13131     // private
13132     beforeDestroy : function(){
13133         Ext.destroyMembers(this, 'endEl', 'innerEl', 'thumb', 'halfThumb', 'focusEl', 'tracker', 'thumbHolder');
13134         Ext.slider.MultiSlider.superclass.beforeDestroy.call(this);
13135     }
13136 });
13137
13138 Ext.reg('multislider', Ext.slider.MultiSlider);
13139
13140 /**
13141  * @class Ext.slider.SingleSlider
13142  * @extends Ext.slider.MultiSlider
13143  * Slider which supports vertical or horizontal orientation, keyboard adjustments,
13144  * configurable snapping, axis clicking and animation. Can be added as an item to
13145  * any container. Example usage:
13146 <pre><code>
13147 new Ext.slider.SingleSlider({
13148     renderTo: Ext.getBody(),
13149     width: 200,
13150     value: 50,
13151     increment: 10,
13152     minValue: 0,
13153     maxValue: 100
13154 });
13155 </code></pre>
13156  * The class Ext.slider.SingleSlider is aliased to Ext.Slider for backwards compatibility.
13157  */
13158 Ext.slider.SingleSlider = Ext.extend(Ext.slider.MultiSlider, {
13159     constructor: function(config) {
13160       config = config || {};
13161
13162       Ext.applyIf(config, {
13163           values: [config.value || 0]
13164       });
13165
13166       Ext.slider.SingleSlider.superclass.constructor.call(this, config);
13167     },
13168
13169     /**
13170      * Returns the current value of the slider
13171      * @return {Number} The current value of the slider
13172      */
13173     getValue: function() {
13174         //just returns the value of the first thumb, which should be the only one in a single slider
13175         return Ext.slider.SingleSlider.superclass.getValue.call(this, 0);
13176     },
13177
13178     /**
13179      * Programmatically sets the value of the Slider. Ensures that the value is constrained within
13180      * the minValue and maxValue.
13181      * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)
13182      * @param {Boolean} animate Turn on or off animation, defaults to true
13183      */
13184     setValue: function(value, animate) {
13185         var args = Ext.toArray(arguments),
13186             len  = args.length;
13187
13188         //this is to maintain backwards compatiblity for sliders with only one thunb. Usually you must pass the thumb
13189         //index to setValue, but if we only have one thumb we inject the index here first if given the multi-slider
13190         //signature without the required index. The index will always be 0 for a single slider
13191         if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
13192             args.unshift(0);
13193         }
13194
13195         return Ext.slider.SingleSlider.superclass.setValue.apply(this, args);
13196     },
13197
13198     /**
13199      * Synchronizes the thumb position to the proper proportion of the total component width based
13200      * on the current slider {@link #value}.  This will be called automatically when the Slider
13201      * is resized by a layout, but if it is rendered auto width, this method can be called from
13202      * another resize handler to sync the Slider if necessary.
13203      */
13204     syncThumb : function() {
13205         return Ext.slider.SingleSlider.superclass.syncThumb.apply(this, [0].concat(arguments));
13206     },
13207     
13208     // private
13209     getNearest : function(){
13210         // Since there's only 1 thumb, it's always the nearest
13211         return this.thumbs[0];    
13212     }
13213 });
13214
13215 //backwards compatibility
13216 Ext.Slider = Ext.slider.SingleSlider;
13217
13218 Ext.reg('slider', Ext.slider.SingleSlider);
13219
13220 // private class to support vertical sliders
13221 Ext.slider.Vertical = {
13222     onResize : function(w, h){
13223         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
13224         this.syncThumb();
13225     },
13226
13227     getRatio : function(){
13228         var h = this.innerEl.getHeight(),
13229             v = this.maxValue - this.minValue;
13230         return h/v;
13231     },
13232
13233     moveThumb: function(index, v, animate) {
13234         var thumb = this.thumbs[index],
13235             el    = thumb.el;
13236
13237         if (!animate || this.animate === false) {
13238             el.setBottom(v);
13239         } else {
13240             el.shift({bottom: v, stopFx: true, duration:.35});
13241         }
13242     },
13243
13244     onClickChange : function(local) {
13245         if (local.left > this.clickRange[0] && local.left < this.clickRange[1]) {
13246             var thumb = this.getNearest(local, 'top'),
13247                 index = thumb.index,
13248                 value = this.minValue + this.reverseValue(this.innerEl.getHeight() - local.top);
13249
13250             this.setValue(index, Ext.util.Format.round(value, this.decimalPrecision), undefined, true);
13251         }
13252     }
13253 };
13254
13255 //private class to support vertical dragging of thumbs within a slider
13256 Ext.slider.Thumb.Vertical = {
13257     getNewValue: function() {
13258         var slider   = this.slider,
13259             innerEl  = slider.innerEl,
13260             pos      = innerEl.translatePoints(this.tracker.getXY()),
13261             bottom   = innerEl.getHeight() - pos.top;
13262
13263         return slider.minValue + Ext.util.Format.round(bottom / slider.getRatio(), slider.decimalPrecision);
13264     }
13265 };
13266 /**
13267  * @class Ext.ProgressBar
13268  * @extends Ext.BoxComponent
13269  * <p>An updateable progress bar component.  The progress bar supports two different modes: manual and automatic.</p>
13270  * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the
13271  * progress bar as needed from your own code.  This method is most appropriate when you want to show progress
13272  * throughout an operation that has predictable points of interest at which you can update the control.</p>
13273  * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it
13274  * once the operation is complete.  You can optionally have the progress bar wait for a specific amount of time
13275  * and then clear itself.  Automatic mode is most appropriate for timed operations or asynchronous operations in
13276  * which you have no need for indicating intermediate progress.</p>
13277  * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0)
13278  * @cfg {String} text The progress bar text (defaults to '')
13279  * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress
13280  * bar's internal text element)
13281  * @cfg {String} id The progress bar element's id (defaults to an auto-generated id)
13282  * @xtype progress
13283  */
13284 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
13285    /**
13286     * @cfg {String} baseCls
13287     * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress')
13288     */
13289     baseCls : 'x-progress',
13290     
13291     /**
13292     * @cfg {Boolean} animate
13293     * True to animate the progress bar during transitions (defaults to false)
13294     */
13295     animate : false,
13296
13297     // private
13298     waitTimer : null,
13299
13300     // private
13301     initComponent : function(){
13302         Ext.ProgressBar.superclass.initComponent.call(this);
13303         this.addEvents(
13304             /**
13305              * @event update
13306              * Fires after each update interval
13307              * @param {Ext.ProgressBar} this
13308              * @param {Number} The current progress value
13309              * @param {String} The current progress text
13310              */
13311             "update"
13312         );
13313     },
13314
13315     // private
13316     onRender : function(ct, position){
13317         var tpl = new Ext.Template(
13318             '<div class="{cls}-wrap">',
13319                 '<div class="{cls}-inner">',
13320                     '<div class="{cls}-bar">',
13321                         '<div class="{cls}-text">',
13322                             '<div>&#160;</div>',
13323                         '</div>',
13324                     '</div>',
13325                     '<div class="{cls}-text {cls}-text-back">',
13326                         '<div>&#160;</div>',
13327                     '</div>',
13328                 '</div>',
13329             '</div>'
13330         );
13331
13332         this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
13333             : tpl.append(ct, {cls: this.baseCls}, true);
13334                 
13335         if(this.id){
13336             this.el.dom.id = this.id;
13337         }
13338         var inner = this.el.dom.firstChild;
13339         this.progressBar = Ext.get(inner.firstChild);
13340
13341         if(this.textEl){
13342             //use an external text el
13343             this.textEl = Ext.get(this.textEl);
13344             delete this.textTopEl;
13345         }else{
13346             //setup our internal layered text els
13347             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
13348             var textBackEl = Ext.get(inner.childNodes[1]);
13349             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
13350             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
13351             this.textEl.setWidth(inner.offsetWidth);
13352         }
13353         this.progressBar.setHeight(inner.offsetHeight);
13354     },
13355     
13356     // private
13357     afterRender : function(){
13358         Ext.ProgressBar.superclass.afterRender.call(this);
13359         if(this.value){
13360             this.updateProgress(this.value, this.text);
13361         }else{
13362             this.updateText(this.text);
13363         }
13364     },
13365
13366     /**
13367      * Updates the progress bar value, and optionally its text.  If the text argument is not specified,
13368      * any existing text value will be unchanged.  To blank out existing text, pass ''.  Note that even
13369      * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for
13370      * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control.
13371      * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0)
13372      * @param {String} text (optional) The string to display in the progress text element (defaults to '')
13373      * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is
13374      * not specified, the default for the class is used (default to false)
13375      * @return {Ext.ProgressBar} this
13376      */
13377     updateProgress : function(value, text, animate){
13378         this.value = value || 0;
13379         if(text){
13380             this.updateText(text);
13381         }
13382         if(this.rendered && !this.isDestroyed){
13383             var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
13384             this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
13385             if(this.textTopEl){
13386                 //textTopEl should be the same width as the bar so overflow will clip as the bar moves
13387                 this.textTopEl.removeClass('x-hidden').setWidth(w);
13388             }
13389         }
13390         this.fireEvent('update', this, value, text);
13391         return this;
13392     },
13393
13394     /**
13395      * Initiates an auto-updating progress bar.  A duration can be specified, in which case the progress
13396      * bar will automatically reset after a fixed amount of time and optionally call a callback function
13397      * if specified.  If no duration is passed in, then the progress bar will run indefinitely and must
13398      * be manually cleared by calling {@link #reset}.  The wait method accepts a config object with
13399      * the following properties:
13400      * <pre>
13401 Property   Type          Description
13402 ---------- ------------  ----------------------------------------------------------------------
13403 duration   Number        The length of time in milliseconds that the progress bar should
13404                          run before resetting itself (defaults to undefined, in which case it
13405                          will run indefinitely until reset is called)
13406 interval   Number        The length of time in milliseconds between each progress update
13407                          (defaults to 1000 ms)
13408 animate    Boolean       Whether to animate the transition of the progress bar. If this value is
13409                          not specified, the default for the class is used.                                                   
13410 increment  Number        The number of progress update segments to display within the progress
13411                          bar (defaults to 10).  If the bar reaches the end and is still
13412                          updating, it will automatically wrap back to the beginning.
13413 text       String        Optional text to display in the progress bar element (defaults to '').
13414 fn         Function      A callback function to execute after the progress bar finishes auto-
13415                          updating.  The function will be called with no arguments.  This function
13416                          will be ignored if duration is not specified since in that case the
13417                          progress bar can only be stopped programmatically, so any required function
13418                          should be called by the same code after it resets the progress bar.
13419 scope      Object        The scope that is passed to the callback function (only applies when
13420                          duration and fn are both passed).
13421 </pre>
13422          *
13423          * Example usage:
13424          * <pre><code>
13425 var p = new Ext.ProgressBar({
13426    renderTo: 'my-el'
13427 });
13428
13429 //Wait for 5 seconds, then update the status el (progress bar will auto-reset)
13430 p.wait({
13431    interval: 100, //bar will move fast!
13432    duration: 5000,
13433    increment: 15,
13434    text: 'Updating...',
13435    scope: this,
13436    fn: function(){
13437       Ext.fly('status').update('Done!');
13438    }
13439 });
13440
13441 //Or update indefinitely until some async action completes, then reset manually
13442 p.wait();
13443 myAction.on('complete', function(){
13444     p.reset();
13445     Ext.fly('status').update('Done!');
13446 });
13447 </code></pre>
13448      * @param {Object} config (optional) Configuration options
13449      * @return {Ext.ProgressBar} this
13450      */
13451     wait : function(o){
13452         if(!this.waitTimer){
13453             var scope = this;
13454             o = o || {};
13455             this.updateText(o.text);
13456             this.waitTimer = Ext.TaskMgr.start({
13457                 run: function(i){
13458                     var inc = o.increment || 10;
13459                     i -= 1;
13460                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
13461                 },
13462                 interval: o.interval || 1000,
13463                 duration: o.duration,
13464                 onStop: function(){
13465                     if(o.fn){
13466                         o.fn.apply(o.scope || this);
13467                     }
13468                     this.reset();
13469                 },
13470                 scope: scope
13471             });
13472         }
13473         return this;
13474     },
13475
13476     /**
13477      * Returns true if the progress bar is currently in a {@link #wait} operation
13478      * @return {Boolean} True if waiting, else false
13479      */
13480     isWaiting : function(){
13481         return this.waitTimer !== null;
13482     },
13483
13484     /**
13485      * Updates the progress bar text.  If specified, textEl will be updated, otherwise the progress
13486      * bar itself will display the updated text.
13487      * @param {String} text (optional) The string to display in the progress text element (defaults to '')
13488      * @return {Ext.ProgressBar} this
13489      */
13490     updateText : function(text){
13491         this.text = text || '&#160;';
13492         if(this.rendered){
13493             this.textEl.update(this.text);
13494         }
13495         return this;
13496     },
13497     
13498     /**
13499      * Synchronizes the inner bar width to the proper proportion of the total componet width based
13500      * on the current progress {@link #value}.  This will be called automatically when the ProgressBar
13501      * is resized by a layout, but if it is rendered auto width, this method can be called from
13502      * another resize handler to sync the ProgressBar if necessary.
13503      */
13504     syncProgressBar : function(){
13505         if(this.value){
13506             this.updateProgress(this.value, this.text);
13507         }
13508         return this;
13509     },
13510
13511     /**
13512      * Sets the size of the progress bar.
13513      * @param {Number} width The new width in pixels
13514      * @param {Number} height The new height in pixels
13515      * @return {Ext.ProgressBar} this
13516      */
13517     setSize : function(w, h){
13518         Ext.ProgressBar.superclass.setSize.call(this, w, h);
13519         if(this.textTopEl){
13520             var inner = this.el.dom.firstChild;
13521             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
13522         }
13523         this.syncProgressBar();
13524         return this;
13525     },
13526
13527     /**
13528      * Resets the progress bar value to 0 and text to empty string.  If hide = true, the progress
13529      * bar will also be hidden (using the {@link #hideMode} property internally).
13530      * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false)
13531      * @return {Ext.ProgressBar} this
13532      */
13533     reset : function(hide){
13534         this.updateProgress(0);
13535         if(this.textTopEl){
13536             this.textTopEl.addClass('x-hidden');
13537         }
13538         this.clearTimer();
13539         if(hide === true){
13540             this.hide();
13541         }
13542         return this;
13543     },
13544     
13545     // private
13546     clearTimer : function(){
13547         if(this.waitTimer){
13548             this.waitTimer.onStop = null; //prevent recursion
13549             Ext.TaskMgr.stop(this.waitTimer);
13550             this.waitTimer = null;
13551         }
13552     },
13553     
13554     onDestroy: function(){
13555         this.clearTimer();
13556         if(this.rendered){
13557             if(this.textEl.isComposite){
13558                 this.textEl.clear();
13559             }
13560             Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
13561         }
13562         Ext.ProgressBar.superclass.onDestroy.call(this);
13563     }
13564 });
13565 Ext.reg('progress', Ext.ProgressBar);