Upgrade to ExtJS 3.1.1 - Released 02/08/2010
[extjs.git] / pkgs / cmp-foundation-debug.js
1 /*!
2  * Ext JS Library 3.1.1
3  * Copyright(c) 2006-2010 Ext JS, LLC
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**
8  * @class Ext.ComponentMgr
9  * <p>Provides a registry of all Components (instances of {@link Ext.Component} or any subclass
10  * thereof) on a page so that they can be easily accessed by {@link Ext.Component component}
11  * {@link Ext.Component#id id} (see {@link #get}, or the convenience method {@link Ext#getCmp Ext.getCmp}).</p>
12  * <p>This object also provides a registry of available Component <i>classes</i>
13  * indexed by a mnemonic code known as the Component's {@link Ext.Component#xtype xtype}.
14  * The <code>{@link Ext.Component#xtype xtype}</code> provides a way to avoid instantiating child Components
15  * when creating a full, nested config object for a complete Ext page.</p>
16  * <p>A child Component may be specified simply as a <i>config object</i>
17  * as long as the correct <code>{@link Ext.Component#xtype xtype}</code> is specified so that if and when the Component
18  * needs rendering, the correct type can be looked up for lazy instantiation.</p>
19  * <p>For a list of all available <code>{@link Ext.Component#xtype xtypes}</code>, see {@link Ext.Component}.</p>
20  * @singleton
21  */
22 Ext.ComponentMgr = function(){
23     var all = new Ext.util.MixedCollection();
24     var types = {};
25     var ptypes = {};
26
27     return {
28         /**
29          * Registers a component.
30          * @param {Ext.Component} c The component
31          */
32         register : function(c){
33             all.add(c);
34         },
35
36         /**
37          * Unregisters a component.
38          * @param {Ext.Component} c The component
39          */
40         unregister : function(c){
41             all.remove(c);
42         },
43
44         /**
45          * Returns a component by {@link Ext.Component#id id}.
46          * For additional details see {@link Ext.util.MixedCollection#get}.
47          * @param {String} id The component {@link Ext.Component#id id}
48          * @return Ext.Component The Component, <code>undefined</code> if not found, or <code>null</code> if a
49          * Class was found.
50          */
51         get : function(id){
52             return all.get(id);
53         },
54
55         /**
56          * Registers a function that will be called when a Component with the specified id is added to ComponentMgr. This will happen on instantiation.
57          * @param {String} id The component {@link Ext.Component#id id}
58          * @param {Function} fn The callback function
59          * @param {Object} scope The scope (<code>this</code> reference) in which the callback is executed. Defaults to the Component.
60          */
61         onAvailable : function(id, fn, scope){
62             all.on("add", function(index, o){
63                 if(o.id == id){
64                     fn.call(scope || o, o);
65                     all.un("add", fn, scope);
66                 }
67             });
68         },
69
70         /**
71          * The MixedCollection used internally for the component cache. An example usage may be subscribing to
72          * events on the MixedCollection to monitor addition or removal.  Read-only.
73          * @type {MixedCollection}
74          */
75         all : all,
76         
77         /**
78          * 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     // private
1031     ctype : 'Ext.Component',
1032
1033     // private
1034     actionMode : 'el',
1035
1036     // private
1037     getActionEl : function(){
1038         return this[this.actionMode];
1039     },
1040
1041     initPlugin : function(p){
1042         if(p.ptype && !Ext.isFunction(p.init)){
1043             p = Ext.ComponentMgr.createPlugin(p);
1044         }else if(Ext.isString(p)){
1045             p = Ext.ComponentMgr.createPlugin({
1046                 ptype: p
1047             });
1048         }
1049         p.init(this);
1050         return p;
1051     },
1052
1053     /* // protected
1054      * Function to be implemented by Component subclasses to be part of standard component initialization flow (it is empty by default).
1055      * <pre><code>
1056 // Traditional constructor:
1057 Ext.Foo = function(config){
1058     // call superclass constructor:
1059     Ext.Foo.superclass.constructor.call(this, config);
1060
1061     this.addEvents({
1062         // add events
1063     });
1064 };
1065 Ext.extend(Ext.Foo, Ext.Bar, {
1066    // class body
1067 }
1068
1069 // initComponent replaces the constructor:
1070 Ext.Foo = Ext.extend(Ext.Bar, {
1071     initComponent : function(){
1072         // call superclass initComponent
1073         Ext.Container.superclass.initComponent.call(this);
1074
1075         this.addEvents({
1076             // add events
1077         });
1078     }
1079 }
1080 </code></pre>
1081      */
1082     initComponent : Ext.emptyFn,
1083
1084     /**
1085      * <p>Render this Component into the passed HTML element.</p>
1086      * <p><b>If you are using a {@link Ext.Container Container} object to house this Component, then
1087      * do not use the render method.</b></p>
1088      * <p>A Container's child Components are rendered by that Container's
1089      * {@link Ext.Container#layout layout} manager when the Container is first rendered.</p>
1090      * <p>Certain layout managers allow dynamic addition of child components. Those that do
1091      * include {@link Ext.layout.CardLayout}, {@link Ext.layout.AnchorLayout},
1092      * {@link Ext.layout.FormLayout}, {@link Ext.layout.TableLayout}.</p>
1093      * <p>If the Container is already rendered when a new child Component is added, you may need to call
1094      * the Container's {@link Ext.Container#doLayout doLayout} to refresh the view which causes any
1095      * unrendered child Components to be rendered. This is required so that you can add multiple
1096      * child components if needed while only refreshing the layout once.</p>
1097      * <p>When creating complex UIs, it is important to remember that sizing and positioning
1098      * of child items is the responsibility of the Container's {@link Ext.Container#layout layout} manager.
1099      * If you expect child items to be sized in response to user interactions, you must
1100      * configure the Container with a layout manager which creates and manages the type of layout you
1101      * have in mind.</p>
1102      * <p><b>Omitting the Container's {@link Ext.Container#layout layout} config means that a basic
1103      * layout manager is used which does nothing but render child components sequentially into the
1104      * Container. No sizing or positioning will be performed in this situation.</b></p>
1105      * @param {Element/HTMLElement/String} container (optional) The element this Component should be
1106      * rendered into. If it is being created from existing markup, this should be omitted.
1107      * @param {String/Number} position (optional) The element ID or DOM node index within the container <b>before</b>
1108      * which this component will be inserted (defaults to appending to the end of the container)
1109      */
1110     render : function(container, position){
1111         if(!this.rendered && this.fireEvent('beforerender', this) !== false){
1112             if(!container && this.el){
1113                 this.el = Ext.get(this.el);
1114                 container = this.el.dom.parentNode;
1115                 this.allowDomMove = false;
1116             }
1117             this.container = Ext.get(container);
1118             if(this.ctCls){
1119                 this.container.addClass(this.ctCls);
1120             }
1121             this.rendered = true;
1122             if(position !== undefined){
1123                 if(Ext.isNumber(position)){
1124                     position = this.container.dom.childNodes[position];
1125                 }else{
1126                     position = Ext.getDom(position);
1127                 }
1128             }
1129             this.onRender(this.container, position || null);
1130             if(this.autoShow){
1131                 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
1132             }
1133             if(this.cls){
1134                 this.el.addClass(this.cls);
1135                 delete this.cls;
1136             }
1137             if(this.style){
1138                 this.el.applyStyles(this.style);
1139                 delete this.style;
1140             }
1141             if(this.overCls){
1142                 this.el.addClassOnOver(this.overCls);
1143             }
1144             this.fireEvent('render', this);
1145
1146
1147             // Populate content of the component with html, contentEl or
1148             // a tpl.
1149             var contentTarget = this.getContentTarget();
1150             if (this.html){
1151                 contentTarget.update(Ext.DomHelper.markup(this.html));
1152                 delete this.html;
1153             }
1154             if (this.contentEl){
1155                 var ce = Ext.getDom(this.contentEl);
1156                 Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
1157                 contentTarget.appendChild(ce);
1158             }
1159             if (this.tpl) {
1160                 if (!this.tpl.compile) {
1161                     this.tpl = new Ext.XTemplate(this.tpl);
1162                 }
1163                 if (this.data) {
1164                     this.tpl[this.tplWriteMode](contentTarget, this.data);
1165                     delete this.data;
1166                 }
1167             }
1168             this.afterRender(this.container);
1169
1170
1171             if(this.hidden){
1172                 // call this so we don't fire initial hide events.
1173                 this.doHide();
1174             }
1175             if(this.disabled){
1176                 // pass silent so the event doesn't fire the first time.
1177                 this.disable(true);
1178             }
1179
1180             if(this.stateful !== false){
1181                 this.initStateEvents();
1182             }
1183             this.fireEvent('afterrender', this);
1184         }
1185         return this;
1186     },
1187
1188
1189     /**
1190      * Update the content area of a component.
1191      * @param {Mixed} htmlOrData
1192      * If this component has been configured with a template via the tpl config
1193      * then it will use this argument as data to populate the template.
1194      * If this component was not configured with a template, the components
1195      * content area will be updated via Ext.Element update
1196      * @param {Boolean} loadScripts
1197      * (optional) Only legitimate when using the html configuration. Defaults to false
1198      * @param {Function} callback
1199      * (optional) Only legitimate when using the html configuration. Callback to execute when scripts have finished loading
1200      */
1201     update: function(htmlOrData, loadScripts, cb) {
1202         var contentTarget = this.getContentTarget();
1203         if (this.tpl && typeof htmlOrData !== "string") {
1204             this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
1205         } else {
1206             var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
1207             contentTarget.update(html, loadScripts, cb);
1208         }
1209     },
1210
1211
1212     /**
1213      * @private
1214      * Method to manage awareness of when components are added to their
1215      * respective Container, firing an added event.
1216      * References are established at add time rather than at render time.
1217      * @param {Ext.Container} container Container which holds the component
1218      * @param {number} pos Position at which the component was added
1219      */
1220     onAdded : function(container, pos) {
1221         this.ownerCt = container;
1222         this.initRef();
1223         this.fireEvent('added', this, container, pos);
1224     },
1225
1226     /**
1227      * @private
1228      * Method to manage awareness of when components are removed from their
1229      * respective Container, firing an removed event. References are properly
1230      * cleaned up after removing a component from its owning container.
1231      */
1232     onRemoved : function() {
1233         this.removeRef();
1234         this.fireEvent('removed', this, this.ownerCt);
1235         delete this.ownerCt;
1236     },
1237
1238     /**
1239      * @private
1240      * Method to establish a reference to a component.
1241      */
1242     initRef : function() {
1243         /**
1244          * @cfg {String} ref
1245          * <p>A path specification, relative to the Component's <code>{@link #ownerCt}</code>
1246          * specifying into which ancestor Container to place a named reference to this Component.</p>
1247          * <p>The ancestor axis can be traversed by using '/' characters in the path.
1248          * For example, to put a reference to a Toolbar Button into <i>the Panel which owns the Toolbar</i>:</p><pre><code>
1249 var myGrid = new Ext.grid.EditorGridPanel({
1250     title: 'My EditorGridPanel',
1251     store: myStore,
1252     colModel: myColModel,
1253     tbar: [{
1254         text: 'Save',
1255         handler: saveChanges,
1256         disabled: true,
1257         ref: '../saveButton'
1258     }],
1259     listeners: {
1260         afteredit: function() {
1261 //          The button reference is in the GridPanel
1262             myGrid.saveButton.enable();
1263         }
1264     }
1265 });
1266 </code></pre>
1267          * <p>In the code above, if the <code>ref</code> had been <code>'saveButton'</code>
1268          * the reference would have been placed into the Toolbar. Each '/' in the <code>ref</code>
1269          * moves up one level from the Component's <code>{@link #ownerCt}</code>.</p>
1270          * <p>Also see the <code>{@link #added}</code> and <code>{@link #removed}</code> events.</p>
1271          */
1272         if(this.ref && !this.refOwner){
1273             var levels = this.ref.split('/'),
1274                 last = levels.length,
1275                 i = 0,
1276                 t = this;
1277
1278             while(t && i < last){
1279                 t = t.ownerCt;
1280                 ++i;
1281             }
1282             if(t){
1283                 t[this.refName = levels[--i]] = this;
1284                 /**
1285                  * @type Ext.Container
1286                  * @property refOwner
1287                  * The ancestor Container into which the {@link #ref} reference was inserted if this Component
1288                  * is a child of a Container, and has been configured with a <code>ref</code>.
1289                  */
1290                 this.refOwner = t;
1291             }
1292         }
1293     },
1294
1295     removeRef : function() {
1296         if (this.refOwner && this.refName) {
1297             delete this.refOwner[this.refName];
1298             delete this.refOwner;
1299         }
1300     },
1301
1302     // private
1303     initState : function(){
1304         if(Ext.state.Manager){
1305             var id = this.getStateId();
1306             if(id){
1307                 var state = Ext.state.Manager.get(id);
1308                 if(state){
1309                     if(this.fireEvent('beforestaterestore', this, state) !== false){
1310                         this.applyState(Ext.apply({}, state));
1311                         this.fireEvent('staterestore', this, state);
1312                     }
1313                 }
1314             }
1315         }
1316     },
1317
1318     // private
1319     getStateId : function(){
1320         return this.stateId || ((/^(ext-comp-|ext-gen)/).test(String(this.id)) ? null : this.id);
1321     },
1322
1323     // private
1324     initStateEvents : function(){
1325         if(this.stateEvents){
1326             for(var i = 0, e; e = this.stateEvents[i]; i++){
1327                 this.on(e, this.saveState, this, {delay:100});
1328             }
1329         }
1330     },
1331
1332     // private
1333     applyState : function(state){
1334         if(state){
1335             Ext.apply(this, state);
1336         }
1337     },
1338
1339     // private
1340     getState : function(){
1341         return null;
1342     },
1343
1344     // private
1345     saveState : function(){
1346         if(Ext.state.Manager && this.stateful !== false){
1347             var id = this.getStateId();
1348             if(id){
1349                 var state = this.getState();
1350                 if(this.fireEvent('beforestatesave', this, state) !== false){
1351                     Ext.state.Manager.set(id, state);
1352                     this.fireEvent('statesave', this, state);
1353                 }
1354             }
1355         }
1356     },
1357
1358     /**
1359      * Apply this component to existing markup that is valid. With this function, no call to render() is required.
1360      * @param {String/HTMLElement} el
1361      */
1362     applyToMarkup : function(el){
1363         this.allowDomMove = false;
1364         this.el = Ext.get(el);
1365         this.render(this.el.dom.parentNode);
1366     },
1367
1368     /**
1369      * Adds a CSS class to the component's underlying element.
1370      * @param {string} cls The CSS class name to add
1371      * @return {Ext.Component} this
1372      */
1373     addClass : function(cls){
1374         if(this.el){
1375             this.el.addClass(cls);
1376         }else{
1377             this.cls = this.cls ? this.cls + ' ' + cls : cls;
1378         }
1379         return this;
1380     },
1381
1382     /**
1383      * Removes a CSS class from the component's underlying element.
1384      * @param {string} cls The CSS class name to remove
1385      * @return {Ext.Component} this
1386      */
1387     removeClass : function(cls){
1388         if(this.el){
1389             this.el.removeClass(cls);
1390         }else if(this.cls){
1391             this.cls = this.cls.split(' ').remove(cls).join(' ');
1392         }
1393         return this;
1394     },
1395
1396     // private
1397     // default function is not really useful
1398     onRender : function(ct, position){
1399         if(!this.el && this.autoEl){
1400             if(Ext.isString(this.autoEl)){
1401                 this.el = document.createElement(this.autoEl);
1402             }else{
1403                 var div = document.createElement('div');
1404                 Ext.DomHelper.overwrite(div, this.autoEl);
1405                 this.el = div.firstChild;
1406             }
1407             if (!this.el.id) {
1408                 this.el.id = this.getId();
1409             }
1410         }
1411         if(this.el){
1412             this.el = Ext.get(this.el);
1413             if(this.allowDomMove !== false){
1414                 ct.dom.insertBefore(this.el.dom, position);
1415                 if (div) {
1416                     Ext.removeNode(div);
1417                     div = null;
1418                 }
1419             }
1420         }
1421     },
1422
1423     // private
1424     getAutoCreate : function(){
1425         var cfg = Ext.isObject(this.autoCreate) ?
1426                       this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
1427         if(this.id && !cfg.id){
1428             cfg.id = this.id;
1429         }
1430         return cfg;
1431     },
1432
1433     // private
1434     afterRender : Ext.emptyFn,
1435
1436     /**
1437      * Destroys this component by purging any event listeners, removing the component's element from the DOM,
1438      * removing the component from its {@link Ext.Container} (if applicable) and unregistering it from
1439      * {@link Ext.ComponentMgr}.  Destruction is generally handled automatically by the framework and this method
1440      * should usually not need to be called directly.
1441      *
1442      */
1443     destroy : function(){
1444         if(!this.isDestroyed){
1445             if(this.fireEvent('beforedestroy', this) !== false){
1446                 this.destroying = true;
1447                 this.beforeDestroy();
1448                 if(this.ownerCt && this.ownerCt.remove){
1449                     this.ownerCt.remove(this, false);
1450                 }
1451                 if(this.rendered){
1452                     this.el.remove();
1453                     if(this.actionMode == 'container' || this.removeMode == 'container'){
1454                         this.container.remove();
1455                     }
1456                 }
1457                 this.onDestroy();
1458                 Ext.ComponentMgr.unregister(this);
1459                 this.fireEvent('destroy', this);
1460                 this.purgeListeners();
1461                 this.destroying = false;
1462                 this.isDestroyed = true;
1463             }
1464         }
1465     },
1466
1467     deleteMembers : function(){
1468         var args = arguments;
1469         for(var i = 0, len = args.length; i < len; ++i){
1470             delete this[args[i]];
1471         }
1472     },
1473
1474     // private
1475     beforeDestroy : Ext.emptyFn,
1476
1477     // private
1478     onDestroy  : Ext.emptyFn,
1479
1480     /**
1481      * <p>Returns the {@link Ext.Element} which encapsulates this Component.</p>
1482      * <p>This will <i>usually</i> be a &lt;DIV> element created by the class's onRender method, but
1483      * that may be overridden using the {@link #autoEl} config.</p>
1484      * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br>
1485      * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners
1486      * for this Component's own Observable events), see the {@link #listeners} config for a suggestion,
1487      * or use a render listener directly:</p><pre><code>
1488 new Ext.Panel({
1489     title: 'The Clickable Panel',
1490     listeners: {
1491         render: function(p) {
1492             // Append the Panel to the click handler&#39;s argument list.
1493             p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));
1494         },
1495         single: true  // Remove the listener after first invocation
1496     }
1497 });
1498 </code></pre>
1499      * @return {Ext.Element} The Element which encapsulates this Component.
1500      */
1501     getEl : function(){
1502         return this.el;
1503     },
1504
1505     // private
1506     getContentTarget : function(){
1507         return this.el;
1508     },
1509
1510     /**
1511      * Returns the <code>id</code> of this component or automatically generates and
1512      * returns an <code>id</code> if an <code>id</code> is not defined yet:<pre><code>
1513      * 'ext-comp-' + (++Ext.Component.AUTO_ID)
1514      * </code></pre>
1515      * @return {String} id
1516      */
1517     getId : function(){
1518         return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
1519     },
1520
1521     /**
1522      * Returns the <code>{@link #itemId}</code> of this component.  If an
1523      * <code>{@link #itemId}</code> was not assigned through configuration the
1524      * <code>id</code> is returned using <code>{@link #getId}</code>.
1525      * @return {String}
1526      */
1527     getItemId : function(){
1528         return this.itemId || this.getId();
1529     },
1530
1531     /**
1532      * Try to focus this component.
1533      * @param {Boolean} selectText (optional) If applicable, true to also select the text in this component
1534      * @param {Boolean/Number} delay (optional) Delay the focus this number of milliseconds (true for 10 milliseconds)
1535      * @return {Ext.Component} this
1536      */
1537     focus : function(selectText, delay){
1538         if(delay){
1539             this.focus.defer(Ext.isNumber(delay) ? delay : 10, this, [selectText, false]);
1540             return;
1541         }
1542         if(this.rendered){
1543             this.el.focus();
1544             if(selectText === true){
1545                 this.el.dom.select();
1546             }
1547         }
1548         return this;
1549     },
1550
1551     // private
1552     blur : function(){
1553         if(this.rendered){
1554             this.el.blur();
1555         }
1556         return this;
1557     },
1558
1559     /**
1560      * Disable this component and fire the 'disable' event.
1561      * @return {Ext.Component} this
1562      */
1563     disable : function(/* private */ silent){
1564         if(this.rendered){
1565             this.onDisable();
1566         }
1567         this.disabled = true;
1568         if(silent !== true){
1569             this.fireEvent('disable', this);
1570         }
1571         return this;
1572     },
1573
1574     // private
1575     onDisable : function(){
1576         this.getActionEl().addClass(this.disabledClass);
1577         this.el.dom.disabled = true;
1578     },
1579
1580     /**
1581      * Enable this component and fire the 'enable' event.
1582      * @return {Ext.Component} this
1583      */
1584     enable : function(){
1585         if(this.rendered){
1586             this.onEnable();
1587         }
1588         this.disabled = false;
1589         this.fireEvent('enable', this);
1590         return this;
1591     },
1592
1593     // private
1594     onEnable : function(){
1595         this.getActionEl().removeClass(this.disabledClass);
1596         this.el.dom.disabled = false;
1597     },
1598
1599     /**
1600      * Convenience function for setting disabled/enabled by boolean.
1601      * @param {Boolean} disabled
1602      * @return {Ext.Component} this
1603      */
1604     setDisabled : function(disabled){
1605         return this[disabled ? 'disable' : 'enable']();
1606     },
1607
1608     /**
1609      * Show this component.  Listen to the '{@link #beforeshow}' event and return
1610      * <tt>false</tt> to cancel showing the component.  Fires the '{@link #show}'
1611      * event after showing the component.
1612      * @return {Ext.Component} this
1613      */
1614     show : function(){
1615         if(this.fireEvent('beforeshow', this) !== false){
1616             this.hidden = false;
1617             if(this.autoRender){
1618                 this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
1619             }
1620             if(this.rendered){
1621                 this.onShow();
1622             }
1623             this.fireEvent('show', this);
1624         }
1625         return this;
1626     },
1627
1628     // private
1629     onShow : function(){
1630         this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);
1631     },
1632
1633     /**
1634      * Hide this component.  Listen to the '{@link #beforehide}' event and return
1635      * <tt>false</tt> to cancel hiding the component.  Fires the '{@link #hide}'
1636      * event after hiding the component. Note this method is called internally if
1637      * the component is configured to be <code>{@link #hidden}</code>.
1638      * @return {Ext.Component} this
1639      */
1640     hide : function(){
1641         if(this.fireEvent('beforehide', this) !== false){
1642             this.doHide();
1643             this.fireEvent('hide', this);
1644         }
1645         return this;
1646     },
1647
1648     // private
1649     doHide: function(){
1650         this.hidden = true;
1651         if(this.rendered){
1652             this.onHide();
1653         }
1654     },
1655
1656     // private
1657     onHide : function(){
1658         this.getVisibilityEl().addClass('x-hide-' + this.hideMode);
1659     },
1660
1661     // private
1662     getVisibilityEl : function(){
1663         return this.hideParent ? this.container : this.getActionEl();
1664     },
1665
1666     /**
1667      * Convenience function to hide or show this component by boolean.
1668      * @param {Boolean} visible True to show, false to hide
1669      * @return {Ext.Component} this
1670      */
1671     setVisible : function(visible){
1672         return this[visible ? 'show' : 'hide']();
1673     },
1674
1675     /**
1676      * Returns true if this component is visible.
1677      * @return {Boolean} True if this component is visible, false otherwise.
1678      */
1679     isVisible : function(){
1680         return this.rendered && this.getVisibilityEl().isVisible();
1681     },
1682
1683     /**
1684      * Clone the current component using the original config values passed into this instance by default.
1685      * @param {Object} overrides A new config containing any properties to override in the cloned version.
1686      * An id property can be passed on this object, otherwise one will be generated to avoid duplicates.
1687      * @return {Ext.Component} clone The cloned copy of this component
1688      */
1689     cloneConfig : function(overrides){
1690         overrides = overrides || {};
1691         var id = overrides.id || Ext.id();
1692         var cfg = Ext.applyIf(overrides, this.initialConfig);
1693         cfg.id = id; // prevent dup id
1694         return new this.constructor(cfg);
1695     },
1696
1697     /**
1698      * Gets the xtype for this component as registered with {@link Ext.ComponentMgr}. For a list of all
1699      * available xtypes, see the {@link Ext.Component} header. Example usage:
1700      * <pre><code>
1701 var t = new Ext.form.TextField();
1702 alert(t.getXType());  // alerts 'textfield'
1703 </code></pre>
1704      * @return {String} The xtype
1705      */
1706     getXType : function(){
1707         return this.constructor.xtype;
1708     },
1709
1710     /**
1711      * <p>Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended
1712      * from the xtype (default) or whether it is directly of the xtype specified (shallow = true).</p>
1713      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1714      * to participate in determination of inherited xtypes.</b></p>
1715      * <p>For a list of all available xtypes, see the {@link Ext.Component} header.</p>
1716      * <p>Example usage:</p>
1717      * <pre><code>
1718 var t = new Ext.form.TextField();
1719 var isText = t.isXType('textfield');        // true
1720 var isBoxSubclass = t.isXType('box');       // true, descended from BoxComponent
1721 var isBoxInstance = t.isXType('box', true); // false, not a direct BoxComponent instance
1722 </code></pre>
1723      * @param {String} xtype The xtype to check for this Component
1724      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
1725      * the default), or true to check whether this Component is directly of the specified xtype.
1726      * @return {Boolean} True if this component descends from the specified xtype, false otherwise.
1727      */
1728     isXType : function(xtype, shallow){
1729         //assume a string by default
1730         if (Ext.isFunction(xtype)){
1731             xtype = xtype.xtype; //handle being passed the class, e.g. Ext.Component
1732         }else if (Ext.isObject(xtype)){
1733             xtype = xtype.constructor.xtype; //handle being passed an instance
1734         }
1735
1736         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
1737     },
1738
1739     /**
1740      * <p>Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all
1741      * available xtypes, see the {@link Ext.Component} header.</p>
1742      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1743      * to participate in determination of inherited xtypes.</b></p>
1744      * <p>Example usage:</p>
1745      * <pre><code>
1746 var t = new Ext.form.TextField();
1747 alert(t.getXTypes());  // alerts 'component/box/field/textfield'
1748 </code></pre>
1749      * @return {String} The xtype hierarchy string
1750      */
1751     getXTypes : function(){
1752         var tc = this.constructor;
1753         if(!tc.xtypes){
1754             var c = [], sc = this;
1755             while(sc && sc.constructor.xtype){
1756                 c.unshift(sc.constructor.xtype);
1757                 sc = sc.constructor.superclass;
1758             }
1759             tc.xtypeChain = c;
1760             tc.xtypes = c.join('/');
1761         }
1762         return tc.xtypes;
1763     },
1764
1765     /**
1766      * Find a container above this component at any level by a custom function. If the passed function returns
1767      * true, the container will be returned.
1768      * @param {Function} fn The custom function to call with the arguments (container, this component).
1769      * @return {Ext.Container} The first Container for which the custom function returns true
1770      */
1771     findParentBy : function(fn) {
1772         for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
1773         return p || null;
1774     },
1775
1776     /**
1777      * Find a container above this component at any level by xtype or class
1778      * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
1779      * @return {Ext.Container} The first Container which matches the given xtype or class
1780      */
1781     findParentByType : function(xtype) {
1782         return Ext.isFunction(xtype) ?
1783             this.findParentBy(function(p){
1784                 return p.constructor === xtype;
1785             }) :
1786             this.findParentBy(function(p){
1787                 return p.constructor.xtype === xtype;
1788             });
1789     },
1790
1791     // protected
1792     getPositionEl : function(){
1793         return this.positionEl || this.el;
1794     },
1795
1796     // private
1797     purgeListeners : function(){
1798         Ext.Component.superclass.purgeListeners.call(this);
1799         if(this.mons){
1800             this.on('beforedestroy', this.clearMons, this, {single: true});
1801         }
1802     },
1803
1804     // private
1805     clearMons : function(){
1806         Ext.each(this.mons, function(m){
1807             m.item.un(m.ename, m.fn, m.scope);
1808         }, this);
1809         this.mons = [];
1810     },
1811
1812     // private
1813     createMons: function(){
1814         if(!this.mons){
1815             this.mons = [];
1816             this.on('beforedestroy', this.clearMons, this, {single: true});
1817         }
1818     },
1819
1820     /**
1821      * <p>Adds listeners to any Observable object (or Elements) which are automatically removed when this Component
1822      * is destroyed. Usage:</p><code><pre>
1823 myGridPanel.mon(myGridPanel.getSelectionModel(), 'selectionchange', handleSelectionChange, null, {buffer: 50});
1824 </pre></code>
1825      * <p>or:</p><code><pre>
1826 myGridPanel.mon(myGridPanel.getSelectionModel(), {
1827     selectionchange: handleSelectionChange,
1828     buffer: 50
1829 });
1830 </pre></code>
1831      * @param {Observable|Element} item The item to which to add a listener/listeners.
1832      * @param {Object|String} ename The event name, or an object containing event name properties.
1833      * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this
1834      * is the handler function.
1835      * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this
1836      * is the scope (<code>this</code> reference) in which the handler function is executed.
1837      * @param {Object} opt Optional. If the <code>ename</code> parameter was an event name, this
1838      * is the {@link Ext.util.Observable#addListener addListener} options.
1839      */
1840     mon : function(item, ename, fn, scope, opt){
1841         this.createMons();
1842         if(Ext.isObject(ename)){
1843             var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
1844
1845             var o = ename;
1846             for(var e in o){
1847                 if(propRe.test(e)){
1848                     continue;
1849                 }
1850                 if(Ext.isFunction(o[e])){
1851                     // shared options
1852                     this.mons.push({
1853                         item: item, ename: e, fn: o[e], scope: o.scope
1854                     });
1855                     item.on(e, o[e], o.scope, o);
1856                 }else{
1857                     // individual options
1858                     this.mons.push({
1859                         item: item, ename: e, fn: o[e], scope: o.scope
1860                     });
1861                     item.on(e, o[e]);
1862                 }
1863             }
1864             return;
1865         }
1866
1867         this.mons.push({
1868             item: item, ename: ename, fn: fn, scope: scope
1869         });
1870         item.on(ename, fn, scope, opt);
1871     },
1872
1873     /**
1874      * Removes listeners that were added by the {@link #mon} method.
1875      * @param {Observable|Element} item The item from which to remove a listener/listeners.
1876      * @param {Object|String} ename The event name, or an object containing event name properties.
1877      * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this
1878      * is the handler function.
1879      * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this
1880      * is the scope (<code>this</code> reference) in which the handler function is executed.
1881      */
1882     mun : function(item, ename, fn, scope){
1883         var found, mon;
1884         this.createMons();
1885         for(var i = 0, len = this.mons.length; i < len; ++i){
1886             mon = this.mons[i];
1887             if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){
1888                 this.mons.splice(i, 1);
1889                 item.un(ename, fn, scope);
1890                 found = true;
1891                 break;
1892             }
1893         }
1894         return found;
1895     },
1896
1897     /**
1898      * Returns the next component in the owning container
1899      * @return Ext.Component
1900      */
1901     nextSibling : function(){
1902         if(this.ownerCt){
1903             var index = this.ownerCt.items.indexOf(this);
1904             if(index != -1 && index+1 < this.ownerCt.items.getCount()){
1905                 return this.ownerCt.items.itemAt(index+1);
1906             }
1907         }
1908         return null;
1909     },
1910
1911     /**
1912      * Returns the previous component in the owning container
1913      * @return Ext.Component
1914      */
1915     previousSibling : function(){
1916         if(this.ownerCt){
1917             var index = this.ownerCt.items.indexOf(this);
1918             if(index > 0){
1919                 return this.ownerCt.items.itemAt(index-1);
1920             }
1921         }
1922         return null;
1923     },
1924
1925     /**
1926      * Provides the link for Observable's fireEvent method to bubble up the ownership hierarchy.
1927      * @return {Ext.Container} the Container which owns this Component.
1928      */
1929     getBubbleTarget : function(){
1930         return this.ownerCt;
1931     }
1932 });
1933
1934 Ext.reg('component', Ext.Component);/**\r
1935  * @class Ext.Action\r
1936  * <p>An Action is a piece of reusable functionality that can be abstracted out of any particular component so that it\r
1937  * can be usefully shared among multiple components.  Actions let you share handlers, configuration options and UI\r
1938  * updates across any components that support the Action interface (primarily {@link Ext.Toolbar}, {@link Ext.Button}\r
1939  * and {@link Ext.menu.Menu} components).</p>\r
1940  * <p>Aside from supporting the config object interface, any component that needs to use Actions must also support\r
1941  * the following method list, as these will be called as needed by the Action class: setText(string), setIconCls(string),\r
1942  * setDisabled(boolean), setVisible(boolean) and setHandler(function).</p>\r
1943  * Example usage:<br>\r
1944  * <pre><code>\r
1945 // Define the shared action.  Each component below will have the same\r
1946 // display text and icon, and will display the same message on click.\r
1947 var action = new Ext.Action({\r
1948     {@link #text}: 'Do something',\r
1949     {@link #handler}: function(){\r
1950         Ext.Msg.alert('Click', 'You did something.');\r
1951     },\r
1952     {@link #iconCls}: 'do-something',\r
1953     {@link #itemId}: 'myAction'\r
1954 });\r
1955 \r
1956 var panel = new Ext.Panel({\r
1957     title: 'Actions',\r
1958     width: 500,\r
1959     height: 300,\r
1960     tbar: [\r
1961         // Add the action directly to a toolbar as a menu button\r
1962         action,\r
1963         {\r
1964             text: 'Action Menu',\r
1965             // Add the action to a menu as a text item\r
1966             menu: [action]\r
1967         }\r
1968     ],\r
1969     items: [\r
1970         // Add the action to the panel body as a standard button\r
1971         new Ext.Button(action)\r
1972     ],\r
1973     renderTo: Ext.getBody()\r
1974 });\r
1975 \r
1976 // Change the text for all components using the action\r
1977 action.setText('Something else');\r
1978 \r
1979 // Reference an action through a container using the itemId\r
1980 var btn = panel.getComponent('myAction');\r
1981 var aRef = btn.baseAction;\r
1982 aRef.setText('New text');\r
1983 </code></pre>\r
1984  * @constructor\r
1985  * @param {Object} config The configuration options\r
1986  */\r
1987 Ext.Action = Ext.extend(Object, {\r
1988     /**\r
1989      * @cfg {String} text The text to set for all components using this action (defaults to '').\r
1990      */\r
1991     /**\r
1992      * @cfg {String} iconCls\r
1993      * The CSS class selector that specifies a background image to be used as the header icon for\r
1994      * all components using this action (defaults to '').\r
1995      * <p>An example of specifying a custom icon class would be something like:\r
1996      * </p><pre><code>\r
1997 // specify the property in the config for the class:\r
1998      ...\r
1999      iconCls: 'do-something'\r
2000 \r
2001 // css class that specifies background image to be used as the icon image:\r
2002 .do-something { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }\r
2003 </code></pre>\r
2004      */\r
2005     /**\r
2006      * @cfg {Boolean} disabled True to disable all components using this action, false to enable them (defaults to false).\r
2007      */\r
2008     /**\r
2009      * @cfg {Boolean} hidden True to hide all components using this action, false to show them (defaults to false).\r
2010      */\r
2011     /**\r
2012      * @cfg {Function} handler The function that will be invoked by each component tied to this action\r
2013      * when the component's primary event is triggered (defaults to undefined).\r
2014      */\r
2015     /**\r
2016      * @cfg {String} itemId\r
2017      * See {@link Ext.Component}.{@link Ext.Component#itemId itemId}.\r
2018      */\r
2019     /**\r
2020      * @cfg {Object} scope The scope (<tt><b>this</b></tt> reference) in which the\r
2021      * <code>{@link #handler}</code> is executed. Defaults to this Button.\r
2022      */\r
2023 \r
2024     constructor : function(config){\r
2025         this.initialConfig = config;\r
2026         this.itemId = config.itemId = (config.itemId || config.id || Ext.id());\r
2027         this.items = [];\r
2028     },\r
2029     \r
2030     // private\r
2031     isAction : true,\r
2032 \r
2033     /**\r
2034      * Sets the text to be displayed by all components using this action.\r
2035      * @param {String} text The text to display\r
2036      */\r
2037     setText : function(text){\r
2038         this.initialConfig.text = text;\r
2039         this.callEach('setText', [text]);\r
2040     },\r
2041 \r
2042     /**\r
2043      * Gets the text currently displayed by all components using this action.\r
2044      */\r
2045     getText : function(){\r
2046         return this.initialConfig.text;\r
2047     },\r
2048 \r
2049     /**\r
2050      * Sets the icon CSS class for all components using this action.  The class should supply\r
2051      * a background image that will be used as the icon image.\r
2052      * @param {String} cls The CSS class supplying the icon image\r
2053      */\r
2054     setIconClass : function(cls){\r
2055         this.initialConfig.iconCls = cls;\r
2056         this.callEach('setIconClass', [cls]);\r
2057     },\r
2058 \r
2059     /**\r
2060      * Gets the icon CSS class currently used by all components using this action.\r
2061      */\r
2062     getIconClass : function(){\r
2063         return this.initialConfig.iconCls;\r
2064     },\r
2065 \r
2066     /**\r
2067      * Sets the disabled state of all components using this action.  Shortcut method\r
2068      * for {@link #enable} and {@link #disable}.\r
2069      * @param {Boolean} disabled True to disable the component, false to enable it\r
2070      */\r
2071     setDisabled : function(v){\r
2072         this.initialConfig.disabled = v;\r
2073         this.callEach('setDisabled', [v]);\r
2074     },\r
2075 \r
2076     /**\r
2077      * Enables all components using this action.\r
2078      */\r
2079     enable : function(){\r
2080         this.setDisabled(false);\r
2081     },\r
2082 \r
2083     /**\r
2084      * Disables all components using this action.\r
2085      */\r
2086     disable : function(){\r
2087         this.setDisabled(true);\r
2088     },\r
2089 \r
2090     /**\r
2091      * Returns true if the components using this action are currently disabled, else returns false.  \r
2092      */\r
2093     isDisabled : function(){\r
2094         return this.initialConfig.disabled;\r
2095     },\r
2096 \r
2097     /**\r
2098      * Sets the hidden state of all components using this action.  Shortcut method\r
2099      * for <code>{@link #hide}</code> and <code>{@link #show}</code>.\r
2100      * @param {Boolean} hidden True to hide the component, false to show it\r
2101      */\r
2102     setHidden : function(v){\r
2103         this.initialConfig.hidden = v;\r
2104         this.callEach('setVisible', [!v]);\r
2105     },\r
2106 \r
2107     /**\r
2108      * Shows all components using this action.\r
2109      */\r
2110     show : function(){\r
2111         this.setHidden(false);\r
2112     },\r
2113 \r
2114     /**\r
2115      * Hides all components using this action.\r
2116      */\r
2117     hide : function(){\r
2118         this.setHidden(true);\r
2119     },\r
2120 \r
2121     /**\r
2122      * Returns true if the components using this action are currently hidden, else returns false.  \r
2123      */\r
2124     isHidden : function(){\r
2125         return this.initialConfig.hidden;\r
2126     },\r
2127 \r
2128     /**\r
2129      * Sets the function that will be called by each Component using this action when its primary event is triggered.\r
2130      * @param {Function} fn The function that will be invoked by the action's components.  The function\r
2131      * will be called with no arguments.\r
2132      * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed. Defaults to the Component firing the event.\r
2133      */\r
2134     setHandler : function(fn, scope){\r
2135         this.initialConfig.handler = fn;\r
2136         this.initialConfig.scope = scope;\r
2137         this.callEach('setHandler', [fn, scope]);\r
2138     },\r
2139 \r
2140     /**\r
2141      * Executes the specified function once for each Component currently tied to this action.  The function passed\r
2142      * in should accept a single argument that will be an object that supports the basic Action config/method interface.\r
2143      * @param {Function} fn The function to execute for each component\r
2144      * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed.  Defaults to the Component.\r
2145      */\r
2146     each : function(fn, scope){\r
2147         Ext.each(this.items, fn, scope);\r
2148     },\r
2149 \r
2150     // private\r
2151     callEach : function(fnName, args){\r
2152         var cs = this.items;\r
2153         for(var i = 0, len = cs.length; i < len; i++){\r
2154             cs[i][fnName].apply(cs[i], args);\r
2155         }\r
2156     },\r
2157 \r
2158     // private\r
2159     addComponent : function(comp){\r
2160         this.items.push(comp);\r
2161         comp.on('destroy', this.removeComponent, this);\r
2162     },\r
2163 \r
2164     // private\r
2165     removeComponent : function(comp){\r
2166         this.items.remove(comp);\r
2167     },\r
2168 \r
2169     /**\r
2170      * Executes this action manually using the handler function specified in the original config object\r
2171      * or the handler function set with <code>{@link #setHandler}</code>.  Any arguments passed to this\r
2172      * function will be passed on to the handler function.\r
2173      * @param {Mixed} arg1 (optional) Variable number of arguments passed to the handler function\r
2174      * @param {Mixed} arg2 (optional)\r
2175      * @param {Mixed} etc... (optional)\r
2176      */\r
2177     execute : function(){\r
2178         this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);\r
2179     }\r
2180 });\r
2181 /**
2182  * @class Ext.Layer
2183  * @extends Ext.Element
2184  * An extended {@link Ext.Element} object that supports a shadow and shim, constrain to viewport and
2185  * automatic maintaining of shadow/shim positions.
2186  * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true)
2187  * @cfg {String/Boolean} shadow True to automatically create an {@link Ext.Shadow}, or a string indicating the
2188  * shadow's display {@link Ext.Shadow#mode}. False to disable the shadow. (defaults to false)
2189  * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: 'div', cls: 'x-layer'}).
2190  * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true)
2191  * @cfg {String} cls CSS class to add to the element
2192  * @cfg {Number} zindex Starting z-index (defaults to 11000)
2193  * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 4)
2194  * @cfg {Boolean} useDisplay
2195  * Defaults to use css offsets to hide the Layer. Specify <tt>true</tt>
2196  * to use css style <tt>'display:none;'</tt> to hide the Layer.
2197  * @constructor
2198  * @param {Object} config An object with config options.
2199  * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element. If the element is not found it creates it.
2200  */
2201 (function(){
2202 Ext.Layer = function(config, existingEl){
2203     config = config || {};
2204     var dh = Ext.DomHelper;
2205     var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
2206     if(existingEl){
2207         this.dom = Ext.getDom(existingEl);
2208     }
2209     if(!this.dom){
2210         var o = config.dh || {tag: 'div', cls: 'x-layer'};
2211         this.dom = dh.append(pel, o);
2212     }
2213     if(config.cls){
2214         this.addClass(config.cls);
2215     }
2216     this.constrain = config.constrain !== false;
2217     this.setVisibilityMode(Ext.Element.VISIBILITY);
2218     if(config.id){
2219         this.id = this.dom.id = config.id;
2220     }else{
2221         this.id = Ext.id(this.dom);
2222     }
2223     this.zindex = config.zindex || this.getZIndex();
2224     this.position('absolute', this.zindex);
2225     if(config.shadow){
2226         this.shadowOffset = config.shadowOffset || 4;
2227         this.shadow = new Ext.Shadow({
2228             offset : this.shadowOffset,
2229             mode : config.shadow
2230         });
2231     }else{
2232         this.shadowOffset = 0;
2233     }
2234     this.useShim = config.shim !== false && Ext.useShims;
2235     this.useDisplay = config.useDisplay;
2236     this.hide();
2237 };
2238
2239 var supr = Ext.Element.prototype;
2240
2241 // shims are shared among layer to keep from having 100 iframes
2242 var shims = [];
2243
2244 Ext.extend(Ext.Layer, Ext.Element, {
2245
2246     getZIndex : function(){
2247         return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
2248     },
2249
2250     getShim : function(){
2251         if(!this.useShim){
2252             return null;
2253         }
2254         if(this.shim){
2255             return this.shim;
2256         }
2257         var shim = shims.shift();
2258         if(!shim){
2259             shim = this.createShim();
2260             shim.enableDisplayMode('block');
2261             shim.dom.style.display = 'none';
2262             shim.dom.style.visibility = 'visible';
2263         }
2264         var pn = this.dom.parentNode;
2265         if(shim.dom.parentNode != pn){
2266             pn.insertBefore(shim.dom, this.dom);
2267         }
2268         shim.setStyle('z-index', this.getZIndex()-2);
2269         this.shim = shim;
2270         return shim;
2271     },
2272
2273     hideShim : function(){
2274         if(this.shim){
2275             this.shim.setDisplayed(false);
2276             shims.push(this.shim);
2277             delete this.shim;
2278         }
2279     },
2280
2281     disableShadow : function(){
2282         if(this.shadow){
2283             this.shadowDisabled = true;
2284             this.shadow.hide();
2285             this.lastShadowOffset = this.shadowOffset;
2286             this.shadowOffset = 0;
2287         }
2288     },
2289
2290     enableShadow : function(show){
2291         if(this.shadow){
2292             this.shadowDisabled = false;
2293             this.shadowOffset = this.lastShadowOffset;
2294             delete this.lastShadowOffset;
2295             if(show){
2296                 this.sync(true);
2297             }
2298         }
2299     },
2300
2301     // private
2302     // this code can execute repeatedly in milliseconds (i.e. during a drag) so
2303     // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
2304     sync : function(doShow){
2305         var sw = this.shadow;
2306         if(!this.updating && this.isVisible() && (sw || this.useShim)){
2307             var sh = this.getShim();
2308
2309             var w = this.getWidth(),
2310                 h = this.getHeight();
2311
2312             var l = this.getLeft(true),
2313                 t = this.getTop(true);
2314
2315             if(sw && !this.shadowDisabled){
2316                 if(doShow && !sw.isVisible()){
2317                     sw.show(this);
2318                 }else{
2319                     sw.realign(l, t, w, h);
2320                 }
2321                 if(sh){
2322                     if(doShow){
2323                        sh.show();
2324                     }
2325                     // fit the shim behind the shadow, so it is shimmed too
2326                     var a = sw.adjusts, s = sh.dom.style;
2327                     s.left = (Math.min(l, l+a.l))+'px';
2328                     s.top = (Math.min(t, t+a.t))+'px';
2329                     s.width = (w+a.w)+'px';
2330                     s.height = (h+a.h)+'px';
2331                 }
2332             }else if(sh){
2333                 if(doShow){
2334                    sh.show();
2335                 }
2336                 sh.setSize(w, h);
2337                 sh.setLeftTop(l, t);
2338             }
2339
2340         }
2341     },
2342
2343     // private
2344     destroy : function(){
2345         this.hideShim();
2346         if(this.shadow){
2347             this.shadow.hide();
2348         }
2349         this.removeAllListeners();
2350         Ext.removeNode(this.dom);
2351         delete this.dom;
2352     },
2353
2354     remove : function(){
2355         this.destroy();
2356     },
2357
2358     // private
2359     beginUpdate : function(){
2360         this.updating = true;
2361     },
2362
2363     // private
2364     endUpdate : function(){
2365         this.updating = false;
2366         this.sync(true);
2367     },
2368
2369     // private
2370     hideUnders : function(negOffset){
2371         if(this.shadow){
2372             this.shadow.hide();
2373         }
2374         this.hideShim();
2375     },
2376
2377     // private
2378     constrainXY : function(){
2379         if(this.constrain){
2380             var vw = Ext.lib.Dom.getViewWidth(),
2381                 vh = Ext.lib.Dom.getViewHeight();
2382             var s = Ext.getDoc().getScroll();
2383
2384             var xy = this.getXY();
2385             var x = xy[0], y = xy[1];
2386             var so = this.shadowOffset;
2387             var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so;
2388             // only move it if it needs it
2389             var moved = false;
2390             // first validate right/bottom
2391             if((x + w) > vw+s.left){
2392                 x = vw - w - so;
2393                 moved = true;
2394             }
2395             if((y + h) > vh+s.top){
2396                 y = vh - h - so;
2397                 moved = true;
2398             }
2399             // then make sure top/left isn't negative
2400             if(x < s.left){
2401                 x = s.left;
2402                 moved = true;
2403             }
2404             if(y < s.top){
2405                 y = s.top;
2406                 moved = true;
2407             }
2408             if(moved){
2409                 if(this.avoidY){
2410                     var ay = this.avoidY;
2411                     if(y <= ay && (y+h) >= ay){
2412                         y = ay-h-5;
2413                     }
2414                 }
2415                 xy = [x, y];
2416                 this.storeXY(xy);
2417                 supr.setXY.call(this, xy);
2418                 this.sync();
2419             }
2420         }
2421         return this;
2422     },
2423
2424     isVisible : function(){
2425         return this.visible;
2426     },
2427
2428     // private
2429     showAction : function(){
2430         this.visible = true; // track visibility to prevent getStyle calls
2431         if(this.useDisplay === true){
2432             this.setDisplayed('');
2433         }else if(this.lastXY){
2434             supr.setXY.call(this, this.lastXY);
2435         }else if(this.lastLT){
2436             supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
2437         }
2438     },
2439
2440     // private
2441     hideAction : function(){
2442         this.visible = false;
2443         if(this.useDisplay === true){
2444             this.setDisplayed(false);
2445         }else{
2446             this.setLeftTop(-10000,-10000);
2447         }
2448     },
2449
2450     // overridden Element method
2451     setVisible : function(v, a, d, c, e){
2452         if(v){
2453             this.showAction();
2454         }
2455         if(a && v){
2456             var cb = function(){
2457                 this.sync(true);
2458                 if(c){
2459                     c();
2460                 }
2461             }.createDelegate(this);
2462             supr.setVisible.call(this, true, true, d, cb, e);
2463         }else{
2464             if(!v){
2465                 this.hideUnders(true);
2466             }
2467             var cb = c;
2468             if(a){
2469                 cb = function(){
2470                     this.hideAction();
2471                     if(c){
2472                         c();
2473                     }
2474                 }.createDelegate(this);
2475             }
2476             supr.setVisible.call(this, v, a, d, cb, e);
2477             if(v){
2478                 this.sync(true);
2479             }else if(!a){
2480                 this.hideAction();
2481             }
2482         }
2483         return this;
2484     },
2485
2486     storeXY : function(xy){
2487         delete this.lastLT;
2488         this.lastXY = xy;
2489     },
2490
2491     storeLeftTop : function(left, top){
2492         delete this.lastXY;
2493         this.lastLT = [left, top];
2494     },
2495
2496     // private
2497     beforeFx : function(){
2498         this.beforeAction();
2499         return Ext.Layer.superclass.beforeFx.apply(this, arguments);
2500     },
2501
2502     // private
2503     afterFx : function(){
2504         Ext.Layer.superclass.afterFx.apply(this, arguments);
2505         this.sync(this.isVisible());
2506     },
2507
2508     // private
2509     beforeAction : function(){
2510         if(!this.updating && this.shadow){
2511             this.shadow.hide();
2512         }
2513     },
2514
2515     // overridden Element method
2516     setLeft : function(left){
2517         this.storeLeftTop(left, this.getTop(true));
2518         supr.setLeft.apply(this, arguments);
2519         this.sync();
2520         return this;
2521     },
2522
2523     setTop : function(top){
2524         this.storeLeftTop(this.getLeft(true), top);
2525         supr.setTop.apply(this, arguments);
2526         this.sync();
2527         return this;
2528     },
2529
2530     setLeftTop : function(left, top){
2531         this.storeLeftTop(left, top);
2532         supr.setLeftTop.apply(this, arguments);
2533         this.sync();
2534         return this;
2535     },
2536
2537     setXY : function(xy, a, d, c, e){
2538         this.fixDisplay();
2539         this.beforeAction();
2540         this.storeXY(xy);
2541         var cb = this.createCB(c);
2542         supr.setXY.call(this, xy, a, d, cb, e);
2543         if(!a){
2544             cb();
2545         }
2546         return this;
2547     },
2548
2549     // private
2550     createCB : function(c){
2551         var el = this;
2552         return function(){
2553             el.constrainXY();
2554             el.sync(true);
2555             if(c){
2556                 c();
2557             }
2558         };
2559     },
2560
2561     // overridden Element method
2562     setX : function(x, a, d, c, e){
2563         this.setXY([x, this.getY()], a, d, c, e);
2564         return this;
2565     },
2566
2567     // overridden Element method
2568     setY : function(y, a, d, c, e){
2569         this.setXY([this.getX(), y], a, d, c, e);
2570         return this;
2571     },
2572
2573     // overridden Element method
2574     setSize : function(w, h, a, d, c, e){
2575         this.beforeAction();
2576         var cb = this.createCB(c);
2577         supr.setSize.call(this, w, h, a, d, cb, e);
2578         if(!a){
2579             cb();
2580         }
2581         return this;
2582     },
2583
2584     // overridden Element method
2585     setWidth : function(w, a, d, c, e){
2586         this.beforeAction();
2587         var cb = this.createCB(c);
2588         supr.setWidth.call(this, w, a, d, cb, e);
2589         if(!a){
2590             cb();
2591         }
2592         return this;
2593     },
2594
2595     // overridden Element method
2596     setHeight : function(h, a, d, c, e){
2597         this.beforeAction();
2598         var cb = this.createCB(c);
2599         supr.setHeight.call(this, h, a, d, cb, e);
2600         if(!a){
2601             cb();
2602         }
2603         return this;
2604     },
2605
2606     // overridden Element method
2607     setBounds : function(x, y, w, h, a, d, c, e){
2608         this.beforeAction();
2609         var cb = this.createCB(c);
2610         if(!a){
2611             this.storeXY([x, y]);
2612             supr.setXY.call(this, [x, y]);
2613             supr.setSize.call(this, w, h, a, d, cb, e);
2614             cb();
2615         }else{
2616             supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
2617         }
2618         return this;
2619     },
2620
2621     /**
2622      * Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
2623      * incremented by two more than the value passed in so that it always shows above any shadow or shim (the shadow
2624      * element, if any, will be assigned z-index + 1, and the shim element, if any, will be assigned the unmodified z-index).
2625      * @param {Number} zindex The new z-index to set
2626      * @return {this} The Layer
2627      */
2628     setZIndex : function(zindex){
2629         this.zindex = zindex;
2630         this.setStyle('z-index', zindex + 2);
2631         if(this.shadow){
2632             this.shadow.setZIndex(zindex + 1);
2633         }
2634         if(this.shim){
2635             this.shim.setStyle('z-index', zindex);
2636         }
2637         return this;
2638     }
2639 });
2640 })();
2641 /**
2642  * @class Ext.Shadow
2643  * Simple class that can provide a shadow effect for any element.  Note that the element MUST be absolutely positioned,
2644  * and the shadow does not provide any shimming.  This should be used only in simple cases -- for more advanced
2645  * functionality that can also provide the same shadow effect, see the {@link Ext.Layer} class.
2646  * @constructor
2647  * Create a new Shadow
2648  * @param {Object} config The config object
2649  */
2650 Ext.Shadow = function(config){
2651     Ext.apply(this, config);
2652     if(typeof this.mode != "string"){
2653         this.mode = this.defaultMode;
2654     }
2655     var o = this.offset, a = {h: 0};
2656     var rad = Math.floor(this.offset/2);
2657     switch(this.mode.toLowerCase()){ // all this hideous nonsense calculates the various offsets for shadows
2658         case "drop":
2659             a.w = 0;
2660             a.l = a.t = o;
2661             a.t -= 1;
2662             if(Ext.isIE){
2663                 a.l -= this.offset + rad;
2664                 a.t -= this.offset + rad;
2665                 a.w -= rad;
2666                 a.h -= rad;
2667                 a.t += 1;
2668             }
2669         break;
2670         case "sides":
2671             a.w = (o*2);
2672             a.l = -o;
2673             a.t = o-1;
2674             if(Ext.isIE){
2675                 a.l -= (this.offset - rad);
2676                 a.t -= this.offset + rad;
2677                 a.l += 1;
2678                 a.w -= (this.offset - rad)*2;
2679                 a.w -= rad + 1;
2680                 a.h -= 1;
2681             }
2682         break;
2683         case "frame":
2684             a.w = a.h = (o*2);
2685             a.l = a.t = -o;
2686             a.t += 1;
2687             a.h -= 2;
2688             if(Ext.isIE){
2689                 a.l -= (this.offset - rad);
2690                 a.t -= (this.offset - rad);
2691                 a.l += 1;
2692                 a.w -= (this.offset + rad + 1);
2693                 a.h -= (this.offset + rad);
2694                 a.h += 1;
2695             }
2696         break;
2697     };
2698
2699     this.adjusts = a;
2700 };
2701
2702 Ext.Shadow.prototype = {
2703     /**
2704      * @cfg {String} mode
2705      * The shadow display mode.  Supports the following options:<div class="mdetail-params"><ul>
2706      * <li><b><tt>sides</tt></b> : Shadow displays on both sides and bottom only</li>
2707      * <li><b><tt>frame</tt></b> : Shadow displays equally on all four sides</li>
2708      * <li><b><tt>drop</tt></b> : Traditional bottom-right drop shadow</li>
2709      * </ul></div>
2710      */
2711     /**
2712      * @cfg {String} offset
2713      * The number of pixels to offset the shadow from the element (defaults to <tt>4</tt>)
2714      */
2715     offset: 4,
2716
2717     // private
2718     defaultMode: "drop",
2719
2720     /**
2721      * Displays the shadow under the target element
2722      * @param {Mixed} targetEl The id or element under which the shadow should display
2723      */
2724     show : function(target){
2725         target = Ext.get(target);
2726         if(!this.el){
2727             this.el = Ext.Shadow.Pool.pull();
2728             if(this.el.dom.nextSibling != target.dom){
2729                 this.el.insertBefore(target);
2730             }
2731         }
2732         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
2733         if(Ext.isIE){
2734             this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
2735         }
2736         this.realign(
2737             target.getLeft(true),
2738             target.getTop(true),
2739             target.getWidth(),
2740             target.getHeight()
2741         );
2742         this.el.dom.style.display = "block";
2743     },
2744
2745     /**
2746      * Returns true if the shadow is visible, else false
2747      */
2748     isVisible : function(){
2749         return this.el ? true : false;  
2750     },
2751
2752     /**
2753      * Direct alignment when values are already available. Show must be called at least once before
2754      * calling this method to ensure it is initialized.
2755      * @param {Number} left The target element left position
2756      * @param {Number} top The target element top position
2757      * @param {Number} width The target element width
2758      * @param {Number} height The target element height
2759      */
2760     realign : function(l, t, w, h){
2761         if(!this.el){
2762             return;
2763         }
2764         var a = this.adjusts, d = this.el.dom, s = d.style;
2765         var iea = 0;
2766         s.left = (l+a.l)+"px";
2767         s.top = (t+a.t)+"px";
2768         var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
2769         if(s.width != sws || s.height != shs){
2770             s.width = sws;
2771             s.height = shs;
2772             if(!Ext.isIE){
2773                 var cn = d.childNodes;
2774                 var sww = Math.max(0, (sw-12))+"px";
2775                 cn[0].childNodes[1].style.width = sww;
2776                 cn[1].childNodes[1].style.width = sww;
2777                 cn[2].childNodes[1].style.width = sww;
2778                 cn[1].style.height = Math.max(0, (sh-12))+"px";
2779             }
2780         }
2781     },
2782
2783     /**
2784      * Hides this shadow
2785      */
2786     hide : function(){
2787         if(this.el){
2788             this.el.dom.style.display = "none";
2789             Ext.Shadow.Pool.push(this.el);
2790             delete this.el;
2791         }
2792     },
2793
2794     /**
2795      * Adjust the z-index of this shadow
2796      * @param {Number} zindex The new z-index
2797      */
2798     setZIndex : function(z){
2799         this.zIndex = z;
2800         if(this.el){
2801             this.el.setStyle("z-index", z);
2802         }
2803     }
2804 };
2805
2806 // Private utility class that manages the internal Shadow cache
2807 Ext.Shadow.Pool = function(){
2808     var p = [];
2809     var markup = Ext.isIE ?
2810                  '<div class="x-ie-shadow"></div>' :
2811                  '<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>';
2812     return {
2813         pull : function(){
2814             var sh = p.shift();
2815             if(!sh){
2816                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
2817                 sh.autoBoxAdjust = false;
2818             }
2819             return sh;
2820         },
2821
2822         push : function(sh){
2823             p.push(sh);
2824         }
2825     };
2826 }();/**
2827  * @class Ext.BoxComponent
2828  * @extends Ext.Component
2829  * <p>Base class for any {@link Ext.Component Component} that is to be sized as a box, using width and height.</p>
2830  * <p>BoxComponent provides automatic box model adjustments for sizing and positioning and will work correctly
2831  * within the Component rendering model.</p>
2832  * <p>A BoxComponent may be created as a custom Component which encapsulates any HTML element, either a pre-existing
2833  * element, or one that is created to your specifications at render time. Usually, to participate in layouts,
2834  * a Component will need to be a <b>Box</b>Component in order to have its width and height managed.</p>
2835  * <p>To use a pre-existing element as a BoxComponent, configure it so that you preset the <b>el</b> property to the
2836  * element to reference:<pre><code>
2837 var pageHeader = new Ext.BoxComponent({
2838     el: 'my-header-div'
2839 });</code></pre>
2840  * This may then be {@link Ext.Container#add added} to a {@link Ext.Container Container} as a child item.</p>
2841  * <p>To create a BoxComponent based around a HTML element to be created at render time, use the
2842  * {@link Ext.Component#autoEl autoEl} config option which takes the form of a
2843  * {@link Ext.DomHelper DomHelper} specification:<pre><code>
2844 var myImage = new Ext.BoxComponent({
2845     autoEl: {
2846         tag: 'img',
2847         src: '/images/my-image.jpg'
2848     }
2849 });</code></pre></p>
2850  * @constructor
2851  * @param {Ext.Element/String/Object} config The configuration options.
2852  * @xtype box
2853  */
2854 Ext.BoxComponent = Ext.extend(Ext.Component, {
2855
2856     // Configs below are used for all Components when rendered by BoxLayout.
2857     /**
2858      * @cfg {Number} flex
2859      * <p><b>Note</b>: this config is only used when this Component is rendered
2860      * by a Container which has been configured to use a <b>{@link Ext.layout.BoxLayout BoxLayout}.</b>
2861      * Each child Component with a <code>flex</code> property will be flexed either vertically (by a VBoxLayout)
2862      * or horizontally (by an HBoxLayout) according to the item's <b>relative</b> <code>flex</code> value
2863      * compared to the sum of all Components with <code>flex</flex> value specified. Any child items that have
2864      * either a <code>flex = 0</code> or <code>flex = undefined</code> will not be 'flexed' (the initial size will not be changed).
2865      */
2866     // Configs below are used for all Components when rendered by AnchorLayout.
2867     /**
2868      * @cfg {String} anchor <p><b>Note</b>: this config is only used when this Component is rendered
2869      * by a Container which has been configured to use an <b>{@link Ext.layout.AnchorLayout AnchorLayout} (or subclass thereof).</b>
2870      * based layout manager, for example:<div class="mdetail-params"><ul>
2871      * <li>{@link Ext.form.FormPanel}</li>
2872      * <li>specifying <code>layout: 'anchor' // or 'form', or 'absolute'</code></li>
2873      * </ul></div></p>
2874      * <p>See {@link Ext.layout.AnchorLayout}.{@link Ext.layout.AnchorLayout#anchor anchor} also.</p>
2875      */
2876     // tabTip config is used when a BoxComponent is a child of a TabPanel
2877     /**
2878      * @cfg {String} tabTip
2879      * <p><b>Note</b>: this config is only used when this BoxComponent is a child item of a TabPanel.</p>
2880      * A string to be used as innerHTML (html tags are accepted) to show in a tooltip when mousing over
2881      * the associated tab selector element. {@link Ext.QuickTips}.init()
2882      * must be called in order for the tips to render.
2883      */
2884     // Configs below are used for all Components when rendered by BorderLayout.
2885     /**
2886      * @cfg {String} region <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2887      * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2888      * layout manager (e.g. specifying <tt>layout:'border'</tt>).</p><br>
2889      * <p>See {@link Ext.layout.BorderLayout} also.</p>
2890      */
2891     // margins config is used when a BoxComponent is rendered by BorderLayout or BoxLayout.
2892     /**
2893      * @cfg {Object} margins <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2894      * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2895      * or one of the two <b>{@link Ext.layout.BoxLayout BoxLayout} subclasses.</b></p>
2896      * <p>An object containing margins to apply to this BoxComponent in the
2897      * format:</p><pre><code>
2898 {
2899     top: (top margin),
2900     right: (right margin),
2901     bottom: (bottom margin),
2902     left: (left margin)
2903 }</code></pre>
2904      * <p>May also be a string containing space-separated, numeric margin values. The order of the
2905      * sides associated with each value matches the way CSS processes margin values:</p>
2906      * <p><div class="mdetail-params"><ul>
2907      * <li>If there is only one value, it applies to all sides.</li>
2908      * <li>If there are two values, the top and bottom borders are set to the first value and the
2909      * right and left are set to the second.</li>
2910      * <li>If there are three values, the top is set to the first value, the left and right are set
2911      * to the second, and the bottom is set to the third.</li>
2912      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
2913      * </ul></div></p>
2914      * <p>Defaults to:</p><pre><code>
2915      * {top:0, right:0, bottom:0, left:0}
2916      * </code></pre>
2917      */
2918     /**
2919      * @cfg {Number} x
2920      * The local x (left) coordinate for this component if contained within a positioning container.
2921      */
2922     /**
2923      * @cfg {Number} y
2924      * The local y (top) coordinate for this component if contained within a positioning container.
2925      */
2926     /**
2927      * @cfg {Number} pageX
2928      * The page level x coordinate for this component if contained within a positioning container.
2929      */
2930     /**
2931      * @cfg {Number} pageY
2932      * The page level y coordinate for this component if contained within a positioning container.
2933      */
2934     /**
2935      * @cfg {Number} height
2936      * The height of this component in pixels (defaults to auto).
2937      * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
2938      */
2939     /**
2940      * @cfg {Number} width
2941      * The width of this component in pixels (defaults to auto).
2942      * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
2943      */
2944     /**
2945      * @cfg {Number} boxMinHeight
2946      * <p>The minimum value in pixels which this BoxComponent will set its height to.</p>
2947      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2948      */
2949     /**
2950      * @cfg {Number} boxMinWidth
2951      * <p>The minimum value in pixels which this BoxComponent will set its width to.</p>
2952      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2953      */
2954     /**
2955      * @cfg {Number} boxMaxHeight
2956      * <p>The maximum value in pixels which this BoxComponent will set its height to.</p>
2957      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2958      */
2959     /**
2960      * @cfg {Number} boxMaxWidth
2961      * <p>The maximum value in pixels which this BoxComponent will set its width to.</p>
2962      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2963      */
2964     /**
2965      * @cfg {Boolean} autoHeight
2966      * <p>True to use height:'auto', false to use fixed height (or allow it to be managed by its parent
2967      * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
2968      * <p><b>Note</b>: Although many components inherit this config option, not all will
2969      * function as expected with a height of 'auto'. Setting autoHeight:true means that the
2970      * browser will manage height based on the element's contents, and that Ext will not manage it at all.</p>
2971      * <p>If the <i>browser</i> is managing the height, be aware that resizes performed by the browser in response
2972      * to changes within the structure of the Component cannot be detected. Therefore changes to the height might
2973      * result in elements needing to be synchronized with the new height. Example:</p><pre><code>
2974 var w = new Ext.Window({
2975     title: 'Window',
2976     width: 600,
2977     autoHeight: true,
2978     items: {
2979         title: 'Collapse Me',
2980         height: 400,
2981         collapsible: true,
2982         border: false,
2983         listeners: {
2984             beforecollapse: function() {
2985                 w.el.shadow.hide();
2986             },
2987             beforeexpand: function() {
2988                 w.el.shadow.hide();
2989             },
2990             collapse: function() {
2991                 w.syncShadow();
2992             },
2993             expand: function() {
2994                 w.syncShadow();
2995             }
2996         }
2997     }
2998 }).show();
2999 </code></pre>
3000      */
3001     /**
3002      * @cfg {Boolean} autoWidth
3003      * <p>True to use width:'auto', false to use fixed width (or allow it to be managed by its parent
3004      * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
3005      * <p><b>Note</b>: Although many components  inherit this config option, not all will
3006      * function as expected with a width of 'auto'. Setting autoWidth:true means that the
3007      * browser will manage width based on the element's contents, and that Ext will not manage it at all.</p>
3008      * <p>If the <i>browser</i> is managing the width, be aware that resizes performed by the browser in response
3009      * to changes within the structure of the Component cannot be detected. Therefore changes to the width might
3010      * result in elements needing to be synchronized with the new width. For example, where the target element is:</p><pre><code>
3011 &lt;div id='grid-container' style='margin-left:25%;width:50%'>&lt;/div>
3012 </code></pre>
3013      * A Panel rendered into that target element must listen for browser window resize in order to relay its
3014       * child items when the browser changes its width:<pre><code>
3015 var myPanel = new Ext.Panel({
3016     renderTo: 'grid-container',
3017     monitorResize: true, // relay on browser resize
3018     title: 'Panel',
3019     height: 400,
3020     autoWidth: true,
3021     layout: 'hbox',
3022     layoutConfig: {
3023         align: 'stretch'
3024     },
3025     defaults: {
3026         flex: 1
3027     },
3028     items: [{
3029         title: 'Box 1',
3030     }, {
3031         title: 'Box 2'
3032     }, {
3033         title: 'Box 3'
3034     }],
3035 });
3036 </code></pre>
3037      */
3038     /**
3039      * @cfg {Boolean} autoScroll
3040      * <code>true</code> to use overflow:'auto' on the components layout element and show scroll bars automatically when
3041      * necessary, <code>false</code> to clip any overflowing content (defaults to <code>false</code>).
3042      */
3043
3044     /* // private internal config
3045      * {Boolean} deferHeight
3046      * True to defer height calculations to an external component, false to allow this component to set its own
3047      * height (defaults to false).
3048      */
3049
3050     // private
3051     initComponent : function(){
3052         Ext.BoxComponent.superclass.initComponent.call(this);
3053         this.addEvents(
3054             /**
3055              * @event resize
3056              * Fires after the component is resized.
3057              * @param {Ext.Component} this
3058              * @param {Number} adjWidth The box-adjusted width that was set
3059              * @param {Number} adjHeight The box-adjusted height that was set
3060              * @param {Number} rawWidth The width that was originally specified
3061              * @param {Number} rawHeight The height that was originally specified
3062              */
3063             'resize',
3064             /**
3065              * @event move
3066              * Fires after the component is moved.
3067              * @param {Ext.Component} this
3068              * @param {Number} x The new x position
3069              * @param {Number} y The new y position
3070              */
3071             'move'
3072         );
3073     },
3074
3075     // private, set in afterRender to signify that the component has been rendered
3076     boxReady : false,
3077     // private, used to defer height settings to subclasses
3078     deferHeight: false,
3079
3080     /**
3081      * Sets the width and height of this BoxComponent. This method fires the {@link #resize} event. This method can accept
3082      * either width and height as separate arguments, or you can pass a size object like <code>{width:10, height:20}</code>.
3083      * @param {Mixed} width The new width to set. This may be one of:<div class="mdetail-params"><ul>
3084      * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3085      * <li>A String used to set the CSS width style.</li>
3086      * <li>A size object in the format <code>{width: widthValue, height: heightValue}</code>.</li>
3087      * <li><code>undefined</code> to leave the width unchanged.</li>
3088      * </ul></div>
3089      * @param {Mixed} height The new height to set (not required if a size object is passed as the first arg).
3090      * This may be one of:<div class="mdetail-params"><ul>
3091      * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3092      * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
3093      * <li><code>undefined</code> to leave the height unchanged.</li>
3094      * </ul></div>
3095      * @return {Ext.BoxComponent} this
3096      */
3097     setSize : function(w, h){
3098
3099         // support for standard size objects
3100         if(typeof w == 'object'){
3101             h = w.height, w = w.width;
3102         }
3103         if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
3104             w = this.boxMinWidth;
3105         }
3106         if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) {
3107             h = this.boxMinHeight;
3108         }
3109         if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) {
3110             w = this.boxMaxWidth;
3111         }
3112         if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) {
3113             h = this.boxMaxHeight;
3114         }
3115         // not rendered
3116         if(!this.boxReady){
3117             this.width = w, this.height = h;
3118             return this;
3119         }
3120
3121         // prevent recalcs when not needed
3122         if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
3123             return this;
3124         }
3125         this.lastSize = {width: w, height: h};
3126         var adj = this.adjustSize(w, h),
3127             aw = adj.width,
3128             ah = adj.height,
3129             rz;
3130         if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
3131             rz = this.getResizeEl();
3132             if(!this.deferHeight && aw !== undefined && ah !== undefined){
3133                 rz.setSize(aw, ah);
3134             }else if(!this.deferHeight && ah !== undefined){
3135                 rz.setHeight(ah);
3136             }else if(aw !== undefined){
3137                 rz.setWidth(aw);
3138             }
3139             this.onResize(aw, ah, w, h);
3140             this.fireEvent('resize', this, aw, ah, w, h);
3141         }
3142         return this;
3143     },
3144
3145     /**
3146      * Sets the width of the component.  This method fires the {@link #resize} event.
3147      * @param {Number} width The new width to setThis may be one of:<div class="mdetail-params"><ul>
3148      * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3149      * <li>A String used to set the CSS width style.</li>
3150      * </ul></div>
3151      * @return {Ext.BoxComponent} this
3152      */
3153     setWidth : function(width){
3154         return this.setSize(width);
3155     },
3156
3157     /**
3158      * Sets the height of the component.  This method fires the {@link #resize} event.
3159      * @param {Number} height The new height to set. This may be one of:<div class="mdetail-params"><ul>
3160      * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3161      * <li>A String used to set the CSS height style.</li>
3162      * <li><i>undefined</i> to leave the height unchanged.</li>
3163      * </ul></div>
3164      * @return {Ext.BoxComponent} this
3165      */
3166     setHeight : function(height){
3167         return this.setSize(undefined, height);
3168     },
3169
3170     /**
3171      * Gets the current size of the component's underlying element.
3172      * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
3173      */
3174     getSize : function(){
3175         return this.getResizeEl().getSize();
3176     },
3177
3178     /**
3179      * Gets the current width of the component's underlying element.
3180      * @return {Number}
3181      */
3182     getWidth : function(){
3183         return this.getResizeEl().getWidth();
3184     },
3185
3186     /**
3187      * Gets the current height of the component's underlying element.
3188      * @return {Number}
3189      */
3190     getHeight : function(){
3191         return this.getResizeEl().getHeight();
3192     },
3193
3194     /**
3195      * Gets the current size of the component's underlying element, including space taken by its margins.
3196      * @return {Object} An object containing the element's size {width: (element width + left/right margins), height: (element height + top/bottom margins)}
3197      */
3198     getOuterSize : function(){
3199         var el = this.getResizeEl();
3200         return {width: el.getWidth() + el.getMargins('lr'),
3201                 height: el.getHeight() + el.getMargins('tb')};
3202     },
3203
3204     /**
3205      * Gets the current XY position of the component's underlying element.
3206      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
3207      * @return {Array} The XY position of the element (e.g., [100, 200])
3208      */
3209     getPosition : function(local){
3210         var el = this.getPositionEl();
3211         if(local === true){
3212             return [el.getLeft(true), el.getTop(true)];
3213         }
3214         return this.xy || el.getXY();
3215     },
3216
3217     /**
3218      * Gets the current box measurements of the component's underlying element.
3219      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
3220      * @return {Object} box An object in the format {x, y, width, height}
3221      */
3222     getBox : function(local){
3223         var pos = this.getPosition(local);
3224         var s = this.getSize();
3225         s.x = pos[0];
3226         s.y = pos[1];
3227         return s;
3228     },
3229
3230     /**
3231      * Sets the current box measurements of the component's underlying element.
3232      * @param {Object} box An object in the format {x, y, width, height}
3233      * @return {Ext.BoxComponent} this
3234      */
3235     updateBox : function(box){
3236         this.setSize(box.width, box.height);
3237         this.setPagePosition(box.x, box.y);
3238         return this;
3239     },
3240
3241     /**
3242      * <p>Returns the outermost Element of this Component which defines the Components overall size.</p>
3243      * <p><i>Usually</i> this will return the same Element as <code>{@link #getEl}</code>,
3244      * but in some cases, a Component may have some more wrapping Elements around its main
3245      * active Element.</p>
3246      * <p>An example is a ComboBox. It is encased in a <i>wrapping</i> Element which
3247      * contains both the <code>&lt;input></code> Element (which is what would be returned
3248      * by its <code>{@link #getEl}</code> method, <i>and</i> the trigger button Element.
3249      * This Element is returned as the <code>resizeEl</code>.
3250      * @return {Ext.Element} The Element which is to be resized by size managing layouts.
3251      */
3252     getResizeEl : function(){
3253         return this.resizeEl || this.el;
3254     },
3255
3256     /**
3257      * Sets the overflow on the content element of the component.
3258      * @param {Boolean} scroll True to allow the Component to auto scroll.
3259      * @return {Ext.BoxComponent} this
3260      */
3261     setAutoScroll : function(scroll){
3262         if(this.rendered){
3263             this.getContentTarget().setOverflow(scroll ? 'auto' : '');
3264         }
3265         this.autoScroll = scroll;
3266         return this;
3267     },
3268
3269     /**
3270      * Sets the left and top of the component.  To set the page XY position instead, use {@link #setPagePosition}.
3271      * This method fires the {@link #move} event.
3272      * @param {Number} left The new left
3273      * @param {Number} top The new top
3274      * @return {Ext.BoxComponent} this
3275      */
3276     setPosition : function(x, y){
3277         if(x && typeof x[1] == 'number'){
3278             y = x[1];
3279             x = x[0];
3280         }
3281         this.x = x;
3282         this.y = y;
3283         if(!this.boxReady){
3284             return this;
3285         }
3286         var adj = this.adjustPosition(x, y);
3287         var ax = adj.x, ay = adj.y;
3288
3289         var el = this.getPositionEl();
3290         if(ax !== undefined || ay !== undefined){
3291             if(ax !== undefined && ay !== undefined){
3292                 el.setLeftTop(ax, ay);
3293             }else if(ax !== undefined){
3294                 el.setLeft(ax);
3295             }else if(ay !== undefined){
3296                 el.setTop(ay);
3297             }
3298             this.onPosition(ax, ay);
3299             this.fireEvent('move', this, ax, ay);
3300         }
3301         return this;
3302     },
3303
3304     /**
3305      * Sets the page XY position of the component.  To set the left and top instead, use {@link #setPosition}.
3306      * This method fires the {@link #move} event.
3307      * @param {Number} x The new x position
3308      * @param {Number} y The new y position
3309      * @return {Ext.BoxComponent} this
3310      */
3311     setPagePosition : function(x, y){
3312         if(x && typeof x[1] == 'number'){
3313             y = x[1];
3314             x = x[0];
3315         }
3316         this.pageX = x;
3317         this.pageY = y;
3318         if(!this.boxReady){
3319             return;
3320         }
3321         if(x === undefined || y === undefined){ // cannot translate undefined points
3322             return;
3323         }
3324         var p = this.getPositionEl().translatePoints(x, y);
3325         this.setPosition(p.left, p.top);
3326         return this;
3327     },
3328
3329     // private
3330     afterRender : function(){
3331         Ext.BoxComponent.superclass.afterRender.call(this);
3332         if(this.resizeEl){
3333             this.resizeEl = Ext.get(this.resizeEl);
3334         }
3335         if(this.positionEl){
3336             this.positionEl = Ext.get(this.positionEl);
3337         }
3338         this.boxReady = true;
3339         Ext.isDefined(this.autoScroll) && this.setAutoScroll(this.autoScroll);
3340         this.setSize(this.width, this.height);
3341         if(this.x || this.y){
3342             this.setPosition(this.x, this.y);
3343         }else if(this.pageX || this.pageY){
3344             this.setPagePosition(this.pageX, this.pageY);
3345         }
3346     },
3347
3348     /**
3349      * Force the component's size to recalculate based on the underlying element's current height and width.
3350      * @return {Ext.BoxComponent} this
3351      */
3352     syncSize : function(){
3353         delete this.lastSize;
3354         this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
3355         return this;
3356     },
3357
3358     /* // protected
3359      * Called after the component is resized, this method is empty by default but can be implemented by any
3360      * subclass that needs to perform custom logic after a resize occurs.
3361      * @param {Number} adjWidth The box-adjusted width that was set
3362      * @param {Number} adjHeight The box-adjusted height that was set
3363      * @param {Number} rawWidth The width that was originally specified
3364      * @param {Number} rawHeight The height that was originally specified
3365      */
3366     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
3367     },
3368
3369     /* // protected
3370      * Called after the component is moved, this method is empty by default but can be implemented by any
3371      * subclass that needs to perform custom logic after a move occurs.
3372      * @param {Number} x The new x position
3373      * @param {Number} y The new y position
3374      */
3375     onPosition : function(x, y){
3376
3377     },
3378
3379     // private
3380     adjustSize : function(w, h){
3381         if(this.autoWidth){
3382             w = 'auto';
3383         }
3384         if(this.autoHeight){
3385             h = 'auto';
3386         }
3387         return {width : w, height: h};
3388     },
3389
3390     // private
3391     adjustPosition : function(x, y){
3392         return {x : x, y: y};
3393     }
3394 });
3395 Ext.reg('box', Ext.BoxComponent);
3396
3397
3398 /**
3399  * @class Ext.Spacer
3400  * @extends Ext.BoxComponent
3401  * <p>Used to provide a sizable space in a layout.</p>
3402  * @constructor
3403  * @param {Object} config
3404  */
3405 Ext.Spacer = Ext.extend(Ext.BoxComponent, {
3406     autoEl:'div'
3407 });
3408 Ext.reg('spacer', Ext.Spacer);/**\r
3409  * @class Ext.SplitBar\r
3410  * @extends Ext.util.Observable\r
3411  * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).\r
3412  * <br><br>\r
3413  * Usage:\r
3414  * <pre><code>\r
3415 var split = new Ext.SplitBar("elementToDrag", "elementToSize",\r
3416                    Ext.SplitBar.HORIZONTAL, Ext.SplitBar.LEFT);\r
3417 split.setAdapter(new Ext.SplitBar.AbsoluteLayoutAdapter("container"));\r
3418 split.minSize = 100;\r
3419 split.maxSize = 600;\r
3420 split.animate = true;\r
3421 split.on('moved', splitterMoved);\r
3422 </code></pre>\r
3423  * @constructor\r
3424  * Create a new SplitBar\r
3425  * @param {Mixed} dragElement The element to be dragged and act as the SplitBar.\r
3426  * @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged\r
3427  * @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)\r
3428  * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or\r
3429                         Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial\r
3430                         position of the SplitBar).\r
3431  */\r
3432 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){\r
3433 \r
3434     /** @private */\r
3435     this.el = Ext.get(dragElement, true);\r
3436     this.el.dom.unselectable = "on";\r
3437     /** @private */\r
3438     this.resizingEl = Ext.get(resizingElement, true);\r
3439 \r
3440     /**\r
3441      * @private\r
3442      * The orientation of the split. Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)\r
3443      * Note: If this is changed after creating the SplitBar, the placement property must be manually updated\r
3444      * @type Number\r
3445      */\r
3446     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;\r
3447 \r
3448     /**\r
3449      * The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.\r
3450      * @type Number\r
3451      * @property tickSize\r
3452      */\r
3453     /**\r
3454      * The minimum size of the resizing element. (Defaults to 0)\r
3455      * @type Number\r
3456      */\r
3457     this.minSize = 0;\r
3458 \r
3459     /**\r
3460      * The maximum size of the resizing element. (Defaults to 2000)\r
3461      * @type Number\r
3462      */\r
3463     this.maxSize = 2000;\r
3464 \r
3465     /**\r
3466      * Whether to animate the transition to the new size\r
3467      * @type Boolean\r
3468      */\r
3469     this.animate = false;\r
3470 \r
3471     /**\r
3472      * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.\r
3473      * @type Boolean\r
3474      */\r
3475     this.useShim = false;\r
3476 \r
3477     /** @private */\r
3478     this.shim = null;\r
3479 \r
3480     if(!existingProxy){\r
3481         /** @private */\r
3482         this.proxy = Ext.SplitBar.createProxy(this.orientation);\r
3483     }else{\r
3484         this.proxy = Ext.get(existingProxy).dom;\r
3485     }\r
3486     /** @private */\r
3487     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});\r
3488 \r
3489     /** @private */\r
3490     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);\r
3491 \r
3492     /** @private */\r
3493     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);\r
3494 \r
3495     /** @private */\r
3496     this.dragSpecs = {};\r
3497 \r
3498     /**\r
3499      * @private The adapter to use to positon and resize elements\r
3500      */\r
3501     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();\r
3502     this.adapter.init(this);\r
3503 \r
3504     if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
3505         /** @private */\r
3506         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);\r
3507         this.el.addClass("x-splitbar-h");\r
3508     }else{\r
3509         /** @private */\r
3510         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);\r
3511         this.el.addClass("x-splitbar-v");\r
3512     }\r
3513 \r
3514     this.addEvents(\r
3515         /**\r
3516          * @event resize\r
3517          * Fires when the splitter is moved (alias for {@link #moved})\r
3518          * @param {Ext.SplitBar} this\r
3519          * @param {Number} newSize the new width or height\r
3520          */\r
3521         "resize",\r
3522         /**\r
3523          * @event moved\r
3524          * Fires when the splitter is moved\r
3525          * @param {Ext.SplitBar} this\r
3526          * @param {Number} newSize the new width or height\r
3527          */\r
3528         "moved",\r
3529         /**\r
3530          * @event beforeresize\r
3531          * Fires before the splitter is dragged\r
3532          * @param {Ext.SplitBar} this\r
3533          */\r
3534         "beforeresize",\r
3535 \r
3536         "beforeapply"\r
3537     );\r
3538 \r
3539     Ext.SplitBar.superclass.constructor.call(this);\r
3540 };\r
3541 \r
3542 Ext.extend(Ext.SplitBar, Ext.util.Observable, {\r
3543     onStartProxyDrag : function(x, y){\r
3544         this.fireEvent("beforeresize", this);\r
3545         this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);\r
3546         this.overlay.unselectable();\r
3547         this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));\r
3548         this.overlay.show();\r
3549         Ext.get(this.proxy).setDisplayed("block");\r
3550         var size = this.adapter.getElementSize(this);\r
3551         this.activeMinSize = this.getMinimumSize();\r
3552         this.activeMaxSize = this.getMaximumSize();\r
3553         var c1 = size - this.activeMinSize;\r
3554         var c2 = Math.max(this.activeMaxSize - size, 0);\r
3555         if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
3556             this.dd.resetConstraints();\r
3557             this.dd.setXConstraint(\r
3558                 this.placement == Ext.SplitBar.LEFT ? c1 : c2,\r
3559                 this.placement == Ext.SplitBar.LEFT ? c2 : c1,\r
3560                 this.tickSize\r
3561             );\r
3562             this.dd.setYConstraint(0, 0);\r
3563         }else{\r
3564             this.dd.resetConstraints();\r
3565             this.dd.setXConstraint(0, 0);\r
3566             this.dd.setYConstraint(\r
3567                 this.placement == Ext.SplitBar.TOP ? c1 : c2,\r
3568                 this.placement == Ext.SplitBar.TOP ? c2 : c1,\r
3569                 this.tickSize\r
3570             );\r
3571          }\r
3572         this.dragSpecs.startSize = size;\r
3573         this.dragSpecs.startPoint = [x, y];\r
3574         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);\r
3575     },\r
3576 \r
3577     /**\r
3578      * @private Called after the drag operation by the DDProxy\r
3579      */\r
3580     onEndProxyDrag : function(e){\r
3581         Ext.get(this.proxy).setDisplayed(false);\r
3582         var endPoint = Ext.lib.Event.getXY(e);\r
3583         if(this.overlay){\r
3584             Ext.destroy(this.overlay);\r
3585             delete this.overlay;\r
3586         }\r
3587         var newSize;\r
3588         if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
3589             newSize = this.dragSpecs.startSize +\r
3590                 (this.placement == Ext.SplitBar.LEFT ?\r
3591                     endPoint[0] - this.dragSpecs.startPoint[0] :\r
3592                     this.dragSpecs.startPoint[0] - endPoint[0]\r
3593                 );\r
3594         }else{\r
3595             newSize = this.dragSpecs.startSize +\r
3596                 (this.placement == Ext.SplitBar.TOP ?\r
3597                     endPoint[1] - this.dragSpecs.startPoint[1] :\r
3598                     this.dragSpecs.startPoint[1] - endPoint[1]\r
3599                 );\r
3600         }\r
3601         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);\r
3602         if(newSize != this.dragSpecs.startSize){\r
3603             if(this.fireEvent('beforeapply', this, newSize) !== false){\r
3604                 this.adapter.setElementSize(this, newSize);\r
3605                 this.fireEvent("moved", this, newSize);\r
3606                 this.fireEvent("resize", this, newSize);\r
3607             }\r
3608         }\r
3609     },\r
3610 \r
3611     /**\r
3612      * Get the adapter this SplitBar uses\r
3613      * @return The adapter object\r
3614      */\r
3615     getAdapter : function(){\r
3616         return this.adapter;\r
3617     },\r
3618 \r
3619     /**\r
3620      * Set the adapter this SplitBar uses\r
3621      * @param {Object} adapter A SplitBar adapter object\r
3622      */\r
3623     setAdapter : function(adapter){\r
3624         this.adapter = adapter;\r
3625         this.adapter.init(this);\r
3626     },\r
3627 \r
3628     /**\r
3629      * Gets the minimum size for the resizing element\r
3630      * @return {Number} The minimum size\r
3631      */\r
3632     getMinimumSize : function(){\r
3633         return this.minSize;\r
3634     },\r
3635 \r
3636     /**\r
3637      * Sets the minimum size for the resizing element\r
3638      * @param {Number} minSize The minimum size\r
3639      */\r
3640     setMinimumSize : function(minSize){\r
3641         this.minSize = minSize;\r
3642     },\r
3643 \r
3644     /**\r
3645      * Gets the maximum size for the resizing element\r
3646      * @return {Number} The maximum size\r
3647      */\r
3648     getMaximumSize : function(){\r
3649         return this.maxSize;\r
3650     },\r
3651 \r
3652     /**\r
3653      * Sets the maximum size for the resizing element\r
3654      * @param {Number} maxSize The maximum size\r
3655      */\r
3656     setMaximumSize : function(maxSize){\r
3657         this.maxSize = maxSize;\r
3658     },\r
3659 \r
3660     /**\r
3661      * Sets the initialize size for the resizing element\r
3662      * @param {Number} size The initial size\r
3663      */\r
3664     setCurrentSize : function(size){\r
3665         var oldAnimate = this.animate;\r
3666         this.animate = false;\r
3667         this.adapter.setElementSize(this, size);\r
3668         this.animate = oldAnimate;\r
3669     },\r
3670 \r
3671     /**\r
3672      * Destroy this splitbar.\r
3673      * @param {Boolean} removeEl True to remove the element\r
3674      */\r
3675     destroy : function(removeEl){\r
3676         Ext.destroy(this.shim, Ext.get(this.proxy));\r
3677         this.dd.unreg();\r
3678         if(removeEl){\r
3679             this.el.remove();\r
3680         }\r
3681         this.purgeListeners();\r
3682     }\r
3683 });\r
3684 \r
3685 /**\r
3686  * @private static Create our own proxy element element. So it will be the same same size on all browsers, we won't use borders. Instead we use a background color.\r
3687  */\r
3688 Ext.SplitBar.createProxy = function(dir){\r
3689     var proxy = new Ext.Element(document.createElement("div"));\r
3690     document.body.appendChild(proxy.dom);\r
3691     proxy.unselectable();\r
3692     var cls = 'x-splitbar-proxy';\r
3693     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));\r
3694     return proxy.dom;\r
3695 };\r
3696 \r
3697 /**\r
3698  * @class Ext.SplitBar.BasicLayoutAdapter\r
3699  * Default Adapter. It assumes the splitter and resizing element are not positioned\r
3700  * elements and only gets/sets the width of the element. Generally used for table based layouts.\r
3701  */\r
3702 Ext.SplitBar.BasicLayoutAdapter = function(){\r
3703 };\r
3704 \r
3705 Ext.SplitBar.BasicLayoutAdapter.prototype = {\r
3706     // do nothing for now\r
3707     init : function(s){\r
3708 \r
3709     },\r
3710     /**\r
3711      * Called before drag operations to get the current size of the resizing element.\r
3712      * @param {Ext.SplitBar} s The SplitBar using this adapter\r
3713      */\r
3714      getElementSize : function(s){\r
3715         if(s.orientation == Ext.SplitBar.HORIZONTAL){\r
3716             return s.resizingEl.getWidth();\r
3717         }else{\r
3718             return s.resizingEl.getHeight();\r
3719         }\r
3720     },\r
3721 \r
3722     /**\r
3723      * Called after drag operations to set the size of the resizing element.\r
3724      * @param {Ext.SplitBar} s The SplitBar using this adapter\r
3725      * @param {Number} newSize The new size to set\r
3726      * @param {Function} onComplete A function to be invoked when resizing is complete\r
3727      */\r
3728     setElementSize : function(s, newSize, onComplete){\r
3729         if(s.orientation == Ext.SplitBar.HORIZONTAL){\r
3730             if(!s.animate){\r
3731                 s.resizingEl.setWidth(newSize);\r
3732                 if(onComplete){\r
3733                     onComplete(s, newSize);\r
3734                 }\r
3735             }else{\r
3736                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');\r
3737             }\r
3738         }else{\r
3739 \r
3740             if(!s.animate){\r
3741                 s.resizingEl.setHeight(newSize);\r
3742                 if(onComplete){\r
3743                     onComplete(s, newSize);\r
3744                 }\r
3745             }else{\r
3746                 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');\r
3747             }\r
3748         }\r
3749     }\r
3750 };\r
3751 \r
3752 /**\r
3753  *@class Ext.SplitBar.AbsoluteLayoutAdapter\r
3754  * @extends Ext.SplitBar.BasicLayoutAdapter\r
3755  * Adapter that  moves the splitter element to align with the resized sizing element.\r
3756  * Used with an absolute positioned SplitBar.\r
3757  * @param {Mixed} container The container that wraps around the absolute positioned content. If it's\r
3758  * document.body, make sure you assign an id to the body element.\r
3759  */\r
3760 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){\r
3761     this.basic = new Ext.SplitBar.BasicLayoutAdapter();\r
3762     this.container = Ext.get(container);\r
3763 };\r
3764 \r
3765 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {\r
3766     init : function(s){\r
3767         this.basic.init(s);\r
3768     },\r
3769 \r
3770     getElementSize : function(s){\r
3771         return this.basic.getElementSize(s);\r
3772     },\r
3773 \r
3774     setElementSize : function(s, newSize, onComplete){\r
3775         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));\r
3776     },\r
3777 \r
3778     moveSplitter : function(s){\r
3779         var yes = Ext.SplitBar;\r
3780         switch(s.placement){\r
3781             case yes.LEFT:\r
3782                 s.el.setX(s.resizingEl.getRight());\r
3783                 break;\r
3784             case yes.RIGHT:\r
3785                 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");\r
3786                 break;\r
3787             case yes.TOP:\r
3788                 s.el.setY(s.resizingEl.getBottom());\r
3789                 break;\r
3790             case yes.BOTTOM:\r
3791                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());\r
3792                 break;\r
3793         }\r
3794     }\r
3795 };\r
3796 \r
3797 /**\r
3798  * Orientation constant - Create a vertical SplitBar\r
3799  * @static\r
3800  * @type Number\r
3801  */\r
3802 Ext.SplitBar.VERTICAL = 1;\r
3803 \r
3804 /**\r
3805  * Orientation constant - Create a horizontal SplitBar\r
3806  * @static\r
3807  * @type Number\r
3808  */\r
3809 Ext.SplitBar.HORIZONTAL = 2;\r
3810 \r
3811 /**\r
3812  * Placement constant - The resizing element is to the left of the splitter element\r
3813  * @static\r
3814  * @type Number\r
3815  */\r
3816 Ext.SplitBar.LEFT = 1;\r
3817 \r
3818 /**\r
3819  * Placement constant - The resizing element is to the right of the splitter element\r
3820  * @static\r
3821  * @type Number\r
3822  */\r
3823 Ext.SplitBar.RIGHT = 2;\r
3824 \r
3825 /**\r
3826  * Placement constant - The resizing element is positioned above the splitter element\r
3827  * @static\r
3828  * @type Number\r
3829  */\r
3830 Ext.SplitBar.TOP = 3;\r
3831 \r
3832 /**\r
3833  * Placement constant - The resizing element is positioned under splitter element\r
3834  * @static\r
3835  * @type Number\r
3836  */\r
3837 Ext.SplitBar.BOTTOM = 4;\r
3838 /**
3839  * @class Ext.Container
3840  * @extends Ext.BoxComponent
3841  * <p>Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the
3842  * basic behavior of containing items, namely adding, inserting and removing items.</p>
3843  *
3844  * <p>The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}.
3845  * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight
3846  * Container to be encapsulated by an HTML element to your specifications by using the
3847  * <code><b>{@link Ext.Component#autoEl autoEl}</b></code> config option. This is a useful technique when creating
3848  * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels}
3849  * for example.</p>
3850  *
3851  * <p>The code below illustrates both how to explicitly create a Container, and how to implicitly
3852  * create one using the <b><code>'container'</code></b> xtype:<pre><code>
3853 // explicitly create a Container
3854 var embeddedColumns = new Ext.Container({
3855     autoEl: 'div',  // This is the default
3856     layout: 'column',
3857     defaults: {
3858         // implicitly create Container by specifying xtype
3859         xtype: 'container',
3860         autoEl: 'div', // This is the default.
3861         layout: 'form',
3862         columnWidth: 0.5,
3863         style: {
3864             padding: '10px'
3865         }
3866     },
3867 //  The two items below will be Ext.Containers, each encapsulated by a &lt;DIV> element.
3868     items: [{
3869         items: {
3870             xtype: 'datefield',
3871             name: 'startDate',
3872             fieldLabel: 'Start date'
3873         }
3874     }, {
3875         items: {
3876             xtype: 'datefield',
3877             name: 'endDate',
3878             fieldLabel: 'End date'
3879         }
3880     }]
3881 });</code></pre></p>
3882  *
3883  * <p><u><b>Layout</b></u></p>
3884  * <p>Container classes delegate the rendering of child Components to a layout
3885  * manager class which must be configured into the Container using the
3886  * <code><b>{@link #layout}</b></code> configuration property.</p>
3887  * <p>When either specifying child <code>{@link #items}</code> of a Container,
3888  * or dynamically {@link #add adding} Components to a Container, remember to
3889  * consider how you wish the Container to arrange those child elements, and
3890  * whether those child elements need to be sized using one of Ext's built-in
3891  * <b><code>{@link #layout}</code></b> schemes. By default, Containers use the
3892  * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only
3893  * renders child components, appending them one after the other inside the
3894  * Container, and <b>does not apply any sizing</b> at all.</p>
3895  * <p>A common mistake is when a developer neglects to specify a
3896  * <b><code>{@link #layout}</code></b> (e.g. widgets like GridPanels or
3897  * TreePanels are added to Containers for which no <code><b>{@link #layout}</b></code>
3898  * has been specified). If a Container is left to use the default
3899  * {@link Ext.layout.ContainerLayout ContainerLayout} scheme, none of its
3900  * child components will be resized, or changed in any way when the Container
3901  * is resized.</p>
3902  * <p>Certain layout managers allow dynamic addition of child components.
3903  * Those that do include {@link Ext.layout.CardLayout},
3904  * {@link Ext.layout.AnchorLayout}, {@link Ext.layout.FormLayout}, and
3905  * {@link Ext.layout.TableLayout}. For example:<pre><code>
3906 //  Create the GridPanel.
3907 var myNewGrid = new Ext.grid.GridPanel({
3908     store: myStore,
3909     columns: myColumnModel,
3910     title: 'Results', // the title becomes the title of the tab
3911 });
3912
3913 myTabPanel.add(myNewGrid); // {@link Ext.TabPanel} implicitly uses {@link Ext.layout.CardLayout CardLayout}
3914 myTabPanel.{@link Ext.TabPanel#setActiveTab setActiveTab}(myNewGrid);
3915  * </code></pre></p>
3916  * <p>The example above adds a newly created GridPanel to a TabPanel. Note that
3917  * a TabPanel uses {@link Ext.layout.CardLayout} as its layout manager which
3918  * means all its child items are sized to {@link Ext.layout.FitLayout fit}
3919  * exactly into its client area.
3920  * <p><b><u>Overnesting is a common problem</u></b>.
3921  * An example of overnesting occurs when a GridPanel is added to a TabPanel
3922  * by wrapping the GridPanel <i>inside</i> a wrapping Panel (that has no
3923  * <code><b>{@link #layout}</b></code> specified) and then add that wrapping Panel
3924  * to the TabPanel. The point to realize is that a GridPanel <b>is</b> a
3925  * Component which can be added directly to a Container. If the wrapping Panel
3926  * has no <code><b>{@link #layout}</b></code> configuration, then the overnested
3927  * GridPanel will not be sized as expected.<p>
3928  *
3929  * <p><u><b>Adding via remote configuration</b></u></p>
3930  *
3931  * <p>A server side script can be used to add Components which are generated dynamically on the server.
3932  * An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server
3933  * based on certain parameters:
3934  * </p><pre><code>
3935 // execute an Ajax request to invoke server side script:
3936 Ext.Ajax.request({
3937     url: 'gen-invoice-grid.php',
3938     // send additional parameters to instruct server script
3939     params: {
3940         startDate: Ext.getCmp('start-date').getValue(),
3941         endDate: Ext.getCmp('end-date').getValue()
3942     },
3943     // process the response object to add it to the TabPanel:
3944     success: function(xhr) {
3945         var newComponent = eval(xhr.responseText); // see discussion below
3946         myTabPanel.add(newComponent); // add the component to the TabPanel
3947         myTabPanel.setActiveTab(newComponent);
3948     },
3949     failure: function() {
3950         Ext.Msg.alert("Grid create failed", "Server communication failure");
3951     }
3952 });
3953 </code></pre>
3954  * <p>The server script needs to return an executable Javascript statement which, when processed
3955  * using <code>eval()</code>, will return either a config object with an {@link Ext.Component#xtype xtype},
3956  * or an instantiated Component. The server might return this for example:</p><pre><code>
3957 (function() {
3958     function formatDate(value){
3959         return value ? value.dateFormat('M d, Y') : '';
3960     };
3961
3962     var store = new Ext.data.Store({
3963         url: 'get-invoice-data.php',
3964         baseParams: {
3965             startDate: '01/01/2008',
3966             endDate: '01/31/2008'
3967         },
3968         reader: new Ext.data.JsonReader({
3969             record: 'transaction',
3970             idProperty: 'id',
3971             totalRecords: 'total'
3972         }, [
3973            'customer',
3974            'invNo',
3975            {name: 'date', type: 'date', dateFormat: 'm/d/Y'},
3976            {name: 'value', type: 'float'}
3977         ])
3978     });
3979
3980     var grid = new Ext.grid.GridPanel({
3981         title: 'Invoice Report',
3982         bbar: new Ext.PagingToolbar(store),
3983         store: store,
3984         columns: [
3985             {header: "Customer", width: 250, dataIndex: 'customer', sortable: true},
3986             {header: "Invoice Number", width: 120, dataIndex: 'invNo', sortable: true},
3987             {header: "Invoice Date", width: 100, dataIndex: 'date', renderer: formatDate, sortable: true},
3988             {header: "Value", width: 120, dataIndex: 'value', renderer: 'usMoney', sortable: true}
3989         ],
3990     });
3991     store.load();
3992     return grid;  // return instantiated component
3993 })();
3994 </code></pre>
3995  * <p>When the above code fragment is passed through the <code>eval</code> function in the success handler
3996  * of the Ajax request, the code is executed by the Javascript processor, and the anonymous function
3997  * runs, and returns the instantiated grid component.</p>
3998  * <p>Note: since the code above is <i>generated</i> by a server script, the <code>baseParams</code> for
3999  * the Store, the metadata to allow generation of the Record layout, and the ColumnModel
4000  * can all be generated into the code since these are all known on the server.</p>
4001  *
4002  * @xtype container
4003  */
4004 Ext.Container = Ext.extend(Ext.BoxComponent, {
4005     /**
4006      * @cfg {Boolean} monitorResize
4007      * True to automatically monitor window resize events to handle anything that is sensitive to the current size
4008      * of the viewport.  This value is typically managed by the chosen <code>{@link #layout}</code> and should not need
4009      * to be set manually.
4010      */
4011     /**
4012      * @cfg {String/Object} layout
4013      * <p><b>*Important</b>: In order for child items to be correctly sized and
4014      * positioned, typically a layout manager <b>must</b> be specified through
4015      * the <code>layout</code> configuration option.</p>
4016      * <br><p>The sizing and positioning of child {@link items} is the responsibility of
4017      * the Container's layout manager which creates and manages the type of layout
4018      * you have in mind.  For example:</p><pre><code>
4019 new Ext.Window({
4020     width:300, height: 300,
4021     layout: 'fit', // explicitly set layout manager: override the default (layout:'auto')
4022     items: [{
4023         title: 'Panel inside a Window'
4024     }]
4025 }).show();
4026      * </code></pre>
4027      * <p>If the {@link #layout} configuration is not explicitly specified for
4028      * a general purpose container (e.g. Container or Panel) the
4029      * {@link Ext.layout.ContainerLayout default layout manager} will be used
4030      * which does nothing but render child components sequentially into the
4031      * Container (no sizing or positioning will be performed in this situation).
4032      * Some container classes implicitly specify a default layout
4033      * (e.g. FormPanel specifies <code>layout:'form'</code>). Other specific
4034      * purpose classes internally specify/manage their internal layout (e.g.
4035      * GridPanel, TabPanel, TreePanel, Toolbar, Menu, etc.).</p>
4036      * <br><p><b><code>layout</code></b> may be specified as either as an Object or
4037      * as a String:</p><div><ul class="mdetail-params">
4038      *
4039      * <li><u>Specify as an Object</u></li>
4040      * <div><ul class="mdetail-params">
4041      * <li>Example usage:</li>
4042 <pre><code>
4043 layout: {
4044     type: 'vbox',
4045     padding: '5',
4046     align: 'left'
4047 }
4048 </code></pre>
4049      *
4050      * <li><code><b>type</b></code></li>
4051      * <br/><p>The layout type to be used for this container.  If not specified,
4052      * a default {@link Ext.layout.ContainerLayout} will be created and used.</p>
4053      * <br/><p>Valid layout <code>type</code> values are:</p>
4054      * <div class="sub-desc"><ul class="mdetail-params">
4055      * <li><code><b>{@link Ext.layout.AbsoluteLayout absolute}</b></code></li>
4056      * <li><code><b>{@link Ext.layout.AccordionLayout accordion}</b></code></li>
4057      * <li><code><b>{@link Ext.layout.AnchorLayout anchor}</b></code></li>
4058      * <li><code><b>{@link Ext.layout.ContainerLayout auto}</b></code> &nbsp;&nbsp;&nbsp; <b>Default</b></li>
4059      * <li><code><b>{@link Ext.layout.BorderLayout border}</b></code></li>
4060      * <li><code><b>{@link Ext.layout.CardLayout card}</b></code></li>
4061      * <li><code><b>{@link Ext.layout.ColumnLayout column}</b></code></li>
4062      * <li><code><b>{@link Ext.layout.FitLayout fit}</b></code></li>
4063      * <li><code><b>{@link Ext.layout.FormLayout form}</b></code></li>
4064      * <li><code><b>{@link Ext.layout.HBoxLayout hbox}</b></code></li>
4065      * <li><code><b>{@link Ext.layout.MenuLayout menu}</b></code></li>
4066      * <li><code><b>{@link Ext.layout.TableLayout table}</b></code></li>
4067      * <li><code><b>{@link Ext.layout.ToolbarLayout toolbar}</b></code></li>
4068      * <li><code><b>{@link Ext.layout.VBoxLayout vbox}</b></code></li>
4069      * </ul></div>
4070      *
4071      * <li>Layout specific configuration properties</li>
4072      * <br/><p>Additional layout specific configuration properties may also be
4073      * specified. For complete details regarding the valid config options for
4074      * each layout type, see the layout class corresponding to the <code>type</code>
4075      * specified.</p>
4076      *
4077      * </ul></div>
4078      *
4079      * <li><u>Specify as a String</u></li>
4080      * <div><ul class="mdetail-params">
4081      * <li>Example usage:</li>
4082 <pre><code>
4083 layout: 'vbox',
4084 layoutConfig: {
4085     padding: '5',
4086     align: 'left'
4087 }
4088 </code></pre>
4089      * <li><code><b>layout</b></code></li>
4090      * <br/><p>The layout <code>type</code> to be used for this container (see list
4091      * of valid layout type values above).</p><br/>
4092      * <li><code><b>{@link #layoutConfig}</b></code></li>
4093      * <br/><p>Additional layout specific configuration properties. For complete
4094      * details regarding the valid config options for each layout type, see the
4095      * layout class corresponding to the <code>layout</code> specified.</p>
4096      * </ul></div></ul></div>
4097      */
4098     /**
4099      * @cfg {Object} layoutConfig
4100      * This is a config object containing properties specific to the chosen
4101      * <b><code>{@link #layout}</code></b> if <b><code>{@link #layout}</code></b>
4102      * has been specified as a <i>string</i>.</p>
4103      */
4104     /**
4105      * @cfg {Boolean/Number} bufferResize
4106      * When set to true (50 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer
4107      * the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers
4108      * with a large quantity of sub-components for which frequent layout calls would be expensive. Defaults to <code>50</code>.
4109      */
4110     // Deprecated - will be removed in 3.2.x
4111     bufferResize: 50,
4112
4113     /**
4114      * @cfg {String/Number} activeItem
4115      * A string component id or the numeric index of the component that should be initially activated within the
4116      * container's layout on render.  For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first
4117      * item in the container's collection).  activeItem only applies to layout styles that can display
4118      * items one at a time (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout} and
4119      * {@link Ext.layout.FitLayout}).  Related to {@link Ext.layout.ContainerLayout#activeItem}.
4120      */
4121     /**
4122      * @cfg {Object/Array} items
4123      * <pre><b>** IMPORTANT</b>: be sure to <b>{@link #layout specify a <code>layout</code>} if needed ! **</b></pre>
4124      * <p>A single item, or an array of child Components to be added to this container,
4125      * for example:</p>
4126      * <pre><code>
4127 // specifying a single item
4128 items: {...},
4129 layout: 'fit',    // specify a layout!
4130
4131 // specifying multiple items
4132 items: [{...}, {...}],
4133 layout: 'anchor', // specify a layout!
4134      * </code></pre>
4135      * <p>Each item may be:</p>
4136      * <div><ul class="mdetail-params">
4137      * <li>any type of object based on {@link Ext.Component}</li>
4138      * <li>a fully instanciated object or</li>
4139      * <li>an object literal that:</li>
4140      * <div><ul class="mdetail-params">
4141      * <li>has a specified <code>{@link Ext.Component#xtype xtype}</code></li>
4142      * <li>the {@link Ext.Component#xtype} specified is associated with the Component
4143      * desired and should be chosen from one of the available xtypes as listed
4144      * in {@link Ext.Component}.</li>
4145      * <li>If an <code>{@link Ext.Component#xtype xtype}</code> is not explicitly
4146      * specified, the {@link #defaultType} for that Container is used.</li>
4147      * <li>will be "lazily instanciated", avoiding the overhead of constructing a fully
4148      * instanciated Component object</li>
4149      * </ul></div></ul></div>
4150      * <p><b>Notes</b>:</p>
4151      * <div><ul class="mdetail-params">
4152      * <li>Ext uses lazy rendering. Child Components will only be rendered
4153      * should it become necessary. Items are automatically laid out when they are first
4154      * shown (no sizing is done while hidden), or in response to a {@link #doLayout} call.</li>
4155      * <li>Do not specify <code>{@link Ext.Panel#contentEl contentEl}</code>/
4156      * <code>{@link Ext.Panel#html html}</code> with <code>items</code>.</li>
4157      * </ul></div>
4158      */
4159     /**
4160      * @cfg {Object|Function} defaults
4161      * <p>This option is a means of applying default settings to all added items whether added through the {@link #items}
4162      * config or via the {@link #add} or {@link #insert} methods.</p>
4163      * <p>If an added item is a config object, and <b>not</b> an instantiated Component, then the default properties are
4164      * unconditionally applied. If the added item <b>is</b> an instantiated Component, then the default properties are
4165      * applied conditionally so as not to override existing properties in the item.</p>
4166      * <p>If the defaults option is specified as a function, then the function will be called using this Container as the
4167      * scope (<code>this</code> reference) and passing the added item as the first parameter. Any resulting object
4168      * from that call is then applied to the item as default properties.</p>
4169      * <p>For example, to automatically apply padding to the body of each of a set of
4170      * contained {@link Ext.Panel} items, you could pass: <code>defaults: {bodyStyle:'padding:15px'}</code>.</p>
4171      * <p>Usage:</p><pre><code>
4172 defaults: {               // defaults are applied to items, not the container
4173     autoScroll:true
4174 },
4175 items: [
4176     {
4177         xtype: 'panel',   // defaults <b>do not</b> have precedence over
4178         id: 'panel1',     // options in config objects, so the defaults
4179         autoScroll: false // will not be applied here, panel1 will be autoScroll:false
4180     },
4181     new Ext.Panel({       // defaults <b>do</b> have precedence over options
4182         id: 'panel2',     // options in components, so the defaults
4183         autoScroll: false // will be applied here, panel2 will be autoScroll:true.
4184     })
4185 ]
4186      * </code></pre>
4187      */
4188
4189
4190     /** @cfg {Boolean} autoDestroy
4191      * If true the container will automatically destroy any contained component that is removed from it, else
4192      * destruction must be handled manually (defaults to true).
4193      */
4194     autoDestroy : true,
4195
4196     /** @cfg {Boolean} forceLayout
4197      * If true the container will force a layout initially even if hidden or collapsed. This option
4198      * is useful for forcing forms to render in collapsed or hidden containers. (defaults to false).
4199      */
4200     forceLayout: false,
4201
4202     /** @cfg {Boolean} hideBorders
4203      * True to hide the borders of each contained component, false to defer to the component's existing
4204      * border settings (defaults to false).
4205      */
4206     /** @cfg {String} defaultType
4207      * <p>The default {@link Ext.Component xtype} of child Components to create in this Container when
4208      * a child item is specified as a raw configuration object, rather than as an instantiated Component.</p>
4209      * <p>Defaults to <code>'panel'</code>, except {@link Ext.menu.Menu} which defaults to <code>'menuitem'</code>,
4210      * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to <code>'button'</code>.</p>
4211      */
4212     defaultType : 'panel',
4213
4214     /** @cfg {String} resizeEvent
4215      * The event to listen to for resizing in layouts. Defaults to <code>'resize'</code>.
4216      */
4217     resizeEvent: 'resize',
4218
4219     /**
4220      * @cfg {Array} bubbleEvents
4221      * <p>An array of events that, when fired, should be bubbled to any parent container.
4222      * See {@link Ext.util.Observable#enableBubble}.
4223      * Defaults to <code>['add', 'remove']</code>.
4224      */
4225     bubbleEvents: ['add', 'remove'],
4226
4227     // private
4228     initComponent : function(){
4229         Ext.Container.superclass.initComponent.call(this);
4230
4231         this.addEvents(
4232             /**
4233              * @event afterlayout
4234              * Fires when the components in this container are arranged by the associated layout manager.
4235              * @param {Ext.Container} this
4236              * @param {ContainerLayout} layout The ContainerLayout implementation for this container
4237              */
4238             'afterlayout',
4239             /**
4240              * @event beforeadd
4241              * Fires before any {@link Ext.Component} is added or inserted into the container.
4242              * A handler can return false to cancel the add.
4243              * @param {Ext.Container} this
4244              * @param {Ext.Component} component The component being added
4245              * @param {Number} index The index at which the component will be added to the container's items collection
4246              */
4247             'beforeadd',
4248             /**
4249              * @event beforeremove
4250              * Fires before any {@link Ext.Component} is removed from the container.  A handler can return
4251              * false to cancel the remove.
4252              * @param {Ext.Container} this
4253              * @param {Ext.Component} component The component being removed
4254              */
4255             'beforeremove',
4256             /**
4257              * @event add
4258              * @bubbles
4259              * Fires after any {@link Ext.Component} is added or inserted into the container.
4260              * @param {Ext.Container} this
4261              * @param {Ext.Component} component The component that was added
4262              * @param {Number} index The index at which the component was added to the container's items collection
4263              */
4264             'add',
4265             /**
4266              * @event remove
4267              * @bubbles
4268              * Fires after any {@link Ext.Component} is removed from the container.
4269              * @param {Ext.Container} this
4270              * @param {Ext.Component} component The component that was removed
4271              */
4272             'remove'
4273         );
4274
4275         this.enableBubble(this.bubbleEvents);
4276
4277         /**
4278          * The collection of components in this container as a {@link Ext.util.MixedCollection}
4279          * @type MixedCollection
4280          * @property items
4281          */
4282         var items = this.items;
4283         if(items){
4284             delete this.items;
4285             this.add(items);
4286         }
4287     },
4288
4289     // private
4290     initItems : function(){
4291         if(!this.items){
4292             this.items = new Ext.util.MixedCollection(false, this.getComponentId);
4293             this.getLayout(); // initialize the layout
4294         }
4295     },
4296
4297     // private
4298     setLayout : function(layout){
4299         if(this.layout && this.layout != layout){
4300             this.layout.setContainer(null);
4301         }
4302         this.initItems();
4303         this.layout = layout;
4304         layout.setContainer(this);
4305     },
4306
4307     afterRender: function(){
4308         // Render this Container, this should be done before setLayout is called which
4309         // will hook onResize
4310         Ext.Container.superclass.afterRender.call(this);
4311         if(!this.layout){
4312             this.layout = 'auto';
4313         }
4314         if(Ext.isObject(this.layout) && !this.layout.layout){
4315             this.layoutConfig = this.layout;
4316             this.layout = this.layoutConfig.type;
4317         }
4318         if(Ext.isString(this.layout)){
4319             this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
4320         }
4321         this.setLayout(this.layout);
4322
4323         // If a CardLayout, the active item set
4324         if(this.activeItem !== undefined){
4325             var item = this.activeItem;
4326             delete this.activeItem;
4327             this.layout.setActiveItem(item);
4328         }
4329
4330         // If we have no ownerCt, render and size all children
4331         if(!this.ownerCt){
4332             this.doLayout(false, true);
4333         }
4334
4335         // This is a manually configured flag set by users in conjunction with renderTo.
4336         // Not to be confused with the flag by the same name used in Layouts.
4337         if(this.monitorResize === true){
4338             Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
4339         }
4340     },
4341
4342     /**
4343      * <p>Returns the Element to be used to contain the child Components of this Container.</p>
4344      * <p>An implementation is provided which returns the Container's {@link #getEl Element}, but
4345      * if there is a more complex structure to a Container, this may be overridden to return
4346      * the element into which the {@link #layout layout} renders child Components.</p>
4347      * @return {Ext.Element} The Element to render child Components into.
4348      */
4349     getLayoutTarget : function(){
4350         return this.el;
4351     },
4352
4353     // private - used as the key lookup function for the items collection
4354     getComponentId : function(comp){
4355         return comp.getItemId();
4356     },
4357
4358     /**
4359      * <p>Adds {@link Ext.Component Component}(s) to this Container.</p>
4360      * <br><p><b>Description</b></u> :
4361      * <div><ul class="mdetail-params">
4362      * <li>Fires the {@link #beforeadd} event before adding</li>
4363      * <li>The Container's {@link #defaults default config values} will be applied
4364      * accordingly (see <code>{@link #defaults}</code> for details).</li>
4365      * <li>Fires the {@link #add} event after the component has been added.</li>
4366      * </ul></div>
4367      * <br><p><b>Notes</b></u> :
4368      * <div><ul class="mdetail-params">
4369      * <li>If the Container is <i>already rendered</i> when <code>add</code>
4370      * is called, you may need to call {@link #doLayout} to refresh the view which causes
4371      * any unrendered child Components to be rendered. This is required so that you can
4372      * <code>add</code> multiple child components if needed while only refreshing the layout
4373      * once. For example:<pre><code>
4374 var tb = new {@link Ext.Toolbar}();
4375 tb.render(document.body);  // toolbar is rendered
4376 tb.add({text:'Button 1'}); // add multiple items ({@link #defaultType} for {@link Ext.Toolbar Toolbar} is 'button')
4377 tb.add({text:'Button 2'});
4378 tb.{@link #doLayout}();             // refresh the layout
4379      * </code></pre></li>
4380      * <li><i>Warning:</i> Containers directly managed by the BorderLayout layout manager
4381      * may not be removed or added.  See the Notes for {@link Ext.layout.BorderLayout BorderLayout}
4382      * for more details.</li>
4383      * </ul></div>
4384      * @param {Object/Array} component
4385      * <p>Either a single component or an Array of components to add.  See
4386      * <code>{@link #items}</code> for additional information.</p>
4387      * @param {Object} (Optional) component_2
4388      * @param {Object} (Optional) component_n
4389      * @return {Ext.Component} component The Component (or config object) that was added.
4390      */
4391     add : function(comp){
4392         this.initItems();
4393         var args = arguments.length > 1;
4394         if(args || Ext.isArray(comp)){
4395             var result = [];
4396             Ext.each(args ? arguments : comp, function(c){
4397                 result.push(this.add(c));
4398             }, this);
4399             return result;
4400         }
4401         var c = this.lookupComponent(this.applyDefaults(comp));
4402         var index = this.items.length;
4403         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
4404             this.items.add(c);
4405             // *onAdded
4406             c.onAdded(this, index);
4407             this.onAdd(c);
4408             this.fireEvent('add', this, c, index);
4409         }
4410         return c;
4411     },
4412
4413     onAdd : function(c){
4414         // Empty template method
4415     },
4416
4417     // private
4418     onAdded : function(container, pos) {
4419         //overridden here so we can cascade down, not worth creating a template method.
4420         this.ownerCt = container;
4421         this.initRef();
4422         //initialize references for child items
4423         this.cascade(function(c){
4424             c.initRef();
4425         });
4426         this.fireEvent('added', this, container, pos);
4427     },
4428
4429     /**
4430      * Inserts a Component into this Container at a specified index. Fires the
4431      * {@link #beforeadd} event before inserting, then fires the {@link #add} event after the
4432      * Component has been inserted.
4433      * @param {Number} index The index at which the Component will be inserted
4434      * into the Container's items collection
4435      * @param {Ext.Component} component The child Component to insert.<br><br>
4436      * Ext uses lazy rendering, and will only render the inserted Component should
4437      * it become necessary.<br><br>
4438      * A Component config object may be passed in order to avoid the overhead of
4439      * constructing a real Component object if lazy rendering might mean that the
4440      * inserted Component will not be rendered immediately. To take advantage of
4441      * this 'lazy instantiation', set the {@link Ext.Component#xtype} config
4442      * property to the registered type of the Component wanted.<br><br>
4443      * For a list of all available xtypes, see {@link Ext.Component}.
4444      * @return {Ext.Component} component The Component (or config object) that was
4445      * inserted with the Container's default config values applied.
4446      */
4447     insert : function(index, comp){
4448         this.initItems();
4449         var a = arguments, len = a.length;
4450         if(len > 2){
4451             var result = [];
4452             for(var i = len-1; i >= 1; --i) {
4453                 result.push(this.insert(index, a[i]));
4454             }
4455             return result;
4456         }
4457         var c = this.lookupComponent(this.applyDefaults(comp));
4458         index = Math.min(index, this.items.length);
4459         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
4460             if(c.ownerCt == this){
4461                 this.items.remove(c);
4462             }
4463             this.items.insert(index, c);
4464             c.onAdded(this, index);
4465             this.onAdd(c);
4466             this.fireEvent('add', this, c, index);
4467         }
4468         return c;
4469     },
4470
4471     // private
4472     applyDefaults : function(c){
4473         var d = this.defaults;
4474         if(d){
4475             if(Ext.isFunction(d)){
4476                 d = d.call(this, c);
4477             }
4478             if(Ext.isString(c)){
4479                 c = Ext.ComponentMgr.get(c);
4480                 Ext.apply(c, d);
4481             }else if(!c.events){
4482                 Ext.applyIf(c, d);
4483             }else{
4484                 Ext.apply(c, d);
4485             }
4486         }
4487         return c;
4488     },
4489
4490     // private
4491     onBeforeAdd : function(item){
4492         if(item.ownerCt){
4493             item.ownerCt.remove(item, false);
4494         }
4495         if(this.hideBorders === true){
4496             item.border = (item.border === true);
4497         }
4498     },
4499
4500     /**
4501      * Removes a component from this container.  Fires the {@link #beforeremove} event before removing, then fires
4502      * the {@link #remove} event after the component has been removed.
4503      * @param {Component/String} component The component reference or id to remove.
4504      * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
4505      * Defaults to the value of this Container's {@link #autoDestroy} config.
4506      * @return {Ext.Component} component The Component that was removed.
4507      */
4508     remove : function(comp, autoDestroy){
4509         this.initItems();
4510         var c = this.getComponent(comp);
4511         if(c && this.fireEvent('beforeremove', this, c) !== false){
4512             this.doRemove(c, autoDestroy);
4513             this.fireEvent('remove', this, c);
4514         }
4515         return c;
4516     },
4517
4518     onRemove: function(c){
4519         // Empty template method
4520     },
4521
4522     // private
4523     doRemove: function(c, autoDestroy){
4524         var l = this.layout,
4525             hasLayout = l && this.rendered;
4526
4527         if(hasLayout){
4528             l.onRemove(c);
4529         }
4530         this.items.remove(c);
4531         c.onRemoved();
4532         this.onRemove(c);
4533         if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
4534             c.destroy();
4535         }
4536         if(hasLayout){
4537             l.afterRemove(c);
4538         }
4539     },
4540
4541     /**
4542      * Removes all components from this container.
4543      * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
4544      * Defaults to the value of this Container's {@link #autoDestroy} config.
4545      * @return {Array} Array of the destroyed components
4546      */
4547     removeAll: function(autoDestroy){
4548         this.initItems();
4549         var item, rem = [], items = [];
4550         this.items.each(function(i){
4551             rem.push(i);
4552         });
4553         for (var i = 0, len = rem.length; i < len; ++i){
4554             item = rem[i];
4555             this.remove(item, autoDestroy);
4556             if(item.ownerCt !== this){
4557                 items.push(item);
4558             }
4559         }
4560         return items;
4561     },
4562
4563     /**
4564      * Examines this container's <code>{@link #items}</code> <b>property</b>
4565      * and gets a direct child component of this container.
4566      * @param {String/Number} comp This parameter may be any of the following:
4567      * <div><ul class="mdetail-params">
4568      * <li>a <b><code>String</code></b> : representing the <code>{@link Ext.Component#itemId itemId}</code>
4569      * or <code>{@link Ext.Component#id id}</code> of the child component </li>
4570      * <li>a <b><code>Number</code></b> : representing the position of the child component
4571      * within the <code>{@link #items}</code> <b>property</b></li>
4572      * </ul></div>
4573      * <p>For additional information see {@link Ext.util.MixedCollection#get}.
4574      * @return Ext.Component The component (if found).
4575      */
4576     getComponent : function(comp){
4577         if(Ext.isObject(comp)){
4578             comp = comp.getItemId();
4579         }
4580         return this.items.get(comp);
4581     },
4582
4583     // private
4584     lookupComponent : function(comp){
4585         if(Ext.isString(comp)){
4586             return Ext.ComponentMgr.get(comp);
4587         }else if(!comp.events){
4588             return this.createComponent(comp);
4589         }
4590         return comp;
4591     },
4592
4593     // private
4594     createComponent : function(config, defaultType){
4595         // add in ownerCt at creation time but then immediately
4596         // remove so that onBeforeAdd can handle it
4597         var c = config.render ? config : Ext.create(Ext.apply({
4598             ownerCt: this
4599         }, config), defaultType || this.defaultType);
4600         delete c.ownerCt;
4601         return c;
4602     },
4603
4604     /**
4605     * We can only lay out if there is a view area in which to layout.
4606     * display:none on the layout target, *or any of its parent elements* will mean it has no view area.
4607     */
4608
4609     // private
4610     canLayout : function() {
4611         var el = this.getVisibilityEl();
4612         return el && el.dom && !el.isStyle("display", "none");
4613     },
4614
4615     /**
4616      * Force this container's layout to be recalculated. A call to this function is required after adding a new component
4617      * to an already rendered container, or possibly after changing sizing/position properties of child components.
4618      * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto
4619      * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer)
4620      * @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden.
4621      * @return {Ext.Container} this
4622      */
4623
4624     doLayout : function(shallow, force){
4625         var rendered = this.rendered,
4626             forceLayout = force || this.forceLayout;
4627
4628         if(this.collapsed || !this.canLayout()){
4629             this.deferLayout = this.deferLayout || !shallow;
4630             if(!forceLayout){
4631                 return;
4632             }
4633             shallow = shallow && !this.deferLayout;
4634         } else {
4635             delete this.deferLayout;
4636         }
4637         if(rendered && this.layout){
4638             this.layout.layout();
4639         }
4640         if(shallow !== true && this.items){
4641             var cs = this.items.items;
4642             for(var i = 0, len = cs.length; i < len; i++){
4643                 var c = cs[i];
4644                 if(c.doLayout){
4645                     c.doLayout(false, forceLayout);
4646                 }
4647             }
4648         }
4649         if(rendered){
4650             this.onLayout(shallow, forceLayout);
4651         }
4652         // Initial layout completed
4653         this.hasLayout = true;
4654         delete this.forceLayout;
4655     },
4656
4657     onLayout : Ext.emptyFn,
4658
4659     // private
4660     shouldBufferLayout: function(){
4661         /*
4662          * Returns true if the container should buffer a layout.
4663          * This is true only if the container has previously been laid out
4664          * and has a parent container that is pending a layout.
4665          */
4666         var hl = this.hasLayout;
4667         if(this.ownerCt){
4668             // Only ever buffer if we've laid out the first time and we have one pending.
4669             return hl ? !this.hasLayoutPending() : false;
4670         }
4671         // Never buffer initial layout
4672         return hl;
4673     },
4674
4675     // private
4676     hasLayoutPending: function(){
4677         // Traverse hierarchy to see if any parent container has a pending layout.
4678         var pending = false;
4679         this.ownerCt.bubble(function(c){
4680             if(c.layoutPending){
4681                 pending = true;
4682                 return false;
4683             }
4684         });
4685         return pending;
4686     },
4687
4688     onShow : function(){
4689         // removes css classes that were added to hide
4690         Ext.Container.superclass.onShow.call(this);
4691         // If we were sized during the time we were hidden, layout.
4692         if(Ext.isDefined(this.deferLayout)){
4693             delete this.deferLayout;
4694             this.doLayout(true);
4695         }
4696     },
4697
4698     /**
4699      * Returns the layout currently in use by the container.  If the container does not currently have a layout
4700      * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout.
4701      * @return {ContainerLayout} layout The container's layout
4702      */
4703     getLayout : function(){
4704         if(!this.layout){
4705             var layout = new Ext.layout.ContainerLayout(this.layoutConfig);
4706             this.setLayout(layout);
4707         }
4708         return this.layout;
4709     },
4710
4711     // private
4712     beforeDestroy : function(){
4713         var c;
4714         if(this.items){
4715             while(c = this.items.first()){
4716                 this.doRemove(c, true);
4717             }
4718         }
4719         if(this.monitorResize){
4720             Ext.EventManager.removeResizeListener(this.doLayout, this);
4721         }
4722         Ext.destroy(this.layout);
4723         Ext.Container.superclass.beforeDestroy.call(this);
4724     },
4725
4726     /**
4727      * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of
4728      * function call will be the scope provided or the current component. The arguments to the function
4729      * will be the args provided or the current component. If the function returns false at any point,
4730      * the bubble is stopped.
4731      * @param {Function} fn The function to call
4732      * @param {Object} scope (optional) The scope of the function (defaults to current node)
4733      * @param {Array} args (optional) The args to call the function with (default to passing the current component)
4734      * @return {Ext.Container} this
4735      */
4736     bubble : function(fn, scope, args){
4737         var p = this;
4738         while(p){
4739             if(fn.apply(scope || p, args || [p]) === false){
4740                 break;
4741             }
4742             p = p.ownerCt;
4743         }
4744         return this;
4745     },
4746
4747     /**
4748      * Cascades down the component/container heirarchy from this component (called first), calling the specified function with
4749      * each component. The scope (<i>this</i>) of
4750      * function call will be the scope provided or the current component. The arguments to the function
4751      * will be the args provided or the current component. If the function returns false at any point,
4752      * the cascade is stopped on that branch.
4753      * @param {Function} fn The function to call
4754      * @param {Object} scope (optional) The scope of the function (defaults to current component)
4755      * @param {Array} args (optional) The args to call the function with (defaults to passing the current component)
4756      * @return {Ext.Container} this
4757      */
4758     cascade : function(fn, scope, args){
4759         if(fn.apply(scope || this, args || [this]) !== false){
4760             if(this.items){
4761                 var cs = this.items.items;
4762                 for(var i = 0, len = cs.length; i < len; i++){
4763                     if(cs[i].cascade){
4764                         cs[i].cascade(fn, scope, args);
4765                     }else{
4766                         fn.apply(scope || cs[i], args || [cs[i]]);
4767                     }
4768                 }
4769             }
4770         }
4771         return this;
4772     },
4773
4774     /**
4775      * Find a component under this container at any level by id
4776      * @param {String} id
4777      * @return Ext.Component
4778      */
4779     findById : function(id){
4780         var m, ct = this;
4781         this.cascade(function(c){
4782             if(ct != c && c.id === id){
4783                 m = c;
4784                 return false;
4785             }
4786         });
4787         return m || null;
4788     },
4789
4790     /**
4791      * Find a component under this container at any level by xtype or class
4792      * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
4793      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
4794      * the default), or true to check whether this Component is directly of the specified xtype.
4795      * @return {Array} Array of Ext.Components
4796      */
4797     findByType : function(xtype, shallow){
4798         return this.findBy(function(c){
4799             return c.isXType(xtype, shallow);
4800         });
4801     },
4802
4803     /**
4804      * Find a component under this container at any level by property
4805      * @param {String} prop
4806      * @param {String} value
4807      * @return {Array} Array of Ext.Components
4808      */
4809     find : function(prop, value){
4810         return this.findBy(function(c){
4811             return c[prop] === value;
4812         });
4813     },
4814
4815     /**
4816      * Find a component under this container at any level by a custom function. If the passed function returns
4817      * true, the component will be included in the results. The passed function is called with the arguments (component, this container).
4818      * @param {Function} fn The function to call
4819      * @param {Object} scope (optional)
4820      * @return {Array} Array of Ext.Components
4821      */
4822     findBy : function(fn, scope){
4823         var m = [], ct = this;
4824         this.cascade(function(c){
4825             if(ct != c && fn.call(scope || c, c, ct) === true){
4826                 m.push(c);
4827             }
4828         });
4829         return m;
4830     },
4831
4832     /**
4833      * Get a component contained by this container (alias for items.get(key))
4834      * @param {String/Number} key The index or id of the component
4835      * @return {Ext.Component} Ext.Component
4836      */
4837     get : function(key){
4838         return this.items.get(key);
4839     }
4840 });
4841
4842 Ext.Container.LAYOUTS = {};
4843 Ext.reg('container', Ext.Container);
4844 /**
4845  * @class Ext.layout.ContainerLayout
4846  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
4847  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
4848  */
4849 Ext.layout.ContainerLayout = Ext.extend(Object, {
4850     /**
4851      * @cfg {String} extraCls
4852      * <p>An optional extra CSS class that will be added to the container. This can be useful for adding
4853      * customized styles to the container or any of its children using standard CSS rules. See
4854      * {@link Ext.Component}.{@link Ext.Component#ctCls ctCls} also.</p>
4855      * <p><b>Note</b>: <tt>extraCls</tt> defaults to <tt>''</tt> except for the following classes
4856      * which assign a value by default:
4857      * <div class="mdetail-params"><ul>
4858      * <li>{@link Ext.layout.AbsoluteLayout Absolute Layout} : <tt>'x-abs-layout-item'</tt></li>
4859      * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-item'</tt></li>
4860      * <li>{@link Ext.layout.ColumnLayout Column Layout} : <tt>'x-column'</tt></li>
4861      * </ul></div>
4862      * To configure the above Classes with an extra CSS class append to the default.  For example,
4863      * for ColumnLayout:<pre><code>
4864      * extraCls: 'x-column custom-class'
4865      * </code></pre>
4866      * </p>
4867      */
4868     /**
4869      * @cfg {Boolean} renderHidden
4870      * True to hide each contained item on render (defaults to false).
4871      */
4872
4873     /**
4874      * A reference to the {@link Ext.Component} that is active.  For example, <pre><code>
4875      * if(myPanel.layout.activeItem.id == 'item-1') { ... }
4876      * </code></pre>
4877      * <tt>activeItem</tt> only applies to layout styles that can display items one at a time
4878      * (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout}
4879      * and {@link Ext.layout.FitLayout}).  Read-only.  Related to {@link Ext.Container#activeItem}.
4880      * @type {Ext.Component}
4881      * @property activeItem
4882      */
4883
4884     // private
4885     monitorResize:false,
4886     // private
4887     activeItem : null,
4888
4889     constructor : function(config){
4890         this.id = Ext.id(null, 'ext-layout-');
4891         Ext.apply(this, config);
4892     },
4893
4894     type: 'container',
4895
4896     /* Workaround for how IE measures autoWidth elements.  It prefers bottom-up measurements
4897       whereas other browser prefer top-down.  We will hide all target child elements before we measure and
4898       put them back to get an accurate measurement.
4899     */
4900     IEMeasureHack : function(target, viewFlag) {
4901         var tChildren = target.dom.childNodes, tLen = tChildren.length, c, d = [], e, i, ret;
4902         for (i = 0 ; i < tLen ; i++) {
4903             c = tChildren[i];
4904             e = Ext.get(c);
4905             if (e) {
4906                 d[i] = e.getStyle('display');
4907                 e.setStyle({display: 'none'});
4908             }
4909         }
4910         ret = target ? target.getViewSize(viewFlag) : {};
4911         for (i = 0 ; i < tLen ; i++) {
4912             c = tChildren[i];
4913             e = Ext.get(c);
4914             if (e) {
4915                 e.setStyle({display: d[i]});
4916             }
4917         }
4918         return ret;
4919     },
4920
4921     // Placeholder for the derived layouts
4922     getLayoutTargetSize : Ext.EmptyFn,
4923
4924     // private
4925     layout : function(){
4926         var ct = this.container, target = ct.getLayoutTarget();
4927         if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
4928             target.addClass(this.targetCls);
4929         }
4930         this.onLayout(ct, target);
4931         ct.fireEvent('afterlayout', ct, this);
4932     },
4933
4934     // private
4935     onLayout : function(ct, target){
4936         this.renderAll(ct, target);
4937     },
4938
4939     // private
4940     isValidParent : function(c, target){
4941         return target && c.getPositionEl().dom.parentNode == (target.dom || target);
4942     },
4943
4944     // private
4945     renderAll : function(ct, target){
4946         var items = ct.items.items, i, c, len = items.length;
4947         for(i = 0; i < len; i++) {
4948             c = items[i];
4949             if(c && (!c.rendered || !this.isValidParent(c, target))){
4950                 this.renderItem(c, i, target);
4951             }
4952         }
4953     },
4954
4955     // private
4956     renderItem : function(c, position, target){
4957         if(c){
4958             if(!c.rendered){
4959                 c.render(target, position);
4960                 this.configureItem(c, position);
4961             }else if(!this.isValidParent(c, target)){
4962                 if(Ext.isNumber(position)){
4963                     position = target.dom.childNodes[position];
4964                 }
4965                 target.dom.insertBefore(c.getPositionEl().dom, position || null);
4966                 c.container = target;
4967                 this.configureItem(c, position);
4968             }
4969         }
4970     },
4971
4972     // private.
4973     // Get all rendered items to lay out.
4974     getRenderedItems: function(ct){
4975         var t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = [];
4976         for (i = 0; i < len; i++) {
4977             if((c = cti[i]).rendered && this.isValidParent(c, t)){
4978                 items.push(c);
4979             }
4980         };
4981         return items;
4982     },
4983
4984     // private
4985     configureItem: function(c, position){
4986         if(this.extraCls){
4987             var t = c.getPositionEl ? c.getPositionEl() : c;
4988             t.addClass(this.extraCls);
4989         }
4990         // If we are forcing a layout, do so *before* we hide so elements have height/width
4991         if(c.doLayout && this.forceLayout){
4992             c.doLayout();
4993         }
4994         if (this.renderHidden && c != this.activeItem) {
4995             c.hide();
4996         }
4997     },
4998
4999     onRemove: function(c){
5000          if(this.activeItem == c){
5001             delete this.activeItem;
5002          }
5003          if(c.rendered && this.extraCls){
5004             var t = c.getPositionEl ? c.getPositionEl() : c;
5005             t.removeClass(this.extraCls);
5006         }
5007     },
5008
5009     afterRemove: function(c){
5010         if(c.removeRestore){
5011             c.removeMode = 'container';
5012             delete c.removeRestore;
5013         }
5014     },
5015
5016     // private
5017     onResize: function(){
5018         var ct = this.container,
5019             b;
5020         if(ct.collapsed){
5021             return;
5022         }
5023         if(b = ct.bufferResize){
5024             // Only allow if we should buffer the layout
5025             if(ct.shouldBufferLayout()){
5026                 if(!this.resizeTask){
5027                     this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
5028                     this.resizeBuffer = Ext.isNumber(b) ? b : 50;
5029                 }
5030                 ct.layoutPending = true;
5031                 this.resizeTask.delay(this.resizeBuffer);
5032             }
5033         }else{
5034             this.runLayout();
5035         }
5036     },
5037
5038     runLayout: function(){
5039         var ct = this.container;
5040         // AutoLayout is known to require the recursive doLayout call, others need this currently (BorderLayout for example)
5041         // but shouldn't.  A more extensive review will take place for 3.2 which requires a ContainerMgr with hierarchy lookups.
5042         //this.layout();
5043         //ct.onLayout();
5044         ct.doLayout();
5045         delete ct.layoutPending;
5046     },
5047
5048     // private
5049     setContainer : function(ct){
5050         if (!Ext.LayoutManager) {
5051             Ext.LayoutManager = {};
5052         }
5053
5054         /* This monitorResize flag will be renamed soon as to avoid confusion
5055         * with the Container version which hooks onWindowResize to doLayout
5056         *
5057         * monitorResize flag in this context attaches the resize event between
5058         * a container and it's layout
5059         */
5060
5061         if(this.monitorResize && ct != this.container){
5062             var old = this.container;
5063             if(old){
5064                 old.un(old.resizeEvent, this.onResize, this);
5065             }
5066             if(ct){
5067                 ct.on(ct.resizeEvent, this.onResize, this);
5068             }
5069         }
5070         this.container = ct;
5071     },
5072
5073     // private
5074     parseMargins : function(v){
5075         if(Ext.isNumber(v)){
5076             v = v.toString();
5077         }
5078         var ms = v.split(' ');
5079         var len = ms.length;
5080         if(len == 1){
5081             ms[1] = ms[2] = ms[3] = ms[0];
5082         } else if(len == 2){
5083             ms[2] = ms[0];
5084             ms[3] = ms[1];
5085         } else if(len == 3){
5086             ms[3] = ms[1];
5087         }
5088         return {
5089             top:parseInt(ms[0], 10) || 0,
5090             right:parseInt(ms[1], 10) || 0,
5091             bottom:parseInt(ms[2], 10) || 0,
5092             left:parseInt(ms[3], 10) || 0
5093         };
5094     },
5095
5096     /**
5097      * The {@link Ext.Template Ext.Template} used by Field rendering layout classes (such as
5098      * {@link Ext.layout.FormLayout}) to create the DOM structure of a fully wrapped,
5099      * labeled and styled form Field. A default Template is supplied, but this may be
5100      * overriden to create custom field structures. The template processes values returned from
5101      * {@link Ext.layout.FormLayout#getTemplateArgs}.
5102      * @property fieldTpl
5103      * @type Ext.Template
5104      */
5105     fieldTpl: (function() {
5106         var t = new Ext.Template(
5107             '<div class="x-form-item {itemCls}" tabIndex="-1">',
5108                 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
5109                 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
5110                 '</div><div class="{clearCls}"></div>',
5111             '</div>'
5112         );
5113         t.disableFormats = true;
5114         return t.compile();
5115     })(),
5116
5117     /*
5118      * Destroys this layout. This is a template method that is empty by default, but should be implemented
5119      * by subclasses that require explicit destruction to purge event handlers or remove DOM nodes.
5120      * @protected
5121      */
5122     destroy : function(){
5123         if(!Ext.isEmpty(this.targetCls)){
5124             var target = this.container.getLayoutTarget();
5125             if(target){
5126                 target.removeClass(this.targetCls);
5127             }
5128         }
5129     }
5130 });/**
5131  * @class Ext.layout.AutoLayout
5132  * <p>The AutoLayout is the default layout manager delegated by {@link Ext.Container} to
5133  * render any child Components when no <tt>{@link Ext.Container#layout layout}</tt> is configured into
5134  * a {@link Ext.Container Container}. ContainerLayout provides the basic foundation for all other layout
5135  * classes in Ext. It simply renders all child Components into the Container, performing no sizing or
5136  * positioning services. To utilize a layout that provides sizing and positioning of child Components,
5137  * specify an appropriate <tt>{@link Ext.Container#layout layout}</tt>.</p>
5138  */
5139 Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
5140     runLayout: function(){
5141         var ct = this.container;
5142         ct.doLayout();
5143         delete ct.layoutPending;
5144     }
5145 });
5146
5147 Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
5148 /**\r
5149  * @class Ext.layout.FitLayout\r
5150  * @extends Ext.layout.ContainerLayout\r
5151  * <p>This is a base class for layouts that contain <b>a single item</b> that automatically expands to fill the layout's\r
5152  * container.  This class is intended to be extended or created via the <tt>layout:'fit'</tt> {@link Ext.Container#layout}\r
5153  * config, and should generally not need to be created directly via the new keyword.</p>\r
5154  * <p>FitLayout does not have any direct config options (other than inherited ones).  To fit a panel to a container\r
5155  * using FitLayout, simply set layout:'fit' on the container and add a single panel to it.  If the container has\r
5156  * multiple panels, only the first one will be displayed.  Example usage:</p>\r
5157  * <pre><code>\r
5158 var p = new Ext.Panel({\r
5159     title: 'Fit Layout',\r
5160     layout:'fit',\r
5161     items: {\r
5162         title: 'Inner Panel',\r
5163         html: '&lt;p&gt;This is the inner panel content&lt;/p&gt;',\r
5164         border: false\r
5165     }\r
5166 });\r
5167 </code></pre>\r
5168  */\r
5169 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
5170     // private\r
5171     monitorResize:true,\r
5172 \r
5173     type: 'fit',\r
5174 \r
5175     getLayoutTargetSize : function() {\r
5176         var target = this.container.getLayoutTarget();\r
5177         if (!target) {\r
5178             return {};\r
5179         }\r
5180         // Style Sized (scrollbars not included)\r
5181         return target.getStyleSize();\r
5182     },\r
5183 \r
5184     // private\r
5185     onLayout : function(ct, target){\r
5186         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);\r
5187         if(!ct.collapsed){\r
5188             this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());\r
5189         }\r
5190     },\r
5191 \r
5192     // private\r
5193     setItemSize : function(item, size){\r
5194         if(item && size.height > 0){ // display none?\r
5195             item.setSize(size);\r
5196         }\r
5197     }\r
5198 });\r
5199 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;/**\r
5200  * @class Ext.layout.CardLayout\r
5201  * @extends Ext.layout.FitLayout\r
5202  * <p>This layout manages multiple child Components, each fitted to the Container, where only a single child Component can be\r
5203  * visible at any given time.  This layout style is most commonly used for wizards, tab implementations, etc.\r
5204  * This class is intended to be extended or created via the layout:'card' {@link Ext.Container#layout} config,\r
5205  * and should generally not need to be created directly via the new keyword.</p>\r
5206  * <p>The CardLayout's focal method is {@link #setActiveItem}.  Since only one panel is displayed at a time,\r
5207  * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of\r
5208  * the next panel to display.  The layout itself does not provide a user interface for handling this navigation,\r
5209  * so that functionality must be provided by the developer.</p>\r
5210  * <p>In the following example, a simplistic wizard setup is demonstrated.  A button bar is added\r
5211  * to the footer of the containing panel to provide navigation buttons.  The buttons will be handled by a\r
5212  * common navigation routine -- for this example, the implementation of that routine has been ommitted since\r
5213  * it can be any type of custom logic.  Note that other uses of a CardLayout (like a tab control) would require a\r
5214  * completely different implementation.  For serious implementations, a better approach would be to extend\r
5215  * CardLayout to provide the custom functionality needed.  Example usage:</p>\r
5216  * <pre><code>\r
5217 var navHandler = function(direction){\r
5218     // This routine could contain business logic required to manage the navigation steps.\r
5219     // It would call setActiveItem as needed, manage navigation button state, handle any\r
5220     // branching logic that might be required, handle alternate actions like cancellation\r
5221     // or finalization, etc.  A complete wizard implementation could get pretty\r
5222     // sophisticated depending on the complexity required, and should probably be\r
5223     // done as a subclass of CardLayout in a real-world implementation.\r
5224 };\r
5225 \r
5226 var card = new Ext.Panel({\r
5227     title: 'Example Wizard',\r
5228     layout:'card',\r
5229     activeItem: 0, // make sure the active item is set on the container config!\r
5230     bodyStyle: 'padding:15px',\r
5231     defaults: {\r
5232         // applied to each contained panel\r
5233         border:false\r
5234     },\r
5235     // just an example of one possible navigation scheme, using buttons\r
5236     bbar: [\r
5237         {\r
5238             id: 'move-prev',\r
5239             text: 'Back',\r
5240             handler: navHandler.createDelegate(this, [-1]),\r
5241             disabled: true\r
5242         },\r
5243         '->', // greedy spacer so that the buttons are aligned to each side\r
5244         {\r
5245             id: 'move-next',\r
5246             text: 'Next',\r
5247             handler: navHandler.createDelegate(this, [1])\r
5248         }\r
5249     ],\r
5250     // the panels (or "cards") within the layout\r
5251     items: [{\r
5252         id: 'card-0',\r
5253         html: '&lt;h1&gt;Welcome to the Wizard!&lt;/h1&gt;&lt;p&gt;Step 1 of 3&lt;/p&gt;'\r
5254     },{\r
5255         id: 'card-1',\r
5256         html: '&lt;p&gt;Step 2 of 3&lt;/p&gt;'\r
5257     },{\r
5258         id: 'card-2',\r
5259         html: '&lt;h1&gt;Congratulations!&lt;/h1&gt;&lt;p&gt;Step 3 of 3 - Complete&lt;/p&gt;'\r
5260     }]\r
5261 });\r
5262 </code></pre>\r
5263  */\r
5264 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {\r
5265     /**\r
5266      * @cfg {Boolean} deferredRender\r
5267      * True to render each contained item at the time it becomes active, false to render all contained items\r
5268      * as soon as the layout is rendered (defaults to false).  If there is a significant amount of content or\r
5269      * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to\r
5270      * true might improve performance.\r
5271      */\r
5272     deferredRender : false,\r
5273 \r
5274     /**\r
5275      * @cfg {Boolean} layoutOnCardChange\r
5276      * True to force a layout of the active item when the active card is changed. Defaults to false.\r
5277      */\r
5278     layoutOnCardChange : false,\r
5279 \r
5280     /**\r
5281      * @cfg {Boolean} renderHidden @hide\r
5282      */\r
5283     // private\r
5284     renderHidden : true,\r
5285 \r
5286     type: 'card',\r
5287 \r
5288     constructor: function(config){\r
5289         Ext.layout.CardLayout.superclass.constructor.call(this, config);\r
5290     },\r
5291 \r
5292     /**\r
5293      * Sets the active (visible) item in the layout.\r
5294      * @param {String/Number} item The string component id or numeric index of the item to activate\r
5295      */\r
5296     setActiveItem : function(item){\r
5297         var ai = this.activeItem,\r
5298             ct = this.container;\r
5299         item = ct.getComponent(item);\r
5300 \r
5301         // Is this a valid, different card?\r
5302         if(item && ai != item){\r
5303 \r
5304             // Changing cards, hide the current one\r
5305             if(ai){\r
5306                 ai.hide();\r
5307                 if (ai.hidden !== true) {\r
5308                     return false;\r
5309                 }\r
5310                 ai.fireEvent('deactivate', ai);\r
5311             }\r
5312             // Change activeItem reference\r
5313             this.activeItem = item;\r
5314 \r
5315             // The container is about to get a recursive layout, remove any deferLayout reference\r
5316             // because it will trigger a redundant layout.\r
5317             delete item.deferLayout;\r
5318 \r
5319             // Show the new component\r
5320             item.show();\r
5321 \r
5322             this.layout();\r
5323 \r
5324             if(item.doLayout){\r
5325                 item.doLayout();\r
5326             }\r
5327             item.fireEvent('activate', item);\r
5328         }\r
5329     },\r
5330 \r
5331     // private\r
5332     renderAll : function(ct, target){\r
5333         if(this.deferredRender){\r
5334             this.renderItem(this.activeItem, undefined, target);\r
5335         }else{\r
5336             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);\r
5337         }\r
5338     }\r
5339 });\r
5340 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;/**
5341  * @class Ext.layout.AnchorLayout
5342  * @extends Ext.layout.ContainerLayout
5343  * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.
5344  * If the container is resized, all anchored items are automatically rerendered according to their
5345  * <b><tt>{@link #anchor}</tt></b> rules.</p>
5346  * <p>This class is intended to be extended or created via the layout:'anchor' {@link Ext.Container#layout}
5347  * config, and should generally not need to be created directly via the new keyword.</p>
5348  * <p>AnchorLayout does not have any direct config options (other than inherited ones). By default,
5349  * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the
5350  * container using the AnchorLayout can supply an anchoring-specific config property of <b>anchorSize</b>.
5351  * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating
5352  * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring
5353  * logic if necessary.  For example:</p>
5354  * <pre><code>
5355 var viewport = new Ext.Viewport({
5356     layout:'anchor',
5357     anchorSize: {width:800, height:600},
5358     items:[{
5359         title:'Item 1',
5360         html:'Content 1',
5361         width:800,
5362         anchor:'right 20%'
5363     },{
5364         title:'Item 2',
5365         html:'Content 2',
5366         width:300,
5367         anchor:'50% 30%'
5368     },{
5369         title:'Item 3',
5370         html:'Content 3',
5371         width:600,
5372         anchor:'-100 50%'
5373     }]
5374 });
5375  * </code></pre>
5376  */
5377 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
5378     /**
5379      * @cfg {String} anchor
5380      * <p>This configuation option is to be applied to <b>child <tt>items</tt></b> of a container managed by
5381      * this layout (ie. configured with <tt>layout:'anchor'</tt>).</p><br/>
5382      *
5383      * <p>This value is what tells the layout how an item should be anchored to the container. <tt>items</tt>
5384      * added to an AnchorLayout accept an anchoring-specific config property of <b>anchor</b> which is a string
5385      * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').
5386      * The following types of anchor values are supported:<div class="mdetail-params"><ul>
5387      *
5388      * <li><b>Percentage</b> : Any value between 1 and 100, expressed as a percentage.<div class="sub-desc">
5389      * The first anchor is the percentage width that the item should take up within the container, and the
5390      * second is the percentage height.  For example:<pre><code>
5391 // two values specified
5392 anchor: '100% 50%' // render item complete width of the container and
5393                    // 1/2 height of the container
5394 // one value specified
5395 anchor: '100%'     // the width value; the height will default to auto
5396      * </code></pre></div></li>
5397      *
5398      * <li><b>Offsets</b> : Any positive or negative integer value.<div class="sub-desc">
5399      * This is a raw adjustment where the first anchor is the offset from the right edge of the container,
5400      * and the second is the offset from the bottom edge. For example:<pre><code>
5401 // two values specified
5402 anchor: '-50 -100' // render item the complete width of the container
5403                    // minus 50 pixels and
5404                    // the complete height minus 100 pixels.
5405 // one value specified
5406 anchor: '-50'      // anchor value is assumed to be the right offset value
5407                    // bottom offset will default to 0
5408      * </code></pre></div></li>
5409      *
5410      * <li><b>Sides</b> : Valid values are <tt>'right'</tt> (or <tt>'r'</tt>) and <tt>'bottom'</tt>
5411      * (or <tt>'b'</tt>).<div class="sub-desc">
5412      * Either the container must have a fixed size or an anchorSize config value defined at render time in
5413      * order for these to have any effect.</div></li>
5414      *
5415      * <li><b>Mixed</b> : <div class="sub-desc">
5416      * Anchor values can also be mixed as needed.  For example, to render the width offset from the container
5417      * right edge by 50 pixels and 75% of the container's height use:
5418      * <pre><code>
5419 anchor: '-50 75%'
5420      * </code></pre></div></li>
5421      *
5422      *
5423      * </ul></div>
5424      */
5425
5426     // private
5427     monitorResize:true,
5428     type: 'anchor',
5429
5430     getLayoutTargetSize : function() {
5431         var target = this.container.getLayoutTarget();
5432         if (!target) {
5433             return {};
5434         }
5435         // Style Sized (scrollbars not included)
5436         return target.getStyleSize();
5437     },
5438
5439     // private
5440     onLayout : function(ct, target){
5441         Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
5442         var size = this.getLayoutTargetSize();
5443
5444         var w = size.width, h = size.height;
5445
5446         if(w < 20 && h < 20){
5447             return;
5448         }
5449
5450         // find the container anchoring size
5451         var aw, ah;
5452         if(ct.anchorSize){
5453             if(typeof ct.anchorSize == 'number'){
5454                 aw = ct.anchorSize;
5455             }else{
5456                 aw = ct.anchorSize.width;
5457                 ah = ct.anchorSize.height;
5458             }
5459         }else{
5460             aw = ct.initialConfig.width;
5461             ah = ct.initialConfig.height;
5462         }
5463
5464         var cs = this.getRenderedItems(ct), len = cs.length, i, c, a, cw, ch, el, vs;
5465         for(i = 0; i < len; i++){
5466             c = cs[i];
5467             el = c.getPositionEl();
5468             if(c.anchor){
5469                 a = c.anchorSpec;
5470                 if(!a){ // cache all anchor values
5471                     vs = c.anchor.split(' ');
5472                     c.anchorSpec = a = {
5473                         right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
5474                         bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
5475                     };
5476                 }
5477                 cw = a.right ? this.adjustWidthAnchor(a.right(w) - el.getMargins('lr'), c) : undefined;
5478                 ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h) - el.getMargins('tb'), c) : undefined;
5479
5480                 if(cw || ch){
5481                     c.setSize(cw || undefined, ch || undefined);
5482                 }
5483             }
5484         }
5485     },
5486
5487     // private
5488     parseAnchor : function(a, start, cstart){
5489         if(a && a != 'none'){
5490             var last;
5491             if(/^(r|right|b|bottom)$/i.test(a)){   // standard anchor
5492                 var diff = cstart - start;
5493                 return function(v){
5494                     if(v !== last){
5495                         last = v;
5496                         return v - diff;
5497                     }
5498                 }
5499             }else if(a.indexOf('%') != -1){
5500                 var ratio = parseFloat(a.replace('%', ''))*.01;   // percentage
5501                 return function(v){
5502                     if(v !== last){
5503                         last = v;
5504                         return Math.floor(v*ratio);
5505                     }
5506                 }
5507             }else{
5508                 a = parseInt(a, 10);
5509                 if(!isNaN(a)){                            // simple offset adjustment
5510                     return function(v){
5511                         if(v !== last){
5512                             last = v;
5513                             return v + a;
5514                         }
5515                     }
5516                 }
5517             }
5518         }
5519         return false;
5520     },
5521
5522     // private
5523     adjustWidthAnchor : function(value, comp){
5524         return value;
5525     },
5526
5527     // private
5528     adjustHeightAnchor : function(value, comp){
5529         return value;
5530     }
5531
5532     /**
5533      * @property activeItem
5534      * @hide
5535      */
5536 });
5537 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
5538 /**\r
5539  * @class Ext.layout.ColumnLayout\r
5540  * @extends Ext.layout.ContainerLayout\r
5541  * <p>This is the layout style of choice for creating structural layouts in a multi-column format where the width of\r
5542  * each column can be specified as a percentage or fixed width, but the height is allowed to vary based on the content.\r
5543  * This class is intended to be extended or created via the layout:'column' {@link Ext.Container#layout} config,\r
5544  * and should generally not need to be created directly via the new keyword.</p>\r
5545  * <p>ColumnLayout does not have any direct config options (other than inherited ones), but it does support a\r
5546  * specific config property of <b><tt>columnWidth</tt></b> that can be included in the config of any panel added to it.  The\r
5547  * layout will use the columnWidth (if present) or width of each panel during layout to determine how to size each panel.\r
5548  * If width or columnWidth is not specified for a given panel, its width will default to the panel's width (or auto).</p>\r
5549  * <p>The width property is always evaluated as pixels, and must be a number greater than or equal to 1.\r
5550  * The columnWidth property is always evaluated as a percentage, and must be a decimal value greater than 0 and\r
5551  * less than 1 (e.g., .25).</p>\r
5552  * <p>The basic rules for specifying column widths are pretty simple.  The logic makes two passes through the\r
5553  * set of contained panels.  During the first layout pass, all panels that either have a fixed width or none\r
5554  * specified (auto) are skipped, but their widths are subtracted from the overall container width.  During the second\r
5555  * pass, all panels with columnWidths are assigned pixel widths in proportion to their percentages based on\r
5556  * the total <b>remaining</b> container width.  In other words, percentage width panels are designed to fill the space\r
5557  * left over by all the fixed-width and/or auto-width panels.  Because of this, while you can specify any number of columns\r
5558  * with different percentages, the columnWidths must always add up to 1 (or 100%) when added together, otherwise your\r
5559  * layout may not render as expected.  Example usage:</p>\r
5560  * <pre><code>\r
5561 // All columns are percentages -- they must add up to 1\r
5562 var p = new Ext.Panel({\r
5563     title: 'Column Layout - Percentage Only',\r
5564     layout:'column',\r
5565     items: [{\r
5566         title: 'Column 1',\r
5567         columnWidth: .25\r
5568     },{\r
5569         title: 'Column 2',\r
5570         columnWidth: .6\r
5571     },{\r
5572         title: 'Column 3',\r
5573         columnWidth: .15\r
5574     }]\r
5575 });\r
5576 \r
5577 // Mix of width and columnWidth -- all columnWidth values must add up\r
5578 // to 1. The first column will take up exactly 120px, and the last two\r
5579 // columns will fill the remaining container width.\r
5580 var p = new Ext.Panel({\r
5581     title: 'Column Layout - Mixed',\r
5582     layout:'column',\r
5583     items: [{\r
5584         title: 'Column 1',\r
5585         width: 120\r
5586     },{\r
5587         title: 'Column 2',\r
5588         columnWidth: .8\r
5589     },{\r
5590         title: 'Column 3',\r
5591         columnWidth: .2\r
5592     }]\r
5593 });\r
5594 </code></pre>\r
5595  */\r
5596 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
5597     // private\r
5598     monitorResize:true,\r
5599 \r
5600     type: 'column',\r
5601 \r
5602     extraCls: 'x-column',\r
5603 \r
5604     scrollOffset : 0,\r
5605 \r
5606     // private\r
5607 \r
5608     targetCls: 'x-column-layout-ct',\r
5609 \r
5610     isValidParent : function(c, target){\r
5611         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;\r
5612     },\r
5613 \r
5614     getLayoutTargetSize : function() {\r
5615         var target = this.container.getLayoutTarget(), ret;\r
5616         if (target) {\r
5617             ret = target.getViewSize();\r
5618             ret.width -= target.getPadding('lr');\r
5619             ret.height -= target.getPadding('tb');\r
5620         }\r
5621         return ret;\r
5622     },\r
5623 \r
5624     renderAll : function(ct, target) {\r
5625         if(!this.innerCt){\r
5626             // the innerCt prevents wrapping and shuffling while\r
5627             // the container is resizing\r
5628             this.innerCt = target.createChild({cls:'x-column-inner'});\r
5629             this.innerCt.createChild({cls:'x-clear'});\r
5630         }\r
5631         Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);\r
5632     },\r
5633 \r
5634     // private\r
5635     onLayout : function(ct, target){\r
5636         var cs = ct.items.items, len = cs.length, c, i;\r
5637 \r
5638         this.renderAll(ct, target);\r
5639 \r
5640         var size = this.getLayoutTargetSize();\r
5641 \r
5642         if(size.width < 1 && size.height < 1){ // display none?\r
5643             return;\r
5644         }\r
5645 \r
5646         var w = size.width - this.scrollOffset,\r
5647             h = size.height,\r
5648             pw = w;\r
5649 \r
5650         this.innerCt.setWidth(w);\r
5651 \r
5652         // some columns can be percentages while others are fixed\r
5653         // so we need to make 2 passes\r
5654 \r
5655         for(i = 0; i < len; i++){\r
5656             c = cs[i];\r
5657             if(!c.columnWidth){\r
5658                 pw -= (c.getWidth() + c.getPositionEl().getMargins('lr'));\r
5659             }\r
5660         }\r
5661 \r
5662         pw = pw < 0 ? 0 : pw;\r
5663 \r
5664         for(i = 0; i < len; i++){\r
5665             c = cs[i];\r
5666             if(c.columnWidth){\r
5667                 c.setSize(Math.floor(c.columnWidth * pw) - c.getPositionEl().getMargins('lr'));\r
5668             }\r
5669         }\r
5670 \r
5671         // Browsers differ as to when they account for scrollbars.  We need to re-measure to see if the scrollbar\r
5672         // spaces were accounted for properly.  If not, re-layout.\r
5673         if (Ext.isIE) {\r
5674             if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {\r
5675                 var ts = this.getLayoutTargetSize();\r
5676                 if (ts.width != size.width){\r
5677                     this.adjustmentPass = true;\r
5678                     this.onLayout(ct, target);\r
5679                 }\r
5680             }\r
5681         }\r
5682         delete this.adjustmentPass;\r
5683     }\r
5684 \r
5685     /**\r
5686      * @property activeItem\r
5687      * @hide\r
5688      */\r
5689 });\r
5690 \r
5691 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;/**
5692  * @class Ext.layout.BorderLayout
5693  * @extends Ext.layout.ContainerLayout
5694  * <p>This is a multi-pane, application-oriented UI layout style that supports multiple
5695  * nested panels, automatic {@link Ext.layout.BorderLayout.Region#split split} bars between
5696  * {@link Ext.layout.BorderLayout.Region#BorderLayout.Region regions} and built-in
5697  * {@link Ext.layout.BorderLayout.Region#collapsible expanding and collapsing} of regions.</p>
5698  * <p>This class is intended to be extended or created via the <tt>layout:'border'</tt>
5699  * {@link Ext.Container#layout} config, and should generally not need to be created directly
5700  * via the new keyword.</p>
5701  * <p>BorderLayout does not have any direct config options (other than inherited ones).
5702  * All configuration options available for customizing the BorderLayout are at the
5703  * {@link Ext.layout.BorderLayout.Region} and {@link Ext.layout.BorderLayout.SplitRegion}
5704  * levels.</p>
5705  * <p>Example usage:</p>
5706  * <pre><code>
5707 var myBorderPanel = new Ext.Panel({
5708     {@link Ext.Component#renderTo renderTo}: document.body,
5709     {@link Ext.BoxComponent#width width}: 700,
5710     {@link Ext.BoxComponent#height height}: 500,
5711     {@link Ext.Panel#title title}: 'Border Layout',
5712     {@link Ext.Container#layout layout}: 'border',
5713     {@link Ext.Container#items items}: [{
5714         {@link Ext.Panel#title title}: 'South Region is resizable',
5715         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south',     // position for region
5716         {@link Ext.BoxComponent#height height}: 100,
5717         {@link Ext.layout.BorderLayout.Region#split split}: true,         // enable resizing
5718         {@link Ext.SplitBar#minSize minSize}: 75,         // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50}
5719         {@link Ext.SplitBar#maxSize maxSize}: 150,
5720         {@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5'
5721     },{
5722         // xtype: 'panel' implied by default
5723         {@link Ext.Panel#title title}: 'West Region is collapsible',
5724         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}:'west',
5725         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 0 0 5',
5726         {@link Ext.BoxComponent#width width}: 200,
5727         {@link Ext.layout.BorderLayout.Region#collapsible collapsible}: true,   // make collapsible
5728         {@link Ext.layout.BorderLayout.Region#cmargins cmargins}: '5 5 0 5', // adjust top margin when collapsed
5729         {@link Ext.Component#id id}: 'west-region-container',
5730         {@link Ext.Container#layout layout}: 'fit',
5731         {@link Ext.Panel#unstyled unstyled}: true
5732     },{
5733         {@link Ext.Panel#title title}: 'Center Region',
5734         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'center',     // center region is required, no width/height specified
5735         {@link Ext.Component#xtype xtype}: 'container',
5736         {@link Ext.Container#layout layout}: 'fit',
5737         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 5 0 0'
5738     }]
5739 });
5740 </code></pre>
5741  * <p><b><u>Notes</u></b>:</p><div class="mdetail-params"><ul>
5742  * <li>Any container using the BorderLayout <b>must</b> have a child item with <tt>region:'center'</tt>.
5743  * The child item in the center region will always be resized to fill the remaining space not used by
5744  * the other regions in the layout.</li>
5745  * <li>Any child items with a region of <tt>west</tt> or <tt>east</tt> must have <tt>width</tt> defined
5746  * (an integer representing the number of pixels that the region should take up).</li>
5747  * <li>Any child items with a region of <tt>north</tt> or <tt>south</tt> must have <tt>height</tt> defined.</li>
5748  * <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
5749  * Components within a BorderLayout, have them wrapped by an additional Container which is directly
5750  * managed by the BorderLayout.  If the region is to be collapsible, the Container used directly
5751  * by the BorderLayout manager should be a Panel.  In the following example a Container (an Ext.Panel)
5752  * is added to the west region:
5753  * <div style="margin-left:16px"><pre><code>
5754 wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container');
5755 wrc.{@link Ext.Panel#removeAll removeAll}();
5756 wrc.{@link Ext.Container#add add}({
5757     title: 'Added Panel',
5758     html: 'Some content'
5759 });
5760 wrc.{@link Ext.Container#doLayout doLayout}();
5761  * </code></pre></div>
5762  * </li>
5763  * <li> To reference a {@link Ext.layout.BorderLayout.Region Region}:
5764  * <div style="margin-left:16px"><pre><code>
5765 wr = myBorderPanel.layout.west;
5766  * </code></pre></div>
5767  * </li>
5768  * </ul></div>
5769  */
5770 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
5771     // private
5772     monitorResize:true,
5773     // private
5774     rendered : false,
5775
5776     type: 'border',
5777
5778     targetCls: 'x-border-layout-ct',
5779
5780     getLayoutTargetSize : function() {
5781         var target = this.container.getLayoutTarget();
5782         return target ? target.getViewSize() : {};
5783     },
5784
5785     // private
5786     onLayout : function(ct, target){
5787         var collapsed, i, c, pos, items = ct.items.items, len = items.length;
5788         if(!this.rendered){
5789             collapsed = [];
5790             for(i = 0; i < len; i++) {
5791                 c = items[i];
5792                 pos = c.region;
5793                 if(c.collapsed){
5794                     collapsed.push(c);
5795                 }
5796                 c.collapsed = false;
5797                 if(!c.rendered){
5798                     c.render(target, i);
5799                     c.getPositionEl().addClass('x-border-panel');
5800                 }
5801                 this[pos] = pos != 'center' && c.split ?
5802                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
5803                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
5804                 this[pos].render(target, c);
5805             }
5806             this.rendered = true;
5807         }
5808
5809         var size = this.getLayoutTargetSize();
5810         if(size.width < 20 || size.height < 20){ // display none?
5811             if(collapsed){
5812                 this.restoreCollapsed = collapsed;
5813             }
5814             return;
5815         }else if(this.restoreCollapsed){
5816             collapsed = this.restoreCollapsed;
5817             delete this.restoreCollapsed;
5818         }
5819
5820         var w = size.width, h = size.height,
5821             centerW = w, centerH = h, centerY = 0, centerX = 0,
5822             n = this.north, s = this.south, west = this.west, e = this.east, c = this.center,
5823             b, m, totalWidth, totalHeight;
5824         if(!c && Ext.layout.BorderLayout.WARN !== false){
5825             throw 'No center region defined in BorderLayout ' + ct.id;
5826         }
5827
5828         if(n && n.isVisible()){
5829             b = n.getSize();
5830             m = n.getMargins();
5831             b.width = w - (m.left+m.right);
5832             b.x = m.left;
5833             b.y = m.top;
5834             centerY = b.height + b.y + m.bottom;
5835             centerH -= centerY;
5836             n.applyLayout(b);
5837         }
5838         if(s && s.isVisible()){
5839             b = s.getSize();
5840             m = s.getMargins();
5841             b.width = w - (m.left+m.right);
5842             b.x = m.left;
5843             totalHeight = (b.height + m.top + m.bottom);
5844             b.y = h - totalHeight + m.top;
5845             centerH -= totalHeight;
5846             s.applyLayout(b);
5847         }
5848         if(west && west.isVisible()){
5849             b = west.getSize();
5850             m = west.getMargins();
5851             b.height = centerH - (m.top+m.bottom);
5852             b.x = m.left;
5853             b.y = centerY + m.top;
5854             totalWidth = (b.width + m.left + m.right);
5855             centerX += totalWidth;
5856             centerW -= totalWidth;
5857             west.applyLayout(b);
5858         }
5859         if(e && e.isVisible()){
5860             b = e.getSize();
5861             m = e.getMargins();
5862             b.height = centerH - (m.top+m.bottom);
5863             totalWidth = (b.width + m.left + m.right);
5864             b.x = w - totalWidth + m.left;
5865             b.y = centerY + m.top;
5866             centerW -= totalWidth;
5867             e.applyLayout(b);
5868         }
5869         if(c){
5870             m = c.getMargins();
5871             var centerBox = {
5872                 x: centerX + m.left,
5873                 y: centerY + m.top,
5874                 width: centerW - (m.left+m.right),
5875                 height: centerH - (m.top+m.bottom)
5876             };
5877             c.applyLayout(centerBox);
5878         }
5879         if(collapsed){
5880             for(i = 0, len = collapsed.length; i < len; i++){
5881                 collapsed[i].collapse(false);
5882             }
5883         }
5884         if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue
5885             target.repaint();
5886         }
5887         // Putting a border layout into an overflowed container is NOT correct and will make a second layout pass necessary.
5888         if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
5889             var ts = this.getLayoutTargetSize();
5890             if (ts.width != size.width || ts.height != size.height){
5891                 this.adjustmentPass = true;
5892                 this.onLayout(ct, target);
5893             }
5894         }
5895         delete this.adjustmentPass;
5896     },
5897
5898     destroy: function() {
5899         var r = ['north', 'south', 'east', 'west'], i, region;
5900         for (i = 0; i < r.length; i++) {
5901             region = this[r[i]];
5902             if(region){
5903                 if(region.destroy){
5904                     region.destroy();
5905                 }else if (region.split){
5906                     region.split.destroy(true);
5907                 }
5908             }
5909         }
5910         Ext.layout.BorderLayout.superclass.destroy.call(this);
5911     }
5912
5913     /**
5914      * @property activeItem
5915      * @hide
5916      */
5917 });
5918
5919 /**
5920  * @class Ext.layout.BorderLayout.Region
5921  * <p>This is a region of a {@link Ext.layout.BorderLayout BorderLayout} that acts as a subcontainer
5922  * within the layout.  Each region has its own {@link Ext.layout.ContainerLayout layout} that is
5923  * independent of other regions and the containing BorderLayout, and can be any of the
5924  * {@link Ext.layout.ContainerLayout valid Ext layout types}.</p>
5925  * <p>Region size is managed automatically and cannot be changed by the user -- for
5926  * {@link #split resizable regions}, see {@link Ext.layout.BorderLayout.SplitRegion}.</p>
5927  * @constructor
5928  * Create a new Region.
5929  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
5930  * @param {Object} config The configuration options
5931  * @param {String} position The region position.  Valid values are: <tt>north</tt>, <tt>south</tt>,
5932  * <tt>east</tt>, <tt>west</tt> and <tt>center</tt>.  Every {@link Ext.layout.BorderLayout BorderLayout}
5933  * <b>must have a center region</b> for the primary content -- all other regions are optional.
5934  */
5935 Ext.layout.BorderLayout.Region = function(layout, config, pos){
5936     Ext.apply(this, config);
5937     this.layout = layout;
5938     this.position = pos;
5939     this.state = {};
5940     if(typeof this.margins == 'string'){
5941         this.margins = this.layout.parseMargins(this.margins);
5942     }
5943     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
5944     if(this.collapsible){
5945         if(typeof this.cmargins == 'string'){
5946             this.cmargins = this.layout.parseMargins(this.cmargins);
5947         }
5948         if(this.collapseMode == 'mini' && !this.cmargins){
5949             this.cmargins = {left:0,top:0,right:0,bottom:0};
5950         }else{
5951             this.cmargins = Ext.applyIf(this.cmargins || {},
5952                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
5953         }
5954     }
5955 };
5956
5957 Ext.layout.BorderLayout.Region.prototype = {
5958     /**
5959      * @cfg {Boolean} animFloat
5960      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
5961      * panel that will close again once the user mouses out of that panel (or clicks out if
5962      * <tt>{@link #autoHide} = false</tt>).  Setting <tt>{@link #animFloat} = false</tt> will
5963      * prevent the open and close of these floated panels from being animated (defaults to <tt>true</tt>).
5964      */
5965     /**
5966      * @cfg {Boolean} autoHide
5967      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
5968      * panel.  If <tt>autoHide = true</tt>, the panel will automatically hide after the user mouses
5969      * out of the panel.  If <tt>autoHide = false</tt>, the panel will continue to display until the
5970      * user clicks outside of the panel (defaults to <tt>true</tt>).
5971      */
5972     /**
5973      * @cfg {String} collapseMode
5974      * <tt>collapseMode</tt> supports two configuration values:<div class="mdetail-params"><ul>
5975      * <li><b><tt>undefined</tt></b> (default)<div class="sub-desc">By default, {@link #collapsible}
5976      * regions are collapsed by clicking the expand/collapse tool button that renders into the region's
5977      * title bar.</div></li>
5978      * <li><b><tt>'mini'</tt></b><div class="sub-desc">Optionally, when <tt>collapseMode</tt> is set to
5979      * <tt>'mini'</tt> the region's split bar will also display a small collapse button in the center of
5980      * the bar. In <tt>'mini'</tt> mode the region will collapse to a thinner bar than in normal mode.
5981      * </div></li>
5982      * </ul></div></p>
5983      * <p><b>Note</b>: if a collapsible region does not have a title bar, then set <tt>collapseMode =
5984      * 'mini'</tt> and <tt>{@link #split} = true</tt> in order for the region to be {@link #collapsible}
5985      * by the user as the expand/collapse tool button (that would go in the title bar) will not be rendered.</p>
5986      * <p>See also <tt>{@link #cmargins}</tt>.</p>
5987      */
5988     /**
5989      * @cfg {Object} margins
5990      * An object containing margins to apply to the region when in the expanded state in the
5991      * format:<pre><code>
5992 {
5993     top: (top margin),
5994     right: (right margin),
5995     bottom: (bottom margin),
5996     left: (left margin)
5997 }</code></pre>
5998      * <p>May also be a string containing space-separated, numeric margin values. The order of the
5999      * sides associated with each value matches the way CSS processes margin values:</p>
6000      * <p><div class="mdetail-params"><ul>
6001      * <li>If there is only one value, it applies to all sides.</li>
6002      * <li>If there are two values, the top and bottom borders are set to the first value and the
6003      * right and left are set to the second.</li>
6004      * <li>If there are three values, the top is set to the first value, the left and right are set
6005      * to the second, and the bottom is set to the third.</li>
6006      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
6007      * </ul></div></p>
6008      * <p>Defaults to:</p><pre><code>
6009      * {top:0, right:0, bottom:0, left:0}
6010      * </code></pre>
6011      */
6012     /**
6013      * @cfg {Object} cmargins
6014      * An object containing margins to apply to the region when in the collapsed state in the
6015      * format:<pre><code>
6016 {
6017     top: (top margin),
6018     right: (right margin),
6019     bottom: (bottom margin),
6020     left: (left margin)
6021 }</code></pre>
6022      * <p>May also be a string containing space-separated, numeric margin values. The order of the
6023      * sides associated with each value matches the way CSS processes margin values.</p>
6024      * <p><ul>
6025      * <li>If there is only one value, it applies to all sides.</li>
6026      * <li>If there are two values, the top and bottom borders are set to the first value and the
6027      * right and left are set to the second.</li>
6028      * <li>If there are three values, the top is set to the first value, the left and right are set
6029      * to the second, and the bottom is set to the third.</li>
6030      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
6031      * </ul></p>
6032      */
6033     /**
6034      * @cfg {Boolean} collapsible
6035      * <p><tt>true</tt> to allow the user to collapse this region (defaults to <tt>false</tt>).  If
6036      * <tt>true</tt>, an expand/collapse tool button will automatically be rendered into the title
6037      * bar of the region, otherwise the button will not be shown.</p>
6038      * <p><b>Note</b>: that a title bar is required to display the collapse/expand toggle button -- if
6039      * no <tt>title</tt> is specified for the region's panel, the region will only be collapsible if
6040      * <tt>{@link #collapseMode} = 'mini'</tt> and <tt>{@link #split} = true</tt>.
6041      */
6042     collapsible : false,
6043     /**
6044      * @cfg {Boolean} split
6045      * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and
6046      * display a 5px wide {@link Ext.SplitBar} between this region and its neighbor, allowing the user to
6047      * resize the regions dynamically.  Defaults to <tt>false</tt> creating a
6048      * {@link Ext.layout.BorderLayout.Region Region}.</p><br>
6049      * <p><b>Notes</b>:</p><div class="mdetail-params"><ul>
6050      * <li>this configuration option is ignored if <tt>region='center'</tt></li>
6051      * <li>when <tt>split == true</tt>, it is common to specify a
6052      * <tt>{@link Ext.SplitBar#minSize minSize}</tt> and <tt>{@link Ext.SplitBar#maxSize maxSize}</tt>
6053      * for the {@link Ext.BoxComponent BoxComponent} representing the region. These are not native
6054      * configs of {@link Ext.BoxComponent BoxComponent}, and are used only by this class.</li>
6055      * <li>if <tt>{@link #collapseMode} = 'mini'</tt> requires <tt>split = true</tt> to reserve space
6056      * for the collapse tool</tt></li>
6057      * </ul></div>
6058      */
6059     split:false,
6060     /**
6061      * @cfg {Boolean} floatable
6062      * <tt>true</tt> to allow clicking a collapsed region's bar to display the region's panel floated
6063      * above the layout, <tt>false</tt> to force the user to fully expand a collapsed region by
6064      * clicking the expand button to see it again (defaults to <tt>true</tt>).
6065      */
6066     floatable: true,
6067     /**
6068      * @cfg {Number} minWidth
6069      * <p>The minimum allowable width in pixels for this region (defaults to <tt>50</tt>).
6070      * <tt>maxWidth</tt> may also be specified.</p><br>
6071      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
6072      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
6073      * <tt>minWidth</tt> / <tt>maxWidth</tt>.</p>
6074      */
6075     minWidth:50,
6076     /**
6077      * @cfg {Number} minHeight
6078      * The minimum allowable height in pixels for this region (defaults to <tt>50</tt>)
6079      * <tt>maxHeight</tt> may also be specified.</p><br>
6080      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
6081      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
6082      * <tt>minHeight</tt> / <tt>maxHeight</tt>.</p>
6083      */
6084     minHeight:50,
6085
6086     // private
6087     defaultMargins : {left:0,top:0,right:0,bottom:0},
6088     // private
6089     defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
6090     // private
6091     defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
6092     floatingZIndex: 100,
6093
6094     /**
6095      * True if this region is collapsed. Read-only.
6096      * @type Boolean
6097      * @property
6098      */
6099     isCollapsed : false,
6100
6101     /**
6102      * This region's panel.  Read-only.
6103      * @type Ext.Panel
6104      * @property panel
6105      */
6106     /**
6107      * This region's layout.  Read-only.
6108      * @type Layout
6109      * @property layout
6110      */
6111     /**
6112      * This region's layout position (north, south, east, west or center).  Read-only.
6113      * @type String
6114      * @property position
6115      */
6116
6117     // private
6118     render : function(ct, p){
6119         this.panel = p;
6120         p.el.enableDisplayMode();
6121         this.targetEl = ct;
6122         this.el = p.el;
6123
6124         var gs = p.getState, ps = this.position;
6125         p.getState = function(){
6126             return Ext.apply(gs.call(p) || {}, this.state);
6127         }.createDelegate(this);
6128
6129         if(ps != 'center'){
6130             p.allowQueuedExpand = false;
6131             p.on({
6132                 beforecollapse: this.beforeCollapse,
6133                 collapse: this.onCollapse,
6134                 beforeexpand: this.beforeExpand,
6135                 expand: this.onExpand,
6136                 hide: this.onHide,
6137                 show: this.onShow,
6138                 scope: this
6139             });
6140             if(this.collapsible || this.floatable){
6141                 p.collapseEl = 'el';
6142                 p.slideAnchor = this.getSlideAnchor();
6143             }
6144             if(p.tools && p.tools.toggle){
6145                 p.tools.toggle.addClass('x-tool-collapse-'+ps);
6146                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
6147             }
6148         }
6149     },
6150
6151     // private
6152     getCollapsedEl : function(){
6153         if(!this.collapsedEl){
6154             if(!this.toolTemplate){
6155                 var tt = new Ext.Template(
6156                      '<div class="x-tool x-tool-{id}">&#160;</div>'
6157                 );
6158                 tt.disableFormats = true;
6159                 tt.compile();
6160                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
6161             }
6162             this.collapsedEl = this.targetEl.createChild({
6163                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
6164                 id: this.panel.id + '-xcollapsed'
6165             });
6166             this.collapsedEl.enableDisplayMode('block');
6167
6168             if(this.collapseMode == 'mini'){
6169                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
6170                 this.miniCollapsedEl = this.collapsedEl.createChild({
6171                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
6172                 });
6173                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
6174                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
6175                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
6176             }else {
6177                 if(this.collapsible !== false && !this.hideCollapseTool) {
6178                     var t = this.toolTemplate.append(
6179                             this.collapsedEl.dom,
6180                             {id:'expand-'+this.position}, true);
6181                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
6182                     t.on('click', this.onExpandClick, this, {stopEvent:true});
6183                 }
6184                 if(this.floatable !== false || this.titleCollapse){
6185                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
6186                    this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
6187                 }
6188             }
6189         }
6190         return this.collapsedEl;
6191     },
6192
6193     // private
6194     onExpandClick : function(e){
6195         if(this.isSlid){
6196             this.panel.expand(false);
6197         }else{
6198             this.panel.expand();
6199         }
6200     },
6201
6202     // private
6203     onCollapseClick : function(e){
6204         this.panel.collapse();
6205     },
6206
6207     // private
6208     beforeCollapse : function(p, animate){
6209         this.lastAnim = animate;
6210         if(this.splitEl){
6211             this.splitEl.hide();
6212         }
6213         this.getCollapsedEl().show();
6214         var el = this.panel.getEl();
6215         this.originalZIndex = el.getStyle('z-index');
6216         el.setStyle('z-index', 100);
6217         this.isCollapsed = true;
6218         this.layout.layout();
6219     },
6220
6221     // private
6222     onCollapse : function(animate){
6223         this.panel.el.setStyle('z-index', 1);
6224         if(this.lastAnim === false || this.panel.animCollapse === false){
6225             this.getCollapsedEl().dom.style.visibility = 'visible';
6226         }else{
6227             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
6228         }
6229         this.state.collapsed = true;
6230         this.panel.saveState();
6231     },
6232
6233     // private
6234     beforeExpand : function(animate){
6235         if(this.isSlid){
6236             this.afterSlideIn();
6237         }
6238         var c = this.getCollapsedEl();
6239         this.el.show();
6240         if(this.position == 'east' || this.position == 'west'){
6241             this.panel.setSize(undefined, c.getHeight());
6242         }else{
6243             this.panel.setSize(c.getWidth(), undefined);
6244         }
6245         c.hide();
6246         c.dom.style.visibility = 'hidden';
6247         this.panel.el.setStyle('z-index', this.floatingZIndex);
6248     },
6249
6250     // private
6251     onExpand : function(){
6252         this.isCollapsed = false;
6253         if(this.splitEl){
6254             this.splitEl.show();
6255         }
6256         this.layout.layout();
6257         this.panel.el.setStyle('z-index', this.originalZIndex);
6258         this.state.collapsed = false;
6259         this.panel.saveState();
6260     },
6261
6262     // private
6263     collapseClick : function(e){
6264         if(this.isSlid){
6265            e.stopPropagation();
6266            this.slideIn();
6267         }else{
6268            e.stopPropagation();
6269            this.slideOut();
6270         }
6271     },
6272
6273     // private
6274     onHide : function(){
6275         if(this.isCollapsed){
6276             this.getCollapsedEl().hide();
6277         }else if(this.splitEl){
6278             this.splitEl.hide();
6279         }
6280     },
6281
6282     // private
6283     onShow : function(){
6284         if(this.isCollapsed){
6285             this.getCollapsedEl().show();
6286         }else if(this.splitEl){
6287             this.splitEl.show();
6288         }
6289     },
6290
6291     /**
6292      * True if this region is currently visible, else false.
6293      * @return {Boolean}
6294      */
6295     isVisible : function(){
6296         return !this.panel.hidden;
6297     },
6298
6299     /**
6300      * Returns the current margins for this region.  If the region is collapsed, the
6301      * {@link #cmargins} (collapsed margins) value will be returned, otherwise the
6302      * {@link #margins} value will be returned.
6303      * @return {Object} An object containing the element's margins: <tt>{left: (left
6304      * margin), top: (top margin), right: (right margin), bottom: (bottom margin)}</tt>
6305      */
6306     getMargins : function(){
6307         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
6308     },
6309
6310     /**
6311      * Returns the current size of this region.  If the region is collapsed, the size of the
6312      * collapsedEl will be returned, otherwise the size of the region's panel will be returned.
6313      * @return {Object} An object containing the element's size: <tt>{width: (element width),
6314      * height: (element height)}</tt>
6315      */
6316     getSize : function(){
6317         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
6318     },
6319
6320     /**
6321      * Sets the specified panel as the container element for this region.
6322      * @param {Ext.Panel} panel The new panel
6323      */
6324     setPanel : function(panel){
6325         this.panel = panel;
6326     },
6327
6328     /**
6329      * Returns the minimum allowable width for this region.
6330      * @return {Number} The minimum width
6331      */
6332     getMinWidth: function(){
6333         return this.minWidth;
6334     },
6335
6336     /**
6337      * Returns the minimum allowable height for this region.
6338      * @return {Number} The minimum height
6339      */
6340     getMinHeight: function(){
6341         return this.minHeight;
6342     },
6343
6344     // private
6345     applyLayoutCollapsed : function(box){
6346         var ce = this.getCollapsedEl();
6347         ce.setLeftTop(box.x, box.y);
6348         ce.setSize(box.width, box.height);
6349     },
6350
6351     // private
6352     applyLayout : function(box){
6353         if(this.isCollapsed){
6354             this.applyLayoutCollapsed(box);
6355         }else{
6356             this.panel.setPosition(box.x, box.y);
6357             this.panel.setSize(box.width, box.height);
6358         }
6359     },
6360
6361     // private
6362     beforeSlide: function(){
6363         this.panel.beforeEffect();
6364     },
6365
6366     // private
6367     afterSlide : function(){
6368         this.panel.afterEffect();
6369     },
6370
6371     // private
6372     initAutoHide : function(){
6373         if(this.autoHide !== false){
6374             if(!this.autoHideHd){
6375                 var st = new Ext.util.DelayedTask(this.slideIn, this);
6376                 this.autoHideHd = {
6377                     "mouseout": function(e){
6378                         if(!e.within(this.el, true)){
6379                             st.delay(500);
6380                         }
6381                     },
6382                     "mouseover" : function(e){
6383                         st.cancel();
6384                     },
6385                     scope : this
6386                 };
6387             }
6388             this.el.on(this.autoHideHd);
6389             this.collapsedEl.on(this.autoHideHd);
6390         }
6391     },
6392
6393     // private
6394     clearAutoHide : function(){
6395         if(this.autoHide !== false){
6396             this.el.un("mouseout", this.autoHideHd.mouseout);
6397             this.el.un("mouseover", this.autoHideHd.mouseover);
6398             this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
6399             this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
6400         }
6401     },
6402
6403     // private
6404     clearMonitor : function(){
6405         Ext.getDoc().un("click", this.slideInIf, this);
6406     },
6407
6408     /**
6409      * If this Region is {@link #floatable}, this method slides this Region into full visibility <i>over the top
6410      * of the center Region</i> where it floats until either {@link #slideIn} is called, or other regions of the layout
6411      * are clicked, or the mouse exits the Region.
6412      */
6413     slideOut : function(){
6414         if(this.isSlid || this.el.hasActiveFx()){
6415             return;
6416         }
6417         this.isSlid = true;
6418         var ts = this.panel.tools, dh, pc;
6419         if(ts && ts.toggle){
6420             ts.toggle.hide();
6421         }
6422         this.el.show();
6423
6424         // Temporarily clear the collapsed flag so we can onResize the panel on the slide
6425         pc = this.panel.collapsed;
6426         this.panel.collapsed = false;
6427
6428         if(this.position == 'east' || this.position == 'west'){
6429             // Temporarily clear the deferHeight flag so we can size the height on the slide
6430             dh = this.panel.deferHeight;
6431             this.panel.deferHeight = false;
6432
6433             this.panel.setSize(undefined, this.collapsedEl.getHeight());
6434
6435             // Put the deferHeight flag back after setSize
6436             this.panel.deferHeight = dh;
6437         }else{
6438             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
6439         }
6440
6441         // Put the collapsed flag back after onResize
6442         this.panel.collapsed = pc;
6443
6444         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
6445         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
6446         this.el.setStyle("z-index", this.floatingZIndex+2);
6447         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
6448         if(this.animFloat !== false){
6449             this.beforeSlide();
6450             this.el.slideIn(this.getSlideAnchor(), {
6451                 callback: function(){
6452                     this.afterSlide();
6453                     this.initAutoHide();
6454                     Ext.getDoc().on("click", this.slideInIf, this);
6455                 },
6456                 scope: this,
6457                 block: true
6458             });
6459         }else{
6460             this.initAutoHide();
6461              Ext.getDoc().on("click", this.slideInIf, this);
6462         }
6463     },
6464
6465     // private
6466     afterSlideIn : function(){
6467         this.clearAutoHide();
6468         this.isSlid = false;
6469         this.clearMonitor();
6470         this.el.setStyle("z-index", "");
6471         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
6472         this.el.dom.style.left = this.restoreLT[0];
6473         this.el.dom.style.top = this.restoreLT[1];
6474
6475         var ts = this.panel.tools;
6476         if(ts && ts.toggle){
6477             ts.toggle.show();
6478         }
6479     },
6480
6481     /**
6482      * If this Region is {@link #floatable}, and this Region has been slid into floating visibility, then this method slides
6483      * this region back into its collapsed state.
6484      */
6485     slideIn : function(cb){
6486         if(!this.isSlid || this.el.hasActiveFx()){
6487             Ext.callback(cb);
6488             return;
6489         }
6490         this.isSlid = false;
6491         if(this.animFloat !== false){
6492             this.beforeSlide();
6493             this.el.slideOut(this.getSlideAnchor(), {
6494                 callback: function(){
6495                     this.el.hide();
6496                     this.afterSlide();
6497                     this.afterSlideIn();
6498                     Ext.callback(cb);
6499                 },
6500                 scope: this,
6501                 block: true
6502             });
6503         }else{
6504             this.el.hide();
6505             this.afterSlideIn();
6506         }
6507     },
6508
6509     // private
6510     slideInIf : function(e){
6511         if(!e.within(this.el)){
6512             this.slideIn();
6513         }
6514     },
6515
6516     // private
6517     anchors : {
6518         "west" : "left",
6519         "east" : "right",
6520         "north" : "top",
6521         "south" : "bottom"
6522     },
6523
6524     // private
6525     sanchors : {
6526         "west" : "l",
6527         "east" : "r",
6528         "north" : "t",
6529         "south" : "b"
6530     },
6531
6532     // private
6533     canchors : {
6534         "west" : "tl-tr",
6535         "east" : "tr-tl",
6536         "north" : "tl-bl",
6537         "south" : "bl-tl"
6538     },
6539
6540     // private
6541     getAnchor : function(){
6542         return this.anchors[this.position];
6543     },
6544
6545     // private
6546     getCollapseAnchor : function(){
6547         return this.canchors[this.position];
6548     },
6549
6550     // private
6551     getSlideAnchor : function(){
6552         return this.sanchors[this.position];
6553     },
6554
6555     // private
6556     getAlignAdj : function(){
6557         var cm = this.cmargins;
6558         switch(this.position){
6559             case "west":
6560                 return [0, 0];
6561             break;
6562             case "east":
6563                 return [0, 0];
6564             break;
6565             case "north":
6566                 return [0, 0];
6567             break;
6568             case "south":
6569                 return [0, 0];
6570             break;
6571         }
6572     },
6573
6574     // private
6575     getExpandAdj : function(){
6576         var c = this.collapsedEl, cm = this.cmargins;
6577         switch(this.position){
6578             case "west":
6579                 return [-(cm.right+c.getWidth()+cm.left), 0];
6580             break;
6581             case "east":
6582                 return [cm.right+c.getWidth()+cm.left, 0];
6583             break;
6584             case "north":
6585                 return [0, -(cm.top+cm.bottom+c.getHeight())];
6586             break;
6587             case "south":
6588                 return [0, cm.top+cm.bottom+c.getHeight()];
6589             break;
6590         }
6591     },
6592
6593     destroy : function(){
6594         Ext.destroy(this.miniCollapsedEl, this.collapsedEl);
6595     }
6596 };
6597
6598 /**
6599  * @class Ext.layout.BorderLayout.SplitRegion
6600  * @extends Ext.layout.BorderLayout.Region
6601  * <p>This is a specialized type of {@link Ext.layout.BorderLayout.Region BorderLayout region} that
6602  * has a built-in {@link Ext.SplitBar} for user resizing of regions.  The movement of the split bar
6603  * is configurable to move either {@link #tickSize smooth or incrementally}.</p>
6604  * @constructor
6605  * Create a new SplitRegion.
6606  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
6607  * @param {Object} config The configuration options
6608  * @param {String} position The region position.  Valid values are: north, south, east, west and center.  Every
6609  * BorderLayout must have a center region for the primary content -- all other regions are optional.
6610  */
6611 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
6612     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
6613     // prevent switch
6614     this.applyLayout = this.applyFns[pos];
6615 };
6616
6617 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
6618     /**
6619      * @cfg {Number} tickSize
6620      * The increment, in pixels by which to move this Region's {@link Ext.SplitBar SplitBar}.
6621      * By default, the {@link Ext.SplitBar SplitBar} moves smoothly.
6622      */
6623     /**
6624      * @cfg {String} splitTip
6625      * The tooltip to display when the user hovers over a
6626      * {@link Ext.layout.BorderLayout.Region#collapsible non-collapsible} region's split bar
6627      * (defaults to <tt>"Drag to resize."</tt>).  Only applies if
6628      * <tt>{@link #useSplitTips} = true</tt>.
6629      */
6630     splitTip : "Drag to resize.",
6631     /**
6632      * @cfg {String} collapsibleSplitTip
6633      * The tooltip to display when the user hovers over a
6634      * {@link Ext.layout.BorderLayout.Region#collapsible collapsible} region's split bar
6635      * (defaults to "Drag to resize. Double click to hide."). Only applies if
6636      * <tt>{@link #useSplitTips} = true</tt>.
6637      */
6638     collapsibleSplitTip : "Drag to resize. Double click to hide.",
6639     /**
6640      * @cfg {Boolean} useSplitTips
6641      * <tt>true</tt> to display a tooltip when the user hovers over a region's split bar
6642      * (defaults to <tt>false</tt>).  The tooltip text will be the value of either
6643      * <tt>{@link #splitTip}</tt> or <tt>{@link #collapsibleSplitTip}</tt> as appropriate.
6644      */
6645     useSplitTips : false,
6646
6647     // private
6648     splitSettings : {
6649         north : {
6650             orientation: Ext.SplitBar.VERTICAL,
6651             placement: Ext.SplitBar.TOP,
6652             maxFn : 'getVMaxSize',
6653             minProp: 'minHeight',
6654             maxProp: 'maxHeight'
6655         },
6656         south : {
6657             orientation: Ext.SplitBar.VERTICAL,
6658             placement: Ext.SplitBar.BOTTOM,
6659             maxFn : 'getVMaxSize',
6660             minProp: 'minHeight',
6661             maxProp: 'maxHeight'
6662         },
6663         east : {
6664             orientation: Ext.SplitBar.HORIZONTAL,
6665             placement: Ext.SplitBar.RIGHT,
6666             maxFn : 'getHMaxSize',
6667             minProp: 'minWidth',
6668             maxProp: 'maxWidth'
6669         },
6670         west : {
6671             orientation: Ext.SplitBar.HORIZONTAL,
6672             placement: Ext.SplitBar.LEFT,
6673             maxFn : 'getHMaxSize',
6674             minProp: 'minWidth',
6675             maxProp: 'maxWidth'
6676         }
6677     },
6678
6679     // private
6680     applyFns : {
6681         west : function(box){
6682             if(this.isCollapsed){
6683                 return this.applyLayoutCollapsed(box);
6684             }
6685             var sd = this.splitEl.dom, s = sd.style;
6686             this.panel.setPosition(box.x, box.y);
6687             var sw = sd.offsetWidth;
6688             s.left = (box.x+box.width-sw)+'px';
6689             s.top = (box.y)+'px';
6690             s.height = Math.max(0, box.height)+'px';
6691             this.panel.setSize(box.width-sw, box.height);
6692         },
6693         east : function(box){
6694             if(this.isCollapsed){
6695                 return this.applyLayoutCollapsed(box);
6696             }
6697             var sd = this.splitEl.dom, s = sd.style;
6698             var sw = sd.offsetWidth;
6699             this.panel.setPosition(box.x+sw, box.y);
6700             s.left = (box.x)+'px';
6701             s.top = (box.y)+'px';
6702             s.height = Math.max(0, box.height)+'px';
6703             this.panel.setSize(box.width-sw, box.height);
6704         },
6705         north : function(box){
6706             if(this.isCollapsed){
6707                 return this.applyLayoutCollapsed(box);
6708             }
6709             var sd = this.splitEl.dom, s = sd.style;
6710             var sh = sd.offsetHeight;
6711             this.panel.setPosition(box.x, box.y);
6712             s.left = (box.x)+'px';
6713             s.top = (box.y+box.height-sh)+'px';
6714             s.width = Math.max(0, box.width)+'px';
6715             this.panel.setSize(box.width, box.height-sh);
6716         },
6717         south : function(box){
6718             if(this.isCollapsed){
6719                 return this.applyLayoutCollapsed(box);
6720             }
6721             var sd = this.splitEl.dom, s = sd.style;
6722             var sh = sd.offsetHeight;
6723             this.panel.setPosition(box.x, box.y+sh);
6724             s.left = (box.x)+'px';
6725             s.top = (box.y)+'px';
6726             s.width = Math.max(0, box.width)+'px';
6727             this.panel.setSize(box.width, box.height-sh);
6728         }
6729     },
6730
6731     // private
6732     render : function(ct, p){
6733         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
6734
6735         var ps = this.position;
6736
6737         this.splitEl = ct.createChild({
6738             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
6739             id: this.panel.id + '-xsplit'
6740         });
6741
6742         if(this.collapseMode == 'mini'){
6743             this.miniSplitEl = this.splitEl.createChild({
6744                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
6745             });
6746             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
6747             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
6748         }
6749
6750         var s = this.splitSettings[ps];
6751
6752         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
6753         this.split.tickSize = this.tickSize;
6754         this.split.placement = s.placement;
6755         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
6756         this.split.minSize = this.minSize || this[s.minProp];
6757         this.split.on("beforeapply", this.onSplitMove, this);
6758         this.split.useShim = this.useShim === true;
6759         this.maxSize = this.maxSize || this[s.maxProp];
6760
6761         if(p.hidden){
6762             this.splitEl.hide();
6763         }
6764
6765         if(this.useSplitTips){
6766             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
6767         }
6768         if(this.collapsible){
6769             this.splitEl.on("dblclick", this.onCollapseClick,  this);
6770         }
6771     },
6772
6773     //docs inherit from superclass
6774     getSize : function(){
6775         if(this.isCollapsed){
6776             return this.collapsedEl.getSize();
6777         }
6778         var s = this.panel.getSize();
6779         if(this.position == 'north' || this.position == 'south'){
6780             s.height += this.splitEl.dom.offsetHeight;
6781         }else{
6782             s.width += this.splitEl.dom.offsetWidth;
6783         }
6784         return s;
6785     },
6786
6787     // private
6788     getHMaxSize : function(){
6789          var cmax = this.maxSize || 10000;
6790          var center = this.layout.center;
6791          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
6792     },
6793
6794     // private
6795     getVMaxSize : function(){
6796         var cmax = this.maxSize || 10000;
6797         var center = this.layout.center;
6798         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
6799     },
6800
6801     // private
6802     onSplitMove : function(split, newSize){
6803         var s = this.panel.getSize();
6804         this.lastSplitSize = newSize;
6805         if(this.position == 'north' || this.position == 'south'){
6806             this.panel.setSize(s.width, newSize);
6807             this.state.height = newSize;
6808         }else{
6809             this.panel.setSize(newSize, s.height);
6810             this.state.width = newSize;
6811         }
6812         this.layout.layout();
6813         this.panel.saveState();
6814         return false;
6815     },
6816
6817     /**
6818      * Returns a reference to the split bar in use by this region.
6819      * @return {Ext.SplitBar} The split bar
6820      */
6821     getSplitBar : function(){
6822         return this.split;
6823     },
6824
6825     // inherit docs
6826     destroy : function() {
6827         Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
6828         Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
6829     }
6830 });
6831
6832 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;/**
6833  * @class Ext.layout.FormLayout
6834  * @extends Ext.layout.AnchorLayout
6835  * <p>This layout manager is specifically designed for rendering and managing child Components of
6836  * {@link Ext.form.FormPanel forms}. It is responsible for rendering the labels of
6837  * {@link Ext.form.Field Field}s.</p>
6838  *
6839  * <p>This layout manager is used when a Container is configured with the <tt>layout:'form'</tt>
6840  * {@link Ext.Container#layout layout} config option, and should generally not need to be created directly
6841  * via the new keyword. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
6842  *
6843  * <p>In an application, it will usually be preferrable to use a {@link Ext.form.FormPanel FormPanel}
6844  * (which is configured with FormLayout as its layout class by default) since it also provides built-in
6845  * functionality for {@link Ext.form.BasicForm#doAction loading, validating and submitting} the form.</p>
6846  *
6847  * <p>A {@link Ext.Container Container} <i>using</i> the FormLayout layout manager (e.g.
6848  * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) can also accept the following
6849  * layout-specific config properties:<div class="mdetail-params"><ul>
6850  * <li><b><tt>{@link Ext.form.FormPanel#hideLabels hideLabels}</tt></b></li>
6851  * <li><b><tt>{@link Ext.form.FormPanel#labelAlign labelAlign}</tt></b></li>
6852  * <li><b><tt>{@link Ext.form.FormPanel#labelPad labelPad}</tt></b></li>
6853  * <li><b><tt>{@link Ext.form.FormPanel#labelSeparator labelSeparator}</tt></b></li>
6854  * <li><b><tt>{@link Ext.form.FormPanel#labelWidth labelWidth}</tt></b></li>
6855  * </ul></div></p>
6856  *
6857  * <p>Any Component (including Fields) managed by FormLayout accepts the following as a config option:
6858  * <div class="mdetail-params"><ul>
6859  * <li><b><tt>{@link Ext.Component#anchor anchor}</tt></b></li>
6860  * </ul></div></p>
6861  *
6862  * <p>Any Component managed by FormLayout may be rendered as a form field (with an associated label) by
6863  * configuring it with a non-null <b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b>. Components configured
6864  * in this way may be configured with the following options which affect the way the FormLayout renders them:
6865  * <div class="mdetail-params"><ul>
6866  * <li><b><tt>{@link Ext.Component#clearCls clearCls}</tt></b></li>
6867  * <li><b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b></li>
6868  * <li><b><tt>{@link Ext.Component#hideLabel hideLabel}</tt></b></li>
6869  * <li><b><tt>{@link Ext.Component#itemCls itemCls}</tt></b></li>
6870  * <li><b><tt>{@link Ext.Component#labelSeparator labelSeparator}</tt></b></li>
6871  * <li><b><tt>{@link Ext.Component#labelStyle labelStyle}</tt></b></li>
6872  * </ul></div></p>
6873  *
6874  * <p>Example usage:</p>
6875  * <pre><code>
6876 // Required if showing validation messages
6877 Ext.QuickTips.init();
6878
6879 // While you can create a basic Panel with layout:'form', practically
6880 // you should usually use a FormPanel to also get its form functionality
6881 // since it already creates a FormLayout internally.
6882 var form = new Ext.form.FormPanel({
6883     title: 'Form Layout',
6884     bodyStyle: 'padding:15px',
6885     width: 350,
6886     defaultType: 'textfield',
6887     defaults: {
6888         // applied to each contained item
6889         width: 230,
6890         msgTarget: 'side'
6891     },
6892     items: [{
6893             fieldLabel: 'First Name',
6894             name: 'first',
6895             allowBlank: false,
6896             {@link Ext.Component#labelSeparator labelSeparator}: ':' // override labelSeparator layout config
6897         },{
6898             fieldLabel: 'Last Name',
6899             name: 'last'
6900         },{
6901             fieldLabel: 'Email',
6902             name: 'email',
6903             vtype:'email'
6904         }, {
6905             xtype: 'textarea',
6906             hideLabel: true,     // override hideLabels layout config
6907             name: 'msg',
6908             anchor: '100% -53'
6909         }
6910     ],
6911     buttons: [
6912         {text: 'Save'},
6913         {text: 'Cancel'}
6914     ],
6915     layoutConfig: {
6916         {@link #labelSeparator}: '~' // superseded by assignment below
6917     },
6918     // config options applicable to container when layout='form':
6919     hideLabels: false,
6920     labelAlign: 'left',   // or 'right' or 'top'
6921     {@link Ext.form.FormPanel#labelSeparator labelSeparator}: '>>', // takes precedence over layoutConfig value
6922     labelWidth: 65,       // defaults to 100
6923     labelPad: 8           // defaults to 5, must specify labelWidth to be honored
6924 });
6925 </code></pre>
6926  */
6927 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
6928
6929     /**
6930      * @cfg {String} labelSeparator
6931      * See {@link Ext.form.FormPanel}.{@link Ext.form.FormPanel#labelSeparator labelSeparator}.  Configuration
6932      * of this property at the <b>container</b> level takes precedence.
6933      */
6934     labelSeparator : ':',
6935
6936     /**
6937      * Read only. The CSS style specification string added to field labels in this layout if not
6938      * otherwise {@link Ext.Component#labelStyle specified by each contained field}.
6939      * @type String
6940      * @property labelStyle
6941      */
6942
6943     /**
6944      * @cfg {Boolean} trackLabels
6945      * True to show/hide the field label when the field is hidden. Defaults to <tt>false</tt>.
6946      */
6947     trackLabels: false,
6948
6949     type: 'form',
6950
6951
6952     onRemove: function(c){
6953         Ext.layout.FormLayout.superclass.onRemove.call(this, c);
6954         if(this.trackLabels){
6955             c.un('show', this.onFieldShow, this);
6956             c.un('hide', this.onFieldHide, this);
6957         }
6958         // check for itemCt, since we may be removing a fieldset or something similar
6959         var el = c.getPositionEl(),
6960                 ct = c.getItemCt && c.getItemCt();
6961         if(c.rendered && ct){
6962             if (el && el.dom) {
6963                 el.insertAfter(ct);
6964             }
6965             Ext.destroy(ct);
6966             Ext.destroyMembers(c, 'label', 'itemCt');
6967             if(c.customItemCt){
6968                 Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
6969             }
6970         }
6971     },
6972
6973     // private
6974     setContainer : function(ct){
6975         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
6976         if(ct.labelAlign){
6977             ct.addClass('x-form-label-'+ct.labelAlign);
6978         }
6979
6980         if(ct.hideLabels){
6981             Ext.apply(this, {
6982                 labelStyle: 'display:none',
6983                 elementStyle: 'padding-left:0;',
6984                 labelAdjust: 0
6985             });
6986         }else{
6987             this.labelSeparator = ct.labelSeparator || this.labelSeparator;
6988             ct.labelWidth = ct.labelWidth || 100;
6989             if(Ext.isNumber(ct.labelWidth)){
6990                 var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
6991                 Ext.apply(this, {
6992                     labelAdjust: ct.labelWidth + pad,
6993                     labelStyle: 'width:' + ct.labelWidth + 'px;',
6994                     elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
6995                 });
6996             }
6997             if(ct.labelAlign == 'top'){
6998                 Ext.apply(this, {
6999                     labelStyle: 'width:auto;',
7000                     labelAdjust: 0,
7001                     elementStyle: 'padding-left:0;'
7002                 });
7003             }
7004         }
7005     },
7006
7007     // private
7008     isHide: function(c){
7009         return c.hideLabel || this.container.hideLabels;
7010     },
7011
7012     onFieldShow: function(c){
7013         c.getItemCt().removeClass('x-hide-' + c.hideMode);
7014     },
7015
7016     onFieldHide: function(c){
7017         c.getItemCt().addClass('x-hide-' + c.hideMode);
7018     },
7019
7020     //private
7021     getLabelStyle: function(s){
7022         var ls = '', items = [this.labelStyle, s];
7023         for (var i = 0, len = items.length; i < len; ++i){
7024             if (items[i]){
7025                 ls += items[i];
7026                 if (ls.substr(-1, 1) != ';'){
7027                     ls += ';'
7028                 }
7029             }
7030         }
7031         return ls;
7032     },
7033
7034     /**
7035      * @cfg {Ext.Template} fieldTpl
7036      * A {@link Ext.Template#compile compile}d {@link Ext.Template} for rendering
7037      * the fully wrapped, labeled and styled form Field. Defaults to:</p><pre><code>
7038 new Ext.Template(
7039     &#39;&lt;div class="x-form-item {itemCls}" tabIndex="-1">&#39;,
7040         &#39;&lt;&#108;abel for="{id}" style="{labelStyle}" class="x-form-item-&#108;abel">{&#108;abel}{labelSeparator}&lt;/&#108;abel>&#39;,
7041         &#39;&lt;div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">&#39;,
7042         &#39;&lt;/div>&lt;div class="{clearCls}">&lt;/div>&#39;,
7043     '&lt;/div>'
7044 );
7045 </code></pre>
7046      * <p>This may be specified to produce a different DOM structure when rendering form Fields.</p>
7047      * <p>A description of the properties within the template follows:</p><div class="mdetail-params"><ul>
7048      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
7049      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
7050      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
7051      * supplied at the container level.</div></li>
7052      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
7053      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
7054      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
7055      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
7056      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
7057      * field (defaults to <tt>''</tt>)</div></li>
7058      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
7059      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
7060      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
7061      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
7062      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
7063      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
7064      * </ul></div>
7065      * <p>Also see <tt>{@link #getTemplateArgs}</tt></p>
7066      */
7067
7068     // private
7069     renderItem : function(c, position, target){
7070         if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
7071             var args = this.getTemplateArgs(c);
7072             if(Ext.isNumber(position)){
7073                 position = target.dom.childNodes[position] || null;
7074             }
7075             if(position){
7076                 c.itemCt = this.fieldTpl.insertBefore(position, args, true);
7077             }else{
7078                 c.itemCt = this.fieldTpl.append(target, args, true);
7079             }
7080             if(!c.getItemCt){
7081                 // Non form fields don't have getItemCt, apply it here
7082                 // This will get cleaned up in onRemove
7083                 Ext.apply(c, {
7084                     getItemCt: function(){
7085                         return c.itemCt;
7086                     },
7087                     customItemCt: true
7088                 });
7089             }
7090             c.label = c.getItemCt().child('label.x-form-item-label');
7091             if(!c.rendered){
7092                 c.render('x-form-el-' + c.id);
7093             }else if(!this.isValidParent(c, target)){
7094                 Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
7095             }
7096             if(this.trackLabels){
7097                 if(c.hidden){
7098                     this.onFieldHide(c);
7099                 }
7100                 c.on({
7101                     scope: this,
7102                     show: this.onFieldShow,
7103                     hide: this.onFieldHide
7104                 });
7105             }
7106             this.configureItem(c);
7107         }else {
7108             Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
7109         }
7110     },
7111
7112     /**
7113      * <p>Provides template arguments for rendering the fully wrapped, labeled and styled form Field.</p>
7114      * <p>This method returns an object hash containing properties used by the layout's {@link #fieldTpl}
7115      * to create a correctly wrapped, labeled and styled form Field. This may be overriden to
7116      * create custom layouts. The properties which must be returned are:</p><div class="mdetail-params"><ul>
7117      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
7118      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
7119      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
7120      * supplied at the container level.</div></li>
7121      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
7122      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
7123      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
7124      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
7125      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
7126      * field (defaults to <tt>''</tt>)</div></li>
7127      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
7128      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
7129      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
7130      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
7131      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
7132      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
7133      * </ul></div>
7134      * @param (Ext.form.Field} field The {@link Ext.form.Field Field} being rendered.
7135      * @return An object hash containing the properties required to render the Field.
7136      */
7137     getTemplateArgs: function(field) {
7138         var noLabelSep = !field.fieldLabel || field.hideLabel;
7139         return {
7140             id: field.id,
7141             label: field.fieldLabel,
7142             labelStyle: this.getLabelStyle(field.labelStyle),
7143             elementStyle: this.elementStyle||'',
7144             labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator),
7145             itemCls: (field.itemCls||this.container.itemCls||'') + (field.hideLabel ? ' x-hide-label' : ''),
7146             clearCls: field.clearCls || 'x-form-clear-left'
7147         };
7148     },
7149
7150     // private
7151     adjustWidthAnchor: function(value, c){
7152         if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){
7153             var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
7154             return value - this.labelAdjust + (adjust ? -3 : 0);
7155         }
7156         return value;
7157     },
7158
7159     adjustHeightAnchor : function(value, c){
7160         if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
7161             return value - c.label.getHeight();
7162         }
7163         return value;
7164     },
7165
7166     // private
7167     isValidParent : function(c, target){
7168         return target && this.container.getEl().contains(c.getPositionEl());
7169     }
7170
7171     /**
7172      * @property activeItem
7173      * @hide
7174      */
7175 });
7176
7177 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
7178 /**\r
7179  * @class Ext.layout.AccordionLayout\r
7180  * @extends Ext.layout.FitLayout\r
7181  * <p>This is a layout that manages multiple Panels in an expandable accordion style such that only\r
7182  * <b>one Panel can be expanded at any given time</b>. Each Panel has built-in support for expanding and collapsing.</p>\r
7183  * <p>Note: Only Ext.Panels <b>and all subclasses of Ext.Panel</b> may be used in an accordion layout Container.</p>\r
7184  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>\r
7185  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>\r
7186  * <p>Example usage:</p>\r
7187  * <pre><code>\r
7188 var accordion = new Ext.Panel({\r
7189     title: 'Accordion Layout',\r
7190     layout:'accordion',\r
7191     defaults: {\r
7192         // applied to each contained panel\r
7193         bodyStyle: 'padding:15px'\r
7194     },\r
7195     layoutConfig: {\r
7196         // layout-specific configs go here\r
7197         titleCollapse: false,\r
7198         animate: true,\r
7199         activeOnTop: true\r
7200     },\r
7201     items: [{\r
7202         title: 'Panel 1',\r
7203         html: '&lt;p&gt;Panel content!&lt;/p&gt;'\r
7204     },{\r
7205         title: 'Panel 2',\r
7206         html: '&lt;p&gt;Panel content!&lt;/p&gt;'\r
7207     },{\r
7208         title: 'Panel 3',\r
7209         html: '&lt;p&gt;Panel content!&lt;/p&gt;'\r
7210     }]\r
7211 });\r
7212 </code></pre>\r
7213  */\r
7214 Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {\r
7215     /**\r
7216      * @cfg {Boolean} fill\r
7217      * True to adjust the active item's height to fill the available space in the container, false to use the\r
7218      * item's current height, or auto height if not explicitly set (defaults to true).\r
7219      */\r
7220     fill : true,\r
7221     /**\r
7222      * @cfg {Boolean} autoWidth\r
7223      * True to set each contained item's width to 'auto', false to use the item's current width (defaults to true).\r
7224      * Note that some components, in particular the {@link Ext.grid.GridPanel grid}, will not function properly within\r
7225      * layouts if they have auto width, so in such cases this config should be set to false.\r
7226      */\r
7227     autoWidth : true,\r
7228     /**\r
7229      * @cfg {Boolean} titleCollapse\r
7230      * True to allow expand/collapse of each contained panel by clicking anywhere on the title bar, false to allow\r
7231      * expand/collapse only when the toggle tool button is clicked (defaults to true).  When set to false,\r
7232      * {@link #hideCollapseTool} should be false also.\r
7233      */\r
7234     titleCollapse : true,\r
7235     /**\r
7236      * @cfg {Boolean} hideCollapseTool\r
7237      * True to hide the contained panels' collapse/expand toggle buttons, false to display them (defaults to false).\r
7238      * When set to true, {@link #titleCollapse} should be true also.\r
7239      */\r
7240     hideCollapseTool : false,\r
7241     /**\r
7242      * @cfg {Boolean} collapseFirst\r
7243      * True to make sure the collapse/expand toggle button always renders first (to the left of) any other tools\r
7244      * in the contained panels' title bars, false to render it last (defaults to false).\r
7245      */\r
7246     collapseFirst : false,\r
7247     /**\r
7248      * @cfg {Boolean} animate\r
7249      * True to slide the contained panels open and closed during expand/collapse using animation, false to open and\r
7250      * close directly with no animation (defaults to false).  Note: to defer to the specific config setting of each\r
7251      * contained panel for this property, set this to undefined at the layout level.\r
7252      */\r
7253     animate : false,\r
7254     /**\r
7255      * @cfg {Boolean} sequence\r
7256      * <b>Experimental</b>. If animate is set to true, this will result in each animation running in sequence.\r
7257      */\r
7258     sequence : false,\r
7259     /**\r
7260      * @cfg {Boolean} activeOnTop\r
7261      * True to swap the position of each panel as it is expanded so that it becomes the first item in the container,\r
7262      * false to keep the panels in the rendered order. <b>This is NOT compatible with "animate:true"</b> (defaults to false).\r
7263      */\r
7264     activeOnTop : false,\r
7265 \r
7266     type: 'accordion',\r
7267 \r
7268     renderItem : function(c){\r
7269         if(this.animate === false){\r
7270             c.animCollapse = false;\r
7271         }\r
7272         c.collapsible = true;\r
7273         if(this.autoWidth){\r
7274             c.autoWidth = true;\r
7275         }\r
7276         if(this.titleCollapse){\r
7277             c.titleCollapse = true;\r
7278         }\r
7279         if(this.hideCollapseTool){\r
7280             c.hideCollapseTool = true;\r
7281         }\r
7282         if(this.collapseFirst !== undefined){\r
7283             c.collapseFirst = this.collapseFirst;\r
7284         }\r
7285         if(!this.activeItem && !c.collapsed){\r
7286             this.setActiveItem(c, true);\r
7287         }else if(this.activeItem && this.activeItem != c){\r
7288             c.collapsed = true;\r
7289         }\r
7290         Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);\r
7291         c.header.addClass('x-accordion-hd');\r
7292         c.on('beforeexpand', this.beforeExpand, this);\r
7293     },\r
7294 \r
7295     onRemove: function(c){\r
7296         Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);\r
7297         if(c.rendered){\r
7298             c.header.removeClass('x-accordion-hd');\r
7299         }\r
7300         c.un('beforeexpand', this.beforeExpand, this);\r
7301     },\r
7302 \r
7303     // private\r
7304     beforeExpand : function(p, anim){\r
7305         var ai = this.activeItem;\r
7306         if(ai){\r
7307             if(this.sequence){\r
7308                 delete this.activeItem;\r
7309                 if (!ai.collapsed){\r
7310                     ai.collapse({callback:function(){\r
7311                         p.expand(anim || true);\r
7312                     }, scope: this});\r
7313                     return false;\r
7314                 }\r
7315             }else{\r
7316                 ai.collapse(this.animate);\r
7317             }\r
7318         }\r
7319         this.setActive(p);\r
7320         if(this.activeOnTop){\r
7321             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);\r
7322         }\r
7323         // Items have been hidden an possibly rearranged, we need to get the container size again.\r
7324         this.layout();\r
7325     },\r
7326 \r
7327     // private\r
7328     setItemSize : function(item, size){\r
7329         if(this.fill && item){\r
7330             var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;\r
7331             // Add up all the header heights\r
7332             for (i = 0; i < len; i++) {\r
7333                 if((p = ct[i]) != item){\r
7334                     hh += p.header.getHeight();\r
7335                 }\r
7336             };\r
7337             // Subtract the header heights from the container size\r
7338             size.height -= hh;\r
7339             // Call setSize on the container to set the correct height.  For Panels, deferedHeight\r
7340             // will simply store this size for when the expansion is done.\r
7341             item.setSize(size);\r
7342         }\r
7343     },\r
7344 \r
7345     /**\r
7346      * Sets the active (expanded) item in the layout.\r
7347      * @param {String/Number} item The string component id or numeric index of the item to activate\r
7348      */\r
7349     setActiveItem : function(item){\r
7350         this.setActive(item, true);\r
7351     },\r
7352 \r
7353     // private\r
7354     setActive : function(item, expand){\r
7355         var ai = this.activeItem;\r
7356         item = this.container.getComponent(item);\r
7357         if(ai != item){\r
7358             if(item.rendered && item.collapsed && expand){\r
7359                 item.expand();\r
7360             }else{\r
7361                 if(ai){\r
7362                    ai.fireEvent('deactivate', ai);\r
7363                 }\r
7364                 this.activeItem = item;\r
7365                 item.fireEvent('activate', item);\r
7366             }\r
7367         }\r
7368     }\r
7369 });\r
7370 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;\r
7371 \r
7372 //backwards compat\r
7373 Ext.layout.Accordion = Ext.layout.AccordionLayout;/**\r
7374  * @class Ext.layout.TableLayout\r
7375  * @extends Ext.layout.ContainerLayout\r
7376  * <p>This layout allows you to easily render content into an HTML table.  The total number of columns can be\r
7377  * specified, and rowspan and colspan can be used to create complex layouts within the table.\r
7378  * This class is intended to be extended or created via the layout:'table' {@link Ext.Container#layout} config,\r
7379  * and should generally not need to be created directly via the new keyword.</p>\r
7380  * <p>Note that when creating a layout via config, the layout-specific config properties must be passed in via\r
7381  * the {@link Ext.Container#layoutConfig} object which will then be applied internally to the layout.  In the\r
7382  * case of TableLayout, the only valid layout config property is {@link #columns}.  However, the items added to a\r
7383  * TableLayout can supply the following table-specific config properties:</p>\r
7384  * <ul>\r
7385  * <li><b>rowspan</b> Applied to the table cell containing the item.</li>\r
7386  * <li><b>colspan</b> Applied to the table cell containing the item.</li>\r
7387  * <li><b>cellId</b> An id applied to the table cell containing the item.</li>\r
7388  * <li><b>cellCls</b> A CSS class name added to the table cell containing the item.</li>\r
7389  * </ul>\r
7390  * <p>The basic concept of building up a TableLayout is conceptually very similar to building up a standard\r
7391  * HTML table.  You simply add each panel (or "cell") that you want to include along with any span attributes\r
7392  * specified as the special config properties of rowspan and colspan which work exactly like their HTML counterparts.\r
7393  * Rather than explicitly creating and nesting rows and columns as you would in HTML, you simply specify the\r
7394  * total column count in the layoutConfig and start adding panels in their natural order from left to right,\r
7395  * top to bottom.  The layout will automatically figure out, based on the column count, rowspans and colspans,\r
7396  * how to position each panel within the table.  Just like with HTML tables, your rowspans and colspans must add\r
7397  * up correctly in your overall layout or you'll end up with missing and/or extra cells!  Example usage:</p>\r
7398  * <pre><code>\r
7399 // This code will generate a layout table that is 3 columns by 2 rows\r
7400 // with some spanning included.  The basic layout will be:\r
7401 // +--------+-----------------+\r
7402 // |   A    |   B             |\r
7403 // |        |--------+--------|\r
7404 // |        |   C    |   D    |\r
7405 // +--------+--------+--------+\r
7406 var table = new Ext.Panel({\r
7407     title: 'Table Layout',\r
7408     layout:'table',\r
7409     defaults: {\r
7410         // applied to each contained panel\r
7411         bodyStyle:'padding:20px'\r
7412     },\r
7413     layoutConfig: {\r
7414         // The total column count must be specified here\r
7415         columns: 3\r
7416     },\r
7417     items: [{\r
7418         html: '&lt;p&gt;Cell A content&lt;/p&gt;',\r
7419         rowspan: 2\r
7420     },{\r
7421         html: '&lt;p&gt;Cell B content&lt;/p&gt;',\r
7422         colspan: 2\r
7423     },{\r
7424         html: '&lt;p&gt;Cell C content&lt;/p&gt;',\r
7425         cellCls: 'highlight'\r
7426     },{\r
7427         html: '&lt;p&gt;Cell D content&lt;/p&gt;'\r
7428     }]\r
7429 });\r
7430 </code></pre>\r
7431  */\r
7432 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
7433     /**\r
7434      * @cfg {Number} columns\r
7435      * The total number of columns to create in the table for this layout.  If not specified, all Components added to\r
7436      * this layout will be rendered into a single row using one column per Component.\r
7437      */\r
7438 \r
7439     // private\r
7440     monitorResize:false,\r
7441 \r
7442     type: 'table',\r
7443 \r
7444     targetCls: 'x-table-layout-ct',\r
7445 \r
7446     /**\r
7447      * @cfg {Object} tableAttrs\r
7448      * <p>An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification\r
7449      * used to create the layout's <tt>&lt;table&gt;</tt> element. Example:</p><pre><code>\r
7450 {\r
7451     xtype: 'panel',\r
7452     layout: 'table',\r
7453     layoutConfig: {\r
7454         tableAttrs: {\r
7455             style: {\r
7456                 width: '100%'\r
7457             }\r
7458         },\r
7459         columns: 3\r
7460     }\r
7461 }</code></pre>\r
7462      */\r
7463     tableAttrs:null,\r
7464 \r
7465     // private\r
7466     setContainer : function(ct){\r
7467         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);\r
7468 \r
7469         this.currentRow = 0;\r
7470         this.currentColumn = 0;\r
7471         this.cells = [];\r
7472     },\r
7473     \r
7474     // private\r
7475     onLayout : function(ct, target){\r
7476         var cs = ct.items.items, len = cs.length, c, i;\r
7477 \r
7478         if(!this.table){\r
7479             target.addClass('x-table-layout-ct');\r
7480 \r
7481             this.table = target.createChild(\r
7482                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);\r
7483         }\r
7484         this.renderAll(ct, target);\r
7485     },\r
7486 \r
7487     // private\r
7488     getRow : function(index){\r
7489         var row = this.table.tBodies[0].childNodes[index];\r
7490         if(!row){\r
7491             row = document.createElement('tr');\r
7492             this.table.tBodies[0].appendChild(row);\r
7493         }\r
7494         return row;\r
7495     },\r
7496 \r
7497     // private\r
7498     getNextCell : function(c){\r
7499         var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);\r
7500         var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];\r
7501         for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){\r
7502             if(!this.cells[rowIndex]){\r
7503                 this.cells[rowIndex] = [];\r
7504             }\r
7505             for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){\r
7506                 this.cells[rowIndex][colIndex] = true;\r
7507             }\r
7508         }\r
7509         var td = document.createElement('td');\r
7510         if(c.cellId){\r
7511             td.id = c.cellId;\r
7512         }\r
7513         var cls = 'x-table-layout-cell';\r
7514         if(c.cellCls){\r
7515             cls += ' ' + c.cellCls;\r
7516         }\r
7517         td.className = cls;\r
7518         if(c.colspan){\r
7519             td.colSpan = c.colspan;\r
7520         }\r
7521         if(c.rowspan){\r
7522             td.rowSpan = c.rowspan;\r
7523         }\r
7524         this.getRow(curRow).appendChild(td);\r
7525         return td;\r
7526     },\r
7527 \r
7528     // private\r
7529     getNextNonSpan: function(colIndex, rowIndex){\r
7530         var cols = this.columns;\r
7531         while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {\r
7532             if(cols && colIndex >= cols){\r
7533                 rowIndex++;\r
7534                 colIndex = 0;\r
7535             }else{\r
7536                 colIndex++;\r
7537             }\r
7538         }\r
7539         return [colIndex, rowIndex];\r
7540     },\r
7541 \r
7542     // private\r
7543     renderItem : function(c, position, target){\r
7544         // Ensure we have our inner table to get cells to render into.\r
7545         if(!this.table){\r
7546             this.table = target.createChild(\r
7547                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);\r
7548         }\r
7549         if(c && !c.rendered){\r
7550             c.render(this.getNextCell(c));\r
7551             this.configureItem(c, position);\r
7552         }else if(c && !this.isValidParent(c, target)){\r
7553             var container = this.getNextCell(c);\r
7554             container.insertBefore(c.getPositionEl().dom, null);\r
7555             c.container = Ext.get(container);\r
7556             this.configureItem(c, position);\r
7557         }\r
7558     },\r
7559 \r
7560     // private\r
7561     isValidParent : function(c, target){\r
7562         return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);\r
7563     }\r
7564 \r
7565     /**\r
7566      * @property activeItem\r
7567      * @hide\r
7568      */\r
7569 });\r
7570 \r
7571 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;/**
7572  * @class Ext.layout.AbsoluteLayout
7573  * @extends Ext.layout.AnchorLayout
7574  * <p>This is a layout that inherits the anchoring of <b>{@link Ext.layout.AnchorLayout}</b> and adds the
7575  * ability for x/y positioning using the standard x and y component config options.</p>
7576  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
7577  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
7578  * <p>Example usage:</p>
7579  * <pre><code>
7580 var form = new Ext.form.FormPanel({
7581     title: 'Absolute Layout',
7582     layout:'absolute',
7583     layoutConfig: {
7584         // layout-specific configs go here
7585         extraCls: 'x-abs-layout-item',
7586     },
7587     baseCls: 'x-plain',
7588     url:'save-form.php',
7589     defaultType: 'textfield',
7590     items: [{
7591         x: 0,
7592         y: 5,
7593         xtype:'label',
7594         text: 'Send To:'
7595     },{
7596         x: 60,
7597         y: 0,
7598         name: 'to',
7599         anchor:'100%'  // anchor width by percentage
7600     },{
7601         x: 0,
7602         y: 35,
7603         xtype:'label',
7604         text: 'Subject:'
7605     },{
7606         x: 60,
7607         y: 30,
7608         name: 'subject',
7609         anchor: '100%'  // anchor width by percentage
7610     },{
7611         x:0,
7612         y: 60,
7613         xtype: 'textarea',
7614         name: 'msg',
7615         anchor: '100% 100%'  // anchor width and height
7616     }]
7617 });
7618 </code></pre>
7619  */
7620 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
7621
7622     extraCls: 'x-abs-layout-item',
7623
7624     type: 'anchor',
7625
7626     onLayout : function(ct, target){
7627         target.position();
7628         this.paddingLeft = target.getPadding('l');
7629         this.paddingTop = target.getPadding('t');
7630         Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
7631     },
7632
7633     // private
7634     adjustWidthAnchor : function(value, comp){
7635         return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
7636     },
7637
7638     // private
7639     adjustHeightAnchor : function(value, comp){
7640         return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
7641     }
7642     /**
7643      * @property activeItem
7644      * @hide
7645      */
7646 });
7647 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
7648 /**
7649  * @class Ext.layout.BoxLayout
7650  * @extends Ext.layout.ContainerLayout
7651  * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
7652  */
7653 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
7654     /**
7655      * @cfg {Object} defaultMargins
7656      * <p>If the individual contained items do not have a <tt>margins</tt>
7657      * property specified, the default margins from this property will be
7658      * applied to each item.</p>
7659      * <br><p>This property may be specified as an object containing margins
7660      * to apply in the format:</p><pre><code>
7661 {
7662     top: (top margin),
7663     right: (right margin),
7664     bottom: (bottom margin),
7665     left: (left margin)
7666 }</code></pre>
7667      * <p>This property may also be specified as a string containing
7668      * space-separated, numeric margin values. The order of the sides associated
7669      * with each value matches the way CSS processes margin values:</p>
7670      * <div class="mdetail-params"><ul>
7671      * <li>If there is only one value, it applies to all sides.</li>
7672      * <li>If there are two values, the top and bottom borders are set to the
7673      * first value and the right and left are set to the second.</li>
7674      * <li>If there are three values, the top is set to the first value, the left
7675      * and right are set to the second, and the bottom is set to the third.</li>
7676      * <li>If there are four values, they apply to the top, right, bottom, and
7677      * left, respectively.</li>
7678      * </ul></div>
7679      * <p>Defaults to:</p><pre><code>
7680      * {top:0, right:0, bottom:0, left:0}
7681      * </code></pre>
7682      */
7683     defaultMargins : {left:0,top:0,right:0,bottom:0},
7684     /**
7685      * @cfg {String} padding
7686      * <p>Sets the padding to be applied to all child items managed by this layout.</p>
7687      * <p>This property must be specified as a string containing
7688      * space-separated, numeric padding values. The order of the sides associated
7689      * with each value matches the way CSS processes padding values:</p>
7690      * <div class="mdetail-params"><ul>
7691      * <li>If there is only one value, it applies to all sides.</li>
7692      * <li>If there are two values, the top and bottom borders are set to the
7693      * first value and the right and left are set to the second.</li>
7694      * <li>If there are three values, the top is set to the first value, the left
7695      * and right are set to the second, and the bottom is set to the third.</li>
7696      * <li>If there are four values, they apply to the top, right, bottom, and
7697      * left, respectively.</li>
7698      * </ul></div>
7699      * <p>Defaults to: <code>"0"</code></p>
7700      */
7701     padding : '0',
7702     // documented in subclasses
7703     pack : 'start',
7704
7705     // private
7706     monitorResize : true,
7707     type: 'box',
7708     scrollOffset : 0,
7709     extraCls : 'x-box-item',
7710     targetCls : 'x-box-layout-ct',
7711     innerCls : 'x-box-inner',
7712
7713     constructor : function(config){
7714         Ext.layout.BoxLayout.superclass.constructor.call(this, config);
7715         if(Ext.isString(this.defaultMargins)){
7716             this.defaultMargins = this.parseMargins(this.defaultMargins);
7717         }
7718     },
7719
7720     // private
7721     isValidParent : function(c, target){
7722         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
7723     },
7724
7725     // private
7726     renderAll : function(ct, target){
7727         if(!this.innerCt){
7728             // the innerCt prevents wrapping and shuffling while
7729             // the container is resizing
7730             this.innerCt = target.createChild({cls:this.innerCls});
7731             this.padding = this.parseMargins(this.padding);
7732         }
7733         Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
7734     },
7735
7736     onLayout : function(ct, target){
7737         this.renderAll(ct, target);
7738     },
7739
7740     getLayoutTargetSize : function(){
7741         var target = this.container.getLayoutTarget(), ret;
7742         if (target) {
7743             ret = target.getViewSize();
7744             ret.width -= target.getPadding('lr');
7745             ret.height -= target.getPadding('tb');
7746         }
7747         return ret;
7748     },
7749
7750     // private
7751     renderItem : function(c){
7752         if(Ext.isString(c.margins)){
7753             c.margins = this.parseMargins(c.margins);
7754         }else if(!c.margins){
7755             c.margins = this.defaultMargins;
7756         }
7757         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
7758     }
7759 });
7760
7761 /**
7762  * @class Ext.layout.VBoxLayout
7763  * @extends Ext.layout.BoxLayout
7764  * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical
7765  * space between child items containing a numeric <code>flex</code> configuration.</p>
7766  * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option.
7767  */
7768 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
7769     /**
7770      * @cfg {String} align
7771      * Controls how the child items of the container are aligned. Acceptable configuration values for this
7772      * property are:
7773      * <div class="mdetail-params"><ul>
7774      * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally
7775      * at the <b>left</b> side of the container</div></li>
7776      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the
7777      * <b>mid-width</b> of the container</div></li>
7778      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill
7779      * the width of the container</div></li>
7780      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to
7781      * the size of the largest item.</div></li>
7782      * </ul></div>
7783      */
7784     align : 'left', // left, center, stretch, strechmax
7785     type: 'vbox',
7786     /**
7787      * @cfg {String} pack
7788      * Controls how the child items of the container are packed together. Acceptable configuration values
7789      * for this property are:
7790      * <div class="mdetail-params"><ul>
7791      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
7792      * <b>top</b> side of container</div></li>
7793      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
7794      * <b>mid-height</b> of container</div></li>
7795      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>
7796      * side of container</div></li>
7797      * </ul></div>
7798      */
7799     /**
7800      * @cfg {Number} flex
7801      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
7802      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>
7803      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
7804      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
7805      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
7806      */
7807
7808     // private
7809     onLayout : function(ct, target){
7810         Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);
7811
7812         var cs = this.getRenderedItems(ct), csLen = cs.length,
7813             c, i, cm, ch, margin, cl, diff, aw, availHeight,
7814             size = this.getLayoutTargetSize(),
7815             w = size.width,
7816             h = size.height - this.scrollOffset,
7817             l = this.padding.left,
7818             t = this.padding.top,
7819             isStart = this.pack == 'start',
7820             extraHeight = 0,
7821             maxWidth = 0,
7822             totalFlex = 0,
7823             usedHeight = 0,
7824             idx = 0,
7825             heights = [],
7826             restore = [];
7827
7828         // Do only width calculations and apply those first, as they can affect height
7829         for (i = 0 ; i < csLen; i++) {
7830             c = cs[i];
7831             cm = c.margins;
7832             margin = cm.top + cm.bottom;
7833             // Max height for align
7834             maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);
7835         }
7836
7837         var innerCtWidth = maxWidth + this.padding.left + this.padding.right;
7838         switch(this.align){
7839             case 'stretch':
7840                 this.innerCt.setSize(w, h);
7841                 break;
7842             case 'stretchmax':
7843             case 'left':
7844                 this.innerCt.setSize(innerCtWidth, h);
7845                 break;
7846             case 'center':
7847                 this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);
7848                 break;
7849         }
7850
7851         var availableWidth = Math.max(0, w - this.padding.left - this.padding.right);
7852         // Apply widths
7853         for (i = 0 ; i < csLen; i++) {
7854             c = cs[i];
7855             cm = c.margins;
7856             if(this.align == 'stretch'){
7857                 c.setWidth(((w - (this.padding.left + this.padding.right)) - (cm.left + cm.right)).constrain(
7858                     c.minWidth || 0, c.maxWidth || 1000000));
7859             }else if(this.align == 'stretchmax'){
7860                 c.setWidth((maxWidth - (cm.left + cm.right)).constrain(
7861                     c.minWidth || 0, c.maxWidth || 1000000));
7862             }else if(isStart && c.flex){
7863                 c.setWidth();
7864             }
7865
7866         }
7867
7868         // Height calculations
7869         for (i = 0 ; i < csLen; i++) {
7870             c = cs[i];
7871             // Total of all the flex values
7872             totalFlex += c.flex || 0;
7873             // Don't run height calculations on flexed items
7874             if (!c.flex) {
7875                 // Render and layout sub-containers without a flex or height, once
7876                 if (!c.height && !c.hasLayout && c.doLayout) {
7877                     c.doLayout();
7878                 }
7879                 ch = c.getHeight();
7880             } else {
7881                 ch = 0;
7882             }
7883
7884             cm = c.margins;
7885             // Determine how much height is available to flex
7886             extraHeight += ch + cm.top + cm.bottom;
7887         }
7888         // Final avail height calc
7889         availHeight = Math.max(0, (h - extraHeight - this.padding.top - this.padding.bottom));
7890
7891         var leftOver = availHeight;
7892         for (i = 0 ; i < csLen; i++) {
7893             c = cs[i];
7894             if(isStart && c.flex){
7895                 ch = Math.floor(availHeight * (c.flex / totalFlex));
7896                 leftOver -= ch;
7897                 heights.push(ch);
7898             }
7899         }
7900         if(this.pack == 'center'){
7901             t += availHeight ? availHeight / 2 : 0;
7902         }else if(this.pack == 'end'){
7903             t += availHeight;
7904         }
7905         idx = 0;
7906         // Apply heights
7907         for (i = 0 ; i < csLen; i++) {
7908             c = cs[i];
7909             cm = c.margins;
7910             t += cm.top;
7911             aw = availableWidth;
7912             cl = l + cm.left // default left pos
7913
7914             // Adjust left pos for centering
7915             if(this.align == 'center'){
7916                 if((diff = availableWidth - (c.getWidth() + cm.left + cm.right)) > 0){
7917                     cl += (diff/2);
7918                     aw -= diff;
7919                 }
7920             }
7921
7922             c.setPosition(cl, t);
7923             if(isStart && c.flex){
7924                 ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));
7925                 c.setSize(aw, ch);
7926             }else{
7927                 ch = c.getHeight();
7928             }
7929             t += ch + cm.bottom;
7930         }
7931         // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
7932         if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
7933             var ts = this.getLayoutTargetSize();
7934             if (ts.width != size.width || ts.height != size.height){
7935                 this.adjustmentPass = true;
7936                 this.onLayout(ct, target);
7937             }
7938         }
7939         delete this.adjustmentPass;
7940     }
7941 });
7942
7943 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
7944
7945 /**
7946  * @class Ext.layout.HBoxLayout
7947  * @extends Ext.layout.BoxLayout
7948  * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal
7949  * space between child items containing a numeric <code>flex</code> configuration.</p>
7950  * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option.
7951  */
7952 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
7953     /**
7954      * @cfg {String} align
7955      * Controls how the child items of the container are aligned. Acceptable configuration values for this
7956      * property are:
7957      * <div class="mdetail-params"><ul>
7958      * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically
7959      * at the <b>top</b> of the container</div></li>
7960      * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically in the
7961      * <b>middle</b> of the container</div></li>
7962      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill
7963      * the height of the container</div></li>
7964      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to
7965      * the height of the largest item.</div></li>
7966      */
7967     align : 'top', // top, middle, stretch, strechmax
7968     type: 'hbox',
7969     /**
7970      * @cfg {String} pack
7971      * Controls how the child items of the container are packed together. Acceptable configuration values
7972      * for this property are:
7973      * <div class="mdetail-params"><ul>
7974      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
7975      * <b>left</b> side of container</div></li>
7976      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
7977      * <b>mid-width</b> of container</div></li>
7978      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>
7979      * side of container</div></li>
7980      * </ul></div>
7981      */
7982     /**
7983      * @cfg {Number} flex
7984      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
7985      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>
7986      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
7987      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
7988      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
7989      */
7990
7991     // private
7992     onLayout : function(ct, target){
7993         Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);
7994
7995         var cs = this.getRenderedItems(ct), csLen = cs.length,
7996             c, i, cm, cw, ch, diff, availWidth,
7997             size = this.getLayoutTargetSize(),
7998             w = size.width - this.scrollOffset,
7999             h = size.height,
8000             l = this.padding.left,
8001             t = this.padding.top,
8002             isStart = this.pack == 'start',
8003             isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
8004             extraWidth = 0,
8005             maxHeight = 0,
8006             totalFlex = 0,
8007             usedWidth = 0;
8008
8009         for (i = 0 ; i < csLen; i++) {
8010             c = cs[i];
8011             // Total of all the flex values
8012             totalFlex += c.flex || 0;
8013             // Don't run width calculations on flexed items
8014             if (!c.flex) {
8015                 // Render and layout sub-containers without a flex or width, once
8016                 if (!c.width && !c.hasLayout && c.doLayout) {
8017                     c.doLayout();
8018                 }
8019                 cw = c.getWidth();
8020             } else {
8021                 cw = 0;
8022             }
8023             cm = c.margins;
8024             // Determine how much width is available to flex
8025             extraWidth += cw + cm.left + cm.right;
8026             // Max height for align
8027             maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom);
8028         }
8029         // Final avail width calc
8030         availWidth = Math.max(0, (w - extraWidth - this.padding.left - this.padding.right));
8031
8032         var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom;
8033         switch(this.align){
8034             case 'stretch':
8035                 this.innerCt.setSize(w, h);
8036                 break;
8037             case 'stretchmax':
8038             case 'top':
8039                 this.innerCt.setSize(w, innerCtHeight);
8040                 break;
8041             case 'middle':
8042                 this.innerCt.setSize(w, h = Math.max(h, innerCtHeight));
8043                 break;
8044         }
8045
8046         var leftOver = availWidth,
8047             widths = [],
8048             restore = [],
8049             idx = 0,
8050             availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom);
8051
8052         for (i = 0 ; i < csLen; i++) {
8053             c = cs[i];
8054             if(isStart && c.flex){
8055                 cw = Math.floor(availWidth * (c.flex / totalFlex));
8056                 leftOver -= cw;
8057                 widths.push(cw);
8058             }
8059         }
8060
8061         if(this.pack == 'center'){
8062             l += availWidth ? availWidth / 2 : 0;
8063         }else if(this.pack == 'end'){
8064             l += availWidth;
8065         }
8066         for (i = 0 ; i < csLen; i++) {
8067             c = cs[i];
8068             cm = c.margins;
8069             l += cm.left;
8070             c.setPosition(l, t + cm.top);
8071             if(isStart && c.flex){
8072                 cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0));
8073                 if(isRestore){
8074                     restore.push(c.getHeight());
8075                 }
8076                 c.setSize(cw, availableHeight);
8077             }else{
8078                 cw = c.getWidth();
8079             }
8080             l += cw + cm.right;
8081         }
8082
8083         idx = 0;
8084         for (i = 0 ; i < csLen; i++) {
8085             c = cs[i];
8086             cm = c.margins;
8087             ch = c.getHeight();
8088             if(isStart && c.flex){
8089                 ch = restore[idx++];
8090             }
8091             if(this.align == 'stretch'){
8092                 c.setHeight(((h - (this.padding.top + this.padding.bottom)) - (cm.top + cm.bottom)).constrain(
8093                     c.minHeight || 0, c.maxHeight || 1000000));
8094             }else if(this.align == 'stretchmax'){
8095                 c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain(
8096                     c.minHeight || 0, c.maxHeight || 1000000));
8097             }else{
8098                 if(this.align == 'middle'){
8099                     diff = availableHeight - (ch + cm.top + cm.bottom);
8100                     ch = t + cm.top + (diff/2);
8101                     if(diff > 0){
8102                         c.setPosition(c.x, ch);
8103                     }
8104                 }
8105                 if(isStart && c.flex){
8106                     c.setHeight(ch);
8107                 }
8108             }
8109         }
8110         // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
8111         if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
8112             var ts = this.getLayoutTargetSize();
8113             if (ts.width != size.width || ts.height != size.height){
8114                 this.adjustmentPass = true;
8115                 this.onLayout(ct, target);
8116             }
8117         }
8118         delete this.adjustmentPass;
8119     }
8120 });
8121
8122 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
8123 /**
8124  * @class Ext.layout.ToolbarLayout
8125  * @extends Ext.layout.ContainerLayout
8126  * Layout manager implicitly used by Ext.Toolbar.
8127  */
8128 Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
8129     monitorResize : true,
8130     triggerWidth : 18,
8131     lastOverflow : false,
8132
8133     noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
8134
8135     // private
8136     onLayout : function(ct, target){
8137         if(!this.leftTr){
8138             var align = ct.buttonAlign == 'center' ? 'center' : 'left';
8139             target.addClass('x-toolbar-layout-ct');
8140             target.insertHtml('beforeEnd',
8141                  '<table cellspacing="0" class="x-toolbar-ct"><tbody><tr><td class="x-toolbar-left" align="' + align + '"><table cellspacing="0"><tbody><tr class="x-toolbar-left-row"></tr></tbody></table></td><td class="x-toolbar-right" align="right"><table cellspacing="0" class="x-toolbar-right-ct"><tbody><tr><td><table cellspacing="0"><tbody><tr class="x-toolbar-right-row"></tr></tbody></table></td><td><table cellspacing="0"><tbody><tr class="x-toolbar-extras-row"></tr></tbody></table></td></tr></tbody></table></td></tr></tbody></table>');
8142             this.leftTr = target.child('tr.x-toolbar-left-row', true);
8143             this.rightTr = target.child('tr.x-toolbar-right-row', true);
8144             this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
8145         }
8146
8147         var side = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
8148             pos = 0,
8149             items = ct.items.items;
8150
8151         for(var i = 0, len = items.length, c; i < len; i++, pos++) {
8152             c = items[i];
8153             if(c.isFill){
8154                 side = this.rightTr;
8155                 pos = -1;
8156             }else if(!c.rendered){
8157                 c.render(this.insertCell(c, side, pos));
8158             }else{
8159                 if(!c.xtbHidden && !this.isValidParent(c, side.childNodes[pos])){
8160                     var td = this.insertCell(c, side, pos);
8161                     td.appendChild(c.getPositionEl().dom);
8162                     c.container = Ext.get(td);
8163                 }
8164             }
8165         }
8166         //strip extra empty cells
8167         this.cleanup(this.leftTr);
8168         this.cleanup(this.rightTr);
8169         this.cleanup(this.extrasTr);
8170         this.fitToSize(target);
8171     },
8172
8173     cleanup : function(row){
8174         var cn = row.childNodes, i, c;
8175         for(i = cn.length-1; i >= 0 && (c = cn[i]); i--){
8176             if(!c.firstChild){
8177                 row.removeChild(c);
8178             }
8179         }
8180     },
8181
8182     insertCell : function(c, side, pos){
8183         var td = document.createElement('td');
8184         td.className='x-toolbar-cell';
8185         side.insertBefore(td, side.childNodes[pos]||null);
8186         return td;
8187     },
8188
8189     hideItem : function(item){
8190         var h = (this.hiddens = this.hiddens || []);
8191         h.push(item);
8192         item.xtbHidden = true;
8193         item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
8194         item.hide();
8195     },
8196
8197     unhideItem : function(item){
8198         item.show();
8199         item.xtbHidden = false;
8200         this.hiddens.remove(item);
8201         if(this.hiddens.length < 1){
8202             delete this.hiddens;
8203         }
8204     },
8205
8206     getItemWidth : function(c){
8207         return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
8208     },
8209
8210     fitToSize : function(t){
8211         if(this.container.enableOverflow === false){
8212             return;
8213         }
8214         var w = t.dom.clientWidth,
8215             lw = this.lastWidth || 0,
8216             iw = t.dom.firstChild.offsetWidth,
8217             clipWidth = w - this.triggerWidth,
8218             hideIndex = -1;
8219
8220         this.lastWidth = w;
8221
8222         if(iw > w || (this.hiddens && w >= lw)){
8223             var i, items = this.container.items.items,
8224                 len = items.length, c,
8225                 loopWidth = 0;
8226
8227             for(i = 0; i < len; i++) {
8228                 c = items[i];
8229                 if(!c.isFill){
8230                     loopWidth += this.getItemWidth(c);
8231                     if(loopWidth > clipWidth){
8232                         if(!(c.hidden || c.xtbHidden)){
8233                             this.hideItem(c);
8234                         }
8235                     }else if(c.xtbHidden){
8236                         this.unhideItem(c);
8237                     }
8238                 }
8239             }
8240         }
8241         if(this.hiddens){
8242             this.initMore();
8243             if(!this.lastOverflow){
8244                 this.container.fireEvent('overflowchange', this.container, true);
8245                 this.lastOverflow = true;
8246             }
8247         }else if(this.more){
8248             this.clearMenu();
8249             this.more.destroy();
8250             delete this.more;
8251             if(this.lastOverflow){
8252                 this.container.fireEvent('overflowchange', this.container, false);
8253                 this.lastOverflow = false;
8254             }
8255         }
8256     },
8257
8258     createMenuConfig : function(c, hideOnClick){
8259         var cfg = Ext.apply({}, c.initialConfig),
8260             group = c.toggleGroup;
8261
8262         Ext.apply(cfg, {
8263             text: c.overflowText || c.text,
8264             iconCls: c.iconCls,
8265             icon: c.icon,
8266             itemId: c.itemId,
8267             disabled: c.disabled,
8268             handler: c.handler,
8269             scope: c.scope,
8270             menu: c.menu,
8271             hideOnClick: hideOnClick
8272         });
8273         if(group || c.enableToggle){
8274             Ext.apply(cfg, {
8275                 group: group,
8276                 checked: c.pressed,
8277                 listeners: {
8278                     checkchange: function(item, checked){
8279                         c.toggle(checked);
8280                     }
8281                 }
8282             });
8283         }
8284         delete cfg.ownerCt;
8285         delete cfg.xtype;
8286         delete cfg.id;
8287         return cfg;
8288     },
8289
8290     // private
8291     addComponentToMenu : function(m, c){
8292         if(c instanceof Ext.Toolbar.Separator){
8293             m.add('-');
8294         }else if(Ext.isFunction(c.isXType)){
8295             if(c.isXType('splitbutton')){
8296                 m.add(this.createMenuConfig(c, true));
8297             }else if(c.isXType('button')){
8298                 m.add(this.createMenuConfig(c, !c.menu));
8299             }else if(c.isXType('buttongroup')){
8300                 c.items.each(function(item){
8301                      this.addComponentToMenu(m, item);
8302                 }, this);
8303             }
8304         }
8305     },
8306
8307     clearMenu : function(){
8308         var m = this.moreMenu;
8309         if(m && m.items){
8310             m.items.each(function(item){
8311                 delete item.menu;
8312             });
8313         }
8314     },
8315
8316     // private
8317     beforeMoreShow : function(m){
8318         var h = this.container.items.items,
8319             len = h.length,
8320             c,
8321             prev,
8322             needsSep = function(group, item){
8323                 return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
8324             };
8325
8326         this.clearMenu();
8327         m.removeAll();
8328         for(var i = 0; i < len; i++){
8329             c = h[i];
8330             if(c.xtbHidden){
8331                 if(prev && (needsSep(c, prev) || needsSep(prev, c))){
8332                     m.add('-');
8333                 }
8334                 this.addComponentToMenu(m, c);
8335                 prev = c;
8336             }
8337         }
8338         // put something so the menu isn't empty
8339         // if no compatible items found
8340         if(m.items.length < 1){
8341             m.add(this.noItemsMenuText);
8342         }
8343     },
8344
8345     initMore : function(){
8346         if(!this.more){
8347             this.moreMenu = new Ext.menu.Menu({
8348                 ownerCt : this.container,
8349                 listeners: {
8350                     beforeshow: this.beforeMoreShow,
8351                     scope: this
8352                 }
8353
8354             });
8355             this.more = new Ext.Button({
8356                 iconCls : 'x-toolbar-more-icon',
8357                 cls     : 'x-toolbar-more',
8358                 menu    : this.moreMenu,
8359                 ownerCt : this.container
8360             });
8361             var td = this.insertCell(this.more, this.extrasTr, 100);
8362             this.more.render(td);
8363         }
8364     },
8365
8366     destroy : function(){
8367         Ext.destroy(this.more, this.moreMenu);
8368         delete this.leftTr;
8369         delete this.rightTr;
8370         delete this.extrasTr;
8371         Ext.layout.ToolbarLayout.superclass.destroy.call(this);
8372     }
8373 });
8374
8375 Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;/**
8376  * @class Ext.layout.MenuLayout
8377  * @extends Ext.layout.ContainerLayout
8378  * <p>Layout manager used by {@link Ext.menu.Menu}. Generally this class should not need to be used directly.</p>
8379  */
8380  Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
8381     monitorResize : true,
8382
8383     setContainer : function(ct){
8384         this.monitorResize = !ct.floating;
8385         // This event is only fired by the menu in IE, used so we don't couple
8386         // the menu with the layout.
8387         ct.on('autosize', this.doAutoSize, this);
8388         Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
8389     },
8390
8391     renderItem : function(c, position, target){
8392         if (!this.itemTpl) {
8393             this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
8394                 '<li id="{itemId}" class="{itemCls}">',
8395                     '<tpl if="needsIcon">',
8396                         '<img src="{icon}" class="{iconCls}"/>',
8397                     '</tpl>',
8398                 '</li>'
8399             );
8400         }
8401
8402         if(c && !c.rendered){
8403             if(Ext.isNumber(position)){
8404                 position = target.dom.childNodes[position];
8405             }
8406             var a = this.getItemArgs(c);
8407
8408 //          The Component's positionEl is the <li> it is rendered into
8409             c.render(c.positionEl = position ?
8410                 this.itemTpl.insertBefore(position, a, true) :
8411                 this.itemTpl.append(target, a, true));
8412
8413 //          Link the containing <li> to the item.
8414             c.positionEl.menuItemId = c.getItemId();
8415
8416 //          If rendering a regular Component, and it needs an icon,
8417 //          move the Component rightwards.
8418             if (!a.isMenuItem && a.needsIcon) {
8419                 c.positionEl.addClass('x-menu-list-item-indent');
8420             }
8421             this.configureItem(c, position);
8422         }else if(c && !this.isValidParent(c, target)){
8423             if(Ext.isNumber(position)){
8424                 position = target.dom.childNodes[position];
8425             }
8426             target.dom.insertBefore(c.getActionEl().dom, position || null);
8427         }
8428     },
8429
8430     getItemArgs : function(c) {
8431         var isMenuItem = c instanceof Ext.menu.Item;
8432         return {
8433             isMenuItem: isMenuItem,
8434             needsIcon: !isMenuItem && (c.icon || c.iconCls),
8435             icon: c.icon || Ext.BLANK_IMAGE_URL,
8436             iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
8437             itemId: 'x-menu-el-' + c.id,
8438             itemCls: 'x-menu-list-item '
8439         };
8440     },
8441
8442     //  Valid if the Component is in a <li> which is part of our target <ul>
8443     isValidParent : function(c, target) {
8444         return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
8445     },
8446
8447     onLayout : function(ct, target){
8448         Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
8449         this.doAutoSize();
8450     },
8451
8452     doAutoSize : function(){
8453         var ct = this.container, w = ct.width;
8454         if(ct.floating){
8455             if(w){
8456                 ct.setWidth(w);
8457             }else if(Ext.isIE){
8458                 ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
8459                 var el = ct.getEl(), t = el.dom.offsetWidth; // force recalc
8460                 ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
8461             }
8462         }
8463     }
8464 });
8465 Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;/**\r
8466  * @class Ext.Viewport\r
8467  * @extends Ext.Container\r
8468  * <p>A specialized container representing the viewable application area (the browser viewport).</p>\r
8469  * <p>The Viewport renders itself to the document body, and automatically sizes itself to the size of\r
8470  * the browser viewport and manages window resizing. There may only be one Viewport created\r
8471  * in a page. Inner layouts are available by virtue of the fact that all {@link Ext.Panel Panel}s\r
8472  * added to the Viewport, either through its {@link #items}, or through the items, or the {@link #add}\r
8473  * method of any of its child Panels may themselves have a layout.</p>\r
8474  * <p>The Viewport does not provide scrolling, so child Panels within the Viewport should provide\r
8475  * for scrolling if needed using the {@link #autoScroll} config.</p>\r
8476  * <p>An example showing a classic application border layout:</p><pre><code>\r
8477 new Ext.Viewport({\r
8478     layout: 'border',\r
8479     items: [{\r
8480         region: 'north',\r
8481         html: '&lt;h1 class="x-panel-header">Page Title&lt;/h1>',\r
8482         autoHeight: true,\r
8483         border: false,\r
8484         margins: '0 0 5 0'\r
8485     }, {\r
8486         region: 'west',\r
8487         collapsible: true,\r
8488         title: 'Navigation',\r
8489         width: 200\r
8490         // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout}\r
8491     }, {\r
8492         region: 'south',\r
8493         title: 'Title for Panel',\r
8494         collapsible: true,\r
8495         html: 'Information goes here',\r
8496         split: true,\r
8497         height: 100,\r
8498         minHeight: 100\r
8499     }, {\r
8500         region: 'east',\r
8501         title: 'Title for the Grid Panel',\r
8502         collapsible: true,\r
8503         split: true,\r
8504         width: 200,\r
8505         xtype: 'grid',\r
8506         // remaining grid configuration not shown ...\r
8507         // notice that the GridPanel is added directly as the region\r
8508         // it is not "overnested" inside another Panel\r
8509     }, {\r
8510         region: 'center',\r
8511         xtype: 'tabpanel', // TabPanel itself has no title\r
8512         items: {\r
8513             title: 'Default Tab',\r
8514             html: 'The first tab\'s content. Others may be added dynamically'\r
8515         }\r
8516     }]\r
8517 });\r
8518 </code></pre>\r
8519  * @constructor\r
8520  * Create a new Viewport\r
8521  * @param {Object} config The config object\r
8522  * @xtype viewport\r
8523  */\r
8524 Ext.Viewport = Ext.extend(Ext.Container, {\r
8525     /*\r
8526      * Privatize config options which, if used, would interfere with the\r
8527      * correct operation of the Viewport as the sole manager of the\r
8528      * layout of the document body.\r
8529      */\r
8530     /**\r
8531      * @cfg {Mixed} applyTo @hide\r
8532      */\r
8533     /**\r
8534      * @cfg {Boolean} allowDomMove @hide\r
8535      */\r
8536     /**\r
8537      * @cfg {Boolean} hideParent @hide\r
8538      */\r
8539     /**\r
8540      * @cfg {Mixed} renderTo @hide\r
8541      */\r
8542     /**\r
8543      * @cfg {Boolean} hideParent @hide\r
8544      */\r
8545     /**\r
8546      * @cfg {Number} height @hide\r
8547      */\r
8548     /**\r
8549      * @cfg {Number} width @hide\r
8550      */\r
8551     /**\r
8552      * @cfg {Boolean} autoHeight @hide\r
8553      */\r
8554     /**\r
8555      * @cfg {Boolean} autoWidth @hide\r
8556      */\r
8557     /**\r
8558      * @cfg {Boolean} deferHeight @hide\r
8559      */\r
8560     /**\r
8561      * @cfg {Boolean} monitorResize @hide\r
8562      */\r
8563 \r
8564     initComponent : function() {\r
8565         Ext.Viewport.superclass.initComponent.call(this);\r
8566         document.getElementsByTagName('html')[0].className += ' x-viewport';\r
8567         this.el = Ext.getBody();\r
8568         this.el.setHeight = Ext.emptyFn;\r
8569         this.el.setWidth = Ext.emptyFn;\r
8570         this.el.setSize = Ext.emptyFn;\r
8571         this.el.dom.scroll = 'no';\r
8572         this.allowDomMove = false;\r
8573         this.autoWidth = true;\r
8574         this.autoHeight = true;\r
8575         Ext.EventManager.onWindowResize(this.fireResize, this);\r
8576         this.renderTo = this.el;\r
8577     },\r
8578 \r
8579     fireResize : function(w, h){\r
8580         this.fireEvent('resize', this, w, h, w, h);\r
8581     }\r
8582 });\r
8583 Ext.reg('viewport', Ext.Viewport);\r
8584 /**
8585  * @class Ext.Panel
8586  * @extends Ext.Container
8587  * <p>Panel is a container that has specific functionality and structural components that make
8588  * it the perfect building block for application-oriented user interfaces.</p>
8589  * <p>Panels are, by virtue of their inheritance from {@link Ext.Container}, capable
8590  * of being configured with a {@link Ext.Container#layout layout}, and containing child Components.</p>
8591  * <p>When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.Container#add adding} Components
8592  * to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether
8593  * 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
8594  * default, Panels use the {@link Ext.layout.ContainerLayout ContainerLayout} scheme. This simply renders
8595  * child components, appending them one after the other inside the Container, and <b>does not apply any sizing</b>
8596  * at all.</p>
8597  * <p>A Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate
8598  * {@link #header}, {@link #footer} and {@link #body} sections (see {@link #frame} for additional
8599  * information).</p>
8600  * <p>Panel also provides built-in {@link #collapsible expandable and collapsible behavior}, along with
8601  * a variety of {@link #tools prebuilt tool buttons} that can be wired up to provide other customized
8602  * behavior.  Panels can be easily dropped into any {@link Ext.Container Container} or layout, and the
8603  * layout and rendering pipeline is {@link Ext.Container#add completely managed by the framework}.</p>
8604  * @constructor
8605  * @param {Object} config The config object
8606  * @xtype panel
8607  */
8608 Ext.Panel = Ext.extend(Ext.Container, {
8609     /**
8610      * The Panel's header {@link Ext.Element Element}. Read-only.
8611      * <p>This Element is used to house the {@link #title} and {@link #tools}</p>
8612      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
8613      * @type Ext.Element
8614      * @property header
8615      */
8616     /**
8617      * The Panel's body {@link Ext.Element Element} which may be used to contain HTML content.
8618      * The content may be specified in the {@link #html} config, or it may be loaded using the
8619      * {@link autoLoad} config, or through the Panel's {@link #getUpdater Updater}. Read-only.
8620      * <p>If this is used to load visible HTML elements in either way, then
8621      * the Panel may not be used as a Layout for hosting nested Panels.</p>
8622      * <p>If this Panel is intended to be used as the host of a Layout (See {@link #layout}
8623      * then the body Element must not be loaded or changed - it is under the control
8624      * of the Panel's Layout.
8625      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
8626      * @type Ext.Element
8627      * @property body
8628      */
8629     /**
8630      * The Panel's bwrap {@link Ext.Element Element} used to contain other Panel elements
8631      * (tbar, body, bbar, footer). See {@link #bodyCfg}. Read-only.
8632      * @type Ext.Element
8633      * @property bwrap
8634      */
8635     /**
8636      * True if this panel is collapsed. Read-only.
8637      * @type Boolean
8638      * @property collapsed
8639      */
8640     /**
8641      * @cfg {Object} bodyCfg
8642      * <p>A {@link Ext.DomHelper DomHelper} element specification object may be specified for any
8643      * Panel Element.</p>
8644      * <p>By default, the Default element in the table below will be used for the html markup to
8645      * create a child element with the commensurate Default class name (<code>baseCls</code> will be
8646      * replaced by <code>{@link #baseCls}</code>):</p>
8647      * <pre>
8648      * Panel      Default  Default             Custom      Additional       Additional
8649      * Element    element  class               element     class            style
8650      * ========   ==========================   =========   ==============   ===========
8651      * {@link #header}     div      {@link #baseCls}+'-header'   {@link #headerCfg}   headerCssClass   headerStyle
8652      * {@link #bwrap}      div      {@link #baseCls}+'-bwrap'     {@link #bwrapCfg}    bwrapCssClass    bwrapStyle
8653      * + tbar     div      {@link #baseCls}+'-tbar'       {@link #tbarCfg}     tbarCssClass     tbarStyle
8654      * + {@link #body}     div      {@link #baseCls}+'-body'       {@link #bodyCfg}     {@link #bodyCssClass}     {@link #bodyStyle}
8655      * + bbar     div      {@link #baseCls}+'-bbar'       {@link #bbarCfg}     bbarCssClass     bbarStyle
8656      * + {@link #footer}   div      {@link #baseCls}+'-footer'   {@link #footerCfg}   footerCssClass   footerStyle
8657      * </pre>
8658      * <p>Configuring a Custom element may be used, for example, to force the {@link #body} Element
8659      * to use a different form of markup than is created by default. An example of this might be
8660      * to {@link Ext.Element#createChild create a child} Panel containing a custom content, such as
8661      * a header, or forcing centering of all Panel content by having the body be a &lt;center&gt;
8662      * element:</p>
8663      * <pre><code>
8664 new Ext.Panel({
8665     title: 'Message Title',
8666     renderTo: Ext.getBody(),
8667     width: 200, height: 130,
8668     <b>bodyCfg</b>: {
8669         tag: 'center',
8670         cls: 'x-panel-body',  // Default class not applied if Custom element specified
8671         html: 'Message'
8672     },
8673     footerCfg: {
8674         tag: 'h2',
8675         cls: 'x-panel-footer'        // same as the Default class
8676         html: 'footer html'
8677     },
8678     footerCssClass: 'custom-footer', // additional css class, see {@link Ext.element#addClass addClass}
8679     footerStyle:    'background-color:red' // see {@link #bodyStyle}
8680 });
8681      * </code></pre>
8682      * <p>The example above also explicitly creates a <code>{@link #footer}</code> with custom markup and
8683      * styling applied.</p>
8684      */
8685     /**
8686      * @cfg {Object} headerCfg
8687      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
8688      * of this Panel's {@link #header} Element.  See <code>{@link #bodyCfg}</code> also.</p>
8689      */
8690     /**
8691      * @cfg {Object} bwrapCfg
8692      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
8693      * of this Panel's {@link #bwrap} Element.  See <code>{@link #bodyCfg}</code> also.</p>
8694      */
8695     /**
8696      * @cfg {Object} tbarCfg
8697      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
8698      * of this Panel's {@link #tbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
8699      */
8700     /**
8701      * @cfg {Object} bbarCfg
8702      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
8703      * of this Panel's {@link #bbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
8704      */
8705     /**
8706      * @cfg {Object} footerCfg
8707      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
8708      * of this Panel's {@link #footer} Element.  See <code>{@link #bodyCfg}</code> also.</p>
8709      */
8710     /**
8711      * @cfg {Boolean} closable
8712      * Panels themselves do not directly support being closed, but some Panel subclasses do (like
8713      * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}.  Specify <code>true</code>
8714      * to enable closing in such situations. Defaults to <code>false</code>.
8715      */
8716     /**
8717      * The Panel's footer {@link Ext.Element Element}. Read-only.
8718      * <p>This Element is used to house the Panel's <code>{@link #buttons}</code> or <code>{@link #fbar}</code>.</p>
8719      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
8720      * @type Ext.Element
8721      * @property footer
8722      */
8723     /**
8724      * @cfg {Mixed} applyTo
8725      * <p>The id of the node, a DOM node or an existing Element corresponding to a DIV that is already present in
8726      * the document that specifies some panel-specific structural markup.  When <code>applyTo</code> is used,
8727      * constituent parts of the panel can be specified by CSS class name within the main element, and the panel
8728      * will automatically create those components from that markup. Any required components not specified in the
8729      * markup will be autogenerated if necessary.</p>
8730      * <p>The following class names are supported (baseCls will be replaced by {@link #baseCls}):</p>
8731      * <ul><li>baseCls + '-header'</li>
8732      * <li>baseCls + '-header-text'</li>
8733      * <li>baseCls + '-bwrap'</li>
8734      * <li>baseCls + '-tbar'</li>
8735      * <li>baseCls + '-body'</li>
8736      * <li>baseCls + '-bbar'</li>
8737      * <li>baseCls + '-footer'</li></ul>
8738      * <p>Using this config, a call to render() is not required.  If applyTo is specified, any value passed for
8739      * {@link #renderTo} will be ignored and the target element's parent node will automatically be used as the
8740      * panel's container.</p>
8741      */
8742     /**
8743      * @cfg {Object/Array} tbar
8744      * <p>The top toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
8745      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
8746      * To access the top toolbar after render, use {@link #getTopToolbar}.</p>
8747      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
8748      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
8749      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
8750      * submission parameters are collected from the DOM tree.</p>
8751      */
8752     /**
8753      * @cfg {Object/Array} bbar
8754      * <p>The bottom toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
8755      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
8756      * To access the bottom toolbar after render, use {@link #getBottomToolbar}.</p>
8757      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
8758      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
8759      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
8760      * submission parameters are collected from the DOM tree.</p>
8761      */
8762     /** @cfg {Object/Array} fbar
8763      * <p>A {@link Ext.Toolbar Toolbar} object, a Toolbar config, or an array of
8764      * {@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>
8765      * <p>After render, the <code>fbar</code> property will be an {@link Ext.Toolbar Toolbar} instance.</p>
8766      * <p>If <code>{@link #buttons}</code> are specified, they will supersede the <code>fbar</code> configuration property.</p>
8767      * The Panel's <code>{@link #buttonAlign}</code> configuration affects the layout of these items, for example:
8768      * <pre><code>
8769 var w = new Ext.Window({
8770     height: 250,
8771     width: 500,
8772     bbar: new Ext.Toolbar({
8773         items: [{
8774             text: 'bbar Left'
8775         },'->',{
8776             text: 'bbar Right'
8777         }]
8778     }),
8779     {@link #buttonAlign}: 'left', // anything but 'center' or 'right' and you can use '-', and '->'
8780                                   // to control the alignment of fbar items
8781     fbar: [{
8782         text: 'fbar Left'
8783     },'->',{
8784         text: 'fbar Right'
8785     }]
8786 }).show();
8787      * </code></pre>
8788      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
8789      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
8790      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
8791      * submission parameters are collected from the DOM tree.</p>
8792      */
8793     /**
8794      * @cfg {Boolean} header
8795      * <code>true</code> to create the Panel's header element explicitly, <code>false</code> to skip creating
8796      * it.  If a <code>{@link #title}</code> is set the header will be created automatically, otherwise it will not.
8797      * If a <code>{@link #title}</code> is set but <code>header</code> is explicitly set to <code>false</code>, the header
8798      * will not be rendered.
8799      */
8800     /**
8801      * @cfg {Boolean} footer
8802      * <code>true</code> to create the footer element explicitly, false to skip creating it. The footer
8803      * will be created automatically if <code>{@link #buttons}</code> or a <code>{@link #fbar}</code> have
8804      * been configured.  See <code>{@link #bodyCfg}</code> for an example.
8805      */
8806     /**
8807      * @cfg {String} title
8808      * The title text to be used as innerHTML (html tags are accepted) to display in the panel
8809      * <code>{@link #header}</code> (defaults to ''). When a <code>title</code> is specified the
8810      * <code>{@link #header}</code> element will automatically be created and displayed unless
8811      * {@link #header} is explicitly set to <code>false</code>.  If you do not want to specify a
8812      * <code>title</code> at config time, but you may want one later, you must either specify a non-empty
8813      * <code>title</code> (a blank space ' ' will do) or <code>header:true</code> so that the container
8814      * element will get created.
8815      */
8816     /**
8817      * @cfg {Array} buttons
8818      * <code>buttons</code> will be used as <code>{@link Ext.Container#items items}</code> for the toolbar in
8819      * the footer (<code>{@link #fbar}</code>). Typically the value of this configuration property will be
8820      * an array of {@link Ext.Button}s or {@link Ext.Button} configuration objects.
8821      * If an item is configured with <code>minWidth</code> or the Panel is configured with <code>minButtonWidth</code>,
8822      * that width will be applied to the item.
8823      */
8824     /**
8825      * @cfg {Object/String/Function} autoLoad
8826      * A valid url spec according to the Updater {@link Ext.Updater#update} method.
8827      * If autoLoad is not null, the panel will attempt to load its contents
8828      * immediately upon render.<p>
8829      * The URL will become the default URL for this panel's {@link #body} element,
8830      * so it may be {@link Ext.Element#refresh refresh}ed at any time.</p>
8831      */
8832     /**
8833      * @cfg {Boolean} frame
8834      * <code>false</code> by default to render with plain 1px square borders. <code>true</code> to render with
8835      * 9 elements, complete with custom rounded corners (also see {@link Ext.Element#boxWrap}).
8836      * <p>The template generated for each condition is depicted below:</p><pre><code>
8837      *
8838 // frame = false
8839 &lt;div id="developer-specified-id-goes-here" class="x-panel">
8840
8841     &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:false)&lt;/span>&lt;/div>
8842
8843     &lt;div class="x-panel-bwrap">
8844         &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
8845     &lt;/div>
8846 &lt;/div>
8847
8848 // frame = true (create 9 elements)
8849 &lt;div id="developer-specified-id-goes-here" class="x-panel">
8850     &lt;div class="x-panel-tl">&lt;div class="x-panel-tr">&lt;div class="x-panel-tc">
8851         &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:true)&lt;/span>&lt;/div>
8852     &lt;/div>&lt;/div>&lt;/div>
8853
8854     &lt;div class="x-panel-bwrap">
8855         &lt;div class="x-panel-ml">&lt;div class="x-panel-mr">&lt;div class="x-panel-mc">
8856             &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
8857         &lt;/div>&lt;/div>&lt;/div>
8858
8859         &lt;div class="x-panel-bl">&lt;div class="x-panel-br">&lt;div class="x-panel-bc"/>
8860         &lt;/div>&lt;/div>&lt;/div>
8861 &lt;/div>
8862      * </code></pre>
8863      */
8864     /**
8865      * @cfg {Boolean} border
8866      * True to display the borders of the panel's body element, false to hide them (defaults to true).  By default,
8867      * the border is a 2px wide inset border, but this can be further altered by setting {@link #bodyBorder} to false.
8868      */
8869     /**
8870      * @cfg {Boolean} bodyBorder
8871      * True to display an interior border on the body element of the panel, false to hide it (defaults to true).
8872      * This only applies when {@link #border} == true.  If border == true and bodyBorder == false, the border will display
8873      * as a 1px wide inset border, giving the entire body element an inset appearance.
8874      */
8875     /**
8876      * @cfg {String/Object/Function} bodyCssClass
8877      * Additional css class selector to be applied to the {@link #body} element in the format expected by
8878      * {@link Ext.Element#addClass} (defaults to null). See {@link #bodyCfg}.
8879      */
8880     /**
8881      * @cfg {String/Object/Function} bodyStyle
8882      * Custom CSS styles to be applied to the {@link #body} element in the format expected by
8883      * {@link Ext.Element#applyStyles} (defaults to null). See {@link #bodyCfg}.
8884      */
8885     /**
8886      * @cfg {String} iconCls
8887      * The CSS class selector that specifies a background image to be used as the header icon (defaults to '').
8888      * <p>An example of specifying a custom icon class would be something like:
8889      * </p><pre><code>
8890 // specify the property in the config for the class:
8891      ...
8892      iconCls: 'my-icon'
8893
8894 // css class that specifies background image to be used as the icon image:
8895 .my-icon { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
8896 </code></pre>
8897      */
8898     /**
8899      * @cfg {Boolean} collapsible
8900      * True to make the panel collapsible and have the expand/collapse toggle button automatically rendered into
8901      * the header tool button area, false to keep the panel statically sized with no button (defaults to false).
8902      */
8903     /**
8904      * @cfg {Array} tools
8905      * An array of tool button configs to be added to the header tool area. When rendered, each tool is
8906      * stored as an {@link Ext.Element Element} referenced by a public property called <code><b></b>tools.<i>&lt;tool-type&gt;</i></code>
8907      * <p>Each tool config may contain the following properties:
8908      * <div class="mdetail-params"><ul>
8909      * <li><b>id</b> : String<div class="sub-desc"><b>Required.</b> The type
8910      * 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
8911      * resulting tool Element. Ext provides CSS rules, and an icon sprite containing images for the tool types listed below.
8912      * The developer may implement custom tools by supplying alternate CSS rules and background images:
8913      * <ul>
8914      * <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>
8915      * <div class="x-tool x-tool-close" style="float:left; margin-right:5;"> </div><div><code> close</code></div>
8916      * <div class="x-tool x-tool-minimize" style="float:left; margin-right:5;"> </div><div><code> minimize</code></div>
8917      * <div class="x-tool x-tool-maximize" style="float:left; margin-right:5;"> </div><div><code> maximize</code></div>
8918      * <div class="x-tool x-tool-restore" style="float:left; margin-right:5;"> </div><div><code> restore</code></div>
8919      * <div class="x-tool x-tool-gear" style="float:left; margin-right:5;"> </div><div><code> gear</code></div>
8920      * <div class="x-tool x-tool-pin" style="float:left; margin-right:5;"> </div><div><code> pin</code></div>
8921      * <div class="x-tool x-tool-unpin" style="float:left; margin-right:5;"> </div><div><code> unpin</code></div>
8922      * <div class="x-tool x-tool-right" style="float:left; margin-right:5;"> </div><div><code> right</code></div>
8923      * <div class="x-tool x-tool-left" style="float:left; margin-right:5;"> </div><div><code> left</code></div>
8924      * <div class="x-tool x-tool-up" style="float:left; margin-right:5;"> </div><div><code> up</code></div>
8925      * <div class="x-tool x-tool-down" style="float:left; margin-right:5;"> </div><div><code> down</code></div>
8926      * <div class="x-tool x-tool-refresh" style="float:left; margin-right:5;"> </div><div><code> refresh</code></div>
8927      * <div class="x-tool x-tool-minus" style="float:left; margin-right:5;"> </div><div><code> minus</code></div>
8928      * <div class="x-tool x-tool-plus" style="float:left; margin-right:5;"> </div><div><code> plus</code></div>
8929      * <div class="x-tool x-tool-help" style="float:left; margin-right:5;"> </div><div><code> help</code></div>
8930      * <div class="x-tool x-tool-search" style="float:left; margin-right:5;"> </div><div><code> search</code></div>
8931      * <div class="x-tool x-tool-save" style="float:left; margin-right:5;"> </div><div><code> save</code></div>
8932      * <div class="x-tool x-tool-print" style="float:left; margin-right:5;"> </div><div><code> print</code></div>
8933      * </ul></div></li>
8934      * <li><b>handler</b> : Function<div class="sub-desc"><b>Required.</b> The function to
8935      * call when clicked. Arguments passed are:<ul>
8936      * <li><b>event</b> : Ext.EventObject<div class="sub-desc">The click event.</div></li>
8937      * <li><b>toolEl</b> : Ext.Element<div class="sub-desc">The tool Element.</div></li>
8938      * <li><b>panel</b> : Ext.Panel<div class="sub-desc">The host Panel</div></li>
8939      * <li><b>tc</b> : Object<div class="sub-desc">The tool configuration object</div></li>
8940      * </ul></div></li>
8941      * <li><b>stopEvent</b> : Boolean<div class="sub-desc">Defaults to true. Specify as false to allow click event to propagate.</div></li>
8942      * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the handler.</div></li>
8943      * <li><b>qtip</b> : String/Object<div class="sub-desc">A tip string, or
8944      * a config argument to {@link Ext.QuickTip#register}</div></li>
8945      * <li><b>hidden</b> : Boolean<div class="sub-desc">True to initially render hidden.</div></li>
8946      * <li><b>on</b> : Object<div class="sub-desc">A listener config object specifiying
8947      * event listeners in the format of an argument to {@link #addListener}</div></li>
8948      * </ul></div>
8949      * <p>Note that, apart from the toggle tool which is provided when a panel is collapsible, these
8950      * tools only provide the visual button. Any required functionality must be provided by adding
8951      * handlers that implement the necessary behavior.</p>
8952      * <p>Example usage:</p>
8953      * <pre><code>
8954 tools:[{
8955     id:'refresh',
8956     qtip: 'Refresh form Data',
8957     // hidden:true,
8958     handler: function(event, toolEl, panel){
8959         // refresh logic
8960     }
8961 },
8962 {
8963     id:'help',
8964     qtip: 'Get Help',
8965     handler: function(event, toolEl, panel){
8966         // whatever
8967     }
8968 }]
8969 </code></pre>
8970      * <p>For the custom id of <code>'help'</code> define two relevant css classes with a link to
8971      * a 15x15 image:</p>
8972      * <pre><code>
8973 .x-tool-help {background-image: url(images/help.png);}
8974 .x-tool-help-over {background-image: url(images/help_over.png);}
8975 // if using an image sprite:
8976 .x-tool-help {background-image: url(images/help.png) no-repeat 0 0;}
8977 .x-tool-help-over {background-position:-15px 0;}
8978 </code></pre>
8979      */
8980     /**
8981      * @cfg {Ext.Template/Ext.XTemplate} toolTemplate
8982      * <p>A Template used to create {@link #tools} in the {@link #header} Element. Defaults to:</p><pre><code>
8983 new Ext.Template('&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>')</code></pre>
8984      * <p>This may may be overridden to provide a custom DOM structure for tools based upon a more
8985      * complex XTemplate. The template's data is a single tool configuration object (Not the entire Array)
8986      * as specified in {@link #tools}.  In the following example an &lt;a> tag is used to provide a
8987      * visual indication when hovering over the tool:</p><pre><code>
8988 var win = new Ext.Window({
8989     tools: [{
8990         id: 'download',
8991         href: '/MyPdfDoc.pdf'
8992     }],
8993     toolTemplate: new Ext.XTemplate(
8994         '&lt;tpl if="id==\'download\'">',
8995             '&lt;a class="x-tool x-tool-pdf" href="{href}">&lt;/a>',
8996         '&lt;/tpl>',
8997         '&lt;tpl if="id!=\'download\'">',
8998             '&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>',
8999         '&lt;/tpl>'
9000     ),
9001     width:500,
9002     height:300,
9003     closeAction:'hide'
9004 });</code></pre>
9005      * <p>Note that the CSS class 'x-tool-pdf' should have an associated style rule which provides an
9006      * appropriate background image, something like:</p>
9007     <pre><code>
9008     a.x-tool-pdf {background-image: url(../shared/extjs/images/pdf.gif)!important;}
9009     </code></pre>
9010      */
9011     /**
9012      * @cfg {Boolean} hideCollapseTool
9013      * <code>true</code> to hide the expand/collapse toggle button when <code>{@link #collapsible} == true</code>,
9014      * <code>false</code> to display it (defaults to <code>false</code>).
9015      */
9016     /**
9017      * @cfg {Boolean} titleCollapse
9018      * <code>true</code> to allow expanding and collapsing the panel (when <code>{@link #collapsible} = true</code>)
9019      * by clicking anywhere in the header bar, <code>false</code>) to allow it only by clicking to tool button
9020      * (defaults to <code>false</code>)). If this panel is a child item of a border layout also see the
9021      * {@link Ext.layout.BorderLayout.Region BorderLayout.Region}
9022      * <code>{@link Ext.layout.BorderLayout.Region#floatable floatable}</code> config option.
9023      */
9024
9025     /**
9026      * @cfg {Mixed} floating
9027      * <p>This property is used to configure the underlying {@link Ext.Layer}. Acceptable values for this
9028      * configuration property are:</p><div class="mdetail-params"><ul>
9029      * <li><b><code>false</code></b> : <b>Default.</b><div class="sub-desc">Display the panel inline where it is
9030      * rendered.</div></li>
9031      * <li><b><code>true</code></b> : <div class="sub-desc">Float the panel (absolute position it with automatic
9032      * shimming and shadow).<ul>
9033      * <div class="sub-desc">Setting floating to true will create an Ext.Layer for this panel and display the
9034      * panel at negative offsets so that it is hidden.</div>
9035      * <div class="sub-desc">Since the panel will be absolute positioned, the position must be set explicitly
9036      * <i>after</i> render (e.g., <code>myPanel.setPosition(100,100);</code>).</div>
9037      * <div class="sub-desc"><b>Note</b>: when floating a panel you should always assign a fixed width,
9038      * otherwise it will be auto width and will expand to fill to the right edge of the viewport.</div>
9039      * </ul></div></li>
9040      * <li><b><code>{@link Ext.Layer object}</code></b> : <div class="sub-desc">The specified object will be used
9041      * as the configuration object for the {@link Ext.Layer} that will be created.</div></li>
9042      * </ul></div>
9043      */
9044     /**
9045      * @cfg {Boolean/String} shadow
9046      * <code>true</code> (or a valid Ext.Shadow {@link Ext.Shadow#mode} value) to display a shadow behind the
9047      * panel, <code>false</code> to display no shadow (defaults to <code>'sides'</code>).  Note that this option
9048      * only applies when <code>{@link #floating} = true</code>.
9049      */
9050     /**
9051      * @cfg {Number} shadowOffset
9052      * The number of pixels to offset the shadow if displayed (defaults to <code>4</code>). Note that this
9053      * option only applies when <code>{@link #floating} = true</code>.
9054      */
9055     /**
9056      * @cfg {Boolean} shim
9057      * <code>false</code> to disable the iframe shim in browsers which need one (defaults to <code>true</code>).
9058      * Note that this option only applies when <code>{@link #floating} = true</code>.
9059      */
9060     /**
9061      * @cfg {Object/Array} keys
9062      * A {@link Ext.KeyMap} config object (in the format expected by {@link Ext.KeyMap#addBinding}
9063      * used to assign custom key handling to this panel (defaults to <code>null</code>).
9064      */
9065     /**
9066      * @cfg {Boolean/Object} draggable
9067      * <p><code>true</code> to enable dragging of this Panel (defaults to <code>false</code>).</p>
9068      * <p>For custom drag/drop implementations, an <b>Ext.Panel.DD</b> config could also be passed
9069      * in this config instead of <code>true</code>. Ext.Panel.DD is an internal, undocumented class which
9070      * moves a proxy Element around in place of the Panel's element, but provides no other behaviour
9071      * during dragging or on drop. It is a subclass of {@link Ext.dd.DragSource}, so behaviour may be
9072      * added by implementing the interface methods of {@link Ext.dd.DragDrop} e.g.:
9073      * <pre><code>
9074 new Ext.Panel({
9075     title: 'Drag me',
9076     x: 100,
9077     y: 100,
9078     renderTo: Ext.getBody(),
9079     floating: true,
9080     frame: true,
9081     width: 400,
9082     height: 200,
9083     draggable: {
9084 //      Config option of Ext.Panel.DD class.
9085 //      It&#39;s a floating Panel, so do not show a placeholder proxy in the original position.
9086         insertProxy: false,
9087
9088 //      Called for each mousemove event while dragging the DD object.
9089         onDrag : function(e){
9090 //          Record the x,y position of the drag proxy so that we can
9091 //          position the Panel at end of drag.
9092             var pel = this.proxy.getEl();
9093             this.x = pel.getLeft(true);
9094             this.y = pel.getTop(true);
9095
9096 //          Keep the Shadow aligned if there is one.
9097             var s = this.panel.getEl().shadow;
9098             if (s) {
9099                 s.realign(this.x, this.y, pel.getWidth(), pel.getHeight());
9100             }
9101         },
9102
9103 //      Called on the mouseup event.
9104         endDrag : function(e){
9105             this.panel.setPosition(this.x, this.y);
9106         }
9107     }
9108 }).show();
9109 </code></pre>
9110      */
9111     /**
9112      * @cfg {Boolean} disabled
9113      * Render this panel disabled (default is <code>false</code>). An important note when using the disabled
9114      * config on panels is that IE will often fail to initialize the disabled mask element correectly if
9115      * the panel's layout has not yet completed by the time the Panel is disabled during the render process.
9116      * If you experience this issue, you may need to instead use the {@link #afterlayout} event to initialize
9117      * the disabled state:
9118      * <pre><code>
9119 new Ext.Panel({
9120     ...
9121     listeners: {
9122         'afterlayout': {
9123             fn: function(p){
9124                 p.disable();
9125             },
9126             single: true // important, as many layouts can occur
9127         }
9128     }
9129 });
9130 </code></pre>
9131      */
9132     /**
9133      * @cfg {Boolean} autoHeight
9134      * <code>true</code> to use height:'auto', <code>false</code> to use fixed height (defaults to <code>false</code>).
9135      * <b>Note</b>: Setting <code>autoHeight: true</code> means that the browser will manage the panel's height
9136      * based on its contents, and that Ext will not manage it at all. If the panel is within a layout that
9137      * manages dimensions (<code>fit</code>, <code>border</code>, etc.) then setting <code>autoHeight: true</code>
9138      * can cause issues with scrolling and will not generally work as expected since the panel will take
9139      * on the height of its contents rather than the height required by the Ext layout.
9140      */
9141
9142
9143     /**
9144      * @cfg {String} baseCls
9145      * The base CSS class to apply to this panel's element (defaults to <code>'x-panel'</code>).
9146      * <p>Another option available by default is to specify <code>'x-plain'</code> which strips all styling
9147      * except for required attributes for Ext layouts to function (e.g. overflow:hidden).
9148      * See <code>{@link #unstyled}</code> also.</p>
9149      */
9150     baseCls : 'x-panel',
9151     /**
9152      * @cfg {String} collapsedCls
9153      * A CSS class to add to the panel's element after it has been collapsed (defaults to
9154      * <code>'x-panel-collapsed'</code>).
9155      */
9156     collapsedCls : 'x-panel-collapsed',
9157     /**
9158      * @cfg {Boolean} maskDisabled
9159      * <code>true</code> to mask the panel when it is {@link #disabled}, <code>false</code> to not mask it (defaults
9160      * to <code>true</code>).  Either way, the panel will always tell its contained elements to disable themselves
9161      * when it is disabled, but masking the panel can provide an additional visual cue that the panel is
9162      * disabled.
9163      */
9164     maskDisabled : true,
9165     /**
9166      * @cfg {Boolean} animCollapse
9167      * <code>true</code> to animate the transition when the panel is collapsed, <code>false</code> to skip the
9168      * animation (defaults to <code>true</code> if the {@link Ext.Fx} class is available, otherwise <code>false</code>).
9169      */
9170     animCollapse : Ext.enableFx,
9171     /**
9172      * @cfg {Boolean} headerAsText
9173      * <code>true</code> to display the panel <code>{@link #title}</code> in the <code>{@link #header}</code>,
9174      * <code>false</code> to hide it (defaults to <code>true</code>).
9175      */
9176     headerAsText : true,
9177     /**
9178      * @cfg {String} buttonAlign
9179      * The alignment of any {@link #buttons} added to this panel.  Valid values are <code>'right'</code>,
9180      * <code>'left'</code> and <code>'center'</code> (defaults to <code>'right'</code>).
9181      */
9182     buttonAlign : 'right',
9183     /**
9184      * @cfg {Boolean} collapsed
9185      * <code>true</code> to render the panel collapsed, <code>false</code> to render it expanded (defaults to
9186      * <code>false</code>).
9187      */
9188     collapsed : false,
9189     /**
9190      * @cfg {Boolean} collapseFirst
9191      * <code>true</code> to make sure the collapse/expand toggle button always renders first (to the left of)
9192      * any other tools in the panel's title bar, <code>false</code> to render it last (defaults to <code>true</code>).
9193      */
9194     collapseFirst : true,
9195     /**
9196      * @cfg {Number} minButtonWidth
9197      * Minimum width in pixels of all {@link #buttons} in this panel (defaults to <code>75</code>)
9198      */
9199     minButtonWidth : 75,
9200     /**
9201      * @cfg {Boolean} unstyled
9202      * Overrides the <code>{@link #baseCls}</code> setting to <code>{@link #baseCls} = 'x-plain'</code> which renders
9203      * the panel unstyled except for required attributes for Ext layouts to function (e.g. overflow:hidden).
9204      */
9205     /**
9206      * @cfg {String} elements
9207      * A comma-delimited list of panel elements to initialize when the panel is rendered.  Normally, this list will be
9208      * generated automatically based on the items added to the panel at config time, but sometimes it might be useful to
9209      * make sure a structural element is rendered even if not specified at config time (for example, you may want
9210      * to add a button or toolbar dynamically after the panel has been rendered).  Adding those elements to this
9211      * list will allocate the required placeholders in the panel when it is rendered.  Valid values are<div class="mdetail-params"><ul>
9212      * <li><code>header</code></li>
9213      * <li><code>tbar</code> (top bar)</li>
9214      * <li><code>body</code></li>
9215      * <li><code>bbar</code> (bottom bar)</li>
9216      * <li><code>footer</code></li>
9217      * </ul></div>
9218      * Defaults to '<code>body</code>'.
9219      */
9220     elements : 'body',
9221     /**
9222      * @cfg {Boolean} preventBodyReset
9223      * Defaults to <code>false</code>.  When set to <code>true</code>, an extra css class <code>'x-panel-normal'</code>
9224      * will be added to the panel's element, effectively applying css styles suggested by the W3C
9225      * (see http://www.w3.org/TR/CSS21/sample.html) to the Panel's <b>body</b> element (not the header,
9226      * footer, etc.).
9227      */
9228     preventBodyReset : false,
9229
9230     /**
9231      * @cfg {Number/String} padding
9232      * A shortcut for setting a padding style on the body element. The value can either be
9233      * a number to be applied to all sides, or a normal css string describing padding.
9234      * Defaults to <tt>undefined</tt>.
9235      *
9236      */
9237     padding: undefined,
9238
9239     /** @cfg {String} resizeEvent
9240      * The event to listen to for resizing in layouts. Defaults to <tt>'bodyresize'</tt>.
9241      */
9242     resizeEvent: 'bodyresize',
9243
9244     // protected - these could be used to customize the behavior of the window,
9245     // but changing them would not be useful without further mofifications and
9246     // could lead to unexpected or undesirable results.
9247     toolTarget : 'header',
9248     collapseEl : 'bwrap',
9249     slideAnchor : 't',
9250     disabledClass : '',
9251
9252     // private, notify box this class will handle heights
9253     deferHeight : true,
9254     // private
9255     expandDefaults: {
9256         duration : 0.25
9257     },
9258     // private
9259     collapseDefaults : {
9260         duration : 0.25
9261     },
9262
9263     // private
9264     initComponent : function(){
9265         Ext.Panel.superclass.initComponent.call(this);
9266
9267         this.addEvents(
9268             /**
9269              * @event bodyresize
9270              * Fires after the Panel has been resized.
9271              * @param {Ext.Panel} p the Panel which has been resized.
9272              * @param {Number} width The Panel body's new width.
9273              * @param {Number} height The Panel body's new height.
9274              */
9275             'bodyresize',
9276             /**
9277              * @event titlechange
9278              * Fires after the Panel title has been {@link #title set} or {@link #setTitle changed}.
9279              * @param {Ext.Panel} p the Panel which has had its title changed.
9280              * @param {String} The new title.
9281              */
9282             'titlechange',
9283             /**
9284              * @event iconchange
9285              * Fires after the Panel icon class has been {@link #iconCls set} or {@link #setIconClass changed}.
9286              * @param {Ext.Panel} p the Panel which has had its {@link #iconCls icon class} changed.
9287              * @param {String} The new icon class.
9288              * @param {String} The old icon class.
9289              */
9290             'iconchange',
9291             /**
9292              * @event collapse
9293              * Fires after the Panel has been collapsed.
9294              * @param {Ext.Panel} p the Panel that has been collapsed.
9295              */
9296             'collapse',
9297             /**
9298              * @event expand
9299              * Fires after the Panel has been expanded.
9300              * @param {Ext.Panel} p The Panel that has been expanded.
9301              */
9302             'expand',
9303             /**
9304              * @event beforecollapse
9305              * Fires before the Panel is collapsed.  A handler can return false to cancel the collapse.
9306              * @param {Ext.Panel} p the Panel being collapsed.
9307              * @param {Boolean} animate True if the collapse is animated, else false.
9308              */
9309             'beforecollapse',
9310             /**
9311              * @event beforeexpand
9312              * Fires before the Panel is expanded.  A handler can return false to cancel the expand.
9313              * @param {Ext.Panel} p The Panel being expanded.
9314              * @param {Boolean} animate True if the expand is animated, else false.
9315              */
9316             'beforeexpand',
9317             /**
9318              * @event beforeclose
9319              * Fires before the Panel is closed.  Note that Panels do not directly support being closed, but some
9320              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.  This event only
9321              * applies to such subclasses.
9322              * A handler can return false to cancel the close.
9323              * @param {Ext.Panel} p The Panel being closed.
9324              */
9325             'beforeclose',
9326             /**
9327              * @event close
9328              * Fires after the Panel is closed.  Note that Panels do not directly support being closed, but some
9329              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.
9330              * @param {Ext.Panel} p The Panel that has been closed.
9331              */
9332             'close',
9333             /**
9334              * @event activate
9335              * Fires after the Panel has been visually activated.
9336              * Note that Panels do not directly support being activated, but some Panel subclasses
9337              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
9338              * activate and deactivate events under the control of the TabPanel.
9339              * @param {Ext.Panel} p The Panel that has been activated.
9340              */
9341             'activate',
9342             /**
9343              * @event deactivate
9344              * Fires after the Panel has been visually deactivated.
9345              * Note that Panels do not directly support being deactivated, but some Panel subclasses
9346              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
9347              * activate and deactivate events under the control of the TabPanel.
9348              * @param {Ext.Panel} p The Panel that has been deactivated.
9349              */
9350             'deactivate'
9351         );
9352
9353         if(this.unstyled){
9354             this.baseCls = 'x-plain';
9355         }
9356
9357
9358         this.toolbars = [];
9359         // shortcuts
9360         if(this.tbar){
9361             this.elements += ',tbar';
9362             this.topToolbar = this.createToolbar(this.tbar);
9363             delete this.tbar;
9364
9365         }
9366         if(this.bbar){
9367             this.elements += ',bbar';
9368             this.bottomToolbar = this.createToolbar(this.bbar);
9369             delete this.bbar;
9370         }
9371
9372         if(this.header === true){
9373             this.elements += ',header';
9374             delete this.header;
9375         }else if(this.headerCfg || (this.title && this.header !== false)){
9376             this.elements += ',header';
9377         }
9378
9379         if(this.footerCfg || this.footer === true){
9380             this.elements += ',footer';
9381             delete this.footer;
9382         }
9383
9384         if(this.buttons){
9385             this.fbar = this.buttons;
9386             delete this.buttons;
9387         }
9388         if(this.fbar){
9389             this.createFbar(this.fbar);
9390         }
9391         if(this.autoLoad){
9392             this.on('render', this.doAutoLoad, this, {delay:10});
9393         }
9394     },
9395
9396     // private
9397     createFbar : function(fbar){
9398         var min = this.minButtonWidth;
9399         this.elements += ',footer';
9400         this.fbar = this.createToolbar(fbar, {
9401             buttonAlign: this.buttonAlign,
9402             toolbarCls: 'x-panel-fbar',
9403             enableOverflow: false,
9404             defaults: function(c){
9405                 return {
9406                     minWidth: c.minWidth || min
9407                 };
9408             }
9409         });
9410         //@compat addButton and buttons could possibly be removed
9411         //@target 4.0
9412         /**
9413          * This Panel's Array of buttons as created from the <code>{@link #buttons}</code>
9414          * config property. Read only.
9415          * @type Array
9416          * @property buttons
9417          */
9418         this.fbar.items.each(function(c){
9419             c.minWidth = c.minWidth || this.minButtonWidth;
9420         }, this);
9421         this.buttons = this.fbar.items.items;
9422     },
9423
9424     // private
9425     createToolbar: function(tb, options){
9426         var result;
9427         // Convert array to proper toolbar config
9428         if(Ext.isArray(tb)){
9429             tb = {
9430                 items: tb
9431             };
9432         }
9433         result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
9434         this.toolbars.push(result);
9435         return result;
9436     },
9437
9438     // private
9439     createElement : function(name, pnode){
9440         if(this[name]){
9441             pnode.appendChild(this[name].dom);
9442             return;
9443         }
9444
9445         if(name === 'bwrap' || this.elements.indexOf(name) != -1){
9446             if(this[name+'Cfg']){
9447                 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
9448             }else{
9449                 var el = document.createElement('div');
9450                 el.className = this[name+'Cls'];
9451                 this[name] = Ext.get(pnode.appendChild(el));
9452             }
9453             if(this[name+'CssClass']){
9454                 this[name].addClass(this[name+'CssClass']);
9455             }
9456             if(this[name+'Style']){
9457                 this[name].applyStyles(this[name+'Style']);
9458             }
9459         }
9460     },
9461
9462     // private
9463     onRender : function(ct, position){
9464         Ext.Panel.superclass.onRender.call(this, ct, position);
9465         this.createClasses();
9466
9467         var el = this.el,
9468             d = el.dom,
9469             bw,
9470             ts;
9471
9472
9473         if(this.collapsible && !this.hideCollapseTool){
9474             this.tools = this.tools ? this.tools.slice(0) : [];
9475             this.tools[this.collapseFirst?'unshift':'push']({
9476                 id: 'toggle',
9477                 handler : this.toggleCollapse,
9478                 scope: this
9479             });
9480         }
9481
9482         if(this.tools){
9483             ts = this.tools;
9484             this.elements += (this.header !== false) ? ',header' : '';
9485         }
9486         this.tools = {};
9487
9488         el.addClass(this.baseCls);
9489         if(d.firstChild){ // existing markup
9490             this.header = el.down('.'+this.headerCls);
9491             this.bwrap = el.down('.'+this.bwrapCls);
9492             var cp = this.bwrap ? this.bwrap : el;
9493             this.tbar = cp.down('.'+this.tbarCls);
9494             this.body = cp.down('.'+this.bodyCls);
9495             this.bbar = cp.down('.'+this.bbarCls);
9496             this.footer = cp.down('.'+this.footerCls);
9497             this.fromMarkup = true;
9498         }
9499         if (this.preventBodyReset === true) {
9500             el.addClass('x-panel-reset');
9501         }
9502         if(this.cls){
9503             el.addClass(this.cls);
9504         }
9505
9506         if(this.buttons){
9507             this.elements += ',footer';
9508         }
9509
9510         // This block allows for maximum flexibility and performance when using existing markup
9511
9512         // framing requires special markup
9513         if(this.frame){
9514             el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
9515
9516             this.createElement('header', d.firstChild.firstChild.firstChild);
9517             this.createElement('bwrap', d);
9518
9519             // append the mid and bottom frame to the bwrap
9520             bw = this.bwrap.dom;
9521             var ml = d.childNodes[1], bl = d.childNodes[2];
9522             bw.appendChild(ml);
9523             bw.appendChild(bl);
9524
9525             var mc = bw.firstChild.firstChild.firstChild;
9526             this.createElement('tbar', mc);
9527             this.createElement('body', mc);
9528             this.createElement('bbar', mc);
9529             this.createElement('footer', bw.lastChild.firstChild.firstChild);
9530
9531             if(!this.footer){
9532                 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
9533             }
9534             /*
9535              * Store a reference to this element so:
9536              * a) We aren't looking it up all the time
9537              * b) The last element is reported incorrectly when using a loadmask
9538              */
9539             this.ft = Ext.get(this.bwrap.dom.lastChild);
9540             this.mc = Ext.get(mc);
9541         }else{
9542             this.createElement('header', d);
9543             this.createElement('bwrap', d);
9544
9545             // append the mid and bottom frame to the bwrap
9546             bw = this.bwrap.dom;
9547             this.createElement('tbar', bw);
9548             this.createElement('body', bw);
9549             this.createElement('bbar', bw);
9550             this.createElement('footer', bw);
9551
9552             if(!this.header){
9553                 this.body.addClass(this.bodyCls + '-noheader');
9554                 if(this.tbar){
9555                     this.tbar.addClass(this.tbarCls + '-noheader');
9556                 }
9557             }
9558         }
9559
9560         if(Ext.isDefined(this.padding)){
9561             this.body.setStyle('padding', this.body.addUnits(this.padding));
9562         }
9563
9564         if(this.border === false){
9565             this.el.addClass(this.baseCls + '-noborder');
9566             this.body.addClass(this.bodyCls + '-noborder');
9567             if(this.header){
9568                 this.header.addClass(this.headerCls + '-noborder');
9569             }
9570             if(this.footer){
9571                 this.footer.addClass(this.footerCls + '-noborder');
9572             }
9573             if(this.tbar){
9574                 this.tbar.addClass(this.tbarCls + '-noborder');
9575             }
9576             if(this.bbar){
9577                 this.bbar.addClass(this.bbarCls + '-noborder');
9578             }
9579         }
9580
9581         if(this.bodyBorder === false){
9582            this.body.addClass(this.bodyCls + '-noborder');
9583         }
9584
9585         this.bwrap.enableDisplayMode('block');
9586
9587         if(this.header){
9588             this.header.unselectable();
9589
9590             // for tools, we need to wrap any existing header markup
9591             if(this.headerAsText){
9592                 this.header.dom.innerHTML =
9593                     '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
9594
9595                 if(this.iconCls){
9596                     this.setIconClass(this.iconCls);
9597                 }
9598             }
9599         }
9600
9601         if(this.floating){
9602             this.makeFloating(this.floating);
9603         }
9604
9605         if(this.collapsible && this.titleCollapse && this.header){
9606             this.mon(this.header, 'click', this.toggleCollapse, this);
9607             this.header.setStyle('cursor', 'pointer');
9608         }
9609         if(ts){
9610             this.addTool.apply(this, ts);
9611         }
9612
9613         // Render Toolbars.
9614         if(this.fbar){
9615             this.footer.addClass('x-panel-btns');
9616             this.fbar.ownerCt = this;
9617             this.fbar.render(this.footer);
9618             this.footer.createChild({cls:'x-clear'});
9619         }
9620         if(this.tbar && this.topToolbar){
9621             this.topToolbar.ownerCt = this;
9622             this.topToolbar.render(this.tbar);
9623         }
9624         if(this.bbar && this.bottomToolbar){
9625             this.bottomToolbar.ownerCt = this;
9626             this.bottomToolbar.render(this.bbar);
9627         }
9628     },
9629
9630     /**
9631      * Sets the CSS class that provides the icon image for this panel.  This method will replace any existing
9632      * icon class if one has already been set and fire the {@link #iconchange} event after completion.
9633      * @param {String} cls The new CSS class name
9634      */
9635     setIconClass : function(cls){
9636         var old = this.iconCls;
9637         this.iconCls = cls;
9638         if(this.rendered && this.header){
9639             if(this.frame){
9640                 this.header.addClass('x-panel-icon');
9641                 this.header.replaceClass(old, this.iconCls);
9642             }else{
9643                 var hd = this.header,
9644                     img = hd.child('img.x-panel-inline-icon');
9645                 if(img){
9646                     Ext.fly(img).replaceClass(old, this.iconCls);
9647                 }else{
9648                     Ext.DomHelper.insertBefore(hd.dom.firstChild, {
9649                         tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
9650                     });
9651                  }
9652             }
9653         }
9654         this.fireEvent('iconchange', this, cls, old);
9655     },
9656
9657     // private
9658     makeFloating : function(cfg){
9659         this.floating = true;
9660         this.el = new Ext.Layer(Ext.apply({}, cfg, {
9661             shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
9662             shadowOffset: this.shadowOffset,
9663             constrain:false,
9664             shim: this.shim === false ? false : undefined
9665         }), this.el);
9666     },
9667
9668     /**
9669      * Returns the {@link Ext.Toolbar toolbar} from the top (<code>{@link #tbar}</code>) section of the panel.
9670      * @return {Ext.Toolbar} The toolbar
9671      */
9672     getTopToolbar : function(){
9673         return this.topToolbar;
9674     },
9675
9676     /**
9677      * Returns the {@link Ext.Toolbar toolbar} from the bottom (<code>{@link #bbar}</code>) section of the panel.
9678      * @return {Ext.Toolbar} The toolbar
9679      */
9680     getBottomToolbar : function(){
9681         return this.bottomToolbar;
9682     },
9683
9684     /**
9685      * Adds a button to this panel.  Note that this method must be called prior to rendering.  The preferred
9686      * approach is to add buttons via the {@link #buttons} config.
9687      * @param {String/Object} config A valid {@link Ext.Button} config.  A string will become the text for a default
9688      * button config, an object will be treated as a button config object.
9689      * @param {Function} handler The function to be called on button {@link Ext.Button#click}
9690      * @param {Object} scope The scope (<code>this</code> reference) in which the button handler function is executed. Defaults to the Button.
9691      * @return {Ext.Button} The button that was added
9692      */
9693     addButton : function(config, handler, scope){
9694         if(!this.fbar){
9695             this.createFbar([]);
9696         }
9697         if(handler){
9698             if(Ext.isString(config)){
9699                 config = {text: config};
9700             }
9701             config = Ext.apply({
9702                 handler: handler,
9703                 scope: scope
9704             }, config)
9705         }
9706         return this.fbar.add(config);
9707     },
9708
9709     // private
9710     addTool : function(){
9711         if(!this.rendered){
9712             if(!this.tools){
9713                 this.tools = [];
9714             }
9715             Ext.each(arguments, function(arg){
9716                 this.tools.push(arg)
9717             }, this);
9718             return;
9719         }
9720          // nowhere to render tools!
9721         if(!this[this.toolTarget]){
9722             return;
9723         }
9724         if(!this.toolTemplate){
9725             // initialize the global tool template on first use
9726             var tt = new Ext.Template(
9727                  '<div class="x-tool x-tool-{id}">&#160;</div>'
9728             );
9729             tt.disableFormats = true;
9730             tt.compile();
9731             Ext.Panel.prototype.toolTemplate = tt;
9732         }
9733         for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9734             var tc = a[i];
9735             if(!this.tools[tc.id]){
9736                 var overCls = 'x-tool-'+tc.id+'-over';
9737                 var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
9738                 this.tools[tc.id] = t;
9739                 t.enableDisplayMode('block');
9740                 this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
9741                 if(tc.on){
9742                     this.mon(t, tc.on);
9743                 }
9744                 if(tc.hidden){
9745                     t.hide();
9746                 }
9747                 if(tc.qtip){
9748                     if(Ext.isObject(tc.qtip)){
9749                         Ext.QuickTips.register(Ext.apply({
9750                               target: t.id
9751                         }, tc.qtip));
9752                     } else {
9753                         t.dom.qtip = tc.qtip;
9754                     }
9755                 }
9756                 t.addClassOnOver(overCls);
9757             }
9758         }
9759     },
9760
9761     onLayout : function(shallow, force){
9762         Ext.Panel.superclass.onLayout.apply(this, arguments);
9763         if(this.hasLayout && this.toolbars.length > 0){
9764             Ext.each(this.toolbars, function(tb){
9765                 tb.doLayout(undefined, force);
9766             });
9767             this.syncHeight();
9768         }
9769     },
9770
9771     syncHeight : function(){
9772         var h = this.toolbarHeight,
9773                 bd = this.body,
9774                 lsh = this.lastSize.height,
9775                 sz;
9776
9777         if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
9778             return;
9779         }
9780
9781
9782         if(h != this.getToolbarHeight()){
9783             h = Math.max(0, this.adjustBodyHeight(lsh - this.getFrameHeight()));
9784             bd.setHeight(h);
9785             sz = bd.getSize();
9786             this.toolbarHeight = this.getToolbarHeight();
9787             this.onBodyResize(sz.width, sz.height);
9788         }
9789     },
9790
9791     // private
9792     onShow : function(){
9793         if(this.floating){
9794             return this.el.show();
9795         }
9796         Ext.Panel.superclass.onShow.call(this);
9797     },
9798
9799     // private
9800     onHide : function(){
9801         if(this.floating){
9802             return this.el.hide();
9803         }
9804         Ext.Panel.superclass.onHide.call(this);
9805     },
9806
9807     // private
9808     createToolHandler : function(t, tc, overCls, panel){
9809         return function(e){
9810             t.removeClass(overCls);
9811             if(tc.stopEvent !== false){
9812                 e.stopEvent();
9813             }
9814             if(tc.handler){
9815                 tc.handler.call(tc.scope || t, e, t, panel, tc);
9816             }
9817         };
9818     },
9819
9820     // private
9821     afterRender : function(){
9822         if(this.floating && !this.hidden){
9823             this.el.show();
9824         }
9825         if(this.title){
9826             this.setTitle(this.title);
9827         }
9828         Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
9829         if (this.collapsed) {
9830             this.collapsed = false;
9831             this.collapse(false);
9832         }
9833         this.initEvents();
9834     },
9835
9836     // private
9837     getKeyMap : function(){
9838         if(!this.keyMap){
9839             this.keyMap = new Ext.KeyMap(this.el, this.keys);
9840         }
9841         return this.keyMap;
9842     },
9843
9844     // private
9845     initEvents : function(){
9846         if(this.keys){
9847             this.getKeyMap();
9848         }
9849         if(this.draggable){
9850             this.initDraggable();
9851         }
9852         if(this.toolbars.length > 0){
9853             Ext.each(this.toolbars, function(tb){
9854                 tb.doLayout();
9855                 tb.on({
9856                     scope: this,
9857                     afterlayout: this.syncHeight,
9858                     remove: this.syncHeight
9859                 });
9860             }, this);
9861             this.syncHeight();
9862         }
9863
9864     },
9865
9866     // private
9867     initDraggable : function(){
9868         /**
9869          * <p>If this Panel is configured {@link #draggable}, this property will contain
9870          * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.</p>
9871          * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource}
9872          * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
9873          * @type Ext.dd.DragSource.
9874          * @property dd
9875          */
9876         this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
9877     },
9878
9879     // private
9880     beforeEffect : function(anim){
9881         if(this.floating){
9882             this.el.beforeAction();
9883         }
9884         if(anim !== false){
9885             this.el.addClass('x-panel-animated');
9886         }
9887     },
9888
9889     // private
9890     afterEffect : function(anim){
9891         this.syncShadow();
9892         if(anim !== false){
9893             this.el.removeClass('x-panel-animated');
9894         }
9895     },
9896
9897     // private - wraps up an animation param with internal callbacks
9898     createEffect : function(a, cb, scope){
9899         var o = {
9900             scope:scope,
9901             block:true
9902         };
9903         if(a === true){
9904             o.callback = cb;
9905             return o;
9906         }else if(!a.callback){
9907             o.callback = cb;
9908         }else { // wrap it up
9909             o.callback = function(){
9910                 cb.call(scope);
9911                 Ext.callback(a.callback, a.scope);
9912             };
9913         }
9914         return Ext.applyIf(o, a);
9915     },
9916
9917     /**
9918      * Collapses the panel body so that it becomes hidden.  Fires the {@link #beforecollapse} event which will
9919      * cancel the collapse action if it returns false.
9920      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
9921      * {@link #animCollapse} panel config)
9922      * @return {Ext.Panel} this
9923      */
9924     collapse : function(animate){
9925         if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
9926             return;
9927         }
9928         var doAnim = animate === true || (animate !== false && this.animCollapse);
9929         this.beforeEffect(doAnim);
9930         this.onCollapse(doAnim, animate);
9931         return this;
9932     },
9933
9934     // private
9935     onCollapse : function(doAnim, animArg){
9936         if(doAnim){
9937             this[this.collapseEl].slideOut(this.slideAnchor,
9938                     Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
9939                         this.collapseDefaults));
9940         }else{
9941             this[this.collapseEl].hide();
9942             this.afterCollapse(false);
9943         }
9944     },
9945
9946     // private
9947     afterCollapse : function(anim){
9948         this.collapsed = true;
9949         this.el.addClass(this.collapsedCls);
9950         this.afterEffect(anim);
9951         this.fireEvent('collapse', this);
9952     },
9953
9954     /**
9955      * Expands the panel body so that it becomes visible.  Fires the {@link #beforeexpand} event which will
9956      * cancel the expand action if it returns false.
9957      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
9958      * {@link #animCollapse} panel config)
9959      * @return {Ext.Panel} this
9960      */
9961     expand : function(animate){
9962         if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
9963             return;
9964         }
9965         var doAnim = animate === true || (animate !== false && this.animCollapse);
9966         this.el.removeClass(this.collapsedCls);
9967         this.beforeEffect(doAnim);
9968         this.onExpand(doAnim, animate);
9969         return this;
9970     },
9971
9972     // private
9973     onExpand : function(doAnim, animArg){
9974         if(doAnim){
9975             this[this.collapseEl].slideIn(this.slideAnchor,
9976                     Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
9977                         this.expandDefaults));
9978         }else{
9979             this[this.collapseEl].show();
9980             this.afterExpand(false);
9981         }
9982     },
9983
9984     // private
9985     afterExpand : function(anim){
9986         this.collapsed = false;
9987         this.afterEffect(anim);
9988         if (this.deferLayout) {
9989             delete this.deferLayout;
9990             this.doLayout(true);
9991         }
9992         this.fireEvent('expand', this);
9993     },
9994
9995     /**
9996      * Shortcut for performing an {@link #expand} or {@link #collapse} based on the current state of the panel.
9997      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
9998      * {@link #animCollapse} panel config)
9999      * @return {Ext.Panel} this
10000      */
10001     toggleCollapse : function(animate){
10002         this[this.collapsed ? 'expand' : 'collapse'](animate);
10003         return this;
10004     },
10005
10006     // private
10007     onDisable : function(){
10008         if(this.rendered && this.maskDisabled){
10009             this.el.mask();
10010         }
10011         Ext.Panel.superclass.onDisable.call(this);
10012     },
10013
10014     // private
10015     onEnable : function(){
10016         if(this.rendered && this.maskDisabled){
10017             this.el.unmask();
10018         }
10019         Ext.Panel.superclass.onEnable.call(this);
10020     },
10021
10022     // private
10023     onResize : function(w, h){
10024         if(Ext.isDefined(w) || Ext.isDefined(h)){
10025             if(!this.collapsed){
10026                 // First, set the the Panel's body width.
10027                 // If we have auto-widthed it, get the resulting full offset width so we can size the Toolbars to match
10028                 // The Toolbars must not buffer this resize operation because we need to know their heights.
10029
10030                 if(Ext.isNumber(w)){
10031                     this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
10032                 } else if (w == 'auto') {
10033                     w = this.body.setWidth('auto').dom.offsetWidth;
10034                 } else {
10035                     w = this.body.dom.offsetWidth;
10036                 }
10037
10038                 if(this.tbar){
10039                     this.tbar.setWidth(w);
10040                     if(this.topToolbar){
10041                         this.topToolbar.setSize(w);
10042                     }
10043                 }
10044                 if(this.bbar){
10045                     this.bbar.setWidth(w);
10046                     if(this.bottomToolbar){
10047                         this.bottomToolbar.setSize(w);
10048                         // The bbar does not move on resize without this.
10049                         if (Ext.isIE) {
10050                             this.bbar.setStyle('position', 'static');
10051                             this.bbar.setStyle('position', '');
10052                         }
10053                     }
10054                 }
10055                 if(this.footer){
10056                     this.footer.setWidth(w);
10057                     if(this.fbar){
10058                         this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
10059                     }
10060                 }
10061
10062                 // At this point, the Toolbars must be layed out for getFrameHeight to find a result.
10063                 if(Ext.isNumber(h)){
10064                     h = Math.max(0, this.adjustBodyHeight(h - this.getFrameHeight()));
10065                     this.body.setHeight(h);
10066                 }else if(h == 'auto'){
10067                     this.body.setHeight(h);
10068                 }
10069
10070                 if(this.disabled && this.el._mask){
10071                     this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
10072                 }
10073             }else{
10074                 // Adds an event to set the correct height afterExpand.  This accounts for the deferHeight flag in panel
10075                 this.queuedBodySize = {width: w, height: h};
10076                 if(!this.queuedExpand && this.allowQueuedExpand !== false){
10077                     this.queuedExpand = true;
10078                     this.on('expand', function(){
10079                         delete this.queuedExpand;
10080                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
10081                     }, this, {single:true});
10082                 }
10083             }
10084             this.onBodyResize(w, h);
10085         }
10086         this.syncShadow();
10087         Ext.Panel.superclass.onResize.call(this);
10088     },
10089
10090     // private
10091     onBodyResize: function(w, h){
10092         this.fireEvent('bodyresize', this, w, h);
10093     },
10094
10095     // private
10096     getToolbarHeight: function(){
10097         var h = 0;
10098         if(this.rendered){
10099             Ext.each(this.toolbars, function(tb){
10100                 h += tb.getHeight();
10101             }, this);
10102         }
10103         return h;
10104     },
10105
10106     // private
10107     adjustBodyHeight : function(h){
10108         return h;
10109     },
10110
10111     // private
10112     adjustBodyWidth : function(w){
10113         return w;
10114     },
10115
10116     // private
10117     onPosition : function(){
10118         this.syncShadow();
10119     },
10120
10121     /**
10122      * Returns the width in pixels of the framing elements of this panel (not including the body width).  To
10123      * retrieve the body width see {@link #getInnerWidth}.
10124      * @return {Number} The frame width
10125      */
10126     getFrameWidth : function(){
10127         var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
10128
10129         if(this.frame){
10130             var l = this.bwrap.dom.firstChild;
10131             w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
10132             w += this.mc.getFrameWidth('lr');
10133         }
10134         return w;
10135     },
10136
10137     /**
10138      * Returns the height in pixels of the framing elements of this panel (including any top and bottom bars and
10139      * header and footer elements, but not including the body height).  To retrieve the body height see {@link #getInnerHeight}.
10140      * @return {Number} The frame height
10141      */
10142     getFrameHeight : function(){
10143         var h  = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
10144         h += (this.tbar ? this.tbar.getHeight() : 0) +
10145              (this.bbar ? this.bbar.getHeight() : 0);
10146
10147         if(this.frame){
10148             h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
10149         }else{
10150             h += (this.header ? this.header.getHeight() : 0) +
10151                 (this.footer ? this.footer.getHeight() : 0);
10152         }
10153         return h;
10154     },
10155
10156     /**
10157      * Returns the width in pixels of the body element (not including the width of any framing elements).
10158      * For the frame width see {@link #getFrameWidth}.
10159      * @return {Number} The body width
10160      */
10161     getInnerWidth : function(){
10162         return this.getSize().width - this.getFrameWidth();
10163     },
10164
10165     /**
10166      * Returns the height in pixels of the body element (not including the height of any framing elements).
10167      * For the frame height see {@link #getFrameHeight}.
10168      * @return {Number} The body height
10169      */
10170     getInnerHeight : function(){
10171         return this.getSize().height - this.getFrameHeight();
10172     },
10173
10174     // private
10175     syncShadow : function(){
10176         if(this.floating){
10177             this.el.sync(true);
10178         }
10179     },
10180
10181     // private
10182     getLayoutTarget : function(){
10183         return this.body;
10184     },
10185
10186     // private
10187     getContentTarget : function(){
10188         return this.body;
10189     },
10190
10191     /**
10192      * <p>Sets the title text for the panel and optionally the {@link #iconCls icon class}.</p>
10193      * <p>In order to be able to set the title, a header element must have been created
10194      * for the Panel. This is triggered either by configuring the Panel with a non-blank <code>{@link #title}</code>,
10195      * or configuring it with <code><b>{@link #header}: true</b></code>.</p>
10196      * @param {String} title The title text to set
10197      * @param {String} iconCls (optional) {@link #iconCls iconCls} A user-defined CSS class that provides the icon image for this panel
10198      */
10199     setTitle : function(title, iconCls){
10200         this.title = title;
10201         if(this.header && this.headerAsText){
10202             this.header.child('span').update(title);
10203         }
10204         if(iconCls){
10205             this.setIconClass(iconCls);
10206         }
10207         this.fireEvent('titlechange', this, title);
10208         return this;
10209     },
10210
10211     /**
10212      * Get the {@link Ext.Updater} for this panel. Enables you to perform Ajax updates of this panel's body.
10213      * @return {Ext.Updater} The Updater
10214      */
10215     getUpdater : function(){
10216         return this.body.getUpdater();
10217     },
10218
10219      /**
10220      * Loads this content panel immediately with content returned from an XHR call.
10221      * @param {Object/String/Function} config A config object containing any of the following options:
10222 <pre><code>
10223 panel.load({
10224     url: 'your-url.php',
10225     params: {param1: 'foo', param2: 'bar'}, // or a URL encoded string
10226     callback: yourFunction,
10227     scope: yourObject, // optional scope for the callback
10228     discardUrl: false,
10229     nocache: false,
10230     text: 'Loading...',
10231     timeout: 30,
10232     scripts: false
10233 });
10234 </code></pre>
10235      * The only required property is url. The optional properties nocache, text and scripts
10236      * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their
10237      * associated property on this panel Updater instance.
10238      * @return {Ext.Panel} this
10239      */
10240     load : function(){
10241         var um = this.body.getUpdater();
10242         um.update.apply(um, arguments);
10243         return this;
10244     },
10245
10246     // private
10247     beforeDestroy : function(){
10248         Ext.Panel.superclass.beforeDestroy.call(this);
10249         if(this.header){
10250             this.header.removeAllListeners();
10251         }
10252         if(this.tools){
10253             for(var k in this.tools){
10254                 Ext.destroy(this.tools[k]);
10255             }
10256         }
10257         if(this.toolbars.length > 0){
10258             Ext.each(this.toolbars, function(tb){
10259                 tb.un('afterlayout', this.syncHeight, this);
10260                 tb.un('remove', this.syncHeight, this);
10261             }, this);
10262         }
10263         if(Ext.isArray(this.buttons)){
10264             while(this.buttons.length) {
10265                 Ext.destroy(this.buttons[0]);
10266             }
10267         }
10268         if(this.rendered){
10269             Ext.destroy(
10270                 this.ft,
10271                 this.header,
10272                 this.footer,
10273                 this.toolbars,
10274                 this.tbar,
10275                 this.bbar,
10276                 this.body,
10277                 this.mc,
10278                 this.bwrap
10279             );
10280             if (this.fbar) {
10281                 Ext.destroy(
10282                     this.fbar,
10283                     this.fbar.el
10284                 );
10285             }
10286         }else{
10287             Ext.destroy(
10288                 this.topToolbar,
10289                 this.bottomToolbar
10290             );
10291         }
10292     },
10293
10294     // private
10295     createClasses : function(){
10296         this.headerCls = this.baseCls + '-header';
10297         this.headerTextCls = this.baseCls + '-header-text';
10298         this.bwrapCls = this.baseCls + '-bwrap';
10299         this.tbarCls = this.baseCls + '-tbar';
10300         this.bodyCls = this.baseCls + '-body';
10301         this.bbarCls = this.baseCls + '-bbar';
10302         this.footerCls = this.baseCls + '-footer';
10303     },
10304
10305     // private
10306     createGhost : function(cls, useShim, appendTo){
10307         var el = document.createElement('div');
10308         el.className = 'x-panel-ghost ' + (cls ? cls : '');
10309         if(this.header){
10310             el.appendChild(this.el.dom.firstChild.cloneNode(true));
10311         }
10312         Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
10313         el.style.width = this.el.dom.offsetWidth + 'px';;
10314         if(!appendTo){
10315             this.container.dom.appendChild(el);
10316         }else{
10317             Ext.getDom(appendTo).appendChild(el);
10318         }
10319         if(useShim !== false && this.el.useShim !== false){
10320             var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
10321             layer.show();
10322             return layer;
10323         }else{
10324             return new Ext.Element(el);
10325         }
10326     },
10327
10328     // private
10329     doAutoLoad : function(){
10330         var u = this.body.getUpdater();
10331         if(this.renderer){
10332             u.setRenderer(this.renderer);
10333         }
10334         u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
10335     },
10336
10337     /**
10338      * Retrieve a tool by id.
10339      * @param {String} id
10340      * @return {Object} tool
10341      */
10342     getTool : function(id) {
10343         return this.tools[id];
10344     }
10345
10346 /**
10347  * @cfg {String} autoEl @hide
10348  */
10349 });
10350 Ext.reg('panel', Ext.Panel);
10351 /**
10352  * @class Ext.Editor
10353  * @extends Ext.Component
10354  * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
10355  * @constructor
10356  * Create a new Editor
10357  * @param {Object} config The config object
10358  * @xtype editor
10359  */
10360 Ext.Editor = function(field, config){
10361     if(field.field){
10362         this.field = Ext.create(field.field, 'textfield');
10363         config = Ext.apply({}, field); // copy so we don't disturb original config
10364         delete config.field;
10365     }else{
10366         this.field = field;
10367     }
10368     Ext.Editor.superclass.constructor.call(this, config);
10369 };
10370
10371 Ext.extend(Ext.Editor, Ext.Component, {
10372     /**
10373     * @cfg {Ext.form.Field} field
10374     * The Field object (or descendant) or config object for field
10375     */
10376     /**
10377      * @cfg {Boolean} allowBlur
10378      * True to {@link #completeEdit complete the editing process} if in edit mode when the
10379      * field is blurred. Defaults to <tt>false</tt>.
10380      */
10381     /**
10382      * @cfg {Boolean/String} autoSize
10383      * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only,
10384      * or "height" to adopt the height only, "none" to always use the field dimensions. (defaults to false)
10385      */
10386     /**
10387      * @cfg {Boolean} revertInvalid
10388      * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
10389      * validation fails (defaults to true)
10390      */
10391     /**
10392      * @cfg {Boolean} ignoreNoChange
10393      * True to skip the edit completion process (no save, no events fired) if the user completes an edit and
10394      * the value has not changed (defaults to false).  Applies only to string values - edits for other data types
10395      * will never be ignored.
10396      */
10397     /**
10398      * @cfg {Boolean} hideEl
10399      * False to keep the bound element visible while the editor is displayed (defaults to true)
10400      */
10401     /**
10402      * @cfg {Mixed} value
10403      * The data value of the underlying field (defaults to "")
10404      */
10405     value : "",
10406     /**
10407      * @cfg {String} alignment
10408      * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?").
10409      */
10410     alignment: "c-c?",
10411     /**
10412      * @cfg {Array} offsets
10413      * The offsets to use when aligning (see {@link Ext.Element#alignTo} for more details. Defaults to <tt>[0, 0]</tt>.
10414      */
10415     offsets: [0, 0],
10416     /**
10417      * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
10418      * for bottom-right shadow (defaults to "frame")
10419      */
10420     shadow : "frame",
10421     /**
10422      * @cfg {Boolean} constrain True to constrain the editor to the viewport
10423      */
10424     constrain : false,
10425     /**
10426      * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true)
10427      */
10428     swallowKeys : true,
10429     /**
10430      * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed. Defaults to <tt>true</tt>.
10431      */
10432     completeOnEnter : true,
10433     /**
10434      * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed. Defaults to <tt>true</tt>.
10435      */
10436     cancelOnEsc : true,
10437     /**
10438      * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
10439      */
10440     updateEl : false,
10441
10442     initComponent : function(){
10443         Ext.Editor.superclass.initComponent.call(this);
10444         this.addEvents(
10445             /**
10446              * @event beforestartedit
10447              * Fires when editing is initiated, but before the value changes.  Editing can be canceled by returning
10448              * false from the handler of this event.
10449              * @param {Editor} this
10450              * @param {Ext.Element} boundEl The underlying element bound to this editor
10451              * @param {Mixed} value The field value being set
10452              */
10453             "beforestartedit",
10454             /**
10455              * @event startedit
10456              * Fires when this editor is displayed
10457              * @param {Ext.Element} boundEl The underlying element bound to this editor
10458              * @param {Mixed} value The starting field value
10459              */
10460             "startedit",
10461             /**
10462              * @event beforecomplete
10463              * Fires after a change has been made to the field, but before the change is reflected in the underlying
10464              * field.  Saving the change to the field can be canceled by returning false from the handler of this event.
10465              * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
10466              * event will not fire since no edit actually occurred.
10467              * @param {Editor} this
10468              * @param {Mixed} value The current field value
10469              * @param {Mixed} startValue The original field value
10470              */
10471             "beforecomplete",
10472             /**
10473              * @event complete
10474              * Fires after editing is complete and any changed value has been written to the underlying field.
10475              * @param {Editor} this
10476              * @param {Mixed} value The current field value
10477              * @param {Mixed} startValue The original field value
10478              */
10479             "complete",
10480             /**
10481              * @event canceledit
10482              * Fires after editing has been canceled and the editor's value has been reset.
10483              * @param {Editor} this
10484              * @param {Mixed} value The user-entered field value that was discarded
10485              * @param {Mixed} startValue The original field value that was set back into the editor after cancel
10486              */
10487             "canceledit",
10488             /**
10489              * @event specialkey
10490              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
10491              * {@link Ext.EventObject#getKey} to determine which key was pressed.
10492              * @param {Ext.form.Field} this
10493              * @param {Ext.EventObject} e The event object
10494              */
10495             "specialkey"
10496         );
10497     },
10498
10499     // private
10500     onRender : function(ct, position){
10501         this.el = new Ext.Layer({
10502             shadow: this.shadow,
10503             cls: "x-editor",
10504             parentEl : ct,
10505             shim : this.shim,
10506             shadowOffset: this.shadowOffset || 4,
10507             id: this.id,
10508             constrain: this.constrain
10509         });
10510         if(this.zIndex){
10511             this.el.setZIndex(this.zIndex);
10512         }
10513         this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
10514         if(this.field.msgTarget != 'title'){
10515             this.field.msgTarget = 'qtip';
10516         }
10517         this.field.inEditor = true;
10518         this.mon(this.field, {
10519             scope: this,
10520             blur: this.onBlur,
10521             specialkey: this.onSpecialKey
10522         });
10523         if(this.field.grow){
10524             this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
10525         }
10526         this.field.render(this.el).show();
10527         this.field.getEl().dom.name = '';
10528         if(this.swallowKeys){
10529             this.field.el.swallowEvent([
10530                 'keypress', // *** Opera
10531                 'keydown'   // *** all other browsers
10532             ]);
10533         }
10534     },
10535
10536     // private
10537     onSpecialKey : function(field, e){
10538         var key = e.getKey(),
10539             complete = this.completeOnEnter && key == e.ENTER,
10540             cancel = this.cancelOnEsc && key == e.ESC;
10541         if(complete || cancel){
10542             e.stopEvent();
10543             if(complete){
10544                 this.completeEdit();
10545             }else{
10546                 this.cancelEdit();
10547             }
10548             if(field.triggerBlur){
10549                 field.triggerBlur();
10550             }
10551         }
10552         this.fireEvent('specialkey', field, e);
10553     },
10554
10555     /**
10556      * Starts the editing process and shows the editor.
10557      * @param {Mixed} el The element to edit
10558      * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
10559       * to the innerHTML of el.
10560      */
10561     startEdit : function(el, value){
10562         if(this.editing){
10563             this.completeEdit();
10564         }
10565         this.boundEl = Ext.get(el);
10566         var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
10567         if(!this.rendered){
10568             this.render(this.parentEl || document.body);
10569         }
10570         if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
10571             this.startValue = v;
10572             this.field.reset();
10573             this.field.setValue(v);
10574             this.realign(true);
10575             this.editing = true;
10576             this.show();
10577         }
10578     },
10579
10580     // private
10581     doAutoSize : function(){
10582         if(this.autoSize){
10583             var sz = this.boundEl.getSize(),
10584                 fs = this.field.getSize();
10585
10586             switch(this.autoSize){
10587                 case "width":
10588                     this.setSize(sz.width, fs.height);
10589                     break;
10590                 case "height":
10591                     this.setSize(fs.width, sz.height);
10592                     break;
10593                 case "none":
10594                     this.setSize(fs.width, fs.height);
10595                     break;
10596                 default:
10597                     this.setSize(sz.width, sz.height);
10598             }
10599         }
10600     },
10601
10602     /**
10603      * Sets the height and width of this editor.
10604      * @param {Number} width The new width
10605      * @param {Number} height The new height
10606      */
10607     setSize : function(w, h){
10608         delete this.field.lastSize;
10609         this.field.setSize(w, h);
10610         if(this.el){
10611             if(Ext.isGecko2 || Ext.isOpera){
10612                 // prevent layer scrollbars
10613                 this.el.setSize(w, h);
10614             }
10615             this.el.sync();
10616         }
10617     },
10618
10619     /**
10620      * Realigns the editor to the bound field based on the current alignment config value.
10621      * @param {Boolean} autoSize (optional) True to size the field to the dimensions of the bound element.
10622      */
10623     realign : function(autoSize){
10624         if(autoSize === true){
10625             this.doAutoSize();
10626         }
10627         this.el.alignTo(this.boundEl, this.alignment, this.offsets);
10628     },
10629
10630     /**
10631      * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
10632      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
10633      */
10634     completeEdit : function(remainVisible){
10635         if(!this.editing){
10636             return;
10637         }
10638         var v = this.getValue();
10639         if(!this.field.isValid()){
10640             if(this.revertInvalid !== false){
10641                 this.cancelEdit(remainVisible);
10642             }
10643             return;
10644         }
10645         if(String(v) === String(this.startValue) && this.ignoreNoChange){
10646             this.hideEdit(remainVisible);
10647             return;
10648         }
10649         if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
10650             v = this.getValue();
10651             if(this.updateEl && this.boundEl){
10652                 this.boundEl.update(v);
10653             }
10654             this.hideEdit(remainVisible);
10655             this.fireEvent("complete", this, v, this.startValue);
10656         }
10657     },
10658
10659     // private
10660     onShow : function(){
10661         this.el.show();
10662         if(this.hideEl !== false){
10663             this.boundEl.hide();
10664         }
10665         this.field.show().focus(false, true);
10666         this.fireEvent("startedit", this.boundEl, this.startValue);
10667     },
10668
10669     /**
10670      * Cancels the editing process and hides the editor without persisting any changes.  The field value will be
10671      * reverted to the original starting value.
10672      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
10673      * cancel (defaults to false)
10674      */
10675     cancelEdit : function(remainVisible){
10676         if(this.editing){
10677             var v = this.getValue();
10678             this.setValue(this.startValue);
10679             this.hideEdit(remainVisible);
10680             this.fireEvent("canceledit", this, v, this.startValue);
10681         }
10682     },
10683
10684     // private
10685     hideEdit: function(remainVisible){
10686         if(remainVisible !== true){
10687             this.editing = false;
10688             this.hide();
10689         }
10690     },
10691
10692     // private
10693     onBlur : function(){
10694         // selectSameEditor flag allows the same editor to be started without onBlur firing on itself
10695         if(this.allowBlur !== true && this.editing && this.selectSameEditor !== true){
10696             this.completeEdit();
10697         }
10698     },
10699
10700     // private
10701     onHide : function(){
10702         if(this.editing){
10703             this.completeEdit();
10704             return;
10705         }
10706         this.field.blur();
10707         if(this.field.collapse){
10708             this.field.collapse();
10709         }
10710         this.el.hide();
10711         if(this.hideEl !== false){
10712             this.boundEl.show();
10713         }
10714     },
10715
10716     /**
10717      * Sets the data value of the editor
10718      * @param {Mixed} value Any valid value supported by the underlying field
10719      */
10720     setValue : function(v){
10721         this.field.setValue(v);
10722     },
10723
10724     /**
10725      * Gets the data value of the editor
10726      * @return {Mixed} The data value
10727      */
10728     getValue : function(){
10729         return this.field.getValue();
10730     },
10731
10732     beforeDestroy : function(){
10733         Ext.destroyMembers(this, 'field');
10734
10735         delete this.parentEl;
10736         delete this.boundEl;
10737     }
10738 });
10739 Ext.reg('editor', Ext.Editor);
10740 /**
10741  * @class Ext.ColorPalette
10742  * @extends Ext.Component
10743  * Simple color palette class for choosing colors.  The palette can be rendered to any container.<br />
10744  * Here's an example of typical usage:
10745  * <pre><code>
10746 var cp = new Ext.ColorPalette({value:'993300'});  // initial selected color
10747 cp.render('my-div');
10748
10749 cp.on('select', function(palette, selColor){
10750     // do something with selColor
10751 });
10752 </code></pre>
10753  * @constructor
10754  * Create a new ColorPalette
10755  * @param {Object} config The config object
10756  * @xtype colorpalette
10757  */
10758 Ext.ColorPalette = Ext.extend(Ext.Component, {
10759         /**
10760          * @cfg {String} tpl An existing XTemplate instance to be used in place of the default template for rendering the component.
10761          */
10762     /**
10763      * @cfg {String} itemCls
10764      * The CSS class to apply to the containing element (defaults to 'x-color-palette')
10765      */
10766     itemCls : 'x-color-palette',
10767     /**
10768      * @cfg {String} value
10769      * The initial color to highlight (should be a valid 6-digit color hex code without the # symbol).  Note that
10770      * the hex codes are case-sensitive.
10771      */
10772     value : null,
10773     /**
10774      * @cfg {String} clickEvent
10775      * The DOM event that will cause a color to be selected. This can be any valid event name (dblclick, contextmenu). 
10776      * Defaults to <tt>'click'</tt>.
10777      */
10778     clickEvent :'click',
10779     // private
10780     ctype : 'Ext.ColorPalette',
10781
10782     /**
10783      * @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the {@link #select} event
10784      */
10785     allowReselect : false,
10786
10787     /**
10788      * <p>An array of 6-digit color hex code strings (without the # symbol).  This array can contain any number
10789      * of colors, and each hex code should be unique.  The width of the palette is controlled via CSS by adjusting
10790      * the width property of the 'x-color-palette' class (or assigning a custom class), so you can balance the number
10791      * of colors with the width setting until the box is symmetrical.</p>
10792      * <p>You can override individual colors if needed:</p>
10793      * <pre><code>
10794 var cp = new Ext.ColorPalette();
10795 cp.colors[0] = 'FF0000';  // change the first box to red
10796 </code></pre>
10797
10798 Or you can provide a custom array of your own for complete control:
10799 <pre><code>
10800 var cp = new Ext.ColorPalette();
10801 cp.colors = ['000000', '993300', '333300'];
10802 </code></pre>
10803      * @type Array
10804      */
10805     colors : [
10806         '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
10807         '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
10808         'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
10809         'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
10810         'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
10811     ],
10812
10813     /**
10814      * @cfg {Function} handler
10815      * Optional. A function that will handle the select event of this palette.
10816      * The handler is passed the following parameters:<div class="mdetail-params"><ul>
10817      * <li><code>palette</code> : ColorPalette<div class="sub-desc">The {@link #palette Ext.ColorPalette}.</div></li>
10818      * <li><code>color</code> : String<div class="sub-desc">The 6-digit color hex code (without the # symbol).</div></li>
10819      * </ul></div>
10820      */
10821     /**
10822      * @cfg {Object} scope
10823      * The scope (<tt><b>this</b></tt> reference) in which the <code>{@link #handler}</code>
10824      * function will be called.  Defaults to this ColorPalette instance.
10825      */
10826     
10827     // private
10828     initComponent : function(){
10829         Ext.ColorPalette.superclass.initComponent.call(this);
10830         this.addEvents(
10831             /**
10832              * @event select
10833              * Fires when a color is selected
10834              * @param {ColorPalette} this
10835              * @param {String} color The 6-digit color hex code (without the # symbol)
10836              */
10837             'select'
10838         );
10839
10840         if(this.handler){
10841             this.on('select', this.handler, this.scope, true);
10842         }    
10843     },
10844
10845     // private
10846     onRender : function(container, position){
10847         this.autoEl = {
10848             tag: 'div',
10849             cls: this.itemCls
10850         };
10851         Ext.ColorPalette.superclass.onRender.call(this, container, position);
10852         var t = this.tpl || new Ext.XTemplate(
10853             '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
10854         );
10855         t.overwrite(this.el, this.colors);
10856         this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
10857         if(this.clickEvent != 'click'){
10858                 this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
10859         }
10860     },
10861
10862     // private
10863     afterRender : function(){
10864         Ext.ColorPalette.superclass.afterRender.call(this);
10865         if(this.value){
10866             var s = this.value;
10867             this.value = null;
10868             this.select(s);
10869         }
10870     },
10871
10872     // private
10873     handleClick : function(e, t){
10874         e.preventDefault();
10875         if(!this.disabled){
10876             var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
10877             this.select(c.toUpperCase());
10878         }
10879     },
10880
10881     /**
10882      * Selects the specified color in the palette (fires the {@link #select} event)
10883      * @param {String} color A valid 6-digit color hex code (# will be stripped if included)
10884      */
10885     select : function(color){
10886         color = color.replace('#', '');
10887         if(color != this.value || this.allowReselect){
10888             var el = this.el;
10889             if(this.value){
10890                 el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
10891             }
10892             el.child('a.color-'+color).addClass('x-color-palette-sel');
10893             this.value = color;
10894             this.fireEvent('select', this, color);
10895         }
10896     }
10897
10898     /**
10899      * @cfg {String} autoEl @hide
10900      */
10901 });
10902 Ext.reg('colorpalette', Ext.ColorPalette);
10903 /**
10904  * @class Ext.DatePicker
10905  * @extends Ext.Component
10906  * <p>A popup date picker. This class is used by the {@link Ext.form.DateField DateField} class
10907  * to allow browsing and selection of valid dates.</p>
10908  * <p>All the string values documented below may be overridden by including an Ext locale file in
10909  * your page.</p>
10910  * @constructor
10911  * Create a new DatePicker
10912  * @param {Object} config The config object
10913  * @xtype datepicker
10914  */
10915 Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
10916     /**
10917      * @cfg {String} todayText
10918      * The text to display on the button that selects the current date (defaults to <code>'Today'</code>)
10919      */
10920     todayText : 'Today',
10921     /**
10922      * @cfg {String} okText
10923      * The text to display on the ok button (defaults to <code>'&#160;OK&#160;'</code> to give the user extra clicking room)
10924      */
10925     okText : '&#160;OK&#160;',
10926     /**
10927      * @cfg {String} cancelText
10928      * The text to display on the cancel button (defaults to <code>'Cancel'</code>)
10929      */
10930     cancelText : 'Cancel',
10931     /**
10932      * @cfg {Function} handler
10933      * Optional. A function that will handle the select event of this picker.
10934      * The handler is passed the following parameters:<div class="mdetail-params"><ul>
10935      * <li><code>picker</code> : DatePicker<div class="sub-desc">This DatePicker.</div></li>
10936      * <li><code>date</code> : Date<div class="sub-desc">The selected date.</div></li>
10937      * </ul></div>
10938      */
10939     /**
10940      * @cfg {Object} scope
10941      * The scope (<code><b>this</b></code> reference) in which the <code>{@link #handler}</code>
10942      * function will be called.  Defaults to this DatePicker instance.
10943      */ 
10944     /**
10945      * @cfg {String} todayTip
10946      * A string used to format the message for displaying in a tooltip over the button that
10947      * selects the current date. Defaults to <code>'{0} (Spacebar)'</code> where
10948      * the <code>{0}</code> token is replaced by today's date.
10949      */
10950     todayTip : '{0} (Spacebar)',
10951     /**
10952      * @cfg {String} minText
10953      * The error text to display if the minDate validation fails (defaults to <code>'This date is before the minimum date'</code>)
10954      */
10955     minText : 'This date is before the minimum date',
10956     /**
10957      * @cfg {String} maxText
10958      * The error text to display if the maxDate validation fails (defaults to <code>'This date is after the maximum date'</code>)
10959      */
10960     maxText : 'This date is after the maximum date',
10961     /**
10962      * @cfg {String} format
10963      * The default date format string which can be overriden for localization support.  The format must be
10964      * valid according to {@link Date#parseDate} (defaults to <code>'m/d/y'</code>).
10965      */
10966     format : 'm/d/y',
10967     /**
10968      * @cfg {String} disabledDaysText
10969      * The tooltip to display when the date falls on a disabled day (defaults to <code>'Disabled'</code>)
10970      */
10971     disabledDaysText : 'Disabled',
10972     /**
10973      * @cfg {String} disabledDatesText
10974      * The tooltip text to display when the date falls on a disabled date (defaults to <code>'Disabled'</code>)
10975      */
10976     disabledDatesText : 'Disabled',
10977     /**
10978      * @cfg {Array} monthNames
10979      * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
10980      */
10981     monthNames : Date.monthNames,
10982     /**
10983      * @cfg {Array} dayNames
10984      * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
10985      */
10986     dayNames : Date.dayNames,
10987     /**
10988      * @cfg {String} nextText
10989      * The next month navigation button tooltip (defaults to <code>'Next Month (Control+Right)'</code>)
10990      */
10991     nextText : 'Next Month (Control+Right)',
10992     /**
10993      * @cfg {String} prevText
10994      * The previous month navigation button tooltip (defaults to <code>'Previous Month (Control+Left)'</code>)
10995      */
10996     prevText : 'Previous Month (Control+Left)',
10997     /**
10998      * @cfg {String} monthYearText
10999      * The header month selector tooltip (defaults to <code>'Choose a month (Control+Up/Down to move years)'</code>)
11000      */
11001     monthYearText : 'Choose a month (Control+Up/Down to move years)',
11002     /**
11003      * @cfg {Number} startDay
11004      * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
11005      */
11006     startDay : 0,
11007     /**
11008      * @cfg {Boolean} showToday
11009      * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar
11010      * that selects the current date (defaults to <code>true</code>).
11011      */
11012     showToday : true,
11013     /**
11014      * @cfg {Date} minDate
11015      * Minimum allowable date (JavaScript date object, defaults to null)
11016      */
11017     /**
11018      * @cfg {Date} maxDate
11019      * Maximum allowable date (JavaScript date object, defaults to null)
11020      */
11021     /**
11022      * @cfg {Array} disabledDays
11023      * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
11024      */
11025     /**
11026      * @cfg {RegExp} disabledDatesRE
11027      * JavaScript regular expression used to disable a pattern of dates (defaults to null).  The {@link #disabledDates}
11028      * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the
11029      * disabledDates value.
11030      */
11031     /**
11032      * @cfg {Array} disabledDates
11033      * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular
11034      * expression so they are very powerful. Some examples:
11035      * <ul>
11036      * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>
11037      * <li>['03/08', '09/16'] would disable those days for every year</li>
11038      * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>
11039      * <li>['03/../2006'] would disable every day in March 2006</li>
11040      * <li>['^03'] would disable every day in every March</li>
11041      * </ul>
11042      * Note that the format of the dates included in the array should exactly match the {@link #format} config.
11043      * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to
11044      * escape the dot when restricting dates. For example: ['03\\.08\\.03'].
11045      */
11046     
11047     // private
11048     // Set by other components to stop the picker focus being updated when the value changes.
11049     focusOnSelect: true,
11050
11051     // private
11052     initComponent : function(){
11053         Ext.DatePicker.superclass.initComponent.call(this);
11054
11055         this.value = this.value ?
11056                  this.value.clearTime(true) : new Date().clearTime();
11057
11058         this.addEvents(
11059             /**
11060              * @event select
11061              * Fires when a date is selected
11062              * @param {DatePicker} this DatePicker
11063              * @param {Date} date The selected date
11064              */
11065             'select'
11066         );
11067
11068         if(this.handler){
11069             this.on('select', this.handler,  this.scope || this);
11070         }
11071
11072         this.initDisabledDays();
11073     },
11074
11075     // private
11076     initDisabledDays : function(){
11077         if(!this.disabledDatesRE && this.disabledDates){
11078             var dd = this.disabledDates,
11079                 len = dd.length - 1,
11080                 re = '(?:';
11081                 
11082             Ext.each(dd, function(d, i){
11083                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
11084                 if(i != len){
11085                     re += '|';
11086                 }
11087             }, this);
11088             this.disabledDatesRE = new RegExp(re + ')');
11089         }
11090     },
11091
11092     /**
11093      * Replaces any existing disabled dates with new values and refreshes the DatePicker.
11094      * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config
11095      * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.
11096      */
11097     setDisabledDates : function(dd){
11098         if(Ext.isArray(dd)){
11099             this.disabledDates = dd;
11100             this.disabledDatesRE = null;
11101         }else{
11102             this.disabledDatesRE = dd;
11103         }
11104         this.initDisabledDays();
11105         this.update(this.value, true);
11106     },
11107
11108     /**
11109      * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.
11110      * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config
11111      * for details on supported values.
11112      */
11113     setDisabledDays : function(dd){
11114         this.disabledDays = dd;
11115         this.update(this.value, true);
11116     },
11117
11118     /**
11119      * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
11120      * @param {Date} value The minimum date that can be selected
11121      */
11122     setMinDate : function(dt){
11123         this.minDate = dt;
11124         this.update(this.value, true);
11125     },
11126
11127     /**
11128      * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
11129      * @param {Date} value The maximum date that can be selected
11130      */
11131     setMaxDate : function(dt){
11132         this.maxDate = dt;
11133         this.update(this.value, true);
11134     },
11135
11136     /**
11137      * Sets the value of the date field
11138      * @param {Date} value The date to set
11139      */
11140     setValue : function(value){
11141         this.value = value.clearTime(true);
11142         this.update(this.value);
11143     },
11144
11145     /**
11146      * Gets the current selected value of the date field
11147      * @return {Date} The selected date
11148      */
11149     getValue : function(){
11150         return this.value;
11151     },
11152
11153     // private
11154     focus : function(){
11155         this.update(this.activeDate);
11156     },
11157     
11158     // private
11159     onEnable: function(initial){
11160         Ext.DatePicker.superclass.onEnable.call(this);    
11161         this.doDisabled(false);
11162         this.update(initial ? this.value : this.activeDate);
11163         if(Ext.isIE){
11164             this.el.repaint();
11165         }
11166         
11167     },
11168     
11169     // private
11170     onDisable : function(){
11171         Ext.DatePicker.superclass.onDisable.call(this);   
11172         this.doDisabled(true);
11173         if(Ext.isIE && !Ext.isIE8){
11174             /* Really strange problem in IE6/7, when disabled, have to explicitly
11175              * repaint each of the nodes to get them to display correctly, simply
11176              * calling repaint on the main element doesn't appear to be enough.
11177              */
11178              Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
11179                  Ext.fly(el).repaint();
11180              });
11181         }
11182     },
11183     
11184     // private
11185     doDisabled : function(disabled){
11186         this.keyNav.setDisabled(disabled);
11187         this.prevRepeater.setDisabled(disabled);
11188         this.nextRepeater.setDisabled(disabled);
11189         if(this.showToday){
11190             this.todayKeyListener.setDisabled(disabled);
11191             this.todayBtn.setDisabled(disabled);
11192         }
11193     },
11194
11195     // private
11196     onRender : function(container, position){
11197         var m = [
11198              '<table cellspacing="0">',
11199                 '<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>',
11200                 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
11201                 dn = this.dayNames,
11202                 i;
11203         for(i = 0; i < 7; i++){
11204             var d = this.startDay+i;
11205             if(d > 6){
11206                 d = d-7;
11207             }
11208             m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
11209         }
11210         m[m.length] = '</tr></thead><tbody><tr>';
11211         for(i = 0; i < 42; i++) {
11212             if(i % 7 === 0 && i !== 0){
11213                 m[m.length] = '</tr><tr>';
11214             }
11215             m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
11216         }
11217         m.push('</tr></tbody></table></td></tr>',
11218                 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
11219                 '</table><div class="x-date-mp"></div>');
11220
11221         var el = document.createElement('div');
11222         el.className = 'x-date-picker';
11223         el.innerHTML = m.join('');
11224
11225         container.dom.insertBefore(el, position);
11226
11227         this.el = Ext.get(el);
11228         this.eventEl = Ext.get(el.firstChild);
11229
11230         this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
11231             handler: this.showPrevMonth,
11232             scope: this,
11233             preventDefault:true,
11234             stopDefault:true
11235         });
11236
11237         this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
11238             handler: this.showNextMonth,
11239             scope: this,
11240             preventDefault:true,
11241             stopDefault:true
11242         });
11243
11244         this.monthPicker = this.el.down('div.x-date-mp');
11245         this.monthPicker.enableDisplayMode('block');
11246
11247         this.keyNav = new Ext.KeyNav(this.eventEl, {
11248             'left' : function(e){
11249                 if(e.ctrlKey){
11250                     this.showPrevMonth();
11251                 }else{
11252                     this.update(this.activeDate.add('d', -1));    
11253                 }
11254             },
11255
11256             'right' : function(e){
11257                 if(e.ctrlKey){
11258                     this.showNextMonth();
11259                 }else{
11260                     this.update(this.activeDate.add('d', 1));    
11261                 }
11262             },
11263
11264             'up' : function(e){
11265                 if(e.ctrlKey){
11266                     this.showNextYear();
11267                 }else{
11268                     this.update(this.activeDate.add('d', -7));
11269                 }
11270             },
11271
11272             'down' : function(e){
11273                 if(e.ctrlKey){
11274                     this.showPrevYear();
11275                 }else{
11276                     this.update(this.activeDate.add('d', 7));
11277                 }
11278             },
11279
11280             'pageUp' : function(e){
11281                 this.showNextMonth();
11282             },
11283
11284             'pageDown' : function(e){
11285                 this.showPrevMonth();
11286             },
11287
11288             'enter' : function(e){
11289                 e.stopPropagation();
11290                 return true;
11291             },
11292
11293             scope : this
11294         });
11295
11296         this.el.unselectable();
11297
11298         this.cells = this.el.select('table.x-date-inner tbody td');
11299         this.textNodes = this.el.query('table.x-date-inner tbody span');
11300
11301         this.mbtn = new Ext.Button({
11302             text: '&#160;',
11303             tooltip: this.monthYearText,
11304             renderTo: this.el.child('td.x-date-middle', true)
11305         });
11306         this.mbtn.el.child('em').addClass('x-btn-arrow');
11307
11308         if(this.showToday){
11309             this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
11310             var today = (new Date()).dateFormat(this.format);
11311             this.todayBtn = new Ext.Button({
11312                 renderTo: this.el.child('td.x-date-bottom', true),
11313                 text: String.format(this.todayText, today),
11314                 tooltip: String.format(this.todayTip, today),
11315                 handler: this.selectToday,
11316                 scope: this
11317             });
11318         }
11319         this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
11320         this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
11321         this.mon(this.mbtn, 'click', this.showMonthPicker, this);
11322         this.onEnable(true);
11323     },
11324
11325     // private
11326     createMonthPicker : function(){
11327         if(!this.monthPicker.dom.firstChild){
11328             var buf = ['<table border="0" cellspacing="0">'];
11329             for(var i = 0; i < 6; i++){
11330                 buf.push(
11331                     '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
11332                     '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
11333                     i === 0 ?
11334                     '<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>' :
11335                     '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
11336                 );
11337             }
11338             buf.push(
11339                 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
11340                     this.okText,
11341                     '</button><button type="button" class="x-date-mp-cancel">',
11342                     this.cancelText,
11343                     '</button></td></tr>',
11344                 '</table>'
11345             );
11346             this.monthPicker.update(buf.join(''));
11347
11348             this.mon(this.monthPicker, 'click', this.onMonthClick, this);
11349             this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
11350
11351             this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
11352             this.mpYears = this.monthPicker.select('td.x-date-mp-year');
11353
11354             this.mpMonths.each(function(m, a, i){
11355                 i += 1;
11356                 if((i%2) === 0){
11357                     m.dom.xmonth = 5 + Math.round(i * 0.5);
11358                 }else{
11359                     m.dom.xmonth = Math.round((i-1) * 0.5);
11360                 }
11361             });
11362         }
11363     },
11364
11365     // private
11366     showMonthPicker : function(){
11367         if(!this.disabled){
11368             this.createMonthPicker();
11369             var size = this.el.getSize();
11370             this.monthPicker.setSize(size);
11371             this.monthPicker.child('table').setSize(size);
11372
11373             this.mpSelMonth = (this.activeDate || this.value).getMonth();
11374             this.updateMPMonth(this.mpSelMonth);
11375             this.mpSelYear = (this.activeDate || this.value).getFullYear();
11376             this.updateMPYear(this.mpSelYear);
11377
11378             this.monthPicker.slideIn('t', {duration:0.2});
11379         }
11380     },
11381
11382     // private
11383     updateMPYear : function(y){
11384         this.mpyear = y;
11385         var ys = this.mpYears.elements;
11386         for(var i = 1; i <= 10; i++){
11387             var td = ys[i-1], y2;
11388             if((i%2) === 0){
11389                 y2 = y + Math.round(i * 0.5);
11390                 td.firstChild.innerHTML = y2;
11391                 td.xyear = y2;
11392             }else{
11393                 y2 = y - (5-Math.round(i * 0.5));
11394                 td.firstChild.innerHTML = y2;
11395                 td.xyear = y2;
11396             }
11397             this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
11398         }
11399     },
11400
11401     // private
11402     updateMPMonth : function(sm){
11403         this.mpMonths.each(function(m, a, i){
11404             m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
11405         });
11406     },
11407
11408     // private
11409     selectMPMonth : function(m){
11410
11411     },
11412
11413     // private
11414     onMonthClick : function(e, t){
11415         e.stopEvent();
11416         var el = new Ext.Element(t), pn;
11417         if(el.is('button.x-date-mp-cancel')){
11418             this.hideMonthPicker();
11419         }
11420         else if(el.is('button.x-date-mp-ok')){
11421             var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
11422             if(d.getMonth() != this.mpSelMonth){
11423                 // 'fix' the JS rolling date conversion if needed
11424                 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
11425             }
11426             this.update(d);
11427             this.hideMonthPicker();
11428         }
11429         else if((pn = el.up('td.x-date-mp-month', 2))){
11430             this.mpMonths.removeClass('x-date-mp-sel');
11431             pn.addClass('x-date-mp-sel');
11432             this.mpSelMonth = pn.dom.xmonth;
11433         }
11434         else if((pn = el.up('td.x-date-mp-year', 2))){
11435             this.mpYears.removeClass('x-date-mp-sel');
11436             pn.addClass('x-date-mp-sel');
11437             this.mpSelYear = pn.dom.xyear;
11438         }
11439         else if(el.is('a.x-date-mp-prev')){
11440             this.updateMPYear(this.mpyear-10);
11441         }
11442         else if(el.is('a.x-date-mp-next')){
11443             this.updateMPYear(this.mpyear+10);
11444         }
11445     },
11446
11447     // private
11448     onMonthDblClick : function(e, t){
11449         e.stopEvent();
11450         var el = new Ext.Element(t), pn;
11451         if((pn = el.up('td.x-date-mp-month', 2))){
11452             this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
11453             this.hideMonthPicker();
11454         }
11455         else if((pn = el.up('td.x-date-mp-year', 2))){
11456             this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
11457             this.hideMonthPicker();
11458         }
11459     },
11460
11461     // private
11462     hideMonthPicker : function(disableAnim){
11463         if(this.monthPicker){
11464             if(disableAnim === true){
11465                 this.monthPicker.hide();
11466             }else{
11467                 this.monthPicker.slideOut('t', {duration:0.2});
11468             }
11469         }
11470     },
11471
11472     // private
11473     showPrevMonth : function(e){
11474         this.update(this.activeDate.add('mo', -1));
11475     },
11476
11477     // private
11478     showNextMonth : function(e){
11479         this.update(this.activeDate.add('mo', 1));
11480     },
11481
11482     // private
11483     showPrevYear : function(){
11484         this.update(this.activeDate.add('y', -1));
11485     },
11486
11487     // private
11488     showNextYear : function(){
11489         this.update(this.activeDate.add('y', 1));
11490     },
11491
11492     // private
11493     handleMouseWheel : function(e){
11494         e.stopEvent();
11495         if(!this.disabled){
11496             var delta = e.getWheelDelta();
11497             if(delta > 0){
11498                 this.showPrevMonth();
11499             } else if(delta < 0){
11500                 this.showNextMonth();
11501             }
11502         }
11503     },
11504
11505     // private
11506     handleDateClick : function(e, t){
11507         e.stopEvent();
11508         if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
11509             this.cancelFocus = this.focusOnSelect === false;
11510             this.setValue(new Date(t.dateValue));
11511             delete this.cancelFocus;
11512             this.fireEvent('select', this, this.value);
11513         }
11514     },
11515
11516     // private
11517     selectToday : function(){
11518         if(this.todayBtn && !this.todayBtn.disabled){
11519             this.setValue(new Date().clearTime());
11520             this.fireEvent('select', this, this.value);
11521         }
11522     },
11523
11524     // private
11525     update : function(date, forceRefresh){
11526         if(this.rendered){
11527                 var vd = this.activeDate, vis = this.isVisible();
11528                 this.activeDate = date;
11529                 if(!forceRefresh && vd && this.el){
11530                     var t = date.getTime();
11531                     if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
11532                         this.cells.removeClass('x-date-selected');
11533                         this.cells.each(function(c){
11534                            if(c.dom.firstChild.dateValue == t){
11535                                c.addClass('x-date-selected');
11536                                if(vis && !this.cancelFocus){
11537                                    Ext.fly(c.dom.firstChild).focus(50);
11538                                }
11539                                return false;
11540                            }
11541                         }, this);
11542                         return;
11543                     }
11544                 }
11545                 var days = date.getDaysInMonth(),
11546                     firstOfMonth = date.getFirstDateOfMonth(),
11547                     startingPos = firstOfMonth.getDay()-this.startDay;
11548         
11549                 if(startingPos < 0){
11550                     startingPos += 7;
11551                 }
11552                 days += startingPos;
11553         
11554                 var pm = date.add('mo', -1),
11555                     prevStart = pm.getDaysInMonth()-startingPos,
11556                     cells = this.cells.elements,
11557                     textEls = this.textNodes,
11558                     // convert everything to numbers so it's fast
11559                     day = 86400000,
11560                     d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime(),
11561                     today = new Date().clearTime().getTime(),
11562                     sel = date.clearTime(true).getTime(),
11563                     min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
11564                     max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
11565                     ddMatch = this.disabledDatesRE,
11566                     ddText = this.disabledDatesText,
11567                     ddays = this.disabledDays ? this.disabledDays.join('') : false,
11568                     ddaysText = this.disabledDaysText,
11569                     format = this.format;
11570         
11571                 if(this.showToday){
11572                     var td = new Date().clearTime(),
11573                         disable = (td < min || td > max ||
11574                         (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
11575                         (ddays && ddays.indexOf(td.getDay()) != -1));
11576         
11577                     if(!this.disabled){
11578                         this.todayBtn.setDisabled(disable);
11579                         this.todayKeyListener[disable ? 'disable' : 'enable']();
11580                     }
11581                 }
11582         
11583                 var setCellClass = function(cal, cell){
11584                     cell.title = '';
11585                     var t = d.getTime();
11586                     cell.firstChild.dateValue = t;
11587                     if(t == today){
11588                         cell.className += ' x-date-today';
11589                         cell.title = cal.todayText;
11590                     }
11591                     if(t == sel){
11592                         cell.className += ' x-date-selected';
11593                         if(vis){
11594                             Ext.fly(cell.firstChild).focus(50);
11595                         }
11596                     }
11597                     // disabling
11598                     if(t < min) {
11599                         cell.className = ' x-date-disabled';
11600                         cell.title = cal.minText;
11601                         return;
11602                     }
11603                     if(t > max) {
11604                         cell.className = ' x-date-disabled';
11605                         cell.title = cal.maxText;
11606                         return;
11607                     }
11608                     if(ddays){
11609                         if(ddays.indexOf(d.getDay()) != -1){
11610                             cell.title = ddaysText;
11611                             cell.className = ' x-date-disabled';
11612                         }
11613                     }
11614                     if(ddMatch && format){
11615                         var fvalue = d.dateFormat(format);
11616                         if(ddMatch.test(fvalue)){
11617                             cell.title = ddText.replace('%0', fvalue);
11618                             cell.className = ' x-date-disabled';
11619                         }
11620                     }
11621                 };
11622         
11623                 var i = 0;
11624                 for(; i < startingPos; i++) {
11625                     textEls[i].innerHTML = (++prevStart);
11626                     d.setDate(d.getDate()+1);
11627                     cells[i].className = 'x-date-prevday';
11628                     setCellClass(this, cells[i]);
11629                 }
11630                 for(; i < days; i++){
11631                     var intDay = i - startingPos + 1;
11632                     textEls[i].innerHTML = (intDay);
11633                     d.setDate(d.getDate()+1);
11634                     cells[i].className = 'x-date-active';
11635                     setCellClass(this, cells[i]);
11636                 }
11637                 var extraDays = 0;
11638                 for(; i < 42; i++) {
11639                      textEls[i].innerHTML = (++extraDays);
11640                      d.setDate(d.getDate()+1);
11641                      cells[i].className = 'x-date-nextday';
11642                      setCellClass(this, cells[i]);
11643                 }
11644         
11645                 this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
11646         
11647                 if(!this.internalRender){
11648                     var main = this.el.dom.firstChild,
11649                         w = main.offsetWidth;
11650                     this.el.setWidth(w + this.el.getBorderWidth('lr'));
11651                     Ext.fly(main).setWidth(w);
11652                     this.internalRender = true;
11653                     // opera does not respect the auto grow header center column
11654                     // then, after it gets a width opera refuses to recalculate
11655                     // without a second pass
11656                     if(Ext.isOpera && !this.secondPass){
11657                         main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
11658                         this.secondPass = true;
11659                         this.update.defer(10, this, [date]);
11660                     }
11661                 }
11662         }
11663     },
11664
11665     // private
11666     beforeDestroy : function() {
11667         if(this.rendered){
11668             Ext.destroy(
11669                 this.keyNav,
11670                 this.monthPicker,
11671                 this.eventEl,
11672                 this.mbtn,
11673                 this.nextRepeater,
11674                 this.prevRepeater,
11675                 this.cells.el,
11676                 this.todayBtn
11677             );
11678             delete this.textNodes;
11679             delete this.cells.elements;
11680         }
11681     }
11682
11683     /**
11684      * @cfg {String} autoEl @hide
11685      */
11686 });
11687
11688 Ext.reg('datepicker', Ext.DatePicker);
11689 /**
11690  * @class Ext.LoadMask
11691  * A simple utility class for generically masking elements while loading data.  If the {@link #store}
11692  * config option is specified, the masking will be automatically synchronized with the store's loading
11693  * process and the mask element will be cached for reuse.  For all other elements, this mask will replace the
11694  * element's Updater load indicator and will be destroyed after the initial load.
11695  * <p>Example usage:</p>
11696  *<pre><code>
11697 // Basic mask:
11698 var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
11699 myMask.show();
11700 </code></pre>
11701  * @constructor
11702  * Create a new LoadMask
11703  * @param {Mixed} el The element or DOM node, or its id
11704  * @param {Object} config The config object
11705  */
11706 Ext.LoadMask = function(el, config){
11707     this.el = Ext.get(el);
11708     Ext.apply(this, config);
11709     if(this.store){
11710         this.store.on({
11711             scope: this,
11712             beforeload: this.onBeforeLoad,
11713             load: this.onLoad,
11714             exception: this.onLoad
11715         });
11716         this.removeMask = Ext.value(this.removeMask, false);
11717     }else{
11718         var um = this.el.getUpdater();
11719         um.showLoadIndicator = false; // disable the default indicator
11720         um.on({
11721             scope: this,
11722             beforeupdate: this.onBeforeLoad,
11723             update: this.onLoad,
11724             failure: this.onLoad
11725         });
11726         this.removeMask = Ext.value(this.removeMask, true);
11727     }
11728 };
11729
11730 Ext.LoadMask.prototype = {
11731     /**
11732      * @cfg {Ext.data.Store} store
11733      * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and
11734      * hidden on either load sucess, or load fail.
11735      */
11736     /**
11737      * @cfg {Boolean} removeMask
11738      * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
11739      * False to persist the mask element reference for multiple uses (e.g., for paged data widgets).  Defaults to false.
11740      */
11741     /**
11742      * @cfg {String} msg
11743      * The text to display in a centered loading message box (defaults to 'Loading...')
11744      */
11745     msg : 'Loading...',
11746     /**
11747      * @cfg {String} msgCls
11748      * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
11749      */
11750     msgCls : 'x-mask-loading',
11751
11752     /**
11753      * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
11754      * @type Boolean
11755      */
11756     disabled: false,
11757
11758     /**
11759      * Disables the mask to prevent it from being displayed
11760      */
11761     disable : function(){
11762        this.disabled = true;
11763     },
11764
11765     /**
11766      * Enables the mask so that it can be displayed
11767      */
11768     enable : function(){
11769         this.disabled = false;
11770     },
11771
11772     // private
11773     onLoad : function(){
11774         this.el.unmask(this.removeMask);
11775     },
11776
11777     // private
11778     onBeforeLoad : function(){
11779         if(!this.disabled){
11780             this.el.mask(this.msg, this.msgCls);
11781         }
11782     },
11783
11784     /**
11785      * Show this LoadMask over the configured Element.
11786      */
11787     show: function(){
11788         this.onBeforeLoad();
11789     },
11790
11791     /**
11792      * Hide this LoadMask.
11793      */
11794     hide: function(){
11795         this.onLoad();
11796     },
11797
11798     // private
11799     destroy : function(){
11800         if(this.store){
11801             this.store.un('beforeload', this.onBeforeLoad, this);
11802             this.store.un('load', this.onLoad, this);
11803             this.store.un('exception', this.onLoad, this);
11804         }else{
11805             var um = this.el.getUpdater();
11806             um.un('beforeupdate', this.onBeforeLoad, this);
11807             um.un('update', this.onLoad, this);
11808             um.un('failure', this.onLoad, this);
11809         }
11810     }
11811 };/**\r
11812  * @class Ext.Slider\r
11813  * @extends Ext.BoxComponent\r
11814  * Slider which supports vertical or horizontal orientation, keyboard adjustments,\r
11815  * configurable snapping, axis clicking and animation. Can be added as an item to\r
11816  * any container. Example usage:\r
11817 <pre><code>\r
11818 new Ext.Slider({\r
11819     renderTo: Ext.getBody(),\r
11820     width: 200,\r
11821     value: 50,\r
11822     increment: 10,\r
11823     minValue: 0,\r
11824     maxValue: 100\r
11825 });\r
11826 </code></pre>\r
11827  */\r
11828 Ext.Slider = Ext.extend(Ext.BoxComponent, {\r
11829     /**\r
11830      * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.\r
11831      */\r
11832     /**\r
11833      * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.\r
11834      */\r
11835     vertical: false,\r
11836     /**\r
11837      * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.\r
11838      */\r
11839     minValue: 0,\r
11840     /**\r
11841      * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.\r
11842      */\r
11843     maxValue: 100,\r
11844     /**\r
11845      * @cfg {Number/Boolean} decimalPrecision.\r
11846      * <p>The number of decimal places to which to round the Slider's value. Defaults to 0.</p>\r
11847      * <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>\r
11848      */\r
11849     decimalPrecision: 0,\r
11850     /**\r
11851      * @cfg {Number} keyIncrement How many units to change the Slider when adjusting with keyboard navigation. Defaults to 1. If the increment config is larger, it will be used instead.\r
11852      */\r
11853     keyIncrement: 1,\r
11854     /**\r
11855      * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.\r
11856      */\r
11857     increment: 0,\r
11858     // private\r
11859     clickRange: [5,15],\r
11860     /**\r
11861      * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true\r
11862      */\r
11863     clickToChange : true,\r
11864     /**\r
11865      * @cfg {Boolean} animate Turn on or off animation. Defaults to true\r
11866      */\r
11867     animate: true,\r
11868 \r
11869     /**\r
11870      * True while the thumb is in a drag operation\r
11871      * @type boolean\r
11872      */\r
11873     dragging: false,\r
11874 \r
11875     // private override\r
11876     initComponent : function(){\r
11877         if(!Ext.isDefined(this.value)){\r
11878             this.value = this.minValue;\r
11879         }\r
11880         Ext.Slider.superclass.initComponent.call(this);\r
11881         this.keyIncrement = Math.max(this.increment, this.keyIncrement);\r
11882         this.addEvents(\r
11883             /**\r
11884              * @event beforechange\r
11885              * Fires before the slider value is changed. By returning false from an event handler,\r
11886              * you can cancel the event and prevent the slider from changing.\r
11887              * @param {Ext.Slider} slider The slider\r
11888              * @param {Number} newValue The new value which the slider is being changed to.\r
11889              * @param {Number} oldValue The old value which the slider was previously.\r
11890              */\r
11891             'beforechange',\r
11892             /**\r
11893              * @event change\r
11894              * Fires when the slider value is changed.\r
11895              * @param {Ext.Slider} slider The slider\r
11896              * @param {Number} newValue The new value which the slider has been changed to.\r
11897              */\r
11898             'change',\r
11899             /**\r
11900              * @event changecomplete\r
11901              * Fires when the slider value is changed by the user and any drag operations have completed.\r
11902              * @param {Ext.Slider} slider The slider\r
11903              * @param {Number} newValue The new value which the slider has been changed to.\r
11904              */\r
11905             'changecomplete',\r
11906             /**\r
11907              * @event dragstart\r
11908              * Fires after a drag operation has started.\r
11909              * @param {Ext.Slider} slider The slider\r
11910              * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
11911              */\r
11912             'dragstart',\r
11913             /**\r
11914              * @event drag\r
11915              * Fires continuously during the drag operation while the mouse is moving.\r
11916              * @param {Ext.Slider} slider The slider\r
11917              * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
11918              */\r
11919             'drag',\r
11920             /**\r
11921              * @event dragend\r
11922              * Fires after the drag operation has completed.\r
11923              * @param {Ext.Slider} slider The slider\r
11924              * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
11925              */\r
11926             'dragend'\r
11927         );\r
11928 \r
11929         if(this.vertical){\r
11930             Ext.apply(this, Ext.Slider.Vertical);\r
11931         }\r
11932     },\r
11933 \r
11934     // private override\r
11935     onRender : function(){\r
11936         this.autoEl = {\r
11937             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),\r
11938             cn:{cls:'x-slider-end',cn:{cls:'x-slider-inner',cn:[{cls:'x-slider-thumb'},{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]}}\r
11939         };\r
11940         Ext.Slider.superclass.onRender.apply(this, arguments);\r
11941         this.endEl = this.el.first();\r
11942         this.innerEl = this.endEl.first();\r
11943         this.thumb = this.innerEl.first();\r
11944         this.halfThumb = (this.vertical ? this.thumb.getHeight() : this.thumb.getWidth())/2;\r
11945         this.focusEl = this.thumb.next();\r
11946         this.initEvents();\r
11947     },\r
11948 \r
11949     // private override\r
11950     initEvents : function(){\r
11951         this.thumb.addClassOnOver('x-slider-thumb-over');\r
11952         this.mon(this.el, {\r
11953             scope: this,\r
11954             mousedown: this.onMouseDown,\r
11955             keydown: this.onKeyDown\r
11956         });\r
11957 \r
11958         this.focusEl.swallowEvent("click", true);\r
11959 \r
11960         this.tracker = new Ext.dd.DragTracker({\r
11961             onBeforeStart: this.onBeforeDragStart.createDelegate(this),\r
11962             onStart: this.onDragStart.createDelegate(this),\r
11963             onDrag: this.onDrag.createDelegate(this),\r
11964             onEnd: this.onDragEnd.createDelegate(this),\r
11965             tolerance: 3,\r
11966             autoStart: 300\r
11967         });\r
11968         this.tracker.initEl(this.thumb);\r
11969     },\r
11970 \r
11971     // private override\r
11972     onMouseDown : function(e){\r
11973         if(this.disabled){\r
11974             return;\r
11975         }\r
11976         if(this.clickToChange && e.target != this.thumb.dom){\r
11977             var local = this.innerEl.translatePoints(e.getXY());\r
11978             this.onClickChange(local);\r
11979         }\r
11980         this.focus();\r
11981     },\r
11982 \r
11983     // private\r
11984     onClickChange : function(local){\r
11985         if(local.top > this.clickRange[0] && local.top < this.clickRange[1]){\r
11986             this.setValue(Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);\r
11987         }\r
11988     },\r
11989 \r
11990     // private\r
11991     onKeyDown : function(e){\r
11992         if(this.disabled){e.preventDefault();return;}\r
11993         var k = e.getKey();\r
11994         switch(k){\r
11995             case e.UP:\r
11996             case e.RIGHT:\r
11997                 e.stopEvent();\r
11998                 if(e.ctrlKey){\r
11999                     this.setValue(this.maxValue, undefined, true);\r
12000                 }else{\r
12001                     this.setValue(this.value+this.keyIncrement, undefined, true);\r
12002                 }\r
12003             break;\r
12004             case e.DOWN:\r
12005             case e.LEFT:\r
12006                 e.stopEvent();\r
12007                 if(e.ctrlKey){\r
12008                     this.setValue(this.minValue, undefined, true);\r
12009                 }else{\r
12010                     this.setValue(this.value-this.keyIncrement, undefined, true);\r
12011                 }\r
12012             break;\r
12013             default:\r
12014                 e.preventDefault();\r
12015         }\r
12016     },\r
12017 \r
12018     // private\r
12019     doSnap : function(value){\r
12020         if(!(this.increment && value)){\r
12021             return value;\r
12022         }\r
12023         var newValue = value,\r
12024             inc = this.increment,\r
12025             m = value % inc;\r
12026         if(m != 0){\r
12027             newValue -= m;\r
12028             if(m * 2 > inc){\r
12029                 newValue += inc;\r
12030             }else if(m * 2 < -inc){\r
12031                 newValue -= inc;\r
12032             }\r
12033         }\r
12034         return newValue.constrain(this.minValue,  this.maxValue);\r
12035     },\r
12036 \r
12037     // private\r
12038     afterRender : function(){\r
12039         Ext.Slider.superclass.afterRender.apply(this, arguments);\r
12040         if(this.value !== undefined){\r
12041             var v = this.normalizeValue(this.value);\r
12042             if(v !== this.value){\r
12043                 delete this.value;\r
12044                 this.setValue(v, false);\r
12045             }else{\r
12046                 this.moveThumb(this.translateValue(v), false);\r
12047             }\r
12048         }\r
12049     },\r
12050 \r
12051     // private\r
12052     getRatio : function(){\r
12053         var w = this.innerEl.getWidth(),\r
12054             v = this.maxValue - this.minValue;\r
12055         return v == 0 ? w : (w/v);\r
12056     },\r
12057 \r
12058     // private\r
12059     normalizeValue : function(v){\r
12060         v = this.doSnap(v);\r
12061         v = Ext.util.Format.round(v, this.decimalPrecision);\r
12062         v = v.constrain(this.minValue, this.maxValue);\r
12063         return v;\r
12064     },\r
12065     \r
12066     /**\r
12067      * Sets the minimum value for the slider instance. If the current value is less than the \r
12068      * minimum value, the current value will be changed.\r
12069      * @param {Number} val The new minimum value\r
12070      */\r
12071     setMinValue : function(val){\r
12072         this.minValue = val;\r
12073         this.syncThumb();\r
12074         if(this.value < val){\r
12075             this.setValue(val);\r
12076         }\r
12077     },\r
12078     \r
12079     /**\r
12080      * Sets the maximum value for the slider instance. If the current value is more than the \r
12081      * maximum value, the current value will be changed.\r
12082      * @param {Number} val The new maximum value\r
12083      */\r
12084     setMaxValue : function(val){\r
12085         this.maxValue = val;\r
12086         this.syncThumb();\r
12087         if(this.value > val){\r
12088             this.setValue(val);\r
12089         }\r
12090     },\r
12091 \r
12092     /**\r
12093      * Programmatically sets the value of the Slider. Ensures that the value is constrained within\r
12094      * the minValue and maxValue.\r
12095      * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)\r
12096      * @param {Boolean} animate Turn on or off animation, defaults to true\r
12097      */\r
12098     setValue : function(v, animate, changeComplete){\r
12099         v = this.normalizeValue(v);\r
12100         if(v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false){\r
12101             this.value = v;\r
12102             this.moveThumb(this.translateValue(v), animate !== false);\r
12103             this.fireEvent('change', this, v);\r
12104             if(changeComplete){\r
12105                 this.fireEvent('changecomplete', this, v);\r
12106             }\r
12107         }\r
12108     },\r
12109 \r
12110     // private\r
12111     translateValue : function(v){\r
12112         var ratio = this.getRatio();\r
12113         return (v * ratio) - (this.minValue * ratio) - this.halfThumb;\r
12114     },\r
12115 \r
12116     reverseValue : function(pos){\r
12117         var ratio = this.getRatio();\r
12118         return (pos + (this.minValue * ratio)) / ratio;\r
12119     },\r
12120 \r
12121     // private\r
12122     moveThumb: function(v, animate){\r
12123         if(!animate || this.animate === false){\r
12124             this.thumb.setLeft(v);\r
12125         }else{\r
12126             this.thumb.shift({left: v, stopFx: true, duration:.35});\r
12127         }\r
12128     },\r
12129 \r
12130     // private\r
12131     focus : function(){\r
12132         this.focusEl.focus(10);\r
12133     },\r
12134 \r
12135     // private\r
12136     onBeforeDragStart : function(e){\r
12137         return !this.disabled;\r
12138     },\r
12139 \r
12140     // private\r
12141     onDragStart: function(e){\r
12142         this.thumb.addClass('x-slider-thumb-drag');\r
12143         this.dragging = true;\r
12144         this.dragStartValue = this.value;\r
12145         this.fireEvent('dragstart', this, e);\r
12146     },\r
12147 \r
12148     // private\r
12149     onDrag: function(e){\r
12150         var pos = this.innerEl.translatePoints(this.tracker.getXY());\r
12151         this.setValue(Ext.util.Format.round(this.reverseValue(pos.left), this.decimalPrecision), false);\r
12152         this.fireEvent('drag', this, e);\r
12153     },\r
12154 \r
12155     // private\r
12156     onDragEnd: function(e){\r
12157         this.thumb.removeClass('x-slider-thumb-drag');\r
12158         this.dragging = false;\r
12159         this.fireEvent('dragend', this, e);\r
12160         if(this.dragStartValue != this.value){\r
12161             this.fireEvent('changecomplete', this, this.value);\r
12162         }\r
12163     },\r
12164 \r
12165     // private\r
12166     onResize : function(w, h){\r
12167         this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));\r
12168         this.syncThumb();\r
12169         Ext.Slider.superclass.onResize.apply(this, arguments);\r
12170     },\r
12171 \r
12172     //private\r
12173     onDisable: function(){\r
12174         Ext.Slider.superclass.onDisable.call(this);\r
12175         this.thumb.addClass(this.disabledClass);\r
12176         if(Ext.isIE){\r
12177             //IE breaks when using overflow visible and opacity other than 1.\r
12178             //Create a place holder for the thumb and display it.\r
12179             var xy = this.thumb.getXY();\r
12180             this.thumb.hide();\r
12181             this.innerEl.addClass(this.disabledClass).dom.disabled = true;\r
12182             if (!this.thumbHolder){\r
12183                 this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});\r
12184             }\r
12185             this.thumbHolder.show().setXY(xy);\r
12186         }\r
12187     },\r
12188 \r
12189     //private\r
12190     onEnable: function(){\r
12191         Ext.Slider.superclass.onEnable.call(this);\r
12192         this.thumb.removeClass(this.disabledClass);\r
12193         if(Ext.isIE){\r
12194             this.innerEl.removeClass(this.disabledClass).dom.disabled = false;\r
12195             if(this.thumbHolder){\r
12196                 this.thumbHolder.hide();\r
12197             }\r
12198             this.thumb.show();\r
12199             this.syncThumb();\r
12200         }\r
12201     },\r
12202 \r
12203     /**\r
12204      * Synchronizes the thumb position to the proper proportion of the total component width based\r
12205      * on the current slider {@link #value}.  This will be called automatically when the Slider\r
12206      * is resized by a layout, but if it is rendered auto width, this method can be called from\r
12207      * another resize handler to sync the Slider if necessary.\r
12208      */\r
12209     syncThumb : function(){\r
12210         if(this.rendered){\r
12211             this.moveThumb(this.translateValue(this.value));\r
12212         }\r
12213     },\r
12214 \r
12215     /**\r
12216      * Returns the current value of the slider\r
12217      * @return {Number} The current value of the slider\r
12218      */\r
12219     getValue : function(){\r
12220         return this.value;\r
12221     },\r
12222 \r
12223     // private\r
12224     beforeDestroy : function(){\r
12225         Ext.destroyMembers(this, 'endEl', 'innerEl', 'thumb', 'halfThumb', 'focusEl', 'tracker', 'thumbHolder');\r
12226         Ext.Slider.superclass.beforeDestroy.call(this);\r
12227     }\r
12228 });\r
12229 Ext.reg('slider', Ext.Slider);\r
12230 \r
12231 // private class to support vertical sliders\r
12232 Ext.Slider.Vertical = {\r
12233     onResize : function(w, h){\r
12234         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));\r
12235         this.syncThumb();\r
12236     },\r
12237 \r
12238     getRatio : function(){\r
12239         var h = this.innerEl.getHeight(),\r
12240             v = this.maxValue - this.minValue;\r
12241         return h/v;\r
12242     },\r
12243 \r
12244     moveThumb: function(v, animate){\r
12245         if(!animate || this.animate === false){\r
12246             this.thumb.setBottom(v);\r
12247         }else{\r
12248             this.thumb.shift({bottom: v, stopFx: true, duration:.35});\r
12249         }\r
12250     },\r
12251 \r
12252     onDrag: function(e){\r
12253         var pos = this.innerEl.translatePoints(this.tracker.getXY()),\r
12254             bottom = this.innerEl.getHeight()-pos.top;\r
12255         this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), false);\r
12256         this.fireEvent('drag', this, e);\r
12257     },\r
12258 \r
12259     onClickChange : function(local){\r
12260         if(local.left > this.clickRange[0] && local.left < this.clickRange[1]){\r
12261             var bottom = this.innerEl.getHeight() - local.top;\r
12262             this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), undefined, true);\r
12263         }\r
12264     }\r
12265 };/**\r
12266  * @class Ext.ProgressBar\r
12267  * @extends Ext.BoxComponent\r
12268  * <p>An updateable progress bar component.  The progress bar supports two different modes: manual and automatic.</p>\r
12269  * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the\r
12270  * progress bar as needed from your own code.  This method is most appropriate when you want to show progress\r
12271  * throughout an operation that has predictable points of interest at which you can update the control.</p>\r
12272  * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it\r
12273  * once the operation is complete.  You can optionally have the progress bar wait for a specific amount of time\r
12274  * and then clear itself.  Automatic mode is most appropriate for timed operations or asynchronous operations in\r
12275  * which you have no need for indicating intermediate progress.</p>\r
12276  * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0)\r
12277  * @cfg {String} text The progress bar text (defaults to '')\r
12278  * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress\r
12279  * bar's internal text element)\r
12280  * @cfg {String} id The progress bar element's id (defaults to an auto-generated id)\r
12281  * @xtype progress\r
12282  */\r
12283 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {\r
12284    /**\r
12285     * @cfg {String} baseCls\r
12286     * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress')\r
12287     */\r
12288     baseCls : 'x-progress',\r
12289     \r
12290     /**\r
12291     * @cfg {Boolean} animate\r
12292     * True to animate the progress bar during transitions (defaults to false)\r
12293     */\r
12294     animate : false,\r
12295 \r
12296     // private\r
12297     waitTimer : null,\r
12298 \r
12299     // private\r
12300     initComponent : function(){\r
12301         Ext.ProgressBar.superclass.initComponent.call(this);\r
12302         this.addEvents(\r
12303             /**\r
12304              * @event update\r
12305              * Fires after each update interval\r
12306              * @param {Ext.ProgressBar} this\r
12307              * @param {Number} The current progress value\r
12308              * @param {String} The current progress text\r
12309              */\r
12310             "update"\r
12311         );\r
12312     },\r
12313 \r
12314     // private\r
12315     onRender : function(ct, position){\r
12316         var tpl = new Ext.Template(\r
12317             '<div class="{cls}-wrap">',\r
12318                 '<div class="{cls}-inner">',\r
12319                     '<div class="{cls}-bar">',\r
12320                         '<div class="{cls}-text">',\r
12321                             '<div>&#160;</div>',\r
12322                         '</div>',\r
12323                     '</div>',\r
12324                     '<div class="{cls}-text {cls}-text-back">',\r
12325                         '<div>&#160;</div>',\r
12326                     '</div>',\r
12327                 '</div>',\r
12328             '</div>'\r
12329         );\r
12330 \r
12331         this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)\r
12332                 : tpl.append(ct, {cls: this.baseCls}, true);\r
12333                         \r
12334         if(this.id){\r
12335             this.el.dom.id = this.id;\r
12336         }\r
12337         var inner = this.el.dom.firstChild;\r
12338         this.progressBar = Ext.get(inner.firstChild);\r
12339 \r
12340         if(this.textEl){\r
12341             //use an external text el\r
12342             this.textEl = Ext.get(this.textEl);\r
12343             delete this.textTopEl;\r
12344         }else{\r
12345             //setup our internal layered text els\r
12346             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);\r
12347             var textBackEl = Ext.get(inner.childNodes[1]);\r
12348             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');\r
12349             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);\r
12350             this.textEl.setWidth(inner.offsetWidth);\r
12351         }\r
12352         this.progressBar.setHeight(inner.offsetHeight);\r
12353     },\r
12354     \r
12355     // private\r
12356     afterRender : function(){\r
12357         Ext.ProgressBar.superclass.afterRender.call(this);\r
12358         if(this.value){\r
12359             this.updateProgress(this.value, this.text);\r
12360         }else{\r
12361             this.updateText(this.text);\r
12362         }\r
12363     },\r
12364 \r
12365     /**\r
12366      * Updates the progress bar value, and optionally its text.  If the text argument is not specified,\r
12367      * any existing text value will be unchanged.  To blank out existing text, pass ''.  Note that even\r
12368      * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for\r
12369      * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control.\r
12370      * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0)\r
12371      * @param {String} text (optional) The string to display in the progress text element (defaults to '')\r
12372      * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is\r
12373      * not specified, the default for the class is used (default to false)\r
12374      * @return {Ext.ProgressBar} this\r
12375      */\r
12376     updateProgress : function(value, text, animate){\r
12377         this.value = value || 0;\r
12378         if(text){\r
12379             this.updateText(text);\r
12380         }\r
12381         if(this.rendered && !this.isDestroyed){\r
12382             var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);\r
12383             this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));\r
12384             if(this.textTopEl){\r
12385                 //textTopEl should be the same width as the bar so overflow will clip as the bar moves\r
12386                 this.textTopEl.removeClass('x-hidden').setWidth(w);\r
12387             }\r
12388         }\r
12389         this.fireEvent('update', this, value, text);\r
12390         return this;\r
12391     },\r
12392 \r
12393     /**\r
12394      * Initiates an auto-updating progress bar.  A duration can be specified, in which case the progress\r
12395      * bar will automatically reset after a fixed amount of time and optionally call a callback function\r
12396      * if specified.  If no duration is passed in, then the progress bar will run indefinitely and must\r
12397      * be manually cleared by calling {@link #reset}.  The wait method accepts a config object with\r
12398      * the following properties:\r
12399      * <pre>\r
12400 Property   Type          Description\r
12401 ---------- ------------  ----------------------------------------------------------------------\r
12402 duration   Number        The length of time in milliseconds that the progress bar should\r
12403                          run before resetting itself (defaults to undefined, in which case it\r
12404                          will run indefinitely until reset is called)\r
12405 interval   Number        The length of time in milliseconds between each progress update\r
12406                          (defaults to 1000 ms)\r
12407 animate    Boolean       Whether to animate the transition of the progress bar. If this value is\r
12408                          not specified, the default for the class is used.                                                   \r
12409 increment  Number        The number of progress update segments to display within the progress\r
12410                          bar (defaults to 10).  If the bar reaches the end and is still\r
12411                          updating, it will automatically wrap back to the beginning.\r
12412 text       String        Optional text to display in the progress bar element (defaults to '').\r
12413 fn         Function      A callback function to execute after the progress bar finishes auto-\r
12414                          updating.  The function will be called with no arguments.  This function\r
12415                          will be ignored if duration is not specified since in that case the\r
12416                          progress bar can only be stopped programmatically, so any required function\r
12417                          should be called by the same code after it resets the progress bar.\r
12418 scope      Object        The scope that is passed to the callback function (only applies when\r
12419                          duration and fn are both passed).\r
12420 </pre>\r
12421          *\r
12422          * Example usage:\r
12423          * <pre><code>\r
12424 var p = new Ext.ProgressBar({\r
12425    renderTo: 'my-el'\r
12426 });\r
12427 \r
12428 //Wait for 5 seconds, then update the status el (progress bar will auto-reset)\r
12429 p.wait({\r
12430    interval: 100, //bar will move fast!\r
12431    duration: 5000,\r
12432    increment: 15,\r
12433    text: 'Updating...',\r
12434    scope: this,\r
12435    fn: function(){\r
12436       Ext.fly('status').update('Done!');\r
12437    }\r
12438 });\r
12439 \r
12440 //Or update indefinitely until some async action completes, then reset manually\r
12441 p.wait();\r
12442 myAction.on('complete', function(){\r
12443     p.reset();\r
12444     Ext.fly('status').update('Done!');\r
12445 });\r
12446 </code></pre>\r
12447      * @param {Object} config (optional) Configuration options\r
12448      * @return {Ext.ProgressBar} this\r
12449      */\r
12450     wait : function(o){\r
12451         if(!this.waitTimer){\r
12452             var scope = this;\r
12453             o = o || {};\r
12454             this.updateText(o.text);\r
12455             this.waitTimer = Ext.TaskMgr.start({\r
12456                 run: function(i){\r
12457                     var inc = o.increment || 10;\r
12458                     i -= 1;\r
12459                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);\r
12460                 },\r
12461                 interval: o.interval || 1000,\r
12462                 duration: o.duration,\r
12463                 onStop: function(){\r
12464                     if(o.fn){\r
12465                         o.fn.apply(o.scope || this);\r
12466                     }\r
12467                     this.reset();\r
12468                 },\r
12469                 scope: scope\r
12470             });\r
12471         }\r
12472         return this;\r
12473     },\r
12474 \r
12475     /**\r
12476      * Returns true if the progress bar is currently in a {@link #wait} operation\r
12477      * @return {Boolean} True if waiting, else false\r
12478      */\r
12479     isWaiting : function(){\r
12480         return this.waitTimer !== null;\r
12481     },\r
12482 \r
12483     /**\r
12484      * Updates the progress bar text.  If specified, textEl will be updated, otherwise the progress\r
12485      * bar itself will display the updated text.\r
12486      * @param {String} text (optional) The string to display in the progress text element (defaults to '')\r
12487      * @return {Ext.ProgressBar} this\r
12488      */\r
12489     updateText : function(text){\r
12490         this.text = text || '&#160;';\r
12491         if(this.rendered){\r
12492             this.textEl.update(this.text);\r
12493         }\r
12494         return this;\r
12495     },\r
12496     \r
12497     /**\r
12498      * Synchronizes the inner bar width to the proper proportion of the total componet width based\r
12499      * on the current progress {@link #value}.  This will be called automatically when the ProgressBar\r
12500      * is resized by a layout, but if it is rendered auto width, this method can be called from\r
12501      * another resize handler to sync the ProgressBar if necessary.\r
12502      */\r
12503     syncProgressBar : function(){\r
12504         if(this.value){\r
12505             this.updateProgress(this.value, this.text);\r
12506         }\r
12507         return this;\r
12508     },\r
12509 \r
12510     /**\r
12511      * Sets the size of the progress bar.\r
12512      * @param {Number} width The new width in pixels\r
12513      * @param {Number} height The new height in pixels\r
12514      * @return {Ext.ProgressBar} this\r
12515      */\r
12516     setSize : function(w, h){\r
12517         Ext.ProgressBar.superclass.setSize.call(this, w, h);\r
12518         if(this.textTopEl){\r
12519             var inner = this.el.dom.firstChild;\r
12520             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);\r
12521         }\r
12522         this.syncProgressBar();\r
12523         return this;\r
12524     },\r
12525 \r
12526     /**\r
12527      * Resets the progress bar value to 0 and text to empty string.  If hide = true, the progress\r
12528      * bar will also be hidden (using the {@link #hideMode} property internally).\r
12529      * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false)\r
12530      * @return {Ext.ProgressBar} this\r
12531      */\r
12532     reset : function(hide){\r
12533         this.updateProgress(0);\r
12534         if(this.textTopEl){\r
12535             this.textTopEl.addClass('x-hidden');\r
12536         }\r
12537         this.clearTimer();\r
12538         if(hide === true){\r
12539             this.hide();\r
12540         }\r
12541         return this;\r
12542     },\r
12543     \r
12544     // private\r
12545     clearTimer : function(){\r
12546         if(this.waitTimer){\r
12547             this.waitTimer.onStop = null; //prevent recursion\r
12548             Ext.TaskMgr.stop(this.waitTimer);\r
12549             this.waitTimer = null;\r
12550         }\r
12551     },\r
12552     \r
12553     onDestroy: function(){\r
12554         this.clearTimer();\r
12555         if(this.rendered){\r
12556             if(this.textEl.isComposite){\r
12557                 this.textEl.clear();\r
12558             }\r
12559             Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');\r
12560         }\r
12561         Ext.ProgressBar.superclass.onDestroy.call(this);\r
12562     }\r
12563 });\r
12564 Ext.reg('progress', Ext.ProgressBar);