Upgrade to ExtJS 3.3.0 - Released 10/06/2010
[extjs.git] / pkgs / cmp-foundation-debug.js
1 /*!
2  * Ext JS Library 3.3.0
3  * Copyright(c) 2006-2010 Ext JS, Inc.
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**
8  * @class Ext.ComponentMgr
9  * <p>Provides a registry of all Components (instances of {@link Ext.Component} or any subclass
10  * thereof) on a page so that they can be easily accessed by {@link Ext.Component component}
11  * {@link Ext.Component#id id} (see {@link #get}, or the convenience method {@link Ext#getCmp Ext.getCmp}).</p>
12  * <p>This object also provides a registry of available Component <i>classes</i>
13  * indexed by a mnemonic code known as the Component's {@link Ext.Component#xtype xtype}.
14  * The <code>{@link Ext.Component#xtype xtype}</code> provides a way to avoid instantiating child Components
15  * when creating a full, nested config object for a complete Ext page.</p>
16  * <p>A child Component may be specified simply as a <i>config object</i>
17  * as long as the correct <code>{@link Ext.Component#xtype xtype}</code> is specified so that if and when the Component
18  * needs rendering, the correct type can be looked up for lazy instantiation.</p>
19  * <p>For a list of all available <code>{@link Ext.Component#xtype xtypes}</code>, see {@link Ext.Component}.</p>
20  * @singleton
21  */
22 Ext.ComponentMgr = function(){
23     var all = new Ext.util.MixedCollection();
24     var types = {};
25     var ptypes = {};
26
27     return {
28         /**
29          * Registers a component.
30          * @param {Ext.Component} c The component
31          */
32         register : function(c){
33             all.add(c);
34         },
35
36         /**
37          * Unregisters a component.
38          * @param {Ext.Component} c The component
39          */
40         unregister : function(c){
41             all.remove(c);
42         },
43
44         /**
45          * Returns a component by {@link Ext.Component#id id}.
46          * For additional details see {@link Ext.util.MixedCollection#get}.
47          * @param {String} id The component {@link Ext.Component#id id}
48          * @return Ext.Component The Component, <code>undefined</code> if not found, or <code>null</code> if a
49          * Class was found.
50          */
51         get : function(id){
52             return all.get(id);
53         },
54
55         /**
56          * Registers a function that will be called when a Component with the specified id is added to ComponentMgr. This will happen on instantiation.
57          * @param {String} id The component {@link Ext.Component#id id}
58          * @param {Function} fn The callback function
59          * @param {Object} scope The scope (<code>this</code> reference) in which the callback is executed. Defaults to the Component.
60          */
61         onAvailable : function(id, fn, scope){
62             all.on("add", function(index, o){
63                 if(o.id == id){
64                     fn.call(scope || o, o);
65                     all.un("add", fn, scope);
66                 }
67             });
68         },
69
70         /**
71          * The MixedCollection used internally for the component cache. An example usage may be subscribing to
72          * events on the MixedCollection to monitor addition or removal.  Read-only.
73          * @type {MixedCollection}
74          */
75         all : all,
76         
77         /**
78          * The xtypes that have been registered with the component manager.
79          * @type {Object}
80          */
81         types : types,
82         
83         /**
84          * The ptypes that have been registered with the component manager.
85          * @type {Object}
86          */
87         ptypes: ptypes,
88         
89         /**
90          * Checks if a Component type is registered.
91          * @param {Ext.Component} xtype The mnemonic string by which the Component class may be looked up
92          * @return {Boolean} Whether the type is registered.
93          */
94         isRegistered : function(xtype){
95             return types[xtype] !== undefined;    
96         },
97         
98         /**
99          * Checks if a Plugin type is registered.
100          * @param {Ext.Component} ptype The mnemonic string by which the Plugin class may be looked up
101          * @return {Boolean} Whether the type is registered.
102          */
103         isPluginRegistered : function(ptype){
104             return ptypes[ptype] !== undefined;    
105         },        
106
107         /**
108          * <p>Registers a new Component constructor, keyed by a new
109          * {@link Ext.Component#xtype}.</p>
110          * <p>Use this method (or its alias {@link Ext#reg Ext.reg}) to register new
111          * subclasses of {@link Ext.Component} so that lazy instantiation may be used when specifying
112          * child Components.
113          * see {@link Ext.Container#items}</p>
114          * @param {String} xtype The mnemonic string by which the Component class may be looked up.
115          * @param {Constructor} cls The new Component class.
116          */
117         registerType : function(xtype, cls){
118             types[xtype] = cls;
119             cls.xtype = xtype;
120         },
121
122         /**
123          * Creates a new Component from the specified config object using the
124          * config object's {@link Ext.component#xtype xtype} to determine the class to instantiate.
125          * @param {Object} config A configuration object for the Component you wish to create.
126          * @param {Constructor} defaultType The constructor to provide the default Component type if
127          * the config object does not contain a <code>xtype</code>. (Optional if the config contains a <code>xtype</code>).
128          * @return {Ext.Component} The newly instantiated Component.
129          */
130         create : function(config, defaultType){
131             return config.render ? config : new types[config.xtype || defaultType](config);
132         },
133
134         /**
135          * <p>Registers a new Plugin constructor, keyed by a new
136          * {@link Ext.Component#ptype}.</p>
137          * <p>Use this method (or its alias {@link Ext#preg Ext.preg}) to register new
138          * plugins for {@link Ext.Component}s so that lazy instantiation may be used when specifying
139          * Plugins.</p>
140          * @param {String} ptype The mnemonic string by which the Plugin class may be looked up.
141          * @param {Constructor} cls The new Plugin class.
142          */
143         registerPlugin : function(ptype, cls){
144             ptypes[ptype] = cls;
145             cls.ptype = ptype;
146         },
147
148         /**
149          * Creates a new Plugin from the specified config object using the
150          * config object's {@link Ext.component#ptype ptype} to determine the class to instantiate.
151          * @param {Object} config A configuration object for the Plugin you wish to create.
152          * @param {Constructor} defaultType The constructor to provide the default Plugin type if
153          * the config object does not contain a <code>ptype</code>. (Optional if the config contains a <code>ptype</code>).
154          * @return {Ext.Component} The newly instantiated Plugin.
155          */
156         createPlugin : function(config, defaultType){
157             var PluginCls = ptypes[config.ptype || defaultType];
158             if (PluginCls.init) {
159                 return PluginCls;                
160             } else {
161                 return new PluginCls(config);
162             }            
163         }
164     };
165 }();
166
167 /**
168  * Shorthand for {@link Ext.ComponentMgr#registerType}
169  * @param {String} xtype The {@link Ext.component#xtype mnemonic string} by which the Component class
170  * may be looked up.
171  * @param {Constructor} cls The new Component class.
172  * @member Ext
173  * @method reg
174  */
175 Ext.reg = Ext.ComponentMgr.registerType; // this will be called a lot internally, shorthand to keep the bytes down
176 /**
177  * Shorthand for {@link Ext.ComponentMgr#registerPlugin}
178  * @param {String} ptype The {@link Ext.component#ptype mnemonic string} by which the Plugin class
179  * may be looked up.
180  * @param {Constructor} cls The new Plugin class.
181  * @member Ext
182  * @method preg
183  */
184 Ext.preg = Ext.ComponentMgr.registerPlugin;
185 /**
186  * Shorthand for {@link Ext.ComponentMgr#create}
187  * Creates a new Component from the specified config object using the
188  * config object's {@link Ext.component#xtype xtype} to determine the class to instantiate.
189  * @param {Object} config A configuration object for the Component you wish to create.
190  * @param {Constructor} defaultType The constructor to provide the default Component type if
191  * the config object does not contain a <code>xtype</code>. (Optional if the config contains a <code>xtype</code>).
192  * @return {Ext.Component} The newly instantiated Component.
193  * @member Ext
194  * @method create
195  */
196 Ext.create = Ext.ComponentMgr.create;/**
197  * @class Ext.Component
198  * @extends Ext.util.Observable
199  * <p>Base class for all Ext components.  All subclasses of Component may participate in the automated
200  * Ext component lifecycle of creation, rendering and destruction which is provided by the {@link Ext.Container Container} class.
201  * Components may be added to a Container through the {@link Ext.Container#items items} config option at the time the Container is created,
202  * or they may be added dynamically via the {@link Ext.Container#add add} method.</p>
203  * <p>The Component base class has built-in support for basic hide/show and enable/disable behavior.</p>
204  * <p>All Components are registered with the {@link Ext.ComponentMgr} on construction so that they can be referenced at any time via
205  * {@link Ext#getCmp}, passing the {@link #id}.</p>
206  * <p>All user-developed visual widgets that are required to participate in automated lifecycle and size management should subclass Component (or
207  * {@link Ext.BoxComponent} if managed box model handling is required, ie height and width management).</p>
208  * <p>See the <a href="http://extjs.com/learn/Tutorial:Creating_new_UI_controls">Creating new UI controls</a> tutorial for details on how
209  * and to either extend or augment ExtJs base classes to create custom Components.</p>
210  * <p>Every component has a specific xtype, which is its Ext-specific type name, along with methods for checking the
211  * xtype like {@link #getXType} and {@link #isXType}. This is the list of all valid xtypes:</p>
212  * <pre>
213 xtype            Class
214 -------------    ------------------
215 box              {@link Ext.BoxComponent}
216 button           {@link Ext.Button}
217 buttongroup      {@link Ext.ButtonGroup}
218 colorpalette     {@link Ext.ColorPalette}
219 component        {@link Ext.Component}
220 container        {@link Ext.Container}
221 cycle            {@link Ext.CycleButton}
222 dataview         {@link Ext.DataView}
223 datepicker       {@link Ext.DatePicker}
224 editor           {@link Ext.Editor}
225 editorgrid       {@link Ext.grid.EditorGridPanel}
226 flash            {@link Ext.FlashComponent}
227 grid             {@link Ext.grid.GridPanel}
228 listview         {@link Ext.ListView}
229 multislider      {@link Ext.slider.MultiSlider}
230 panel            {@link Ext.Panel}
231 progress         {@link Ext.ProgressBar}
232 propertygrid     {@link Ext.grid.PropertyGrid}
233 slider           {@link Ext.slider.SingleSlider}
234 spacer           {@link Ext.Spacer}
235 splitbutton      {@link Ext.SplitButton}
236 tabpanel         {@link Ext.TabPanel}
237 treepanel        {@link Ext.tree.TreePanel}
238 viewport         {@link Ext.ViewPort}
239 window           {@link Ext.Window}
240
241 Toolbar components
242 ---------------------------------------
243 paging           {@link Ext.PagingToolbar}
244 toolbar          {@link Ext.Toolbar}
245 tbbutton         {@link Ext.Toolbar.Button}        (deprecated; use button)
246 tbfill           {@link Ext.Toolbar.Fill}
247 tbitem           {@link Ext.Toolbar.Item}
248 tbseparator      {@link Ext.Toolbar.Separator}
249 tbspacer         {@link Ext.Toolbar.Spacer}
250 tbsplit          {@link Ext.Toolbar.SplitButton}   (deprecated; use splitbutton)
251 tbtext           {@link Ext.Toolbar.TextItem}
252
253 Menu components
254 ---------------------------------------
255 menu             {@link Ext.menu.Menu}
256 colormenu        {@link Ext.menu.ColorMenu}
257 datemenu         {@link Ext.menu.DateMenu}
258 menubaseitem     {@link Ext.menu.BaseItem}
259 menucheckitem    {@link Ext.menu.CheckItem}
260 menuitem         {@link Ext.menu.Item}
261 menuseparator    {@link Ext.menu.Separator}
262 menutextitem     {@link Ext.menu.TextItem}
263
264 Form components
265 ---------------------------------------
266 form             {@link Ext.form.FormPanel}
267 checkbox         {@link Ext.form.Checkbox}
268 checkboxgroup    {@link Ext.form.CheckboxGroup}
269 combo            {@link Ext.form.ComboBox}
270 compositefield   {@link Ext.form.CompositeField}
271 datefield        {@link Ext.form.DateField}
272 displayfield     {@link Ext.form.DisplayField}
273 field            {@link Ext.form.Field}
274 fieldset         {@link Ext.form.FieldSet}
275 hidden           {@link Ext.form.Hidden}
276 htmleditor       {@link Ext.form.HtmlEditor}
277 label            {@link Ext.form.Label}
278 numberfield      {@link Ext.form.NumberField}
279 radio            {@link Ext.form.Radio}
280 radiogroup       {@link Ext.form.RadioGroup}
281 textarea         {@link Ext.form.TextArea}
282 textfield        {@link Ext.form.TextField}
283 timefield        {@link Ext.form.TimeField}
284 trigger          {@link Ext.form.TriggerField}
285
286 Chart components
287 ---------------------------------------
288 chart            {@link Ext.chart.Chart}
289 barchart         {@link Ext.chart.BarChart}
290 cartesianchart   {@link Ext.chart.CartesianChart}
291 columnchart      {@link Ext.chart.ColumnChart}
292 linechart        {@link Ext.chart.LineChart}
293 piechart         {@link Ext.chart.PieChart}
294
295 Store xtypes
296 ---------------------------------------
297 arraystore       {@link Ext.data.ArrayStore}
298 directstore      {@link Ext.data.DirectStore}
299 groupingstore    {@link Ext.data.GroupingStore}
300 jsonstore        {@link Ext.data.JsonStore}
301 simplestore      {@link Ext.data.SimpleStore}      (deprecated; use arraystore)
302 store            {@link Ext.data.Store}
303 xmlstore         {@link Ext.data.XmlStore}
304 </pre>
305  * @constructor
306  * @param {Ext.Element/String/Object} config The configuration options may be specified as either:
307  * <div class="mdetail-params"><ul>
308  * <li><b>an element</b> :
309  * <p class="sub-desc">it is set as the internal element and its id used as the component id</p></li>
310  * <li><b>a string</b> :
311  * <p class="sub-desc">it is assumed to be the id of an existing element and is used as the component id</p></li>
312  * <li><b>anything else</b> :
313  * <p class="sub-desc">it is assumed to be a standard config object and is applied to the component</p></li>
314  * </ul></div>
315  */
316 Ext.Component = function(config){
317     config = config || {};
318     if(config.initialConfig){
319         if(config.isAction){           // actions
320             this.baseAction = config;
321         }
322         config = config.initialConfig; // component cloning / action set up
323     }else if(config.tagName || config.dom || Ext.isString(config)){ // element object
324         config = {applyTo: config, id: config.id || config};
325     }
326
327     /**
328      * This Component's initial configuration specification. Read-only.
329      * @type Object
330      * @property initialConfig
331      */
332     this.initialConfig = config;
333
334     Ext.apply(this, config);
335     this.addEvents(
336         /**
337          * @event added
338          * Fires when a component is added to an Ext.Container
339          * @param {Ext.Component} this
340          * @param {Ext.Container} ownerCt Container which holds the component
341          * @param {number} index Position at which the component was added
342          */
343         'added',
344         /**
345          * @event disable
346          * Fires after the component is disabled.
347          * @param {Ext.Component} this
348          */
349         'disable',
350         /**
351          * @event enable
352          * Fires after the component is enabled.
353          * @param {Ext.Component} this
354          */
355         'enable',
356         /**
357          * @event beforeshow
358          * Fires before the component is shown by calling the {@link #show} method.
359          * Return false from an event handler to stop the show.
360          * @param {Ext.Component} this
361          */
362         'beforeshow',
363         /**
364          * @event show
365          * Fires after the component is shown when calling the {@link #show} method.
366          * @param {Ext.Component} this
367          */
368         'show',
369         /**
370          * @event beforehide
371          * Fires before the component is hidden by calling the {@link #hide} method.
372          * Return false from an event handler to stop the hide.
373          * @param {Ext.Component} this
374          */
375         'beforehide',
376         /**
377          * @event hide
378          * Fires after the component is hidden.
379          * Fires after the component is hidden when calling the {@link #hide} method.
380          * @param {Ext.Component} this
381          */
382         'hide',
383         /**
384          * @event removed
385          * Fires when a component is removed from an Ext.Container
386          * @param {Ext.Component} this
387          * @param {Ext.Container} ownerCt Container which holds the component
388          */
389         'removed',
390         /**
391          * @event beforerender
392          * Fires before the component is {@link #rendered}. Return false from an
393          * event handler to stop the {@link #render}.
394          * @param {Ext.Component} this
395          */
396         'beforerender',
397         /**
398          * @event render
399          * Fires after the component markup is {@link #rendered}.
400          * @param {Ext.Component} this
401          */
402         'render',
403         /**
404          * @event afterrender
405          * <p>Fires after the component rendering is finished.</p>
406          * <p>The afterrender event is fired after this Component has been {@link #rendered}, been postprocesed
407          * by any afterRender method defined for the Component, and, if {@link #stateful}, after state
408          * has been restored.</p>
409          * @param {Ext.Component} this
410          */
411         'afterrender',
412         /**
413          * @event beforedestroy
414          * Fires before the component is {@link #destroy}ed. Return false from an event handler to stop the {@link #destroy}.
415          * @param {Ext.Component} this
416          */
417         'beforedestroy',
418         /**
419          * @event destroy
420          * Fires after the component is {@link #destroy}ed.
421          * @param {Ext.Component} this
422          */
423         'destroy',
424         /**
425          * @event beforestaterestore
426          * Fires before the state of the component is restored. Return false from an event handler to stop the restore.
427          * @param {Ext.Component} this
428          * @param {Object} state The hash of state values returned from the StateProvider. If this
429          * event is not vetoed, then the state object is passed to <b><tt>applyState</tt></b>. By default,
430          * that simply copies property values into this Component. The method maybe overriden to
431          * provide custom state restoration.
432          */
433         'beforestaterestore',
434         /**
435          * @event staterestore
436          * Fires after the state of the component is restored.
437          * @param {Ext.Component} this
438          * @param {Object} state The hash of state values returned from the StateProvider. This is passed
439          * to <b><tt>applyState</tt></b>. By default, that simply copies property values into this
440          * Component. The method maybe overriden to provide custom state restoration.
441          */
442         'staterestore',
443         /**
444          * @event beforestatesave
445          * Fires before the state of the component is saved to the configured state provider. Return false to stop the save.
446          * @param {Ext.Component} this
447          * @param {Object} state The hash of state values. This is determined by calling
448          * <b><tt>getState()</tt></b> on the Component. This method must be provided by the
449          * developer to return whetever representation of state is required, by default, Ext.Component
450          * has a null implementation.
451          */
452         'beforestatesave',
453         /**
454          * @event statesave
455          * Fires after the state of the component is saved to the configured state provider.
456          * @param {Ext.Component} this
457          * @param {Object} state The hash of state values. This is determined by calling
458          * <b><tt>getState()</tt></b> on the Component. This method must be provided by the
459          * developer to return whetever representation of state is required, by default, Ext.Component
460          * has a null implementation.
461          */
462         'statesave'
463     );
464     this.getId();
465     Ext.ComponentMgr.register(this);
466     Ext.Component.superclass.constructor.call(this);
467
468     if(this.baseAction){
469         this.baseAction.addComponent(this);
470     }
471
472     this.initComponent();
473
474     if(this.plugins){
475         if(Ext.isArray(this.plugins)){
476             for(var i = 0, len = this.plugins.length; i < len; i++){
477                 this.plugins[i] = this.initPlugin(this.plugins[i]);
478             }
479         }else{
480             this.plugins = this.initPlugin(this.plugins);
481         }
482     }
483
484     if(this.stateful !== false){
485         this.initState();
486     }
487
488     if(this.applyTo){
489         this.applyToMarkup(this.applyTo);
490         delete this.applyTo;
491     }else if(this.renderTo){
492         this.render(this.renderTo);
493         delete this.renderTo;
494     }
495 };
496
497 // private
498 Ext.Component.AUTO_ID = 1000;
499
500 Ext.extend(Ext.Component, Ext.util.Observable, {
501     // Configs below are used for all Components when rendered by FormLayout.
502     /**
503      * @cfg {String} fieldLabel <p>The label text to display next to this Component (defaults to '').</p>
504      * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container which
505      * has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout manager (e.g.
506      * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>).</p><br>
507      * <p>Also see <tt>{@link #hideLabel}</tt> and
508      * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</p>
509      * Example use:<pre><code>
510 new Ext.FormPanel({
511     height: 100,
512     renderTo: Ext.getBody(),
513     items: [{
514         xtype: 'textfield',
515         fieldLabel: 'Name'
516     }]
517 });
518 </code></pre>
519      */
520     /**
521      * @cfg {String} labelStyle <p>A CSS style specification string to apply directly to this field's
522      * label.  Defaults to the container's labelStyle value if set (e.g.,
523      * <tt>{@link Ext.layout.FormLayout#labelStyle}</tt> , or '').</p>
524      * <br><p><b>Note</b>: see the note for <code>{@link #clearCls}</code>.</p><br>
525      * <p>Also see <code>{@link #hideLabel}</code> and
526      * <code>{@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</code></p>
527      * Example use:<pre><code>
528 new Ext.FormPanel({
529     height: 100,
530     renderTo: Ext.getBody(),
531     items: [{
532         xtype: 'textfield',
533         fieldLabel: 'Name',
534         labelStyle: 'font-weight:bold;'
535     }]
536 });
537 </code></pre>
538      */
539     /**
540      * @cfg {String} labelSeparator <p>The separator to display after the text of each
541      * <tt>{@link #fieldLabel}</tt>.  This property may be configured at various levels.
542      * The order of precedence is:
543      * <div class="mdetail-params"><ul>
544      * <li>field / component level</li>
545      * <li>container level</li>
546      * <li>{@link Ext.layout.FormLayout#labelSeparator layout level} (defaults to colon <tt>':'</tt>)</li>
547      * </ul></div>
548      * To display no separator for this field's label specify empty string ''.</p>
549      * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</tt>.</p><br>
550      * <p>Also see <tt>{@link #hideLabel}</tt> and
551      * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</p>
552      * Example use:<pre><code>
553 new Ext.FormPanel({
554     height: 100,
555     renderTo: Ext.getBody(),
556     layoutConfig: {
557         labelSeparator: '~'   // layout config has lowest priority (defaults to ':')
558     },
559     {@link Ext.layout.FormLayout#labelSeparator labelSeparator}: '>>',     // config at container level
560     items: [{
561         xtype: 'textfield',
562         fieldLabel: 'Field 1',
563         labelSeparator: '...' // field/component level config supersedes others
564     },{
565         xtype: 'textfield',
566         fieldLabel: 'Field 2' // labelSeparator will be '='
567     }]
568 });
569 </code></pre>
570      */
571     /**
572      * @cfg {Boolean} hideLabel <p><tt>true</tt> to completely hide the label element
573      * ({@link #fieldLabel label} and {@link #labelSeparator separator}). Defaults to <tt>false</tt>.
574      * By default, even if you do not specify a <tt>{@link #fieldLabel}</tt> the space will still be
575      * reserved so that the field will line up with other fields that do have labels.
576      * Setting this to <tt>true</tt> will cause the field to not reserve that space.</p>
577      * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</tt>.</p><br>
578      * Example use:<pre><code>
579 new Ext.FormPanel({
580     height: 100,
581     renderTo: Ext.getBody(),
582     items: [{
583         xtype: 'textfield'
584         hideLabel: true
585     }]
586 });
587 </code></pre>
588      */
589     /**
590      * @cfg {String} clearCls <p>The CSS class used to to apply to the special clearing div rendered
591      * directly after each form field wrapper to provide field clearing (defaults to
592      * <tt>'x-form-clear-left'</tt>).</p>
593      * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container
594      * which has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout
595      * manager (e.g. {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) and either a
596      * <tt>{@link #fieldLabel}</tt> is specified or <tt>isFormField=true</tt> is specified.</p><br>
597      * <p>See {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl} also.</p>
598      */
599     /**
600      * @cfg {String} itemCls
601      * <p><b>Note</b>: this config is only used when this Component is rendered by a Container which
602      * has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout manager (e.g.
603      * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>).</p><br>
604      * <p>An additional CSS class to apply to the div wrapping the form item
605      * element of this field.  If supplied, <tt>itemCls</tt> at the <b>field</b> level will override
606      * the default <tt>itemCls</tt> supplied at the <b>container</b> level. The value specified for
607      * <tt>itemCls</tt> will be added to the default class (<tt>'x-form-item'</tt>).</p>
608      * <p>Since it is applied to the item wrapper (see
609      * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}), it allows
610      * you to write standard CSS rules that can apply to the field, the label (if specified), or
611      * any other element within the markup for the field.</p>
612      * <br><p><b>Note</b>: see the note for <tt>{@link #fieldLabel}</tt>.</p><br>
613      * Example use:<pre><code>
614 // Apply a style to the field&#39;s label:
615 &lt;style>
616     .required .x-form-item-label {font-weight:bold;color:red;}
617 &lt;/style>
618
619 new Ext.FormPanel({
620     height: 100,
621     renderTo: Ext.getBody(),
622     items: [{
623         xtype: 'textfield',
624         fieldLabel: 'Name',
625         itemCls: 'required' //this label will be styled
626     },{
627         xtype: 'textfield',
628         fieldLabel: 'Favorite Color'
629     }]
630 });
631 </code></pre>
632      */
633
634     /**
635      * @cfg {String} id
636      * <p>The <b>unique</b> id of this component (defaults to an {@link #getId auto-assigned id}).
637      * You should assign an id if you need to be able to access the component later and you do
638      * not have an object reference available (e.g., using {@link Ext}.{@link Ext#getCmp getCmp}).</p>
639      * <p>Note that this id will also be used as the element id for the containing HTML element
640      * that is rendered to the page for this component. This allows you to write id-based CSS
641      * rules to style the specific instance of this component uniquely, and also to select
642      * sub-elements using this component's id as the parent.</p>
643      * <p><b>Note</b>: to avoid complications imposed by a unique <tt>id</tt> also see
644      * <code>{@link #itemId}</code> and <code>{@link #ref}</code>.</p>
645      * <p><b>Note</b>: to access the container of an item see <code>{@link #ownerCt}</code>.</p>
646      */
647     /**
648      * @cfg {String} itemId
649      * <p>An <tt>itemId</tt> can be used as an alternative way to get a reference to a component
650      * when no object reference is available.  Instead of using an <code>{@link #id}</code> with
651      * {@link Ext}.{@link Ext#getCmp getCmp}, use <code>itemId</code> with
652      * {@link Ext.Container}.{@link Ext.Container#getComponent getComponent} which will retrieve
653      * <code>itemId</code>'s or <tt>{@link #id}</tt>'s. Since <code>itemId</code>'s are an index to the
654      * container's internal MixedCollection, the <code>itemId</code> is scoped locally to the container --
655      * avoiding potential conflicts with {@link Ext.ComponentMgr} which requires a <b>unique</b>
656      * <code>{@link #id}</code>.</p>
657      * <pre><code>
658 var c = new Ext.Panel({ //
659     {@link Ext.BoxComponent#height height}: 300,
660     {@link #renderTo}: document.body,
661     {@link Ext.Container#layout layout}: 'auto',
662     {@link Ext.Container#items items}: [
663         {
664             itemId: 'p1',
665             {@link Ext.Panel#title title}: 'Panel 1',
666             {@link Ext.BoxComponent#height height}: 150
667         },
668         {
669             itemId: 'p2',
670             {@link Ext.Panel#title title}: 'Panel 2',
671             {@link Ext.BoxComponent#height height}: 150
672         }
673     ]
674 })
675 p1 = c.{@link Ext.Container#getComponent getComponent}('p1'); // not the same as {@link Ext#getCmp Ext.getCmp()}
676 p2 = p1.{@link #ownerCt}.{@link Ext.Container#getComponent getComponent}('p2'); // reference via a sibling
677      * </code></pre>
678      * <p>Also see <tt>{@link #id}</tt> and <code>{@link #ref}</code>.</p>
679      * <p><b>Note</b>: to access the container of an item see <tt>{@link #ownerCt}</tt>.</p>
680      */
681     /**
682      * @cfg {String} xtype
683      * The registered <tt>xtype</tt> to create. This config option is not used when passing
684      * a config object into a constructor. This config option is used only when
685      * lazy instantiation is being used, and a child item of a Container is being
686      * specified not as a fully instantiated Component, but as a <i>Component config
687      * object</i>. The <tt>xtype</tt> will be looked up at render time up to determine what
688      * type of child Component to create.<br><br>
689      * The predefined xtypes are listed {@link Ext.Component here}.
690      * <br><br>
691      * If you subclass Components to create your own Components, you may register
692      * them using {@link Ext.ComponentMgr#registerType} in order to be able to
693      * take advantage of lazy instantiation and rendering.
694      */
695     /**
696      * @cfg {String} ptype
697      * The registered <tt>ptype</tt> to create. This config option is not used when passing
698      * a config object into a constructor. This config option is used only when
699      * lazy instantiation is being used, and a Plugin is being
700      * specified not as a fully instantiated Component, but as a <i>Component config
701      * object</i>. The <tt>ptype</tt> will be looked up at render time up to determine what
702      * type of Plugin to create.<br><br>
703      * If you create your own Plugins, you may register them using
704      * {@link Ext.ComponentMgr#registerPlugin} in order to be able to
705      * take advantage of lazy instantiation and rendering.
706      */
707     /**
708      * @cfg {String} cls
709      * An optional extra CSS class that will be added to this component's Element (defaults to '').  This can be
710      * useful for adding customized styles to the component or any of its children using standard CSS rules.
711      */
712     /**
713      * @cfg {String} overCls
714      * An optional extra CSS class that will be added to this component's Element when the mouse moves
715      * over the Element, and removed when the mouse moves out. (defaults to '').  This can be
716      * useful for adding customized 'active' or 'hover' styles to the component or any of its children using standard CSS rules.
717      */
718     /**
719      * @cfg {String} style
720      * A custom style specification to be applied to this component's Element.  Should be a valid argument to
721      * {@link Ext.Element#applyStyles}.
722      * <pre><code>
723 new Ext.Panel({
724     title: 'Some Title',
725     renderTo: Ext.getBody(),
726     width: 400, height: 300,
727     layout: 'form',
728     items: [{
729         xtype: 'textarea',
730         style: {
731             width: '95%',
732             marginBottom: '10px'
733         }
734     },
735         new Ext.Button({
736             text: 'Send',
737             minWidth: '100',
738             style: {
739                 marginBottom: '10px'
740             }
741         })
742     ]
743 });
744      * </code></pre>
745      */
746     /**
747      * @cfg {String} ctCls
748      * <p>An optional extra CSS class that will be added to this component's container. This can be useful for
749      * adding customized styles to the container or any of its children using standard CSS rules.  See
750      * {@link Ext.layout.ContainerLayout}.{@link Ext.layout.ContainerLayout#extraCls extraCls} also.</p>
751      * <p><b>Note</b>: <tt>ctCls</tt> defaults to <tt>''</tt> except for the following class
752      * which assigns a value by default:
753      * <div class="mdetail-params"><ul>
754      * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-layout-ct'</tt></li>
755      * </ul></div>
756      * To configure the above Class with an extra CSS class append to the default.  For example,
757      * for BoxLayout (Hbox and Vbox):<pre><code>
758      * ctCls: 'x-box-layout-ct custom-class'
759      * </code></pre>
760      * </p>
761      */
762     /**
763      * @cfg {Boolean} disabled
764      * Render this component disabled (default is false).
765      */
766     disabled : false,
767     /**
768      * @cfg {Boolean} hidden
769      * Render this component hidden (default is false). If <tt>true</tt>, the
770      * {@link #hide} method will be called internally.
771      */
772     hidden : false,
773     /**
774      * @cfg {Object/Array} plugins
775      * An object or array of objects that will provide custom functionality for this component.  The only
776      * requirement for a valid plugin is that it contain an init method that accepts a reference of type Ext.Component.
777      * When a component is created, if any plugins are available, the component will call the init method on each
778      * plugin, passing a reference to itself.  Each plugin can then call methods or respond to events on the
779      * component as needed to provide its functionality.
780      */
781     /**
782      * @cfg {Mixed} applyTo
783      * <p>Specify the id of the element, a DOM element or an existing Element corresponding to a DIV
784      * that is already present in the document that specifies some structural markup for this
785      * component.</p><div><ul>
786      * <li><b>Description</b> : <ul>
787      * <div class="sub-desc">When <tt>applyTo</tt> is used, constituent parts of the component can also be specified
788      * by id or CSS class name within the main element, and the component being created may attempt
789      * to create its subcomponents from that markup if applicable.</div>
790      * </ul></li>
791      * <li><b>Notes</b> : <ul>
792      * <div class="sub-desc">When using this config, a call to render() is not required.</div>
793      * <div class="sub-desc">If applyTo is specified, any value passed for {@link #renderTo} will be ignored and the target
794      * element's parent node will automatically be used as the component's container.</div>
795      * </ul></li>
796      * </ul></div>
797      */
798     /**
799      * @cfg {Mixed} renderTo
800      * <p>Specify the id of the element, a DOM element or an existing Element that this component
801      * will be rendered into.</p><div><ul>
802      * <li><b>Notes</b> : <ul>
803      * <div class="sub-desc">Do <u>not</u> use this option if the Component is to be a child item of
804      * a {@link Ext.Container Container}. It is the responsibility of the
805      * {@link Ext.Container Container}'s {@link Ext.Container#layout layout manager}
806      * to render and manage its child items.</div>
807      * <div class="sub-desc">When using this config, a call to render() is not required.</div>
808      * </ul></li>
809      * </ul></div>
810      * <p>See <tt>{@link #render}</tt> also.</p>
811      */
812     /**
813      * @cfg {Boolean} stateful
814      * <p>A flag which causes the Component to attempt to restore the state of
815      * internal properties from a saved state on startup. The component must have
816      * either a <code>{@link #stateId}</code> or <code>{@link #id}</code> assigned
817      * for state to be managed. Auto-generated ids are not guaranteed to be stable
818      * across page loads and cannot be relied upon to save and restore the same
819      * state for a component.<p>
820      * <p>For state saving to work, the state manager's provider must have been
821      * set to an implementation of {@link Ext.state.Provider} which overrides the
822      * {@link Ext.state.Provider#set set} and {@link Ext.state.Provider#get get}
823      * methods to save and recall name/value pairs. A built-in implementation,
824      * {@link Ext.state.CookieProvider} is available.</p>
825      * <p>To set the state provider for the current page:</p>
826      * <pre><code>
827 Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
828     expires: new Date(new Date().getTime()+(1000*60*60*24*7)), //7 days from now
829 }));
830      * </code></pre>
831      * <p>A stateful Component attempts to save state when one of the events
832      * listed in the <code>{@link #stateEvents}</code> configuration fires.</p>
833      * <p>To save state, a stateful Component first serializes its state by
834      * calling <b><code>getState</code></b>. By default, this function does
835      * nothing. The developer must provide an implementation which returns an
836      * object hash which represents the Component's restorable state.</p>
837      * <p>The value yielded by getState is passed to {@link Ext.state.Manager#set}
838      * which uses the configured {@link Ext.state.Provider} to save the object
839      * keyed by the Component's <code>{@link stateId}</code>, or, if that is not
840      * specified, its <code>{@link #id}</code>.</p>
841      * <p>During construction, a stateful Component attempts to <i>restore</i>
842      * its state by calling {@link Ext.state.Manager#get} passing the
843      * <code>{@link #stateId}</code>, or, if that is not specified, the
844      * <code>{@link #id}</code>.</p>
845      * <p>The resulting object is passed to <b><code>applyState</code></b>.
846      * The default implementation of <code>applyState</code> simply copies
847      * properties into the object, but a developer may override this to support
848      * more behaviour.</p>
849      * <p>You can perform extra processing on state save and restore by attaching
850      * handlers to the {@link #beforestaterestore}, {@link #staterestore},
851      * {@link #beforestatesave} and {@link #statesave} events.</p>
852      */
853     /**
854      * @cfg {String} stateId
855      * The unique id for this component to use for state management purposes
856      * (defaults to the component id if one was set, otherwise null if the
857      * component is using a generated id).
858      * <p>See <code>{@link #stateful}</code> for an explanation of saving and
859      * restoring Component state.</p>
860      */
861     /**
862      * @cfg {Array} stateEvents
863      * <p>An array of events that, when fired, should trigger this component to
864      * save its state (defaults to none). <code>stateEvents</code> may be any type
865      * of event supported by this component, including browser or custom events
866      * (e.g., <tt>['click', 'customerchange']</tt>).</p>
867      * <p>See <code>{@link #stateful}</code> for an explanation of saving and
868      * restoring Component state.</p>
869      */
870     /**
871      * @cfg {Mixed} autoEl
872      * <p>A tag name or {@link Ext.DomHelper DomHelper} spec used to create the {@link #getEl Element} which will
873      * encapsulate this Component.</p>
874      * <p>You do not normally need to specify this. For the base classes {@link Ext.Component}, {@link Ext.BoxComponent},
875      * and {@link Ext.Container}, this defaults to <b><tt>'div'</tt></b>. The more complex Ext classes use a more complex
876      * DOM structure created by their own onRender methods.</p>
877      * <p>This is intended to allow the developer to create application-specific utility Components encapsulated by
878      * different DOM elements. Example usage:</p><pre><code>
879 {
880     xtype: 'box',
881     autoEl: {
882         tag: 'img',
883         src: 'http://www.example.com/example.jpg'
884     }
885 }, {
886     xtype: 'box',
887     autoEl: {
888         tag: 'blockquote',
889         html: 'autoEl is cool!'
890     }
891 }, {
892     xtype: 'container',
893     autoEl: 'ul',
894     cls: 'ux-unordered-list',
895     items: {
896         xtype: 'box',
897         autoEl: 'li',
898         html: 'First list item'
899     }
900 }
901 </code></pre>
902      */
903     autoEl : 'div',
904
905     /**
906      * @cfg {String} disabledClass
907      * CSS class added to the component when it is disabled (defaults to 'x-item-disabled').
908      */
909     disabledClass : 'x-item-disabled',
910     /**
911      * @cfg {Boolean} allowDomMove
912      * Whether the component can move the Dom node when rendering (defaults to true).
913      */
914     allowDomMove : true,
915     /**
916      * @cfg {Boolean} autoShow
917      * True if the component should check for hidden classes (e.g. 'x-hidden' or 'x-hide-display') and remove
918      * them on render (defaults to false).
919      */
920     autoShow : false,
921     /**
922      * @cfg {String} hideMode
923      * <p>How this component should be hidden. Supported values are <tt>'visibility'</tt>
924      * (css visibility), <tt>'offsets'</tt> (negative offset position) and <tt>'display'</tt>
925      * (css display).</p>
926      * <br><p><b>Note</b>: the default of <tt>'display'</tt> is generally preferred
927      * since items are automatically laid out when they are first shown (no sizing
928      * is done while hidden).</p>
929      */
930     hideMode : 'display',
931     /**
932      * @cfg {Boolean} hideParent
933      * True to hide and show the component's container when hide/show is called on the component, false to hide
934      * and show the component itself (defaults to false).  For example, this can be used as a shortcut for a hide
935      * button on a window by setting hide:true on the button when adding it to its parent container.
936      */
937     hideParent : false,
938     /**
939      * <p>The {@link Ext.Element} which encapsulates this Component. Read-only.</p>
940      * <p>This will <i>usually</i> be a &lt;DIV> element created by the class's onRender method, but
941      * that may be overridden using the <code>{@link #autoEl}</code> config.</p>
942      * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br>
943      * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners
944      * for this Component's own Observable events), see the {@link Ext.util.Observable#listeners listeners}
945      * config for a suggestion, or use a render listener directly:</p><pre><code>
946 new Ext.Panel({
947     title: 'The Clickable Panel',
948     listeners: {
949         render: function(p) {
950             // Append the Panel to the click handler&#39;s argument list.
951             p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));
952         },
953         single: true  // Remove the listener after first invocation
954     }
955 });
956 </code></pre>
957      * <p>See also <tt>{@link #getEl getEl}</p>
958      * @type Ext.Element
959      * @property el
960      */
961     /**
962      * This Component's owner {@link Ext.Container Container} (defaults to undefined, and is set automatically when
963      * this Component is added to a Container).  Read-only.
964      * <p><b>Note</b>: to access items within the Container see <tt>{@link #itemId}</tt>.</p>
965      * @type Ext.Container
966      * @property ownerCt
967      */
968     /**
969      * True if this component is hidden. Read-only.
970      * @type Boolean
971      * @property hidden
972      */
973     /**
974      * True if this component is disabled. Read-only.
975      * @type Boolean
976      * @property disabled
977      */
978     /**
979      * True if this component has been rendered. Read-only.
980      * @type Boolean
981      * @property rendered
982      */
983     rendered : false,
984
985     /**
986      * @cfg {String} contentEl
987      * <p>Optional. Specify an existing HTML element, or the <code>id</code> of an existing HTML element to use as the content
988      * for this component.</p>
989      * <ul>
990      * <li><b>Description</b> :
991      * <div class="sub-desc">This config option is used to take an existing HTML element and place it in the layout element
992      * 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>
993      * <li><b>Notes</b> :
994      * <div class="sub-desc">The specified HTML element is appended to the layout element of the component <i>after any configured
995      * {@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>
996      * <div class="sub-desc">The specified HTML element used will not participate in any <code><b>{@link Ext.Container#layout layout}</b></code>
997      * scheme that the Component may use. It is just HTML. Layouts operate on child <code><b>{@link Ext.Container#items items}</b></code>.</div>
998      * <div class="sub-desc">Add either the <code>x-hidden</code> or the <code>x-hide-display</code> CSS class to
999      * prevent a brief flicker of the content before it is rendered to the panel.</div></li>
1000      * </ul>
1001      */
1002     /**
1003      * @cfg {String/Object} html
1004      * An HTML fragment, or a {@link Ext.DomHelper DomHelper} specification to use as the layout element
1005      * content (defaults to ''). The HTML content is added after the component is rendered,
1006      * so the document will not contain this HTML at the time the {@link #render} event is fired.
1007      * This content is inserted into the body <i>before</i> any configured {@link #contentEl} is appended.
1008      */
1009
1010     /**
1011      * @cfg {Mixed} tpl
1012      * An <bold>{@link Ext.Template}</bold>, <bold>{@link Ext.XTemplate}</bold>
1013      * or an array of strings to form an Ext.XTemplate.
1014      * Used in conjunction with the <code>{@link #data}</code> and
1015      * <code>{@link #tplWriteMode}</code> configurations.
1016      */
1017
1018     /**
1019      * @cfg {String} tplWriteMode The Ext.(X)Template method to use when
1020      * updating the content area of the Component. Defaults to <tt>'overwrite'</tt>
1021      * (see <code>{@link Ext.XTemplate#overwrite}</code>).
1022      */
1023     tplWriteMode : 'overwrite',
1024
1025     /**
1026      * @cfg {Mixed} data
1027      * The initial set of data to apply to the <code>{@link #tpl}</code> to
1028      * update the content area of the Component.
1029      */
1030     
1031     /**
1032      * @cfg {Array} bubbleEvents
1033      * <p>An array of events that, when fired, should be bubbled to any parent container.
1034      * See {@link Ext.util.Observable#enableBubble}.
1035      * Defaults to <tt>[]</tt>.
1036      */
1037     bubbleEvents: [],
1038
1039
1040     // private
1041     ctype : 'Ext.Component',
1042
1043     // private
1044     actionMode : 'el',
1045
1046     // private
1047     getActionEl : function(){
1048         return this[this.actionMode];
1049     },
1050
1051     initPlugin : function(p){
1052         if(p.ptype && !Ext.isFunction(p.init)){
1053             p = Ext.ComponentMgr.createPlugin(p);
1054         }else if(Ext.isString(p)){
1055             p = Ext.ComponentMgr.createPlugin({
1056                 ptype: p
1057             });
1058         }
1059         p.init(this);
1060         return p;
1061     },
1062
1063     /* // protected
1064      * Function to be implemented by Component subclasses to be part of standard component initialization flow (it is empty by default).
1065      * <pre><code>
1066 // Traditional constructor:
1067 Ext.Foo = function(config){
1068     // call superclass constructor:
1069     Ext.Foo.superclass.constructor.call(this, config);
1070
1071     this.addEvents({
1072         // add events
1073     });
1074 };
1075 Ext.extend(Ext.Foo, Ext.Bar, {
1076    // class body
1077 }
1078
1079 // initComponent replaces the constructor:
1080 Ext.Foo = Ext.extend(Ext.Bar, {
1081     initComponent : function(){
1082         // call superclass initComponent
1083         Ext.Container.superclass.initComponent.call(this);
1084
1085         this.addEvents({
1086             // add events
1087         });
1088     }
1089 }
1090 </code></pre>
1091      */
1092     initComponent : function(){
1093         /*
1094          * this is double processing, however it allows people to be able to do
1095          * Ext.apply(this, {
1096          *     listeners: {
1097          *         //here
1098          *     }
1099          * });
1100          * MyClass.superclass.initComponent.call(this);
1101          */
1102         if(this.listeners){
1103             this.on(this.listeners);
1104             delete this.listeners;
1105         }
1106         this.enableBubble(this.bubbleEvents);
1107     },
1108
1109     /**
1110      * <p>Render this Component into the passed HTML element.</p>
1111      * <p><b>If you are using a {@link Ext.Container Container} object to house this Component, then
1112      * do not use the render method.</b></p>
1113      * <p>A Container's child Components are rendered by that Container's
1114      * {@link Ext.Container#layout layout} manager when the Container is first rendered.</p>
1115      * <p>Certain layout managers allow dynamic addition of child components. Those that do
1116      * include {@link Ext.layout.CardLayout}, {@link Ext.layout.AnchorLayout},
1117      * {@link Ext.layout.FormLayout}, {@link Ext.layout.TableLayout}.</p>
1118      * <p>If the Container is already rendered when a new child Component is added, you may need to call
1119      * the Container's {@link Ext.Container#doLayout doLayout} to refresh the view which causes any
1120      * unrendered child Components to be rendered. This is required so that you can add multiple
1121      * child components if needed while only refreshing the layout once.</p>
1122      * <p>When creating complex UIs, it is important to remember that sizing and positioning
1123      * of child items is the responsibility of the Container's {@link Ext.Container#layout layout} manager.
1124      * If you expect child items to be sized in response to user interactions, you must
1125      * configure the Container with a layout manager which creates and manages the type of layout you
1126      * have in mind.</p>
1127      * <p><b>Omitting the Container's {@link Ext.Container#layout layout} config means that a basic
1128      * layout manager is used which does nothing but render child components sequentially into the
1129      * Container. No sizing or positioning will be performed in this situation.</b></p>
1130      * @param {Element/HTMLElement/String} container (optional) The element this Component should be
1131      * rendered into. If it is being created from existing markup, this should be omitted.
1132      * @param {String/Number} position (optional) The element ID or DOM node index within the container <b>before</b>
1133      * which this component will be inserted (defaults to appending to the end of the container)
1134      */
1135     render : function(container, position){
1136         if(!this.rendered && this.fireEvent('beforerender', this) !== false){
1137             if(!container && this.el){
1138                 this.el = Ext.get(this.el);
1139                 container = this.el.dom.parentNode;
1140                 this.allowDomMove = false;
1141             }
1142             this.container = Ext.get(container);
1143             if(this.ctCls){
1144                 this.container.addClass(this.ctCls);
1145             }
1146             this.rendered = true;
1147             if(position !== undefined){
1148                 if(Ext.isNumber(position)){
1149                     position = this.container.dom.childNodes[position];
1150                 }else{
1151                     position = Ext.getDom(position);
1152                 }
1153             }
1154             this.onRender(this.container, position || null);
1155             if(this.autoShow){
1156                 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
1157             }
1158             if(this.cls){
1159                 this.el.addClass(this.cls);
1160                 delete this.cls;
1161             }
1162             if(this.style){
1163                 this.el.applyStyles(this.style);
1164                 delete this.style;
1165             }
1166             if(this.overCls){
1167                 this.el.addClassOnOver(this.overCls);
1168             }
1169             this.fireEvent('render', this);
1170
1171
1172             // Populate content of the component with html, contentEl or
1173             // a tpl.
1174             var contentTarget = this.getContentTarget();
1175             if (this.html){
1176                 contentTarget.update(Ext.DomHelper.markup(this.html));
1177                 delete this.html;
1178             }
1179             if (this.contentEl){
1180                 var ce = Ext.getDom(this.contentEl);
1181                 Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
1182                 contentTarget.appendChild(ce);
1183             }
1184             if (this.tpl) {
1185                 if (!this.tpl.compile) {
1186                     this.tpl = new Ext.XTemplate(this.tpl);
1187                 }
1188                 if (this.data) {
1189                     this.tpl[this.tplWriteMode](contentTarget, this.data);
1190                     delete this.data;
1191                 }
1192             }
1193             this.afterRender(this.container);
1194
1195
1196             if(this.hidden){
1197                 // call this so we don't fire initial hide events.
1198                 this.doHide();
1199             }
1200             if(this.disabled){
1201                 // pass silent so the event doesn't fire the first time.
1202                 this.disable(true);
1203             }
1204
1205             if(this.stateful !== false){
1206                 this.initStateEvents();
1207             }
1208             this.fireEvent('afterrender', this);
1209         }
1210         return this;
1211     },
1212
1213
1214     /**
1215      * Update the content area of a component.
1216      * @param {Mixed} htmlOrData
1217      * If this component has been configured with a template via the tpl config
1218      * then it will use this argument as data to populate the template.
1219      * If this component was not configured with a template, the components
1220      * content area will be updated via Ext.Element update
1221      * @param {Boolean} loadScripts
1222      * (optional) Only legitimate when using the html configuration. Defaults to false
1223      * @param {Function} callback
1224      * (optional) Only legitimate when using the html configuration. Callback to execute when scripts have finished loading
1225      */
1226     update: function(htmlOrData, loadScripts, cb) {
1227         var contentTarget = this.getContentTarget();
1228         if (this.tpl && typeof htmlOrData !== "string") {
1229             this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
1230         } else {
1231             var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
1232             contentTarget.update(html, loadScripts, cb);
1233         }
1234     },
1235
1236
1237     /**
1238      * @private
1239      * Method to manage awareness of when components are added to their
1240      * respective Container, firing an added event.
1241      * References are established at add time rather than at render time.
1242      * @param {Ext.Container} container Container which holds the component
1243      * @param {number} pos Position at which the component was added
1244      */
1245     onAdded : function(container, pos) {
1246         this.ownerCt = container;
1247         this.initRef();
1248         this.fireEvent('added', this, container, pos);
1249     },
1250
1251     /**
1252      * @private
1253      * Method to manage awareness of when components are removed from their
1254      * respective Container, firing an removed event. References are properly
1255      * cleaned up after removing a component from its owning container.
1256      */
1257     onRemoved : function() {
1258         this.removeRef();
1259         this.fireEvent('removed', this, this.ownerCt);
1260         delete this.ownerCt;
1261     },
1262
1263     /**
1264      * @private
1265      * Method to establish a reference to a component.
1266      */
1267     initRef : function() {
1268         /**
1269          * @cfg {String} ref
1270          * <p>A path specification, relative to the Component's <code>{@link #ownerCt}</code>
1271          * specifying into which ancestor Container to place a named reference to this Component.</p>
1272          * <p>The ancestor axis can be traversed by using '/' characters in the path.
1273          * For example, to put a reference to a Toolbar Button into <i>the Panel which owns the Toolbar</i>:</p><pre><code>
1274 var myGrid = new Ext.grid.EditorGridPanel({
1275     title: 'My EditorGridPanel',
1276     store: myStore,
1277     colModel: myColModel,
1278     tbar: [{
1279         text: 'Save',
1280         handler: saveChanges,
1281         disabled: true,
1282         ref: '../saveButton'
1283     }],
1284     listeners: {
1285         afteredit: function() {
1286 //          The button reference is in the GridPanel
1287             myGrid.saveButton.enable();
1288         }
1289     }
1290 });
1291 </code></pre>
1292          * <p>In the code above, if the <code>ref</code> had been <code>'saveButton'</code>
1293          * the reference would have been placed into the Toolbar. Each '/' in the <code>ref</code>
1294          * moves up one level from the Component's <code>{@link #ownerCt}</code>.</p>
1295          * <p>Also see the <code>{@link #added}</code> and <code>{@link #removed}</code> events.</p>
1296          */
1297         if(this.ref && !this.refOwner){
1298             var levels = this.ref.split('/'),
1299                 last = levels.length,
1300                 i = 0,
1301                 t = this;
1302
1303             while(t && i < last){
1304                 t = t.ownerCt;
1305                 ++i;
1306             }
1307             if(t){
1308                 t[this.refName = levels[--i]] = this;
1309                 /**
1310                  * @type Ext.Container
1311                  * @property refOwner
1312                  * The ancestor Container into which the {@link #ref} reference was inserted if this Component
1313                  * is a child of a Container, and has been configured with a <code>ref</code>.
1314                  */
1315                 this.refOwner = t;
1316             }
1317         }
1318     },
1319
1320     removeRef : function() {
1321         if (this.refOwner && this.refName) {
1322             delete this.refOwner[this.refName];
1323             delete this.refOwner;
1324         }
1325     },
1326
1327     // private
1328     initState : function(){
1329         if(Ext.state.Manager){
1330             var id = this.getStateId();
1331             if(id){
1332                 var state = Ext.state.Manager.get(id);
1333                 if(state){
1334                     if(this.fireEvent('beforestaterestore', this, state) !== false){
1335                         this.applyState(Ext.apply({}, state));
1336                         this.fireEvent('staterestore', this, state);
1337                     }
1338                 }
1339             }
1340         }
1341     },
1342
1343     // private
1344     getStateId : function(){
1345         return this.stateId || ((/^(ext-comp-|ext-gen)/).test(String(this.id)) ? null : this.id);
1346     },
1347
1348     // private
1349     initStateEvents : function(){
1350         if(this.stateEvents){
1351             for(var i = 0, e; e = this.stateEvents[i]; i++){
1352                 this.on(e, this.saveState, this, {delay:100});
1353             }
1354         }
1355     },
1356
1357     // private
1358     applyState : function(state){
1359         if(state){
1360             Ext.apply(this, state);
1361         }
1362     },
1363
1364     // private
1365     getState : function(){
1366         return null;
1367     },
1368
1369     // private
1370     saveState : function(){
1371         if(Ext.state.Manager && this.stateful !== false){
1372             var id = this.getStateId();
1373             if(id){
1374                 var state = this.getState();
1375                 if(this.fireEvent('beforestatesave', this, state) !== false){
1376                     Ext.state.Manager.set(id, state);
1377                     this.fireEvent('statesave', this, state);
1378                 }
1379             }
1380         }
1381     },
1382
1383     /**
1384      * Apply this component to existing markup that is valid. With this function, no call to render() is required.
1385      * @param {String/HTMLElement} el
1386      */
1387     applyToMarkup : function(el){
1388         this.allowDomMove = false;
1389         this.el = Ext.get(el);
1390         this.render(this.el.dom.parentNode);
1391     },
1392
1393     /**
1394      * Adds a CSS class to the component's underlying element.
1395      * @param {string} cls The CSS class name to add
1396      * @return {Ext.Component} this
1397      */
1398     addClass : function(cls){
1399         if(this.el){
1400             this.el.addClass(cls);
1401         }else{
1402             this.cls = this.cls ? this.cls + ' ' + cls : cls;
1403         }
1404         return this;
1405     },
1406
1407     /**
1408      * Removes a CSS class from the component's underlying element.
1409      * @param {string} cls The CSS class name to remove
1410      * @return {Ext.Component} this
1411      */
1412     removeClass : function(cls){
1413         if(this.el){
1414             this.el.removeClass(cls);
1415         }else if(this.cls){
1416             this.cls = this.cls.split(' ').remove(cls).join(' ');
1417         }
1418         return this;
1419     },
1420
1421     // private
1422     // default function is not really useful
1423     onRender : function(ct, position){
1424         if(!this.el && this.autoEl){
1425             if(Ext.isString(this.autoEl)){
1426                 this.el = document.createElement(this.autoEl);
1427             }else{
1428                 var div = document.createElement('div');
1429                 Ext.DomHelper.overwrite(div, this.autoEl);
1430                 this.el = div.firstChild;
1431             }
1432             if (!this.el.id) {
1433                 this.el.id = this.getId();
1434             }
1435         }
1436         if(this.el){
1437             this.el = Ext.get(this.el);
1438             if(this.allowDomMove !== false){
1439                 ct.dom.insertBefore(this.el.dom, position);
1440                 if (div) {
1441                     Ext.removeNode(div);
1442                     div = null;
1443                 }
1444             }
1445         }
1446     },
1447
1448     // private
1449     getAutoCreate : function(){
1450         var cfg = Ext.isObject(this.autoCreate) ?
1451                       this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
1452         if(this.id && !cfg.id){
1453             cfg.id = this.id;
1454         }
1455         return cfg;
1456     },
1457
1458     // private
1459     afterRender : Ext.emptyFn,
1460
1461     /**
1462      * Destroys this component by purging any event listeners, removing the component's element from the DOM,
1463      * removing the component from its {@link Ext.Container} (if applicable) and unregistering it from
1464      * {@link Ext.ComponentMgr}.  Destruction is generally handled automatically by the framework and this method
1465      * should usually not need to be called directly.
1466      *
1467      */
1468     destroy : function(){
1469         if(!this.isDestroyed){
1470             if(this.fireEvent('beforedestroy', this) !== false){
1471                 this.destroying = true;
1472                 this.beforeDestroy();
1473                 if(this.ownerCt && this.ownerCt.remove){
1474                     this.ownerCt.remove(this, false);
1475                 }
1476                 if(this.rendered){
1477                     this.el.remove();
1478                     if(this.actionMode == 'container' || this.removeMode == 'container'){
1479                         this.container.remove();
1480                     }
1481                 }
1482                 // Stop any buffered tasks
1483                 if(this.focusTask && this.focusTask.cancel){
1484                     this.focusTask.cancel();
1485                 }
1486                 this.onDestroy();
1487                 Ext.ComponentMgr.unregister(this);
1488                 this.fireEvent('destroy', this);
1489                 this.purgeListeners();
1490                 this.destroying = false;
1491                 this.isDestroyed = true;
1492             }
1493         }
1494     },
1495
1496     deleteMembers : function(){
1497         var args = arguments;
1498         for(var i = 0, len = args.length; i < len; ++i){
1499             delete this[args[i]];
1500         }
1501     },
1502
1503     // private
1504     beforeDestroy : Ext.emptyFn,
1505
1506     // private
1507     onDestroy  : Ext.emptyFn,
1508
1509     /**
1510      * <p>Returns the {@link Ext.Element} which encapsulates this Component.</p>
1511      * <p>This will <i>usually</i> be a &lt;DIV> element created by the class's onRender method, but
1512      * that may be overridden using the {@link #autoEl} config.</p>
1513      * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br>
1514      * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners
1515      * for this Component's own Observable events), see the {@link #listeners} config for a suggestion,
1516      * or use a render listener directly:</p><pre><code>
1517 new Ext.Panel({
1518     title: 'The Clickable Panel',
1519     listeners: {
1520         render: function(p) {
1521             // Append the Panel to the click handler&#39;s argument list.
1522             p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));
1523         },
1524         single: true  // Remove the listener after first invocation
1525     }
1526 });
1527 </code></pre>
1528      * @return {Ext.Element} The Element which encapsulates this Component.
1529      */
1530     getEl : function(){
1531         return this.el;
1532     },
1533
1534     // private
1535     getContentTarget : function(){
1536         return this.el;
1537     },
1538
1539     /**
1540      * Returns the <code>id</code> of this component or automatically generates and
1541      * returns an <code>id</code> if an <code>id</code> is not defined yet:<pre><code>
1542      * 'ext-comp-' + (++Ext.Component.AUTO_ID)
1543      * </code></pre>
1544      * @return {String} id
1545      */
1546     getId : function(){
1547         return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
1548     },
1549
1550     /**
1551      * Returns the <code>{@link #itemId}</code> of this component.  If an
1552      * <code>{@link #itemId}</code> was not assigned through configuration the
1553      * <code>id</code> is returned using <code>{@link #getId}</code>.
1554      * @return {String}
1555      */
1556     getItemId : function(){
1557         return this.itemId || this.getId();
1558     },
1559
1560     /**
1561      * Try to focus this component.
1562      * @param {Boolean} selectText (optional) If applicable, true to also select the text in this component
1563      * @param {Boolean/Number} delay (optional) Delay the focus this number of milliseconds (true for 10 milliseconds)
1564      * @return {Ext.Component} this
1565      */
1566     focus : function(selectText, delay){
1567         if(delay){
1568             this.focusTask = new Ext.util.DelayedTask(this.focus, this, [selectText, false]);
1569             this.focusTask.delay(Ext.isNumber(delay) ? delay : 10);
1570             return this;
1571         }
1572         if(this.rendered && !this.isDestroyed){
1573             this.el.focus();
1574             if(selectText === true){
1575                 this.el.dom.select();
1576             }
1577         }
1578         return this;
1579     },
1580
1581     // private
1582     blur : function(){
1583         if(this.rendered){
1584             this.el.blur();
1585         }
1586         return this;
1587     },
1588
1589     /**
1590      * Disable this component and fire the 'disable' event.
1591      * @return {Ext.Component} this
1592      */
1593     disable : function(/* private */ silent){
1594         if(this.rendered){
1595             this.onDisable();
1596         }
1597         this.disabled = true;
1598         if(silent !== true){
1599             this.fireEvent('disable', this);
1600         }
1601         return this;
1602     },
1603
1604     // private
1605     onDisable : function(){
1606         this.getActionEl().addClass(this.disabledClass);
1607         this.el.dom.disabled = true;
1608     },
1609
1610     /**
1611      * Enable this component and fire the 'enable' event.
1612      * @return {Ext.Component} this
1613      */
1614     enable : function(){
1615         if(this.rendered){
1616             this.onEnable();
1617         }
1618         this.disabled = false;
1619         this.fireEvent('enable', this);
1620         return this;
1621     },
1622
1623     // private
1624     onEnable : function(){
1625         this.getActionEl().removeClass(this.disabledClass);
1626         this.el.dom.disabled = false;
1627     },
1628
1629     /**
1630      * Convenience function for setting disabled/enabled by boolean.
1631      * @param {Boolean} disabled
1632      * @return {Ext.Component} this
1633      */
1634     setDisabled : function(disabled){
1635         return this[disabled ? 'disable' : 'enable']();
1636     },
1637
1638     /**
1639      * Show this component.  Listen to the '{@link #beforeshow}' event and return
1640      * <tt>false</tt> to cancel showing the component.  Fires the '{@link #show}'
1641      * event after showing the component.
1642      * @return {Ext.Component} this
1643      */
1644     show : function(){
1645         if(this.fireEvent('beforeshow', this) !== false){
1646             this.hidden = false;
1647             if(this.autoRender){
1648                 this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
1649             }
1650             if(this.rendered){
1651                 this.onShow();
1652             }
1653             this.fireEvent('show', this);
1654         }
1655         return this;
1656     },
1657
1658     // private
1659     onShow : function(){
1660         this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);
1661     },
1662
1663     /**
1664      * Hide this component.  Listen to the '{@link #beforehide}' event and return
1665      * <tt>false</tt> to cancel hiding the component.  Fires the '{@link #hide}'
1666      * event after hiding the component. Note this method is called internally if
1667      * the component is configured to be <code>{@link #hidden}</code>.
1668      * @return {Ext.Component} this
1669      */
1670     hide : function(){
1671         if(this.fireEvent('beforehide', this) !== false){
1672             this.doHide();
1673             this.fireEvent('hide', this);
1674         }
1675         return this;
1676     },
1677
1678     // private
1679     doHide: function(){
1680         this.hidden = true;
1681         if(this.rendered){
1682             this.onHide();
1683         }
1684     },
1685
1686     // private
1687     onHide : function(){
1688         this.getVisibilityEl().addClass('x-hide-' + this.hideMode);
1689     },
1690
1691     // private
1692     getVisibilityEl : function(){
1693         return this.hideParent ? this.container : this.getActionEl();
1694     },
1695
1696     /**
1697      * Convenience function to hide or show this component by boolean.
1698      * @param {Boolean} visible True to show, false to hide
1699      * @return {Ext.Component} this
1700      */
1701     setVisible : function(visible){
1702         return this[visible ? 'show' : 'hide']();
1703     },
1704
1705     /**
1706      * Returns true if this component is visible.
1707      * @return {Boolean} True if this component is visible, false otherwise.
1708      */
1709     isVisible : function(){
1710         return this.rendered && this.getVisibilityEl().isVisible();
1711     },
1712
1713     /**
1714      * Clone the current component using the original config values passed into this instance by default.
1715      * @param {Object} overrides A new config containing any properties to override in the cloned version.
1716      * An id property can be passed on this object, otherwise one will be generated to avoid duplicates.
1717      * @return {Ext.Component} clone The cloned copy of this component
1718      */
1719     cloneConfig : function(overrides){
1720         overrides = overrides || {};
1721         var id = overrides.id || Ext.id();
1722         var cfg = Ext.applyIf(overrides, this.initialConfig);
1723         cfg.id = id; // prevent dup id
1724         return new this.constructor(cfg);
1725     },
1726
1727     /**
1728      * Gets the xtype for this component as registered with {@link Ext.ComponentMgr}. For a list of all
1729      * available xtypes, see the {@link Ext.Component} header. Example usage:
1730      * <pre><code>
1731 var t = new Ext.form.TextField();
1732 alert(t.getXType());  // alerts 'textfield'
1733 </code></pre>
1734      * @return {String} The xtype
1735      */
1736     getXType : function(){
1737         return this.constructor.xtype;
1738     },
1739
1740     /**
1741      * <p>Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended
1742      * from the xtype (default) or whether it is directly of the xtype specified (shallow = true).</p>
1743      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1744      * to participate in determination of inherited xtypes.</b></p>
1745      * <p>For a list of all available xtypes, see the {@link Ext.Component} header.</p>
1746      * <p>Example usage:</p>
1747      * <pre><code>
1748 var t = new Ext.form.TextField();
1749 var isText = t.isXType('textfield');        // true
1750 var isBoxSubclass = t.isXType('box');       // true, descended from BoxComponent
1751 var isBoxInstance = t.isXType('box', true); // false, not a direct BoxComponent instance
1752 </code></pre>
1753      * @param {String/Ext.Component/Class} xtype The xtype to check for this Component. Note that the the component can either be an instance
1754      * or a component class:
1755      * <pre><code>
1756 var c = new Ext.Component();
1757 console.log(c.isXType(c));
1758 console.log(c.isXType(Ext.Component)); 
1759 </code></pre>
1760      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
1761      * the default), or true to check whether this Component is directly of the specified xtype.
1762      * @return {Boolean} True if this component descends from the specified xtype, false otherwise.
1763      */
1764     isXType : function(xtype, shallow){
1765         //assume a string by default
1766         if (Ext.isFunction(xtype)){
1767             xtype = xtype.xtype; //handle being passed the class, e.g. Ext.Component
1768         }else if (Ext.isObject(xtype)){
1769             xtype = xtype.constructor.xtype; //handle being passed an instance
1770         }
1771
1772         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
1773     },
1774
1775     /**
1776      * <p>Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all
1777      * available xtypes, see the {@link Ext.Component} header.</p>
1778      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1779      * to participate in determination of inherited xtypes.</b></p>
1780      * <p>Example usage:</p>
1781      * <pre><code>
1782 var t = new Ext.form.TextField();
1783 alert(t.getXTypes());  // alerts 'component/box/field/textfield'
1784 </code></pre>
1785      * @return {String} The xtype hierarchy string
1786      */
1787     getXTypes : function(){
1788         var tc = this.constructor;
1789         if(!tc.xtypes){
1790             var c = [], sc = this;
1791             while(sc && sc.constructor.xtype){
1792                 c.unshift(sc.constructor.xtype);
1793                 sc = sc.constructor.superclass;
1794             }
1795             tc.xtypeChain = c;
1796             tc.xtypes = c.join('/');
1797         }
1798         return tc.xtypes;
1799     },
1800
1801     /**
1802      * Find a container above this component at any level by a custom function. If the passed function returns
1803      * true, the container will be returned.
1804      * @param {Function} fn The custom function to call with the arguments (container, this component).
1805      * @return {Ext.Container} The first Container for which the custom function returns true
1806      */
1807     findParentBy : function(fn) {
1808         for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
1809         return p || null;
1810     },
1811
1812     /**
1813      * Find a container above this component at any level by xtype or class
1814      * @param {String/Ext.Component/Class} xtype The xtype to check for this Component. Note that the the component can either be an instance
1815      * or a component class:
1816      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
1817      * the default), or true to check whether this Component is directly of the specified xtype.
1818      * @return {Ext.Container} The first Container which matches the given xtype or class
1819      */
1820     findParentByType : function(xtype, shallow){
1821         return this.findParentBy(function(c){
1822             return c.isXType(xtype, shallow);
1823         });
1824     },
1825     
1826     /**
1827      * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of
1828      * function call will be the scope provided or the current component. The arguments to the function
1829      * will be the args provided or the current component. If the function returns false at any point,
1830      * the bubble is stopped.
1831      * @param {Function} fn The function to call
1832      * @param {Object} scope (optional) The scope of the function (defaults to current node)
1833      * @param {Array} args (optional) The args to call the function with (default to passing the current component)
1834      * @return {Ext.Component} this
1835      */
1836     bubble : function(fn, scope, args){
1837         var p = this;
1838         while(p){
1839             if(fn.apply(scope || p, args || [p]) === false){
1840                 break;
1841             }
1842             p = p.ownerCt;
1843         }
1844         return this;
1845     },
1846
1847     // protected
1848     getPositionEl : function(){
1849         return this.positionEl || this.el;
1850     },
1851
1852     // private
1853     purgeListeners : function(){
1854         Ext.Component.superclass.purgeListeners.call(this);
1855         if(this.mons){
1856             this.on('beforedestroy', this.clearMons, this, {single: true});
1857         }
1858     },
1859
1860     // private
1861     clearMons : function(){
1862         Ext.each(this.mons, function(m){
1863             m.item.un(m.ename, m.fn, m.scope);
1864         }, this);
1865         this.mons = [];
1866     },
1867
1868     // private
1869     createMons: function(){
1870         if(!this.mons){
1871             this.mons = [];
1872             this.on('beforedestroy', this.clearMons, this, {single: true});
1873         }
1874     },
1875
1876     /**
1877      * <p>Adds listeners to any Observable object (or Elements) which are automatically removed when this Component
1878      * is destroyed. Usage:</p><code><pre>
1879 myGridPanel.mon(myGridPanel.getSelectionModel(), 'selectionchange', handleSelectionChange, null, {buffer: 50});
1880 </pre></code>
1881      * <p>or:</p><code><pre>
1882 myGridPanel.mon(myGridPanel.getSelectionModel(), {
1883     selectionchange: handleSelectionChange,
1884     buffer: 50
1885 });
1886 </pre></code>
1887      * @param {Observable|Element} item The item to which to add a listener/listeners.
1888      * @param {Object|String} ename The event name, or an object containing event name properties.
1889      * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this
1890      * is the handler function.
1891      * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this
1892      * is the scope (<code>this</code> reference) in which the handler function is executed.
1893      * @param {Object} opt Optional. If the <code>ename</code> parameter was an event name, this
1894      * is the {@link Ext.util.Observable#addListener addListener} options.
1895      */
1896     mon : function(item, ename, fn, scope, opt){
1897         this.createMons();
1898         if(Ext.isObject(ename)){
1899             var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
1900
1901             var o = ename;
1902             for(var e in o){
1903                 if(propRe.test(e)){
1904                     continue;
1905                 }
1906                 if(Ext.isFunction(o[e])){
1907                     // shared options
1908                     this.mons.push({
1909                         item: item, ename: e, fn: o[e], scope: o.scope
1910                     });
1911                     item.on(e, o[e], o.scope, o);
1912                 }else{
1913                     // individual options
1914                     this.mons.push({
1915                         item: item, ename: e, fn: o[e], scope: o.scope
1916                     });
1917                     item.on(e, o[e]);
1918                 }
1919             }
1920             return;
1921         }
1922
1923         this.mons.push({
1924             item: item, ename: ename, fn: fn, scope: scope
1925         });
1926         item.on(ename, fn, scope, opt);
1927     },
1928
1929     /**
1930      * Removes listeners that were added by the {@link #mon} method.
1931      * @param {Observable|Element} item The item from which to remove a listener/listeners.
1932      * @param {Object|String} ename The event name, or an object containing event name properties.
1933      * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this
1934      * is the handler function.
1935      * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this
1936      * is the scope (<code>this</code> reference) in which the handler function is executed.
1937      */
1938     mun : function(item, ename, fn, scope){
1939         var found, mon;
1940         this.createMons();
1941         for(var i = 0, len = this.mons.length; i < len; ++i){
1942             mon = this.mons[i];
1943             if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){
1944                 this.mons.splice(i, 1);
1945                 item.un(ename, fn, scope);
1946                 found = true;
1947                 break;
1948             }
1949         }
1950         return found;
1951     },
1952
1953     /**
1954      * Returns the next component in the owning container
1955      * @return Ext.Component
1956      */
1957     nextSibling : function(){
1958         if(this.ownerCt){
1959             var index = this.ownerCt.items.indexOf(this);
1960             if(index != -1 && index+1 < this.ownerCt.items.getCount()){
1961                 return this.ownerCt.items.itemAt(index+1);
1962             }
1963         }
1964         return null;
1965     },
1966
1967     /**
1968      * Returns the previous component in the owning container
1969      * @return Ext.Component
1970      */
1971     previousSibling : function(){
1972         if(this.ownerCt){
1973             var index = this.ownerCt.items.indexOf(this);
1974             if(index > 0){
1975                 return this.ownerCt.items.itemAt(index-1);
1976             }
1977         }
1978         return null;
1979     },
1980
1981     /**
1982      * Provides the link for Observable's fireEvent method to bubble up the ownership hierarchy.
1983      * @return {Ext.Container} the Container which owns this Component.
1984      */
1985     getBubbleTarget : function(){
1986         return this.ownerCt;
1987     }
1988 });
1989
1990 Ext.reg('component', Ext.Component);
1991 /**
1992  * @class Ext.Action
1993  * <p>An Action is a piece of reusable functionality that can be abstracted out of any particular component so that it
1994  * can be usefully shared among multiple components.  Actions let you share handlers, configuration options and UI
1995  * updates across any components that support the Action interface (primarily {@link Ext.Toolbar}, {@link Ext.Button}
1996  * and {@link Ext.menu.Menu} components).</p>
1997  * <p>Aside from supporting the config object interface, any component that needs to use Actions must also support
1998  * the following method list, as these will be called as needed by the Action class: setText(string), setIconCls(string),
1999  * setDisabled(boolean), setVisible(boolean) and setHandler(function).</p>
2000  * Example usage:<br>
2001  * <pre><code>
2002 // Define the shared action.  Each component below will have the same
2003 // display text and icon, and will display the same message on click.
2004 var action = new Ext.Action({
2005     {@link #text}: 'Do something',
2006     {@link #handler}: function(){
2007         Ext.Msg.alert('Click', 'You did something.');
2008     },
2009     {@link #iconCls}: 'do-something',
2010     {@link #itemId}: 'myAction'
2011 });
2012
2013 var panel = new Ext.Panel({
2014     title: 'Actions',
2015     width: 500,
2016     height: 300,
2017     tbar: [
2018         // Add the action directly to a toolbar as a menu button
2019         action,
2020         {
2021             text: 'Action Menu',
2022             // Add the action to a menu as a text item
2023             menu: [action]
2024         }
2025     ],
2026     items: [
2027         // Add the action to the panel body as a standard button
2028         new Ext.Button(action)
2029     ],
2030     renderTo: Ext.getBody()
2031 });
2032
2033 // Change the text for all components using the action
2034 action.setText('Something else');
2035
2036 // Reference an action through a container using the itemId
2037 var btn = panel.getComponent('myAction');
2038 var aRef = btn.baseAction;
2039 aRef.setText('New text');
2040 </code></pre>
2041  * @constructor
2042  * @param {Object} config The configuration options
2043  */
2044 Ext.Action = Ext.extend(Object, {
2045     /**
2046      * @cfg {String} text The text to set for all components using this action (defaults to '').
2047      */
2048     /**
2049      * @cfg {String} iconCls
2050      * The CSS class selector that specifies a background image to be used as the header icon for
2051      * all components using this action (defaults to '').
2052      * <p>An example of specifying a custom icon class would be something like:
2053      * </p><pre><code>
2054 // specify the property in the config for the class:
2055      ...
2056      iconCls: 'do-something'
2057
2058 // css class that specifies background image to be used as the icon image:
2059 .do-something { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
2060 </code></pre>
2061      */
2062     /**
2063      * @cfg {Boolean} disabled True to disable all components using this action, false to enable them (defaults to false).
2064      */
2065     /**
2066      * @cfg {Boolean} hidden True to hide all components using this action, false to show them (defaults to false).
2067      */
2068     /**
2069      * @cfg {Function} handler The function that will be invoked by each component tied to this action
2070      * when the component's primary event is triggered (defaults to undefined).
2071      */
2072     /**
2073      * @cfg {String} itemId
2074      * See {@link Ext.Component}.{@link Ext.Component#itemId itemId}.
2075      */
2076     /**
2077      * @cfg {Object} scope The scope (<tt><b>this</b></tt> reference) in which the
2078      * <code>{@link #handler}</code> is executed. Defaults to this Button.
2079      */
2080
2081     constructor : function(config){
2082         this.initialConfig = config;
2083         this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
2084         this.items = [];
2085     },
2086     
2087     // private
2088     isAction : true,
2089
2090     /**
2091      * Sets the text to be displayed by all components using this action.
2092      * @param {String} text The text to display
2093      */
2094     setText : function(text){
2095         this.initialConfig.text = text;
2096         this.callEach('setText', [text]);
2097     },
2098
2099     /**
2100      * Gets the text currently displayed by all components using this action.
2101      */
2102     getText : function(){
2103         return this.initialConfig.text;
2104     },
2105
2106     /**
2107      * Sets the icon CSS class for all components using this action.  The class should supply
2108      * a background image that will be used as the icon image.
2109      * @param {String} cls The CSS class supplying the icon image
2110      */
2111     setIconClass : function(cls){
2112         this.initialConfig.iconCls = cls;
2113         this.callEach('setIconClass', [cls]);
2114     },
2115
2116     /**
2117      * Gets the icon CSS class currently used by all components using this action.
2118      */
2119     getIconClass : function(){
2120         return this.initialConfig.iconCls;
2121     },
2122
2123     /**
2124      * Sets the disabled state of all components using this action.  Shortcut method
2125      * for {@link #enable} and {@link #disable}.
2126      * @param {Boolean} disabled True to disable the component, false to enable it
2127      */
2128     setDisabled : function(v){
2129         this.initialConfig.disabled = v;
2130         this.callEach('setDisabled', [v]);
2131     },
2132
2133     /**
2134      * Enables all components using this action.
2135      */
2136     enable : function(){
2137         this.setDisabled(false);
2138     },
2139
2140     /**
2141      * Disables all components using this action.
2142      */
2143     disable : function(){
2144         this.setDisabled(true);
2145     },
2146
2147     /**
2148      * Returns true if the components using this action are currently disabled, else returns false.  
2149      */
2150     isDisabled : function(){
2151         return this.initialConfig.disabled;
2152     },
2153
2154     /**
2155      * Sets the hidden state of all components using this action.  Shortcut method
2156      * for <code>{@link #hide}</code> and <code>{@link #show}</code>.
2157      * @param {Boolean} hidden True to hide the component, false to show it
2158      */
2159     setHidden : function(v){
2160         this.initialConfig.hidden = v;
2161         this.callEach('setVisible', [!v]);
2162     },
2163
2164     /**
2165      * Shows all components using this action.
2166      */
2167     show : function(){
2168         this.setHidden(false);
2169     },
2170
2171     /**
2172      * Hides all components using this action.
2173      */
2174     hide : function(){
2175         this.setHidden(true);
2176     },
2177
2178     /**
2179      * Returns true if the components using this action are currently hidden, else returns false.  
2180      */
2181     isHidden : function(){
2182         return this.initialConfig.hidden;
2183     },
2184
2185     /**
2186      * Sets the function that will be called by each Component using this action when its primary event is triggered.
2187      * @param {Function} fn The function that will be invoked by the action's components.  The function
2188      * will be called with no arguments.
2189      * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed. Defaults to the Component firing the event.
2190      */
2191     setHandler : function(fn, scope){
2192         this.initialConfig.handler = fn;
2193         this.initialConfig.scope = scope;
2194         this.callEach('setHandler', [fn, scope]);
2195     },
2196
2197     /**
2198      * Executes the specified function once for each Component currently tied to this action.  The function passed
2199      * in should accept a single argument that will be an object that supports the basic Action config/method interface.
2200      * @param {Function} fn The function to execute for each component
2201      * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed.  Defaults to the Component.
2202      */
2203     each : function(fn, scope){
2204         Ext.each(this.items, fn, scope);
2205     },
2206
2207     // private
2208     callEach : function(fnName, args){
2209         var cs = this.items;
2210         for(var i = 0, len = cs.length; i < len; i++){
2211             cs[i][fnName].apply(cs[i], args);
2212         }
2213     },
2214
2215     // private
2216     addComponent : function(comp){
2217         this.items.push(comp);
2218         comp.on('destroy', this.removeComponent, this);
2219     },
2220
2221     // private
2222     removeComponent : function(comp){
2223         this.items.remove(comp);
2224     },
2225
2226     /**
2227      * Executes this action manually using the handler function specified in the original config object
2228      * or the handler function set with <code>{@link #setHandler}</code>.  Any arguments passed to this
2229      * function will be passed on to the handler function.
2230      * @param {Mixed} arg1 (optional) Variable number of arguments passed to the handler function
2231      * @param {Mixed} arg2 (optional)
2232      * @param {Mixed} etc... (optional)
2233      */
2234     execute : function(){
2235         this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
2236     }
2237 });
2238 /**
2239  * @class Ext.Layer
2240  * @extends Ext.Element
2241  * An extended {@link Ext.Element} object that supports a shadow and shim, constrain to viewport and
2242  * automatic maintaining of shadow/shim positions.
2243  * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true)
2244  * @cfg {String/Boolean} shadow True to automatically create an {@link Ext.Shadow}, or a string indicating the
2245  * shadow's display {@link Ext.Shadow#mode}. False to disable the shadow. (defaults to false)
2246  * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: 'div', cls: 'x-layer'}).
2247  * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true)
2248  * @cfg {String} cls CSS class to add to the element
2249  * @cfg {Number} zindex Starting z-index (defaults to 11000)
2250  * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 4)
2251  * @cfg {Boolean} useDisplay
2252  * Defaults to use css offsets to hide the Layer. Specify <tt>true</tt>
2253  * to use css style <tt>'display:none;'</tt> to hide the Layer.
2254  * @constructor
2255  * @param {Object} config An object with config options.
2256  * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element. If the element is not found it creates it.
2257  */
2258 (function(){
2259 Ext.Layer = function(config, existingEl){
2260     config = config || {};
2261     var dh = Ext.DomHelper,
2262         cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
2263         
2264     if (existingEl) {
2265         this.dom = Ext.getDom(existingEl);
2266     }
2267     if(!this.dom){
2268         var o = config.dh || {tag: 'div', cls: 'x-layer'};
2269         this.dom = dh.append(pel, o);
2270     }
2271     if(config.cls){
2272         this.addClass(config.cls);
2273     }
2274     this.constrain = config.constrain !== false;
2275     this.setVisibilityMode(Ext.Element.VISIBILITY);
2276     if(config.id){
2277         this.id = this.dom.id = config.id;
2278     }else{
2279         this.id = Ext.id(this.dom);
2280     }
2281     this.zindex = config.zindex || this.getZIndex();
2282     this.position('absolute', this.zindex);
2283     if(config.shadow){
2284         this.shadowOffset = config.shadowOffset || 4;
2285         this.shadow = new Ext.Shadow({
2286             offset : this.shadowOffset,
2287             mode : config.shadow
2288         });
2289     }else{
2290         this.shadowOffset = 0;
2291     }
2292     this.useShim = config.shim !== false && Ext.useShims;
2293     this.useDisplay = config.useDisplay;
2294     this.hide();
2295 };
2296
2297 var supr = Ext.Element.prototype;
2298
2299 // shims are shared among layer to keep from having 100 iframes
2300 var shims = [];
2301
2302 Ext.extend(Ext.Layer, Ext.Element, {
2303
2304     getZIndex : function(){
2305         return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
2306     },
2307
2308     getShim : function(){
2309         if(!this.useShim){
2310             return null;
2311         }
2312         if(this.shim){
2313             return this.shim;
2314         }
2315         var shim = shims.shift();
2316         if(!shim){
2317             shim = this.createShim();
2318             shim.enableDisplayMode('block');
2319             shim.dom.style.display = 'none';
2320             shim.dom.style.visibility = 'visible';
2321         }
2322         var pn = this.dom.parentNode;
2323         if(shim.dom.parentNode != pn){
2324             pn.insertBefore(shim.dom, this.dom);
2325         }
2326         shim.setStyle('z-index', this.getZIndex()-2);
2327         this.shim = shim;
2328         return shim;
2329     },
2330
2331     hideShim : function(){
2332         if(this.shim){
2333             this.shim.setDisplayed(false);
2334             shims.push(this.shim);
2335             delete this.shim;
2336         }
2337     },
2338
2339     disableShadow : function(){
2340         if(this.shadow){
2341             this.shadowDisabled = true;
2342             this.shadow.hide();
2343             this.lastShadowOffset = this.shadowOffset;
2344             this.shadowOffset = 0;
2345         }
2346     },
2347
2348     enableShadow : function(show){
2349         if(this.shadow){
2350             this.shadowDisabled = false;
2351             this.shadowOffset = this.lastShadowOffset;
2352             delete this.lastShadowOffset;
2353             if(show){
2354                 this.sync(true);
2355             }
2356         }
2357     },
2358
2359     // private
2360     // this code can execute repeatedly in milliseconds (i.e. during a drag) so
2361     // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
2362     sync : function(doShow){
2363         var shadow = this.shadow;
2364         if(!this.updating && this.isVisible() && (shadow || this.useShim)){
2365             var shim = this.getShim(),
2366                 w = this.getWidth(),
2367                 h = this.getHeight(),
2368                 l = this.getLeft(true),
2369                 t = this.getTop(true);
2370
2371             if(shadow && !this.shadowDisabled){
2372                 if(doShow && !shadow.isVisible()){
2373                     shadow.show(this);
2374                 }else{
2375                     shadow.realign(l, t, w, h);
2376                 }
2377                 if(shim){
2378                     if(doShow){
2379                        shim.show();
2380                     }
2381                     // fit the shim behind the shadow, so it is shimmed too
2382                     var shadowAdj = shadow.el.getXY(), shimStyle = shim.dom.style,
2383                         shadowSize = shadow.el.getSize();
2384                     shimStyle.left = (shadowAdj[0])+'px';
2385                     shimStyle.top = (shadowAdj[1])+'px';
2386                     shimStyle.width = (shadowSize.width)+'px';
2387                     shimStyle.height = (shadowSize.height)+'px';
2388                 }
2389             }else if(shim){
2390                 if(doShow){
2391                    shim.show();
2392                 }
2393                 shim.setSize(w, h);
2394                 shim.setLeftTop(l, t);
2395             }
2396         }
2397     },
2398
2399     // private
2400     destroy : function(){
2401         this.hideShim();
2402         if(this.shadow){
2403             this.shadow.hide();
2404         }
2405         this.removeAllListeners();
2406         Ext.removeNode(this.dom);
2407         delete this.dom;
2408     },
2409
2410     remove : function(){
2411         this.destroy();
2412     },
2413
2414     // private
2415     beginUpdate : function(){
2416         this.updating = true;
2417     },
2418
2419     // private
2420     endUpdate : function(){
2421         this.updating = false;
2422         this.sync(true);
2423     },
2424
2425     // private
2426     hideUnders : function(negOffset){
2427         if(this.shadow){
2428             this.shadow.hide();
2429         }
2430         this.hideShim();
2431     },
2432
2433     // private
2434     constrainXY : function(){
2435         if(this.constrain){
2436             var vw = Ext.lib.Dom.getViewWidth(),
2437                 vh = Ext.lib.Dom.getViewHeight();
2438             var s = Ext.getDoc().getScroll();
2439
2440             var xy = this.getXY();
2441             var x = xy[0], y = xy[1];
2442             var so = this.shadowOffset;
2443             var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so;
2444             // only move it if it needs it
2445             var moved = false;
2446             // first validate right/bottom
2447             if((x + w) > vw+s.left){
2448                 x = vw - w - so;
2449                 moved = true;
2450             }
2451             if((y + h) > vh+s.top){
2452                 y = vh - h - so;
2453                 moved = true;
2454             }
2455             // then make sure top/left isn't negative
2456             if(x < s.left){
2457                 x = s.left;
2458                 moved = true;
2459             }
2460             if(y < s.top){
2461                 y = s.top;
2462                 moved = true;
2463             }
2464             if(moved){
2465                 if(this.avoidY){
2466                     var ay = this.avoidY;
2467                     if(y <= ay && (y+h) >= ay){
2468                         y = ay-h-5;
2469                     }
2470                 }
2471                 xy = [x, y];
2472                 this.storeXY(xy);
2473                 supr.setXY.call(this, xy);
2474                 this.sync();
2475             }
2476         }
2477         return this;
2478     },
2479     
2480     getConstrainOffset : function(){
2481         return this.shadowOffset;    
2482     },
2483
2484     isVisible : function(){
2485         return this.visible;
2486     },
2487
2488     // private
2489     showAction : function(){
2490         this.visible = true; // track visibility to prevent getStyle calls
2491         if(this.useDisplay === true){
2492             this.setDisplayed('');
2493         }else if(this.lastXY){
2494             supr.setXY.call(this, this.lastXY);
2495         }else if(this.lastLT){
2496             supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
2497         }
2498     },
2499
2500     // private
2501     hideAction : function(){
2502         this.visible = false;
2503         if(this.useDisplay === true){
2504             this.setDisplayed(false);
2505         }else{
2506             this.setLeftTop(-10000,-10000);
2507         }
2508     },
2509
2510     // overridden Element method
2511     setVisible : function(v, a, d, c, e){
2512         if(v){
2513             this.showAction();
2514         }
2515         if(a && v){
2516             var cb = function(){
2517                 this.sync(true);
2518                 if(c){
2519                     c();
2520                 }
2521             }.createDelegate(this);
2522             supr.setVisible.call(this, true, true, d, cb, e);
2523         }else{
2524             if(!v){
2525                 this.hideUnders(true);
2526             }
2527             var cb = c;
2528             if(a){
2529                 cb = function(){
2530                     this.hideAction();
2531                     if(c){
2532                         c();
2533                     }
2534                 }.createDelegate(this);
2535             }
2536             supr.setVisible.call(this, v, a, d, cb, e);
2537             if(v){
2538                 this.sync(true);
2539             }else if(!a){
2540                 this.hideAction();
2541             }
2542         }
2543         return this;
2544     },
2545
2546     storeXY : function(xy){
2547         delete this.lastLT;
2548         this.lastXY = xy;
2549     },
2550
2551     storeLeftTop : function(left, top){
2552         delete this.lastXY;
2553         this.lastLT = [left, top];
2554     },
2555
2556     // private
2557     beforeFx : function(){
2558         this.beforeAction();
2559         return Ext.Layer.superclass.beforeFx.apply(this, arguments);
2560     },
2561
2562     // private
2563     afterFx : function(){
2564         Ext.Layer.superclass.afterFx.apply(this, arguments);
2565         this.sync(this.isVisible());
2566     },
2567
2568     // private
2569     beforeAction : function(){
2570         if(!this.updating && this.shadow){
2571             this.shadow.hide();
2572         }
2573     },
2574
2575     // overridden Element method
2576     setLeft : function(left){
2577         this.storeLeftTop(left, this.getTop(true));
2578         supr.setLeft.apply(this, arguments);
2579         this.sync();
2580         return this;
2581     },
2582
2583     setTop : function(top){
2584         this.storeLeftTop(this.getLeft(true), top);
2585         supr.setTop.apply(this, arguments);
2586         this.sync();
2587         return this;
2588     },
2589
2590     setLeftTop : function(left, top){
2591         this.storeLeftTop(left, top);
2592         supr.setLeftTop.apply(this, arguments);
2593         this.sync();
2594         return this;
2595     },
2596
2597     setXY : function(xy, a, d, c, e){
2598         this.fixDisplay();
2599         this.beforeAction();
2600         this.storeXY(xy);
2601         var cb = this.createCB(c);
2602         supr.setXY.call(this, xy, a, d, cb, e);
2603         if(!a){
2604             cb();
2605         }
2606         return this;
2607     },
2608
2609     // private
2610     createCB : function(c){
2611         var el = this;
2612         return function(){
2613             el.constrainXY();
2614             el.sync(true);
2615             if(c){
2616                 c();
2617             }
2618         };
2619     },
2620
2621     // overridden Element method
2622     setX : function(x, a, d, c, e){
2623         this.setXY([x, this.getY()], a, d, c, e);
2624         return this;
2625     },
2626
2627     // overridden Element method
2628     setY : function(y, a, d, c, e){
2629         this.setXY([this.getX(), y], a, d, c, e);
2630         return this;
2631     },
2632
2633     // overridden Element method
2634     setSize : function(w, h, a, d, c, e){
2635         this.beforeAction();
2636         var cb = this.createCB(c);
2637         supr.setSize.call(this, w, h, a, d, cb, e);
2638         if(!a){
2639             cb();
2640         }
2641         return this;
2642     },
2643
2644     // overridden Element method
2645     setWidth : function(w, a, d, c, e){
2646         this.beforeAction();
2647         var cb = this.createCB(c);
2648         supr.setWidth.call(this, w, a, d, cb, e);
2649         if(!a){
2650             cb();
2651         }
2652         return this;
2653     },
2654
2655     // overridden Element method
2656     setHeight : function(h, a, d, c, e){
2657         this.beforeAction();
2658         var cb = this.createCB(c);
2659         supr.setHeight.call(this, h, a, d, cb, e);
2660         if(!a){
2661             cb();
2662         }
2663         return this;
2664     },
2665
2666     // overridden Element method
2667     setBounds : function(x, y, w, h, a, d, c, e){
2668         this.beforeAction();
2669         var cb = this.createCB(c);
2670         if(!a){
2671             this.storeXY([x, y]);
2672             supr.setXY.call(this, [x, y]);
2673             supr.setSize.call(this, w, h, a, d, cb, e);
2674             cb();
2675         }else{
2676             supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
2677         }
2678         return this;
2679     },
2680
2681     /**
2682      * Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
2683      * incremented by two more than the value passed in so that it always shows above any shadow or shim (the shadow
2684      * element, if any, will be assigned z-index + 1, and the shim element, if any, will be assigned the unmodified z-index).
2685      * @param {Number} zindex The new z-index to set
2686      * @return {this} The Layer
2687      */
2688     setZIndex : function(zindex){
2689         this.zindex = zindex;
2690         this.setStyle('z-index', zindex + 2);
2691         if(this.shadow){
2692             this.shadow.setZIndex(zindex + 1);
2693         }
2694         if(this.shim){
2695             this.shim.setStyle('z-index', zindex);
2696         }
2697         return this;
2698     }
2699 });
2700 })();
2701 /**
2702  * @class Ext.Shadow
2703  * Simple class that can provide a shadow effect for any element.  Note that the element MUST be absolutely positioned,
2704  * and the shadow does not provide any shimming.  This should be used only in simple cases -- for more advanced
2705  * functionality that can also provide the same shadow effect, see the {@link Ext.Layer} class.
2706  * @constructor
2707  * Create a new Shadow
2708  * @param {Object} config The config object
2709  */
2710 Ext.Shadow = function(config) {
2711     Ext.apply(this, config);
2712     if (typeof this.mode != "string") {
2713         this.mode = this.defaultMode;
2714     }
2715     var o = this.offset,
2716         a = {
2717             h: 0
2718         },
2719         rad = Math.floor(this.offset / 2);
2720     switch (this.mode.toLowerCase()) {
2721         // all this hideous nonsense calculates the various offsets for shadows
2722         case "drop":
2723             a.w = 0;
2724             a.l = a.t = o;
2725             a.t -= 1;
2726             if (Ext.isIE) {
2727                 a.l -= this.offset + rad;
2728                 a.t -= this.offset + rad;
2729                 a.w -= rad;
2730                 a.h -= rad;
2731                 a.t += 1;
2732             }
2733         break;
2734         case "sides":
2735             a.w = (o * 2);
2736             a.l = -o;
2737             a.t = o - 1;
2738             if (Ext.isIE) {
2739                 a.l -= (this.offset - rad);
2740                 a.t -= this.offset + rad;
2741                 a.l += 1;
2742                 a.w -= (this.offset - rad) * 2;
2743                 a.w -= rad + 1;
2744                 a.h -= 1;
2745             }
2746         break;
2747         case "frame":
2748             a.w = a.h = (o * 2);
2749             a.l = a.t = -o;
2750             a.t += 1;
2751             a.h -= 2;
2752             if (Ext.isIE) {
2753                 a.l -= (this.offset - rad);
2754                 a.t -= (this.offset - rad);
2755                 a.l += 1;
2756                 a.w -= (this.offset + rad + 1);
2757                 a.h -= (this.offset + rad);
2758                 a.h += 1;
2759             }
2760         break;
2761     };
2762
2763     this.adjusts = a;
2764 };
2765
2766 Ext.Shadow.prototype = {
2767     /**
2768      * @cfg {String} mode
2769      * The shadow display mode.  Supports the following options:<div class="mdetail-params"><ul>
2770      * <li><b><tt>sides</tt></b> : Shadow displays on both sides and bottom only</li>
2771      * <li><b><tt>frame</tt></b> : Shadow displays equally on all four sides</li>
2772      * <li><b><tt>drop</tt></b> : Traditional bottom-right drop shadow</li>
2773      * </ul></div>
2774      */
2775     /**
2776      * @cfg {String} offset
2777      * The number of pixels to offset the shadow from the element (defaults to <tt>4</tt>)
2778      */
2779     offset: 4,
2780
2781     // private
2782     defaultMode: "drop",
2783
2784     /**
2785      * Displays the shadow under the target element
2786      * @param {Mixed} targetEl The id or element under which the shadow should display
2787      */
2788     show: function(target) {
2789         target = Ext.get(target);
2790         if (!this.el) {
2791             this.el = Ext.Shadow.Pool.pull();
2792             if (this.el.dom.nextSibling != target.dom) {
2793                 this.el.insertBefore(target);
2794             }
2795         }
2796         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10) - 1);
2797         if (Ext.isIE) {
2798             this.el.dom.style.filter = "progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius=" + (this.offset) + ")";
2799         }
2800         this.realign(
2801         target.getLeft(true),
2802         target.getTop(true),
2803         target.getWidth(),
2804         target.getHeight()
2805         );
2806         this.el.dom.style.display = "block";
2807     },
2808
2809     /**
2810      * Returns true if the shadow is visible, else false
2811      */
2812     isVisible: function() {
2813         return this.el ? true: false;
2814     },
2815
2816     /**
2817      * Direct alignment when values are already available. Show must be called at least once before
2818      * calling this method to ensure it is initialized.
2819      * @param {Number} left The target element left position
2820      * @param {Number} top The target element top position
2821      * @param {Number} width The target element width
2822      * @param {Number} height The target element height
2823      */
2824     realign: function(l, t, w, h) {
2825         if (!this.el) {
2826             return;
2827         }
2828         var a = this.adjusts,
2829             d = this.el.dom,
2830             s = d.style,
2831             iea = 0,
2832             sw = (w + a.w),
2833             sh = (h + a.h),
2834             sws = sw + "px",
2835             shs = sh + "px",
2836             cn,
2837             sww;
2838         s.left = (l + a.l) + "px";
2839         s.top = (t + a.t) + "px";
2840         if (s.width != sws || s.height != shs) {
2841             s.width = sws;
2842             s.height = shs;
2843             if (!Ext.isIE) {
2844                 cn = d.childNodes;
2845                 sww = Math.max(0, (sw - 12)) + "px";
2846                 cn[0].childNodes[1].style.width = sww;
2847                 cn[1].childNodes[1].style.width = sww;
2848                 cn[2].childNodes[1].style.width = sww;
2849                 cn[1].style.height = Math.max(0, (sh - 12)) + "px";
2850             }
2851         }
2852     },
2853
2854     /**
2855      * Hides this shadow
2856      */
2857     hide: function() {
2858         if (this.el) {
2859             this.el.dom.style.display = "none";
2860             Ext.Shadow.Pool.push(this.el);
2861             delete this.el;
2862         }
2863     },
2864
2865     /**
2866      * Adjust the z-index of this shadow
2867      * @param {Number} zindex The new z-index
2868      */
2869     setZIndex: function(z) {
2870         this.zIndex = z;
2871         if (this.el) {
2872             this.el.setStyle("z-index", z);
2873         }
2874     }
2875 };
2876
2877 // Private utility class that manages the internal Shadow cache
2878 Ext.Shadow.Pool = function() {
2879     var p = [],
2880         markup = Ext.isIE ?
2881             '<div class="x-ie-shadow"></div>':
2882             '<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>';
2883     return {
2884         pull: function() {
2885             var sh = p.shift();
2886             if (!sh) {
2887                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
2888                 sh.autoBoxAdjust = false;
2889             }
2890             return sh;
2891         },
2892
2893         push: function(sh) {
2894             p.push(sh);
2895         }
2896     };
2897 }();/**
2898  * @class Ext.BoxComponent
2899  * @extends Ext.Component
2900  * <p>Base class for any {@link Ext.Component Component} that is to be sized as a box, using width and height.</p>
2901  * <p>BoxComponent provides automatic box model adjustments for sizing and positioning and will work correctly
2902  * within the Component rendering model.</p>
2903  * <p>A BoxComponent may be created as a custom Component which encapsulates any HTML element, either a pre-existing
2904  * element, or one that is created to your specifications at render time. Usually, to participate in layouts,
2905  * a Component will need to be a <b>Box</b>Component in order to have its width and height managed.</p>
2906  * <p>To use a pre-existing element as a BoxComponent, configure it so that you preset the <b>el</b> property to the
2907  * element to reference:<pre><code>
2908 var pageHeader = new Ext.BoxComponent({
2909     el: 'my-header-div'
2910 });</code></pre>
2911  * This may then be {@link Ext.Container#add added} to a {@link Ext.Container Container} as a child item.</p>
2912  * <p>To create a BoxComponent based around a HTML element to be created at render time, use the
2913  * {@link Ext.Component#autoEl autoEl} config option which takes the form of a
2914  * {@link Ext.DomHelper DomHelper} specification:<pre><code>
2915 var myImage = new Ext.BoxComponent({
2916     autoEl: {
2917         tag: 'img',
2918         src: '/images/my-image.jpg'
2919     }
2920 });</code></pre></p>
2921  * @constructor
2922  * @param {Ext.Element/String/Object} config The configuration options.
2923  * @xtype box
2924  */
2925 Ext.BoxComponent = Ext.extend(Ext.Component, {
2926
2927     // Configs below are used for all Components when rendered by BoxLayout.
2928     /**
2929      * @cfg {Number} flex
2930      * <p><b>Note</b>: this config is only used when this Component is rendered
2931      * by a Container which has been configured to use a <b>{@link Ext.layout.BoxLayout BoxLayout}.</b>
2932      * Each child Component with a <code>flex</code> property will be flexed either vertically (by a VBoxLayout)
2933      * or horizontally (by an HBoxLayout) according to the item's <b>relative</b> <code>flex</code> value
2934      * compared to the sum of all Components with <code>flex</flex> value specified. Any child items that have
2935      * either a <code>flex = 0</code> or <code>flex = undefined</code> will not be 'flexed' (the initial size will not be changed).
2936      */
2937     // Configs below are used for all Components when rendered by AnchorLayout.
2938     /**
2939      * @cfg {String} anchor <p><b>Note</b>: this config is only used when this Component is rendered
2940      * by a Container which has been configured to use an <b>{@link Ext.layout.AnchorLayout AnchorLayout} (or subclass thereof).</b>
2941      * based layout manager, for example:<div class="mdetail-params"><ul>
2942      * <li>{@link Ext.form.FormPanel}</li>
2943      * <li>specifying <code>layout: 'anchor' // or 'form', or 'absolute'</code></li>
2944      * </ul></div></p>
2945      * <p>See {@link Ext.layout.AnchorLayout}.{@link Ext.layout.AnchorLayout#anchor anchor} also.</p>
2946      */
2947     // tabTip config is used when a BoxComponent is a child of a TabPanel
2948     /**
2949      * @cfg {String} tabTip
2950      * <p><b>Note</b>: this config is only used when this BoxComponent is a child item of a TabPanel.</p>
2951      * A string to be used as innerHTML (html tags are accepted) to show in a tooltip when mousing over
2952      * the associated tab selector element. {@link Ext.QuickTips}.init()
2953      * must be called in order for the tips to render.
2954      */
2955     // Configs below are used for all Components when rendered by BorderLayout.
2956     /**
2957      * @cfg {String} region <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2958      * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2959      * layout manager (e.g. specifying <tt>layout:'border'</tt>).</p><br>
2960      * <p>See {@link Ext.layout.BorderLayout} also.</p>
2961      */
2962     // margins config is used when a BoxComponent is rendered by BorderLayout or BoxLayout.
2963     /**
2964      * @cfg {Object} margins <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2965      * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2966      * or one of the two <b>{@link Ext.layout.BoxLayout BoxLayout} subclasses.</b></p>
2967      * <p>An object containing margins to apply to this BoxComponent in the
2968      * format:</p><pre><code>
2969 {
2970     top: (top margin),
2971     right: (right margin),
2972     bottom: (bottom margin),
2973     left: (left margin)
2974 }</code></pre>
2975      * <p>May also be a string containing space-separated, numeric margin values. The order of the
2976      * sides associated with each value matches the way CSS processes margin values:</p>
2977      * <p><div class="mdetail-params"><ul>
2978      * <li>If there is only one value, it applies to all sides.</li>
2979      * <li>If there are two values, the top and bottom borders are set to the first value and the
2980      * right and left are set to the second.</li>
2981      * <li>If there are three values, the top is set to the first value, the left and right are set
2982      * to the second, and the bottom is set to the third.</li>
2983      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
2984      * </ul></div></p>
2985      * <p>Defaults to:</p><pre><code>
2986      * {top:0, right:0, bottom:0, left:0}
2987      * </code></pre>
2988      */
2989     /**
2990      * @cfg {Number} x
2991      * The local x (left) coordinate for this component if contained within a positioning container.
2992      */
2993     /**
2994      * @cfg {Number} y
2995      * The local y (top) coordinate for this component if contained within a positioning container.
2996      */
2997     /**
2998      * @cfg {Number} pageX
2999      * The page level x coordinate for this component if contained within a positioning container.
3000      */
3001     /**
3002      * @cfg {Number} pageY
3003      * The page level y coordinate for this component if contained within a positioning container.
3004      */
3005     /**
3006      * @cfg {Number} height
3007      * The height of this component in pixels (defaults to auto).
3008      * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
3009      */
3010     /**
3011      * @cfg {Number} width
3012      * The width of this component in pixels (defaults to auto).
3013      * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
3014      */
3015     /**
3016      * @cfg {Number} boxMinHeight
3017      * <p>The minimum value in pixels which this BoxComponent will set its height to.</p>
3018      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
3019      */
3020     /**
3021      * @cfg {Number} boxMinWidth
3022      * <p>The minimum value in pixels which this BoxComponent will set its width to.</p>
3023      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
3024      */
3025     /**
3026      * @cfg {Number} boxMaxHeight
3027      * <p>The maximum value in pixels which this BoxComponent will set its height to.</p>
3028      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
3029      */
3030     /**
3031      * @cfg {Number} boxMaxWidth
3032      * <p>The maximum value in pixels which this BoxComponent will set its width to.</p>
3033      * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
3034      */
3035     /**
3036      * @cfg {Boolean} autoHeight
3037      * <p>True to use height:'auto', false to use fixed height (or allow it to be managed by its parent
3038      * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
3039      * <p><b>Note</b>: Although many components inherit this config option, not all will
3040      * function as expected with a height of 'auto'. Setting autoHeight:true means that the
3041      * browser will manage height based on the element's contents, and that Ext will not manage it at all.</p>
3042      * <p>If the <i>browser</i> is managing the height, be aware that resizes performed by the browser in response
3043      * to changes within the structure of the Component cannot be detected. Therefore changes to the height might
3044      * result in elements needing to be synchronized with the new height. Example:</p><pre><code>
3045 var w = new Ext.Window({
3046     title: 'Window',
3047     width: 600,
3048     autoHeight: true,
3049     items: {
3050         title: 'Collapse Me',
3051         height: 400,
3052         collapsible: true,
3053         border: false,
3054         listeners: {
3055             beforecollapse: function() {
3056                 w.el.shadow.hide();
3057             },
3058             beforeexpand: function() {
3059                 w.el.shadow.hide();
3060             },
3061             collapse: function() {
3062                 w.syncShadow();
3063             },
3064             expand: function() {
3065                 w.syncShadow();
3066             }
3067         }
3068     }
3069 }).show();
3070 </code></pre>
3071      */
3072     /**
3073      * @cfg {Boolean} autoWidth
3074      * <p>True to use width:'auto', false to use fixed width (or allow it to be managed by its parent
3075      * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
3076      * <p><b>Note</b>: Although many components  inherit this config option, not all will
3077      * function as expected with a width of 'auto'. Setting autoWidth:true means that the
3078      * browser will manage width based on the element's contents, and that Ext will not manage it at all.</p>
3079      * <p>If the <i>browser</i> is managing the width, be aware that resizes performed by the browser in response
3080      * to changes within the structure of the Component cannot be detected. Therefore changes to the width might
3081      * result in elements needing to be synchronized with the new width. For example, where the target element is:</p><pre><code>
3082 &lt;div id='grid-container' style='margin-left:25%;width:50%'>&lt;/div>
3083 </code></pre>
3084      * A Panel rendered into that target element must listen for browser window resize in order to relay its
3085       * child items when the browser changes its width:<pre><code>
3086 var myPanel = new Ext.Panel({
3087     renderTo: 'grid-container',
3088     monitorResize: true, // relay on browser resize
3089     title: 'Panel',
3090     height: 400,
3091     autoWidth: true,
3092     layout: 'hbox',
3093     layoutConfig: {
3094         align: 'stretch'
3095     },
3096     defaults: {
3097         flex: 1
3098     },
3099     items: [{
3100         title: 'Box 1',
3101     }, {
3102         title: 'Box 2'
3103     }, {
3104         title: 'Box 3'
3105     }],
3106 });
3107 </code></pre>
3108      */
3109     /**
3110      * @cfg {Boolean} autoScroll
3111      * <code>true</code> to use overflow:'auto' on the components layout element and show scroll bars automatically when
3112      * necessary, <code>false</code> to clip any overflowing content (defaults to <code>false</code>).
3113      */
3114
3115     /* // private internal config
3116      * {Boolean} deferHeight
3117      * True to defer height calculations to an external component, false to allow this component to set its own
3118      * height (defaults to false).
3119      */
3120
3121     // private
3122     initComponent : function(){
3123         Ext.BoxComponent.superclass.initComponent.call(this);
3124         this.addEvents(
3125             /**
3126              * @event resize
3127              * Fires after the component is resized.
3128              * @param {Ext.Component} this
3129              * @param {Number} adjWidth The box-adjusted width that was set
3130              * @param {Number} adjHeight The box-adjusted height that was set
3131              * @param {Number} rawWidth The width that was originally specified
3132              * @param {Number} rawHeight The height that was originally specified
3133              */
3134             'resize',
3135             /**
3136              * @event move
3137              * Fires after the component is moved.
3138              * @param {Ext.Component} this
3139              * @param {Number} x The new x position
3140              * @param {Number} y The new y position
3141              */
3142             'move'
3143         );
3144     },
3145
3146     // private, set in afterRender to signify that the component has been rendered
3147     boxReady : false,
3148     // private, used to defer height settings to subclasses
3149     deferHeight: false,
3150
3151     /**
3152      * Sets the width and height of this BoxComponent. This method fires the {@link #resize} event. This method can accept
3153      * either width and height as separate arguments, or you can pass a size object like <code>{width:10, height:20}</code>.
3154      * @param {Mixed} width The new width to set. This may be one of:<div class="mdetail-params"><ul>
3155      * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3156      * <li>A String used to set the CSS width style.</li>
3157      * <li>A size object in the format <code>{width: widthValue, height: heightValue}</code>.</li>
3158      * <li><code>undefined</code> to leave the width unchanged.</li>
3159      * </ul></div>
3160      * @param {Mixed} height The new height to set (not required if a size object is passed as the first arg).
3161      * This may be one of:<div class="mdetail-params"><ul>
3162      * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3163      * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
3164      * <li><code>undefined</code> to leave the height unchanged.</li>
3165      * </ul></div>
3166      * @return {Ext.BoxComponent} this
3167      */
3168     setSize : function(w, h){
3169
3170         // support for standard size objects
3171         if(typeof w == 'object'){
3172             h = w.height;
3173             w = w.width;
3174         }
3175         if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
3176             w = this.boxMinWidth;
3177         }
3178         if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) {
3179             h = this.boxMinHeight;
3180         }
3181         if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) {
3182             w = this.boxMaxWidth;
3183         }
3184         if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) {
3185             h = this.boxMaxHeight;
3186         }
3187         // not rendered
3188         if(!this.boxReady){
3189             this.width  = w;
3190             this.height = h;
3191             return this;
3192         }
3193
3194         // prevent recalcs when not needed
3195         if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
3196             return this;
3197         }
3198         this.lastSize = {width: w, height: h};
3199         var adj = this.adjustSize(w, h),
3200             aw = adj.width,
3201             ah = adj.height,
3202             rz;
3203         if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
3204             rz = this.getResizeEl();
3205             if(!this.deferHeight && aw !== undefined && ah !== undefined){
3206                 rz.setSize(aw, ah);
3207             }else if(!this.deferHeight && ah !== undefined){
3208                 rz.setHeight(ah);
3209             }else if(aw !== undefined){
3210                 rz.setWidth(aw);
3211             }
3212             this.onResize(aw, ah, w, h);
3213             this.fireEvent('resize', this, aw, ah, w, h);
3214         }
3215         return this;
3216     },
3217
3218     /**
3219      * Sets the width of the component.  This method fires the {@link #resize} event.
3220      * @param {Mixed} width The new width to set. This may be one of:<div class="mdetail-params"><ul>
3221      * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit defaultUnit}s (by default, pixels).</li>
3222      * <li>A String used to set the CSS width style.</li>
3223      * </ul></div>
3224      * @return {Ext.BoxComponent} this
3225      */
3226     setWidth : function(width){
3227         return this.setSize(width);
3228     },
3229
3230     /**
3231      * Sets the height of the component.  This method fires the {@link #resize} event.
3232      * @param {Mixed} height The new height to set. This may be one of:<div class="mdetail-params"><ul>
3233      * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit defaultUnit}s (by default, pixels).</li>
3234      * <li>A String used to set the CSS height style.</li>
3235      * <li><i>undefined</i> to leave the height unchanged.</li>
3236      * </ul></div>
3237      * @return {Ext.BoxComponent} this
3238      */
3239     setHeight : function(height){
3240         return this.setSize(undefined, height);
3241     },
3242
3243     /**
3244      * Gets the current size of the component's underlying element.
3245      * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
3246      */
3247     getSize : function(){
3248         return this.getResizeEl().getSize();
3249     },
3250
3251     /**
3252      * Gets the current width of the component's underlying element.
3253      * @return {Number}
3254      */
3255     getWidth : function(){
3256         return this.getResizeEl().getWidth();
3257     },
3258
3259     /**
3260      * Gets the current height of the component's underlying element.
3261      * @return {Number}
3262      */
3263     getHeight : function(){
3264         return this.getResizeEl().getHeight();
3265     },
3266
3267     /**
3268      * Gets the current size of the component's underlying element, including space taken by its margins.
3269      * @return {Object} An object containing the element's size {width: (element width + left/right margins), height: (element height + top/bottom margins)}
3270      */
3271     getOuterSize : function(){
3272         var el = this.getResizeEl();
3273         return {width: el.getWidth() + el.getMargins('lr'),
3274                 height: el.getHeight() + el.getMargins('tb')};
3275     },
3276
3277     /**
3278      * Gets the current XY position of the component's underlying element.
3279      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
3280      * @return {Array} The XY position of the element (e.g., [100, 200])
3281      */
3282     getPosition : function(local){
3283         var el = this.getPositionEl();
3284         if(local === true){
3285             return [el.getLeft(true), el.getTop(true)];
3286         }
3287         return this.xy || el.getXY();
3288     },
3289
3290     /**
3291      * Gets the current box measurements of the component's underlying element.
3292      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
3293      * @return {Object} box An object in the format {x, y, width, height}
3294      */
3295     getBox : function(local){
3296         var pos = this.getPosition(local);
3297         var s = this.getSize();
3298         s.x = pos[0];
3299         s.y = pos[1];
3300         return s;
3301     },
3302
3303     /**
3304      * Sets the current box measurements of the component's underlying element.
3305      * @param {Object} box An object in the format {x, y, width, height}
3306      * @return {Ext.BoxComponent} this
3307      */
3308     updateBox : function(box){
3309         this.setSize(box.width, box.height);
3310         this.setPagePosition(box.x, box.y);
3311         return this;
3312     },
3313
3314     /**
3315      * <p>Returns the outermost Element of this Component which defines the Components overall size.</p>
3316      * <p><i>Usually</i> this will return the same Element as <code>{@link #getEl}</code>,
3317      * but in some cases, a Component may have some more wrapping Elements around its main
3318      * active Element.</p>
3319      * <p>An example is a ComboBox. It is encased in a <i>wrapping</i> Element which
3320      * contains both the <code>&lt;input></code> Element (which is what would be returned
3321      * by its <code>{@link #getEl}</code> method, <i>and</i> the trigger button Element.
3322      * This Element is returned as the <code>resizeEl</code>.
3323      * @return {Ext.Element} The Element which is to be resized by size managing layouts.
3324      */
3325     getResizeEl : function(){
3326         return this.resizeEl || this.el;
3327     },
3328
3329     /**
3330      * Sets the overflow on the content element of the component.
3331      * @param {Boolean} scroll True to allow the Component to auto scroll.
3332      * @return {Ext.BoxComponent} this
3333      */
3334     setAutoScroll : function(scroll){
3335         if(this.rendered){
3336             this.getContentTarget().setOverflow(scroll ? 'auto' : '');
3337         }
3338         this.autoScroll = scroll;
3339         return this;
3340     },
3341
3342     /**
3343      * Sets the left and top of the component.  To set the page XY position instead, use {@link #setPagePosition}.
3344      * This method fires the {@link #move} event.
3345      * @param {Number} left The new left
3346      * @param {Number} top The new top
3347      * @return {Ext.BoxComponent} this
3348      */
3349     setPosition : function(x, y){
3350         if(x && typeof x[1] == 'number'){
3351             y = x[1];
3352             x = x[0];
3353         }
3354         this.x = x;
3355         this.y = y;
3356         if(!this.boxReady){
3357             return this;
3358         }
3359         var adj = this.adjustPosition(x, y);
3360         var ax = adj.x, ay = adj.y;
3361
3362         var el = this.getPositionEl();
3363         if(ax !== undefined || ay !== undefined){
3364             if(ax !== undefined && ay !== undefined){
3365                 el.setLeftTop(ax, ay);
3366             }else if(ax !== undefined){
3367                 el.setLeft(ax);
3368             }else if(ay !== undefined){
3369                 el.setTop(ay);
3370             }
3371             this.onPosition(ax, ay);
3372             this.fireEvent('move', this, ax, ay);
3373         }
3374         return this;
3375     },
3376
3377     /**
3378      * Sets the page XY position of the component.  To set the left and top instead, use {@link #setPosition}.
3379      * This method fires the {@link #move} event.
3380      * @param {Number} x The new x position
3381      * @param {Number} y The new y position
3382      * @return {Ext.BoxComponent} this
3383      */
3384     setPagePosition : function(x, y){
3385         if(x && typeof x[1] == 'number'){
3386             y = x[1];
3387             x = x[0];
3388         }
3389         this.pageX = x;
3390         this.pageY = y;
3391         if(!this.boxReady){
3392             return;
3393         }
3394         if(x === undefined || y === undefined){ // cannot translate undefined points
3395             return;
3396         }
3397         var p = this.getPositionEl().translatePoints(x, y);
3398         this.setPosition(p.left, p.top);
3399         return this;
3400     },
3401
3402     // private
3403     afterRender : function(){
3404         Ext.BoxComponent.superclass.afterRender.call(this);
3405         if(this.resizeEl){
3406             this.resizeEl = Ext.get(this.resizeEl);
3407         }
3408         if(this.positionEl){
3409             this.positionEl = Ext.get(this.positionEl);
3410         }
3411         this.boxReady = true;
3412         Ext.isDefined(this.autoScroll) && this.setAutoScroll(this.autoScroll);
3413         this.setSize(this.width, this.height);
3414         if(this.x || this.y){
3415             this.setPosition(this.x, this.y);
3416         }else if(this.pageX || this.pageY){
3417             this.setPagePosition(this.pageX, this.pageY);
3418         }
3419     },
3420
3421     /**
3422      * Force the component's size to recalculate based on the underlying element's current height and width.
3423      * @return {Ext.BoxComponent} this
3424      */
3425     syncSize : function(){
3426         delete this.lastSize;
3427         this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
3428         return this;
3429     },
3430
3431     /* // protected
3432      * Called after the component is resized, this method is empty by default but can be implemented by any
3433      * subclass that needs to perform custom logic after a resize occurs.
3434      * @param {Number} adjWidth The box-adjusted width that was set
3435      * @param {Number} adjHeight The box-adjusted height that was set
3436      * @param {Number} rawWidth The width that was originally specified
3437      * @param {Number} rawHeight The height that was originally specified
3438      */
3439     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
3440     },
3441
3442     /* // protected
3443      * Called after the component is moved, this method is empty by default but can be implemented by any
3444      * subclass that needs to perform custom logic after a move occurs.
3445      * @param {Number} x The new x position
3446      * @param {Number} y The new y position
3447      */
3448     onPosition : function(x, y){
3449
3450     },
3451
3452     // private
3453     adjustSize : function(w, h){
3454         if(this.autoWidth){
3455             w = 'auto';
3456         }
3457         if(this.autoHeight){
3458             h = 'auto';
3459         }
3460         return {width : w, height: h};
3461     },
3462
3463     // private
3464     adjustPosition : function(x, y){
3465         return {x : x, y: y};
3466     }
3467 });
3468 Ext.reg('box', Ext.BoxComponent);
3469
3470
3471 /**
3472  * @class Ext.Spacer
3473  * @extends Ext.BoxComponent
3474  * <p>Used to provide a sizable space in a layout.</p>
3475  * @constructor
3476  * @param {Object} config
3477  */
3478 Ext.Spacer = Ext.extend(Ext.BoxComponent, {
3479     autoEl:'div'
3480 });
3481 Ext.reg('spacer', Ext.Spacer);/**
3482  * @class Ext.SplitBar
3483  * @extends Ext.util.Observable
3484  * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).
3485  * <br><br>
3486  * Usage:
3487  * <pre><code>
3488 var split = new Ext.SplitBar("elementToDrag", "elementToSize",
3489                    Ext.SplitBar.HORIZONTAL, Ext.SplitBar.LEFT);
3490 split.setAdapter(new Ext.SplitBar.AbsoluteLayoutAdapter("container"));
3491 split.minSize = 100;
3492 split.maxSize = 600;
3493 split.animate = true;
3494 split.on('moved', splitterMoved);
3495 </code></pre>
3496  * @constructor
3497  * Create a new SplitBar
3498  * @param {Mixed} dragElement The element to be dragged and act as the SplitBar.
3499  * @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged
3500  * @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
3501  * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or
3502                         Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial
3503                         position of the SplitBar).
3504  */
3505 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
3506
3507     /** @private */
3508     this.el = Ext.get(dragElement, true);
3509     this.el.dom.unselectable = "on";
3510     /** @private */
3511     this.resizingEl = Ext.get(resizingElement, true);
3512
3513     /**
3514      * @private
3515      * The orientation of the split. Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
3516      * Note: If this is changed after creating the SplitBar, the placement property must be manually updated
3517      * @type Number
3518      */
3519     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
3520
3521     /**
3522      * The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.
3523      * @type Number
3524      * @property tickSize
3525      */
3526     /**
3527      * The minimum size of the resizing element. (Defaults to 0)
3528      * @type Number
3529      */
3530     this.minSize = 0;
3531
3532     /**
3533      * The maximum size of the resizing element. (Defaults to 2000)
3534      * @type Number
3535      */
3536     this.maxSize = 2000;
3537
3538     /**
3539      * Whether to animate the transition to the new size
3540      * @type Boolean
3541      */
3542     this.animate = false;
3543
3544     /**
3545      * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.
3546      * @type Boolean
3547      */
3548     this.useShim = false;
3549
3550     /** @private */
3551     this.shim = null;
3552
3553     if(!existingProxy){
3554         /** @private */
3555         this.proxy = Ext.SplitBar.createProxy(this.orientation);
3556     }else{
3557         this.proxy = Ext.get(existingProxy).dom;
3558     }
3559     /** @private */
3560     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
3561
3562     /** @private */
3563     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
3564
3565     /** @private */
3566     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
3567
3568     /** @private */
3569     this.dragSpecs = {};
3570
3571     /**
3572      * @private The adapter to use to positon and resize elements
3573      */
3574     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
3575     this.adapter.init(this);
3576
3577     if(this.orientation == Ext.SplitBar.HORIZONTAL){
3578         /** @private */
3579         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
3580         this.el.addClass("x-splitbar-h");
3581     }else{
3582         /** @private */
3583         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
3584         this.el.addClass("x-splitbar-v");
3585     }
3586
3587     this.addEvents(
3588         /**
3589          * @event resize
3590          * Fires when the splitter is moved (alias for {@link #moved})
3591          * @param {Ext.SplitBar} this
3592          * @param {Number} newSize the new width or height
3593          */
3594         "resize",
3595         /**
3596          * @event moved
3597          * Fires when the splitter is moved
3598          * @param {Ext.SplitBar} this
3599          * @param {Number} newSize the new width or height
3600          */
3601         "moved",
3602         /**
3603          * @event beforeresize
3604          * Fires before the splitter is dragged
3605          * @param {Ext.SplitBar} this
3606          */
3607         "beforeresize",
3608
3609         "beforeapply"
3610     );
3611
3612     Ext.SplitBar.superclass.constructor.call(this);
3613 };
3614
3615 Ext.extend(Ext.SplitBar, Ext.util.Observable, {
3616     onStartProxyDrag : function(x, y){
3617         this.fireEvent("beforeresize", this);
3618         this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);
3619         this.overlay.unselectable();
3620         this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
3621         this.overlay.show();
3622         Ext.get(this.proxy).setDisplayed("block");
3623         var size = this.adapter.getElementSize(this);
3624         this.activeMinSize = this.getMinimumSize();
3625         this.activeMaxSize = this.getMaximumSize();
3626         var c1 = size - this.activeMinSize;
3627         var c2 = Math.max(this.activeMaxSize - size, 0);
3628         if(this.orientation == Ext.SplitBar.HORIZONTAL){
3629             this.dd.resetConstraints();
3630             this.dd.setXConstraint(
3631                 this.placement == Ext.SplitBar.LEFT ? c1 : c2,
3632                 this.placement == Ext.SplitBar.LEFT ? c2 : c1,
3633                 this.tickSize
3634             );
3635             this.dd.setYConstraint(0, 0);
3636         }else{
3637             this.dd.resetConstraints();
3638             this.dd.setXConstraint(0, 0);
3639             this.dd.setYConstraint(
3640                 this.placement == Ext.SplitBar.TOP ? c1 : c2,
3641                 this.placement == Ext.SplitBar.TOP ? c2 : c1,
3642                 this.tickSize
3643             );
3644          }
3645         this.dragSpecs.startSize = size;
3646         this.dragSpecs.startPoint = [x, y];
3647         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
3648     },
3649
3650     /**
3651      * @private Called after the drag operation by the DDProxy
3652      */
3653     onEndProxyDrag : function(e){
3654         Ext.get(this.proxy).setDisplayed(false);
3655         var endPoint = Ext.lib.Event.getXY(e);
3656         if(this.overlay){
3657             Ext.destroy(this.overlay);
3658             delete this.overlay;
3659         }
3660         var newSize;
3661         if(this.orientation == Ext.SplitBar.HORIZONTAL){
3662             newSize = this.dragSpecs.startSize +
3663                 (this.placement == Ext.SplitBar.LEFT ?
3664                     endPoint[0] - this.dragSpecs.startPoint[0] :
3665                     this.dragSpecs.startPoint[0] - endPoint[0]
3666                 );
3667         }else{
3668             newSize = this.dragSpecs.startSize +
3669                 (this.placement == Ext.SplitBar.TOP ?
3670                     endPoint[1] - this.dragSpecs.startPoint[1] :
3671                     this.dragSpecs.startPoint[1] - endPoint[1]
3672                 );
3673         }
3674         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
3675         if(newSize != this.dragSpecs.startSize){
3676             if(this.fireEvent('beforeapply', this, newSize) !== false){
3677                 this.adapter.setElementSize(this, newSize);
3678                 this.fireEvent("moved", this, newSize);
3679                 this.fireEvent("resize", this, newSize);
3680             }
3681         }
3682     },
3683
3684     /**
3685      * Get the adapter this SplitBar uses
3686      * @return The adapter object
3687      */
3688     getAdapter : function(){
3689         return this.adapter;
3690     },
3691
3692     /**
3693      * Set the adapter this SplitBar uses
3694      * @param {Object} adapter A SplitBar adapter object
3695      */
3696     setAdapter : function(adapter){
3697         this.adapter = adapter;
3698         this.adapter.init(this);
3699     },
3700
3701     /**
3702      * Gets the minimum size for the resizing element
3703      * @return {Number} The minimum size
3704      */
3705     getMinimumSize : function(){
3706         return this.minSize;
3707     },
3708
3709     /**
3710      * Sets the minimum size for the resizing element
3711      * @param {Number} minSize The minimum size
3712      */
3713     setMinimumSize : function(minSize){
3714         this.minSize = minSize;
3715     },
3716
3717     /**
3718      * Gets the maximum size for the resizing element
3719      * @return {Number} The maximum size
3720      */
3721     getMaximumSize : function(){
3722         return this.maxSize;
3723     },
3724
3725     /**
3726      * Sets the maximum size for the resizing element
3727      * @param {Number} maxSize The maximum size
3728      */
3729     setMaximumSize : function(maxSize){
3730         this.maxSize = maxSize;
3731     },
3732
3733     /**
3734      * Sets the initialize size for the resizing element
3735      * @param {Number} size The initial size
3736      */
3737     setCurrentSize : function(size){
3738         var oldAnimate = this.animate;
3739         this.animate = false;
3740         this.adapter.setElementSize(this, size);
3741         this.animate = oldAnimate;
3742     },
3743
3744     /**
3745      * Destroy this splitbar.
3746      * @param {Boolean} removeEl True to remove the element
3747      */
3748     destroy : function(removeEl){
3749         Ext.destroy(this.shim, Ext.get(this.proxy));
3750         this.dd.unreg();
3751         if(removeEl){
3752             this.el.remove();
3753         }
3754         this.purgeListeners();
3755     }
3756 });
3757
3758 /**
3759  * @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.
3760  */
3761 Ext.SplitBar.createProxy = function(dir){
3762     var proxy = new Ext.Element(document.createElement("div"));
3763     document.body.appendChild(proxy.dom);
3764     proxy.unselectable();
3765     var cls = 'x-splitbar-proxy';
3766     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
3767     return proxy.dom;
3768 };
3769
3770 /**
3771  * @class Ext.SplitBar.BasicLayoutAdapter
3772  * Default Adapter. It assumes the splitter and resizing element are not positioned
3773  * elements and only gets/sets the width of the element. Generally used for table based layouts.
3774  */
3775 Ext.SplitBar.BasicLayoutAdapter = function(){
3776 };
3777
3778 Ext.SplitBar.BasicLayoutAdapter.prototype = {
3779     // do nothing for now
3780     init : function(s){
3781
3782     },
3783     /**
3784      * Called before drag operations to get the current size of the resizing element.
3785      * @param {Ext.SplitBar} s The SplitBar using this adapter
3786      */
3787      getElementSize : function(s){
3788         if(s.orientation == Ext.SplitBar.HORIZONTAL){
3789             return s.resizingEl.getWidth();
3790         }else{
3791             return s.resizingEl.getHeight();
3792         }
3793     },
3794
3795     /**
3796      * Called after drag operations to set the size of the resizing element.
3797      * @param {Ext.SplitBar} s The SplitBar using this adapter
3798      * @param {Number} newSize The new size to set
3799      * @param {Function} onComplete A function to be invoked when resizing is complete
3800      */
3801     setElementSize : function(s, newSize, onComplete){
3802         if(s.orientation == Ext.SplitBar.HORIZONTAL){
3803             if(!s.animate){
3804                 s.resizingEl.setWidth(newSize);
3805                 if(onComplete){
3806                     onComplete(s, newSize);
3807                 }
3808             }else{
3809                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
3810             }
3811         }else{
3812
3813             if(!s.animate){
3814                 s.resizingEl.setHeight(newSize);
3815                 if(onComplete){
3816                     onComplete(s, newSize);
3817                 }
3818             }else{
3819                 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
3820             }
3821         }
3822     }
3823 };
3824
3825 /**
3826  *@class Ext.SplitBar.AbsoluteLayoutAdapter
3827  * @extends Ext.SplitBar.BasicLayoutAdapter
3828  * Adapter that  moves the splitter element to align with the resized sizing element.
3829  * Used with an absolute positioned SplitBar.
3830  * @param {Mixed} container The container that wraps around the absolute positioned content. If it's
3831  * document.body, make sure you assign an id to the body element.
3832  */
3833 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
3834     this.basic = new Ext.SplitBar.BasicLayoutAdapter();
3835     this.container = Ext.get(container);
3836 };
3837
3838 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
3839     init : function(s){
3840         this.basic.init(s);
3841     },
3842
3843     getElementSize : function(s){
3844         return this.basic.getElementSize(s);
3845     },
3846
3847     setElementSize : function(s, newSize, onComplete){
3848         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
3849     },
3850
3851     moveSplitter : function(s){
3852         var yes = Ext.SplitBar;
3853         switch(s.placement){
3854             case yes.LEFT:
3855                 s.el.setX(s.resizingEl.getRight());
3856                 break;
3857             case yes.RIGHT:
3858                 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
3859                 break;
3860             case yes.TOP:
3861                 s.el.setY(s.resizingEl.getBottom());
3862                 break;
3863             case yes.BOTTOM:
3864                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
3865                 break;
3866         }
3867     }
3868 };
3869
3870 /**
3871  * Orientation constant - Create a vertical SplitBar
3872  * @static
3873  * @type Number
3874  */
3875 Ext.SplitBar.VERTICAL = 1;
3876
3877 /**
3878  * Orientation constant - Create a horizontal SplitBar
3879  * @static
3880  * @type Number
3881  */
3882 Ext.SplitBar.HORIZONTAL = 2;
3883
3884 /**
3885  * Placement constant - The resizing element is to the left of the splitter element
3886  * @static
3887  * @type Number
3888  */
3889 Ext.SplitBar.LEFT = 1;
3890
3891 /**
3892  * Placement constant - The resizing element is to the right of the splitter element
3893  * @static
3894  * @type Number
3895  */
3896 Ext.SplitBar.RIGHT = 2;
3897
3898 /**
3899  * Placement constant - The resizing element is positioned above the splitter element
3900  * @static
3901  * @type Number
3902  */
3903 Ext.SplitBar.TOP = 3;
3904
3905 /**
3906  * Placement constant - The resizing element is positioned under splitter element
3907  * @static
3908  * @type Number
3909  */
3910 Ext.SplitBar.BOTTOM = 4;
3911 /**
3912  * @class Ext.Container
3913  * @extends Ext.BoxComponent
3914  * <p>Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the
3915  * basic behavior of containing items, namely adding, inserting and removing items.</p>
3916  *
3917  * <p>The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}.
3918  * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight
3919  * Container to be encapsulated by an HTML element to your specifications by using the
3920  * <code><b>{@link Ext.Component#autoEl autoEl}</b></code> config option. This is a useful technique when creating
3921  * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels}
3922  * for example.</p>
3923  *
3924  * <p>The code below illustrates both how to explicitly create a Container, and how to implicitly
3925  * create one using the <b><code>'container'</code></b> xtype:<pre><code>
3926 // explicitly create a Container
3927 var embeddedColumns = new Ext.Container({
3928     autoEl: 'div',  // This is the default
3929     layout: 'column',
3930     defaults: {
3931         // implicitly create Container by specifying xtype
3932         xtype: 'container',
3933         autoEl: 'div', // This is the default.
3934         layout: 'form',
3935         columnWidth: 0.5,
3936         style: {
3937             padding: '10px'
3938         }
3939     },
3940 //  The two items below will be Ext.Containers, each encapsulated by a &lt;DIV> element.
3941     items: [{
3942         items: {
3943             xtype: 'datefield',
3944             name: 'startDate',
3945             fieldLabel: 'Start date'
3946         }
3947     }, {
3948         items: {
3949             xtype: 'datefield',
3950             name: 'endDate',
3951             fieldLabel: 'End date'
3952         }
3953     }]
3954 });</code></pre></p>
3955  *
3956  * <p><u><b>Layout</b></u></p>
3957  * <p>Container classes delegate the rendering of child Components to a layout
3958  * manager class which must be configured into the Container using the
3959  * <code><b>{@link #layout}</b></code> configuration property.</p>
3960  * <p>When either specifying child <code>{@link #items}</code> of a Container,
3961  * or dynamically {@link #add adding} Components to a Container, remember to
3962  * consider how you wish the Container to arrange those child elements, and
3963  * whether those child elements need to be sized using one of Ext's built-in
3964  * <b><code>{@link #layout}</code></b> schemes. By default, Containers use the
3965  * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only
3966  * renders child components, appending them one after the other inside the
3967  * Container, and <b>does not apply any sizing</b> at all.</p>
3968  * <p>A common mistake is when a developer neglects to specify a
3969  * <b><code>{@link #layout}</code></b> (e.g. widgets like GridPanels or
3970  * TreePanels are added to Containers for which no <code><b>{@link #layout}</b></code>
3971  * has been specified). If a Container is left to use the default
3972  * {@link Ext.layout.ContainerLayout ContainerLayout} scheme, none of its
3973  * child components will be resized, or changed in any way when the Container
3974  * is resized.</p>
3975  * <p>Certain layout managers allow dynamic addition of child components.
3976  * Those that do include {@link Ext.layout.CardLayout},
3977  * {@link Ext.layout.AnchorLayout}, {@link Ext.layout.FormLayout}, and
3978  * {@link Ext.layout.TableLayout}. For example:<pre><code>
3979 //  Create the GridPanel.
3980 var myNewGrid = new Ext.grid.GridPanel({
3981     store: myStore,
3982     columns: myColumnModel,
3983     title: 'Results', // the title becomes the title of the tab
3984 });
3985
3986 myTabPanel.add(myNewGrid); // {@link Ext.TabPanel} implicitly uses {@link Ext.layout.CardLayout CardLayout}
3987 myTabPanel.{@link Ext.TabPanel#setActiveTab setActiveTab}(myNewGrid);
3988  * </code></pre></p>
3989  * <p>The example above adds a newly created GridPanel to a TabPanel. Note that
3990  * a TabPanel uses {@link Ext.layout.CardLayout} as its layout manager which
3991  * means all its child items are sized to {@link Ext.layout.FitLayout fit}
3992  * exactly into its client area.
3993  * <p><b><u>Overnesting is a common problem</u></b>.
3994  * An example of overnesting occurs when a GridPanel is added to a TabPanel
3995  * by wrapping the GridPanel <i>inside</i> a wrapping Panel (that has no
3996  * <code><b>{@link #layout}</b></code> specified) and then add that wrapping Panel
3997  * to the TabPanel. The point to realize is that a GridPanel <b>is</b> a
3998  * Component which can be added directly to a Container. If the wrapping Panel
3999  * has no <code><b>{@link #layout}</b></code> configuration, then the overnested
4000  * GridPanel will not be sized as expected.<p>
4001  *
4002  * <p><u><b>Adding via remote configuration</b></u></p>
4003  *
4004  * <p>A server side script can be used to add Components which are generated dynamically on the server.
4005  * An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server
4006  * based on certain parameters:
4007  * </p><pre><code>
4008 // execute an Ajax request to invoke server side script:
4009 Ext.Ajax.request({
4010     url: 'gen-invoice-grid.php',
4011     // send additional parameters to instruct server script
4012     params: {
4013         startDate: Ext.getCmp('start-date').getValue(),
4014         endDate: Ext.getCmp('end-date').getValue()
4015     },
4016     // process the response object to add it to the TabPanel:
4017     success: function(xhr) {
4018         var newComponent = eval(xhr.responseText); // see discussion below
4019         myTabPanel.add(newComponent); // add the component to the TabPanel
4020         myTabPanel.setActiveTab(newComponent);
4021     },
4022     failure: function() {
4023         Ext.Msg.alert("Grid create failed", "Server communication failure");
4024     }
4025 });
4026 </code></pre>
4027  * <p>The server script needs to return an executable Javascript statement which, when processed
4028  * using <code>eval()</code>, will return either a config object with an {@link Ext.Component#xtype xtype},
4029  * or an instantiated Component. The server might return this for example:</p><pre><code>
4030 (function() {
4031     function formatDate(value){
4032         return value ? value.dateFormat('M d, Y') : '';
4033     };
4034
4035     var store = new Ext.data.Store({
4036         url: 'get-invoice-data.php',
4037         baseParams: {
4038             startDate: '01/01/2008',
4039             endDate: '01/31/2008'
4040         },
4041         reader: new Ext.data.JsonReader({
4042             record: 'transaction',
4043             idProperty: 'id',
4044             totalRecords: 'total'
4045         }, [
4046            'customer',
4047            'invNo',
4048            {name: 'date', type: 'date', dateFormat: 'm/d/Y'},
4049            {name: 'value', type: 'float'}
4050         ])
4051     });
4052
4053     var grid = new Ext.grid.GridPanel({
4054         title: 'Invoice Report',
4055         bbar: new Ext.PagingToolbar(store),
4056         store: store,
4057         columns: [
4058             {header: "Customer", width: 250, dataIndex: 'customer', sortable: true},
4059             {header: "Invoice Number", width: 120, dataIndex: 'invNo', sortable: true},
4060             {header: "Invoice Date", width: 100, dataIndex: 'date', renderer: formatDate, sortable: true},
4061             {header: "Value", width: 120, dataIndex: 'value', renderer: 'usMoney', sortable: true}
4062         ],
4063     });
4064     store.load();
4065     return grid;  // return instantiated component
4066 })();
4067 </code></pre>
4068  * <p>When the above code fragment is passed through the <code>eval</code> function in the success handler
4069  * of the Ajax request, the code is executed by the Javascript processor, and the anonymous function
4070  * runs, and returns the instantiated grid component.</p>
4071  * <p>Note: since the code above is <i>generated</i> by a server script, the <code>baseParams</code> for
4072  * the Store, the metadata to allow generation of the Record layout, and the ColumnModel
4073  * can all be generated into the code since these are all known on the server.</p>
4074  *
4075  * @xtype container
4076  */
4077 Ext.Container = Ext.extend(Ext.BoxComponent, {
4078     /**
4079      * @cfg {Boolean} monitorResize
4080      * True to automatically monitor window resize events to handle anything that is sensitive to the current size
4081      * of the viewport.  This value is typically managed by the chosen <code>{@link #layout}</code> and should not need
4082      * to be set manually.
4083      */
4084     /**
4085      * @cfg {String/Object} layout
4086      * <p><b>*Important</b>: In order for child items to be correctly sized and
4087      * positioned, typically a layout manager <b>must</b> be specified through
4088      * the <code>layout</code> configuration option.</p>
4089      * <br><p>The sizing and positioning of child {@link items} is the responsibility of
4090      * the Container's layout manager which creates and manages the type of layout
4091      * you have in mind.  For example:</p><pre><code>
4092 new Ext.Window({
4093     width:300, height: 300,
4094     layout: 'fit', // explicitly set layout manager: override the default (layout:'auto')
4095     items: [{
4096         title: 'Panel inside a Window'
4097     }]
4098 }).show();
4099      * </code></pre>
4100      * <p>If the {@link #layout} configuration is not explicitly specified for
4101      * a general purpose container (e.g. Container or Panel) the
4102      * {@link Ext.layout.ContainerLayout default layout manager} will be used
4103      * which does nothing but render child components sequentially into the
4104      * Container (no sizing or positioning will be performed in this situation).
4105      * Some container classes implicitly specify a default layout
4106      * (e.g. FormPanel specifies <code>layout:'form'</code>). Other specific
4107      * purpose classes internally specify/manage their internal layout (e.g.
4108      * GridPanel, TabPanel, TreePanel, Toolbar, Menu, etc.).</p>
4109      * <br><p><b><code>layout</code></b> may be specified as either as an Object or
4110      * as a String:</p><div><ul class="mdetail-params">
4111      *
4112      * <li><u>Specify as an Object</u></li>
4113      * <div><ul class="mdetail-params">
4114      * <li>Example usage:</li>
4115 <pre><code>
4116 layout: {
4117     type: 'vbox',
4118     padding: '5',
4119     align: 'left'
4120 }
4121 </code></pre>
4122      *
4123      * <li><code><b>type</b></code></li>
4124      * <br/><p>The layout type to be used for this container.  If not specified,
4125      * a default {@link Ext.layout.ContainerLayout} will be created and used.</p>
4126      * <br/><p>Valid layout <code>type</code> values are:</p>
4127      * <div class="sub-desc"><ul class="mdetail-params">
4128      * <li><code><b>{@link Ext.layout.AbsoluteLayout absolute}</b></code></li>
4129      * <li><code><b>{@link Ext.layout.AccordionLayout accordion}</b></code></li>
4130      * <li><code><b>{@link Ext.layout.AnchorLayout anchor}</b></code></li>
4131      * <li><code><b>{@link Ext.layout.ContainerLayout auto}</b></code> &nbsp;&nbsp;&nbsp; <b>Default</b></li>
4132      * <li><code><b>{@link Ext.layout.BorderLayout border}</b></code></li>
4133      * <li><code><b>{@link Ext.layout.CardLayout card}</b></code></li>
4134      * <li><code><b>{@link Ext.layout.ColumnLayout column}</b></code></li>
4135      * <li><code><b>{@link Ext.layout.FitLayout fit}</b></code></li>
4136      * <li><code><b>{@link Ext.layout.FormLayout form}</b></code></li>
4137      * <li><code><b>{@link Ext.layout.HBoxLayout hbox}</b></code></li>
4138      * <li><code><b>{@link Ext.layout.MenuLayout menu}</b></code></li>
4139      * <li><code><b>{@link Ext.layout.TableLayout table}</b></code></li>
4140      * <li><code><b>{@link Ext.layout.ToolbarLayout toolbar}</b></code></li>
4141      * <li><code><b>{@link Ext.layout.VBoxLayout vbox}</b></code></li>
4142      * </ul></div>
4143      *
4144      * <li>Layout specific configuration properties</li>
4145      * <br/><p>Additional layout specific configuration properties may also be
4146      * specified. For complete details regarding the valid config options for
4147      * each layout type, see the layout class corresponding to the <code>type</code>
4148      * specified.</p>
4149      *
4150      * </ul></div>
4151      *
4152      * <li><u>Specify as a String</u></li>
4153      * <div><ul class="mdetail-params">
4154      * <li>Example usage:</li>
4155 <pre><code>
4156 layout: 'vbox',
4157 layoutConfig: {
4158     padding: '5',
4159     align: 'left'
4160 }
4161 </code></pre>
4162      * <li><code><b>layout</b></code></li>
4163      * <br/><p>The layout <code>type</code> to be used for this container (see list
4164      * of valid layout type values above).</p><br/>
4165      * <li><code><b>{@link #layoutConfig}</b></code></li>
4166      * <br/><p>Additional layout specific configuration properties. For complete
4167      * details regarding the valid config options for each layout type, see the
4168      * layout class corresponding to the <code>layout</code> specified.</p>
4169      * </ul></div></ul></div>
4170      */
4171     /**
4172      * @cfg {Object} layoutConfig
4173      * This is a config object containing properties specific to the chosen
4174      * <b><code>{@link #layout}</code></b> if <b><code>{@link #layout}</code></b>
4175      * has been specified as a <i>string</i>.</p>
4176      */
4177     /**
4178      * @cfg {Boolean/Number} bufferResize
4179      * When set to true (50 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer
4180      * the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers
4181      * with a large quantity of sub-components for which frequent layout calls would be expensive. Defaults to <code>50</code>.
4182      */
4183     bufferResize: 50,
4184
4185     /**
4186      * @cfg {String/Number} activeItem
4187      * A string component id or the numeric index of the component that should be initially activated within the
4188      * container's layout on render.  For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first
4189      * item in the container's collection).  activeItem only applies to layout styles that can display
4190      * items one at a time (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout} and
4191      * {@link Ext.layout.FitLayout}).  Related to {@link Ext.layout.ContainerLayout#activeItem}.
4192      */
4193     /**
4194      * @cfg {Object/Array} items
4195      * <pre><b>** IMPORTANT</b>: be sure to <b>{@link #layout specify a <code>layout</code>} if needed ! **</b></pre>
4196      * <p>A single item, or an array of child Components to be added to this container,
4197      * for example:</p>
4198      * <pre><code>
4199 // specifying a single item
4200 items: {...},
4201 layout: 'fit',    // specify a layout!
4202
4203 // specifying multiple items
4204 items: [{...}, {...}],
4205 layout: 'anchor', // specify a layout!
4206      * </code></pre>
4207      * <p>Each item may be:</p>
4208      * <div><ul class="mdetail-params">
4209      * <li>any type of object based on {@link Ext.Component}</li>
4210      * <li>a fully instanciated object or</li>
4211      * <li>an object literal that:</li>
4212      * <div><ul class="mdetail-params">
4213      * <li>has a specified <code>{@link Ext.Component#xtype xtype}</code></li>
4214      * <li>the {@link Ext.Component#xtype} specified is associated with the Component
4215      * desired and should be chosen from one of the available xtypes as listed
4216      * in {@link Ext.Component}.</li>
4217      * <li>If an <code>{@link Ext.Component#xtype xtype}</code> is not explicitly
4218      * specified, the {@link #defaultType} for that Container is used.</li>
4219      * <li>will be "lazily instanciated", avoiding the overhead of constructing a fully
4220      * instanciated Component object</li>
4221      * </ul></div></ul></div>
4222      * <p><b>Notes</b>:</p>
4223      * <div><ul class="mdetail-params">
4224      * <li>Ext uses lazy rendering. Child Components will only be rendered
4225      * should it become necessary. Items are automatically laid out when they are first
4226      * shown (no sizing is done while hidden), or in response to a {@link #doLayout} call.</li>
4227      * <li>Do not specify <code>{@link Ext.Panel#contentEl contentEl}</code>/
4228      * <code>{@link Ext.Panel#html html}</code> with <code>items</code>.</li>
4229      * </ul></div>
4230      */
4231     /**
4232      * @cfg {Object|Function} defaults
4233      * <p>This option is a means of applying default settings to all added items whether added through the {@link #items}
4234      * config or via the {@link #add} or {@link #insert} methods.</p>
4235      * <p>If an added item is a config object, and <b>not</b> an instantiated Component, then the default properties are
4236      * unconditionally applied. If the added item <b>is</b> an instantiated Component, then the default properties are
4237      * applied conditionally so as not to override existing properties in the item.</p>
4238      * <p>If the defaults option is specified as a function, then the function will be called using this Container as the
4239      * scope (<code>this</code> reference) and passing the added item as the first parameter. Any resulting object
4240      * from that call is then applied to the item as default properties.</p>
4241      * <p>For example, to automatically apply padding to the body of each of a set of
4242      * contained {@link Ext.Panel} items, you could pass: <code>defaults: {bodyStyle:'padding:15px'}</code>.</p>
4243      * <p>Usage:</p><pre><code>
4244 defaults: {               // defaults are applied to items, not the container
4245     autoScroll:true
4246 },
4247 items: [
4248     {
4249         xtype: 'panel',   // defaults <b>do not</b> have precedence over
4250         id: 'panel1',     // options in config objects, so the defaults
4251         autoScroll: false // will not be applied here, panel1 will be autoScroll:false
4252     },
4253     new Ext.Panel({       // defaults <b>do</b> have precedence over options
4254         id: 'panel2',     // options in components, so the defaults
4255         autoScroll: false // will be applied here, panel2 will be autoScroll:true.
4256     })
4257 ]
4258      * </code></pre>
4259      */
4260
4261
4262     /** @cfg {Boolean} autoDestroy
4263      * If true the container will automatically destroy any contained component that is removed from it, else
4264      * destruction must be handled manually (defaults to true).
4265      */
4266     autoDestroy : true,
4267
4268     /** @cfg {Boolean} forceLayout
4269      * If true the container will force a layout initially even if hidden or collapsed. This option
4270      * is useful for forcing forms to render in collapsed or hidden containers. (defaults to false).
4271      */
4272     forceLayout: false,
4273
4274     /** @cfg {Boolean} hideBorders
4275      * True to hide the borders of each contained component, false to defer to the component's existing
4276      * border settings (defaults to false).
4277      */
4278     /** @cfg {String} defaultType
4279      * <p>The default {@link Ext.Component xtype} of child Components to create in this Container when
4280      * a child item is specified as a raw configuration object, rather than as an instantiated Component.</p>
4281      * <p>Defaults to <code>'panel'</code>, except {@link Ext.menu.Menu} which defaults to <code>'menuitem'</code>,
4282      * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to <code>'button'</code>.</p>
4283      */
4284     defaultType : 'panel',
4285
4286     /** @cfg {String} resizeEvent
4287      * The event to listen to for resizing in layouts. Defaults to <code>'resize'</code>.
4288      */
4289     resizeEvent: 'resize',
4290
4291     /**
4292      * @cfg {Array} bubbleEvents
4293      * <p>An array of events that, when fired, should be bubbled to any parent container.
4294      * See {@link Ext.util.Observable#enableBubble}.
4295      * Defaults to <code>['add', 'remove']</code>.
4296      */
4297     bubbleEvents: ['add', 'remove'],
4298
4299     // private
4300     initComponent : function(){
4301         Ext.Container.superclass.initComponent.call(this);
4302
4303         this.addEvents(
4304             /**
4305              * @event afterlayout
4306              * Fires when the components in this container are arranged by the associated layout manager.
4307              * @param {Ext.Container} this
4308              * @param {ContainerLayout} layout The ContainerLayout implementation for this container
4309              */
4310             'afterlayout',
4311             /**
4312              * @event beforeadd
4313              * Fires before any {@link Ext.Component} is added or inserted into the container.
4314              * A handler can return false to cancel the add.
4315              * @param {Ext.Container} this
4316              * @param {Ext.Component} component The component being added
4317              * @param {Number} index The index at which the component will be added to the container's items collection
4318              */
4319             'beforeadd',
4320             /**
4321              * @event beforeremove
4322              * Fires before any {@link Ext.Component} is removed from the container.  A handler can return
4323              * false to cancel the remove.
4324              * @param {Ext.Container} this
4325              * @param {Ext.Component} component The component being removed
4326              */
4327             'beforeremove',
4328             /**
4329              * @event add
4330              * @bubbles
4331              * Fires after any {@link Ext.Component} is added or inserted into the container.
4332              * @param {Ext.Container} this
4333              * @param {Ext.Component} component The component that was added
4334              * @param {Number} index The index at which the component was added to the container's items collection
4335              */
4336             'add',
4337             /**
4338              * @event remove
4339              * @bubbles
4340              * Fires after any {@link Ext.Component} is removed from the container.
4341              * @param {Ext.Container} this
4342              * @param {Ext.Component} component The component that was removed
4343              */
4344             'remove'
4345         );
4346
4347         /**
4348          * The collection of components in this container as a {@link Ext.util.MixedCollection}
4349          * @type MixedCollection
4350          * @property items
4351          */
4352         var items = this.items;
4353         if(items){
4354             delete this.items;
4355             this.add(items);
4356         }
4357     },
4358
4359     // private
4360     initItems : function(){
4361         if(!this.items){
4362             this.items = new Ext.util.MixedCollection(false, this.getComponentId);
4363             this.getLayout(); // initialize the layout
4364         }
4365     },
4366
4367     // private
4368     setLayout : function(layout){
4369         if(this.layout && this.layout != layout){
4370             this.layout.setContainer(null);
4371         }
4372         this.layout = layout;
4373         this.initItems();
4374         layout.setContainer(this);
4375     },
4376
4377     afterRender: function(){
4378         // Render this Container, this should be done before setLayout is called which
4379         // will hook onResize
4380         Ext.Container.superclass.afterRender.call(this);
4381         if(!this.layout){
4382             this.layout = 'auto';
4383         }
4384         if(Ext.isObject(this.layout) && !this.layout.layout){
4385             this.layoutConfig = this.layout;
4386             this.layout = this.layoutConfig.type;
4387         }
4388         if(Ext.isString(this.layout)){
4389             this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
4390         }
4391         this.setLayout(this.layout);
4392
4393         // If a CardLayout, the active item set
4394         if(this.activeItem !== undefined && this.layout.setActiveItem){
4395             var item = this.activeItem;
4396             delete this.activeItem;
4397             this.layout.setActiveItem(item);
4398         }
4399
4400         // If we have no ownerCt, render and size all children
4401         if(!this.ownerCt){
4402             this.doLayout(false, true);
4403         }
4404
4405         // This is a manually configured flag set by users in conjunction with renderTo.
4406         // Not to be confused with the flag by the same name used in Layouts.
4407         if(this.monitorResize === true){
4408             Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
4409         }
4410     },
4411
4412     /**
4413      * <p>Returns the Element to be used to contain the child Components of this Container.</p>
4414      * <p>An implementation is provided which returns the Container's {@link #getEl Element}, but
4415      * if there is a more complex structure to a Container, this may be overridden to return
4416      * the element into which the {@link #layout layout} renders child Components.</p>
4417      * @return {Ext.Element} The Element to render child Components into.
4418      */
4419     getLayoutTarget : function(){
4420         return this.el;
4421     },
4422
4423     // private - used as the key lookup function for the items collection
4424     getComponentId : function(comp){
4425         return comp.getItemId();
4426     },
4427
4428     /**
4429      * <p>Adds {@link Ext.Component Component}(s) to this Container.</p>
4430      * <br><p><b>Description</b></u> :
4431      * <div><ul class="mdetail-params">
4432      * <li>Fires the {@link #beforeadd} event before adding</li>
4433      * <li>The Container's {@link #defaults default config values} will be applied
4434      * accordingly (see <code>{@link #defaults}</code> for details).</li>
4435      * <li>Fires the {@link #add} event after the component has been added.</li>
4436      * </ul></div>
4437      * <br><p><b>Notes</b></u> :
4438      * <div><ul class="mdetail-params">
4439      * <li>If the Container is <i>already rendered</i> when <code>add</code>
4440      * is called, you may need to call {@link #doLayout} to refresh the view which causes
4441      * any unrendered child Components to be rendered. This is required so that you can
4442      * <code>add</code> multiple child components if needed while only refreshing the layout
4443      * once. For example:<pre><code>
4444 var tb = new {@link Ext.Toolbar}();
4445 tb.render(document.body);  // toolbar is rendered
4446 tb.add({text:'Button 1'}); // add multiple items ({@link #defaultType} for {@link Ext.Toolbar Toolbar} is 'button')
4447 tb.add({text:'Button 2'});
4448 tb.{@link #doLayout}();             // refresh the layout
4449      * </code></pre></li>
4450      * <li><i>Warning:</i> Containers directly managed by the BorderLayout layout manager
4451      * may not be removed or added.  See the Notes for {@link Ext.layout.BorderLayout BorderLayout}
4452      * for more details.</li>
4453      * </ul></div>
4454      * @param {...Object/Array} component
4455      * <p>Either one or more Components to add or an Array of Components to add.  See
4456      * <code>{@link #items}</code> for additional information.</p>
4457      * @return {Ext.Component/Array} The Components that were added.
4458      */
4459     add : function(comp){
4460         this.initItems();
4461         var args = arguments.length > 1;
4462         if(args || Ext.isArray(comp)){
4463             var result = [];
4464             Ext.each(args ? arguments : comp, function(c){
4465                 result.push(this.add(c));
4466             }, this);
4467             return result;
4468         }
4469         var c = this.lookupComponent(this.applyDefaults(comp));
4470         var index = this.items.length;
4471         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
4472             this.items.add(c);
4473             // *onAdded
4474             c.onAdded(this, index);
4475             this.onAdd(c);
4476             this.fireEvent('add', this, c, index);
4477         }
4478         return c;
4479     },
4480
4481     onAdd : function(c){
4482         // Empty template method
4483     },
4484
4485     // private
4486     onAdded : function(container, pos) {
4487         //overridden here so we can cascade down, not worth creating a template method.
4488         this.ownerCt = container;
4489         this.initRef();
4490         //initialize references for child items
4491         this.cascade(function(c){
4492             c.initRef();
4493         });
4494         this.fireEvent('added', this, container, pos);
4495     },
4496
4497     /**
4498      * Inserts a Component into this Container at a specified index. Fires the
4499      * {@link #beforeadd} event before inserting, then fires the {@link #add} event after the
4500      * Component has been inserted.
4501      * @param {Number} index The index at which the Component will be inserted
4502      * into the Container's items collection
4503      * @param {Ext.Component} component The child Component to insert.<br><br>
4504      * Ext uses lazy rendering, and will only render the inserted Component should
4505      * it become necessary.<br><br>
4506      * A Component config object may be passed in order to avoid the overhead of
4507      * constructing a real Component object if lazy rendering might mean that the
4508      * inserted Component will not be rendered immediately. To take advantage of
4509      * this 'lazy instantiation', set the {@link Ext.Component#xtype} config
4510      * property to the registered type of the Component wanted.<br><br>
4511      * For a list of all available xtypes, see {@link Ext.Component}.
4512      * @return {Ext.Component} component The Component (or config object) that was
4513      * inserted with the Container's default config values applied.
4514      */
4515     insert : function(index, comp) {
4516         var args   = arguments,
4517             length = args.length,
4518             result = [],
4519             i, c;
4520         
4521         this.initItems();
4522         
4523         if (length > 2) {
4524             for (i = length - 1; i >= 1; --i) {
4525                 result.push(this.insert(index, args[i]));
4526             }
4527             return result;
4528         }
4529         
4530         c = this.lookupComponent(this.applyDefaults(comp));
4531         index = Math.min(index, this.items.length);
4532         
4533         if (this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false) {
4534             if (c.ownerCt == this) {
4535                 this.items.remove(c);
4536             }
4537             this.items.insert(index, c);
4538             c.onAdded(this, index);
4539             this.onAdd(c);
4540             this.fireEvent('add', this, c, index);
4541         }
4542         
4543         return c;
4544     },
4545
4546     // private
4547     applyDefaults : function(c){
4548         var d = this.defaults;
4549         if(d){
4550             if(Ext.isFunction(d)){
4551                 d = d.call(this, c);
4552             }
4553             if(Ext.isString(c)){
4554                 c = Ext.ComponentMgr.get(c);
4555                 Ext.apply(c, d);
4556             }else if(!c.events){
4557                 Ext.applyIf(c, d);
4558             }else{
4559                 Ext.apply(c, d);
4560             }
4561         }
4562         return c;
4563     },
4564
4565     // private
4566     onBeforeAdd : function(item){
4567         if(item.ownerCt){
4568             item.ownerCt.remove(item, false);
4569         }
4570         if(this.hideBorders === true){
4571             item.border = (item.border === true);
4572         }
4573     },
4574
4575     /**
4576      * Removes a component from this container.  Fires the {@link #beforeremove} event before removing, then fires
4577      * the {@link #remove} event after the component has been removed.
4578      * @param {Component/String} component The component reference or id to remove.
4579      * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
4580      * Defaults to the value of this Container's {@link #autoDestroy} config.
4581      * @return {Ext.Component} component The Component that was removed.
4582      */
4583     remove : function(comp, autoDestroy){
4584         this.initItems();
4585         var c = this.getComponent(comp);
4586         if(c && this.fireEvent('beforeremove', this, c) !== false){
4587             this.doRemove(c, autoDestroy);
4588             this.fireEvent('remove', this, c);
4589         }
4590         return c;
4591     },
4592
4593     onRemove: function(c){
4594         // Empty template method
4595     },
4596
4597     // private
4598     doRemove: function(c, autoDestroy){
4599         var l = this.layout,
4600             hasLayout = l && this.rendered;
4601
4602         if(hasLayout){
4603             l.onRemove(c);
4604         }
4605         this.items.remove(c);
4606         c.onRemoved();
4607         this.onRemove(c);
4608         if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
4609             c.destroy();
4610         }
4611         if(hasLayout){
4612             l.afterRemove(c);
4613         }
4614     },
4615
4616     /**
4617      * Removes all components from this container.
4618      * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
4619      * Defaults to the value of this Container's {@link #autoDestroy} config.
4620      * @return {Array} Array of the destroyed components
4621      */
4622     removeAll: function(autoDestroy){
4623         this.initItems();
4624         var item, rem = [], items = [];
4625         this.items.each(function(i){
4626             rem.push(i);
4627         });
4628         for (var i = 0, len = rem.length; i < len; ++i){
4629             item = rem[i];
4630             this.remove(item, autoDestroy);
4631             if(item.ownerCt !== this){
4632                 items.push(item);
4633             }
4634         }
4635         return items;
4636     },
4637
4638     /**
4639      * Examines this container's <code>{@link #items}</code> <b>property</b>
4640      * and gets a direct child component of this container.
4641      * @param {String/Number} comp This parameter may be any of the following:
4642      * <div><ul class="mdetail-params">
4643      * <li>a <b><code>String</code></b> : representing the <code>{@link Ext.Component#itemId itemId}</code>
4644      * or <code>{@link Ext.Component#id id}</code> of the child component </li>
4645      * <li>a <b><code>Number</code></b> : representing the position of the child component
4646      * within the <code>{@link #items}</code> <b>property</b></li>
4647      * </ul></div>
4648      * <p>For additional information see {@link Ext.util.MixedCollection#get}.
4649      * @return Ext.Component The component (if found).
4650      */
4651     getComponent : function(comp){
4652         if(Ext.isObject(comp)){
4653             comp = comp.getItemId();
4654         }
4655         return this.items.get(comp);
4656     },
4657
4658     // private
4659     lookupComponent : function(comp){
4660         if(Ext.isString(comp)){
4661             return Ext.ComponentMgr.get(comp);
4662         }else if(!comp.events){
4663             return this.createComponent(comp);
4664         }
4665         return comp;
4666     },
4667
4668     // private
4669     createComponent : function(config, defaultType){
4670         if (config.render) {
4671             return config;
4672         }
4673         // add in ownerCt at creation time but then immediately
4674         // remove so that onBeforeAdd can handle it
4675         var c = Ext.create(Ext.apply({
4676             ownerCt: this
4677         }, config), defaultType || this.defaultType);
4678         delete c.initialConfig.ownerCt;
4679         delete c.ownerCt;
4680         return c;
4681     },
4682
4683     /**
4684      * @private
4685      * We can only lay out if there is a view area in which to layout.
4686      * display:none on the layout target, *or any of its parent elements* will mean it has no view area.
4687      */
4688     canLayout : function() {
4689         var el = this.getVisibilityEl();
4690         return el && el.dom && !el.isStyle("display", "none");
4691     },
4692
4693     /**
4694      * Force this container's layout to be recalculated. A call to this function is required after adding a new component
4695      * to an already rendered container, or possibly after changing sizing/position properties of child components.
4696      * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto
4697      * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer)
4698      * @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden.
4699      * @return {Ext.Container} this
4700      */
4701
4702     doLayout : function(shallow, force){
4703         var rendered = this.rendered,
4704             forceLayout = force || this.forceLayout;
4705
4706         if(this.collapsed || !this.canLayout()){
4707             this.deferLayout = this.deferLayout || !shallow;
4708             if(!forceLayout){
4709                 return;
4710             }
4711             shallow = shallow && !this.deferLayout;
4712         } else {
4713             delete this.deferLayout;
4714         }
4715         if(rendered && this.layout){
4716             this.layout.layout();
4717         }
4718         if(shallow !== true && this.items){
4719             var cs = this.items.items;
4720             for(var i = 0, len = cs.length; i < len; i++){
4721                 var c = cs[i];
4722                 if(c.doLayout){
4723                     c.doLayout(false, forceLayout);
4724                 }
4725             }
4726         }
4727         if(rendered){
4728             this.onLayout(shallow, forceLayout);
4729         }
4730         // Initial layout completed
4731         this.hasLayout = true;
4732         delete this.forceLayout;
4733     },
4734
4735     onLayout : Ext.emptyFn,
4736
4737     // private
4738     shouldBufferLayout: function(){
4739         /*
4740          * Returns true if the container should buffer a layout.
4741          * This is true only if the container has previously been laid out
4742          * and has a parent container that is pending a layout.
4743          */
4744         var hl = this.hasLayout;
4745         if(this.ownerCt){
4746             // Only ever buffer if we've laid out the first time and we have one pending.
4747             return hl ? !this.hasLayoutPending() : false;
4748         }
4749         // Never buffer initial layout
4750         return hl;
4751     },
4752
4753     // private
4754     hasLayoutPending: function(){
4755         // Traverse hierarchy to see if any parent container has a pending layout.
4756         var pending = false;
4757         this.ownerCt.bubble(function(c){
4758             if(c.layoutPending){
4759                 pending = true;
4760                 return false;
4761             }
4762         });
4763         return pending;
4764     },
4765
4766     onShow : function(){
4767         // removes css classes that were added to hide
4768         Ext.Container.superclass.onShow.call(this);
4769         // If we were sized during the time we were hidden, layout.
4770         if(Ext.isDefined(this.deferLayout)){
4771             delete this.deferLayout;
4772             this.doLayout(true);
4773         }
4774     },
4775
4776     /**
4777      * Returns the layout currently in use by the container.  If the container does not currently have a layout
4778      * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout.
4779      * @return {ContainerLayout} layout The container's layout
4780      */
4781     getLayout : function(){
4782         if(!this.layout){
4783             var layout = new Ext.layout.AutoLayout(this.layoutConfig);
4784             this.setLayout(layout);
4785         }
4786         return this.layout;
4787     },
4788
4789     // private
4790     beforeDestroy : function(){
4791         var c;
4792         if(this.items){
4793             while(c = this.items.first()){
4794                 this.doRemove(c, true);
4795             }
4796         }
4797         if(this.monitorResize){
4798             Ext.EventManager.removeResizeListener(this.doLayout, this);
4799         }
4800         Ext.destroy(this.layout);
4801         Ext.Container.superclass.beforeDestroy.call(this);
4802     },
4803
4804     /**
4805      * Cascades down the component/container heirarchy from this component (called first), calling the specified function with
4806      * each component. The scope (<i>this</i>) of
4807      * function call will be the scope provided or the current component. The arguments to the function
4808      * will be the args provided or the current component. If the function returns false at any point,
4809      * the cascade is stopped on that branch.
4810      * @param {Function} fn The function to call
4811      * @param {Object} scope (optional) The scope of the function (defaults to current component)
4812      * @param {Array} args (optional) The args to call the function with (defaults to passing the current component)
4813      * @return {Ext.Container} this
4814      */
4815     cascade : function(fn, scope, args){
4816         if(fn.apply(scope || this, args || [this]) !== false){
4817             if(this.items){
4818                 var cs = this.items.items;
4819                 for(var i = 0, len = cs.length; i < len; i++){
4820                     if(cs[i].cascade){
4821                         cs[i].cascade(fn, scope, args);
4822                     }else{
4823                         fn.apply(scope || cs[i], args || [cs[i]]);
4824                     }
4825                 }
4826             }
4827         }
4828         return this;
4829     },
4830
4831     /**
4832      * Find a component under this container at any level by id
4833      * @param {String} id
4834      * @deprecated Fairly useless method, since you can just use Ext.getCmp. Should be removed for 4.0
4835      * If you need to test if an id belongs to a container, you can use getCmp and findParent*.
4836      * @return Ext.Component
4837      */
4838     findById : function(id){
4839         var m = null, 
4840             ct = this;
4841         this.cascade(function(c){
4842             if(ct != c && c.id === id){
4843                 m = c;
4844                 return false;
4845             }
4846         });
4847         return m;
4848     },
4849
4850     /**
4851      * Find a component under this container at any level by xtype or class
4852      * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
4853      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
4854      * the default), or true to check whether this Component is directly of the specified xtype.
4855      * @return {Array} Array of Ext.Components
4856      */
4857     findByType : function(xtype, shallow){
4858         return this.findBy(function(c){
4859             return c.isXType(xtype, shallow);
4860         });
4861     },
4862
4863     /**
4864      * Find a component under this container at any level by property
4865      * @param {String} prop
4866      * @param {String} value
4867      * @return {Array} Array of Ext.Components
4868      */
4869     find : function(prop, value){
4870         return this.findBy(function(c){
4871             return c[prop] === value;
4872         });
4873     },
4874
4875     /**
4876      * Find a component under this container at any level by a custom function. If the passed function returns
4877      * true, the component will be included in the results. The passed function is called with the arguments (component, this container).
4878      * @param {Function} fn The function to call
4879      * @param {Object} scope (optional)
4880      * @return {Array} Array of Ext.Components
4881      */
4882     findBy : function(fn, scope){
4883         var m = [], ct = this;
4884         this.cascade(function(c){
4885             if(ct != c && fn.call(scope || c, c, ct) === true){
4886                 m.push(c);
4887             }
4888         });
4889         return m;
4890     },
4891
4892     /**
4893      * Get a component contained by this container (alias for items.get(key))
4894      * @param {String/Number} key The index or id of the component
4895      * @deprecated Should be removed in 4.0, since getComponent does the same thing.
4896      * @return {Ext.Component} Ext.Component
4897      */
4898     get : function(key){
4899         return this.getComponent(key);
4900     }
4901 });
4902
4903 Ext.Container.LAYOUTS = {};
4904 Ext.reg('container', Ext.Container);
4905 /**
4906  * @class Ext.layout.ContainerLayout
4907  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
4908  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
4909  */
4910 Ext.layout.ContainerLayout = Ext.extend(Object, {
4911     /**
4912      * @cfg {String} extraCls
4913      * <p>An optional extra CSS class that will be added to the container. This can be useful for adding
4914      * customized styles to the container or any of its children using standard CSS rules. See
4915      * {@link Ext.Component}.{@link Ext.Component#ctCls ctCls} also.</p>
4916      * <p><b>Note</b>: <tt>extraCls</tt> defaults to <tt>''</tt> except for the following classes
4917      * which assign a value by default:
4918      * <div class="mdetail-params"><ul>
4919      * <li>{@link Ext.layout.AbsoluteLayout Absolute Layout} : <tt>'x-abs-layout-item'</tt></li>
4920      * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-item'</tt></li>
4921      * <li>{@link Ext.layout.ColumnLayout Column Layout} : <tt>'x-column'</tt></li>
4922      * </ul></div>
4923      * To configure the above Classes with an extra CSS class append to the default.  For example,
4924      * for ColumnLayout:<pre><code>
4925      * extraCls: 'x-column custom-class'
4926      * </code></pre>
4927      * </p>
4928      */
4929     /**
4930      * @cfg {Boolean} renderHidden
4931      * True to hide each contained item on render (defaults to false).
4932      */
4933
4934     /**
4935      * A reference to the {@link Ext.Component} that is active.  For example, <pre><code>
4936      * if(myPanel.layout.activeItem.id == 'item-1') { ... }
4937      * </code></pre>
4938      * <tt>activeItem</tt> only applies to layout styles that can display items one at a time
4939      * (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout}
4940      * and {@link Ext.layout.FitLayout}).  Read-only.  Related to {@link Ext.Container#activeItem}.
4941      * @type {Ext.Component}
4942      * @property activeItem
4943      */
4944
4945     // private
4946     monitorResize:false,
4947     // private
4948     activeItem : null,
4949
4950     constructor : function(config){
4951         this.id = Ext.id(null, 'ext-layout-');
4952         Ext.apply(this, config);
4953     },
4954
4955     type: 'container',
4956
4957     /* Workaround for how IE measures autoWidth elements.  It prefers bottom-up measurements
4958       whereas other browser prefer top-down.  We will hide all target child elements before we measure and
4959       put them back to get an accurate measurement.
4960     */
4961     IEMeasureHack : function(target, viewFlag) {
4962         var tChildren = target.dom.childNodes, tLen = tChildren.length, c, d = [], e, i, ret;
4963         for (i = 0 ; i < tLen ; i++) {
4964             c = tChildren[i];
4965             e = Ext.get(c);
4966             if (e) {
4967                 d[i] = e.getStyle('display');
4968                 e.setStyle({display: 'none'});
4969             }
4970         }
4971         ret = target ? target.getViewSize(viewFlag) : {};
4972         for (i = 0 ; i < tLen ; i++) {
4973             c = tChildren[i];
4974             e = Ext.get(c);
4975             if (e) {
4976                 e.setStyle({display: d[i]});
4977             }
4978         }
4979         return ret;
4980     },
4981
4982     // Placeholder for the derived layouts
4983     getLayoutTargetSize : Ext.EmptyFn,
4984
4985     // private
4986     layout : function(){
4987         var ct = this.container, target = ct.getLayoutTarget();
4988         if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
4989             target.addClass(this.targetCls);
4990         }
4991         this.onLayout(ct, target);
4992         ct.fireEvent('afterlayout', ct, this);
4993     },
4994
4995     // private
4996     onLayout : function(ct, target){
4997         this.renderAll(ct, target);
4998     },
4999
5000     // private
5001     isValidParent : function(c, target){
5002         return target && c.getPositionEl().dom.parentNode == (target.dom || target);
5003     },
5004
5005     // private
5006     renderAll : function(ct, target){
5007         var items = ct.items.items, i, c, len = items.length;
5008         for(i = 0; i < len; i++) {
5009             c = items[i];
5010             if(c && (!c.rendered || !this.isValidParent(c, target))){
5011                 this.renderItem(c, i, target);
5012             }
5013         }
5014     },
5015
5016     /**
5017      * @private
5018      * Renders the given Component into the target Element. If the Component is already rendered,
5019      * it is moved to the provided target instead.
5020      * @param {Ext.Component} c The Component to render
5021      * @param {Number} position The position within the target to render the item to
5022      * @param {Ext.Element} target The target Element
5023      */
5024     renderItem : function(c, position, target){
5025         if (c) {
5026             if (!c.rendered) {
5027                 c.render(target, position);
5028                 this.configureItem(c);
5029             } else if (!this.isValidParent(c, target)) {
5030                 if (Ext.isNumber(position)) {
5031                     position = target.dom.childNodes[position];
5032                 }
5033                 
5034                 target.dom.insertBefore(c.getPositionEl().dom, position || null);
5035                 c.container = target;
5036                 this.configureItem(c);
5037             }
5038         }
5039     },
5040
5041     // private.
5042     // Get all rendered items to lay out.
5043     getRenderedItems: function(ct){
5044         var t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = [];
5045         for (i = 0; i < len; i++) {
5046             if((c = cti[i]).rendered && this.isValidParent(c, t) && c.shouldLayout !== false){
5047                 items.push(c);
5048             }
5049         };
5050         return items;
5051     },
5052
5053     /**
5054      * @private
5055      * Applies extraCls and hides the item if renderHidden is true
5056      */
5057     configureItem: function(c){
5058         if (this.extraCls) {
5059             var t = c.getPositionEl ? c.getPositionEl() : c;
5060             t.addClass(this.extraCls);
5061         }
5062         
5063         // If we are forcing a layout, do so *before* we hide so elements have height/width
5064         if (c.doLayout && this.forceLayout) {
5065             c.doLayout();
5066         }
5067         if (this.renderHidden && c != this.activeItem) {
5068             c.hide();
5069         }
5070     },
5071
5072     onRemove: function(c){
5073         if(this.activeItem == c){
5074             delete this.activeItem;
5075         }
5076         if(c.rendered && this.extraCls){
5077             var t = c.getPositionEl ? c.getPositionEl() : c;
5078             t.removeClass(this.extraCls);
5079         }
5080     },
5081
5082     afterRemove: function(c){
5083         if(c.removeRestore){
5084             c.removeMode = 'container';
5085             delete c.removeRestore;
5086         }
5087     },
5088
5089     // private
5090     onResize: function(){
5091         var ct = this.container,
5092             b;
5093         if(ct.collapsed){
5094             return;
5095         }
5096         if(b = ct.bufferResize && ct.shouldBufferLayout()){
5097             if(!this.resizeTask){
5098                 this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
5099                 this.resizeBuffer = Ext.isNumber(b) ? b : 50;
5100             }
5101             ct.layoutPending = true;
5102             this.resizeTask.delay(this.resizeBuffer);
5103         }else{
5104             this.runLayout();
5105         }
5106     },
5107
5108     runLayout: function(){
5109         var ct = this.container;
5110         this.layout();
5111         ct.onLayout();
5112         delete ct.layoutPending;
5113     },
5114
5115     // private
5116     setContainer : function(ct){
5117         /**
5118          * This monitorResize flag will be renamed soon as to avoid confusion
5119          * with the Container version which hooks onWindowResize to doLayout
5120          *
5121          * monitorResize flag in this context attaches the resize event between
5122          * a container and it's layout
5123          */
5124         if(this.monitorResize && ct != this.container){
5125             var old = this.container;
5126             if(old){
5127                 old.un(old.resizeEvent, this.onResize, this);
5128             }
5129             if(ct){
5130                 ct.on(ct.resizeEvent, this.onResize, this);
5131             }
5132         }
5133         this.container = ct;
5134     },
5135
5136     /**
5137      * Parses a number or string representing margin sizes into an object. Supports CSS-style margin declarations
5138      * (e.g. 10, "10", "10 10", "10 10 10" and "10 10 10 10" are all valid options and would return the same result)
5139      * @param {Number|String} v The encoded margins
5140      * @return {Object} An object with margin sizes for top, right, bottom and left
5141      */
5142     parseMargins : function(v){
5143         if (Ext.isNumber(v)) {
5144             v = v.toString();
5145         }
5146         var ms  = v.split(' '),
5147             len = ms.length;
5148             
5149         if (len == 1) {
5150             ms[1] = ms[2] = ms[3] = ms[0];
5151         } else if(len == 2) {
5152             ms[2] = ms[0];
5153             ms[3] = ms[1];
5154         } else if(len == 3) {
5155             ms[3] = ms[1];
5156         }
5157         
5158         return {
5159             top   :parseInt(ms[0], 10) || 0,
5160             right :parseInt(ms[1], 10) || 0,
5161             bottom:parseInt(ms[2], 10) || 0,
5162             left  :parseInt(ms[3], 10) || 0
5163         };
5164     },
5165
5166     /**
5167      * The {@link Ext.Template Ext.Template} used by Field rendering layout classes (such as
5168      * {@link Ext.layout.FormLayout}) to create the DOM structure of a fully wrapped,
5169      * labeled and styled form Field. A default Template is supplied, but this may be
5170      * overriden to create custom field structures. The template processes values returned from
5171      * {@link Ext.layout.FormLayout#getTemplateArgs}.
5172      * @property fieldTpl
5173      * @type Ext.Template
5174      */
5175     fieldTpl: (function() {
5176         var t = new Ext.Template(
5177             '<div class="x-form-item {itemCls}" tabIndex="-1">',
5178                 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
5179                 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
5180                 '</div><div class="{clearCls}"></div>',
5181             '</div>'
5182         );
5183         t.disableFormats = true;
5184         return t.compile();
5185     })(),
5186
5187     /*
5188      * Destroys this layout. This is a template method that is empty by default, but should be implemented
5189      * by subclasses that require explicit destruction to purge event handlers or remove DOM nodes.
5190      * @protected
5191      */
5192     destroy : function(){
5193         // Stop any buffered layout tasks
5194         if(this.resizeTask && this.resizeTask.cancel){
5195             this.resizeTask.cancel();
5196         }
5197         if(!Ext.isEmpty(this.targetCls)){
5198             var target = this.container.getLayoutTarget();
5199             if(target){
5200                 target.removeClass(this.targetCls);
5201             }
5202         }
5203     }
5204 });/**
5205  * @class Ext.layout.AutoLayout
5206  * <p>The AutoLayout is the default layout manager delegated by {@link Ext.Container} to
5207  * render any child Components when no <tt>{@link Ext.Container#layout layout}</tt> is configured into
5208  * a {@link Ext.Container Container}.</tt>.  AutoLayout provides only a passthrough of any layout calls
5209  * to any child containers.</p>
5210  */
5211 Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
5212     type: 'auto',
5213
5214     monitorResize: true,
5215
5216     onLayout : function(ct, target){
5217         Ext.layout.AutoLayout.superclass.onLayout.call(this, ct, target);
5218         var cs = this.getRenderedItems(ct), len = cs.length, i, c;
5219         for(i = 0; i < len; i++){
5220             c = cs[i];
5221             if (c.doLayout){
5222                 // Shallow layout children
5223                 c.doLayout(true);
5224             }
5225         }
5226     }
5227 });
5228
5229 Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
5230 /**
5231  * @class Ext.layout.FitLayout
5232  * @extends Ext.layout.ContainerLayout
5233  * <p>This is a base class for layouts that contain <b>a single item</b> that automatically expands to fill the layout's
5234  * container.  This class is intended to be extended or created via the <tt>layout:'fit'</tt> {@link Ext.Container#layout}
5235  * config, and should generally not need to be created directly via the new keyword.</p>
5236  * <p>FitLayout does not have any direct config options (other than inherited ones).  To fit a panel to a container
5237  * using FitLayout, simply set layout:'fit' on the container and add a single panel to it.  If the container has
5238  * multiple panels, only the first one will be displayed.  Example usage:</p>
5239  * <pre><code>
5240 var p = new Ext.Panel({
5241     title: 'Fit Layout',
5242     layout:'fit',
5243     items: {
5244         title: 'Inner Panel',
5245         html: '&lt;p&gt;This is the inner panel content&lt;/p&gt;',
5246         border: false
5247     }
5248 });
5249 </code></pre>
5250  */
5251 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
5252     // private
5253     monitorResize:true,
5254
5255     type: 'fit',
5256
5257     getLayoutTargetSize : function() {
5258         var target = this.container.getLayoutTarget();
5259         if (!target) {
5260             return {};
5261         }
5262         // Style Sized (scrollbars not included)
5263         return target.getStyleSize();
5264     },
5265
5266     // private
5267     onLayout : function(ct, target){
5268         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
5269         if(!ct.collapsed){
5270             this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());
5271         }
5272     },
5273
5274     // private
5275     setItemSize : function(item, size){
5276         if(item && size.height > 0){ // display none?
5277             item.setSize(size);
5278         }
5279     }
5280 });
5281 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;/**
5282  * @class Ext.layout.CardLayout
5283  * @extends Ext.layout.FitLayout
5284  * <p>This layout manages multiple child Components, each fitted to the Container, where only a single child Component can be
5285  * visible at any given time.  This layout style is most commonly used for wizards, tab implementations, etc.
5286  * This class is intended to be extended or created via the layout:'card' {@link Ext.Container#layout} config,
5287  * and should generally not need to be created directly via the new keyword.</p>
5288  * <p>The CardLayout's focal method is {@link #setActiveItem}.  Since only one panel is displayed at a time,
5289  * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of
5290  * the next panel to display.  The layout itself does not provide a user interface for handling this navigation,
5291  * so that functionality must be provided by the developer.</p>
5292  * <p>In the following example, a simplistic wizard setup is demonstrated.  A button bar is added
5293  * to the footer of the containing panel to provide navigation buttons.  The buttons will be handled by a
5294  * common navigation routine -- for this example, the implementation of that routine has been ommitted since
5295  * it can be any type of custom logic.  Note that other uses of a CardLayout (like a tab control) would require a
5296  * completely different implementation.  For serious implementations, a better approach would be to extend
5297  * CardLayout to provide the custom functionality needed.  Example usage:</p>
5298  * <pre><code>
5299 var navHandler = function(direction){
5300     // This routine could contain business logic required to manage the navigation steps.
5301     // It would call setActiveItem as needed, manage navigation button state, handle any
5302     // branching logic that might be required, handle alternate actions like cancellation
5303     // or finalization, etc.  A complete wizard implementation could get pretty
5304     // sophisticated depending on the complexity required, and should probably be
5305     // done as a subclass of CardLayout in a real-world implementation.
5306 };
5307
5308 var card = new Ext.Panel({
5309     title: 'Example Wizard',
5310     layout:'card',
5311     activeItem: 0, // make sure the active item is set on the container config!
5312     bodyStyle: 'padding:15px',
5313     defaults: {
5314         // applied to each contained panel
5315         border:false
5316     },
5317     // just an example of one possible navigation scheme, using buttons
5318     bbar: [
5319         {
5320             id: 'move-prev',
5321             text: 'Back',
5322             handler: navHandler.createDelegate(this, [-1]),
5323             disabled: true
5324         },
5325         '->', // greedy spacer so that the buttons are aligned to each side
5326         {
5327             id: 'move-next',
5328             text: 'Next',
5329             handler: navHandler.createDelegate(this, [1])
5330         }
5331     ],
5332     // the panels (or "cards") within the layout
5333     items: [{
5334         id: 'card-0',
5335         html: '&lt;h1&gt;Welcome to the Wizard!&lt;/h1&gt;&lt;p&gt;Step 1 of 3&lt;/p&gt;'
5336     },{
5337         id: 'card-1',
5338         html: '&lt;p&gt;Step 2 of 3&lt;/p&gt;'
5339     },{
5340         id: 'card-2',
5341         html: '&lt;h1&gt;Congratulations!&lt;/h1&gt;&lt;p&gt;Step 3 of 3 - Complete&lt;/p&gt;'
5342     }]
5343 });
5344 </code></pre>
5345  */
5346 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
5347     /**
5348      * @cfg {Boolean} deferredRender
5349      * True to render each contained item at the time it becomes active, false to render all contained items
5350      * as soon as the layout is rendered (defaults to false).  If there is a significant amount of content or
5351      * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to
5352      * true might improve performance.
5353      */
5354     deferredRender : false,
5355
5356     /**
5357      * @cfg {Boolean} layoutOnCardChange
5358      * True to force a layout of the active item when the active card is changed. Defaults to false.
5359      */
5360     layoutOnCardChange : false,
5361
5362     /**
5363      * @cfg {Boolean} renderHidden @hide
5364      */
5365     // private
5366     renderHidden : true,
5367
5368     type: 'card',
5369
5370     /**
5371      * Sets the active (visible) item in the layout.
5372      * @param {String/Number} item The string component id or numeric index of the item to activate
5373      */
5374     setActiveItem : function(item){
5375         var ai = this.activeItem,
5376             ct = this.container;
5377         item = ct.getComponent(item);
5378
5379         // Is this a valid, different card?
5380         if(item && ai != item){
5381
5382             // Changing cards, hide the current one
5383             if(ai){
5384                 ai.hide();
5385                 if (ai.hidden !== true) {
5386                     return false;
5387                 }
5388                 ai.fireEvent('deactivate', ai);
5389             }
5390
5391             var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);
5392
5393             // Change activeItem reference
5394             this.activeItem = item;
5395
5396             // The container is about to get a recursive layout, remove any deferLayout reference
5397             // because it will trigger a redundant layout.
5398             delete item.deferLayout;
5399
5400             // Show the new component
5401             item.show();
5402
5403             this.layout();
5404
5405             if(layout){
5406                 item.doLayout();
5407             }
5408             item.fireEvent('activate', item);
5409         }
5410     },
5411
5412     // private
5413     renderAll : function(ct, target){
5414         if(this.deferredRender){
5415             this.renderItem(this.activeItem, undefined, target);
5416         }else{
5417             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
5418         }
5419     }
5420 });
5421 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;
5422 /**
5423  * @class Ext.layout.AnchorLayout
5424  * @extends Ext.layout.ContainerLayout
5425  * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.
5426  * If the container is resized, all anchored items are automatically rerendered according to their
5427  * <b><tt>{@link #anchor}</tt></b> rules.</p>
5428  * <p>This class is intended to be extended or created via the layout:'anchor' {@link Ext.Container#layout}
5429  * config, and should generally not need to be created directly via the new keyword.</p>
5430  * <p>AnchorLayout does not have any direct config options (other than inherited ones). By default,
5431  * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the
5432  * container using the AnchorLayout can supply an anchoring-specific config property of <b>anchorSize</b>.
5433  * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating
5434  * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring
5435  * logic if necessary.  For example:</p>
5436  * <pre><code>
5437 var viewport = new Ext.Viewport({
5438     layout:'anchor',
5439     anchorSize: {width:800, height:600},
5440     items:[{
5441         title:'Item 1',
5442         html:'Content 1',
5443         width:800,
5444         anchor:'right 20%'
5445     },{
5446         title:'Item 2',
5447         html:'Content 2',
5448         width:300,
5449         anchor:'50% 30%'
5450     },{
5451         title:'Item 3',
5452         html:'Content 3',
5453         width:600,
5454         anchor:'-100 50%'
5455     }]
5456 });
5457  * </code></pre>
5458  */
5459 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
5460     /**
5461      * @cfg {String} anchor
5462      * <p>This configuation option is to be applied to <b>child <tt>items</tt></b> of a container managed by
5463      * this layout (ie. configured with <tt>layout:'anchor'</tt>).</p><br/>
5464      *
5465      * <p>This value is what tells the layout how an item should be anchored to the container. <tt>items</tt>
5466      * added to an AnchorLayout accept an anchoring-specific config property of <b>anchor</b> which is a string
5467      * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').
5468      * The following types of anchor values are supported:<div class="mdetail-params"><ul>
5469      *
5470      * <li><b>Percentage</b> : Any value between 1 and 100, expressed as a percentage.<div class="sub-desc">
5471      * The first anchor is the percentage width that the item should take up within the container, and the
5472      * second is the percentage height.  For example:<pre><code>
5473 // two values specified
5474 anchor: '100% 50%' // render item complete width of the container and
5475                    // 1/2 height of the container
5476 // one value specified
5477 anchor: '100%'     // the width value; the height will default to auto
5478      * </code></pre></div></li>
5479      *
5480      * <li><b>Offsets</b> : Any positive or negative integer value.<div class="sub-desc">
5481      * This is a raw adjustment where the first anchor is the offset from the right edge of the container,
5482      * and the second is the offset from the bottom edge. For example:<pre><code>
5483 // two values specified
5484 anchor: '-50 -100' // render item the complete width of the container
5485                    // minus 50 pixels and
5486                    // the complete height minus 100 pixels.
5487 // one value specified
5488 anchor: '-50'      // anchor value is assumed to be the right offset value
5489                    // bottom offset will default to 0
5490      * </code></pre></div></li>
5491      *
5492      * <li><b>Sides</b> : Valid values are <tt>'right'</tt> (or <tt>'r'</tt>) and <tt>'bottom'</tt>
5493      * (or <tt>'b'</tt>).<div class="sub-desc">
5494      * Either the container must have a fixed size or an anchorSize config value defined at render time in
5495      * order for these to have any effect.</div></li>
5496      *
5497      * <li><b>Mixed</b> : <div class="sub-desc">
5498      * Anchor values can also be mixed as needed.  For example, to render the width offset from the container
5499      * right edge by 50 pixels and 75% of the container's height use:
5500      * <pre><code>
5501 anchor: '-50 75%'
5502      * </code></pre></div></li>
5503      *
5504      *
5505      * </ul></div>
5506      */
5507
5508     // private
5509     monitorResize : true,
5510
5511     type : 'anchor',
5512
5513     /**
5514      * @cfg {String} defaultAnchor
5515      *
5516      * default anchor for all child container items applied if no anchor or specific width is set on the child item.  Defaults to '100%'.
5517      *
5518      */
5519     defaultAnchor : '100%',
5520
5521     parseAnchorRE : /^(r|right|b|bottom)$/i,
5522
5523
5524     getLayoutTargetSize : function() {
5525         var target = this.container.getLayoutTarget(), ret = {};
5526         if (target) {
5527             ret = target.getViewSize();
5528
5529             // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
5530             // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
5531             // with getViewSize
5532             if (Ext.isIE && Ext.isStrict && ret.width == 0){
5533                 ret =  target.getStyleSize();
5534             }
5535             ret.width -= target.getPadding('lr');
5536             ret.height -= target.getPadding('tb');
5537         }
5538         return ret;
5539     },
5540
5541     // private
5542     onLayout : function(container, target) {
5543         Ext.layout.AnchorLayout.superclass.onLayout.call(this, container, target);
5544
5545         var size = this.getLayoutTargetSize(),
5546             containerWidth = size.width,
5547             containerHeight = size.height,
5548             overflow = target.getStyle('overflow'),
5549             components = this.getRenderedItems(container),
5550             len = components.length,
5551             boxes = [],
5552             box,
5553             anchorWidth,
5554             anchorHeight,
5555             component,
5556             anchorSpec,
5557             calcWidth,
5558             calcHeight,
5559             anchorsArray,
5560             totalHeight = 0,
5561             i,
5562             el;
5563
5564         if(containerWidth < 20 && containerHeight < 20){
5565             return;
5566         }
5567
5568         // find the container anchoring size
5569         if(container.anchorSize) {
5570             if(typeof container.anchorSize == 'number') {
5571                 anchorWidth = container.anchorSize;
5572             } else {
5573                 anchorWidth = container.anchorSize.width;
5574                 anchorHeight = container.anchorSize.height;
5575             }
5576         } else {
5577             anchorWidth = container.initialConfig.width;
5578             anchorHeight = container.initialConfig.height;
5579         }
5580
5581         for(i = 0; i < len; i++) {
5582             component = components[i];
5583             el = component.getPositionEl();
5584
5585             // If a child container item has no anchor and no specific width, set the child to the default anchor size
5586             if (!component.anchor && component.items && !Ext.isNumber(component.width) && !(Ext.isIE6 && Ext.isStrict)){
5587                 component.anchor = this.defaultAnchor;
5588             }
5589
5590             if(component.anchor) {
5591                 anchorSpec = component.anchorSpec;
5592                 // cache all anchor values
5593                 if(!anchorSpec){
5594                     anchorsArray = component.anchor.split(' ');
5595                     component.anchorSpec = anchorSpec = {
5596                         right: this.parseAnchor(anchorsArray[0], component.initialConfig.width, anchorWidth),
5597                         bottom: this.parseAnchor(anchorsArray[1], component.initialConfig.height, anchorHeight)
5598                     };
5599                 }
5600                 calcWidth = anchorSpec.right ? this.adjustWidthAnchor(anchorSpec.right(containerWidth) - el.getMargins('lr'), component) : undefined;
5601                 calcHeight = anchorSpec.bottom ? this.adjustHeightAnchor(anchorSpec.bottom(containerHeight) - el.getMargins('tb'), component) : undefined;
5602
5603                 if(calcWidth || calcHeight) {
5604                     boxes.push({
5605                         component: component,
5606                         width: calcWidth || undefined,
5607                         height: calcHeight || undefined
5608                     });
5609                 }
5610             }
5611         }
5612         for (i = 0, len = boxes.length; i < len; i++) {
5613             box = boxes[i];
5614             box.component.setSize(box.width, box.height);
5615         }
5616
5617         if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
5618             var newTargetSize = this.getLayoutTargetSize();
5619             if (newTargetSize.width != size.width || newTargetSize.height != size.height){
5620                 this.adjustmentPass = true;
5621                 this.onLayout(container, target);
5622             }
5623         }
5624
5625         delete this.adjustmentPass;
5626     },
5627
5628     // private
5629     parseAnchor : function(a, start, cstart) {
5630         if (a && a != 'none') {
5631             var last;
5632             // standard anchor
5633             if (this.parseAnchorRE.test(a)) {
5634                 var diff = cstart - start;
5635                 return function(v){
5636                     if(v !== last){
5637                         last = v;
5638                         return v - diff;
5639                     }
5640                 };
5641             // percentage
5642             } else if(a.indexOf('%') != -1) {
5643                 var ratio = parseFloat(a.replace('%', ''))*.01;
5644                 return function(v){
5645                     if(v !== last){
5646                         last = v;
5647                         return Math.floor(v*ratio);
5648                     }
5649                 };
5650             // simple offset adjustment
5651             } else {
5652                 a = parseInt(a, 10);
5653                 if (!isNaN(a)) {
5654                     return function(v) {
5655                         if (v !== last) {
5656                             last = v;
5657                             return v + a;
5658                         }
5659                     };
5660                 }
5661             }
5662         }
5663         return false;
5664     },
5665
5666     // private
5667     adjustWidthAnchor : function(value, comp){
5668         return value;
5669     },
5670
5671     // private
5672     adjustHeightAnchor : function(value, comp){
5673         return value;
5674     }
5675
5676     /**
5677      * @property activeItem
5678      * @hide
5679      */
5680 });
5681 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
5682 /**
5683  * @class Ext.layout.ColumnLayout
5684  * @extends Ext.layout.ContainerLayout
5685  * <p>This is the layout style of choice for creating structural layouts in a multi-column format where the width of
5686  * each column can be specified as a percentage or fixed width, but the height is allowed to vary based on the content.
5687  * This class is intended to be extended or created via the layout:'column' {@link Ext.Container#layout} config,
5688  * and should generally not need to be created directly via the new keyword.</p>
5689  * <p>ColumnLayout does not have any direct config options (other than inherited ones), but it does support a
5690  * specific config property of <b><tt>columnWidth</tt></b> that can be included in the config of any panel added to it.  The
5691  * layout will use the columnWidth (if present) or width of each panel during layout to determine how to size each panel.
5692  * If width or columnWidth is not specified for a given panel, its width will default to the panel's width (or auto).</p>
5693  * <p>The width property is always evaluated as pixels, and must be a number greater than or equal to 1.
5694  * The columnWidth property is always evaluated as a percentage, and must be a decimal value greater than 0 and
5695  * less than 1 (e.g., .25).</p>
5696  * <p>The basic rules for specifying column widths are pretty simple.  The logic makes two passes through the
5697  * set of contained panels.  During the first layout pass, all panels that either have a fixed width or none
5698  * specified (auto) are skipped, but their widths are subtracted from the overall container width.  During the second
5699  * pass, all panels with columnWidths are assigned pixel widths in proportion to their percentages based on
5700  * the total <b>remaining</b> container width.  In other words, percentage width panels are designed to fill the space
5701  * left over by all the fixed-width and/or auto-width panels.  Because of this, while you can specify any number of columns
5702  * with different percentages, the columnWidths must always add up to 1 (or 100%) when added together, otherwise your
5703  * layout may not render as expected.  Example usage:</p>
5704  * <pre><code>
5705 // All columns are percentages -- they must add up to 1
5706 var p = new Ext.Panel({
5707     title: 'Column Layout - Percentage Only',
5708     layout:'column',
5709     items: [{
5710         title: 'Column 1',
5711         columnWidth: .25
5712     },{
5713         title: 'Column 2',
5714         columnWidth: .6
5715     },{
5716         title: 'Column 3',
5717         columnWidth: .15
5718     }]
5719 });
5720
5721 // Mix of width and columnWidth -- all columnWidth values must add up
5722 // to 1. The first column will take up exactly 120px, and the last two
5723 // columns will fill the remaining container width.
5724 var p = new Ext.Panel({
5725     title: 'Column Layout - Mixed',
5726     layout:'column',
5727     items: [{
5728         title: 'Column 1',
5729         width: 120
5730     },{
5731         title: 'Column 2',
5732         columnWidth: .8
5733     },{
5734         title: 'Column 3',
5735         columnWidth: .2
5736     }]
5737 });
5738 </code></pre>
5739  */
5740 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
5741     // private
5742     monitorResize:true,
5743
5744     type: 'column',
5745
5746     extraCls: 'x-column',
5747
5748     scrollOffset : 0,
5749
5750     // private
5751
5752     targetCls: 'x-column-layout-ct',
5753
5754     isValidParent : function(c, target){
5755         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
5756     },
5757
5758     getLayoutTargetSize : function() {
5759         var target = this.container.getLayoutTarget(), ret;
5760         if (target) {
5761             ret = target.getViewSize();
5762
5763             // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
5764             // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
5765             // with getViewSize
5766             if (Ext.isIE && Ext.isStrict && ret.width == 0){
5767                 ret =  target.getStyleSize();
5768             }
5769
5770             ret.width -= target.getPadding('lr');
5771             ret.height -= target.getPadding('tb');
5772         }
5773         return ret;
5774     },
5775
5776     renderAll : function(ct, target) {
5777         if(!this.innerCt){
5778             // the innerCt prevents wrapping and shuffling while
5779             // the container is resizing
5780             this.innerCt = target.createChild({cls:'x-column-inner'});
5781             this.innerCt.createChild({cls:'x-clear'});
5782         }
5783         Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);
5784     },
5785
5786     // private
5787     onLayout : function(ct, target){
5788         var cs = ct.items.items,
5789             len = cs.length,
5790             c,
5791             i,
5792             m,
5793             margins = [];
5794
5795         this.renderAll(ct, target);
5796
5797         var size = this.getLayoutTargetSize();
5798
5799         if(size.width < 1 && size.height < 1){ // display none?
5800             return;
5801         }
5802
5803         var w = size.width - this.scrollOffset,
5804             h = size.height,
5805             pw = w;
5806
5807         this.innerCt.setWidth(w);
5808
5809         // some columns can be percentages while others are fixed
5810         // so we need to make 2 passes
5811
5812         for(i = 0; i < len; i++){
5813             c = cs[i];
5814             m = c.getPositionEl().getMargins('lr');
5815             margins[i] = m;
5816             if(!c.columnWidth){
5817                 pw -= (c.getWidth() + m);
5818             }
5819         }
5820
5821         pw = pw < 0 ? 0 : pw;
5822
5823         for(i = 0; i < len; i++){
5824             c = cs[i];
5825             m = margins[i];
5826             if(c.columnWidth){
5827                 c.setSize(Math.floor(c.columnWidth * pw) - m);
5828             }
5829         }
5830
5831         // Browsers differ as to when they account for scrollbars.  We need to re-measure to see if the scrollbar
5832         // spaces were accounted for properly.  If not, re-layout.
5833         if (Ext.isIE) {
5834             if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
5835                 var ts = this.getLayoutTargetSize();
5836                 if (ts.width != size.width){
5837                     this.adjustmentPass = true;
5838                     this.onLayout(ct, target);
5839                 }
5840             }
5841         }
5842         delete this.adjustmentPass;
5843     }
5844
5845     /**
5846      * @property activeItem
5847      * @hide
5848      */
5849 });
5850
5851 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;
5852 /**
5853  * @class Ext.layout.BorderLayout
5854  * @extends Ext.layout.ContainerLayout
5855  * <p>This is a multi-pane, application-oriented UI layout style that supports multiple
5856  * nested panels, automatic {@link Ext.layout.BorderLayout.Region#split split} bars between
5857  * {@link Ext.layout.BorderLayout.Region#BorderLayout.Region regions} and built-in
5858  * {@link Ext.layout.BorderLayout.Region#collapsible expanding and collapsing} of regions.</p>
5859  * <p>This class is intended to be extended or created via the <tt>layout:'border'</tt>
5860  * {@link Ext.Container#layout} config, and should generally not need to be created directly
5861  * via the new keyword.</p>
5862  * <p>BorderLayout does not have any direct config options (other than inherited ones).
5863  * All configuration options available for customizing the BorderLayout are at the
5864  * {@link Ext.layout.BorderLayout.Region} and {@link Ext.layout.BorderLayout.SplitRegion}
5865  * levels.</p>
5866  * <p>Example usage:</p>
5867  * <pre><code>
5868 var myBorderPanel = new Ext.Panel({
5869     {@link Ext.Component#renderTo renderTo}: document.body,
5870     {@link Ext.BoxComponent#width width}: 700,
5871     {@link Ext.BoxComponent#height height}: 500,
5872     {@link Ext.Panel#title title}: 'Border Layout',
5873     {@link Ext.Container#layout layout}: 'border',
5874     {@link Ext.Container#items items}: [{
5875         {@link Ext.Panel#title title}: 'South Region is resizable',
5876         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south',     // position for region
5877         {@link Ext.BoxComponent#height height}: 100,
5878         {@link Ext.layout.BorderLayout.Region#split split}: true,         // enable resizing
5879         {@link Ext.SplitBar#minSize minSize}: 75,         // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50}
5880         {@link Ext.SplitBar#maxSize maxSize}: 150,
5881         {@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5'
5882     },{
5883         // xtype: 'panel' implied by default
5884         {@link Ext.Panel#title title}: 'West Region is collapsible',
5885         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}:'west',
5886         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 0 0 5',
5887         {@link Ext.BoxComponent#width width}: 200,
5888         {@link Ext.layout.BorderLayout.Region#collapsible collapsible}: true,   // make collapsible
5889         {@link Ext.layout.BorderLayout.Region#cmargins cmargins}: '5 5 0 5', // adjust top margin when collapsed
5890         {@link Ext.Component#id id}: 'west-region-container',
5891         {@link Ext.Container#layout layout}: 'fit',
5892         {@link Ext.Panel#unstyled unstyled}: true
5893     },{
5894         {@link Ext.Panel#title title}: 'Center Region',
5895         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'center',     // center region is required, no width/height specified
5896         {@link Ext.Component#xtype xtype}: 'container',
5897         {@link Ext.Container#layout layout}: 'fit',
5898         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 5 0 0'
5899     }]
5900 });
5901 </code></pre>
5902  * <p><b><u>Notes</u></b>:</p><div class="mdetail-params"><ul>
5903  * <li>Any container using the BorderLayout <b>must</b> have a child item with <tt>region:'center'</tt>.
5904  * The child item in the center region will always be resized to fill the remaining space not used by
5905  * the other regions in the layout.</li>
5906  * <li>Any child items with a region of <tt>west</tt> or <tt>east</tt> must have <tt>width</tt> defined
5907  * (an integer representing the number of pixels that the region should take up).</li>
5908  * <li>Any child items with a region of <tt>north</tt> or <tt>south</tt> must have <tt>height</tt> defined.</li>
5909  * <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
5910  * Components within a BorderLayout, have them wrapped by an additional Container which is directly
5911  * managed by the BorderLayout.  If the region is to be collapsible, the Container used directly
5912  * by the BorderLayout manager should be a Panel.  In the following example a Container (an Ext.Panel)
5913  * is added to the west region:
5914  * <div style="margin-left:16px"><pre><code>
5915 wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container');
5916 wrc.{@link Ext.Panel#removeAll removeAll}();
5917 wrc.{@link Ext.Container#add add}({
5918     title: 'Added Panel',
5919     html: 'Some content'
5920 });
5921 wrc.{@link Ext.Container#doLayout doLayout}();
5922  * </code></pre></div>
5923  * </li>
5924  * <li> To reference a {@link Ext.layout.BorderLayout.Region Region}:
5925  * <div style="margin-left:16px"><pre><code>
5926 wr = myBorderPanel.layout.west;
5927  * </code></pre></div>
5928  * </li>
5929  * </ul></div>
5930  */
5931 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
5932     // private
5933     monitorResize:true,
5934     // private
5935     rendered : false,
5936
5937     type: 'border',
5938
5939     targetCls: 'x-border-layout-ct',
5940
5941     getLayoutTargetSize : function() {
5942         var target = this.container.getLayoutTarget();
5943         return target ? target.getViewSize() : {};
5944     },
5945
5946     // private
5947     onLayout : function(ct, target){
5948         var collapsed, i, c, pos, items = ct.items.items, len = items.length;
5949         if(!this.rendered){
5950             collapsed = [];
5951             for(i = 0; i < len; i++) {
5952                 c = items[i];
5953                 pos = c.region;
5954                 if(c.collapsed){
5955                     collapsed.push(c);
5956                 }
5957                 c.collapsed = false;
5958                 if(!c.rendered){
5959                     c.render(target, i);
5960                     c.getPositionEl().addClass('x-border-panel');
5961                 }
5962                 this[pos] = pos != 'center' && c.split ?
5963                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
5964                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
5965                 this[pos].render(target, c);
5966             }
5967             this.rendered = true;
5968         }
5969
5970         var size = this.getLayoutTargetSize();
5971         if(size.width < 20 || size.height < 20){ // display none?
5972             if(collapsed){
5973                 this.restoreCollapsed = collapsed;
5974             }
5975             return;
5976         }else if(this.restoreCollapsed){
5977             collapsed = this.restoreCollapsed;
5978             delete this.restoreCollapsed;
5979         }
5980
5981         var w = size.width, h = size.height,
5982             centerW = w, centerH = h, centerY = 0, centerX = 0,
5983             n = this.north, s = this.south, west = this.west, e = this.east, c = this.center,
5984             b, m, totalWidth, totalHeight;
5985         if(!c && Ext.layout.BorderLayout.WARN !== false){
5986             throw 'No center region defined in BorderLayout ' + ct.id;
5987         }
5988
5989         if(n && n.isVisible()){
5990             b = n.getSize();
5991             m = n.getMargins();
5992             b.width = w - (m.left+m.right);
5993             b.x = m.left;
5994             b.y = m.top;
5995             centerY = b.height + b.y + m.bottom;
5996             centerH -= centerY;
5997             n.applyLayout(b);
5998         }
5999         if(s && s.isVisible()){
6000             b = s.getSize();
6001             m = s.getMargins();
6002             b.width = w - (m.left+m.right);
6003             b.x = m.left;
6004             totalHeight = (b.height + m.top + m.bottom);
6005             b.y = h - totalHeight + m.top;
6006             centerH -= totalHeight;
6007             s.applyLayout(b);
6008         }
6009         if(west && west.isVisible()){
6010             b = west.getSize();
6011             m = west.getMargins();
6012             b.height = centerH - (m.top+m.bottom);
6013             b.x = m.left;
6014             b.y = centerY + m.top;
6015             totalWidth = (b.width + m.left + m.right);
6016             centerX += totalWidth;
6017             centerW -= totalWidth;
6018             west.applyLayout(b);
6019         }
6020         if(e && e.isVisible()){
6021             b = e.getSize();
6022             m = e.getMargins();
6023             b.height = centerH - (m.top+m.bottom);
6024             totalWidth = (b.width + m.left + m.right);
6025             b.x = w - totalWidth + m.left;
6026             b.y = centerY + m.top;
6027             centerW -= totalWidth;
6028             e.applyLayout(b);
6029         }
6030         if(c){
6031             m = c.getMargins();
6032             var centerBox = {
6033                 x: centerX + m.left,
6034                 y: centerY + m.top,
6035                 width: centerW - (m.left+m.right),
6036                 height: centerH - (m.top+m.bottom)
6037             };
6038             c.applyLayout(centerBox);
6039         }
6040         if(collapsed){
6041             for(i = 0, len = collapsed.length; i < len; i++){
6042                 collapsed[i].collapse(false);
6043             }
6044         }
6045         if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue
6046             target.repaint();
6047         }
6048         // Putting a border layout into an overflowed container is NOT correct and will make a second layout pass necessary.
6049         if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
6050             var ts = this.getLayoutTargetSize();
6051             if (ts.width != size.width || ts.height != size.height){
6052                 this.adjustmentPass = true;
6053                 this.onLayout(ct, target);
6054             }
6055         }
6056         delete this.adjustmentPass;
6057     },
6058
6059     destroy: function() {
6060         var r = ['north', 'south', 'east', 'west'], i, region;
6061         for (i = 0; i < r.length; i++) {
6062             region = this[r[i]];
6063             if(region){
6064                 if(region.destroy){
6065                     region.destroy();
6066                 }else if (region.split){
6067                     region.split.destroy(true);
6068                 }
6069             }
6070         }
6071         Ext.layout.BorderLayout.superclass.destroy.call(this);
6072     }
6073
6074     /**
6075      * @property activeItem
6076      * @hide
6077      */
6078 });
6079
6080 /**
6081  * @class Ext.layout.BorderLayout.Region
6082  * <p>This is a region of a {@link Ext.layout.BorderLayout BorderLayout} that acts as a subcontainer
6083  * within the layout.  Each region has its own {@link Ext.layout.ContainerLayout layout} that is
6084  * independent of other regions and the containing BorderLayout, and can be any of the
6085  * {@link Ext.layout.ContainerLayout valid Ext layout types}.</p>
6086  * <p>Region size is managed automatically and cannot be changed by the user -- for
6087  * {@link #split resizable regions}, see {@link Ext.layout.BorderLayout.SplitRegion}.</p>
6088  * @constructor
6089  * Create a new Region.
6090  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
6091  * @param {Object} config The configuration options
6092  * @param {String} position The region position.  Valid values are: <tt>north</tt>, <tt>south</tt>,
6093  * <tt>east</tt>, <tt>west</tt> and <tt>center</tt>.  Every {@link Ext.layout.BorderLayout BorderLayout}
6094  * <b>must have a center region</b> for the primary content -- all other regions are optional.
6095  */
6096 Ext.layout.BorderLayout.Region = function(layout, config, pos){
6097     Ext.apply(this, config);
6098     this.layout = layout;
6099     this.position = pos;
6100     this.state = {};
6101     if(typeof this.margins == 'string'){
6102         this.margins = this.layout.parseMargins(this.margins);
6103     }
6104     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
6105     if(this.collapsible){
6106         if(typeof this.cmargins == 'string'){
6107             this.cmargins = this.layout.parseMargins(this.cmargins);
6108         }
6109         if(this.collapseMode == 'mini' && !this.cmargins){
6110             this.cmargins = {left:0,top:0,right:0,bottom:0};
6111         }else{
6112             this.cmargins = Ext.applyIf(this.cmargins || {},
6113                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
6114         }
6115     }
6116 };
6117
6118 Ext.layout.BorderLayout.Region.prototype = {
6119     /**
6120      * @cfg {Boolean} animFloat
6121      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
6122      * panel that will close again once the user mouses out of that panel (or clicks out if
6123      * <tt>{@link #autoHide} = false</tt>).  Setting <tt>{@link #animFloat} = false</tt> will
6124      * prevent the open and close of these floated panels from being animated (defaults to <tt>true</tt>).
6125      */
6126     /**
6127      * @cfg {Boolean} autoHide
6128      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
6129      * panel.  If <tt>autoHide = true</tt>, the panel will automatically hide after the user mouses
6130      * out of the panel.  If <tt>autoHide = false</tt>, the panel will continue to display until the
6131      * user clicks outside of the panel (defaults to <tt>true</tt>).
6132      */
6133     /**
6134      * @cfg {String} collapseMode
6135      * <tt>collapseMode</tt> supports two configuration values:<div class="mdetail-params"><ul>
6136      * <li><b><tt>undefined</tt></b> (default)<div class="sub-desc">By default, {@link #collapsible}
6137      * regions are collapsed by clicking the expand/collapse tool button that renders into the region's
6138      * title bar.</div></li>
6139      * <li><b><tt>'mini'</tt></b><div class="sub-desc">Optionally, when <tt>collapseMode</tt> is set to
6140      * <tt>'mini'</tt> the region's split bar will also display a small collapse button in the center of
6141      * the bar. In <tt>'mini'</tt> mode the region will collapse to a thinner bar than in normal mode.
6142      * </div></li>
6143      * </ul></div></p>
6144      * <p><b>Note</b>: if a collapsible region does not have a title bar, then set <tt>collapseMode =
6145      * 'mini'</tt> and <tt>{@link #split} = true</tt> in order for the region to be {@link #collapsible}
6146      * by the user as the expand/collapse tool button (that would go in the title bar) will not be rendered.</p>
6147      * <p>See also <tt>{@link #cmargins}</tt>.</p>
6148      */
6149     /**
6150      * @cfg {Object} margins
6151      * An object containing margins to apply to the region when in the expanded state in the
6152      * format:<pre><code>
6153 {
6154     top: (top margin),
6155     right: (right margin),
6156     bottom: (bottom margin),
6157     left: (left margin)
6158 }</code></pre>
6159      * <p>May also be a string containing space-separated, numeric margin values. The order of the
6160      * sides associated with each value matches the way CSS processes margin values:</p>
6161      * <p><div class="mdetail-params"><ul>
6162      * <li>If there is only one value, it applies to all sides.</li>
6163      * <li>If there are two values, the top and bottom borders are set to the first value and the
6164      * right and left are set to the second.</li>
6165      * <li>If there are three values, the top is set to the first value, the left and right are set
6166      * to the second, and the bottom is set to the third.</li>
6167      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
6168      * </ul></div></p>
6169      * <p>Defaults to:</p><pre><code>
6170      * {top:0, right:0, bottom:0, left:0}
6171      * </code></pre>
6172      */
6173     /**
6174      * @cfg {Object} cmargins
6175      * An object containing margins to apply to the region when in the collapsed state in the
6176      * format:<pre><code>
6177 {
6178     top: (top margin),
6179     right: (right margin),
6180     bottom: (bottom margin),
6181     left: (left margin)
6182 }</code></pre>
6183      * <p>May also be a string containing space-separated, numeric margin values. The order of the
6184      * sides associated with each value matches the way CSS processes margin values.</p>
6185      * <p><ul>
6186      * <li>If there is only one value, it applies to all sides.</li>
6187      * <li>If there are two values, the top and bottom borders are set to the first value and the
6188      * right and left are set to the second.</li>
6189      * <li>If there are three values, the top is set to the first value, the left and right are set
6190      * to the second, and the bottom is set to the third.</li>
6191      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
6192      * </ul></p>
6193      */
6194     /**
6195      * @cfg {Boolean} collapsible
6196      * <p><tt>true</tt> to allow the user to collapse this region (defaults to <tt>false</tt>).  If
6197      * <tt>true</tt>, an expand/collapse tool button will automatically be rendered into the title
6198      * bar of the region, otherwise the button will not be shown.</p>
6199      * <p><b>Note</b>: that a title bar is required to display the collapse/expand toggle button -- if
6200      * no <tt>title</tt> is specified for the region's panel, the region will only be collapsible if
6201      * <tt>{@link #collapseMode} = 'mini'</tt> and <tt>{@link #split} = true</tt>.
6202      */
6203     collapsible : false,
6204     /**
6205      * @cfg {Boolean} split
6206      * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and
6207      * display a 5px wide {@link Ext.SplitBar} between this region and its neighbor, allowing the user to
6208      * resize the regions dynamically.  Defaults to <tt>false</tt> creating a
6209      * {@link Ext.layout.BorderLayout.Region Region}.</p><br>
6210      * <p><b>Notes</b>:</p><div class="mdetail-params"><ul>
6211      * <li>this configuration option is ignored if <tt>region='center'</tt></li>
6212      * <li>when <tt>split == true</tt>, it is common to specify a
6213      * <tt>{@link Ext.SplitBar#minSize minSize}</tt> and <tt>{@link Ext.SplitBar#maxSize maxSize}</tt>
6214      * for the {@link Ext.BoxComponent BoxComponent} representing the region. These are not native
6215      * configs of {@link Ext.BoxComponent BoxComponent}, and are used only by this class.</li>
6216      * <li>if <tt>{@link #collapseMode} = 'mini'</tt> requires <tt>split = true</tt> to reserve space
6217      * for the collapse tool</tt></li>
6218      * </ul></div>
6219      */
6220     split:false,
6221     /**
6222      * @cfg {Boolean} floatable
6223      * <tt>true</tt> to allow clicking a collapsed region's bar to display the region's panel floated
6224      * above the layout, <tt>false</tt> to force the user to fully expand a collapsed region by
6225      * clicking the expand button to see it again (defaults to <tt>true</tt>).
6226      */
6227     floatable: true,
6228     /**
6229      * @cfg {Number} minWidth
6230      * <p>The minimum allowable width in pixels for this region (defaults to <tt>50</tt>).
6231      * <tt>maxWidth</tt> may also be specified.</p><br>
6232      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
6233      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
6234      * <tt>minWidth</tt> / <tt>maxWidth</tt>.</p>
6235      */
6236     minWidth:50,
6237     /**
6238      * @cfg {Number} minHeight
6239      * The minimum allowable height in pixels for this region (defaults to <tt>50</tt>)
6240      * <tt>maxHeight</tt> may also be specified.</p><br>
6241      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
6242      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
6243      * <tt>minHeight</tt> / <tt>maxHeight</tt>.</p>
6244      */
6245     minHeight:50,
6246
6247     // private
6248     defaultMargins : {left:0,top:0,right:0,bottom:0},
6249     // private
6250     defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
6251     // private
6252     defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
6253     floatingZIndex: 100,
6254
6255     /**
6256      * True if this region is collapsed. Read-only.
6257      * @type Boolean
6258      * @property
6259      */
6260     isCollapsed : false,
6261
6262     /**
6263      * This region's panel.  Read-only.
6264      * @type Ext.Panel
6265      * @property panel
6266      */
6267     /**
6268      * This region's layout.  Read-only.
6269      * @type Layout
6270      * @property layout
6271      */
6272     /**
6273      * This region's layout position (north, south, east, west or center).  Read-only.
6274      * @type String
6275      * @property position
6276      */
6277
6278     // private
6279     render : function(ct, p){
6280         this.panel = p;
6281         p.el.enableDisplayMode();
6282         this.targetEl = ct;
6283         this.el = p.el;
6284
6285         var gs = p.getState, ps = this.position;
6286         p.getState = function(){
6287             return Ext.apply(gs.call(p) || {}, this.state);
6288         }.createDelegate(this);
6289
6290         if(ps != 'center'){
6291             p.allowQueuedExpand = false;
6292             p.on({
6293                 beforecollapse: this.beforeCollapse,
6294                 collapse: this.onCollapse,
6295                 beforeexpand: this.beforeExpand,
6296                 expand: this.onExpand,
6297                 hide: this.onHide,
6298                 show: this.onShow,
6299                 scope: this
6300             });
6301             if(this.collapsible || this.floatable){
6302                 p.collapseEl = 'el';
6303                 p.slideAnchor = this.getSlideAnchor();
6304             }
6305             if(p.tools && p.tools.toggle){
6306                 p.tools.toggle.addClass('x-tool-collapse-'+ps);
6307                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
6308             }
6309         }
6310     },
6311
6312     // private
6313     getCollapsedEl : function(){
6314         if(!this.collapsedEl){
6315             if(!this.toolTemplate){
6316                 var tt = new Ext.Template(
6317                      '<div class="x-tool x-tool-{id}">&#160;</div>'
6318                 );
6319                 tt.disableFormats = true;
6320                 tt.compile();
6321                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
6322             }
6323             this.collapsedEl = this.targetEl.createChild({
6324                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
6325                 id: this.panel.id + '-xcollapsed'
6326             });
6327             this.collapsedEl.enableDisplayMode('block');
6328
6329             if(this.collapseMode == 'mini'){
6330                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
6331                 this.miniCollapsedEl = this.collapsedEl.createChild({
6332                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
6333                 });
6334                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
6335                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
6336                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
6337             }else {
6338                 if(this.collapsible !== false && !this.hideCollapseTool) {
6339                     var t = this.expandToolEl = this.toolTemplate.append(
6340                             this.collapsedEl.dom,
6341                             {id:'expand-'+this.position}, true);
6342                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
6343                     t.on('click', this.onExpandClick, this, {stopEvent:true});
6344                 }
6345                 if(this.floatable !== false || this.titleCollapse){
6346                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
6347                    this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
6348                 }
6349             }
6350         }
6351         return this.collapsedEl;
6352     },
6353
6354     // private
6355     onExpandClick : function(e){
6356         if(this.isSlid){
6357             this.panel.expand(false);
6358         }else{
6359             this.panel.expand();
6360         }
6361     },
6362
6363     // private
6364     onCollapseClick : function(e){
6365         this.panel.collapse();
6366     },
6367
6368     // private
6369     beforeCollapse : function(p, animate){
6370         this.lastAnim = animate;
6371         if(this.splitEl){
6372             this.splitEl.hide();
6373         }
6374         this.getCollapsedEl().show();
6375         var el = this.panel.getEl();
6376         this.originalZIndex = el.getStyle('z-index');
6377         el.setStyle('z-index', 100);
6378         this.isCollapsed = true;
6379         this.layout.layout();
6380     },
6381
6382     // private
6383     onCollapse : function(animate){
6384         this.panel.el.setStyle('z-index', 1);
6385         if(this.lastAnim === false || this.panel.animCollapse === false){
6386             this.getCollapsedEl().dom.style.visibility = 'visible';
6387         }else{
6388             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
6389         }
6390         this.state.collapsed = true;
6391         this.panel.saveState();
6392     },
6393
6394     // private
6395     beforeExpand : function(animate){
6396         if(this.isSlid){
6397             this.afterSlideIn();
6398         }
6399         var c = this.getCollapsedEl();
6400         this.el.show();
6401         if(this.position == 'east' || this.position == 'west'){
6402             this.panel.setSize(undefined, c.getHeight());
6403         }else{
6404             this.panel.setSize(c.getWidth(), undefined);
6405         }
6406         c.hide();
6407         c.dom.style.visibility = 'hidden';
6408         this.panel.el.setStyle('z-index', this.floatingZIndex);
6409     },
6410
6411     // private
6412     onExpand : function(){
6413         this.isCollapsed = false;
6414         if(this.splitEl){
6415             this.splitEl.show();
6416         }
6417         this.layout.layout();
6418         this.panel.el.setStyle('z-index', this.originalZIndex);
6419         this.state.collapsed = false;
6420         this.panel.saveState();
6421     },
6422
6423     // private
6424     collapseClick : function(e){
6425         if(this.isSlid){
6426            e.stopPropagation();
6427            this.slideIn();
6428         }else{
6429            e.stopPropagation();
6430            this.slideOut();
6431         }
6432     },
6433
6434     // private
6435     onHide : function(){
6436         if(this.isCollapsed){
6437             this.getCollapsedEl().hide();
6438         }else if(this.splitEl){
6439             this.splitEl.hide();
6440         }
6441     },
6442
6443     // private
6444     onShow : function(){
6445         if(this.isCollapsed){
6446             this.getCollapsedEl().show();
6447         }else if(this.splitEl){
6448             this.splitEl.show();
6449         }
6450     },
6451
6452     /**
6453      * True if this region is currently visible, else false.
6454      * @return {Boolean}
6455      */
6456     isVisible : function(){
6457         return !this.panel.hidden;
6458     },
6459
6460     /**
6461      * Returns the current margins for this region.  If the region is collapsed, the
6462      * {@link #cmargins} (collapsed margins) value will be returned, otherwise the
6463      * {@link #margins} value will be returned.
6464      * @return {Object} An object containing the element's margins: <tt>{left: (left
6465      * margin), top: (top margin), right: (right margin), bottom: (bottom margin)}</tt>
6466      */
6467     getMargins : function(){
6468         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
6469     },
6470
6471     /**
6472      * Returns the current size of this region.  If the region is collapsed, the size of the
6473      * collapsedEl will be returned, otherwise the size of the region's panel will be returned.
6474      * @return {Object} An object containing the element's size: <tt>{width: (element width),
6475      * height: (element height)}</tt>
6476      */
6477     getSize : function(){
6478         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
6479     },
6480
6481     /**
6482      * Sets the specified panel as the container element for this region.
6483      * @param {Ext.Panel} panel The new panel
6484      */
6485     setPanel : function(panel){
6486         this.panel = panel;
6487     },
6488
6489     /**
6490      * Returns the minimum allowable width for this region.
6491      * @return {Number} The minimum width
6492      */
6493     getMinWidth: function(){
6494         return this.minWidth;
6495     },
6496
6497     /**
6498      * Returns the minimum allowable height for this region.
6499      * @return {Number} The minimum height
6500      */
6501     getMinHeight: function(){
6502         return this.minHeight;
6503     },
6504
6505     // private
6506     applyLayoutCollapsed : function(box){
6507         var ce = this.getCollapsedEl();
6508         ce.setLeftTop(box.x, box.y);
6509         ce.setSize(box.width, box.height);
6510     },
6511
6512     // private
6513     applyLayout : function(box){
6514         if(this.isCollapsed){
6515             this.applyLayoutCollapsed(box);
6516         }else{
6517             this.panel.setPosition(box.x, box.y);
6518             this.panel.setSize(box.width, box.height);
6519         }
6520     },
6521
6522     // private
6523     beforeSlide: function(){
6524         this.panel.beforeEffect();
6525     },
6526
6527     // private
6528     afterSlide : function(){
6529         this.panel.afterEffect();
6530     },
6531
6532     // private
6533     initAutoHide : function(){
6534         if(this.autoHide !== false){
6535             if(!this.autoHideHd){
6536                 this.autoHideSlideTask = new Ext.util.DelayedTask(this.slideIn, this);
6537                 this.autoHideHd = {
6538                     "mouseout": function(e){
6539                         if(!e.within(this.el, true)){
6540                             this.autoHideSlideTask.delay(500);
6541                         }
6542                     },
6543                     "mouseover" : function(e){
6544                         this.autoHideSlideTask.cancel();
6545                     },
6546                     scope : this
6547                 };
6548             }
6549             this.el.on(this.autoHideHd);
6550             this.collapsedEl.on(this.autoHideHd);
6551         }
6552     },
6553
6554     // private
6555     clearAutoHide : function(){
6556         if(this.autoHide !== false){
6557             this.el.un("mouseout", this.autoHideHd.mouseout);
6558             this.el.un("mouseover", this.autoHideHd.mouseover);
6559             this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
6560             this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
6561         }
6562     },
6563
6564     // private
6565     clearMonitor : function(){
6566         Ext.getDoc().un("click", this.slideInIf, this);
6567     },
6568
6569     /**
6570      * If this Region is {@link #floatable}, this method slides this Region into full visibility <i>over the top
6571      * of the center Region</i> where it floats until either {@link #slideIn} is called, or other regions of the layout
6572      * are clicked, or the mouse exits the Region.
6573      */
6574     slideOut : function(){
6575         if(this.isSlid || this.el.hasActiveFx()){
6576             return;
6577         }
6578         this.isSlid = true;
6579         var ts = this.panel.tools, dh, pc;
6580         if(ts && ts.toggle){
6581             ts.toggle.hide();
6582         }
6583         this.el.show();
6584
6585         // Temporarily clear the collapsed flag so we can onResize the panel on the slide
6586         pc = this.panel.collapsed;
6587         this.panel.collapsed = false;
6588
6589         if(this.position == 'east' || this.position == 'west'){
6590             // Temporarily clear the deferHeight flag so we can size the height on the slide
6591             dh = this.panel.deferHeight;
6592             this.panel.deferHeight = false;
6593
6594             this.panel.setSize(undefined, this.collapsedEl.getHeight());
6595
6596             // Put the deferHeight flag back after setSize
6597             this.panel.deferHeight = dh;
6598         }else{
6599             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
6600         }
6601
6602         // Put the collapsed flag back after onResize
6603         this.panel.collapsed = pc;
6604
6605         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
6606         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
6607         this.el.setStyle("z-index", this.floatingZIndex+2);
6608         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
6609         if(this.animFloat !== false){
6610             this.beforeSlide();
6611             this.el.slideIn(this.getSlideAnchor(), {
6612                 callback: function(){
6613                     this.afterSlide();
6614                     this.initAutoHide();
6615                     Ext.getDoc().on("click", this.slideInIf, this);
6616                 },
6617                 scope: this,
6618                 block: true
6619             });
6620         }else{
6621             this.initAutoHide();
6622              Ext.getDoc().on("click", this.slideInIf, this);
6623         }
6624     },
6625
6626     // private
6627     afterSlideIn : function(){
6628         this.clearAutoHide();
6629         this.isSlid = false;
6630         this.clearMonitor();
6631         this.el.setStyle("z-index", "");
6632         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
6633         this.el.dom.style.left = this.restoreLT[0];
6634         this.el.dom.style.top = this.restoreLT[1];
6635
6636         var ts = this.panel.tools;
6637         if(ts && ts.toggle){
6638             ts.toggle.show();
6639         }
6640     },
6641
6642     /**
6643      * If this Region is {@link #floatable}, and this Region has been slid into floating visibility, then this method slides
6644      * this region back into its collapsed state.
6645      */
6646     slideIn : function(cb){
6647         if(!this.isSlid || this.el.hasActiveFx()){
6648             Ext.callback(cb);
6649             return;
6650         }
6651         this.isSlid = false;
6652         if(this.animFloat !== false){
6653             this.beforeSlide();
6654             this.el.slideOut(this.getSlideAnchor(), {
6655                 callback: function(){
6656                     this.el.hide();
6657                     this.afterSlide();
6658                     this.afterSlideIn();
6659                     Ext.callback(cb);
6660                 },
6661                 scope: this,
6662                 block: true
6663             });
6664         }else{
6665             this.el.hide();
6666             this.afterSlideIn();
6667         }
6668     },
6669
6670     // private
6671     slideInIf : function(e){
6672         if(!e.within(this.el)){
6673             this.slideIn();
6674         }
6675     },
6676
6677     // private
6678     anchors : {
6679         "west" : "left",
6680         "east" : "right",
6681         "north" : "top",
6682         "south" : "bottom"
6683     },
6684
6685     // private
6686     sanchors : {
6687         "west" : "l",
6688         "east" : "r",
6689         "north" : "t",
6690         "south" : "b"
6691     },
6692
6693     // private
6694     canchors : {
6695         "west" : "tl-tr",
6696         "east" : "tr-tl",
6697         "north" : "tl-bl",
6698         "south" : "bl-tl"
6699     },
6700
6701     // private
6702     getAnchor : function(){
6703         return this.anchors[this.position];
6704     },
6705
6706     // private
6707     getCollapseAnchor : function(){
6708         return this.canchors[this.position];
6709     },
6710
6711     // private
6712     getSlideAnchor : function(){
6713         return this.sanchors[this.position];
6714     },
6715
6716     // private
6717     getAlignAdj : function(){
6718         var cm = this.cmargins;
6719         switch(this.position){
6720             case "west":
6721                 return [0, 0];
6722             break;
6723             case "east":
6724                 return [0, 0];
6725             break;
6726             case "north":
6727                 return [0, 0];
6728             break;
6729             case "south":
6730                 return [0, 0];
6731             break;
6732         }
6733     },
6734
6735     // private
6736     getExpandAdj : function(){
6737         var c = this.collapsedEl, cm = this.cmargins;
6738         switch(this.position){
6739             case "west":
6740                 return [-(cm.right+c.getWidth()+cm.left), 0];
6741             break;
6742             case "east":
6743                 return [cm.right+c.getWidth()+cm.left, 0];
6744             break;
6745             case "north":
6746                 return [0, -(cm.top+cm.bottom+c.getHeight())];
6747             break;
6748             case "south":
6749                 return [0, cm.top+cm.bottom+c.getHeight()];
6750             break;
6751         }
6752     },
6753
6754     destroy : function(){
6755         if (this.autoHideSlideTask && this.autoHideSlideTask.cancel){
6756             this.autoHideSlideTask.cancel();
6757         }
6758         Ext.destroyMembers(this, 'miniCollapsedEl', 'collapsedEl', 'expandToolEl');
6759     }
6760 };
6761
6762 /**
6763  * @class Ext.layout.BorderLayout.SplitRegion
6764  * @extends Ext.layout.BorderLayout.Region
6765  * <p>This is a specialized type of {@link Ext.layout.BorderLayout.Region BorderLayout region} that
6766  * has a built-in {@link Ext.SplitBar} for user resizing of regions.  The movement of the split bar
6767  * is configurable to move either {@link #tickSize smooth or incrementally}.</p>
6768  * @constructor
6769  * Create a new SplitRegion.
6770  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
6771  * @param {Object} config The configuration options
6772  * @param {String} position The region position.  Valid values are: north, south, east, west and center.  Every
6773  * BorderLayout must have a center region for the primary content -- all other regions are optional.
6774  */
6775 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
6776     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
6777     // prevent switch
6778     this.applyLayout = this.applyFns[pos];
6779 };
6780
6781 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
6782     /**
6783      * @cfg {Number} tickSize
6784      * The increment, in pixels by which to move this Region's {@link Ext.SplitBar SplitBar}.
6785      * By default, the {@link Ext.SplitBar SplitBar} moves smoothly.
6786      */
6787     /**
6788      * @cfg {String} splitTip
6789      * The tooltip to display when the user hovers over a
6790      * {@link Ext.layout.BorderLayout.Region#collapsible non-collapsible} region's split bar
6791      * (defaults to <tt>"Drag to resize."</tt>).  Only applies if
6792      * <tt>{@link #useSplitTips} = true</tt>.
6793      */
6794     splitTip : "Drag to resize.",
6795     /**
6796      * @cfg {String} collapsibleSplitTip
6797      * The tooltip to display when the user hovers over a
6798      * {@link Ext.layout.BorderLayout.Region#collapsible collapsible} region's split bar
6799      * (defaults to "Drag to resize. Double click to hide."). Only applies if
6800      * <tt>{@link #useSplitTips} = true</tt>.
6801      */
6802     collapsibleSplitTip : "Drag to resize. Double click to hide.",
6803     /**
6804      * @cfg {Boolean} useSplitTips
6805      * <tt>true</tt> to display a tooltip when the user hovers over a region's split bar
6806      * (defaults to <tt>false</tt>).  The tooltip text will be the value of either
6807      * <tt>{@link #splitTip}</tt> or <tt>{@link #collapsibleSplitTip}</tt> as appropriate.
6808      */
6809     useSplitTips : false,
6810
6811     // private
6812     splitSettings : {
6813         north : {
6814             orientation: Ext.SplitBar.VERTICAL,
6815             placement: Ext.SplitBar.TOP,
6816             maxFn : 'getVMaxSize',
6817             minProp: 'minHeight',
6818             maxProp: 'maxHeight'
6819         },
6820         south : {
6821             orientation: Ext.SplitBar.VERTICAL,
6822             placement: Ext.SplitBar.BOTTOM,
6823             maxFn : 'getVMaxSize',
6824             minProp: 'minHeight',
6825             maxProp: 'maxHeight'
6826         },
6827         east : {
6828             orientation: Ext.SplitBar.HORIZONTAL,
6829             placement: Ext.SplitBar.RIGHT,
6830             maxFn : 'getHMaxSize',
6831             minProp: 'minWidth',
6832             maxProp: 'maxWidth'
6833         },
6834         west : {
6835             orientation: Ext.SplitBar.HORIZONTAL,
6836             placement: Ext.SplitBar.LEFT,
6837             maxFn : 'getHMaxSize',
6838             minProp: 'minWidth',
6839             maxProp: 'maxWidth'
6840         }
6841     },
6842
6843     // private
6844     applyFns : {
6845         west : function(box){
6846             if(this.isCollapsed){
6847                 return this.applyLayoutCollapsed(box);
6848             }
6849             var sd = this.splitEl.dom, s = sd.style;
6850             this.panel.setPosition(box.x, box.y);
6851             var sw = sd.offsetWidth;
6852             s.left = (box.x+box.width-sw)+'px';
6853             s.top = (box.y)+'px';
6854             s.height = Math.max(0, box.height)+'px';
6855             this.panel.setSize(box.width-sw, box.height);
6856         },
6857         east : function(box){
6858             if(this.isCollapsed){
6859                 return this.applyLayoutCollapsed(box);
6860             }
6861             var sd = this.splitEl.dom, s = sd.style;
6862             var sw = sd.offsetWidth;
6863             this.panel.setPosition(box.x+sw, box.y);
6864             s.left = (box.x)+'px';
6865             s.top = (box.y)+'px';
6866             s.height = Math.max(0, box.height)+'px';
6867             this.panel.setSize(box.width-sw, box.height);
6868         },
6869         north : function(box){
6870             if(this.isCollapsed){
6871                 return this.applyLayoutCollapsed(box);
6872             }
6873             var sd = this.splitEl.dom, s = sd.style;
6874             var sh = sd.offsetHeight;
6875             this.panel.setPosition(box.x, box.y);
6876             s.left = (box.x)+'px';
6877             s.top = (box.y+box.height-sh)+'px';
6878             s.width = Math.max(0, box.width)+'px';
6879             this.panel.setSize(box.width, box.height-sh);
6880         },
6881         south : function(box){
6882             if(this.isCollapsed){
6883                 return this.applyLayoutCollapsed(box);
6884             }
6885             var sd = this.splitEl.dom, s = sd.style;
6886             var sh = sd.offsetHeight;
6887             this.panel.setPosition(box.x, box.y+sh);
6888             s.left = (box.x)+'px';
6889             s.top = (box.y)+'px';
6890             s.width = Math.max(0, box.width)+'px';
6891             this.panel.setSize(box.width, box.height-sh);
6892         }
6893     },
6894
6895     // private
6896     render : function(ct, p){
6897         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
6898
6899         var ps = this.position;
6900
6901         this.splitEl = ct.createChild({
6902             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
6903             id: this.panel.id + '-xsplit'
6904         });
6905
6906         if(this.collapseMode == 'mini'){
6907             this.miniSplitEl = this.splitEl.createChild({
6908                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
6909             });
6910             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
6911             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
6912         }
6913
6914         var s = this.splitSettings[ps];
6915
6916         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
6917         this.split.tickSize = this.tickSize;
6918         this.split.placement = s.placement;
6919         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
6920         this.split.minSize = this.minSize || this[s.minProp];
6921         this.split.on("beforeapply", this.onSplitMove, this);
6922         this.split.useShim = this.useShim === true;
6923         this.maxSize = this.maxSize || this[s.maxProp];
6924
6925         if(p.hidden){
6926             this.splitEl.hide();
6927         }
6928
6929         if(this.useSplitTips){
6930             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
6931         }
6932         if(this.collapsible){
6933             this.splitEl.on("dblclick", this.onCollapseClick,  this);
6934         }
6935     },
6936
6937     //docs inherit from superclass
6938     getSize : function(){
6939         if(this.isCollapsed){
6940             return this.collapsedEl.getSize();
6941         }
6942         var s = this.panel.getSize();
6943         if(this.position == 'north' || this.position == 'south'){
6944             s.height += this.splitEl.dom.offsetHeight;
6945         }else{
6946             s.width += this.splitEl.dom.offsetWidth;
6947         }
6948         return s;
6949     },
6950
6951     // private
6952     getHMaxSize : function(){
6953          var cmax = this.maxSize || 10000;
6954          var center = this.layout.center;
6955          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
6956     },
6957
6958     // private
6959     getVMaxSize : function(){
6960         var cmax = this.maxSize || 10000;
6961         var center = this.layout.center;
6962         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
6963     },
6964
6965     // private
6966     onSplitMove : function(split, newSize){
6967         var s = this.panel.getSize();
6968         this.lastSplitSize = newSize;
6969         if(this.position == 'north' || this.position == 'south'){
6970             this.panel.setSize(s.width, newSize);
6971             this.state.height = newSize;
6972         }else{
6973             this.panel.setSize(newSize, s.height);
6974             this.state.width = newSize;
6975         }
6976         this.layout.layout();
6977         this.panel.saveState();
6978         return false;
6979     },
6980
6981     /**
6982      * Returns a reference to the split bar in use by this region.
6983      * @return {Ext.SplitBar} The split bar
6984      */
6985     getSplitBar : function(){
6986         return this.split;
6987     },
6988
6989     // inherit docs
6990     destroy : function() {
6991         Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
6992         Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
6993     }
6994 });
6995
6996 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;
6997 /**
6998  * @class Ext.layout.FormLayout
6999  * @extends Ext.layout.AnchorLayout
7000  * <p>This layout manager is specifically designed for rendering and managing child Components of
7001  * {@link Ext.form.FormPanel forms}. It is responsible for rendering the labels of
7002  * {@link Ext.form.Field Field}s.</p>
7003  *
7004  * <p>This layout manager is used when a Container is configured with the <tt>layout:'form'</tt>
7005  * {@link Ext.Container#layout layout} config option, and should generally not need to be created directly
7006  * via the new keyword. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
7007  *
7008  * <p>In an application, it will usually be preferrable to use a {@link Ext.form.FormPanel FormPanel}
7009  * (which is configured with FormLayout as its layout class by default) since it also provides built-in
7010  * functionality for {@link Ext.form.BasicForm#doAction loading, validating and submitting} the form.</p>
7011  *
7012  * <p>A {@link Ext.Container Container} <i>using</i> the FormLayout layout manager (e.g.
7013  * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) can also accept the following
7014  * layout-specific config properties:<div class="mdetail-params"><ul>
7015  * <li><b><tt>{@link Ext.form.FormPanel#hideLabels hideLabels}</tt></b></li>
7016  * <li><b><tt>{@link Ext.form.FormPanel#labelAlign labelAlign}</tt></b></li>
7017  * <li><b><tt>{@link Ext.form.FormPanel#labelPad labelPad}</tt></b></li>
7018  * <li><b><tt>{@link Ext.form.FormPanel#labelSeparator labelSeparator}</tt></b></li>
7019  * <li><b><tt>{@link Ext.form.FormPanel#labelWidth labelWidth}</tt></b></li>
7020  * </ul></div></p>
7021  *
7022  * <p>Any Component (including Fields) managed by FormLayout accepts the following as a config option:
7023  * <div class="mdetail-params"><ul>
7024  * <li><b><tt>{@link Ext.Component#anchor anchor}</tt></b></li>
7025  * </ul></div></p>
7026  *
7027  * <p>Any Component managed by FormLayout may be rendered as a form field (with an associated label) by
7028  * configuring it with a non-null <b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b>. Components configured
7029  * in this way may be configured with the following options which affect the way the FormLayout renders them:
7030  * <div class="mdetail-params"><ul>
7031  * <li><b><tt>{@link Ext.Component#clearCls clearCls}</tt></b></li>
7032  * <li><b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b></li>
7033  * <li><b><tt>{@link Ext.Component#hideLabel hideLabel}</tt></b></li>
7034  * <li><b><tt>{@link Ext.Component#itemCls itemCls}</tt></b></li>
7035  * <li><b><tt>{@link Ext.Component#labelSeparator labelSeparator}</tt></b></li>
7036  * <li><b><tt>{@link Ext.Component#labelStyle labelStyle}</tt></b></li>
7037  * </ul></div></p>
7038  *
7039  * <p>Example usage:</p>
7040  * <pre><code>
7041 // Required if showing validation messages
7042 Ext.QuickTips.init();
7043
7044 // While you can create a basic Panel with layout:'form', practically
7045 // you should usually use a FormPanel to also get its form functionality
7046 // since it already creates a FormLayout internally.
7047 var form = new Ext.form.FormPanel({
7048     title: 'Form Layout',
7049     bodyStyle: 'padding:15px',
7050     width: 350,
7051     defaultType: 'textfield',
7052     defaults: {
7053         // applied to each contained item
7054         width: 230,
7055         msgTarget: 'side'
7056     },
7057     items: [{
7058             fieldLabel: 'First Name',
7059             name: 'first',
7060             allowBlank: false,
7061             {@link Ext.Component#labelSeparator labelSeparator}: ':' // override labelSeparator layout config
7062         },{
7063             fieldLabel: 'Last Name',
7064             name: 'last'
7065         },{
7066             fieldLabel: 'Email',
7067             name: 'email',
7068             vtype:'email'
7069         }, {
7070             xtype: 'textarea',
7071             hideLabel: true,     // override hideLabels layout config
7072             name: 'msg',
7073             anchor: '100% -53'
7074         }
7075     ],
7076     buttons: [
7077         {text: 'Save'},
7078         {text: 'Cancel'}
7079     ],
7080     layoutConfig: {
7081         {@link #labelSeparator}: '~' // superseded by assignment below
7082     },
7083     // config options applicable to container when layout='form':
7084     hideLabels: false,
7085     labelAlign: 'left',   // or 'right' or 'top'
7086     {@link Ext.form.FormPanel#labelSeparator labelSeparator}: '>>', // takes precedence over layoutConfig value
7087     labelWidth: 65,       // defaults to 100
7088     labelPad: 8           // defaults to 5, must specify labelWidth to be honored
7089 });
7090 </code></pre>
7091  */
7092 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
7093
7094     /**
7095      * @cfg {String} labelSeparator
7096      * See {@link Ext.form.FormPanel}.{@link Ext.form.FormPanel#labelSeparator labelSeparator}.  Configuration
7097      * of this property at the <b>container</b> level takes precedence.
7098      */
7099     labelSeparator : ':',
7100
7101     /**
7102      * Read only. The CSS style specification string added to field labels in this layout if not
7103      * otherwise {@link Ext.Component#labelStyle specified by each contained field}.
7104      * @type String
7105      * @property labelStyle
7106      */
7107
7108     /**
7109      * @cfg {Boolean} trackLabels
7110      * True to show/hide the field label when the field is hidden. Defaults to <tt>true</tt>.
7111      */
7112     trackLabels: true,
7113
7114     type: 'form',
7115
7116     onRemove: function(c){
7117         Ext.layout.FormLayout.superclass.onRemove.call(this, c);
7118         if(this.trackLabels){
7119             c.un('show', this.onFieldShow, this);
7120             c.un('hide', this.onFieldHide, this);
7121         }
7122         // check for itemCt, since we may be removing a fieldset or something similar
7123         var el = c.getPositionEl(),
7124             ct = c.getItemCt && c.getItemCt();
7125         if (c.rendered && ct) {
7126             if (el && el.dom) {
7127                 el.insertAfter(ct);
7128             }
7129             Ext.destroy(ct);
7130             Ext.destroyMembers(c, 'label', 'itemCt');
7131             if (c.customItemCt) {
7132                 Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
7133             }
7134         }
7135     },
7136
7137     // private
7138     setContainer : function(ct){
7139         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
7140         if(ct.labelAlign){
7141             ct.addClass('x-form-label-'+ct.labelAlign);
7142         }
7143
7144         if(ct.hideLabels){
7145             Ext.apply(this, {
7146                 labelStyle: 'display:none',
7147                 elementStyle: 'padding-left:0;',
7148                 labelAdjust: 0
7149             });
7150         }else{
7151             this.labelSeparator = Ext.isDefined(ct.labelSeparator) ? ct.labelSeparator : this.labelSeparator;
7152             ct.labelWidth = ct.labelWidth || 100;
7153             if(Ext.isNumber(ct.labelWidth)){
7154                 var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
7155                 Ext.apply(this, {
7156                     labelAdjust: ct.labelWidth + pad,
7157                     labelStyle: 'width:' + ct.labelWidth + 'px;',
7158                     elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
7159                 });
7160             }
7161             if(ct.labelAlign == 'top'){
7162                 Ext.apply(this, {
7163                     labelStyle: 'width:auto;',
7164                     labelAdjust: 0,
7165                     elementStyle: 'padding-left:0;'
7166                 });
7167             }
7168         }
7169     },
7170
7171     // private
7172     isHide: function(c){
7173         return c.hideLabel || this.container.hideLabels;
7174     },
7175
7176     onFieldShow: function(c){
7177         c.getItemCt().removeClass('x-hide-' + c.hideMode);
7178
7179         // Composite fields will need to layout after the container is made visible
7180         if (c.isComposite) {
7181             c.doLayout();
7182         }
7183     },
7184
7185     onFieldHide: function(c){
7186         c.getItemCt().addClass('x-hide-' + c.hideMode);
7187     },
7188
7189     //private
7190     getLabelStyle: function(s){
7191         var ls = '', items = [this.labelStyle, s];
7192         for (var i = 0, len = items.length; i < len; ++i){
7193             if (items[i]){
7194                 ls += items[i];
7195                 if (ls.substr(-1, 1) != ';'){
7196                     ls += ';';
7197                 }
7198             }
7199         }
7200         return ls;
7201     },
7202
7203     /**
7204      * @cfg {Ext.Template} fieldTpl
7205      * A {@link Ext.Template#compile compile}d {@link Ext.Template} for rendering
7206      * the fully wrapped, labeled and styled form Field. Defaults to:</p><pre><code>
7207 new Ext.Template(
7208     &#39;&lt;div class="x-form-item {itemCls}" tabIndex="-1">&#39;,
7209         &#39;&lt;&#108;abel for="{id}" style="{labelStyle}" class="x-form-item-&#108;abel">{&#108;abel}{labelSeparator}&lt;/&#108;abel>&#39;,
7210         &#39;&lt;div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">&#39;,
7211         &#39;&lt;/div>&lt;div class="{clearCls}">&lt;/div>&#39;,
7212     '&lt;/div>'
7213 );
7214 </code></pre>
7215      * <p>This may be specified to produce a different DOM structure when rendering form Fields.</p>
7216      * <p>A description of the properties within the template follows:</p><div class="mdetail-params"><ul>
7217      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
7218      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
7219      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
7220      * supplied at the container level.</div></li>
7221      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
7222      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
7223      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
7224      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
7225      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
7226      * field (defaults to <tt>''</tt>)</div></li>
7227      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
7228      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
7229      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
7230      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
7231      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
7232      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
7233      * </ul></div>
7234      * <p>Also see <tt>{@link #getTemplateArgs}</tt></p>
7235      */
7236
7237     /**
7238      * @private
7239      *
7240      */
7241     renderItem : function(c, position, target){
7242         if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
7243             var args = this.getTemplateArgs(c);
7244             if(Ext.isNumber(position)){
7245                 position = target.dom.childNodes[position] || null;
7246             }
7247             if(position){
7248                 c.itemCt = this.fieldTpl.insertBefore(position, args, true);
7249             }else{
7250                 c.itemCt = this.fieldTpl.append(target, args, true);
7251             }
7252             if(!c.getItemCt){
7253                 // Non form fields don't have getItemCt, apply it here
7254                 // This will get cleaned up in onRemove
7255                 Ext.apply(c, {
7256                     getItemCt: function(){
7257                         return c.itemCt;
7258                     },
7259                     customItemCt: true
7260                 });
7261             }
7262             c.label = c.getItemCt().child('label.x-form-item-label');
7263             if(!c.rendered){
7264                 c.render('x-form-el-' + c.id);
7265             }else if(!this.isValidParent(c, target)){
7266                 Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
7267             }
7268             if(this.trackLabels){
7269                 if(c.hidden){
7270                     this.onFieldHide(c);
7271                 }
7272                 c.on({
7273                     scope: this,
7274                     show: this.onFieldShow,
7275                     hide: this.onFieldHide
7276                 });
7277             }
7278             this.configureItem(c);
7279         }else {
7280             Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
7281         }
7282     },
7283
7284     /**
7285      * <p>Provides template arguments for rendering the fully wrapped, labeled and styled form Field.</p>
7286      * <p>This method returns an object hash containing properties used by the layout's {@link #fieldTpl}
7287      * to create a correctly wrapped, labeled and styled form Field. This may be overriden to
7288      * create custom layouts. The properties which must be returned are:</p><div class="mdetail-params"><ul>
7289      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
7290      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
7291      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
7292      * supplied at the container level.</div></li>
7293      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
7294      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
7295      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
7296      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
7297      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
7298      * field (defaults to the field's configured fieldLabel property)</div></li>
7299      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
7300      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
7301      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
7302      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
7303      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
7304      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
7305      * </ul></div>
7306      * @param (Ext.form.Field} field The {@link Ext.form.Field Field} being rendered.
7307      * @return {Object} An object hash containing the properties required to render the Field.
7308      */
7309     getTemplateArgs: function(field) {
7310         var noLabelSep = !field.fieldLabel || field.hideLabel;
7311
7312         return {
7313             id            : field.id,
7314             label         : field.fieldLabel,
7315             itemCls       : (field.itemCls || this.container.itemCls || '') + (field.hideLabel ? ' x-hide-label' : ''),
7316             clearCls      : field.clearCls || 'x-form-clear-left',
7317             labelStyle    : this.getLabelStyle(field.labelStyle),
7318             elementStyle  : this.elementStyle || '',
7319             labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator)
7320         };
7321     },
7322
7323     // private
7324     adjustWidthAnchor: function(value, c){
7325         if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){
7326             var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
7327             return value - this.labelAdjust + (adjust ? -3 : 0);
7328         }
7329         return value;
7330     },
7331
7332     adjustHeightAnchor : function(value, c){
7333         if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
7334             return value - c.label.getHeight();
7335         }
7336         return value;
7337     },
7338
7339     // private
7340     isValidParent : function(c, target){
7341         return target && this.container.getEl().contains(c.getPositionEl());
7342     }
7343
7344     /**
7345      * @property activeItem
7346      * @hide
7347      */
7348 });
7349
7350 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
7351 /**
7352  * @class Ext.layout.AccordionLayout
7353  * @extends Ext.layout.FitLayout
7354  * <p>This is a layout that manages multiple Panels in an expandable accordion style such that only
7355  * <b>one Panel can be expanded at any given time</b>. Each Panel has built-in support for expanding and collapsing.</p>
7356  * <p>Note: Only Ext.Panels <b>and all subclasses of Ext.Panel</b> may be used in an accordion layout Container.</p>
7357  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
7358  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
7359  * <p>Example usage:</p>
7360  * <pre><code>
7361 var accordion = new Ext.Panel({
7362     title: 'Accordion Layout',
7363     layout:'accordion',
7364     defaults: {
7365         // applied to each contained panel
7366         bodyStyle: 'padding:15px'
7367     },
7368     layoutConfig: {
7369         // layout-specific configs go here
7370         titleCollapse: false,
7371         animate: true,
7372         activeOnTop: true
7373     },
7374     items: [{
7375         title: 'Panel 1',
7376         html: '&lt;p&gt;Panel content!&lt;/p&gt;'
7377     },{
7378         title: 'Panel 2',
7379         html: '&lt;p&gt;Panel content!&lt;/p&gt;'
7380     },{
7381         title: 'Panel 3',
7382         html: '&lt;p&gt;Panel content!&lt;/p&gt;'
7383     }]
7384 });
7385 </code></pre>
7386  */
7387 Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
7388     /**
7389      * @cfg {Boolean} fill
7390      * True to adjust the active item's height to fill the available space in the container, false to use the
7391      * item's current height, or auto height if not explicitly set (defaults to true).
7392      */
7393     fill : true,
7394     /**
7395      * @cfg {Boolean} autoWidth
7396      * True to set each contained item's width to 'auto', false to use the item's current width (defaults to true).
7397      * Note that some components, in particular the {@link Ext.grid.GridPanel grid}, will not function properly within
7398      * layouts if they have auto width, so in such cases this config should be set to false.
7399      */
7400     autoWidth : true,
7401     /**
7402      * @cfg {Boolean} titleCollapse
7403      * True to allow expand/collapse of each contained panel by clicking anywhere on the title bar, false to allow
7404      * expand/collapse only when the toggle tool button is clicked (defaults to true).  When set to false,
7405      * {@link #hideCollapseTool} should be false also.
7406      */
7407     titleCollapse : true,
7408     /**
7409      * @cfg {Boolean} hideCollapseTool
7410      * True to hide the contained panels' collapse/expand toggle buttons, false to display them (defaults to false).
7411      * When set to true, {@link #titleCollapse} should be true also.
7412      */
7413     hideCollapseTool : false,
7414     /**
7415      * @cfg {Boolean} collapseFirst
7416      * True to make sure the collapse/expand toggle button always renders first (to the left of) any other tools
7417      * in the contained panels' title bars, false to render it last (defaults to false).
7418      */
7419     collapseFirst : false,
7420     /**
7421      * @cfg {Boolean} animate
7422      * True to slide the contained panels open and closed during expand/collapse using animation, false to open and
7423      * close directly with no animation (defaults to false).  Note: to defer to the specific config setting of each
7424      * contained panel for this property, set this to undefined at the layout level.
7425      */
7426     animate : false,
7427     /**
7428      * @cfg {Boolean} sequence
7429      * <b>Experimental</b>. If animate is set to true, this will result in each animation running in sequence.
7430      */
7431     sequence : false,
7432     /**
7433      * @cfg {Boolean} activeOnTop
7434      * True to swap the position of each panel as it is expanded so that it becomes the first item in the container,
7435      * false to keep the panels in the rendered order. <b>This is NOT compatible with "animate:true"</b> (defaults to false).
7436      */
7437     activeOnTop : false,
7438
7439     type: 'accordion',
7440
7441     renderItem : function(c){
7442         if(this.animate === false){
7443             c.animCollapse = false;
7444         }
7445         c.collapsible = true;
7446         if(this.autoWidth){
7447             c.autoWidth = true;
7448         }
7449         if(this.titleCollapse){
7450             c.titleCollapse = true;
7451         }
7452         if(this.hideCollapseTool){
7453             c.hideCollapseTool = true;
7454         }
7455         if(this.collapseFirst !== undefined){
7456             c.collapseFirst = this.collapseFirst;
7457         }
7458         if(!this.activeItem && !c.collapsed){
7459             this.setActiveItem(c, true);
7460         }else if(this.activeItem && this.activeItem != c){
7461             c.collapsed = true;
7462         }
7463         Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
7464         c.header.addClass('x-accordion-hd');
7465         c.on('beforeexpand', this.beforeExpand, this);
7466     },
7467
7468     onRemove: function(c){
7469         Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
7470         if(c.rendered){
7471             c.header.removeClass('x-accordion-hd');
7472         }
7473         c.un('beforeexpand', this.beforeExpand, this);
7474     },
7475
7476     // private
7477     beforeExpand : function(p, anim){
7478         var ai = this.activeItem;
7479         if(ai){
7480             if(this.sequence){
7481                 delete this.activeItem;
7482                 if (!ai.collapsed){
7483                     ai.collapse({callback:function(){
7484                         p.expand(anim || true);
7485                     }, scope: this});
7486                     return false;
7487                 }
7488             }else{
7489                 ai.collapse(this.animate);
7490             }
7491         }
7492         this.setActive(p);
7493         if(this.activeOnTop){
7494             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
7495         }
7496         // Items have been hidden an possibly rearranged, we need to get the container size again.
7497         this.layout();
7498     },
7499
7500     // private
7501     setItemSize : function(item, size){
7502         if(this.fill && item){
7503             var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;
7504             // Add up all the header heights
7505             for (i = 0; i < len; i++) {
7506                 if((p = ct[i]) != item && !p.hidden){
7507                     hh += p.header.getHeight();
7508                 }
7509             };
7510             // Subtract the header heights from the container size
7511             size.height -= hh;
7512             // Call setSize on the container to set the correct height.  For Panels, deferedHeight
7513             // will simply store this size for when the expansion is done.
7514             item.setSize(size);
7515         }
7516     },
7517
7518     /**
7519      * Sets the active (expanded) item in the layout.
7520      * @param {String/Number} item The string component id or numeric index of the item to activate
7521      */
7522     setActiveItem : function(item){
7523         this.setActive(item, true);
7524     },
7525
7526     // private
7527     setActive : function(item, expand){
7528         var ai = this.activeItem;
7529         item = this.container.getComponent(item);
7530         if(ai != item){
7531             if(item.rendered && item.collapsed && expand){
7532                 item.expand();
7533             }else{
7534                 if(ai){
7535                    ai.fireEvent('deactivate', ai);
7536                 }
7537                 this.activeItem = item;
7538                 item.fireEvent('activate', item);
7539             }
7540         }
7541     }
7542 });
7543 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
7544
7545 //backwards compat
7546 Ext.layout.Accordion = Ext.layout.AccordionLayout;/**
7547  * @class Ext.layout.TableLayout
7548  * @extends Ext.layout.ContainerLayout
7549  * <p>This layout allows you to easily render content into an HTML table.  The total number of columns can be
7550  * specified, and rowspan and colspan can be used to create complex layouts within the table.
7551  * This class is intended to be extended or created via the layout:'table' {@link Ext.Container#layout} config,
7552  * and should generally not need to be created directly via the new keyword.</p>
7553  * <p>Note that when creating a layout via config, the layout-specific config properties must be passed in via
7554  * the {@link Ext.Container#layoutConfig} object which will then be applied internally to the layout.  In the
7555  * case of TableLayout, the only valid layout config property is {@link #columns}.  However, the items added to a
7556  * TableLayout can supply the following table-specific config properties:</p>
7557  * <ul>
7558  * <li><b>rowspan</b> Applied to the table cell containing the item.</li>
7559  * <li><b>colspan</b> Applied to the table cell containing the item.</li>
7560  * <li><b>cellId</b> An id applied to the table cell containing the item.</li>
7561  * <li><b>cellCls</b> A CSS class name added to the table cell containing the item.</li>
7562  * </ul>
7563  * <p>The basic concept of building up a TableLayout is conceptually very similar to building up a standard
7564  * HTML table.  You simply add each panel (or "cell") that you want to include along with any span attributes
7565  * specified as the special config properties of rowspan and colspan which work exactly like their HTML counterparts.
7566  * Rather than explicitly creating and nesting rows and columns as you would in HTML, you simply specify the
7567  * total column count in the layoutConfig and start adding panels in their natural order from left to right,
7568  * top to bottom.  The layout will automatically figure out, based on the column count, rowspans and colspans,
7569  * how to position each panel within the table.  Just like with HTML tables, your rowspans and colspans must add
7570  * up correctly in your overall layout or you'll end up with missing and/or extra cells!  Example usage:</p>
7571  * <pre><code>
7572 // This code will generate a layout table that is 3 columns by 2 rows
7573 // with some spanning included.  The basic layout will be:
7574 // +--------+-----------------+
7575 // |   A    |   B             |
7576 // |        |--------+--------|
7577 // |        |   C    |   D    |
7578 // +--------+--------+--------+
7579 var table = new Ext.Panel({
7580     title: 'Table Layout',
7581     layout:'table',
7582     defaults: {
7583         // applied to each contained panel
7584         bodyStyle:'padding:20px'
7585     },
7586     layoutConfig: {
7587         // The total column count must be specified here
7588         columns: 3
7589     },
7590     items: [{
7591         html: '&lt;p&gt;Cell A content&lt;/p&gt;',
7592         rowspan: 2
7593     },{
7594         html: '&lt;p&gt;Cell B content&lt;/p&gt;',
7595         colspan: 2
7596     },{
7597         html: '&lt;p&gt;Cell C content&lt;/p&gt;',
7598         cellCls: 'highlight'
7599     },{
7600         html: '&lt;p&gt;Cell D content&lt;/p&gt;'
7601     }]
7602 });
7603 </code></pre>
7604  */
7605 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
7606     /**
7607      * @cfg {Number} columns
7608      * The total number of columns to create in the table for this layout.  If not specified, all Components added to
7609      * this layout will be rendered into a single row using one column per Component.
7610      */
7611
7612     // private
7613     monitorResize:false,
7614
7615     type: 'table',
7616
7617     targetCls: 'x-table-layout-ct',
7618
7619     /**
7620      * @cfg {Object} tableAttrs
7621      * <p>An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification
7622      * used to create the layout's <tt>&lt;table&gt;</tt> element. Example:</p><pre><code>
7623 {
7624     xtype: 'panel',
7625     layout: 'table',
7626     layoutConfig: {
7627         tableAttrs: {
7628             style: {
7629                 width: '100%'
7630             }
7631         },
7632         columns: 3
7633     }
7634 }</code></pre>
7635      */
7636     tableAttrs:null,
7637
7638     // private
7639     setContainer : function(ct){
7640         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
7641
7642         this.currentRow = 0;
7643         this.currentColumn = 0;
7644         this.cells = [];
7645     },
7646     
7647     // private
7648     onLayout : function(ct, target){
7649         var cs = ct.items.items, len = cs.length, c, i;
7650
7651         if(!this.table){
7652             target.addClass('x-table-layout-ct');
7653
7654             this.table = target.createChild(
7655                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
7656         }
7657         this.renderAll(ct, target);
7658     },
7659
7660     // private
7661     getRow : function(index){
7662         var row = this.table.tBodies[0].childNodes[index];
7663         if(!row){
7664             row = document.createElement('tr');
7665             this.table.tBodies[0].appendChild(row);
7666         }
7667         return row;
7668     },
7669
7670     // private
7671     getNextCell : function(c){
7672         var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
7673         var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
7674         for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
7675             if(!this.cells[rowIndex]){
7676                 this.cells[rowIndex] = [];
7677             }
7678             for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
7679                 this.cells[rowIndex][colIndex] = true;
7680             }
7681         }
7682         var td = document.createElement('td');
7683         if(c.cellId){
7684             td.id = c.cellId;
7685         }
7686         var cls = 'x-table-layout-cell';
7687         if(c.cellCls){
7688             cls += ' ' + c.cellCls;
7689         }
7690         td.className = cls;
7691         if(c.colspan){
7692             td.colSpan = c.colspan;
7693         }
7694         if(c.rowspan){
7695             td.rowSpan = c.rowspan;
7696         }
7697         this.getRow(curRow).appendChild(td);
7698         return td;
7699     },
7700
7701     // private
7702     getNextNonSpan: function(colIndex, rowIndex){
7703         var cols = this.columns;
7704         while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
7705             if(cols && colIndex >= cols){
7706                 rowIndex++;
7707                 colIndex = 0;
7708             }else{
7709                 colIndex++;
7710             }
7711         }
7712         return [colIndex, rowIndex];
7713     },
7714
7715     // private
7716     renderItem : function(c, position, target){
7717         // Ensure we have our inner table to get cells to render into.
7718         if(!this.table){
7719             this.table = target.createChild(
7720                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
7721         }
7722         if(c && !c.rendered){
7723             c.render(this.getNextCell(c));
7724             this.configureItem(c);
7725         }else if(c && !this.isValidParent(c, target)){
7726             var container = this.getNextCell(c);
7727             container.insertBefore(c.getPositionEl().dom, null);
7728             c.container = Ext.get(container);
7729             this.configureItem(c);
7730         }
7731     },
7732
7733     // private
7734     isValidParent : function(c, target){
7735         return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);
7736     },
7737     
7738     destroy: function(){
7739         delete this.table;
7740         Ext.layout.TableLayout.superclass.destroy.call(this);
7741     }
7742
7743     /**
7744      * @property activeItem
7745      * @hide
7746      */
7747 });
7748
7749 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;/**
7750  * @class Ext.layout.AbsoluteLayout
7751  * @extends Ext.layout.AnchorLayout
7752  * <p>This is a layout that inherits the anchoring of <b>{@link Ext.layout.AnchorLayout}</b> and adds the
7753  * ability for x/y positioning using the standard x and y component config options.</p>
7754  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
7755  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
7756  * <p>Example usage:</p>
7757  * <pre><code>
7758 var form = new Ext.form.FormPanel({
7759     title: 'Absolute Layout',
7760     layout:'absolute',
7761     layoutConfig: {
7762         // layout-specific configs go here
7763         extraCls: 'x-abs-layout-item',
7764     },
7765     baseCls: 'x-plain',
7766     url:'save-form.php',
7767     defaultType: 'textfield',
7768     items: [{
7769         x: 0,
7770         y: 5,
7771         xtype:'label',
7772         text: 'Send To:'
7773     },{
7774         x: 60,
7775         y: 0,
7776         name: 'to',
7777         anchor:'100%'  // anchor width by percentage
7778     },{
7779         x: 0,
7780         y: 35,
7781         xtype:'label',
7782         text: 'Subject:'
7783     },{
7784         x: 60,
7785         y: 30,
7786         name: 'subject',
7787         anchor: '100%'  // anchor width by percentage
7788     },{
7789         x:0,
7790         y: 60,
7791         xtype: 'textarea',
7792         name: 'msg',
7793         anchor: '100% 100%'  // anchor width and height
7794     }]
7795 });
7796 </code></pre>
7797  */
7798 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
7799
7800     extraCls: 'x-abs-layout-item',
7801
7802     type: 'absolute',
7803
7804     onLayout : function(ct, target){
7805         target.position();
7806         this.paddingLeft = target.getPadding('l');
7807         this.paddingTop = target.getPadding('t');
7808         Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
7809     },
7810
7811     // private
7812     adjustWidthAnchor : function(value, comp){
7813         return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
7814     },
7815
7816     // private
7817     adjustHeightAnchor : function(value, comp){
7818         return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
7819     }
7820     /**
7821      * @property activeItem
7822      * @hide
7823      */
7824 });
7825 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
7826 /**
7827  * @class Ext.layout.BoxLayout
7828  * @extends Ext.layout.ContainerLayout
7829  * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
7830  */
7831 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
7832     /**
7833      * @cfg {Object} defaultMargins
7834      * <p>If the individual contained items do not have a <tt>margins</tt>
7835      * property specified, the default margins from this property will be
7836      * applied to each item.</p>
7837      * <br><p>This property may be specified as an object containing margins
7838      * to apply in the format:</p><pre><code>
7839 {
7840     top: (top margin),
7841     right: (right margin),
7842     bottom: (bottom margin),
7843     left: (left margin)
7844 }</code></pre>
7845      * <p>This property may also be specified as a string containing
7846      * space-separated, numeric margin values. The order of the sides associated
7847      * with each value matches the way CSS processes margin values:</p>
7848      * <div class="mdetail-params"><ul>
7849      * <li>If there is only one value, it applies to all sides.</li>
7850      * <li>If there are two values, the top and bottom borders are set to the
7851      * first value and the right and left are set to the second.</li>
7852      * <li>If there are three values, the top is set to the first value, the left
7853      * and right are set to the second, and the bottom is set to the third.</li>
7854      * <li>If there are four values, they apply to the top, right, bottom, and
7855      * left, respectively.</li>
7856      * </ul></div>
7857      * <p>Defaults to:</p><pre><code>
7858      * {top:0, right:0, bottom:0, left:0}
7859      * </code></pre>
7860      */
7861     defaultMargins : {left:0,top:0,right:0,bottom:0},
7862     /**
7863      * @cfg {String} padding
7864      * <p>Sets the padding to be applied to all child items managed by this layout.</p>
7865      * <p>This property must be specified as a string containing
7866      * space-separated, numeric padding values. The order of the sides associated
7867      * with each value matches the way CSS processes padding values:</p>
7868      * <div class="mdetail-params"><ul>
7869      * <li>If there is only one value, it applies to all sides.</li>
7870      * <li>If there are two values, the top and bottom borders are set to the
7871      * first value and the right and left are set to the second.</li>
7872      * <li>If there are three values, the top is set to the first value, the left
7873      * and right are set to the second, and the bottom is set to the third.</li>
7874      * <li>If there are four values, they apply to the top, right, bottom, and
7875      * left, respectively.</li>
7876      * </ul></div>
7877      * <p>Defaults to: <code>"0"</code></p>
7878      */
7879     padding : '0',
7880     // documented in subclasses
7881     pack : 'start',
7882
7883     // private
7884     monitorResize : true,
7885     type: 'box',
7886     scrollOffset : 0,
7887     extraCls : 'x-box-item',
7888     targetCls : 'x-box-layout-ct',
7889     innerCls : 'x-box-inner',
7890
7891     constructor : function(config){
7892         Ext.layout.BoxLayout.superclass.constructor.call(this, config);
7893
7894         if (Ext.isString(this.defaultMargins)) {
7895             this.defaultMargins = this.parseMargins(this.defaultMargins);
7896         }
7897         
7898         var handler = this.overflowHandler;
7899         
7900         if (typeof handler == 'string') {
7901             handler = {
7902                 type: handler
7903             };
7904         }
7905         
7906         var handlerType = 'none';
7907         if (handler && handler.type != undefined) {
7908             handlerType = handler.type;
7909         }
7910         
7911         var constructor = Ext.layout.boxOverflow[handlerType];
7912         if (constructor[this.type]) {
7913             constructor = constructor[this.type];
7914         }
7915         
7916         this.overflowHandler = new constructor(this, handler);
7917     },
7918
7919     /**
7920      * @private
7921      * Runs the child box calculations and caches them in childBoxCache. Subclasses can used these cached values
7922      * when laying out
7923      */
7924     onLayout: function(container, target) {
7925         Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);
7926
7927         var tSize = this.getLayoutTargetSize(),
7928             items = this.getVisibleItems(container),
7929             calcs = this.calculateChildBoxes(items, tSize),
7930             boxes = calcs.boxes,
7931             meta  = calcs.meta;
7932         
7933         //invoke the overflow handler, if one is configured
7934         if (tSize.width > 0) {
7935             var handler = this.overflowHandler,
7936                 method  = meta.tooNarrow ? 'handleOverflow' : 'clearOverflow';
7937             
7938             var results = handler[method](calcs, tSize);
7939             
7940             if (results) {
7941                 if (results.targetSize) {
7942                     tSize = results.targetSize;
7943                 }
7944                 
7945                 if (results.recalculate) {
7946                     items = this.getVisibleItems(container);
7947                     calcs = this.calculateChildBoxes(items, tSize);
7948                     boxes = calcs.boxes;
7949                 }
7950             }
7951         }
7952         
7953         /**
7954          * @private
7955          * @property layoutTargetLastSize
7956          * @type Object
7957          * Private cache of the last measured size of the layout target. This should never be used except by
7958          * BoxLayout subclasses during their onLayout run.
7959          */
7960         this.layoutTargetLastSize = tSize;
7961         
7962         /**
7963          * @private
7964          * @property childBoxCache
7965          * @type Array
7966          * Array of the last calculated height, width, top and left positions of each visible rendered component
7967          * within the Box layout.
7968          */
7969         this.childBoxCache = calcs;
7970         
7971         this.updateInnerCtSize(tSize, calcs);
7972         this.updateChildBoxes(boxes);
7973
7974         // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
7975         this.handleTargetOverflow(tSize, container, target);
7976     },
7977
7978     /**
7979      * Resizes and repositions each child component
7980      * @param {Array} boxes The box measurements
7981      */
7982     updateChildBoxes: function(boxes) {
7983         for (var i = 0, length = boxes.length; i < length; i++) {
7984             var box  = boxes[i],
7985                 comp = box.component;
7986             
7987             if (box.dirtySize) {
7988                 comp.setSize(box.width, box.height);
7989             }
7990             // Don't set positions to NaN
7991             if (isNaN(box.left) || isNaN(box.top)) {
7992                 continue;
7993             }
7994             
7995             comp.setPosition(box.left, box.top);
7996         }
7997     },
7998
7999     /**
8000      * @private
8001      * Called by onRender just before the child components are sized and positioned. This resizes the innerCt
8002      * to make sure all child items fit within it. We call this before sizing the children because if our child
8003      * items are larger than the previous innerCt size the browser will insert scrollbars and then remove them
8004      * again immediately afterwards, giving a performance hit.
8005      * Subclasses should provide an implementation.
8006      * @param {Object} currentSize The current height and width of the innerCt
8007      * @param {Array} calculations The new box calculations of all items to be laid out
8008      */
8009     updateInnerCtSize: function(tSize, calcs) {
8010         var align   = this.align,
8011             padding = this.padding,
8012             width   = tSize.width,
8013             height  = tSize.height;
8014         
8015         if (this.type == 'hbox') {
8016             var innerCtWidth  = width,
8017                 innerCtHeight = calcs.meta.maxHeight + padding.top + padding.bottom;
8018
8019             if (align == 'stretch') {
8020                 innerCtHeight = height;
8021             } else if (align == 'middle') {
8022                 innerCtHeight = Math.max(height, innerCtHeight);
8023             }
8024         } else {
8025             var innerCtHeight = height,
8026                 innerCtWidth  = calcs.meta.maxWidth + padding.left + padding.right;
8027
8028             if (align == 'stretch') {
8029                 innerCtWidth = width;
8030             } else if (align == 'center') {
8031                 innerCtWidth = Math.max(width, innerCtWidth);
8032             }
8033         }
8034
8035         this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
8036     },
8037
8038     /**
8039      * @private
8040      * This should be called after onLayout of any BoxLayout subclass. If the target's overflow is not set to 'hidden',
8041      * we need to lay out a second time because the scrollbars may have modified the height and width of the layout
8042      * target. Having a Box layout inside such a target is therefore not recommended.
8043      * @param {Object} previousTargetSize The size and height of the layout target before we just laid out
8044      * @param {Ext.Container} container The container
8045      * @param {Ext.Element} target The target element
8046      */
8047     handleTargetOverflow: function(previousTargetSize, container, target) {
8048         var overflow = target.getStyle('overflow');
8049
8050         if (overflow && overflow != 'hidden' &&!this.adjustmentPass) {
8051             var newTargetSize = this.getLayoutTargetSize();
8052             if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){
8053                 this.adjustmentPass = true;
8054                 this.onLayout(container, target);
8055             }
8056         }
8057
8058         delete this.adjustmentPass;
8059     },
8060
8061     // private
8062     isValidParent : function(c, target) {
8063         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
8064     },
8065
8066     /**
8067      * @private
8068      * Returns all items that are both rendered and visible
8069      * @return {Array} All matching items
8070      */
8071     getVisibleItems: function(ct) {
8072         var ct  = ct || this.container,
8073             t   = ct.getLayoutTarget(),
8074             cti = ct.items.items,
8075             len = cti.length,
8076
8077             i, c, items = [];
8078
8079         for (i = 0; i < len; i++) {
8080             if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true  && c.collapsed !== true && c.shouldLayout !== false){
8081                 items.push(c);
8082             }
8083         }
8084
8085         return items;
8086     },
8087
8088     // private
8089     renderAll : function(ct, target) {
8090         if (!this.innerCt) {
8091             // the innerCt prevents wrapping and shuffling while the container is resizing
8092             this.innerCt = target.createChild({cls:this.innerCls});
8093             this.padding = this.parseMargins(this.padding);
8094         }
8095         Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
8096     },
8097
8098     getLayoutTargetSize : function() {
8099         var target = this.container.getLayoutTarget(), ret;
8100         
8101         if (target) {
8102             ret = target.getViewSize();
8103
8104             // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
8105             // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
8106             // with getViewSize
8107             if (Ext.isIE && Ext.isStrict && ret.width == 0){
8108                 ret =  target.getStyleSize();
8109             }
8110
8111             ret.width  -= target.getPadding('lr');
8112             ret.height -= target.getPadding('tb');
8113         }
8114         
8115         return ret;
8116     },
8117
8118     // private
8119     renderItem : function(c) {
8120         if(Ext.isString(c.margins)){
8121             c.margins = this.parseMargins(c.margins);
8122         }else if(!c.margins){
8123             c.margins = this.defaultMargins;
8124         }
8125         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
8126     },
8127     
8128     /**
8129      * @private
8130      */
8131     destroy: function() {
8132         Ext.destroy(this.overflowHandler);
8133         
8134         Ext.layout.BoxLayout.superclass.destroy.apply(this, arguments);
8135     }
8136 });
8137
8138
8139
8140 Ext.ns('Ext.layout.boxOverflow');
8141
8142 /**
8143  * @class Ext.layout.boxOverflow.None
8144  * @extends Object
8145  * Base class for Box Layout overflow handlers. These specialized classes are invoked when a Box Layout
8146  * (either an HBox or a VBox) has child items that are either too wide (for HBox) or too tall (for VBox)
8147  * for its container.
8148  */
8149
8150 Ext.layout.boxOverflow.None = Ext.extend(Object, {
8151     constructor: function(layout, config) {
8152         this.layout = layout;
8153         
8154         Ext.apply(this, config || {});
8155     },
8156     
8157     handleOverflow: Ext.emptyFn,
8158     
8159     clearOverflow: Ext.emptyFn
8160 });
8161
8162
8163 Ext.layout.boxOverflow.none = Ext.layout.boxOverflow.None;
8164 /**
8165  * @class Ext.layout.boxOverflow.Menu
8166  * @extends Ext.layout.boxOverflow.None
8167  * Description
8168  */
8169 Ext.layout.boxOverflow.Menu = Ext.extend(Ext.layout.boxOverflow.None, {
8170     /**
8171      * @cfg afterCls
8172      * @type String
8173      * CSS class added to the afterCt element. This is the element that holds any special items such as scrollers,
8174      * which must always be present at the rightmost edge of the Container
8175      */
8176     afterCls: 'x-strip-right',
8177     
8178     /**
8179      * @property noItemsMenuText
8180      * @type String
8181      * HTML fragment to render into the toolbar overflow menu if there are no items to display
8182      */
8183     noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
8184     
8185     constructor: function(layout) {
8186         Ext.layout.boxOverflow.Menu.superclass.constructor.apply(this, arguments);
8187         
8188         /**
8189          * @property menuItems
8190          * @type Array
8191          * Array of all items that are currently hidden and should go into the dropdown menu
8192          */
8193         this.menuItems = [];
8194     },
8195     
8196     /**
8197      * @private
8198      * Creates the beforeCt, innerCt and afterCt elements if they have not already been created
8199      * @param {Ext.Container} container The Container attached to this Layout instance
8200      * @param {Ext.Element} target The target Element
8201      */
8202     createInnerElements: function() {
8203         if (!this.afterCt) {
8204             this.afterCt  = this.layout.innerCt.insertSibling({cls: this.afterCls},  'before');
8205         }
8206     },
8207     
8208     /**
8209      * @private
8210      */
8211     clearOverflow: function(calculations, targetSize) {
8212         var newWidth = targetSize.width + (this.afterCt ? this.afterCt.getWidth() : 0),
8213             items    = this.menuItems;
8214         
8215         this.hideTrigger();
8216         
8217         for (var index = 0, length = items.length; index < length; index++) {
8218             items.pop().component.show();
8219         }
8220         
8221         return {
8222             targetSize: {
8223                 height: targetSize.height,
8224                 width : newWidth
8225             }
8226         };
8227     },
8228     
8229     /**
8230      * @private
8231      */
8232     showTrigger: function() {
8233         this.createMenu();
8234         this.menuTrigger.show();
8235     },
8236     
8237     /**
8238      * @private
8239      */
8240     hideTrigger: function() {
8241         if (this.menuTrigger != undefined) {
8242             this.menuTrigger.hide();
8243         }
8244     },
8245     
8246     /**
8247      * @private
8248      * Called before the overflow menu is shown. This constructs the menu's items, caching them for as long as it can.
8249      */
8250     beforeMenuShow: function(menu) {
8251         var items = this.menuItems,
8252             len   = items.length,
8253             item,
8254             prev;
8255
8256         var needsSep = function(group, item){
8257             return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
8258         };
8259         
8260         this.clearMenu();
8261         menu.removeAll();
8262         
8263         for (var i = 0; i < len; i++) {
8264             item = items[i].component;
8265             
8266             if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
8267                 menu.add('-');
8268             }
8269             
8270             this.addComponentToMenu(menu, item);
8271             prev = item;
8272         }
8273
8274         // put something so the menu isn't empty if no compatible items found
8275         if (menu.items.length < 1) {
8276             menu.add(this.noItemsMenuText);
8277         }
8278     },
8279     
8280     /**
8281      * @private
8282      * Returns a menu config for a given component. This config is used to create a menu item
8283      * to be added to the expander menu
8284      * @param {Ext.Component} component The component to create the config for
8285      * @param {Boolean} hideOnClick Passed through to the menu item
8286      */
8287     createMenuConfig : function(component, hideOnClick){
8288         var config = Ext.apply({}, component.initialConfig),
8289             group  = component.toggleGroup;
8290
8291         Ext.copyTo(config, component, [
8292             'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
8293         ]);
8294
8295         Ext.apply(config, {
8296             text       : component.overflowText || component.text,
8297             hideOnClick: hideOnClick
8298         });
8299
8300         if (group || component.enableToggle) {
8301             Ext.apply(config, {
8302                 group  : group,
8303                 checked: component.pressed,
8304                 listeners: {
8305                     checkchange: function(item, checked){
8306                         component.toggle(checked);
8307                     }
8308                 }
8309             });
8310         }
8311
8312         delete config.ownerCt;
8313         delete config.xtype;
8314         delete config.id;
8315
8316         return config;
8317     },
8318
8319     /**
8320      * @private
8321      * Adds the given Toolbar item to the given menu. Buttons inside a buttongroup are added individually.
8322      * @param {Ext.menu.Menu} menu The menu to add to
8323      * @param {Ext.Component} component The component to add
8324      */
8325     addComponentToMenu : function(menu, component) {
8326         if (component instanceof Ext.Toolbar.Separator) {
8327             menu.add('-');
8328
8329         } else if (Ext.isFunction(component.isXType)) {
8330             if (component.isXType('splitbutton')) {
8331                 menu.add(this.createMenuConfig(component, true));
8332
8333             } else if (component.isXType('button')) {
8334                 menu.add(this.createMenuConfig(component, !component.menu));
8335
8336             } else if (component.isXType('buttongroup')) {
8337                 component.items.each(function(item){
8338                      this.addComponentToMenu(menu, item);
8339                 }, this);
8340             }
8341         }
8342     },
8343     
8344     /**
8345      * @private
8346      * Deletes the sub-menu of each item in the expander menu. Submenus are created for items such as
8347      * splitbuttons and buttongroups, where the Toolbar item cannot be represented by a single menu item
8348      */
8349     clearMenu : function(){
8350         var menu = this.moreMenu;
8351         if (menu && menu.items) {
8352             menu.items.each(function(item){
8353                 delete item.menu;
8354             });
8355         }
8356     },
8357     
8358     /**
8359      * @private
8360      * Creates the overflow trigger and menu used when enableOverflow is set to true and the items
8361      * in the layout are too wide to fit in the space available
8362      */
8363     createMenu: function() {
8364         if (!this.menuTrigger) {
8365             this.createInnerElements();
8366             
8367             /**
8368              * @private
8369              * @property menu
8370              * @type Ext.menu.Menu
8371              * The expand menu - holds items for every item that cannot be shown
8372              * because the container is currently not large enough.
8373              */
8374             this.menu = new Ext.menu.Menu({
8375                 ownerCt : this.layout.container,
8376                 listeners: {
8377                     scope: this,
8378                     beforeshow: this.beforeMenuShow
8379                 }
8380             });
8381
8382             /**
8383              * @private
8384              * @property menuTrigger
8385              * @type Ext.Button
8386              * The expand button which triggers the overflow menu to be shown
8387              */
8388             this.menuTrigger = new Ext.Button({
8389                 iconCls : 'x-toolbar-more-icon',
8390                 cls     : 'x-toolbar-more',
8391                 menu    : this.menu,
8392                 renderTo: this.afterCt
8393             });
8394         }
8395     },
8396     
8397     /**
8398      * @private
8399      */
8400     destroy: function() {
8401         Ext.destroy(this.menu, this.menuTrigger);
8402     }
8403 });
8404
8405 Ext.layout.boxOverflow.menu = Ext.layout.boxOverflow.Menu;
8406
8407
8408 /**
8409  * @class Ext.layout.boxOverflow.HorizontalMenu
8410  * @extends Ext.layout.boxOverflow.Menu
8411  * Description
8412  */
8413 Ext.layout.boxOverflow.HorizontalMenu = Ext.extend(Ext.layout.boxOverflow.Menu, {
8414     
8415     constructor: function() {
8416         Ext.layout.boxOverflow.HorizontalMenu.superclass.constructor.apply(this, arguments);
8417         
8418         var me = this,
8419             layout = me.layout,
8420             origFunction = layout.calculateChildBoxes;
8421         
8422         layout.calculateChildBoxes = function(visibleItems, targetSize) {
8423             var calcs = origFunction.apply(layout, arguments),
8424                 meta  = calcs.meta,
8425                 items = me.menuItems;
8426             
8427             //calculate the width of the items currently hidden solely because there is not enough space
8428             //to display them
8429             var hiddenWidth = 0;
8430             for (var index = 0, length = items.length; index < length; index++) {
8431                 hiddenWidth += items[index].width;
8432             }
8433             
8434             meta.minimumWidth += hiddenWidth;
8435             meta.tooNarrow = meta.minimumWidth > targetSize.width;
8436             
8437             return calcs;
8438         };        
8439     },
8440     
8441     handleOverflow: function(calculations, targetSize) {
8442         this.showTrigger();
8443         
8444         var newWidth    = targetSize.width - this.afterCt.getWidth(),
8445             boxes       = calculations.boxes,
8446             usedWidth   = 0,
8447             recalculate = false;
8448         
8449         //calculate the width of all visible items and any spare width
8450         for (var index = 0, length = boxes.length; index < length; index++) {
8451             usedWidth += boxes[index].width;
8452         }
8453         
8454         var spareWidth = newWidth - usedWidth,
8455             showCount  = 0;
8456         
8457         //see if we can re-show any of the hidden components
8458         for (var index = 0, length = this.menuItems.length; index < length; index++) {
8459             var hidden = this.menuItems[index],
8460                 comp   = hidden.component,
8461                 width  = hidden.width;
8462             
8463             if (width < spareWidth) {
8464                 comp.show();
8465                 
8466                 spareWidth -= width;
8467                 showCount ++;
8468                 recalculate = true;
8469             } else {
8470                 break;
8471             }
8472         }
8473                 
8474         if (recalculate) {
8475             this.menuItems = this.menuItems.slice(showCount);
8476         } else {
8477             for (var i = boxes.length - 1; i >= 0; i--) {
8478                 var item  = boxes[i].component,
8479                     right = boxes[i].left + boxes[i].width;
8480
8481                 if (right >= newWidth) {
8482                     this.menuItems.unshift({
8483                         component: item,
8484                         width    : boxes[i].width
8485                     });
8486
8487                     item.hide();
8488                 } else {
8489                     break;
8490                 }
8491             }
8492         }
8493         
8494         if (this.menuItems.length == 0) {
8495             this.hideTrigger();
8496         }
8497         
8498         return {
8499             targetSize: {
8500                 height: targetSize.height,
8501                 width : newWidth
8502             },
8503             recalculate: recalculate
8504         };
8505     }
8506 });
8507
8508 Ext.layout.boxOverflow.menu.hbox = Ext.layout.boxOverflow.HorizontalMenu;/**
8509  * @class Ext.layout.boxOverflow.Scroller
8510  * @extends Ext.layout.boxOverflow.None
8511  * Description
8512  */
8513 Ext.layout.boxOverflow.Scroller = Ext.extend(Ext.layout.boxOverflow.None, {
8514     /**
8515      * @cfg animateScroll
8516      * @type Boolean
8517      * True to animate the scrolling of items within the layout (defaults to true, ignored if enableScroll is false)
8518      */
8519     animateScroll: true,
8520     
8521     /**
8522      * @cfg scrollIncrement
8523      * @type Number
8524      * The number of pixels to scroll by on scroller click (defaults to 100)
8525      */
8526     scrollIncrement: 100,
8527     
8528     /**
8529      * @cfg wheelIncrement
8530      * @type Number
8531      * The number of pixels to increment on mouse wheel scrolling (defaults to <tt>3</tt>).
8532      */
8533     wheelIncrement: 3,
8534     
8535     /**
8536      * @cfg scrollRepeatInterval
8537      * @type Number
8538      * Number of milliseconds between each scroll while a scroller button is held down (defaults to 400)
8539      */
8540     scrollRepeatInterval: 400,
8541     
8542     /**
8543      * @cfg scrollDuration
8544      * @type Number
8545      * Number of seconds that each scroll animation lasts (defaults to 0.4)
8546      */
8547     scrollDuration: 0.4,
8548     
8549     /**
8550      * @cfg beforeCls
8551      * @type String
8552      * CSS class added to the beforeCt element. This is the element that holds any special items such as scrollers,
8553      * which must always be present at the leftmost edge of the Container
8554      */
8555     beforeCls: 'x-strip-left',
8556     
8557     /**
8558      * @cfg afterCls
8559      * @type String
8560      * CSS class added to the afterCt element. This is the element that holds any special items such as scrollers,
8561      * which must always be present at the rightmost edge of the Container
8562      */
8563     afterCls: 'x-strip-right',
8564     
8565     /**
8566      * @cfg scrollerCls
8567      * @type String
8568      * CSS class added to both scroller elements if enableScroll is used
8569      */
8570     scrollerCls: 'x-strip-scroller',
8571     
8572     /**
8573      * @cfg beforeScrollerCls
8574      * @type String
8575      * CSS class added to the left scroller element if enableScroll is used
8576      */
8577     beforeScrollerCls: 'x-strip-scroller-left',
8578     
8579     /**
8580      * @cfg afterScrollerCls
8581      * @type String
8582      * CSS class added to the right scroller element if enableScroll is used
8583      */
8584     afterScrollerCls: 'x-strip-scroller-right',
8585     
8586     /**
8587      * @private
8588      * Sets up an listener to scroll on the layout's innerCt mousewheel event
8589      */
8590     createWheelListener: function() {
8591         this.layout.innerCt.on({
8592             scope     : this,
8593             mousewheel: function(e) {
8594                 e.stopEvent();
8595
8596                 this.scrollBy(e.getWheelDelta() * this.wheelIncrement * -1, false);
8597             }
8598         });
8599     },
8600     
8601     /**
8602      * @private
8603      * Most of the heavy lifting is done in the subclasses
8604      */
8605     handleOverflow: function(calculations, targetSize) {
8606         this.createInnerElements();
8607         this.showScrollers();
8608     },
8609     
8610     /**
8611      * @private
8612      */
8613     clearOverflow: function() {
8614         this.hideScrollers();
8615     },
8616     
8617     /**
8618      * @private
8619      * Shows the scroller elements in the beforeCt and afterCt. Creates the scrollers first if they are not already
8620      * present. 
8621      */
8622     showScrollers: function() {
8623         this.createScrollers();
8624         
8625         this.beforeScroller.show();
8626         this.afterScroller.show();
8627         
8628         this.updateScrollButtons();
8629     },
8630     
8631     /**
8632      * @private
8633      * Hides the scroller elements in the beforeCt and afterCt
8634      */
8635     hideScrollers: function() {
8636         if (this.beforeScroller != undefined) {
8637             this.beforeScroller.hide();
8638             this.afterScroller.hide();          
8639         }
8640     },
8641     
8642     /**
8643      * @private
8644      * Creates the clickable scroller elements and places them into the beforeCt and afterCt
8645      */
8646     createScrollers: function() {
8647         if (!this.beforeScroller && !this.afterScroller) {
8648             var before = this.beforeCt.createChild({
8649                 cls: String.format("{0} {1} ", this.scrollerCls, this.beforeScrollerCls)
8650             });
8651             
8652             var after = this.afterCt.createChild({
8653                 cls: String.format("{0} {1}", this.scrollerCls, this.afterScrollerCls)
8654             });
8655             
8656             before.addClassOnOver(this.beforeScrollerCls + '-hover');
8657             after.addClassOnOver(this.afterScrollerCls + '-hover');
8658             
8659             before.setVisibilityMode(Ext.Element.DISPLAY);
8660             after.setVisibilityMode(Ext.Element.DISPLAY);
8661             
8662             this.beforeRepeater = new Ext.util.ClickRepeater(before, {
8663                 interval: this.scrollRepeatInterval,
8664                 handler : this.scrollLeft,
8665                 scope   : this
8666             });
8667             
8668             this.afterRepeater = new Ext.util.ClickRepeater(after, {
8669                 interval: this.scrollRepeatInterval,
8670                 handler : this.scrollRight,
8671                 scope   : this
8672             });
8673             
8674             /**
8675              * @property beforeScroller
8676              * @type Ext.Element
8677              * The left scroller element. Only created when needed.
8678              */
8679             this.beforeScroller = before;
8680             
8681             /**
8682              * @property afterScroller
8683              * @type Ext.Element
8684              * The left scroller element. Only created when needed.
8685              */
8686             this.afterScroller = after;
8687         }
8688     },
8689     
8690     /**
8691      * @private
8692      */
8693     destroy: function() {
8694         Ext.destroy(this.beforeScroller, this.afterScroller, this.beforeRepeater, this.afterRepeater, this.beforeCt, this.afterCt);
8695     },
8696     
8697     /**
8698      * @private
8699      * Scrolls left or right by the number of pixels specified
8700      * @param {Number} delta Number of pixels to scroll to the right by. Use a negative number to scroll left
8701      */
8702     scrollBy: function(delta, animate) {
8703         this.scrollTo(this.getScrollPosition() + delta, animate);
8704     },
8705     
8706     /**
8707      * @private
8708      * Normalizes an item reference, string id or numerical index into a reference to the item
8709      * @param {Ext.Component|String|Number} item The item reference, id or index
8710      * @return {Ext.Component} The item
8711      */
8712     getItem: function(item) {
8713         if (Ext.isString(item)) {
8714             item = Ext.getCmp(item);
8715         } else if (Ext.isNumber(item)) {
8716             item = this.items[item];
8717         }
8718         
8719         return item;
8720     },
8721     
8722     /**
8723      * @private
8724      * @return {Object} Object passed to scrollTo when scrolling
8725      */
8726     getScrollAnim: function() {
8727         return {
8728             duration: this.scrollDuration, 
8729             callback: this.updateScrollButtons, 
8730             scope   : this
8731         };
8732     },
8733     
8734     /**
8735      * @private
8736      * Enables or disables each scroller button based on the current scroll position
8737      */
8738     updateScrollButtons: function() {
8739         if (this.beforeScroller == undefined || this.afterScroller == undefined) {
8740             return;
8741         }
8742         
8743         var beforeMeth = this.atExtremeBefore()  ? 'addClass' : 'removeClass',
8744             afterMeth  = this.atExtremeAfter() ? 'addClass' : 'removeClass',
8745             beforeCls  = this.beforeScrollerCls + '-disabled',
8746             afterCls   = this.afterScrollerCls  + '-disabled';
8747         
8748         this.beforeScroller[beforeMeth](beforeCls);
8749         this.afterScroller[afterMeth](afterCls);
8750         this.scrolling = false;
8751     },
8752     
8753     /**
8754      * @private
8755      * Returns true if the innerCt scroll is already at its left-most point
8756      * @return {Boolean} True if already at furthest left point
8757      */
8758     atExtremeBefore: function() {
8759         return this.getScrollPosition() === 0;
8760     },
8761     
8762     /**
8763      * @private
8764      * Scrolls to the left by the configured amount
8765      */
8766     scrollLeft: function(animate) {
8767         this.scrollBy(-this.scrollIncrement, animate);
8768     },
8769     
8770     /**
8771      * @private
8772      * Scrolls to the right by the configured amount
8773      */
8774     scrollRight: function(animate) {
8775         this.scrollBy(this.scrollIncrement, animate);
8776     },
8777     
8778     /**
8779      * Scrolls to the given component.
8780      * @param {String|Number|Ext.Component} item The item to scroll to. Can be a numerical index, component id 
8781      * or a reference to the component itself.
8782      * @param {Boolean} animate True to animate the scrolling
8783      */
8784     scrollToItem: function(item, animate) {
8785         item = this.getItem(item);
8786         
8787         if (item != undefined) {
8788             var visibility = this.getItemVisibility(item);
8789             
8790             if (!visibility.fullyVisible) {
8791                 var box  = item.getBox(true, true),
8792                     newX = box.x;
8793                     
8794                 if (visibility.hiddenRight) {
8795                     newX -= (this.layout.innerCt.getWidth() - box.width);
8796                 }
8797                 
8798                 this.scrollTo(newX, animate);
8799             }
8800         }
8801     },
8802     
8803     /**
8804      * @private
8805      * For a given item in the container, return an object with information on whether the item is visible
8806      * with the current innerCt scroll value.
8807      * @param {Ext.Component} item The item
8808      * @return {Object} Values for fullyVisible, hiddenLeft and hiddenRight
8809      */
8810     getItemVisibility: function(item) {
8811         var box         = this.getItem(item).getBox(true, true),
8812             itemLeft    = box.x,
8813             itemRight   = box.x + box.width,
8814             scrollLeft  = this.getScrollPosition(),
8815             scrollRight = this.layout.innerCt.getWidth() + scrollLeft;
8816         
8817         return {
8818             hiddenLeft  : itemLeft < scrollLeft,
8819             hiddenRight : itemRight > scrollRight,
8820             fullyVisible: itemLeft > scrollLeft && itemRight < scrollRight
8821         };
8822     }
8823 });
8824
8825 Ext.layout.boxOverflow.scroller = Ext.layout.boxOverflow.Scroller;
8826
8827
8828 /**\r
8829  * @class Ext.layout.boxOverflow.VerticalScroller\r
8830  * @extends Ext.layout.boxOverflow.Scroller\r
8831  * Description\r
8832  */\r
8833 Ext.layout.boxOverflow.VerticalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
8834     scrollIncrement: 75,
8835     wheelIncrement : 2,
8836     
8837     handleOverflow: function(calculations, targetSize) {
8838         Ext.layout.boxOverflow.VerticalScroller.superclass.handleOverflow.apply(this, arguments);
8839         
8840         return {
8841             targetSize: {
8842                 height: targetSize.height - (this.beforeCt.getHeight() + this.afterCt.getHeight()),
8843                 width : targetSize.width
8844             }
8845         };
8846     },
8847     
8848     /**
8849      * @private
8850      * Creates the beforeCt and afterCt elements if they have not already been created
8851      */
8852     createInnerElements: function() {
8853         var target = this.layout.innerCt;
8854         
8855         //normal items will be rendered to the innerCt. beforeCt and afterCt allow for fixed positioning of
8856         //special items such as scrollers or dropdown menu triggers
8857         if (!this.beforeCt) {
8858             this.beforeCt = target.insertSibling({cls: this.beforeCls}, 'before');
8859             this.afterCt  = target.insertSibling({cls: this.afterCls},  'after');
8860
8861             this.createWheelListener();
8862         }
8863     },
8864     
8865     /**
8866      * @private
8867      * Scrolls to the given position. Performs bounds checking.
8868      * @param {Number} position The position to scroll to. This is constrained.
8869      * @param {Boolean} animate True to animate. If undefined, falls back to value of this.animateScroll
8870      */
8871     scrollTo: function(position, animate) {
8872         var oldPosition = this.getScrollPosition(),
8873             newPosition = position.constrain(0, this.getMaxScrollBottom());
8874         
8875         if (newPosition != oldPosition && !this.scrolling) {
8876             if (animate == undefined) {
8877                 animate = this.animateScroll;
8878             }
8879             
8880             this.layout.innerCt.scrollTo('top', newPosition, animate ? this.getScrollAnim() : false);
8881             
8882             if (animate) {
8883                 this.scrolling = true;
8884             } else {
8885                 this.scrolling = false;
8886                 this.updateScrollButtons();
8887             }
8888         }
8889     },
8890     
8891     /**
8892      * Returns the current scroll position of the innerCt element
8893      * @return {Number} The current scroll position
8894      */
8895     getScrollPosition: function(){
8896         return parseInt(this.layout.innerCt.dom.scrollTop, 10) || 0;
8897     },
8898     
8899     /**
8900      * @private
8901      * Returns the maximum value we can scrollTo
8902      * @return {Number} The max scroll value
8903      */
8904     getMaxScrollBottom: function() {
8905         return this.layout.innerCt.dom.scrollHeight - this.layout.innerCt.getHeight();
8906     },
8907     
8908     /**
8909      * @private
8910      * Returns true if the innerCt scroll is already at its right-most point
8911      * @return {Boolean} True if already at furthest right point
8912      */
8913     atExtremeAfter: function() {
8914         return this.getScrollPosition() >= this.getMaxScrollBottom();
8915     }
8916 });
8917
8918 Ext.layout.boxOverflow.scroller.vbox = Ext.layout.boxOverflow.VerticalScroller;
8919
8920
8921 /**
8922  * @class Ext.layout.boxOverflow.HorizontalScroller
8923  * @extends Ext.layout.boxOverflow.Scroller
8924  * Description
8925  */
8926 Ext.layout.boxOverflow.HorizontalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
8927     handleOverflow: function(calculations, targetSize) {
8928         Ext.layout.boxOverflow.HorizontalScroller.superclass.handleOverflow.apply(this, arguments);
8929         
8930         return {
8931             targetSize: {
8932                 height: targetSize.height,
8933                 width : targetSize.width - (this.beforeCt.getWidth() + this.afterCt.getWidth())
8934             }
8935         };
8936     },
8937     
8938     /**
8939      * @private
8940      * Creates the beforeCt and afterCt elements if they have not already been created
8941      */
8942     createInnerElements: function() {
8943         var target = this.layout.innerCt;
8944         
8945         //normal items will be rendered to the innerCt. beforeCt and afterCt allow for fixed positioning of
8946         //special items such as scrollers or dropdown menu triggers
8947         if (!this.beforeCt) {
8948             this.afterCt  = target.insertSibling({cls: this.afterCls},  'before');
8949             this.beforeCt = target.insertSibling({cls: this.beforeCls}, 'before');
8950             
8951             this.createWheelListener();
8952         }
8953     },
8954     
8955     /**
8956      * @private
8957      * Scrolls to the given position. Performs bounds checking.
8958      * @param {Number} position The position to scroll to. This is constrained.
8959      * @param {Boolean} animate True to animate. If undefined, falls back to value of this.animateScroll
8960      */
8961     scrollTo: function(position, animate) {
8962         var oldPosition = this.getScrollPosition(),
8963             newPosition = position.constrain(0, this.getMaxScrollRight());
8964         
8965         if (newPosition != oldPosition && !this.scrolling) {
8966             if (animate == undefined) {
8967                 animate = this.animateScroll;
8968             }
8969             
8970             this.layout.innerCt.scrollTo('left', newPosition, animate ? this.getScrollAnim() : false);
8971             
8972             if (animate) {
8973                 this.scrolling = true;
8974             } else {
8975                 this.scrolling = false;
8976                 this.updateScrollButtons();
8977             }
8978         }
8979     },
8980     
8981     /**
8982      * Returns the current scroll position of the innerCt element
8983      * @return {Number} The current scroll position
8984      */
8985     getScrollPosition: function(){
8986         return parseInt(this.layout.innerCt.dom.scrollLeft, 10) || 0;
8987     },
8988     
8989     /**
8990      * @private
8991      * Returns the maximum value we can scrollTo
8992      * @return {Number} The max scroll value
8993      */
8994     getMaxScrollRight: function() {
8995         return this.layout.innerCt.dom.scrollWidth - this.layout.innerCt.getWidth();
8996     },
8997     
8998     /**
8999      * @private
9000      * Returns true if the innerCt scroll is already at its right-most point
9001      * @return {Boolean} True if already at furthest right point
9002      */
9003     atExtremeAfter: function() {
9004         return this.getScrollPosition() >= this.getMaxScrollRight();
9005     }
9006 });
9007
9008 Ext.layout.boxOverflow.scroller.hbox = Ext.layout.boxOverflow.HorizontalScroller;/**
9009  * @class Ext.layout.HBoxLayout
9010  * @extends Ext.layout.BoxLayout
9011  * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal
9012  * space between child items containing a numeric <code>flex</code> configuration.</p>
9013  * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option.
9014  */
9015 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
9016     /**
9017      * @cfg {String} align
9018      * Controls how the child items of the container are aligned. Acceptable configuration values for this
9019      * property are:
9020      * <div class="mdetail-params"><ul>
9021      * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically
9022      * at the <b>top</b> of the container</div></li>
9023      * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically in the
9024      * <b>middle</b> of the container</div></li>
9025      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill
9026      * the height of the container</div></li>
9027      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to
9028      * the height of the largest item.</div></li>
9029      */
9030     align: 'top', // top, middle, stretch, strechmax
9031
9032     type : 'hbox',
9033
9034     /**
9035      * @cfg {String} pack
9036      * Controls how the child items of the container are packed together. Acceptable configuration values
9037      * for this property are:
9038      * <div class="mdetail-params"><ul>
9039      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
9040      * <b>left</b> side of container</div></li>
9041      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
9042      * <b>mid-width</b> of container</div></li>
9043      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>
9044      * side of container</div></li>
9045      * </ul></div>
9046      */
9047     /**
9048      * @cfg {Number} flex
9049      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
9050      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>
9051      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
9052      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
9053      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
9054      */
9055
9056     /**
9057      * @private
9058      * Calculates the size and positioning of each item in the HBox. This iterates over all of the rendered,
9059      * visible items and returns a height, width, top and left for each, as well as a reference to each. Also
9060      * returns meta data such as maxHeight which are useful when resizing layout wrappers such as this.innerCt.
9061      * @param {Array} visibleItems The array of all rendered, visible items to be calculated for
9062      * @param {Object} targetSize Object containing target size and height
9063      * @return {Object} Object containing box measurements for each child, plus meta data
9064      */
9065     calculateChildBoxes: function(visibleItems, targetSize) {
9066         var visibleCount = visibleItems.length,
9067
9068             padding      = this.padding,
9069             topOffset    = padding.top,
9070             leftOffset   = padding.left,
9071             paddingVert  = topOffset  + padding.bottom,
9072             paddingHoriz = leftOffset + padding.right,
9073
9074             width        = targetSize.width - this.scrollOffset,
9075             height       = targetSize.height,
9076             availHeight  = Math.max(0, height - paddingVert),
9077
9078             isStart      = this.pack == 'start',
9079             isCenter     = this.pack == 'center',
9080             isEnd        = this.pack == 'end',
9081
9082             nonFlexWidth = 0,
9083             maxHeight    = 0,
9084             totalFlex    = 0,
9085             desiredWidth = 0,
9086             minimumWidth = 0,
9087
9088             //used to cache the calculated size and position values for each child item
9089             boxes        = [],
9090
9091             //used in the for loops below, just declared here for brevity
9092             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, 
9093             horizMargins, vertMargins, stretchHeight;
9094
9095         //gather the total flex of all flexed items and the width taken up by fixed width items
9096         for (i = 0; i < visibleCount; i++) {
9097             child       = visibleItems[i];
9098             childHeight = child.height;
9099             childWidth  = child.width;
9100             canLayout   = !child.hasLayout && typeof child.doLayout == 'function';
9101
9102             // Static width (numeric) requires no calcs
9103             if (typeof childWidth != 'number') {
9104
9105                 // flex and not 'auto' width
9106                 if (child.flex && !childWidth) {
9107                     totalFlex += child.flex;
9108
9109                 // Not flexed or 'auto' width or undefined width
9110                 } else {
9111                     //Render and layout sub-containers without a flex or width defined, as otherwise we
9112                     //don't know how wide the sub-container should be and cannot calculate flexed widths
9113                     if (!childWidth && canLayout) {
9114                         child.doLayout();
9115                     }
9116
9117                     childSize   = child.getSize();
9118                     childWidth  = childSize.width;
9119                     childHeight = childSize.height;
9120                 }
9121             }
9122
9123             childMargins = child.margins;
9124             horizMargins = childMargins.left + childMargins.right;
9125
9126             nonFlexWidth += horizMargins + (childWidth || 0);
9127             desiredWidth += horizMargins + (child.flex ? child.minWidth || 0 : childWidth);
9128             minimumWidth += horizMargins + (child.minWidth || childWidth || 0);
9129
9130             // Max height for align - force layout of non-laid out subcontainers without a numeric height
9131             if (typeof childHeight != 'number') {
9132                 if (canLayout) {
9133                     child.doLayout();
9134                 }
9135                 childHeight = child.getHeight();
9136             }
9137
9138             maxHeight = Math.max(maxHeight, childHeight + childMargins.top + childMargins.bottom);
9139
9140             //cache the size of each child component. Don't set height or width to 0, keep undefined instead
9141             boxes.push({
9142                 component: child,
9143                 height   : childHeight || undefined,
9144                 width    : childWidth  || undefined
9145             });
9146         }
9147                 
9148         var shortfall = desiredWidth - width,
9149             tooNarrow = minimumWidth > width;
9150             
9151         //the width available to the flexed items
9152         var availableWidth = Math.max(0, width - nonFlexWidth - paddingHoriz);
9153         
9154         if (tooNarrow) {
9155             for (i = 0; i < visibleCount; i++) {
9156                 boxes[i].width = visibleItems[i].minWidth || visibleItems[i].width || boxes[i].width;
9157             }
9158         } else {
9159             //all flexed items should be sized to their minimum width, other items should be shrunk down until
9160             //the shortfall has been accounted for
9161             if (shortfall > 0) {
9162                 var minWidths = [];
9163                 
9164                 /**
9165                  * When we have a shortfall but are not tooNarrow, we need to shrink the width of each non-flexed item.
9166                  * Flexed items are immediately reduced to their minWidth and anything already at minWidth is ignored.
9167                  * The remaining items are collected into the minWidths array, which is later used to distribute the shortfall.
9168                  */
9169                 for (var index = 0, length = visibleCount; index < length; index++) {
9170                     var item     = visibleItems[index],
9171                         minWidth = item.minWidth || 0;
9172
9173                     //shrink each non-flex tab by an equal amount to make them all fit. Flexed items are all
9174                     //shrunk to their minWidth because they're flexible and should be the first to lose width
9175                     if (item.flex) {
9176                         boxes[index].width = minWidth;
9177                     } else {
9178                         minWidths.push({
9179                             minWidth : minWidth,
9180                             available: boxes[index].width - minWidth,
9181                             index    : index
9182                         });
9183                     }
9184                 }
9185                 
9186                 //sort by descending amount of width remaining before minWidth is reached
9187                 minWidths.sort(function(a, b) {
9188                     return a.available > b.available ? 1 : -1;
9189                 });
9190                 
9191                 /*
9192                  * Distribute the shortfall (difference between total desired with of all items and actual width available)
9193                  * between the non-flexed items. We try to distribute the shortfall evenly, but apply it to items with the
9194                  * smallest difference between their width and minWidth first, so that if reducing the width by the average
9195                  * amount would make that item less than its minWidth, we carry the remainder over to the next item.
9196                  */
9197                 for (var i = 0, length = minWidths.length; i < length; i++) {
9198                     var itemIndex = minWidths[i].index;
9199                     
9200                     if (itemIndex == undefined) {
9201                         continue;
9202                     }
9203                         
9204                     var item      = visibleItems[itemIndex],
9205                         box       = boxes[itemIndex],
9206                         oldWidth  = box.width,
9207                         minWidth  = item.minWidth,
9208                         newWidth  = Math.max(minWidth, oldWidth - Math.ceil(shortfall / (length - i))),
9209                         reduction = oldWidth - newWidth;
9210                     
9211                     boxes[itemIndex].width = newWidth;
9212                     shortfall -= reduction;                    
9213                 }
9214             } else {
9215                 //temporary variables used in the flex width calculations below
9216                 var remainingWidth = availableWidth,
9217                     remainingFlex  = totalFlex;
9218
9219                 //calculate the widths of each flexed item
9220                 for (i = 0; i < visibleCount; i++) {
9221                     child = visibleItems[i];
9222                     calcs = boxes[i];
9223
9224                     childMargins = child.margins;
9225                     vertMargins  = childMargins.top + childMargins.bottom;
9226
9227                     if (isStart && child.flex && !child.width) {
9228                         flexedWidth     = Math.ceil((child.flex / remainingFlex) * remainingWidth);
9229                         remainingWidth -= flexedWidth;
9230                         remainingFlex  -= child.flex;
9231
9232                         calcs.width = flexedWidth;
9233                         calcs.dirtySize = true;
9234                     }
9235                 }
9236             }
9237         }
9238         
9239         if (isCenter) {
9240             leftOffset += availableWidth / 2;
9241         } else if (isEnd) {
9242             leftOffset += availableWidth;
9243         }
9244         
9245         //finally, calculate the left and top position of each item
9246         for (i = 0; i < visibleCount; i++) {
9247             child = visibleItems[i];
9248             calcs = boxes[i];
9249             
9250             childMargins = child.margins;
9251             leftOffset  += childMargins.left;
9252             vertMargins  = childMargins.top + childMargins.bottom;
9253             
9254             calcs.left = leftOffset;
9255             calcs.top  = topOffset + childMargins.top;
9256
9257             switch (this.align) {
9258                 case 'stretch':
9259                     stretchHeight = availHeight - vertMargins;
9260                     calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
9261                     calcs.dirtySize = true;
9262                     break;
9263                 case 'stretchmax':
9264                     stretchHeight = maxHeight - vertMargins;
9265                     calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
9266                     calcs.dirtySize = true;
9267                     break;
9268                 case 'middle':
9269                     var diff = availHeight - calcs.height - vertMargins;
9270                     if (diff > 0) {
9271                         calcs.top = topOffset + vertMargins + (diff / 2);
9272                     }
9273             }
9274             
9275             leftOffset += calcs.width + childMargins.right;
9276         }
9277
9278         return {
9279             boxes: boxes,
9280             meta : {
9281                 maxHeight   : maxHeight,
9282                 nonFlexWidth: nonFlexWidth,
9283                 desiredWidth: desiredWidth,
9284                 minimumWidth: minimumWidth,
9285                 shortfall   : desiredWidth - width,
9286                 tooNarrow   : tooNarrow
9287             }
9288         };
9289     }
9290 });
9291
9292 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;/**
9293  * @class Ext.layout.VBoxLayout
9294  * @extends Ext.layout.BoxLayout
9295  * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical
9296  * space between child items containing a numeric <code>flex</code> configuration.</p>
9297  * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option.
9298  */
9299 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
9300     /**
9301      * @cfg {String} align
9302      * Controls how the child items of the container are aligned. Acceptable configuration values for this
9303      * property are:
9304      * <div class="mdetail-params"><ul>
9305      * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally
9306      * at the <b>left</b> side of the container</div></li>
9307      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the
9308      * <b>mid-width</b> of the container</div></li>
9309      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill
9310      * the width of the container</div></li>
9311      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to
9312      * the size of the largest item.</div></li>
9313      * </ul></div>
9314      */
9315     align : 'left', // left, center, stretch, strechmax
9316     type: 'vbox',
9317
9318     /**
9319      * @cfg {String} pack
9320      * Controls how the child items of the container are packed together. Acceptable configuration values
9321      * for this property are:
9322      * <div class="mdetail-params"><ul>
9323      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
9324      * <b>top</b> side of container</div></li>
9325      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
9326      * <b>mid-height</b> of container</div></li>
9327      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>
9328      * side of container</div></li>
9329      * </ul></div>
9330      */
9331
9332     /**
9333      * @cfg {Number} flex
9334      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
9335      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>
9336      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
9337      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
9338      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
9339      */
9340
9341     /**
9342      * @private
9343      * Calculates the size and positioning of each item in the VBox. This iterates over all of the rendered,
9344      * visible items and returns a height, width, top and left for each, as well as a reference to each. Also
9345      * returns meta data such as maxHeight which are useful when resizing layout wrappers such as this.innerCt.
9346      * @param {Array} visibleItems The array of all rendered, visible items to be calculated for
9347      * @param {Object} targetSize Object containing target size and height
9348      * @return {Object} Object containing box measurements for each child, plus meta data
9349      */
9350     calculateChildBoxes: function(visibleItems, targetSize) {
9351         var visibleCount = visibleItems.length,
9352
9353             padding      = this.padding,
9354             topOffset    = padding.top,
9355             leftOffset   = padding.left,
9356             paddingVert  = topOffset  + padding.bottom,
9357             paddingHoriz = leftOffset + padding.right,
9358
9359             width        = targetSize.width - this.scrollOffset,
9360             height       = targetSize.height,
9361             availWidth   = Math.max(0, width - paddingHoriz),
9362
9363             isStart      = this.pack == 'start',
9364             isCenter     = this.pack == 'center',
9365             isEnd        = this.pack == 'end',
9366
9367             nonFlexHeight= 0,
9368             maxWidth     = 0,
9369             totalFlex    = 0,
9370             desiredHeight= 0,
9371             minimumHeight= 0,
9372
9373             //used to cache the calculated size and position values for each child item
9374             boxes        = [],
9375             
9376             //used in the for loops below, just declared here for brevity
9377             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, 
9378             horizMargins, vertMargins, stretchWidth;
9379
9380         //gather the total flex of all flexed items and the width taken up by fixed width items
9381         for (i = 0; i < visibleCount; i++) {
9382             child = visibleItems[i];
9383             childHeight = child.height;
9384             childWidth  = child.width;
9385             canLayout   = !child.hasLayout && typeof child.doLayout == 'function';
9386
9387             // Static height (numeric) requires no calcs
9388             if (typeof childHeight != 'number') {
9389
9390                 // flex and not 'auto' height
9391                 if (child.flex && !childHeight) {
9392                     totalFlex += child.flex;
9393
9394                 // Not flexed or 'auto' height or undefined height
9395                 } else {
9396                     //Render and layout sub-containers without a flex or width defined, as otherwise we
9397                     //don't know how wide the sub-container should be and cannot calculate flexed widths
9398                     if (!childHeight && canLayout) {
9399                         child.doLayout();
9400                     }
9401
9402                     childSize = child.getSize();
9403                     childWidth = childSize.width;
9404                     childHeight = childSize.height;
9405                 }
9406             }
9407             
9408             childMargins = child.margins;
9409             vertMargins  = childMargins.top + childMargins.bottom;
9410
9411             nonFlexHeight += vertMargins + (childHeight || 0);
9412             desiredHeight += vertMargins + (child.flex ? child.minHeight || 0 : childHeight);
9413             minimumHeight += vertMargins + (child.minHeight || childHeight || 0);
9414
9415             // Max width for align - force layout of non-layed out subcontainers without a numeric width
9416             if (typeof childWidth != 'number') {
9417                 if (canLayout) {
9418                     child.doLayout();
9419                 }
9420                 childWidth = child.getWidth();
9421             }
9422
9423             maxWidth = Math.max(maxWidth, childWidth + childMargins.left + childMargins.right);
9424
9425             //cache the size of each child component
9426             boxes.push({
9427                 component: child,
9428                 height   : childHeight || undefined,
9429                 width    : childWidth || undefined
9430             });
9431         }
9432                 
9433         var shortfall = desiredHeight - height,
9434             tooNarrow = minimumHeight > height;
9435
9436         //the height available to the flexed items
9437         var availableHeight = Math.max(0, (height - nonFlexHeight - paddingVert));
9438         
9439         if (tooNarrow) {
9440             for (i = 0, length = visibleCount; i < length; i++) {
9441                 boxes[i].height = visibleItems[i].minHeight || visibleItems[i].height || boxes[i].height;
9442             }
9443         } else {
9444             //all flexed items should be sized to their minimum width, other items should be shrunk down until
9445             //the shortfall has been accounted for
9446             if (shortfall > 0) {
9447                 var minHeights = [];
9448
9449                 /**
9450                  * When we have a shortfall but are not tooNarrow, we need to shrink the height of each non-flexed item.
9451                  * Flexed items are immediately reduced to their minHeight and anything already at minHeight is ignored.
9452                  * The remaining items are collected into the minHeights array, which is later used to distribute the shortfall.
9453                  */
9454                 for (var index = 0, length = visibleCount; index < length; index++) {
9455                     var item      = visibleItems[index],
9456                         minHeight = item.minHeight || 0;
9457
9458                     //shrink each non-flex tab by an equal amount to make them all fit. Flexed items are all
9459                     //shrunk to their minHeight because they're flexible and should be the first to lose height
9460                     if (item.flex) {
9461                         boxes[index].height = minHeight;
9462                     } else {
9463                         minHeights.push({
9464                             minHeight: minHeight, 
9465                             available: boxes[index].height - minHeight,
9466                             index    : index
9467                         });
9468                     }
9469                 }
9470
9471                 //sort by descending minHeight value
9472                 minHeights.sort(function(a, b) {
9473                     return a.available > b.available ? 1 : -1;
9474                 });
9475
9476                 /*
9477                  * Distribute the shortfall (difference between total desired with of all items and actual height available)
9478                  * between the non-flexed items. We try to distribute the shortfall evenly, but apply it to items with the
9479                  * smallest difference between their height and minHeight first, so that if reducing the height by the average
9480                  * amount would make that item less than its minHeight, we carry the remainder over to the next item.
9481                  */
9482                 for (var i = 0, length = minHeights.length; i < length; i++) {
9483                     var itemIndex = minHeights[i].index;
9484
9485                     if (itemIndex == undefined) {
9486                         continue;
9487                     }
9488
9489                     var item      = visibleItems[itemIndex],
9490                         box       = boxes[itemIndex],
9491                         oldHeight  = box.height,
9492                         minHeight  = item.minHeight,
9493                         newHeight  = Math.max(minHeight, oldHeight - Math.ceil(shortfall / (length - i))),
9494                         reduction = oldHeight - newHeight;
9495
9496                     boxes[itemIndex].height = newHeight;
9497                     shortfall -= reduction;
9498                 }
9499             } else {
9500                 //temporary variables used in the flex height calculations below
9501                 var remainingHeight = availableHeight,
9502                     remainingFlex   = totalFlex;
9503                 
9504                 //calculate the height of each flexed item
9505                 for (i = 0; i < visibleCount; i++) {
9506                     child = visibleItems[i];
9507                     calcs = boxes[i];
9508
9509                     childMargins = child.margins;
9510                     horizMargins = childMargins.left + childMargins.right;
9511
9512                     if (isStart && child.flex && !child.height) {
9513                         flexedHeight     = Math.ceil((child.flex / remainingFlex) * remainingHeight);
9514                         remainingHeight -= flexedHeight;
9515                         remainingFlex   -= child.flex;
9516
9517                         calcs.height = flexedHeight;
9518                         calcs.dirtySize = true;
9519                     }
9520                 }
9521             }
9522         }
9523
9524         if (isCenter) {
9525             topOffset += availableHeight / 2;
9526         } else if (isEnd) {
9527             topOffset += availableHeight;
9528         }
9529
9530         //finally, calculate the left and top position of each item
9531         for (i = 0; i < visibleCount; i++) {
9532             child = visibleItems[i];
9533             calcs = boxes[i];
9534
9535             childMargins = child.margins;
9536             topOffset   += childMargins.top;
9537             horizMargins = childMargins.left + childMargins.right;
9538             
9539
9540             calcs.left = leftOffset + childMargins.left;
9541             calcs.top  = topOffset;
9542             
9543             switch (this.align) {
9544                 case 'stretch':
9545                     stretchWidth = availWidth - horizMargins;
9546                     calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
9547                     calcs.dirtySize = true;
9548                     break;
9549                 case 'stretchmax':
9550                     stretchWidth = maxWidth - horizMargins;
9551                     calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
9552                     calcs.dirtySize = true;
9553                     break;
9554                 case 'center':
9555                     var diff = availWidth - calcs.width - horizMargins;
9556                     if (diff > 0) {
9557                         calcs.left = leftOffset + horizMargins + (diff / 2);
9558                     }
9559             }
9560
9561             topOffset += calcs.height + childMargins.bottom;
9562         }
9563         
9564         return {
9565             boxes: boxes,
9566             meta : {
9567                 maxWidth     : maxWidth,
9568                 nonFlexHeight: nonFlexHeight,
9569                 desiredHeight: desiredHeight,
9570                 minimumHeight: minimumHeight,
9571                 shortfall    : desiredHeight - height,
9572                 tooNarrow    : tooNarrow
9573             }
9574         };
9575     }
9576 });
9577
9578 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
9579 /**
9580  * @class Ext.layout.ToolbarLayout
9581  * @extends Ext.layout.ContainerLayout
9582  * Layout manager used by Ext.Toolbar. This is highly specialised for use by Toolbars and would not
9583  * usually be used by any other class.
9584  */
9585 Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
9586     monitorResize : true,
9587
9588     type: 'toolbar',
9589
9590     /**
9591      * @property triggerWidth
9592      * @type Number
9593      * The width allocated for the menu trigger at the extreme right end of the Toolbar
9594      */
9595     triggerWidth: 18,
9596
9597     /**
9598      * @property noItemsMenuText
9599      * @type String
9600      * HTML fragment to render into the toolbar overflow menu if there are no items to display
9601      */
9602     noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
9603
9604     /**
9605      * @private
9606      * @property lastOverflow
9607      * @type Boolean
9608      * Used internally to record whether the last layout caused an overflow or not
9609      */
9610     lastOverflow: false,
9611
9612     /**
9613      * @private
9614      * @property tableHTML
9615      * @type String
9616      * String used to build the HTML injected to support the Toolbar's layout. The align property is
9617      * injected into this string inside the td.x-toolbar-left element during onLayout.
9618      */
9619     tableHTML: [
9620         '<table cellspacing="0" class="x-toolbar-ct">',
9621             '<tbody>',
9622                 '<tr>',
9623                     '<td class="x-toolbar-left" align="{0}">',
9624                         '<table cellspacing="0">',
9625                             '<tbody>',
9626                                 '<tr class="x-toolbar-left-row"></tr>',
9627                             '</tbody>',
9628                         '</table>',
9629                     '</td>',
9630                     '<td class="x-toolbar-right" align="right">',
9631                         '<table cellspacing="0" class="x-toolbar-right-ct">',
9632                             '<tbody>',
9633                                 '<tr>',
9634                                     '<td>',
9635                                         '<table cellspacing="0">',
9636                                             '<tbody>',
9637                                                 '<tr class="x-toolbar-right-row"></tr>',
9638                                             '</tbody>',
9639                                         '</table>',
9640                                     '</td>',
9641                                     '<td>',
9642                                         '<table cellspacing="0">',
9643                                             '<tbody>',
9644                                                 '<tr class="x-toolbar-extras-row"></tr>',
9645                                             '</tbody>',
9646                                         '</table>',
9647                                     '</td>',
9648                                 '</tr>',
9649                             '</tbody>',
9650                         '</table>',
9651                     '</td>',
9652                 '</tr>',
9653             '</tbody>',
9654         '</table>'
9655     ].join(""),
9656
9657     /**
9658      * @private
9659      * Create the wrapping Toolbar HTML and render/move all the items into the correct places
9660      */
9661     onLayout : function(ct, target) {
9662         //render the Toolbar <table> HTML if it's not already present
9663         if (!this.leftTr) {
9664             var align = ct.buttonAlign == 'center' ? 'center' : 'left';
9665
9666             target.addClass('x-toolbar-layout-ct');
9667             target.insertHtml('beforeEnd', String.format(this.tableHTML, align));
9668
9669             this.leftTr   = target.child('tr.x-toolbar-left-row', true);
9670             this.rightTr  = target.child('tr.x-toolbar-right-row', true);
9671             this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
9672
9673             if (this.hiddenItem == undefined) {
9674                 /**
9675                  * @property hiddenItems
9676                  * @type Array
9677                  * Holds all items that are currently hidden due to there not being enough space to render them
9678                  * These items will appear on the expand menu.
9679                  */
9680                 this.hiddenItems = [];
9681             }
9682         }
9683
9684         var side     = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
9685             items    = ct.items.items,
9686             position = 0;
9687
9688         //render each item if not already rendered, place it into the correct (left or right) target
9689         for (var i = 0, len = items.length, c; i < len; i++, position++) {
9690             c = items[i];
9691
9692             if (c.isFill) {
9693                 side   = this.rightTr;
9694                 position = -1;
9695             } else if (!c.rendered) {
9696                 c.render(this.insertCell(c, side, position));
9697                 this.configureItem(c);
9698             } else {
9699                 if (!c.xtbHidden && !this.isValidParent(c, side.childNodes[position])) {
9700                     var td = this.insertCell(c, side, position);
9701                     td.appendChild(c.getPositionEl().dom);
9702                     c.container = Ext.get(td);
9703                 }
9704             }
9705         }
9706
9707         //strip extra empty cells
9708         this.cleanup(this.leftTr);
9709         this.cleanup(this.rightTr);
9710         this.cleanup(this.extrasTr);
9711         this.fitToSize(target);
9712     },
9713
9714     /**
9715      * @private
9716      * Removes any empty nodes from the given element
9717      * @param {Ext.Element} el The element to clean up
9718      */
9719     cleanup : function(el) {
9720         var cn = el.childNodes, i, c;
9721
9722         for (i = cn.length-1; i >= 0 && (c = cn[i]); i--) {
9723             if (!c.firstChild) {
9724                 el.removeChild(c);
9725             }
9726         }
9727     },
9728
9729     /**
9730      * @private
9731      * Inserts the given Toolbar item into the given element
9732      * @param {Ext.Component} c The component to add
9733      * @param {Ext.Element} target The target to add the component to
9734      * @param {Number} position The position to add the component at
9735      */
9736     insertCell : function(c, target, position) {
9737         var td = document.createElement('td');
9738         td.className = 'x-toolbar-cell';
9739
9740         target.insertBefore(td, target.childNodes[position] || null);
9741
9742         return td;
9743     },
9744
9745     /**
9746      * @private
9747      * Hides an item because it will not fit in the available width. The item will be unhidden again
9748      * if the Toolbar is resized to be large enough to show it
9749      * @param {Ext.Component} item The item to hide
9750      */
9751     hideItem : function(item) {
9752         this.hiddenItems.push(item);
9753
9754         item.xtbHidden = true;
9755         item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
9756         item.hide();
9757     },
9758
9759     /**
9760      * @private
9761      * Unhides an item that was previously hidden due to there not being enough space left on the Toolbar
9762      * @param {Ext.Component} item The item to show
9763      */
9764     unhideItem : function(item) {
9765         item.show();
9766         item.xtbHidden = false;
9767         this.hiddenItems.remove(item);
9768     },
9769
9770     /**
9771      * @private
9772      * Returns the width of the given toolbar item. If the item is currently hidden because there
9773      * is not enough room to render it, its previous width is returned
9774      * @param {Ext.Component} c The component to measure
9775      * @return {Number} The width of the item
9776      */
9777     getItemWidth : function(c) {
9778         return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
9779     },
9780
9781     /**
9782      * @private
9783      * Called at the end of onLayout. At this point the Toolbar has already been resized, so we need
9784      * to fit the items into the available width. We add up the width required by all of the items in
9785      * the toolbar - if we don't have enough space we hide the extra items and render the expand menu
9786      * trigger.
9787      * @param {Ext.Element} target The Element the Toolbar is currently laid out within
9788      */
9789     fitToSize : function(target) {
9790         if (this.container.enableOverflow === false) {
9791             return;
9792         }
9793
9794         var width       = target.dom.clientWidth,
9795             tableWidth  = target.dom.firstChild.offsetWidth,
9796             clipWidth   = width - this.triggerWidth,
9797             lastWidth   = this.lastWidth || 0,
9798
9799             hiddenItems = this.hiddenItems,
9800             hasHiddens  = hiddenItems.length != 0,
9801             isLarger    = width >= lastWidth;
9802
9803         this.lastWidth  = width;
9804
9805         if (tableWidth > width || (hasHiddens && isLarger)) {
9806             var items     = this.container.items.items,
9807                 len       = items.length,
9808                 loopWidth = 0,
9809                 item;
9810
9811             for (var i = 0; i < len; i++) {
9812                 item = items[i];
9813
9814                 if (!item.isFill) {
9815                     loopWidth += this.getItemWidth(item);
9816                     if (loopWidth > clipWidth) {
9817                         if (!(item.hidden || item.xtbHidden)) {
9818                             this.hideItem(item);
9819                         }
9820                     } else if (item.xtbHidden) {
9821                         this.unhideItem(item);
9822                     }
9823                 }
9824             }
9825         }
9826
9827         //test for number of hidden items again here because they may have changed above
9828         hasHiddens = hiddenItems.length != 0;
9829
9830         if (hasHiddens) {
9831             this.initMore();
9832
9833             if (!this.lastOverflow) {
9834                 this.container.fireEvent('overflowchange', this.container, true);
9835                 this.lastOverflow = true;
9836             }
9837         } else if (this.more) {
9838             this.clearMenu();
9839             this.more.destroy();
9840             delete this.more;
9841
9842             if (this.lastOverflow) {
9843                 this.container.fireEvent('overflowchange', this.container, false);
9844                 this.lastOverflow = false;
9845             }
9846         }
9847     },
9848
9849     /**
9850      * @private
9851      * Returns a menu config for a given component. This config is used to create a menu item
9852      * to be added to the expander menu
9853      * @param {Ext.Component} component The component to create the config for
9854      * @param {Boolean} hideOnClick Passed through to the menu item
9855      */
9856     createMenuConfig : function(component, hideOnClick){
9857         var config = Ext.apply({}, component.initialConfig),
9858             group  = component.toggleGroup;
9859
9860         Ext.copyTo(config, component, [
9861             'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
9862         ]);
9863
9864         Ext.apply(config, {
9865             text       : component.overflowText || component.text,
9866             hideOnClick: hideOnClick
9867         });
9868
9869         if (group || component.enableToggle) {
9870             Ext.apply(config, {
9871                 group  : group,
9872                 checked: component.pressed,
9873                 listeners: {
9874                     checkchange: function(item, checked){
9875                         component.toggle(checked);
9876                     }
9877                 }
9878             });
9879         }
9880
9881         delete config.ownerCt;
9882         delete config.xtype;
9883         delete config.id;
9884
9885         return config;
9886     },
9887
9888     /**
9889      * @private
9890      * Adds the given Toolbar item to the given menu. Buttons inside a buttongroup are added individually.
9891      * @param {Ext.menu.Menu} menu The menu to add to
9892      * @param {Ext.Component} component The component to add
9893      */
9894     addComponentToMenu : function(menu, component) {
9895         if (component instanceof Ext.Toolbar.Separator) {
9896             menu.add('-');
9897
9898         } else if (Ext.isFunction(component.isXType)) {
9899             if (component.isXType('splitbutton')) {
9900                 menu.add(this.createMenuConfig(component, true));
9901
9902             } else if (component.isXType('button')) {
9903                 menu.add(this.createMenuConfig(component, !component.menu));
9904
9905             } else if (component.isXType('buttongroup')) {
9906                 component.items.each(function(item){
9907                      this.addComponentToMenu(menu, item);
9908                 }, this);
9909             }
9910         }
9911     },
9912
9913     /**
9914      * @private
9915      * Deletes the sub-menu of each item in the expander menu. Submenus are created for items such as
9916      * splitbuttons and buttongroups, where the Toolbar item cannot be represented by a single menu item
9917      */
9918     clearMenu : function(){
9919         var menu = this.moreMenu;
9920         if (menu && menu.items) {
9921             menu.items.each(function(item){
9922                 delete item.menu;
9923             });
9924         }
9925     },
9926
9927     /**
9928      * @private
9929      * Called before the expand menu is shown, this rebuilds the menu since it was last shown because
9930      * it is possible that the items hidden due to space limitations on the Toolbar have changed since.
9931      * @param {Ext.menu.Menu} m The menu
9932      */
9933     beforeMoreShow : function(menu) {
9934         var items = this.container.items.items,
9935             len   = items.length,
9936             item,
9937             prev;
9938
9939         var needsSep = function(group, item){
9940             return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
9941         };
9942
9943         this.clearMenu();
9944         menu.removeAll();
9945         for (var i = 0; i < len; i++) {
9946             item = items[i];
9947             if (item.xtbHidden) {
9948                 if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
9949                     menu.add('-');
9950                 }
9951                 this.addComponentToMenu(menu, item);
9952                 prev = item;
9953             }
9954         }
9955
9956         // put something so the menu isn't empty if no compatible items found
9957         if (menu.items.length < 1) {
9958             menu.add(this.noItemsMenuText);
9959         }
9960     },
9961
9962     /**
9963      * @private
9964      * Creates the expand trigger and menu, adding them to the <tr> at the extreme right of the
9965      * Toolbar table
9966      */
9967     initMore : function(){
9968         if (!this.more) {
9969             /**
9970              * @private
9971              * @property moreMenu
9972              * @type Ext.menu.Menu
9973              * The expand menu - holds items for every Toolbar item that cannot be shown
9974              * because the Toolbar is currently not wide enough.
9975              */
9976             this.moreMenu = new Ext.menu.Menu({
9977                 ownerCt : this.container,
9978                 listeners: {
9979                     beforeshow: this.beforeMoreShow,
9980                     scope: this
9981                 }
9982             });
9983
9984             /**
9985              * @private
9986              * @property more
9987              * @type Ext.Button
9988              * The expand button which triggers the overflow menu to be shown
9989              */
9990             this.more = new Ext.Button({
9991                 iconCls: 'x-toolbar-more-icon',
9992                 cls    : 'x-toolbar-more',
9993                 menu   : this.moreMenu,
9994                 ownerCt: this.container
9995             });
9996
9997             var td = this.insertCell(this.more, this.extrasTr, 100);
9998             this.more.render(td);
9999         }
10000     },
10001
10002     destroy : function(){
10003         Ext.destroy(this.more, this.moreMenu);
10004         delete this.leftTr;
10005         delete this.rightTr;
10006         delete this.extrasTr;
10007         Ext.layout.ToolbarLayout.superclass.destroy.call(this);
10008     }
10009 });
10010
10011 Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;
10012 /**
10013  * @class Ext.layout.MenuLayout
10014  * @extends Ext.layout.ContainerLayout
10015  * <p>Layout manager used by {@link Ext.menu.Menu}. Generally this class should not need to be used directly.</p>
10016  */
10017  Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
10018     monitorResize : true,
10019
10020     type: 'menu',
10021
10022     setContainer : function(ct){
10023         this.monitorResize = !ct.floating;
10024         // This event is only fired by the menu in IE, used so we don't couple
10025         // the menu with the layout.
10026         ct.on('autosize', this.doAutoSize, this);
10027         Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
10028     },
10029
10030     renderItem : function(c, position, target){
10031         if (!this.itemTpl) {
10032             this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
10033                 '<li id="{itemId}" class="{itemCls}">',
10034                     '<tpl if="needsIcon">',
10035                         '<img alt="{altText}" src="{icon}" class="{iconCls}"/>',
10036                     '</tpl>',
10037                 '</li>'
10038             );
10039         }
10040
10041         if(c && !c.rendered){
10042             if(Ext.isNumber(position)){
10043                 position = target.dom.childNodes[position];
10044             }
10045             var a = this.getItemArgs(c);
10046
10047 //          The Component's positionEl is the <li> it is rendered into
10048             c.render(c.positionEl = position ?
10049                 this.itemTpl.insertBefore(position, a, true) :
10050                 this.itemTpl.append(target, a, true));
10051
10052 //          Link the containing <li> to the item.
10053             c.positionEl.menuItemId = c.getItemId();
10054
10055 //          If rendering a regular Component, and it needs an icon,
10056 //          move the Component rightwards.
10057             if (!a.isMenuItem && a.needsIcon) {
10058                 c.positionEl.addClass('x-menu-list-item-indent');
10059             }
10060             this.configureItem(c);
10061         }else if(c && !this.isValidParent(c, target)){
10062             if(Ext.isNumber(position)){
10063                 position = target.dom.childNodes[position];
10064             }
10065             target.dom.insertBefore(c.getActionEl().dom, position || null);
10066         }
10067     },
10068
10069     getItemArgs : function(c) {
10070         var isMenuItem = c instanceof Ext.menu.Item,
10071             canHaveIcon = !(isMenuItem || c instanceof Ext.menu.Separator);
10072
10073         return {
10074             isMenuItem: isMenuItem,
10075             needsIcon: canHaveIcon && (c.icon || c.iconCls),
10076             icon: c.icon || Ext.BLANK_IMAGE_URL,
10077             iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
10078             itemId: 'x-menu-el-' + c.id,
10079             itemCls: 'x-menu-list-item ',
10080             altText: c.altText || ''
10081         };
10082     },
10083
10084     //  Valid if the Component is in a <li> which is part of our target <ul>
10085     isValidParent : function(c, target) {
10086         return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
10087     },
10088
10089     onLayout : function(ct, target){
10090         Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
10091         this.doAutoSize();
10092     },
10093
10094     doAutoSize : function(){
10095         var ct = this.container, w = ct.width;
10096         if(ct.floating){
10097             if(w){
10098                 ct.setWidth(w);
10099             }else if(Ext.isIE){
10100                 ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
10101                 var el = ct.getEl(), t = el.dom.offsetWidth; // force recalc
10102                 ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
10103             }
10104         }
10105     }
10106 });
10107 Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;
10108 /**
10109  * @class Ext.Viewport
10110  * @extends Ext.Container
10111  * <p>A specialized container representing the viewable application area (the browser viewport).</p>
10112  * <p>The Viewport renders itself to the document body, and automatically sizes itself to the size of
10113  * the browser viewport and manages window resizing. There may only be one Viewport created
10114  * in a page. Inner layouts are available by virtue of the fact that all {@link Ext.Panel Panel}s
10115  * added to the Viewport, either through its {@link #items}, or through the items, or the {@link #add}
10116  * method of any of its child Panels may themselves have a layout.</p>
10117  * <p>The Viewport does not provide scrolling, so child Panels within the Viewport should provide
10118  * for scrolling if needed using the {@link #autoScroll} config.</p>
10119  * <p>An example showing a classic application border layout:</p><pre><code>
10120 new Ext.Viewport({
10121     layout: 'border',
10122     items: [{
10123         region: 'north',
10124         html: '&lt;h1 class="x-panel-header">Page Title&lt;/h1>',
10125         autoHeight: true,
10126         border: false,
10127         margins: '0 0 5 0'
10128     }, {
10129         region: 'west',
10130         collapsible: true,
10131         title: 'Navigation',
10132         width: 200
10133         // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout}
10134     }, {
10135         region: 'south',
10136         title: 'Title for Panel',
10137         collapsible: true,
10138         html: 'Information goes here',
10139         split: true,
10140         height: 100,
10141         minHeight: 100
10142     }, {
10143         region: 'east',
10144         title: 'Title for the Grid Panel',
10145         collapsible: true,
10146         split: true,
10147         width: 200,
10148         xtype: 'grid',
10149         // remaining grid configuration not shown ...
10150         // notice that the GridPanel is added directly as the region
10151         // it is not "overnested" inside another Panel
10152     }, {
10153         region: 'center',
10154         xtype: 'tabpanel', // TabPanel itself has no title
10155         items: {
10156             title: 'Default Tab',
10157             html: 'The first tab\'s content. Others may be added dynamically'
10158         }
10159     }]
10160 });
10161 </code></pre>
10162  * @constructor
10163  * Create a new Viewport
10164  * @param {Object} config The config object
10165  * @xtype viewport
10166  */
10167 Ext.Viewport = Ext.extend(Ext.Container, {
10168     /*
10169      * Privatize config options which, if used, would interfere with the
10170      * correct operation of the Viewport as the sole manager of the
10171      * layout of the document body.
10172      */
10173     /**
10174      * @cfg {Mixed} applyTo @hide
10175      */
10176     /**
10177      * @cfg {Boolean} allowDomMove @hide
10178      */
10179     /**
10180      * @cfg {Boolean} hideParent @hide
10181      */
10182     /**
10183      * @cfg {Mixed} renderTo @hide
10184      */
10185     /**
10186      * @cfg {Boolean} hideParent @hide
10187      */
10188     /**
10189      * @cfg {Number} height @hide
10190      */
10191     /**
10192      * @cfg {Number} width @hide
10193      */
10194     /**
10195      * @cfg {Boolean} autoHeight @hide
10196      */
10197     /**
10198      * @cfg {Boolean} autoWidth @hide
10199      */
10200     /**
10201      * @cfg {Boolean} deferHeight @hide
10202      */
10203     /**
10204      * @cfg {Boolean} monitorResize @hide
10205      */
10206
10207     initComponent : function() {
10208         Ext.Viewport.superclass.initComponent.call(this);
10209         document.getElementsByTagName('html')[0].className += ' x-viewport';
10210         this.el = Ext.getBody();
10211         this.el.setHeight = Ext.emptyFn;
10212         this.el.setWidth = Ext.emptyFn;
10213         this.el.setSize = Ext.emptyFn;
10214         this.el.dom.scroll = 'no';
10215         this.allowDomMove = false;
10216         this.autoWidth = true;
10217         this.autoHeight = true;
10218         Ext.EventManager.onWindowResize(this.fireResize, this);
10219         this.renderTo = this.el;
10220     },
10221
10222     fireResize : function(w, h){
10223         this.fireEvent('resize', this, w, h, w, h);
10224     }
10225 });
10226 Ext.reg('viewport', Ext.Viewport);
10227 /**
10228  * @class Ext.Panel
10229  * @extends Ext.Container
10230  * <p>Panel is a container that has specific functionality and structural components that make
10231  * it the perfect building block for application-oriented user interfaces.</p>
10232  * <p>Panels are, by virtue of their inheritance from {@link Ext.Container}, capable
10233  * of being configured with a {@link Ext.Container#layout layout}, and containing child Components.</p>
10234  * <p>When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.Container#add adding} Components
10235  * to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether
10236  * 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
10237  * default, Panels use the {@link Ext.layout.ContainerLayout ContainerLayout} scheme. This simply renders
10238  * child components, appending them one after the other inside the Container, and <b>does not apply any sizing</b>
10239  * at all.</p>
10240  * <p>A Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate
10241  * {@link #header}, {@link #footer} and {@link #body} sections (see {@link #frame} for additional
10242  * information).</p>
10243  * <p>Panel also provides built-in {@link #collapsible expandable and collapsible behavior}, along with
10244  * a variety of {@link #tools prebuilt tool buttons} that can be wired up to provide other customized
10245  * behavior.  Panels can be easily dropped into any {@link Ext.Container Container} or layout, and the
10246  * layout and rendering pipeline is {@link Ext.Container#add completely managed by the framework}.</p>
10247  * @constructor
10248  * @param {Object} config The config object
10249  * @xtype panel
10250  */
10251 Ext.Panel = Ext.extend(Ext.Container, {
10252     /**
10253      * The Panel's header {@link Ext.Element Element}. Read-only.
10254      * <p>This Element is used to house the {@link #title} and {@link #tools}</p>
10255      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
10256      * @type Ext.Element
10257      * @property header
10258      */
10259     /**
10260      * The Panel's body {@link Ext.Element Element} which may be used to contain HTML content.
10261      * The content may be specified in the {@link #html} config, or it may be loaded using the
10262      * {@link autoLoad} config, or through the Panel's {@link #getUpdater Updater}. Read-only.
10263      * <p>If this is used to load visible HTML elements in either way, then
10264      * the Panel may not be used as a Layout for hosting nested Panels.</p>
10265      * <p>If this Panel is intended to be used as the host of a Layout (See {@link #layout}
10266      * then the body Element must not be loaded or changed - it is under the control
10267      * of the Panel's Layout.
10268      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
10269      * @type Ext.Element
10270      * @property body
10271      */
10272     /**
10273      * The Panel's bwrap {@link Ext.Element Element} used to contain other Panel elements
10274      * (tbar, body, bbar, footer). See {@link #bodyCfg}. Read-only.
10275      * @type Ext.Element
10276      * @property bwrap
10277      */
10278     /**
10279      * True if this panel is collapsed. Read-only.
10280      * @type Boolean
10281      * @property collapsed
10282      */
10283     /**
10284      * @cfg {Object} bodyCfg
10285      * <p>A {@link Ext.DomHelper DomHelper} element specification object may be specified for any
10286      * Panel Element.</p>
10287      * <p>By default, the Default element in the table below will be used for the html markup to
10288      * create a child element with the commensurate Default class name (<code>baseCls</code> will be
10289      * replaced by <code>{@link #baseCls}</code>):</p>
10290      * <pre>
10291      * Panel      Default  Default             Custom      Additional       Additional
10292      * Element    element  class               element     class            style
10293      * ========   ==========================   =========   ==============   ===========
10294      * {@link #header}     div      {@link #baseCls}+'-header'   {@link #headerCfg}   headerCssClass   headerStyle
10295      * {@link #bwrap}      div      {@link #baseCls}+'-bwrap'     {@link #bwrapCfg}    bwrapCssClass    bwrapStyle
10296      * + tbar     div      {@link #baseCls}+'-tbar'       {@link #tbarCfg}     tbarCssClass     tbarStyle
10297      * + {@link #body}     div      {@link #baseCls}+'-body'       {@link #bodyCfg}     {@link #bodyCssClass}     {@link #bodyStyle}
10298      * + bbar     div      {@link #baseCls}+'-bbar'       {@link #bbarCfg}     bbarCssClass     bbarStyle
10299      * + {@link #footer}   div      {@link #baseCls}+'-footer'   {@link #footerCfg}   footerCssClass   footerStyle
10300      * </pre>
10301      * <p>Configuring a Custom element may be used, for example, to force the {@link #body} Element
10302      * to use a different form of markup than is created by default. An example of this might be
10303      * to {@link Ext.Element#createChild create a child} Panel containing a custom content, such as
10304      * a header, or forcing centering of all Panel content by having the body be a &lt;center&gt;
10305      * element:</p>
10306      * <pre><code>
10307 new Ext.Panel({
10308     title: 'Message Title',
10309     renderTo: Ext.getBody(),
10310     width: 200, height: 130,
10311     <b>bodyCfg</b>: {
10312         tag: 'center',
10313         cls: 'x-panel-body',  // Default class not applied if Custom element specified
10314         html: 'Message'
10315     },
10316     footerCfg: {
10317         tag: 'h2',
10318         cls: 'x-panel-footer',        // same as the Default class
10319         html: 'footer html'
10320     },
10321     footerCssClass: 'custom-footer', // additional css class, see {@link Ext.element#addClass addClass}
10322     footerStyle:    'background-color:red' // see {@link #bodyStyle}
10323 });
10324      * </code></pre>
10325      * <p>The example above also explicitly creates a <code>{@link #footer}</code> with custom markup and
10326      * styling applied.</p>
10327      */
10328     /**
10329      * @cfg {Object} headerCfg
10330      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
10331      * of this Panel's {@link #header} Element.  See <code>{@link #bodyCfg}</code> also.</p>
10332      */
10333     /**
10334      * @cfg {Object} bwrapCfg
10335      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
10336      * of this Panel's {@link #bwrap} Element.  See <code>{@link #bodyCfg}</code> also.</p>
10337      */
10338     /**
10339      * @cfg {Object} tbarCfg
10340      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
10341      * of this Panel's {@link #tbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
10342      */
10343     /**
10344      * @cfg {Object} bbarCfg
10345      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
10346      * of this Panel's {@link #bbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
10347      */
10348     /**
10349      * @cfg {Object} footerCfg
10350      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
10351      * of this Panel's {@link #footer} Element.  See <code>{@link #bodyCfg}</code> also.</p>
10352      */
10353     /**
10354      * @cfg {Boolean} closable
10355      * Panels themselves do not directly support being closed, but some Panel subclasses do (like
10356      * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}.  Specify <code>true</code>
10357      * to enable closing in such situations. Defaults to <code>false</code>.
10358      */
10359     /**
10360      * The Panel's footer {@link Ext.Element Element}. Read-only.
10361      * <p>This Element is used to house the Panel's <code>{@link #buttons}</code> or <code>{@link #fbar}</code>.</p>
10362      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
10363      * @type Ext.Element
10364      * @property footer
10365      */
10366     /**
10367      * @cfg {Mixed} applyTo
10368      * <p>The id of the node, a DOM node or an existing Element corresponding to a DIV that is already present in
10369      * the document that specifies some panel-specific structural markup.  When <code>applyTo</code> is used,
10370      * constituent parts of the panel can be specified by CSS class name within the main element, and the panel
10371      * will automatically create those components from that markup. Any required components not specified in the
10372      * markup will be autogenerated if necessary.</p>
10373      * <p>The following class names are supported (baseCls will be replaced by {@link #baseCls}):</p>
10374      * <ul><li>baseCls + '-header'</li>
10375      * <li>baseCls + '-header-text'</li>
10376      * <li>baseCls + '-bwrap'</li>
10377      * <li>baseCls + '-tbar'</li>
10378      * <li>baseCls + '-body'</li>
10379      * <li>baseCls + '-bbar'</li>
10380      * <li>baseCls + '-footer'</li></ul>
10381      * <p>Using this config, a call to render() is not required.  If applyTo is specified, any value passed for
10382      * {@link #renderTo} will be ignored and the target element's parent node will automatically be used as the
10383      * panel's container.</p>
10384      */
10385     /**
10386      * @cfg {Object/Array} tbar
10387      * <p>The top toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
10388      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
10389      * To access the top toolbar after render, use {@link #getTopToolbar}.</p>
10390      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
10391      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
10392      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
10393      * submission parameters are collected from the DOM tree.</p>
10394      */
10395     /**
10396      * @cfg {Object/Array} bbar
10397      * <p>The bottom toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
10398      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
10399      * To access the bottom toolbar after render, use {@link #getBottomToolbar}.</p>
10400      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
10401      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
10402      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
10403      * submission parameters are collected from the DOM tree.</p>
10404      */
10405     /** @cfg {Object/Array} fbar
10406      * <p>A {@link Ext.Toolbar Toolbar} object, a Toolbar config, or an array of
10407      * {@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>
10408      * <p>After render, the <code>fbar</code> property will be an {@link Ext.Toolbar Toolbar} instance.</p>
10409      * <p>If <code>{@link #buttons}</code> are specified, they will supersede the <code>fbar</code> configuration property.</p>
10410      * The Panel's <code>{@link #buttonAlign}</code> configuration affects the layout of these items, for example:
10411      * <pre><code>
10412 var w = new Ext.Window({
10413     height: 250,
10414     width: 500,
10415     bbar: new Ext.Toolbar({
10416         items: [{
10417             text: 'bbar Left'
10418         },'->',{
10419             text: 'bbar Right'
10420         }]
10421     }),
10422     {@link #buttonAlign}: 'left', // anything but 'center' or 'right' and you can use '-', and '->'
10423                                   // to control the alignment of fbar items
10424     fbar: [{
10425         text: 'fbar Left'
10426     },'->',{
10427         text: 'fbar Right'
10428     }]
10429 }).show();
10430      * </code></pre>
10431      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
10432      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
10433      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
10434      * submission parameters are collected from the DOM tree.</p>
10435      */
10436     /**
10437      * @cfg {Boolean} header
10438      * <code>true</code> to create the Panel's header element explicitly, <code>false</code> to skip creating
10439      * it.  If a <code>{@link #title}</code> is set the header will be created automatically, otherwise it will not.
10440      * If a <code>{@link #title}</code> is set but <code>header</code> is explicitly set to <code>false</code>, the header
10441      * will not be rendered.
10442      */
10443     /**
10444      * @cfg {Boolean} footer
10445      * <code>true</code> to create the footer element explicitly, false to skip creating it. The footer
10446      * will be created automatically if <code>{@link #buttons}</code> or a <code>{@link #fbar}</code> have
10447      * been configured.  See <code>{@link #bodyCfg}</code> for an example.
10448      */
10449     /**
10450      * @cfg {String} title
10451      * The title text to be used as innerHTML (html tags are accepted) to display in the panel
10452      * <code>{@link #header}</code> (defaults to ''). When a <code>title</code> is specified the
10453      * <code>{@link #header}</code> element will automatically be created and displayed unless
10454      * {@link #header} is explicitly set to <code>false</code>.  If you do not want to specify a
10455      * <code>title</code> at config time, but you may want one later, you must either specify a non-empty
10456      * <code>title</code> (a blank space ' ' will do) or <code>header:true</code> so that the container
10457      * element will get created.
10458      */
10459     /**
10460      * @cfg {Array} buttons
10461      * <code>buttons</code> will be used as <code>{@link Ext.Container#items items}</code> for the toolbar in
10462      * the footer (<code>{@link #fbar}</code>). Typically the value of this configuration property will be
10463      * an array of {@link Ext.Button}s or {@link Ext.Button} configuration objects.
10464      * If an item is configured with <code>minWidth</code> or the Panel is configured with <code>minButtonWidth</code>,
10465      * that width will be applied to the item.
10466      */
10467     /**
10468      * @cfg {Object/String/Function} autoLoad
10469      * A valid url spec according to the Updater {@link Ext.Updater#update} method.
10470      * If autoLoad is not null, the panel will attempt to load its contents
10471      * immediately upon render.<p>
10472      * The URL will become the default URL for this panel's {@link #body} element,
10473      * so it may be {@link Ext.Element#refresh refresh}ed at any time.</p>
10474      */
10475     /**
10476      * @cfg {Boolean} frame
10477      * <code>false</code> by default to render with plain 1px square borders. <code>true</code> to render with
10478      * 9 elements, complete with custom rounded corners (also see {@link Ext.Element#boxWrap}).
10479      * <p>The template generated for each condition is depicted below:</p><pre><code>
10480      *
10481 // frame = false
10482 &lt;div id="developer-specified-id-goes-here" class="x-panel">
10483
10484     &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:false)&lt;/span>&lt;/div>
10485
10486     &lt;div class="x-panel-bwrap">
10487         &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
10488     &lt;/div>
10489 &lt;/div>
10490
10491 // frame = true (create 9 elements)
10492 &lt;div id="developer-specified-id-goes-here" class="x-panel">
10493     &lt;div class="x-panel-tl">&lt;div class="x-panel-tr">&lt;div class="x-panel-tc">
10494         &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:true)&lt;/span>&lt;/div>
10495     &lt;/div>&lt;/div>&lt;/div>
10496
10497     &lt;div class="x-panel-bwrap">
10498         &lt;div class="x-panel-ml">&lt;div class="x-panel-mr">&lt;div class="x-panel-mc">
10499             &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
10500         &lt;/div>&lt;/div>&lt;/div>
10501
10502         &lt;div class="x-panel-bl">&lt;div class="x-panel-br">&lt;div class="x-panel-bc"/>
10503         &lt;/div>&lt;/div>&lt;/div>
10504 &lt;/div>
10505      * </code></pre>
10506      */
10507     /**
10508      * @cfg {Boolean} border
10509      * True to display the borders of the panel's body element, false to hide them (defaults to true).  By default,
10510      * the border is a 2px wide inset border, but this can be further altered by setting {@link #bodyBorder} to false.
10511      */
10512     /**
10513      * @cfg {Boolean} bodyBorder
10514      * True to display an interior border on the body element of the panel, false to hide it (defaults to true).
10515      * This only applies when {@link #border} == true.  If border == true and bodyBorder == false, the border will display
10516      * as a 1px wide inset border, giving the entire body element an inset appearance.
10517      */
10518     /**
10519      * @cfg {String/Object/Function} bodyCssClass
10520      * Additional css class selector to be applied to the {@link #body} element in the format expected by
10521      * {@link Ext.Element#addClass} (defaults to null). See {@link #bodyCfg}.
10522      */
10523     /**
10524      * @cfg {String/Object/Function} bodyStyle
10525      * Custom CSS styles to be applied to the {@link #body} element in the format expected by
10526      * {@link Ext.Element#applyStyles} (defaults to null). See {@link #bodyCfg}.
10527      */
10528     /**
10529      * @cfg {String} iconCls
10530      * The CSS class selector that specifies a background image to be used as the header icon (defaults to '').
10531      * <p>An example of specifying a custom icon class would be something like:
10532      * </p><pre><code>
10533 // specify the property in the config for the class:
10534      ...
10535      iconCls: 'my-icon'
10536
10537 // css class that specifies background image to be used as the icon image:
10538 .my-icon { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
10539 </code></pre>
10540      */
10541     /**
10542      * @cfg {Boolean} collapsible
10543      * True to make the panel collapsible and have the expand/collapse toggle button automatically rendered into
10544      * the header tool button area, false to keep the panel statically sized with no button (defaults to false).
10545      */
10546     /**
10547      * @cfg {Array} tools
10548      * An array of tool button configs to be added to the header tool area. When rendered, each tool is
10549      * stored as an {@link Ext.Element Element} referenced by a public property called <code><b></b>tools.<i>&lt;tool-type&gt;</i></code>
10550      * <p>Each tool config may contain the following properties:
10551      * <div class="mdetail-params"><ul>
10552      * <li><b>id</b> : String<div class="sub-desc"><b>Required.</b> The type
10553      * 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
10554      * resulting tool Element. Ext provides CSS rules, and an icon sprite containing images for the tool types listed below.
10555      * The developer may implement custom tools by supplying alternate CSS rules and background images:
10556      * <ul>
10557      * <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>
10558      * <div class="x-tool x-tool-close" style="float:left; margin-right:5;"> </div><div><code> close</code></div>
10559      * <div class="x-tool x-tool-minimize" style="float:left; margin-right:5;"> </div><div><code> minimize</code></div>
10560      * <div class="x-tool x-tool-maximize" style="float:left; margin-right:5;"> </div><div><code> maximize</code></div>
10561      * <div class="x-tool x-tool-restore" style="float:left; margin-right:5;"> </div><div><code> restore</code></div>
10562      * <div class="x-tool x-tool-gear" style="float:left; margin-right:5;"> </div><div><code> gear</code></div>
10563      * <div class="x-tool x-tool-pin" style="float:left; margin-right:5;"> </div><div><code> pin</code></div>
10564      * <div class="x-tool x-tool-unpin" style="float:left; margin-right:5;"> </div><div><code> unpin</code></div>
10565      * <div class="x-tool x-tool-right" style="float:left; margin-right:5;"> </div><div><code> right</code></div>
10566      * <div class="x-tool x-tool-left" style="float:left; margin-right:5;"> </div><div><code> left</code></div>
10567      * <div class="x-tool x-tool-up" style="float:left; margin-right:5;"> </div><div><code> up</code></div>
10568      * <div class="x-tool x-tool-down" style="float:left; margin-right:5;"> </div><div><code> down</code></div>
10569      * <div class="x-tool x-tool-refresh" style="float:left; margin-right:5;"> </div><div><code> refresh</code></div>
10570      * <div class="x-tool x-tool-minus" style="float:left; margin-right:5;"> </div><div><code> minus</code></div>
10571      * <div class="x-tool x-tool-plus" style="float:left; margin-right:5;"> </div><div><code> plus</code></div>
10572      * <div class="x-tool x-tool-help" style="float:left; margin-right:5;"> </div><div><code> help</code></div>
10573      * <div class="x-tool x-tool-search" style="float:left; margin-right:5;"> </div><div><code> search</code></div>
10574      * <div class="x-tool x-tool-save" style="float:left; margin-right:5;"> </div><div><code> save</code></div>
10575      * <div class="x-tool x-tool-print" style="float:left; margin-right:5;"> </div><div><code> print</code></div>
10576      * </ul></div></li>
10577      * <li><b>handler</b> : Function<div class="sub-desc"><b>Required.</b> The function to
10578      * call when clicked. Arguments passed are:<ul>
10579      * <li><b>event</b> : Ext.EventObject<div class="sub-desc">The click event.</div></li>
10580      * <li><b>toolEl</b> : Ext.Element<div class="sub-desc">The tool Element.</div></li>
10581      * <li><b>panel</b> : Ext.Panel<div class="sub-desc">The host Panel</div></li>
10582      * <li><b>tc</b> : Object<div class="sub-desc">The tool configuration object</div></li>
10583      * </ul></div></li>
10584      * <li><b>stopEvent</b> : Boolean<div class="sub-desc">Defaults to true. Specify as false to allow click event to propagate.</div></li>
10585      * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the handler.</div></li>
10586      * <li><b>qtip</b> : String/Object<div class="sub-desc">A tip string, or
10587      * a config argument to {@link Ext.QuickTip#register}</div></li>
10588      * <li><b>hidden</b> : Boolean<div class="sub-desc">True to initially render hidden.</div></li>
10589      * <li><b>on</b> : Object<div class="sub-desc">A listener config object specifiying
10590      * event listeners in the format of an argument to {@link #addListener}</div></li>
10591      * </ul></div>
10592      * <p>Note that, apart from the toggle tool which is provided when a panel is collapsible, these
10593      * tools only provide the visual button. Any required functionality must be provided by adding
10594      * handlers that implement the necessary behavior.</p>
10595      * <p>Example usage:</p>
10596      * <pre><code>
10597 tools:[{
10598     id:'refresh',
10599     qtip: 'Refresh form Data',
10600     // hidden:true,
10601     handler: function(event, toolEl, panel){
10602         // refresh logic
10603     }
10604 },
10605 {
10606     id:'help',
10607     qtip: 'Get Help',
10608     handler: function(event, toolEl, panel){
10609         // whatever
10610     }
10611 }]
10612 </code></pre>
10613      * <p>For the custom id of <code>'help'</code> define two relevant css classes with a link to
10614      * a 15x15 image:</p>
10615      * <pre><code>
10616 .x-tool-help {background-image: url(images/help.png);}
10617 .x-tool-help-over {background-image: url(images/help_over.png);}
10618 // if using an image sprite:
10619 .x-tool-help {background-image: url(images/help.png) no-repeat 0 0;}
10620 .x-tool-help-over {background-position:-15px 0;}
10621 </code></pre>
10622      */
10623     /**
10624      * @cfg {Ext.Template/Ext.XTemplate} toolTemplate
10625      * <p>A Template used to create {@link #tools} in the {@link #header} Element. Defaults to:</p><pre><code>
10626 new Ext.Template('&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>')</code></pre>
10627      * <p>This may may be overridden to provide a custom DOM structure for tools based upon a more
10628      * complex XTemplate. The template's data is a single tool configuration object (Not the entire Array)
10629      * as specified in {@link #tools}.  In the following example an &lt;a> tag is used to provide a
10630      * visual indication when hovering over the tool:</p><pre><code>
10631 var win = new Ext.Window({
10632     tools: [{
10633         id: 'download',
10634         href: '/MyPdfDoc.pdf'
10635     }],
10636     toolTemplate: new Ext.XTemplate(
10637         '&lt;tpl if="id==\'download\'">',
10638             '&lt;a class="x-tool x-tool-pdf" href="{href}">&lt;/a>',
10639         '&lt;/tpl>',
10640         '&lt;tpl if="id!=\'download\'">',
10641             '&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>',
10642         '&lt;/tpl>'
10643     ),
10644     width:500,
10645     height:300,
10646     closeAction:'hide'
10647 });</code></pre>
10648      * <p>Note that the CSS class 'x-tool-pdf' should have an associated style rule which provides an
10649      * appropriate background image, something like:</p>
10650     <pre><code>
10651     a.x-tool-pdf {background-image: url(../shared/extjs/images/pdf.gif)!important;}
10652     </code></pre>
10653      */
10654     /**
10655      * @cfg {Boolean} hideCollapseTool
10656      * <code>true</code> to hide the expand/collapse toggle button when <code>{@link #collapsible} == true</code>,
10657      * <code>false</code> to display it (defaults to <code>false</code>).
10658      */
10659     /**
10660      * @cfg {Boolean} titleCollapse
10661      * <code>true</code> to allow expanding and collapsing the panel (when <code>{@link #collapsible} = true</code>)
10662      * by clicking anywhere in the header bar, <code>false</code>) to allow it only by clicking to tool button
10663      * (defaults to <code>false</code>)). If this panel is a child item of a border layout also see the
10664      * {@link Ext.layout.BorderLayout.Region BorderLayout.Region}
10665      * <code>{@link Ext.layout.BorderLayout.Region#floatable floatable}</code> config option.
10666      */
10667
10668     /**
10669      * @cfg {Mixed} floating
10670      * <p>This property is used to configure the underlying {@link Ext.Layer}. Acceptable values for this
10671      * configuration property are:</p><div class="mdetail-params"><ul>
10672      * <li><b><code>false</code></b> : <b>Default.</b><div class="sub-desc">Display the panel inline where it is
10673      * rendered.</div></li>
10674      * <li><b><code>true</code></b> : <div class="sub-desc">Float the panel (absolute position it with automatic
10675      * shimming and shadow).<ul>
10676      * <div class="sub-desc">Setting floating to true will create an Ext.Layer for this panel and display the
10677      * panel at negative offsets so that it is hidden.</div>
10678      * <div class="sub-desc">Since the panel will be absolute positioned, the position must be set explicitly
10679      * <i>after</i> render (e.g., <code>myPanel.setPosition(100,100);</code>).</div>
10680      * <div class="sub-desc"><b>Note</b>: when floating a panel you should always assign a fixed width,
10681      * otherwise it will be auto width and will expand to fill to the right edge of the viewport.</div>
10682      * </ul></div></li>
10683      * <li><b><code>{@link Ext.Layer object}</code></b> : <div class="sub-desc">The specified object will be used
10684      * as the configuration object for the {@link Ext.Layer} that will be created.</div></li>
10685      * </ul></div>
10686      */
10687     /**
10688      * @cfg {Boolean/String} shadow
10689      * <code>true</code> (or a valid Ext.Shadow {@link Ext.Shadow#mode} value) to display a shadow behind the
10690      * panel, <code>false</code> to display no shadow (defaults to <code>'sides'</code>).  Note that this option
10691      * only applies when <code>{@link #floating} = true</code>.
10692      */
10693     /**
10694      * @cfg {Number} shadowOffset
10695      * The number of pixels to offset the shadow if displayed (defaults to <code>4</code>). Note that this
10696      * option only applies when <code>{@link #floating} = true</code>.
10697      */
10698     /**
10699      * @cfg {Boolean} shim
10700      * <code>false</code> to disable the iframe shim in browsers which need one (defaults to <code>true</code>).
10701      * Note that this option only applies when <code>{@link #floating} = true</code>.
10702      */
10703     /**
10704      * @cfg {Object/Array} keys
10705      * A {@link Ext.KeyMap} config object (in the format expected by {@link Ext.KeyMap#addBinding}
10706      * used to assign custom key handling to this panel (defaults to <code>null</code>).
10707      */
10708     /**
10709      * @cfg {Boolean/Object} draggable
10710      * <p><code>true</code> to enable dragging of this Panel (defaults to <code>false</code>).</p>
10711      * <p>For custom drag/drop implementations, an <b>Ext.Panel.DD</b> config could also be passed
10712      * in this config instead of <code>true</code>. Ext.Panel.DD is an internal, undocumented class which
10713      * moves a proxy Element around in place of the Panel's element, but provides no other behaviour
10714      * during dragging or on drop. It is a subclass of {@link Ext.dd.DragSource}, so behaviour may be
10715      * added by implementing the interface methods of {@link Ext.dd.DragDrop} e.g.:
10716      * <pre><code>
10717 new Ext.Panel({
10718     title: 'Drag me',
10719     x: 100,
10720     y: 100,
10721     renderTo: Ext.getBody(),
10722     floating: true,
10723     frame: true,
10724     width: 400,
10725     height: 200,
10726     draggable: {
10727 //      Config option of Ext.Panel.DD class.
10728 //      It&#39;s a floating Panel, so do not show a placeholder proxy in the original position.
10729         insertProxy: false,
10730
10731 //      Called for each mousemove event while dragging the DD object.
10732         onDrag : function(e){
10733 //          Record the x,y position of the drag proxy so that we can
10734 //          position the Panel at end of drag.
10735             var pel = this.proxy.getEl();
10736             this.x = pel.getLeft(true);
10737             this.y = pel.getTop(true);
10738
10739 //          Keep the Shadow aligned if there is one.
10740             var s = this.panel.getEl().shadow;
10741             if (s) {
10742                 s.realign(this.x, this.y, pel.getWidth(), pel.getHeight());
10743             }
10744         },
10745
10746 //      Called on the mouseup event.
10747         endDrag : function(e){
10748             this.panel.setPosition(this.x, this.y);
10749         }
10750     }
10751 }).show();
10752 </code></pre>
10753      */
10754     /**
10755      * @cfg {Boolean} disabled
10756      * Render this panel disabled (default is <code>false</code>). An important note when using the disabled
10757      * config on panels is that IE will often fail to initialize the disabled mask element correectly if
10758      * the panel's layout has not yet completed by the time the Panel is disabled during the render process.
10759      * If you experience this issue, you may need to instead use the {@link #afterlayout} event to initialize
10760      * the disabled state:
10761      * <pre><code>
10762 new Ext.Panel({
10763     ...
10764     listeners: {
10765         'afterlayout': {
10766             fn: function(p){
10767                 p.disable();
10768             },
10769             single: true // important, as many layouts can occur
10770         }
10771     }
10772 });
10773 </code></pre>
10774      */
10775     /**
10776      * @cfg {Boolean} autoHeight
10777      * <code>true</code> to use height:'auto', <code>false</code> to use fixed height (defaults to <code>false</code>).
10778      * <b>Note</b>: Setting <code>autoHeight: true</code> means that the browser will manage the panel's height
10779      * based on its contents, and that Ext will not manage it at all. If the panel is within a layout that
10780      * manages dimensions (<code>fit</code>, <code>border</code>, etc.) then setting <code>autoHeight: true</code>
10781      * can cause issues with scrolling and will not generally work as expected since the panel will take
10782      * on the height of its contents rather than the height required by the Ext layout.
10783      */
10784
10785
10786     /**
10787      * @cfg {String} baseCls
10788      * The base CSS class to apply to this panel's element (defaults to <code>'x-panel'</code>).
10789      * <p>Another option available by default is to specify <code>'x-plain'</code> which strips all styling
10790      * except for required attributes for Ext layouts to function (e.g. overflow:hidden).
10791      * See <code>{@link #unstyled}</code> also.</p>
10792      */
10793     baseCls : 'x-panel',
10794     /**
10795      * @cfg {String} collapsedCls
10796      * A CSS class to add to the panel's element after it has been collapsed (defaults to
10797      * <code>'x-panel-collapsed'</code>).
10798      */
10799     collapsedCls : 'x-panel-collapsed',
10800     /**
10801      * @cfg {Boolean} maskDisabled
10802      * <code>true</code> to mask the panel when it is {@link #disabled}, <code>false</code> to not mask it (defaults
10803      * to <code>true</code>).  Either way, the panel will always tell its contained elements to disable themselves
10804      * when it is disabled, but masking the panel can provide an additional visual cue that the panel is
10805      * disabled.
10806      */
10807     maskDisabled : true,
10808     /**
10809      * @cfg {Boolean} animCollapse
10810      * <code>true</code> to animate the transition when the panel is collapsed, <code>false</code> to skip the
10811      * animation (defaults to <code>true</code> if the {@link Ext.Fx} class is available, otherwise <code>false</code>).
10812      */
10813     animCollapse : Ext.enableFx,
10814     /**
10815      * @cfg {Boolean} headerAsText
10816      * <code>true</code> to display the panel <code>{@link #title}</code> in the <code>{@link #header}</code>,
10817      * <code>false</code> to hide it (defaults to <code>true</code>).
10818      */
10819     headerAsText : true,
10820     /**
10821      * @cfg {String} buttonAlign
10822      * The alignment of any {@link #buttons} added to this panel.  Valid values are <code>'right'</code>,
10823      * <code>'left'</code> and <code>'center'</code> (defaults to <code>'right'</code>).
10824      */
10825     buttonAlign : 'right',
10826     /**
10827      * @cfg {Boolean} collapsed
10828      * <code>true</code> to render the panel collapsed, <code>false</code> to render it expanded (defaults to
10829      * <code>false</code>).
10830      */
10831     collapsed : false,
10832     /**
10833      * @cfg {Boolean} collapseFirst
10834      * <code>true</code> to make sure the collapse/expand toggle button always renders first (to the left of)
10835      * any other tools in the panel's title bar, <code>false</code> to render it last (defaults to <code>true</code>).
10836      */
10837     collapseFirst : true,
10838     /**
10839      * @cfg {Number} minButtonWidth
10840      * Minimum width in pixels of all {@link #buttons} in this panel (defaults to <code>75</code>)
10841      */
10842     minButtonWidth : 75,
10843     /**
10844      * @cfg {Boolean} unstyled
10845      * Overrides the <code>{@link #baseCls}</code> setting to <code>{@link #baseCls} = 'x-plain'</code> which renders
10846      * the panel unstyled except for required attributes for Ext layouts to function (e.g. overflow:hidden).
10847      */
10848     /**
10849      * @cfg {String} elements
10850      * A comma-delimited list of panel elements to initialize when the panel is rendered.  Normally, this list will be
10851      * generated automatically based on the items added to the panel at config time, but sometimes it might be useful to
10852      * make sure a structural element is rendered even if not specified at config time (for example, you may want
10853      * to add a button or toolbar dynamically after the panel has been rendered).  Adding those elements to this
10854      * list will allocate the required placeholders in the panel when it is rendered.  Valid values are<div class="mdetail-params"><ul>
10855      * <li><code>header</code></li>
10856      * <li><code>tbar</code> (top bar)</li>
10857      * <li><code>body</code></li>
10858      * <li><code>bbar</code> (bottom bar)</li>
10859      * <li><code>footer</code></li>
10860      * </ul></div>
10861      * Defaults to '<code>body</code>'.
10862      */
10863     elements : 'body',
10864     /**
10865      * @cfg {Boolean} preventBodyReset
10866      * Defaults to <code>false</code>.  When set to <code>true</code>, an extra css class <code>'x-panel-normal'</code>
10867      * will be added to the panel's element, effectively applying css styles suggested by the W3C
10868      * (see http://www.w3.org/TR/CSS21/sample.html) to the Panel's <b>body</b> element (not the header,
10869      * footer, etc.).
10870      */
10871     preventBodyReset : false,
10872
10873     /**
10874      * @cfg {Number/String} padding
10875      * A shortcut for setting a padding style on the body element. The value can either be
10876      * a number to be applied to all sides, or a normal css string describing padding.
10877      * Defaults to <tt>undefined</tt>.
10878      *
10879      */
10880     padding: undefined,
10881
10882     /** @cfg {String} resizeEvent
10883      * The event to listen to for resizing in layouts. Defaults to <tt>'bodyresize'</tt>.
10884      */
10885     resizeEvent: 'bodyresize',
10886
10887     // protected - these could be used to customize the behavior of the window,
10888     // but changing them would not be useful without further mofifications and
10889     // could lead to unexpected or undesirable results.
10890     toolTarget : 'header',
10891     collapseEl : 'bwrap',
10892     slideAnchor : 't',
10893     disabledClass : '',
10894
10895     // private, notify box this class will handle heights
10896     deferHeight : true,
10897     // private
10898     expandDefaults: {
10899         duration : 0.25
10900     },
10901     // private
10902     collapseDefaults : {
10903         duration : 0.25
10904     },
10905
10906     // private
10907     initComponent : function(){
10908         Ext.Panel.superclass.initComponent.call(this);
10909
10910         this.addEvents(
10911             /**
10912              * @event bodyresize
10913              * Fires after the Panel has been resized.
10914              * @param {Ext.Panel} p the Panel which has been resized.
10915              * @param {Number} width The Panel body's new width.
10916              * @param {Number} height The Panel body's new height.
10917              */
10918             'bodyresize',
10919             /**
10920              * @event titlechange
10921              * Fires after the Panel title has been {@link #title set} or {@link #setTitle changed}.
10922              * @param {Ext.Panel} p the Panel which has had its title changed.
10923              * @param {String} The new title.
10924              */
10925             'titlechange',
10926             /**
10927              * @event iconchange
10928              * Fires after the Panel icon class has been {@link #iconCls set} or {@link #setIconClass changed}.
10929              * @param {Ext.Panel} p the Panel which has had its {@link #iconCls icon class} changed.
10930              * @param {String} The new icon class.
10931              * @param {String} The old icon class.
10932              */
10933             'iconchange',
10934             /**
10935              * @event collapse
10936              * Fires after the Panel has been collapsed.
10937              * @param {Ext.Panel} p the Panel that has been collapsed.
10938              */
10939             'collapse',
10940             /**
10941              * @event expand
10942              * Fires after the Panel has been expanded.
10943              * @param {Ext.Panel} p The Panel that has been expanded.
10944              */
10945             'expand',
10946             /**
10947              * @event beforecollapse
10948              * Fires before the Panel is collapsed.  A handler can return false to cancel the collapse.
10949              * @param {Ext.Panel} p the Panel being collapsed.
10950              * @param {Boolean} animate True if the collapse is animated, else false.
10951              */
10952             'beforecollapse',
10953             /**
10954              * @event beforeexpand
10955              * Fires before the Panel is expanded.  A handler can return false to cancel the expand.
10956              * @param {Ext.Panel} p The Panel being expanded.
10957              * @param {Boolean} animate True if the expand is animated, else false.
10958              */
10959             'beforeexpand',
10960             /**
10961              * @event beforeclose
10962              * Fires before the Panel is closed.  Note that Panels do not directly support being closed, but some
10963              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.  This event only
10964              * applies to such subclasses.
10965              * A handler can return false to cancel the close.
10966              * @param {Ext.Panel} p The Panel being closed.
10967              */
10968             'beforeclose',
10969             /**
10970              * @event close
10971              * Fires after the Panel is closed.  Note that Panels do not directly support being closed, but some
10972              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.
10973              * @param {Ext.Panel} p The Panel that has been closed.
10974              */
10975             'close',
10976             /**
10977              * @event activate
10978              * Fires after the Panel has been visually activated.
10979              * Note that Panels do not directly support being activated, but some Panel subclasses
10980              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
10981              * activate and deactivate events under the control of the TabPanel.
10982              * @param {Ext.Panel} p The Panel that has been activated.
10983              */
10984             'activate',
10985             /**
10986              * @event deactivate
10987              * Fires after the Panel has been visually deactivated.
10988              * Note that Panels do not directly support being deactivated, but some Panel subclasses
10989              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
10990              * activate and deactivate events under the control of the TabPanel.
10991              * @param {Ext.Panel} p The Panel that has been deactivated.
10992              */
10993             'deactivate'
10994         );
10995
10996         if(this.unstyled){
10997             this.baseCls = 'x-plain';
10998         }
10999
11000
11001         this.toolbars = [];
11002         // shortcuts
11003         if(this.tbar){
11004             this.elements += ',tbar';
11005             this.topToolbar = this.createToolbar(this.tbar);
11006             this.tbar = null;
11007
11008         }
11009         if(this.bbar){
11010             this.elements += ',bbar';
11011             this.bottomToolbar = this.createToolbar(this.bbar);
11012             this.bbar = null;
11013         }
11014
11015         if(this.header === true){
11016             this.elements += ',header';
11017             this.header = null;
11018         }else if(this.headerCfg || (this.title && this.header !== false)){
11019             this.elements += ',header';
11020         }
11021
11022         if(this.footerCfg || this.footer === true){
11023             this.elements += ',footer';
11024             this.footer = null;
11025         }
11026
11027         if(this.buttons){
11028             this.fbar = this.buttons;
11029             this.buttons = null;
11030         }
11031         if(this.fbar){
11032             this.createFbar(this.fbar);
11033         }
11034         if(this.autoLoad){
11035             this.on('render', this.doAutoLoad, this, {delay:10});
11036         }
11037     },
11038
11039     // private
11040     createFbar : function(fbar){
11041         var min = this.minButtonWidth;
11042         this.elements += ',footer';
11043         this.fbar = this.createToolbar(fbar, {
11044             buttonAlign: this.buttonAlign,
11045             toolbarCls: 'x-panel-fbar',
11046             enableOverflow: false,
11047             defaults: function(c){
11048                 return {
11049                     minWidth: c.minWidth || min
11050                 };
11051             }
11052         });
11053         // @compat addButton and buttons could possibly be removed
11054         // @target 4.0
11055         /**
11056          * This Panel's Array of buttons as created from the <code>{@link #buttons}</code>
11057          * config property. Read only.
11058          * @type Array
11059          * @property buttons
11060          */
11061         this.fbar.items.each(function(c){
11062             c.minWidth = c.minWidth || this.minButtonWidth;
11063         }, this);
11064         this.buttons = this.fbar.items.items;
11065     },
11066
11067     // private
11068     createToolbar: function(tb, options){
11069         var result;
11070         // Convert array to proper toolbar config
11071         if(Ext.isArray(tb)){
11072             tb = {
11073                 items: tb
11074             };
11075         }
11076         result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
11077         this.toolbars.push(result);
11078         return result;
11079     },
11080
11081     // private
11082     createElement : function(name, pnode){
11083         if(this[name]){
11084             pnode.appendChild(this[name].dom);
11085             return;
11086         }
11087
11088         if(name === 'bwrap' || this.elements.indexOf(name) != -1){
11089             if(this[name+'Cfg']){
11090                 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
11091             }else{
11092                 var el = document.createElement('div');
11093                 el.className = this[name+'Cls'];
11094                 this[name] = Ext.get(pnode.appendChild(el));
11095             }
11096             if(this[name+'CssClass']){
11097                 this[name].addClass(this[name+'CssClass']);
11098             }
11099             if(this[name+'Style']){
11100                 this[name].applyStyles(this[name+'Style']);
11101             }
11102         }
11103     },
11104
11105     // private
11106     onRender : function(ct, position){
11107         Ext.Panel.superclass.onRender.call(this, ct, position);
11108         this.createClasses();
11109
11110         var el = this.el,
11111             d = el.dom,
11112             bw,
11113             ts;
11114
11115
11116         if(this.collapsible && !this.hideCollapseTool){
11117             this.tools = this.tools ? this.tools.slice(0) : [];
11118             this.tools[this.collapseFirst?'unshift':'push']({
11119                 id: 'toggle',
11120                 handler : this.toggleCollapse,
11121                 scope: this
11122             });
11123         }
11124
11125         if(this.tools){
11126             ts = this.tools;
11127             this.elements += (this.header !== false) ? ',header' : '';
11128         }
11129         this.tools = {};
11130
11131         el.addClass(this.baseCls);
11132         if(d.firstChild){ // existing markup
11133             this.header = el.down('.'+this.headerCls);
11134             this.bwrap = el.down('.'+this.bwrapCls);
11135             var cp = this.bwrap ? this.bwrap : el;
11136             this.tbar = cp.down('.'+this.tbarCls);
11137             this.body = cp.down('.'+this.bodyCls);
11138             this.bbar = cp.down('.'+this.bbarCls);
11139             this.footer = cp.down('.'+this.footerCls);
11140             this.fromMarkup = true;
11141         }
11142         if (this.preventBodyReset === true) {
11143             el.addClass('x-panel-reset');
11144         }
11145         if(this.cls){
11146             el.addClass(this.cls);
11147         }
11148
11149         if(this.buttons){
11150             this.elements += ',footer';
11151         }
11152
11153         // This block allows for maximum flexibility and performance when using existing markup
11154
11155         // framing requires special markup
11156         if(this.frame){
11157             el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
11158
11159             this.createElement('header', d.firstChild.firstChild.firstChild);
11160             this.createElement('bwrap', d);
11161
11162             // append the mid and bottom frame to the bwrap
11163             bw = this.bwrap.dom;
11164             var ml = d.childNodes[1], bl = d.childNodes[2];
11165             bw.appendChild(ml);
11166             bw.appendChild(bl);
11167
11168             var mc = bw.firstChild.firstChild.firstChild;
11169             this.createElement('tbar', mc);
11170             this.createElement('body', mc);
11171             this.createElement('bbar', mc);
11172             this.createElement('footer', bw.lastChild.firstChild.firstChild);
11173
11174             if(!this.footer){
11175                 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
11176             }
11177             /*
11178              * Store a reference to this element so:
11179              * a) We aren't looking it up all the time
11180              * b) The last element is reported incorrectly when using a loadmask
11181              */
11182             this.ft = Ext.get(this.bwrap.dom.lastChild);
11183             this.mc = Ext.get(mc);
11184         }else{
11185             this.createElement('header', d);
11186             this.createElement('bwrap', d);
11187
11188             // append the mid and bottom frame to the bwrap
11189             bw = this.bwrap.dom;
11190             this.createElement('tbar', bw);
11191             this.createElement('body', bw);
11192             this.createElement('bbar', bw);
11193             this.createElement('footer', bw);
11194
11195             if(!this.header){
11196                 this.body.addClass(this.bodyCls + '-noheader');
11197                 if(this.tbar){
11198                     this.tbar.addClass(this.tbarCls + '-noheader');
11199                 }
11200             }
11201         }
11202
11203         if(Ext.isDefined(this.padding)){
11204             this.body.setStyle('padding', this.body.addUnits(this.padding));
11205         }
11206
11207         if(this.border === false){
11208             this.el.addClass(this.baseCls + '-noborder');
11209             this.body.addClass(this.bodyCls + '-noborder');
11210             if(this.header){
11211                 this.header.addClass(this.headerCls + '-noborder');
11212             }
11213             if(this.footer){
11214                 this.footer.addClass(this.footerCls + '-noborder');
11215             }
11216             if(this.tbar){
11217                 this.tbar.addClass(this.tbarCls + '-noborder');
11218             }
11219             if(this.bbar){
11220                 this.bbar.addClass(this.bbarCls + '-noborder');
11221             }
11222         }
11223
11224         if(this.bodyBorder === false){
11225            this.body.addClass(this.bodyCls + '-noborder');
11226         }
11227
11228         this.bwrap.enableDisplayMode('block');
11229
11230         if(this.header){
11231             this.header.unselectable();
11232
11233             // for tools, we need to wrap any existing header markup
11234             if(this.headerAsText){
11235                 this.header.dom.innerHTML =
11236                     '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
11237
11238                 if(this.iconCls){
11239                     this.setIconClass(this.iconCls);
11240                 }
11241             }
11242         }
11243
11244         if(this.floating){
11245             this.makeFloating(this.floating);
11246         }
11247
11248         if(this.collapsible && this.titleCollapse && this.header){
11249             this.mon(this.header, 'click', this.toggleCollapse, this);
11250             this.header.setStyle('cursor', 'pointer');
11251         }
11252         if(ts){
11253             this.addTool.apply(this, ts);
11254         }
11255
11256         // Render Toolbars.
11257         if(this.fbar){
11258             this.footer.addClass('x-panel-btns');
11259             this.fbar.ownerCt = this;
11260             this.fbar.render(this.footer);
11261             this.footer.createChild({cls:'x-clear'});
11262         }
11263         if(this.tbar && this.topToolbar){
11264             this.topToolbar.ownerCt = this;
11265             this.topToolbar.render(this.tbar);
11266         }
11267         if(this.bbar && this.bottomToolbar){
11268             this.bottomToolbar.ownerCt = this;
11269             this.bottomToolbar.render(this.bbar);
11270         }
11271     },
11272
11273     /**
11274      * Sets the CSS class that provides the icon image for this panel.  This method will replace any existing
11275      * icon class if one has already been set and fire the {@link #iconchange} event after completion.
11276      * @param {String} cls The new CSS class name
11277      */
11278     setIconClass : function(cls){
11279         var old = this.iconCls;
11280         this.iconCls = cls;
11281         if(this.rendered && this.header){
11282             if(this.frame){
11283                 this.header.addClass('x-panel-icon');
11284                 this.header.replaceClass(old, this.iconCls);
11285             }else{
11286                 var hd = this.header,
11287                     img = hd.child('img.x-panel-inline-icon');
11288                 if(img){
11289                     Ext.fly(img).replaceClass(old, this.iconCls);
11290                 }else{
11291                     var hdspan = hd.child('span.' + this.headerTextCls);
11292                     if (hdspan) {
11293                         Ext.DomHelper.insertBefore(hdspan.dom, {
11294                             tag:'img', alt: '', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
11295                         });
11296                     }
11297                  }
11298             }
11299         }
11300         this.fireEvent('iconchange', this, cls, old);
11301     },
11302
11303     // private
11304     makeFloating : function(cfg){
11305         this.floating = true;
11306         this.el = new Ext.Layer(Ext.apply({}, cfg, {
11307             shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
11308             shadowOffset: this.shadowOffset,
11309             constrain:false,
11310             shim: this.shim === false ? false : undefined
11311         }), this.el);
11312     },
11313
11314     /**
11315      * Returns the {@link Ext.Toolbar toolbar} from the top (<code>{@link #tbar}</code>) section of the panel.
11316      * @return {Ext.Toolbar} The toolbar
11317      */
11318     getTopToolbar : function(){
11319         return this.topToolbar;
11320     },
11321
11322     /**
11323      * Returns the {@link Ext.Toolbar toolbar} from the bottom (<code>{@link #bbar}</code>) section of the panel.
11324      * @return {Ext.Toolbar} The toolbar
11325      */
11326     getBottomToolbar : function(){
11327         return this.bottomToolbar;
11328     },
11329
11330     /**
11331      * Returns the {@link Ext.Toolbar toolbar} from the footer (<code>{@link #fbar}</code>) section of the panel.
11332      * @return {Ext.Toolbar} The toolbar
11333      */
11334     getFooterToolbar : function() {
11335         return this.fbar;
11336     },
11337
11338     /**
11339      * Adds a button to this panel.  Note that this method must be called prior to rendering.  The preferred
11340      * approach is to add buttons via the {@link #buttons} config.
11341      * @param {String/Object} config A valid {@link Ext.Button} config.  A string will become the text for a default
11342      * button config, an object will be treated as a button config object.
11343      * @param {Function} handler The function to be called on button {@link Ext.Button#click}
11344      * @param {Object} scope The scope (<code>this</code> reference) in which the button handler function is executed. Defaults to the Button.
11345      * @return {Ext.Button} The button that was added
11346      */
11347     addButton : function(config, handler, scope){
11348         if(!this.fbar){
11349             this.createFbar([]);
11350         }
11351         if(handler){
11352             if(Ext.isString(config)){
11353                 config = {text: config};
11354             }
11355             config = Ext.apply({
11356                 handler: handler,
11357                 scope: scope
11358             }, config);
11359         }
11360         return this.fbar.add(config);
11361     },
11362
11363     // private
11364     addTool : function(){
11365         if(!this.rendered){
11366             if(!this.tools){
11367                 this.tools = [];
11368             }
11369             Ext.each(arguments, function(arg){
11370                 this.tools.push(arg);
11371             }, this);
11372             return;
11373         }
11374          // nowhere to render tools!
11375         if(!this[this.toolTarget]){
11376             return;
11377         }
11378         if(!this.toolTemplate){
11379             // initialize the global tool template on first use
11380             var tt = new Ext.Template(
11381                  '<div class="x-tool x-tool-{id}">&#160;</div>'
11382             );
11383             tt.disableFormats = true;
11384             tt.compile();
11385             Ext.Panel.prototype.toolTemplate = tt;
11386         }
11387         for(var i = 0, a = arguments, len = a.length; i < len; i++) {
11388             var tc = a[i];
11389             if(!this.tools[tc.id]){
11390                 var overCls = 'x-tool-'+tc.id+'-over';
11391                 var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
11392                 this.tools[tc.id] = t;
11393                 t.enableDisplayMode('block');
11394                 this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
11395                 if(tc.on){
11396                     this.mon(t, tc.on);
11397                 }
11398                 if(tc.hidden){
11399                     t.hide();
11400                 }
11401                 if(tc.qtip){
11402                     if(Ext.isObject(tc.qtip)){
11403                         Ext.QuickTips.register(Ext.apply({
11404                               target: t.id
11405                         }, tc.qtip));
11406                     } else {
11407                         t.dom.qtip = tc.qtip;
11408                     }
11409                 }
11410                 t.addClassOnOver(overCls);
11411             }
11412         }
11413     },
11414
11415     onLayout : function(shallow, force){
11416         Ext.Panel.superclass.onLayout.apply(this, arguments);
11417         if(this.hasLayout && this.toolbars.length > 0){
11418             Ext.each(this.toolbars, function(tb){
11419                 tb.doLayout(undefined, force);
11420             });
11421             this.syncHeight();
11422         }
11423     },
11424
11425     syncHeight : function(){
11426         var h = this.toolbarHeight,
11427                 bd = this.body,
11428                 lsh = this.lastSize.height,
11429                 sz;
11430
11431         if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
11432             return;
11433         }
11434
11435
11436         if(h != this.getToolbarHeight()){
11437             h = Math.max(0, lsh - this.getFrameHeight());
11438             bd.setHeight(h);
11439             sz = bd.getSize();
11440             this.toolbarHeight = this.getToolbarHeight();
11441             this.onBodyResize(sz.width, sz.height);
11442         }
11443     },
11444
11445     // private
11446     onShow : function(){
11447         if(this.floating){
11448             return this.el.show();
11449         }
11450         Ext.Panel.superclass.onShow.call(this);
11451     },
11452
11453     // private
11454     onHide : function(){
11455         if(this.floating){
11456             return this.el.hide();
11457         }
11458         Ext.Panel.superclass.onHide.call(this);
11459     },
11460
11461     // private
11462     createToolHandler : function(t, tc, overCls, panel){
11463         return function(e){
11464             t.removeClass(overCls);
11465             if(tc.stopEvent !== false){
11466                 e.stopEvent();
11467             }
11468             if(tc.handler){
11469                 tc.handler.call(tc.scope || t, e, t, panel, tc);
11470             }
11471         };
11472     },
11473
11474     // private
11475     afterRender : function(){
11476         if(this.floating && !this.hidden){
11477             this.el.show();
11478         }
11479         if(this.title){
11480             this.setTitle(this.title);
11481         }
11482         Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
11483         if (this.collapsed) {
11484             this.collapsed = false;
11485             this.collapse(false);
11486         }
11487         this.initEvents();
11488     },
11489
11490     // private
11491     getKeyMap : function(){
11492         if(!this.keyMap){
11493             this.keyMap = new Ext.KeyMap(this.el, this.keys);
11494         }
11495         return this.keyMap;
11496     },
11497
11498     // private
11499     initEvents : function(){
11500         if(this.keys){
11501             this.getKeyMap();
11502         }
11503         if(this.draggable){
11504             this.initDraggable();
11505         }
11506         if(this.toolbars.length > 0){
11507             Ext.each(this.toolbars, function(tb){
11508                 tb.doLayout();
11509                 tb.on({
11510                     scope: this,
11511                     afterlayout: this.syncHeight,
11512                     remove: this.syncHeight
11513                 });
11514             }, this);
11515             this.syncHeight();
11516         }
11517
11518     },
11519
11520     // private
11521     initDraggable : function(){
11522         /**
11523          * <p>If this Panel is configured {@link #draggable}, this property will contain
11524          * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.</p>
11525          * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource}
11526          * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
11527          * @type Ext.dd.DragSource.
11528          * @property dd
11529          */
11530         this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
11531     },
11532
11533     // private
11534     beforeEffect : function(anim){
11535         if(this.floating){
11536             this.el.beforeAction();
11537         }
11538         if(anim !== false){
11539             this.el.addClass('x-panel-animated');
11540         }
11541     },
11542
11543     // private
11544     afterEffect : function(anim){
11545         this.syncShadow();
11546         this.el.removeClass('x-panel-animated');
11547     },
11548
11549     // private - wraps up an animation param with internal callbacks
11550     createEffect : function(a, cb, scope){
11551         var o = {
11552             scope:scope,
11553             block:true
11554         };
11555         if(a === true){
11556             o.callback = cb;
11557             return o;
11558         }else if(!a.callback){
11559             o.callback = cb;
11560         }else { // wrap it up
11561             o.callback = function(){
11562                 cb.call(scope);
11563                 Ext.callback(a.callback, a.scope);
11564             };
11565         }
11566         return Ext.applyIf(o, a);
11567     },
11568
11569     /**
11570      * Collapses the panel body so that it becomes hidden.  Fires the {@link #beforecollapse} event which will
11571      * cancel the collapse action if it returns false.
11572      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
11573      * {@link #animCollapse} panel config)
11574      * @return {Ext.Panel} this
11575      */
11576     collapse : function(animate){
11577         if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
11578             return;
11579         }
11580         var doAnim = animate === true || (animate !== false && this.animCollapse);
11581         this.beforeEffect(doAnim);
11582         this.onCollapse(doAnim, animate);
11583         return this;
11584     },
11585
11586     // private
11587     onCollapse : function(doAnim, animArg){
11588         if(doAnim){
11589             this[this.collapseEl].slideOut(this.slideAnchor,
11590                     Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
11591                         this.collapseDefaults));
11592         }else{
11593             this[this.collapseEl].hide(this.hideMode);
11594             this.afterCollapse(false);
11595         }
11596     },
11597
11598     // private
11599     afterCollapse : function(anim){
11600         this.collapsed = true;
11601         this.el.addClass(this.collapsedCls);
11602         if(anim !== false){
11603             this[this.collapseEl].hide(this.hideMode);
11604         }
11605         this.afterEffect(anim);
11606
11607         // Reset lastSize of all sub-components so they KNOW they are in a collapsed container
11608         this.cascade(function(c) {
11609             if (c.lastSize) {
11610                 c.lastSize = { width: undefined, height: undefined };
11611             }
11612         });
11613         this.fireEvent('collapse', this);
11614     },
11615
11616     /**
11617      * Expands the panel body so that it becomes visible.  Fires the {@link #beforeexpand} event which will
11618      * cancel the expand action if it returns false.
11619      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
11620      * {@link #animCollapse} panel config)
11621      * @return {Ext.Panel} this
11622      */
11623     expand : function(animate){
11624         if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
11625             return;
11626         }
11627         var doAnim = animate === true || (animate !== false && this.animCollapse);
11628         this.el.removeClass(this.collapsedCls);
11629         this.beforeEffect(doAnim);
11630         this.onExpand(doAnim, animate);
11631         return this;
11632     },
11633
11634     // private
11635     onExpand : function(doAnim, animArg){
11636         if(doAnim){
11637             this[this.collapseEl].slideIn(this.slideAnchor,
11638                     Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
11639                         this.expandDefaults));
11640         }else{
11641             this[this.collapseEl].show(this.hideMode);
11642             this.afterExpand(false);
11643         }
11644     },
11645
11646     // private
11647     afterExpand : function(anim){
11648         this.collapsed = false;
11649         if(anim !== false){
11650             this[this.collapseEl].show(this.hideMode);
11651         }
11652         this.afterEffect(anim);
11653         if (this.deferLayout) {
11654             delete this.deferLayout;
11655             this.doLayout(true);
11656         }
11657         this.fireEvent('expand', this);
11658     },
11659
11660     /**
11661      * Shortcut for performing an {@link #expand} or {@link #collapse} based on the current state of the panel.
11662      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
11663      * {@link #animCollapse} panel config)
11664      * @return {Ext.Panel} this
11665      */
11666     toggleCollapse : function(animate){
11667         this[this.collapsed ? 'expand' : 'collapse'](animate);
11668         return this;
11669     },
11670
11671     // private
11672     onDisable : function(){
11673         if(this.rendered && this.maskDisabled){
11674             this.el.mask();
11675         }
11676         Ext.Panel.superclass.onDisable.call(this);
11677     },
11678
11679     // private
11680     onEnable : function(){
11681         if(this.rendered && this.maskDisabled){
11682             this.el.unmask();
11683         }
11684         Ext.Panel.superclass.onEnable.call(this);
11685     },
11686
11687     // private
11688     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
11689         var w = adjWidth,
11690             h = adjHeight;
11691
11692         if(Ext.isDefined(w) || Ext.isDefined(h)){
11693             if(!this.collapsed){
11694                 // First, set the the Panel's body width.
11695                 // If we have auto-widthed it, get the resulting full offset width so we can size the Toolbars to match
11696                 // The Toolbars must not buffer this resize operation because we need to know their heights.
11697
11698                 if(Ext.isNumber(w)){
11699                     this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
11700                 } else if (w == 'auto') {
11701                     w = this.body.setWidth('auto').dom.offsetWidth;
11702                 } else {
11703                     w = this.body.dom.offsetWidth;
11704                 }
11705
11706                 if(this.tbar){
11707                     this.tbar.setWidth(w);
11708                     if(this.topToolbar){
11709                         this.topToolbar.setSize(w);
11710                     }
11711                 }
11712                 if(this.bbar){
11713                     this.bbar.setWidth(w);
11714                     if(this.bottomToolbar){
11715                         this.bottomToolbar.setSize(w);
11716                         // The bbar does not move on resize without this.
11717                         if (Ext.isIE) {
11718                             this.bbar.setStyle('position', 'static');
11719                             this.bbar.setStyle('position', '');
11720                         }
11721                     }
11722                 }
11723                 if(this.footer){
11724                     this.footer.setWidth(w);
11725                     if(this.fbar){
11726                         this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
11727                     }
11728                 }
11729
11730                 // At this point, the Toolbars must be layed out for getFrameHeight to find a result.
11731                 if(Ext.isNumber(h)){
11732                     h = Math.max(0, h - this.getFrameHeight());
11733                     //h = Math.max(0, h - (this.getHeight() - this.body.getHeight()));
11734                     this.body.setHeight(h);
11735                 }else if(h == 'auto'){
11736                     this.body.setHeight(h);
11737                 }
11738
11739                 if(this.disabled && this.el._mask){
11740                     this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
11741                 }
11742             }else{
11743                 // Adds an event to set the correct height afterExpand.  This accounts for the deferHeight flag in panel
11744                 this.queuedBodySize = {width: w, height: h};
11745                 if(!this.queuedExpand && this.allowQueuedExpand !== false){
11746                     this.queuedExpand = true;
11747                     this.on('expand', function(){
11748                         delete this.queuedExpand;
11749                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
11750                     }, this, {single:true});
11751                 }
11752             }
11753             this.onBodyResize(w, h);
11754         }
11755         this.syncShadow();
11756         Ext.Panel.superclass.onResize.call(this, adjWidth, adjHeight, rawWidth, rawHeight);
11757
11758     },
11759
11760     // private
11761     onBodyResize: function(w, h){
11762         this.fireEvent('bodyresize', this, w, h);
11763     },
11764
11765     // private
11766     getToolbarHeight: function(){
11767         var h = 0;
11768         if(this.rendered){
11769             Ext.each(this.toolbars, function(tb){
11770                 h += tb.getHeight();
11771             }, this);
11772         }
11773         return h;
11774     },
11775
11776     // deprecate
11777     adjustBodyHeight : function(h){
11778         return h;
11779     },
11780
11781     // private
11782     adjustBodyWidth : function(w){
11783         return w;
11784     },
11785
11786     // private
11787     onPosition : function(){
11788         this.syncShadow();
11789     },
11790
11791     /**
11792      * Returns the width in pixels of the framing elements of this panel (not including the body width).  To
11793      * retrieve the body width see {@link #getInnerWidth}.
11794      * @return {Number} The frame width
11795      */
11796     getFrameWidth : function(){
11797         var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
11798
11799         if(this.frame){
11800             var l = this.bwrap.dom.firstChild;
11801             w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
11802             w += this.mc.getFrameWidth('lr');
11803         }
11804         return w;
11805     },
11806
11807     /**
11808      * Returns the height in pixels of the framing elements of this panel (including any top and bottom bars and
11809      * header and footer elements, but not including the body height).  To retrieve the body height see {@link #getInnerHeight}.
11810      * @return {Number} The frame height
11811      */
11812     getFrameHeight : function() {
11813         var h  = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
11814         h += (this.tbar ? this.tbar.getHeight() : 0) +
11815              (this.bbar ? this.bbar.getHeight() : 0);
11816
11817         if(this.frame){
11818             h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
11819         }else{
11820             h += (this.header ? this.header.getHeight() : 0) +
11821                 (this.footer ? this.footer.getHeight() : 0);
11822         }
11823         return h;
11824     },
11825
11826     /**
11827      * Returns the width in pixels of the body element (not including the width of any framing elements).
11828      * For the frame width see {@link #getFrameWidth}.
11829      * @return {Number} The body width
11830      */
11831     getInnerWidth : function(){
11832         return this.getSize().width - this.getFrameWidth();
11833     },
11834
11835     /**
11836      * Returns the height in pixels of the body element (not including the height of any framing elements).
11837      * For the frame height see {@link #getFrameHeight}.
11838      * @return {Number} The body height
11839      */
11840     getInnerHeight : function(){
11841         return this.body.getHeight();
11842         /* Deprecate
11843             return this.getSize().height - this.getFrameHeight();
11844         */
11845     },
11846
11847     // private
11848     syncShadow : function(){
11849         if(this.floating){
11850             this.el.sync(true);
11851         }
11852     },
11853
11854     // private
11855     getLayoutTarget : function(){
11856         return this.body;
11857     },
11858
11859     // private
11860     getContentTarget : function(){
11861         return this.body;
11862     },
11863
11864     /**
11865      * <p>Sets the title text for the panel and optionally the {@link #iconCls icon class}.</p>
11866      * <p>In order to be able to set the title, a header element must have been created
11867      * for the Panel. This is triggered either by configuring the Panel with a non-blank <code>{@link #title}</code>,
11868      * or configuring it with <code><b>{@link #header}: true</b></code>.</p>
11869      * @param {String} title The title text to set
11870      * @param {String} iconCls (optional) {@link #iconCls iconCls} A user-defined CSS class that provides the icon image for this panel
11871      */
11872     setTitle : function(title, iconCls){
11873         this.title = title;
11874         if(this.header && this.headerAsText){
11875             this.header.child('span').update(title);
11876         }
11877         if(iconCls){
11878             this.setIconClass(iconCls);
11879         }
11880         this.fireEvent('titlechange', this, title);
11881         return this;
11882     },
11883
11884     /**
11885      * Get the {@link Ext.Updater} for this panel. Enables you to perform Ajax updates of this panel's body.
11886      * @return {Ext.Updater} The Updater
11887      */
11888     getUpdater : function(){
11889         return this.body.getUpdater();
11890     },
11891
11892      /**
11893      * Loads this content panel immediately with content returned from an XHR call.
11894      * @param {Object/String/Function} config A config object containing any of the following options:
11895 <pre><code>
11896 panel.load({
11897     url: 'your-url.php',
11898     params: {param1: 'foo', param2: 'bar'}, // or a URL encoded string
11899     callback: yourFunction,
11900     scope: yourObject, // optional scope for the callback
11901     discardUrl: false,
11902     nocache: false,
11903     text: 'Loading...',
11904     timeout: 30,
11905     scripts: false
11906 });
11907 </code></pre>
11908      * The only required property is url. The optional properties nocache, text and scripts
11909      * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their
11910      * associated property on this panel Updater instance.
11911      * @return {Ext.Panel} this
11912      */
11913     load : function(){
11914         var um = this.body.getUpdater();
11915         um.update.apply(um, arguments);
11916         return this;
11917     },
11918
11919     // private
11920     beforeDestroy : function(){
11921         Ext.Panel.superclass.beforeDestroy.call(this);
11922         if(this.header){
11923             this.header.removeAllListeners();
11924         }
11925         if(this.tools){
11926             for(var k in this.tools){
11927                 Ext.destroy(this.tools[k]);
11928             }
11929         }
11930         if(this.toolbars.length > 0){
11931             Ext.each(this.toolbars, function(tb){
11932                 tb.un('afterlayout', this.syncHeight, this);
11933                 tb.un('remove', this.syncHeight, this);
11934             }, this);
11935         }
11936         if(Ext.isArray(this.buttons)){
11937             while(this.buttons.length) {
11938                 Ext.destroy(this.buttons[0]);
11939             }
11940         }
11941         if(this.rendered){
11942             Ext.destroy(
11943                 this.ft,
11944                 this.header,
11945                 this.footer,
11946                 this.tbar,
11947                 this.bbar,
11948                 this.body,
11949                 this.mc,
11950                 this.bwrap,
11951                 this.dd
11952             );
11953             if (this.fbar) {
11954                 Ext.destroy(
11955                     this.fbar,
11956                     this.fbar.el
11957                 );
11958             }
11959         }
11960         Ext.destroy(this.toolbars);
11961     },
11962
11963     // private
11964     createClasses : function(){
11965         this.headerCls = this.baseCls + '-header';
11966         this.headerTextCls = this.baseCls + '-header-text';
11967         this.bwrapCls = this.baseCls + '-bwrap';
11968         this.tbarCls = this.baseCls + '-tbar';
11969         this.bodyCls = this.baseCls + '-body';
11970         this.bbarCls = this.baseCls + '-bbar';
11971         this.footerCls = this.baseCls + '-footer';
11972     },
11973
11974     // private
11975     createGhost : function(cls, useShim, appendTo){
11976         var el = document.createElement('div');
11977         el.className = 'x-panel-ghost ' + (cls ? cls : '');
11978         if(this.header){
11979             el.appendChild(this.el.dom.firstChild.cloneNode(true));
11980         }
11981         Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
11982         el.style.width = this.el.dom.offsetWidth + 'px';;
11983         if(!appendTo){
11984             this.container.dom.appendChild(el);
11985         }else{
11986             Ext.getDom(appendTo).appendChild(el);
11987         }
11988         if(useShim !== false && this.el.useShim !== false){
11989             var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
11990             layer.show();
11991             return layer;
11992         }else{
11993             return new Ext.Element(el);
11994         }
11995     },
11996
11997     // private
11998     doAutoLoad : function(){
11999         var u = this.body.getUpdater();
12000         if(this.renderer){
12001             u.setRenderer(this.renderer);
12002         }
12003         u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
12004     },
12005
12006     /**
12007      * Retrieve a tool by id.
12008      * @param {String} id
12009      * @return {Object} tool
12010      */
12011     getTool : function(id) {
12012         return this.tools[id];
12013     }
12014
12015 /**
12016  * @cfg {String} autoEl @hide
12017  */
12018 });
12019 Ext.reg('panel', Ext.Panel);
12020 /**
12021  * @class Ext.Editor
12022  * @extends Ext.Component
12023  * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
12024  * @constructor
12025  * Create a new Editor
12026  * @param {Object} config The config object
12027  * @xtype editor
12028  */
12029 Ext.Editor = function(field, config){
12030     if(field.field){
12031         this.field = Ext.create(field.field, 'textfield');
12032         config = Ext.apply({}, field); // copy so we don't disturb original config
12033         delete config.field;
12034     }else{
12035         this.field = field;
12036     }
12037     Ext.Editor.superclass.constructor.call(this, config);
12038 };
12039
12040 Ext.extend(Ext.Editor, Ext.Component, {
12041     /**
12042     * @cfg {Ext.form.Field} field
12043     * The Field object (or descendant) or config object for field
12044     */
12045     /**
12046      * @cfg {Boolean} allowBlur
12047      * True to {@link #completeEdit complete the editing process} if in edit mode when the
12048      * field is blurred. Defaults to <tt>true</tt>.
12049      */
12050     allowBlur: true,
12051     /**
12052      * @cfg {Boolean/String} autoSize
12053      * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only,
12054      * or "height" to adopt the height only, "none" to always use the field dimensions. (defaults to false)
12055      */
12056     /**
12057      * @cfg {Boolean} revertInvalid
12058      * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
12059      * validation fails (defaults to true)
12060      */
12061     /**
12062      * @cfg {Boolean} ignoreNoChange
12063      * True to skip the edit completion process (no save, no events fired) if the user completes an edit and
12064      * the value has not changed (defaults to false).  Applies only to string values - edits for other data types
12065      * will never be ignored.
12066      */
12067     /**
12068      * @cfg {Boolean} hideEl
12069      * False to keep the bound element visible while the editor is displayed (defaults to true)
12070      */
12071     /**
12072      * @cfg {Mixed} value
12073      * The data value of the underlying field (defaults to "")
12074      */
12075     value : "",
12076     /**
12077      * @cfg {String} alignment
12078      * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?").
12079      */
12080     alignment: "c-c?",
12081     /**
12082      * @cfg {Array} offsets
12083      * The offsets to use when aligning (see {@link Ext.Element#alignTo} for more details. Defaults to <tt>[0, 0]</tt>.
12084      */
12085     offsets: [0, 0],
12086     /**
12087      * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
12088      * for bottom-right shadow (defaults to "frame")
12089      */
12090     shadow : "frame",
12091     /**
12092      * @cfg {Boolean} constrain True to constrain the editor to the viewport
12093      */
12094     constrain : false,
12095     /**
12096      * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true)
12097      */
12098     swallowKeys : true,
12099     /**
12100      * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed. Defaults to <tt>true</tt>.
12101      */
12102     completeOnEnter : true,
12103     /**
12104      * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed. Defaults to <tt>true</tt>.
12105      */
12106     cancelOnEsc : true,
12107     /**
12108      * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
12109      */
12110     updateEl : false,
12111
12112     initComponent : function(){
12113         Ext.Editor.superclass.initComponent.call(this);
12114         this.addEvents(
12115             /**
12116              * @event beforestartedit
12117              * Fires when editing is initiated, but before the value changes.  Editing can be canceled by returning
12118              * false from the handler of this event.
12119              * @param {Editor} this
12120              * @param {Ext.Element} boundEl The underlying element bound to this editor
12121              * @param {Mixed} value The field value being set
12122              */
12123             "beforestartedit",
12124             /**
12125              * @event startedit
12126              * Fires when this editor is displayed
12127              * @param {Ext.Element} boundEl The underlying element bound to this editor
12128              * @param {Mixed} value The starting field value
12129              */
12130             "startedit",
12131             /**
12132              * @event beforecomplete
12133              * Fires after a change has been made to the field, but before the change is reflected in the underlying
12134              * field.  Saving the change to the field can be canceled by returning false from the handler of this event.
12135              * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
12136              * event will not fire since no edit actually occurred.
12137              * @param {Editor} this
12138              * @param {Mixed} value The current field value
12139              * @param {Mixed} startValue The original field value
12140              */
12141             "beforecomplete",
12142             /**
12143              * @event complete
12144              * Fires after editing is complete and any changed value has been written to the underlying field.
12145              * @param {Editor} this
12146              * @param {Mixed} value The current field value
12147              * @param {Mixed} startValue The original field value
12148              */
12149             "complete",
12150             /**
12151              * @event canceledit
12152              * Fires after editing has been canceled and the editor's value has been reset.
12153              * @param {Editor} this
12154              * @param {Mixed} value The user-entered field value that was discarded
12155              * @param {Mixed} startValue The original field value that was set back into the editor after cancel
12156              */
12157             "canceledit",
12158             /**
12159              * @event specialkey
12160              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
12161              * {@link Ext.EventObject#getKey} to determine which key was pressed.
12162              * @param {Ext.form.Field} this
12163              * @param {Ext.EventObject} e The event object
12164              */
12165             "specialkey"
12166         );
12167     },
12168
12169     // private
12170     onRender : function(ct, position){
12171         this.el = new Ext.Layer({
12172             shadow: this.shadow,
12173             cls: "x-editor",
12174             parentEl : ct,
12175             shim : this.shim,
12176             shadowOffset: this.shadowOffset || 4,
12177             id: this.id,
12178             constrain: this.constrain
12179         });
12180         if(this.zIndex){
12181             this.el.setZIndex(this.zIndex);
12182         }
12183         this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
12184         if(this.field.msgTarget != 'title'){
12185             this.field.msgTarget = 'qtip';
12186         }
12187         this.field.inEditor = true;
12188         this.mon(this.field, {
12189             scope: this,
12190             blur: this.onBlur,
12191             specialkey: this.onSpecialKey
12192         });
12193         if(this.field.grow){
12194             this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
12195         }
12196         this.field.render(this.el).show();
12197         this.field.getEl().dom.name = '';
12198         if(this.swallowKeys){
12199             this.field.el.swallowEvent([
12200                 'keypress', // *** Opera
12201                 'keydown'   // *** all other browsers
12202             ]);
12203         }
12204     },
12205
12206     // private
12207     onSpecialKey : function(field, e){
12208         var key = e.getKey(),
12209             complete = this.completeOnEnter && key == e.ENTER,
12210             cancel = this.cancelOnEsc && key == e.ESC;
12211         if(complete || cancel){
12212             e.stopEvent();
12213             if(complete){
12214                 this.completeEdit();
12215             }else{
12216                 this.cancelEdit();
12217             }
12218             if(field.triggerBlur){
12219                 field.triggerBlur();
12220             }
12221         }
12222         this.fireEvent('specialkey', field, e);
12223     },
12224
12225     /**
12226      * Starts the editing process and shows the editor.
12227      * @param {Mixed} el The element to edit
12228      * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
12229       * to the innerHTML of el.
12230      */
12231     startEdit : function(el, value){
12232         if(this.editing){
12233             this.completeEdit();
12234         }
12235         this.boundEl = Ext.get(el);
12236         var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
12237         if(!this.rendered){
12238             this.render(this.parentEl || document.body);
12239         }
12240         if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
12241             this.startValue = v;
12242             this.field.reset();
12243             this.field.setValue(v);
12244             this.realign(true);
12245             this.editing = true;
12246             this.show();
12247         }
12248     },
12249
12250     // private
12251     doAutoSize : function(){
12252         if(this.autoSize){
12253             var sz = this.boundEl.getSize(),
12254                 fs = this.field.getSize();
12255
12256             switch(this.autoSize){
12257                 case "width":
12258                     this.setSize(sz.width, fs.height);
12259                     break;
12260                 case "height":
12261                     this.setSize(fs.width, sz.height);
12262                     break;
12263                 case "none":
12264                     this.setSize(fs.width, fs.height);
12265                     break;
12266                 default:
12267                     this.setSize(sz.width, sz.height);
12268             }
12269         }
12270     },
12271
12272     /**
12273      * Sets the height and width of this editor.
12274      * @param {Number} width The new width
12275      * @param {Number} height The new height
12276      */
12277     setSize : function(w, h){
12278         delete this.field.lastSize;
12279         this.field.setSize(w, h);
12280         if(this.el){
12281             // IE7 in strict mode doesn't size properly.
12282             if(Ext.isGecko2 || Ext.isOpera || (Ext.isIE7 && Ext.isStrict)){
12283                 // prevent layer scrollbars
12284                 this.el.setSize(w, h);
12285             }
12286             this.el.sync();
12287         }
12288     },
12289
12290     /**
12291      * Realigns the editor to the bound field based on the current alignment config value.
12292      * @param {Boolean} autoSize (optional) True to size the field to the dimensions of the bound element.
12293      */
12294     realign : function(autoSize){
12295         if(autoSize === true){
12296             this.doAutoSize();
12297         }
12298         this.el.alignTo(this.boundEl, this.alignment, this.offsets);
12299     },
12300
12301     /**
12302      * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
12303      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
12304      */
12305     completeEdit : function(remainVisible){
12306         if(!this.editing){
12307             return;
12308         }
12309         // Assert combo values first
12310         if (this.field.assertValue) {
12311             this.field.assertValue();
12312         }
12313         var v = this.getValue();
12314         if(!this.field.isValid()){
12315             if(this.revertInvalid !== false){
12316                 this.cancelEdit(remainVisible);
12317             }
12318             return;
12319         }
12320         if(String(v) === String(this.startValue) && this.ignoreNoChange){
12321             this.hideEdit(remainVisible);
12322             return;
12323         }
12324         if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
12325             v = this.getValue();
12326             if(this.updateEl && this.boundEl){
12327                 this.boundEl.update(v);
12328             }
12329             this.hideEdit(remainVisible);
12330             this.fireEvent("complete", this, v, this.startValue);
12331         }
12332     },
12333
12334     // private
12335     onShow : function(){
12336         this.el.show();
12337         if(this.hideEl !== false){
12338             this.boundEl.hide();
12339         }
12340         this.field.show().focus(false, true);
12341         this.fireEvent("startedit", this.boundEl, this.startValue);
12342     },
12343
12344     /**
12345      * Cancels the editing process and hides the editor without persisting any changes.  The field value will be
12346      * reverted to the original starting value.
12347      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
12348      * cancel (defaults to false)
12349      */
12350     cancelEdit : function(remainVisible){
12351         if(this.editing){
12352             var v = this.getValue();
12353             this.setValue(this.startValue);
12354             this.hideEdit(remainVisible);
12355             this.fireEvent("canceledit", this, v, this.startValue);
12356         }
12357     },
12358
12359     // private
12360     hideEdit: function(remainVisible){
12361         if(remainVisible !== true){
12362             this.editing = false;
12363             this.hide();
12364         }
12365     },
12366
12367     // private
12368     onBlur : function(){
12369         // selectSameEditor flag allows the same editor to be started without onBlur firing on itself
12370         if(this.allowBlur === true && this.editing && this.selectSameEditor !== true){
12371             this.completeEdit();
12372         }
12373     },
12374
12375     // private
12376     onHide : function(){
12377         if(this.editing){
12378             this.completeEdit();
12379             return;
12380         }
12381         this.field.blur();
12382         if(this.field.collapse){
12383             this.field.collapse();
12384         }
12385         this.el.hide();
12386         if(this.hideEl !== false){
12387             this.boundEl.show();
12388         }
12389     },
12390
12391     /**
12392      * Sets the data value of the editor
12393      * @param {Mixed} value Any valid value supported by the underlying field
12394      */
12395     setValue : function(v){
12396         this.field.setValue(v);
12397     },
12398
12399     /**
12400      * Gets the data value of the editor
12401      * @return {Mixed} The data value
12402      */
12403     getValue : function(){
12404         return this.field.getValue();
12405     },
12406
12407     beforeDestroy : function(){
12408         Ext.destroyMembers(this, 'field');
12409
12410         delete this.parentEl;
12411         delete this.boundEl;
12412     }
12413 });
12414 Ext.reg('editor', Ext.Editor);
12415 /**
12416  * @class Ext.ColorPalette
12417  * @extends Ext.Component
12418  * Simple color palette class for choosing colors.  The palette can be rendered to any container.<br />
12419  * Here's an example of typical usage:
12420  * <pre><code>
12421 var cp = new Ext.ColorPalette({value:'993300'});  // initial selected color
12422 cp.render('my-div');
12423
12424 cp.on('select', function(palette, selColor){
12425     // do something with selColor
12426 });
12427 </code></pre>
12428  * @constructor
12429  * Create a new ColorPalette
12430  * @param {Object} config The config object
12431  * @xtype colorpalette
12432  */
12433 Ext.ColorPalette = Ext.extend(Ext.Component, {
12434         /**
12435          * @cfg {String} tpl An existing XTemplate instance to be used in place of the default template for rendering the component.
12436          */
12437     /**
12438      * @cfg {String} itemCls
12439      * The CSS class to apply to the containing element (defaults to 'x-color-palette')
12440      */
12441     itemCls : 'x-color-palette',
12442     /**
12443      * @cfg {String} value
12444      * The initial color to highlight (should be a valid 6-digit color hex code without the # symbol).  Note that
12445      * the hex codes are case-sensitive.
12446      */
12447     value : null,
12448     /**
12449      * @cfg {String} clickEvent
12450      * The DOM event that will cause a color to be selected. This can be any valid event name (dblclick, contextmenu). 
12451      * Defaults to <tt>'click'</tt>.
12452      */
12453     clickEvent :'click',
12454     // private
12455     ctype : 'Ext.ColorPalette',
12456
12457     /**
12458      * @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the {@link #select} event
12459      */
12460     allowReselect : false,
12461
12462     /**
12463      * <p>An array of 6-digit color hex code strings (without the # symbol).  This array can contain any number
12464      * of colors, and each hex code should be unique.  The width of the palette is controlled via CSS by adjusting
12465      * the width property of the 'x-color-palette' class (or assigning a custom class), so you can balance the number
12466      * of colors with the width setting until the box is symmetrical.</p>
12467      * <p>You can override individual colors if needed:</p>
12468      * <pre><code>
12469 var cp = new Ext.ColorPalette();
12470 cp.colors[0] = 'FF0000';  // change the first box to red
12471 </code></pre>
12472
12473 Or you can provide a custom array of your own for complete control:
12474 <pre><code>
12475 var cp = new Ext.ColorPalette();
12476 cp.colors = ['000000', '993300', '333300'];
12477 </code></pre>
12478      * @type Array
12479      */
12480     colors : [
12481         '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
12482         '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
12483         'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
12484         'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
12485         'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
12486     ],
12487
12488     /**
12489      * @cfg {Function} handler
12490      * Optional. A function that will handle the select event of this palette.
12491      * The handler is passed the following parameters:<div class="mdetail-params"><ul>
12492      * <li><code>palette</code> : ColorPalette<div class="sub-desc">The {@link #palette Ext.ColorPalette}.</div></li>
12493      * <li><code>color</code> : String<div class="sub-desc">The 6-digit color hex code (without the # symbol).</div></li>
12494      * </ul></div>
12495      */
12496     /**
12497      * @cfg {Object} scope
12498      * The scope (<tt><b>this</b></tt> reference) in which the <code>{@link #handler}</code>
12499      * function will be called.  Defaults to this ColorPalette instance.
12500      */
12501     
12502     // private
12503     initComponent : function(){
12504         Ext.ColorPalette.superclass.initComponent.call(this);
12505         this.addEvents(
12506             /**
12507              * @event select
12508              * Fires when a color is selected
12509              * @param {ColorPalette} this
12510              * @param {String} color The 6-digit color hex code (without the # symbol)
12511              */
12512             'select'
12513         );
12514
12515         if(this.handler){
12516             this.on('select', this.handler, this.scope, true);
12517         }    
12518     },
12519
12520     // private
12521     onRender : function(container, position){
12522         this.autoEl = {
12523             tag: 'div',
12524             cls: this.itemCls
12525         };
12526         Ext.ColorPalette.superclass.onRender.call(this, container, position);
12527         var t = this.tpl || new Ext.XTemplate(
12528             '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
12529         );
12530         t.overwrite(this.el, this.colors);
12531         this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
12532         if(this.clickEvent != 'click'){
12533                 this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
12534         }
12535     },
12536
12537     // private
12538     afterRender : function(){
12539         Ext.ColorPalette.superclass.afterRender.call(this);
12540         if(this.value){
12541             var s = this.value;
12542             this.value = null;
12543             this.select(s, true);
12544         }
12545     },
12546
12547     // private
12548     handleClick : function(e, t){
12549         e.preventDefault();
12550         if(!this.disabled){
12551             var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
12552             this.select(c.toUpperCase());
12553         }
12554     },
12555
12556     /**
12557      * Selects the specified color in the palette (fires the {@link #select} event)
12558      * @param {String} color A valid 6-digit color hex code (# will be stripped if included)
12559      * @param {Boolean} suppressEvent (optional) True to stop the select event from firing. Defaults to <tt>false</tt>.
12560      */
12561     select : function(color, suppressEvent){
12562         color = color.replace('#', '');
12563         if(color != this.value || this.allowReselect){
12564             var el = this.el;
12565             if(this.value){
12566                 el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
12567             }
12568             el.child('a.color-'+color).addClass('x-color-palette-sel');
12569             this.value = color;
12570             if(suppressEvent !== true){
12571                 this.fireEvent('select', this, color);
12572             }
12573         }
12574     }
12575
12576     /**
12577      * @cfg {String} autoEl @hide
12578      */
12579 });
12580 Ext.reg('colorpalette', Ext.ColorPalette);/**
12581  * @class Ext.DatePicker
12582  * @extends Ext.Component
12583  * <p>A popup date picker. This class is used by the {@link Ext.form.DateField DateField} class
12584  * to allow browsing and selection of valid dates.</p>
12585  * <p>All the string values documented below may be overridden by including an Ext locale file in
12586  * your page.</p>
12587  * @constructor
12588  * Create a new DatePicker
12589  * @param {Object} config The config object
12590  * @xtype datepicker
12591  */
12592 Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
12593     /**
12594      * @cfg {String} todayText
12595      * The text to display on the button that selects the current date (defaults to <code>'Today'</code>)
12596      */
12597     todayText : 'Today',
12598     /**
12599      * @cfg {String} okText
12600      * The text to display on the ok button (defaults to <code>'&#160;OK&#160;'</code> to give the user extra clicking room)
12601      */
12602     okText : '&#160;OK&#160;',
12603     /**
12604      * @cfg {String} cancelText
12605      * The text to display on the cancel button (defaults to <code>'Cancel'</code>)
12606      */
12607     cancelText : 'Cancel',
12608     /**
12609      * @cfg {Function} handler
12610      * Optional. A function that will handle the select event of this picker.
12611      * The handler is passed the following parameters:<div class="mdetail-params"><ul>
12612      * <li><code>picker</code> : DatePicker<div class="sub-desc">This DatePicker.</div></li>
12613      * <li><code>date</code> : Date<div class="sub-desc">The selected date.</div></li>
12614      * </ul></div>
12615      */
12616     /**
12617      * @cfg {Object} scope
12618      * The scope (<code><b>this</b></code> reference) in which the <code>{@link #handler}</code>
12619      * function will be called.  Defaults to this DatePicker instance.
12620      */
12621     /**
12622      * @cfg {String} todayTip
12623      * A string used to format the message for displaying in a tooltip over the button that
12624      * selects the current date. Defaults to <code>'{0} (Spacebar)'</code> where
12625      * the <code>{0}</code> token is replaced by today's date.
12626      */
12627     todayTip : '{0} (Spacebar)',
12628     /**
12629      * @cfg {String} minText
12630      * The error text to display if the minDate validation fails (defaults to <code>'This date is before the minimum date'</code>)
12631      */
12632     minText : 'This date is before the minimum date',
12633     /**
12634      * @cfg {String} maxText
12635      * The error text to display if the maxDate validation fails (defaults to <code>'This date is after the maximum date'</code>)
12636      */
12637     maxText : 'This date is after the maximum date',
12638     /**
12639      * @cfg {String} format
12640      * The default date format string which can be overriden for localization support.  The format must be
12641      * valid according to {@link Date#parseDate} (defaults to <code>'m/d/y'</code>).
12642      */
12643     format : 'm/d/y',
12644     /**
12645      * @cfg {String} disabledDaysText
12646      * The tooltip to display when the date falls on a disabled day (defaults to <code>'Disabled'</code>)
12647      */
12648     disabledDaysText : 'Disabled',
12649     /**
12650      * @cfg {String} disabledDatesText
12651      * The tooltip text to display when the date falls on a disabled date (defaults to <code>'Disabled'</code>)
12652      */
12653     disabledDatesText : 'Disabled',
12654     /**
12655      * @cfg {Array} monthNames
12656      * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
12657      */
12658     monthNames : Date.monthNames,
12659     /**
12660      * @cfg {Array} dayNames
12661      * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
12662      */
12663     dayNames : Date.dayNames,
12664     /**
12665      * @cfg {String} nextText
12666      * The next month navigation button tooltip (defaults to <code>'Next Month (Control+Right)'</code>)
12667      */
12668     nextText : 'Next Month (Control+Right)',
12669     /**
12670      * @cfg {String} prevText
12671      * The previous month navigation button tooltip (defaults to <code>'Previous Month (Control+Left)'</code>)
12672      */
12673     prevText : 'Previous Month (Control+Left)',
12674     /**
12675      * @cfg {String} monthYearText
12676      * The header month selector tooltip (defaults to <code>'Choose a month (Control+Up/Down to move years)'</code>)
12677      */
12678     monthYearText : 'Choose a month (Control+Up/Down to move years)',
12679     /**
12680      * @cfg {Number} startDay
12681      * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
12682      */
12683     startDay : 0,
12684     /**
12685      * @cfg {Boolean} showToday
12686      * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar
12687      * that selects the current date (defaults to <code>true</code>).
12688      */
12689     showToday : true,
12690     /**
12691      * @cfg {Date} minDate
12692      * Minimum allowable date (JavaScript date object, defaults to null)
12693      */
12694     /**
12695      * @cfg {Date} maxDate
12696      * Maximum allowable date (JavaScript date object, defaults to null)
12697      */
12698     /**
12699      * @cfg {Array} disabledDays
12700      * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
12701      */
12702     /**
12703      * @cfg {RegExp} disabledDatesRE
12704      * JavaScript regular expression used to disable a pattern of dates (defaults to null).  The {@link #disabledDates}
12705      * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the
12706      * disabledDates value.
12707      */
12708     /**
12709      * @cfg {Array} disabledDates
12710      * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular
12711      * expression so they are very powerful. Some examples:
12712      * <ul>
12713      * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>
12714      * <li>['03/08', '09/16'] would disable those days for every year</li>
12715      * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>
12716      * <li>['03/../2006'] would disable every day in March 2006</li>
12717      * <li>['^03'] would disable every day in every March</li>
12718      * </ul>
12719      * Note that the format of the dates included in the array should exactly match the {@link #format} config.
12720      * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to
12721      * escape the dot when restricting dates. For example: ['03\\.08\\.03'].
12722      */
12723
12724     // private
12725     // Set by other components to stop the picker focus being updated when the value changes.
12726     focusOnSelect: true,
12727
12728     // default value used to initialise each date in the DatePicker
12729     // (note: 12 noon was chosen because it steers well clear of all DST timezone changes)
12730     initHour: 12, // 24-hour format
12731
12732     // private
12733     initComponent : function(){
12734         Ext.DatePicker.superclass.initComponent.call(this);
12735
12736         this.value = this.value ?
12737                  this.value.clearTime(true) : new Date().clearTime();
12738
12739         this.addEvents(
12740             /**
12741              * @event select
12742              * Fires when a date is selected
12743              * @param {DatePicker} this DatePicker
12744              * @param {Date} date The selected date
12745              */
12746             'select'
12747         );
12748
12749         if(this.handler){
12750             this.on('select', this.handler,  this.scope || this);
12751         }
12752
12753         this.initDisabledDays();
12754     },
12755
12756     // private
12757     initDisabledDays : function(){
12758         if(!this.disabledDatesRE && this.disabledDates){
12759             var dd = this.disabledDates,
12760                 len = dd.length - 1,
12761                 re = '(?:';
12762
12763             Ext.each(dd, function(d, i){
12764                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
12765                 if(i != len){
12766                     re += '|';
12767                 }
12768             }, this);
12769             this.disabledDatesRE = new RegExp(re + ')');
12770         }
12771     },
12772
12773     /**
12774      * Replaces any existing disabled dates with new values and refreshes the DatePicker.
12775      * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config
12776      * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.
12777      */
12778     setDisabledDates : function(dd){
12779         if(Ext.isArray(dd)){
12780             this.disabledDates = dd;
12781             this.disabledDatesRE = null;
12782         }else{
12783             this.disabledDatesRE = dd;
12784         }
12785         this.initDisabledDays();
12786         this.update(this.value, true);
12787     },
12788
12789     /**
12790      * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.
12791      * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config
12792      * for details on supported values.
12793      */
12794     setDisabledDays : function(dd){
12795         this.disabledDays = dd;
12796         this.update(this.value, true);
12797     },
12798
12799     /**
12800      * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
12801      * @param {Date} value The minimum date that can be selected
12802      */
12803     setMinDate : function(dt){
12804         this.minDate = dt;
12805         this.update(this.value, true);
12806     },
12807
12808     /**
12809      * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
12810      * @param {Date} value The maximum date that can be selected
12811      */
12812     setMaxDate : function(dt){
12813         this.maxDate = dt;
12814         this.update(this.value, true);
12815     },
12816
12817     /**
12818      * Sets the value of the date field
12819      * @param {Date} value The date to set
12820      */
12821     setValue : function(value){
12822         this.value = value.clearTime(true);
12823         this.update(this.value);
12824     },
12825
12826     /**
12827      * Gets the current selected value of the date field
12828      * @return {Date} The selected date
12829      */
12830     getValue : function(){
12831         return this.value;
12832     },
12833
12834     // private
12835     focus : function(){
12836         this.update(this.activeDate);
12837     },
12838
12839     // private
12840     onEnable: function(initial){
12841         Ext.DatePicker.superclass.onEnable.call(this);
12842         this.doDisabled(false);
12843         this.update(initial ? this.value : this.activeDate);
12844         if(Ext.isIE){
12845             this.el.repaint();
12846         }
12847
12848     },
12849
12850     // private
12851     onDisable : function(){
12852         Ext.DatePicker.superclass.onDisable.call(this);
12853         this.doDisabled(true);
12854         if(Ext.isIE && !Ext.isIE8){
12855             /* Really strange problem in IE6/7, when disabled, have to explicitly
12856              * repaint each of the nodes to get them to display correctly, simply
12857              * calling repaint on the main element doesn't appear to be enough.
12858              */
12859              Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
12860                  Ext.fly(el).repaint();
12861              });
12862         }
12863     },
12864
12865     // private
12866     doDisabled : function(disabled){
12867         this.keyNav.setDisabled(disabled);
12868         this.prevRepeater.setDisabled(disabled);
12869         this.nextRepeater.setDisabled(disabled);
12870         if(this.showToday){
12871             this.todayKeyListener.setDisabled(disabled);
12872             this.todayBtn.setDisabled(disabled);
12873         }
12874     },
12875
12876     // private
12877     onRender : function(container, position){
12878         var m = [
12879              '<table cellspacing="0">',
12880                 '<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>',
12881                 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
12882                 dn = this.dayNames,
12883                 i;
12884         for(i = 0; i < 7; i++){
12885             var d = this.startDay+i;
12886             if(d > 6){
12887                 d = d-7;
12888             }
12889             m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
12890         }
12891         m[m.length] = '</tr></thead><tbody><tr>';
12892         for(i = 0; i < 42; i++) {
12893             if(i % 7 === 0 && i !== 0){
12894                 m[m.length] = '</tr><tr>';
12895             }
12896             m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
12897         }
12898         m.push('</tr></tbody></table></td></tr>',
12899                 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
12900                 '</table><div class="x-date-mp"></div>');
12901
12902         var el = document.createElement('div');
12903         el.className = 'x-date-picker';
12904         el.innerHTML = m.join('');
12905
12906         container.dom.insertBefore(el, position);
12907
12908         this.el = Ext.get(el);
12909         this.eventEl = Ext.get(el.firstChild);
12910
12911         this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
12912             handler: this.showPrevMonth,
12913             scope: this,
12914             preventDefault:true,
12915             stopDefault:true
12916         });
12917
12918         this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
12919             handler: this.showNextMonth,
12920             scope: this,
12921             preventDefault:true,
12922             stopDefault:true
12923         });
12924
12925         this.monthPicker = this.el.down('div.x-date-mp');
12926         this.monthPicker.enableDisplayMode('block');
12927
12928         this.keyNav = new Ext.KeyNav(this.eventEl, {
12929             'left' : function(e){
12930                 if(e.ctrlKey){
12931                     this.showPrevMonth();
12932                 }else{
12933                     this.update(this.activeDate.add('d', -1));
12934                 }
12935             },
12936
12937             'right' : function(e){
12938                 if(e.ctrlKey){
12939                     this.showNextMonth();
12940                 }else{
12941                     this.update(this.activeDate.add('d', 1));
12942                 }
12943             },
12944
12945             'up' : function(e){
12946                 if(e.ctrlKey){
12947                     this.showNextYear();
12948                 }else{
12949                     this.update(this.activeDate.add('d', -7));
12950                 }
12951             },
12952
12953             'down' : function(e){
12954                 if(e.ctrlKey){
12955                     this.showPrevYear();
12956                 }else{
12957                     this.update(this.activeDate.add('d', 7));
12958                 }
12959             },
12960
12961             'pageUp' : function(e){
12962                 this.showNextMonth();
12963             },
12964
12965             'pageDown' : function(e){
12966                 this.showPrevMonth();
12967             },
12968
12969             'enter' : function(e){
12970                 e.stopPropagation();
12971                 return true;
12972             },
12973
12974             scope : this
12975         });
12976
12977         this.el.unselectable();
12978
12979         this.cells = this.el.select('table.x-date-inner tbody td');
12980         this.textNodes = this.el.query('table.x-date-inner tbody span');
12981
12982         this.mbtn = new Ext.Button({
12983             text: '&#160;',
12984             tooltip: this.monthYearText,
12985             renderTo: this.el.child('td.x-date-middle', true)
12986         });
12987         this.mbtn.el.child('em').addClass('x-btn-arrow');
12988
12989         if(this.showToday){
12990             this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
12991             var today = (new Date()).dateFormat(this.format);
12992             this.todayBtn = new Ext.Button({
12993                 renderTo: this.el.child('td.x-date-bottom', true),
12994                 text: String.format(this.todayText, today),
12995                 tooltip: String.format(this.todayTip, today),
12996                 handler: this.selectToday,
12997                 scope: this
12998             });
12999         }
13000         this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
13001         this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
13002         this.mon(this.mbtn, 'click', this.showMonthPicker, this);
13003         this.onEnable(true);
13004     },
13005
13006     // private
13007     createMonthPicker : function(){
13008         if(!this.monthPicker.dom.firstChild){
13009             var buf = ['<table border="0" cellspacing="0">'];
13010             for(var i = 0; i < 6; i++){
13011                 buf.push(
13012                     '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
13013                     '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
13014                     i === 0 ?
13015                     '<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>' :
13016                     '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
13017                 );
13018             }
13019             buf.push(
13020                 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
13021                     this.okText,
13022                     '</button><button type="button" class="x-date-mp-cancel">',
13023                     this.cancelText,
13024                     '</button></td></tr>',
13025                 '</table>'
13026             );
13027             this.monthPicker.update(buf.join(''));
13028
13029             this.mon(this.monthPicker, 'click', this.onMonthClick, this);
13030             this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
13031
13032             this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
13033             this.mpYears = this.monthPicker.select('td.x-date-mp-year');
13034
13035             this.mpMonths.each(function(m, a, i){
13036                 i += 1;
13037                 if((i%2) === 0){
13038                     m.dom.xmonth = 5 + Math.round(i * 0.5);
13039                 }else{
13040                     m.dom.xmonth = Math.round((i-1) * 0.5);
13041                 }
13042             });
13043         }
13044     },
13045
13046     // private
13047     showMonthPicker : function(){
13048         if(!this.disabled){
13049             this.createMonthPicker();
13050             var size = this.el.getSize();
13051             this.monthPicker.setSize(size);
13052             this.monthPicker.child('table').setSize(size);
13053
13054             this.mpSelMonth = (this.activeDate || this.value).getMonth();
13055             this.updateMPMonth(this.mpSelMonth);
13056             this.mpSelYear = (this.activeDate || this.value).getFullYear();
13057             this.updateMPYear(this.mpSelYear);
13058
13059             this.monthPicker.slideIn('t', {duration:0.2});
13060         }
13061     },
13062
13063     // private
13064     updateMPYear : function(y){
13065         this.mpyear = y;
13066         var ys = this.mpYears.elements;
13067         for(var i = 1; i <= 10; i++){
13068             var td = ys[i-1], y2;
13069             if((i%2) === 0){
13070                 y2 = y + Math.round(i * 0.5);
13071                 td.firstChild.innerHTML = y2;
13072                 td.xyear = y2;
13073             }else{
13074                 y2 = y - (5-Math.round(i * 0.5));
13075                 td.firstChild.innerHTML = y2;
13076                 td.xyear = y2;
13077             }
13078             this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
13079         }
13080     },
13081
13082     // private
13083     updateMPMonth : function(sm){
13084         this.mpMonths.each(function(m, a, i){
13085             m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
13086         });
13087     },
13088
13089     // private
13090     selectMPMonth : function(m){
13091
13092     },
13093
13094     // private
13095     onMonthClick : function(e, t){
13096         e.stopEvent();
13097         var el = new Ext.Element(t), pn;
13098         if(el.is('button.x-date-mp-cancel')){
13099             this.hideMonthPicker();
13100         }
13101         else if(el.is('button.x-date-mp-ok')){
13102             var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
13103             if(d.getMonth() != this.mpSelMonth){
13104                 // 'fix' the JS rolling date conversion if needed
13105                 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
13106             }
13107             this.update(d);
13108             this.hideMonthPicker();
13109         }
13110         else if((pn = el.up('td.x-date-mp-month', 2))){
13111             this.mpMonths.removeClass('x-date-mp-sel');
13112             pn.addClass('x-date-mp-sel');
13113             this.mpSelMonth = pn.dom.xmonth;
13114         }
13115         else if((pn = el.up('td.x-date-mp-year', 2))){
13116             this.mpYears.removeClass('x-date-mp-sel');
13117             pn.addClass('x-date-mp-sel');
13118             this.mpSelYear = pn.dom.xyear;
13119         }
13120         else if(el.is('a.x-date-mp-prev')){
13121             this.updateMPYear(this.mpyear-10);
13122         }
13123         else if(el.is('a.x-date-mp-next')){
13124             this.updateMPYear(this.mpyear+10);
13125         }
13126     },
13127
13128     // private
13129     onMonthDblClick : function(e, t){
13130         e.stopEvent();
13131         var el = new Ext.Element(t), pn;
13132         if((pn = el.up('td.x-date-mp-month', 2))){
13133             this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
13134             this.hideMonthPicker();
13135         }
13136         else if((pn = el.up('td.x-date-mp-year', 2))){
13137             this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
13138             this.hideMonthPicker();
13139         }
13140     },
13141
13142     // private
13143     hideMonthPicker : function(disableAnim){
13144         if(this.monthPicker){
13145             if(disableAnim === true){
13146                 this.monthPicker.hide();
13147             }else{
13148                 this.monthPicker.slideOut('t', {duration:0.2});
13149             }
13150         }
13151     },
13152
13153     // private
13154     showPrevMonth : function(e){
13155         this.update(this.activeDate.add('mo', -1));
13156     },
13157
13158     // private
13159     showNextMonth : function(e){
13160         this.update(this.activeDate.add('mo', 1));
13161     },
13162
13163     // private
13164     showPrevYear : function(){
13165         this.update(this.activeDate.add('y', -1));
13166     },
13167
13168     // private
13169     showNextYear : function(){
13170         this.update(this.activeDate.add('y', 1));
13171     },
13172
13173     // private
13174     handleMouseWheel : function(e){
13175         e.stopEvent();
13176         if(!this.disabled){
13177             var delta = e.getWheelDelta();
13178             if(delta > 0){
13179                 this.showPrevMonth();
13180             } else if(delta < 0){
13181                 this.showNextMonth();
13182             }
13183         }
13184     },
13185
13186     // private
13187     handleDateClick : function(e, t){
13188         e.stopEvent();
13189         if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
13190             this.cancelFocus = this.focusOnSelect === false;
13191             this.setValue(new Date(t.dateValue));
13192             delete this.cancelFocus;
13193             this.fireEvent('select', this, this.value);
13194         }
13195     },
13196
13197     // private
13198     selectToday : function(){
13199         if(this.todayBtn && !this.todayBtn.disabled){
13200             this.setValue(new Date().clearTime());
13201             this.fireEvent('select', this, this.value);
13202         }
13203     },
13204
13205     // private
13206     update : function(date, forceRefresh){
13207         if(this.rendered){
13208             var vd = this.activeDate, vis = this.isVisible();
13209             this.activeDate = date;
13210             if(!forceRefresh && vd && this.el){
13211                 var t = date.getTime();
13212                 if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
13213                     this.cells.removeClass('x-date-selected');
13214                     this.cells.each(function(c){
13215                        if(c.dom.firstChild.dateValue == t){
13216                            c.addClass('x-date-selected');
13217                            if(vis && !this.cancelFocus){
13218                                Ext.fly(c.dom.firstChild).focus(50);
13219                            }
13220                            return false;
13221                        }
13222                     }, this);
13223                     return;
13224                 }
13225             }
13226             var days = date.getDaysInMonth(),
13227                 firstOfMonth = date.getFirstDateOfMonth(),
13228                 startingPos = firstOfMonth.getDay()-this.startDay;
13229
13230             if(startingPos < 0){
13231                 startingPos += 7;
13232             }
13233             days += startingPos;
13234
13235             var pm = date.add('mo', -1),
13236                 prevStart = pm.getDaysInMonth()-startingPos,
13237                 cells = this.cells.elements,
13238                 textEls = this.textNodes,
13239                 // convert everything to numbers so it's fast
13240                 d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart, this.initHour)),
13241                 today = new Date().clearTime().getTime(),
13242                 sel = date.clearTime(true).getTime(),
13243                 min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
13244                 max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
13245                 ddMatch = this.disabledDatesRE,
13246                 ddText = this.disabledDatesText,
13247                 ddays = this.disabledDays ? this.disabledDays.join('') : false,
13248                 ddaysText = this.disabledDaysText,
13249                 format = this.format;
13250
13251             if(this.showToday){
13252                 var td = new Date().clearTime(),
13253                     disable = (td < min || td > max ||
13254                     (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
13255                     (ddays && ddays.indexOf(td.getDay()) != -1));
13256
13257                 if(!this.disabled){
13258                     this.todayBtn.setDisabled(disable);
13259                     this.todayKeyListener[disable ? 'disable' : 'enable']();
13260                 }
13261             }
13262
13263             var setCellClass = function(cal, cell){
13264                 cell.title = '';
13265                 var t = d.clearTime(true).getTime();
13266                 cell.firstChild.dateValue = t;
13267                 if(t == today){
13268                     cell.className += ' x-date-today';
13269                     cell.title = cal.todayText;
13270                 }
13271                 if(t == sel){
13272                     cell.className += ' x-date-selected';
13273                     if(vis){
13274                         Ext.fly(cell.firstChild).focus(50);
13275                     }
13276                 }
13277                 // disabling
13278                 if(t < min) {
13279                     cell.className = ' x-date-disabled';
13280                     cell.title = cal.minText;
13281                     return;
13282                 }
13283                 if(t > max) {
13284                     cell.className = ' x-date-disabled';
13285                     cell.title = cal.maxText;
13286                     return;
13287                 }
13288                 if(ddays){
13289                     if(ddays.indexOf(d.getDay()) != -1){
13290                         cell.title = ddaysText;
13291                         cell.className = ' x-date-disabled';
13292                     }
13293                 }
13294                 if(ddMatch && format){
13295                     var fvalue = d.dateFormat(format);
13296                     if(ddMatch.test(fvalue)){
13297                         cell.title = ddText.replace('%0', fvalue);
13298                         cell.className = ' x-date-disabled';
13299                     }
13300                 }
13301             };
13302
13303             var i = 0;
13304             for(; i < startingPos; i++) {
13305                 textEls[i].innerHTML = (++prevStart);
13306                 d.setDate(d.getDate()+1);
13307                 cells[i].className = 'x-date-prevday';
13308                 setCellClass(this, cells[i]);
13309             }
13310             for(; i < days; i++){
13311                 var intDay = i - startingPos + 1;
13312                 textEls[i].innerHTML = (intDay);
13313                 d.setDate(d.getDate()+1);
13314                 cells[i].className = 'x-date-active';
13315                 setCellClass(this, cells[i]);
13316             }
13317             var extraDays = 0;
13318             for(; i < 42; i++) {
13319                  textEls[i].innerHTML = (++extraDays);
13320                  d.setDate(d.getDate()+1);
13321                  cells[i].className = 'x-date-nextday';
13322                  setCellClass(this, cells[i]);
13323             }
13324
13325             this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
13326
13327             if(!this.internalRender){
13328                 var main = this.el.dom.firstChild,
13329                     w = main.offsetWidth;
13330                 this.el.setWidth(w + this.el.getBorderWidth('lr'));
13331                 Ext.fly(main).setWidth(w);
13332                 this.internalRender = true;
13333                 // opera does not respect the auto grow header center column
13334                 // then, after it gets a width opera refuses to recalculate
13335                 // without a second pass
13336                 if(Ext.isOpera && !this.secondPass){
13337                     main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
13338                     this.secondPass = true;
13339                     this.update.defer(10, this, [date]);
13340                 }
13341             }
13342         }
13343     },
13344
13345     // private
13346     beforeDestroy : function() {
13347         if(this.rendered){
13348             Ext.destroy(
13349                 this.keyNav,
13350                 this.monthPicker,
13351                 this.eventEl,
13352                 this.mbtn,
13353                 this.nextRepeater,
13354                 this.prevRepeater,
13355                 this.cells.el,
13356                 this.todayBtn
13357             );
13358             delete this.textNodes;
13359             delete this.cells.elements;
13360         }
13361     }
13362
13363     /**
13364      * @cfg {String} autoEl @hide
13365      */
13366 });
13367
13368 Ext.reg('datepicker', Ext.DatePicker);
13369 /**
13370  * @class Ext.LoadMask
13371  * A simple utility class for generically masking elements while loading data.  If the {@link #store}
13372  * config option is specified, the masking will be automatically synchronized with the store's loading
13373  * process and the mask element will be cached for reuse.  For all other elements, this mask will replace the
13374  * element's Updater load indicator and will be destroyed after the initial load.
13375  * <p>Example usage:</p>
13376  *<pre><code>
13377 // Basic mask:
13378 var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
13379 myMask.show();
13380 </code></pre>
13381  * @constructor
13382  * Create a new LoadMask
13383  * @param {Mixed} el The element or DOM node, or its id
13384  * @param {Object} config The config object
13385  */
13386 Ext.LoadMask = function(el, config){
13387     this.el = Ext.get(el);
13388     Ext.apply(this, config);
13389     if(this.store){
13390         this.store.on({
13391             scope: this,
13392             beforeload: this.onBeforeLoad,
13393             load: this.onLoad,
13394             exception: this.onLoad
13395         });
13396         this.removeMask = Ext.value(this.removeMask, false);
13397     }else{
13398         var um = this.el.getUpdater();
13399         um.showLoadIndicator = false; // disable the default indicator
13400         um.on({
13401             scope: this,
13402             beforeupdate: this.onBeforeLoad,
13403             update: this.onLoad,
13404             failure: this.onLoad
13405         });
13406         this.removeMask = Ext.value(this.removeMask, true);
13407     }
13408 };
13409
13410 Ext.LoadMask.prototype = {
13411     /**
13412      * @cfg {Ext.data.Store} store
13413      * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and
13414      * hidden on either load sucess, or load fail.
13415      */
13416     /**
13417      * @cfg {Boolean} removeMask
13418      * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
13419      * False to persist the mask element reference for multiple uses (e.g., for paged data widgets).  Defaults to false.
13420      */
13421     /**
13422      * @cfg {String} msg
13423      * The text to display in a centered loading message box (defaults to 'Loading...')
13424      */
13425     msg : 'Loading...',
13426     /**
13427      * @cfg {String} msgCls
13428      * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
13429      */
13430     msgCls : 'x-mask-loading',
13431
13432     /**
13433      * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
13434      * @type Boolean
13435      */
13436     disabled: false,
13437
13438     /**
13439      * Disables the mask to prevent it from being displayed
13440      */
13441     disable : function(){
13442        this.disabled = true;
13443     },
13444
13445     /**
13446      * Enables the mask so that it can be displayed
13447      */
13448     enable : function(){
13449         this.disabled = false;
13450     },
13451
13452     // private
13453     onLoad : function(){
13454         this.el.unmask(this.removeMask);
13455     },
13456
13457     // private
13458     onBeforeLoad : function(){
13459         if(!this.disabled){
13460             this.el.mask(this.msg, this.msgCls);
13461         }
13462     },
13463
13464     /**
13465      * Show this LoadMask over the configured Element.
13466      */
13467     show: function(){
13468         this.onBeforeLoad();
13469     },
13470
13471     /**
13472      * Hide this LoadMask.
13473      */
13474     hide: function(){
13475         this.onLoad();
13476     },
13477
13478     // private
13479     destroy : function(){
13480         if(this.store){
13481             this.store.un('beforeload', this.onBeforeLoad, this);
13482             this.store.un('load', this.onLoad, this);
13483             this.store.un('exception', this.onLoad, this);
13484         }else{
13485             var um = this.el.getUpdater();
13486             um.un('beforeupdate', this.onBeforeLoad, this);
13487             um.un('update', this.onLoad, this);
13488             um.un('failure', this.onLoad, this);
13489         }
13490     }
13491 };Ext.ns('Ext.slider');
13492
13493 /**
13494  * @class Ext.slider.Thumb
13495  * @extends Object
13496  * Represents a single thumb element on a Slider. This would not usually be created manually and would instead
13497  * be created internally by an {@link Ext.slider.MultiSlider Ext.Slider}.
13498  */
13499 Ext.slider.Thumb = Ext.extend(Object, {
13500     
13501     /**
13502      * True while the thumb is in a drag operation
13503      * @type Boolean
13504      */
13505     dragging: false,
13506
13507     /**
13508      * @constructor
13509      * @cfg {Ext.slider.MultiSlider} slider The Slider to render to (required)
13510      */
13511     constructor: function(config) {
13512         /**
13513          * @property slider
13514          * @type Ext.slider.MultiSlider
13515          * The slider this thumb is contained within
13516          */
13517         Ext.apply(this, config || {}, {
13518             cls: 'x-slider-thumb',
13519
13520             /**
13521              * @cfg {Boolean} constrain True to constrain the thumb so that it cannot overlap its siblings
13522              */
13523             constrain: false
13524         });
13525
13526         Ext.slider.Thumb.superclass.constructor.call(this, config);
13527
13528         if (this.slider.vertical) {
13529             Ext.apply(this, Ext.slider.Thumb.Vertical);
13530         }
13531     },
13532
13533     /**
13534      * Renders the thumb into a slider
13535      */
13536     render: function() {
13537         this.el = this.slider.innerEl.insertFirst({cls: this.cls});
13538
13539         this.initEvents();
13540     },
13541
13542     /**
13543      * Enables the thumb if it is currently disabled
13544      */
13545     enable: function() {
13546         this.disabled = false;
13547         this.el.removeClass(this.slider.disabledClass);
13548     },
13549
13550     /**
13551      * Disables the thumb if it is currently enabled
13552      */
13553     disable: function() {
13554         this.disabled = true;
13555         this.el.addClass(this.slider.disabledClass);
13556     },
13557
13558     /**
13559      * Sets up an Ext.dd.DragTracker for this thumb
13560      */
13561     initEvents: function() {
13562         var el = this.el;
13563
13564         el.addClassOnOver('x-slider-thumb-over');
13565
13566         this.tracker = new Ext.dd.DragTracker({
13567             onBeforeStart: this.onBeforeDragStart.createDelegate(this),
13568             onStart      : this.onDragStart.createDelegate(this),
13569             onDrag       : this.onDrag.createDelegate(this),
13570             onEnd        : this.onDragEnd.createDelegate(this),
13571             tolerance    : 3,
13572             autoStart    : 300
13573         });
13574
13575         this.tracker.initEl(el);
13576     },
13577
13578     /**
13579      * @private
13580      * This is tied into the internal Ext.dd.DragTracker. If the slider is currently disabled,
13581      * this returns false to disable the DragTracker too.
13582      * @return {Boolean} False if the slider is currently disabled
13583      */
13584     onBeforeDragStart : function(e) {
13585         if (this.disabled) {
13586             return false;
13587         } else {
13588             this.slider.promoteThumb(this);
13589             return true;
13590         }
13591     },
13592
13593     /**
13594      * @private
13595      * This is tied into the internal Ext.dd.DragTracker's onStart template method. Adds the drag CSS class
13596      * to the thumb and fires the 'dragstart' event
13597      */
13598     onDragStart: function(e){
13599         this.el.addClass('x-slider-thumb-drag');
13600         this.dragging = true;
13601         this.dragStartValue = this.value;
13602
13603         this.slider.fireEvent('dragstart', this.slider, e, this);
13604     },
13605
13606     /**
13607      * @private
13608      * This is tied into the internal Ext.dd.DragTracker's onDrag template method. This is called every time
13609      * the DragTracker detects a drag movement. It updates the Slider's value using the position of the drag
13610      */
13611     onDrag: function(e) {
13612         var slider   = this.slider,
13613             index    = this.index,
13614             newValue = this.getNewValue();
13615
13616         if (this.constrain) {
13617             var above = slider.thumbs[index + 1],
13618                 below = slider.thumbs[index - 1];
13619
13620             if (below != undefined && newValue <= below.value) newValue = below.value;
13621             if (above != undefined && newValue >= above.value) newValue = above.value;
13622         }
13623
13624         slider.setValue(index, newValue, false);
13625         slider.fireEvent('drag', slider, e, this);
13626     },
13627
13628     getNewValue: function() {
13629         var slider   = this.slider,
13630             pos      = slider.innerEl.translatePoints(this.tracker.getXY());
13631
13632         return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
13633     },
13634
13635     /**
13636      * @private
13637      * This is tied to the internal Ext.dd.DragTracker's onEnd template method. Removes the drag CSS class and
13638      * fires the 'changecomplete' event with the new value
13639      */
13640     onDragEnd: function(e) {
13641         var slider = this.slider,
13642             value  = this.value;
13643
13644         this.el.removeClass('x-slider-thumb-drag');
13645
13646         this.dragging = false;
13647         slider.fireEvent('dragend', slider, e);
13648
13649         if (this.dragStartValue != value) {
13650             slider.fireEvent('changecomplete', slider, value, this);
13651         }
13652     },
13653     
13654     /**
13655      * @private
13656      * Destroys the thumb
13657      */
13658     destroy: function(){
13659         Ext.destroyMembers(this, 'tracker', 'el');
13660     }
13661 });
13662
13663 /**
13664  * @class Ext.slider.MultiSlider
13665  * @extends Ext.BoxComponent
13666  * Slider which supports vertical or horizontal orientation, keyboard adjustments, configurable snapping, axis clicking and animation. Can be added as an item to any container. Example usage:
13667 <pre>
13668 new Ext.Slider({
13669     renderTo: Ext.getBody(),
13670     width: 200,
13671     value: 50,
13672     increment: 10,
13673     minValue: 0,
13674     maxValue: 100
13675 });
13676 </pre>
13677  * Sliders can be created with more than one thumb handle by passing an array of values instead of a single one:
13678 <pre>
13679 new Ext.Slider({
13680     renderTo: Ext.getBody(),
13681     width: 200,
13682     values: [25, 50, 75],
13683     minValue: 0,
13684     maxValue: 100,
13685
13686     //this defaults to true, setting to false allows the thumbs to pass each other
13687     {@link #constrainThumbs}: false
13688 });
13689 </pre>
13690  */
13691 Ext.slider.MultiSlider = Ext.extend(Ext.BoxComponent, {
13692     /**
13693      * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.
13694      */
13695     /**
13696      * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.
13697      */
13698     vertical: false,
13699     /**
13700      * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.
13701      */
13702     minValue: 0,
13703     /**
13704      * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.
13705      */
13706     maxValue: 100,
13707     /**
13708      * @cfg {Number/Boolean} decimalPrecision.
13709      * <p>The number of decimal places to which to round the Slider's value. Defaults to 0.</p>
13710      * <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>
13711      */
13712     decimalPrecision: 0,
13713     /**
13714      * @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.
13715      */
13716     keyIncrement: 1,
13717     /**
13718      * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.
13719      */
13720     increment: 0,
13721
13722     /**
13723      * @private
13724      * @property clickRange
13725      * @type Array
13726      * Determines whether or not a click to the slider component is considered to be a user request to change the value. Specified as an array of [top, bottom],
13727      * the click event's 'top' property is compared to these numbers and the click only considered a change request if it falls within them. e.g. if the 'top'
13728      * value of the click event is 4 or 16, the click is not considered a change request as it falls outside of the [5, 15] range
13729      */
13730     clickRange: [5,15],
13731
13732     /**
13733      * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true
13734      */
13735     clickToChange : true,
13736     /**
13737      * @cfg {Boolean} animate Turn on or off animation. Defaults to true
13738      */
13739     animate: true,
13740     /**
13741      * @cfg {Boolean} constrainThumbs True to disallow thumbs from overlapping one another. Defaults to true
13742      */
13743     constrainThumbs: true,
13744
13745     /**
13746      * @private
13747      * @property topThumbZIndex
13748      * @type Number
13749      * The number used internally to set the z index of the top thumb (see promoteThumb for details)
13750      */
13751     topThumbZIndex: 10000,
13752
13753     // private override
13754     initComponent : function(){
13755         if(!Ext.isDefined(this.value)){
13756             this.value = this.minValue;
13757         }
13758
13759         /**
13760          * @property thumbs
13761          * @type Array
13762          * Array containing references to each thumb
13763          */
13764         this.thumbs = [];
13765
13766         Ext.slider.MultiSlider.superclass.initComponent.call(this);
13767
13768         this.keyIncrement = Math.max(this.increment, this.keyIncrement);
13769         this.addEvents(
13770             /**
13771              * @event beforechange
13772              * Fires before the slider value is changed. By returning false from an event handler,
13773              * you can cancel the event and prevent the slider from changing.
13774              * @param {Ext.slider.MultiSlider} slider The slider
13775              * @param {Number} newValue The new value which the slider is being changed to.
13776              * @param {Number} oldValue The old value which the slider was previously.
13777              */
13778             'beforechange',
13779
13780             /**
13781              * @event change
13782              * Fires when the slider value is changed.
13783              * @param {Ext.slider.MultiSlider} slider The slider
13784              * @param {Number} newValue The new value which the slider has been changed to.
13785              * @param {Ext.slider.Thumb} thumb The thumb that was changed
13786              */
13787             'change',
13788
13789             /**
13790              * @event changecomplete
13791              * Fires when the slider value is changed by the user and any drag operations have completed.
13792              * @param {Ext.slider.MultiSlider} slider The slider
13793              * @param {Number} newValue The new value which the slider has been changed to.
13794              * @param {Ext.slider.Thumb} thumb The thumb that was changed
13795              */
13796             'changecomplete',
13797
13798             /**
13799              * @event dragstart
13800              * Fires after a drag operation has started.
13801              * @param {Ext.slider.MultiSlider} slider The slider
13802              * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
13803              */
13804             'dragstart',
13805
13806             /**
13807              * @event drag
13808              * Fires continuously during the drag operation while the mouse is moving.
13809              * @param {Ext.slider.MultiSlider} slider The slider
13810              * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
13811              */
13812             'drag',
13813
13814             /**
13815              * @event dragend
13816              * Fires after the drag operation has completed.
13817              * @param {Ext.slider.MultiSlider} slider The slider
13818              * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
13819              */
13820             'dragend'
13821         );
13822
13823         /**
13824          * @property values
13825          * @type Array
13826          * Array of values to initalize the thumbs with
13827          */
13828         if (this.values == undefined || Ext.isEmpty(this.values)) this.values = [0];
13829
13830         var values = this.values;
13831
13832         for (var i=0; i < values.length; i++) {
13833             this.addThumb(values[i]);
13834         }
13835
13836         if(this.vertical){
13837             Ext.apply(this, Ext.slider.Vertical);
13838         }
13839     },
13840
13841     /**
13842      * Creates a new thumb and adds it to the slider
13843      * @param {Number} value The initial value to set on the thumb. Defaults to 0
13844      */
13845     addThumb: function(value) {
13846         var thumb = new Ext.slider.Thumb({
13847             value    : value,
13848             slider   : this,
13849             index    : this.thumbs.length,
13850             constrain: this.constrainThumbs
13851         });
13852         this.thumbs.push(thumb);
13853
13854         //render the thumb now if needed
13855         if (this.rendered) thumb.render();
13856     },
13857
13858     /**
13859      * @private
13860      * Moves the given thumb above all other by increasing its z-index. This is called when as drag
13861      * any thumb, so that the thumb that was just dragged is always at the highest z-index. This is
13862      * required when the thumbs are stacked on top of each other at one of the ends of the slider's
13863      * range, which can result in the user not being able to move any of them.
13864      * @param {Ext.slider.Thumb} topThumb The thumb to move to the top
13865      */
13866     promoteThumb: function(topThumb) {
13867         var thumbs = this.thumbs,
13868             zIndex, thumb;
13869
13870         for (var i = 0, j = thumbs.length; i < j; i++) {
13871             thumb = thumbs[i];
13872
13873             if (thumb == topThumb) {
13874                 zIndex = this.topThumbZIndex;
13875             } else {
13876                 zIndex = '';
13877             }
13878
13879             thumb.el.setStyle('zIndex', zIndex);
13880         }
13881     },
13882
13883     // private override
13884     onRender : function() {
13885         this.autoEl = {
13886             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
13887             cn : {
13888                 cls: 'x-slider-end',
13889                 cn : {
13890                     cls:'x-slider-inner',
13891                     cn : [{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]
13892                 }
13893             }
13894         };
13895
13896         Ext.slider.MultiSlider.superclass.onRender.apply(this, arguments);
13897
13898         this.endEl   = this.el.first();
13899         this.innerEl = this.endEl.first();
13900         this.focusEl = this.innerEl.child('.x-slider-focus');
13901
13902         //render each thumb
13903         for (var i=0; i < this.thumbs.length; i++) {
13904             this.thumbs[i].render();
13905         }
13906
13907         //calculate the size of half a thumb
13908         var thumb      = this.innerEl.child('.x-slider-thumb');
13909         this.halfThumb = (this.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
13910
13911         this.initEvents();
13912     },
13913
13914     /**
13915      * @private
13916      * Adds keyboard and mouse listeners on this.el. Ignores click events on the internal focus element.
13917      * Creates a new DragTracker which is used to control what happens when the user drags the thumb around.
13918      */
13919     initEvents : function(){
13920         this.mon(this.el, {
13921             scope    : this,
13922             mousedown: this.onMouseDown,
13923             keydown  : this.onKeyDown
13924         });
13925
13926         this.focusEl.swallowEvent("click", true);
13927     },
13928
13929     /**
13930      * @private
13931      * Mousedown handler for the slider. If the clickToChange is enabled and the click was not on the draggable 'thumb',
13932      * this calculates the new value of the slider and tells the implementation (Horizontal or Vertical) to move the thumb
13933      * @param {Ext.EventObject} e The click event
13934      */
13935     onMouseDown : function(e){
13936         if(this.disabled){
13937             return;
13938         }
13939
13940         //see if the click was on any of the thumbs
13941         var thumbClicked = false;
13942         for (var i=0; i < this.thumbs.length; i++) {
13943             thumbClicked = thumbClicked || e.target == this.thumbs[i].el.dom;
13944         }
13945
13946         if (this.clickToChange && !thumbClicked) {
13947             var local = this.innerEl.translatePoints(e.getXY());
13948             this.onClickChange(local);
13949         }
13950         this.focus();
13951     },
13952
13953     /**
13954      * @private
13955      * Moves the thumb to the indicated position. Note that a Vertical implementation is provided in Ext.slider.Vertical.
13956      * Only changes the value if the click was within this.clickRange.
13957      * @param {Object} local Object containing top and left values for the click event.
13958      */
13959     onClickChange : function(local) {
13960         if (local.top > this.clickRange[0] && local.top < this.clickRange[1]) {
13961             //find the nearest thumb to the click event
13962             var thumb = this.getNearest(local, 'left'),
13963                 index = thumb.index;
13964
13965             this.setValue(index, Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
13966         }
13967     },
13968
13969     /**
13970      * @private
13971      * Returns the nearest thumb to a click event, along with its distance
13972      * @param {Object} local Object containing top and left values from a click event
13973      * @param {String} prop The property of local to compare on. Use 'left' for horizontal sliders, 'top' for vertical ones
13974      * @return {Object} The closest thumb object and its distance from the click event
13975      */
13976     getNearest: function(local, prop) {
13977         var localValue = prop == 'top' ? this.innerEl.getHeight() - local[prop] : local[prop],
13978             clickValue = this.reverseValue(localValue),
13979             nearestDistance = (this.maxValue - this.minValue) + 5, //add a small fudge for the end of the slider 
13980             index = 0,
13981             nearest = null;
13982
13983         for (var i=0; i < this.thumbs.length; i++) {
13984             var thumb = this.thumbs[i],
13985                 value = thumb.value,
13986                 dist  = Math.abs(value - clickValue);
13987
13988             if (Math.abs(dist <= nearestDistance)) {
13989                 nearest = thumb;
13990                 index = i;
13991                 nearestDistance = dist;
13992             }
13993         }
13994         return nearest;
13995     },
13996
13997     /**
13998      * @private
13999      * Handler for any keypresses captured by the slider. If the key is UP or RIGHT, the thumb is moved along to the right
14000      * by this.keyIncrement. If DOWN or LEFT it is moved left. Pressing CTRL moves the slider to the end in either direction
14001      * @param {Ext.EventObject} e The Event object
14002      */
14003     onKeyDown : function(e){
14004         /*
14005          * The behaviour for keyboard handling with multiple thumbs is currently undefined.
14006          * There's no real sane default for it, so leave it like this until we come up
14007          * with a better way of doing it.
14008          */
14009         if(this.disabled || this.thumbs.length !== 1){
14010             e.preventDefault();
14011             return;
14012         }
14013         var k = e.getKey(),
14014             val;
14015         switch(k){
14016             case e.UP:
14017             case e.RIGHT:
14018                 e.stopEvent();
14019                 val = e.ctrlKey ? this.maxValue : this.getValue(0) + this.keyIncrement;
14020                 this.setValue(0, val, undefined, true);
14021             break;
14022             case e.DOWN:
14023             case e.LEFT:
14024                 e.stopEvent();
14025                 val = e.ctrlKey ? this.minValue : this.getValue(0) - this.keyIncrement;
14026                 this.setValue(0, val, undefined, true);
14027             break;
14028             default:
14029                 e.preventDefault();
14030         }
14031     },
14032
14033     /**
14034      * @private
14035      * If using snapping, this takes a desired new value and returns the closest snapped
14036      * value to it
14037      * @param {Number} value The unsnapped value
14038      * @return {Number} The value of the nearest snap target
14039      */
14040     doSnap : function(value){
14041         if (!(this.increment && value)) {
14042             return value;
14043         }
14044         var newValue = value,
14045             inc = this.increment,
14046             m = value % inc;
14047         if (m != 0) {
14048             newValue -= m;
14049             if (m * 2 >= inc) {
14050                 newValue += inc;
14051             } else if (m * 2 < -inc) {
14052                 newValue -= inc;
14053             }
14054         }
14055         return newValue.constrain(this.minValue,  this.maxValue);
14056     },
14057
14058     // private
14059     afterRender : function(){
14060         Ext.slider.MultiSlider.superclass.afterRender.apply(this, arguments);
14061
14062         for (var i=0; i < this.thumbs.length; i++) {
14063             var thumb = this.thumbs[i];
14064
14065             if (thumb.value !== undefined) {
14066                 var v = this.normalizeValue(thumb.value);
14067
14068                 if (v !== thumb.value) {
14069                     // delete this.value;
14070                     this.setValue(i, v, false);
14071                 } else {
14072                     this.moveThumb(i, this.translateValue(v), false);
14073                 }
14074             }
14075         };
14076     },
14077
14078     /**
14079      * @private
14080      * Returns the ratio of pixels to mapped values. e.g. if the slider is 200px wide and maxValue - minValue is 100,
14081      * the ratio is 2
14082      * @return {Number} The ratio of pixels to mapped values
14083      */
14084     getRatio : function(){
14085         var w = this.innerEl.getWidth(),
14086             v = this.maxValue - this.minValue;
14087         return v == 0 ? w : (w/v);
14088     },
14089
14090     /**
14091      * @private
14092      * Returns a snapped, constrained value when given a desired value
14093      * @param {Number} value Raw number value
14094      * @return {Number} The raw value rounded to the correct d.p. and constrained within the set max and min values
14095      */
14096     normalizeValue : function(v){
14097         v = this.doSnap(v);
14098         v = Ext.util.Format.round(v, this.decimalPrecision);
14099         v = v.constrain(this.minValue, this.maxValue);
14100         return v;
14101     },
14102
14103     /**
14104      * Sets the minimum value for the slider instance. If the current value is less than the
14105      * minimum value, the current value will be changed.
14106      * @param {Number} val The new minimum value
14107      */
14108     setMinValue : function(val){
14109         this.minValue = val;
14110         var i = 0,
14111             thumbs = this.thumbs,
14112             len = thumbs.length,
14113             t;
14114             
14115         for(; i < len; ++i){
14116             t = thumbs[i];
14117             t.value = t.value < val ? val : t.value;
14118         }
14119         this.syncThumb();
14120     },
14121
14122     /**
14123      * Sets the maximum value for the slider instance. If the current value is more than the
14124      * maximum value, the current value will be changed.
14125      * @param {Number} val The new maximum value
14126      */
14127     setMaxValue : function(val){
14128         this.maxValue = val;
14129         var i = 0,
14130             thumbs = this.thumbs,
14131             len = thumbs.length,
14132             t;
14133             
14134         for(; i < len; ++i){
14135             t = thumbs[i];
14136             t.value = t.value > val ? val : t.value;
14137         }
14138         this.syncThumb();
14139     },
14140
14141     /**
14142      * Programmatically sets the value of the Slider. Ensures that the value is constrained within
14143      * the minValue and maxValue.
14144      * @param {Number} index Index of the thumb to move
14145      * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)
14146      * @param {Boolean} animate Turn on or off animation, defaults to true
14147      */
14148     setValue : function(index, v, animate, changeComplete) {
14149         var thumb = this.thumbs[index],
14150             el    = thumb.el;
14151
14152         v = this.normalizeValue(v);
14153
14154         if (v !== thumb.value && this.fireEvent('beforechange', this, v, thumb.value, thumb) !== false) {
14155             thumb.value = v;
14156             if(this.rendered){
14157                 this.moveThumb(index, this.translateValue(v), animate !== false);
14158                 this.fireEvent('change', this, v, thumb);
14159                 if(changeComplete){
14160                     this.fireEvent('changecomplete', this, v, thumb);
14161                 }
14162             }
14163         }
14164     },
14165
14166     /**
14167      * @private
14168      */
14169     translateValue : function(v) {
14170         var ratio = this.getRatio();
14171         return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
14172     },
14173
14174     /**
14175      * @private
14176      * Given a pixel location along the slider, returns the mapped slider value for that pixel.
14177      * E.g. if we have a slider 200px wide with minValue = 100 and maxValue = 500, reverseValue(50)
14178      * returns 200
14179      * @param {Number} pos The position along the slider to return a mapped value for
14180      * @return {Number} The mapped value for the given position
14181      */
14182     reverseValue : function(pos){
14183         var ratio = this.getRatio();
14184         return (pos + (this.minValue * ratio)) / ratio;
14185     },
14186
14187     /**
14188      * @private
14189      * @param {Number} index Index of the thumb to move
14190      */
14191     moveThumb: function(index, v, animate){
14192         var thumb = this.thumbs[index].el;
14193
14194         if(!animate || this.animate === false){
14195             thumb.setLeft(v);
14196         }else{
14197             thumb.shift({left: v, stopFx: true, duration:.35});
14198         }
14199     },
14200
14201     // private
14202     focus : function(){
14203         this.focusEl.focus(10);
14204     },
14205
14206     // private
14207     onResize : function(w, h){
14208         var thumbs = this.thumbs,
14209             len = thumbs.length,
14210             i = 0;
14211             
14212         /*
14213          * If we happen to be animating during a resize, the position of the thumb will likely be off
14214          * when the animation stops. As such, just stop any animations before syncing the thumbs.
14215          */
14216         for(; i < len; ++i){
14217             thumbs[i].el.stopFx();    
14218         }
14219         // check to see if we're using an auto width
14220         if(Ext.isNumber(w)){
14221             this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
14222         }
14223         this.syncThumb();
14224         Ext.slider.MultiSlider.superclass.onResize.apply(this, arguments);
14225     },
14226
14227     //private
14228     onDisable: function(){
14229         Ext.slider.MultiSlider.superclass.onDisable.call(this);
14230
14231         for (var i=0; i < this.thumbs.length; i++) {
14232             var thumb = this.thumbs[i],
14233                 el    = thumb.el;
14234
14235             thumb.disable();
14236
14237             if(Ext.isIE){
14238                 //IE breaks when using overflow visible and opacity other than 1.
14239                 //Create a place holder for the thumb and display it.
14240                 var xy = el.getXY();
14241                 el.hide();
14242
14243                 this.innerEl.addClass(this.disabledClass).dom.disabled = true;
14244
14245                 if (!this.thumbHolder) {
14246                     this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});
14247                 }
14248
14249                 this.thumbHolder.show().setXY(xy);
14250             }
14251         }
14252     },
14253
14254     //private
14255     onEnable: function(){
14256         Ext.slider.MultiSlider.superclass.onEnable.call(this);
14257
14258         for (var i=0; i < this.thumbs.length; i++) {
14259             var thumb = this.thumbs[i],
14260                 el    = thumb.el;
14261
14262             thumb.enable();
14263
14264             if (Ext.isIE) {
14265                 this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
14266
14267                 if (this.thumbHolder) this.thumbHolder.hide();
14268
14269                 el.show();
14270                 this.syncThumb();
14271             }
14272         }
14273     },
14274
14275     /**
14276      * Synchronizes the thumb position to the proper proportion of the total component width based
14277      * on the current slider {@link #value}.  This will be called automatically when the Slider
14278      * is resized by a layout, but if it is rendered auto width, this method can be called from
14279      * another resize handler to sync the Slider if necessary.
14280      */
14281     syncThumb : function() {
14282         if (this.rendered) {
14283             for (var i=0; i < this.thumbs.length; i++) {
14284                 this.moveThumb(i, this.translateValue(this.thumbs[i].value));
14285             }
14286         }
14287     },
14288
14289     /**
14290      * Returns the current value of the slider
14291      * @param {Number} index The index of the thumb to return a value for
14292      * @return {Number} The current value of the slider
14293      */
14294     getValue : function(index) {
14295         return this.thumbs[index].value;
14296     },
14297
14298     /**
14299      * Returns an array of values - one for the location of each thumb
14300      * @return {Array} The set of thumb values
14301      */
14302     getValues: function() {
14303         var values = [];
14304
14305         for (var i=0; i < this.thumbs.length; i++) {
14306             values.push(this.thumbs[i].value);
14307         }
14308
14309         return values;
14310     },
14311
14312     // private
14313     beforeDestroy : function(){
14314         var thumbs = this.thumbs;
14315         for(var i = 0, len = thumbs.length; i < len; ++i){
14316             thumbs[i].destroy();
14317             thumbs[i] = null;
14318         }
14319         Ext.destroyMembers(this, 'endEl', 'innerEl', 'focusEl', 'thumbHolder');
14320         Ext.slider.MultiSlider.superclass.beforeDestroy.call(this);
14321     }
14322 });
14323
14324 Ext.reg('multislider', Ext.slider.MultiSlider);
14325
14326 /**
14327  * @class Ext.slider.SingleSlider
14328  * @extends Ext.slider.MultiSlider
14329  * Slider which supports vertical or horizontal orientation, keyboard adjustments,
14330  * configurable snapping, axis clicking and animation. Can be added as an item to
14331  * any container. Example usage:
14332 <pre><code>
14333 new Ext.slider.SingleSlider({
14334     renderTo: Ext.getBody(),
14335     width: 200,
14336     value: 50,
14337     increment: 10,
14338     minValue: 0,
14339     maxValue: 100
14340 });
14341 </code></pre>
14342  * The class Ext.slider.SingleSlider is aliased to Ext.Slider for backwards compatibility.
14343  */
14344 Ext.slider.SingleSlider = Ext.extend(Ext.slider.MultiSlider, {
14345     constructor: function(config) {
14346       config = config || {};
14347
14348       Ext.applyIf(config, {
14349           values: [config.value || 0]
14350       });
14351
14352       Ext.slider.SingleSlider.superclass.constructor.call(this, config);
14353     },
14354
14355     /**
14356      * Returns the current value of the slider
14357      * @return {Number} The current value of the slider
14358      */
14359     getValue: function() {
14360         //just returns the value of the first thumb, which should be the only one in a single slider
14361         return Ext.slider.SingleSlider.superclass.getValue.call(this, 0);
14362     },
14363
14364     /**
14365      * Programmatically sets the value of the Slider. Ensures that the value is constrained within
14366      * the minValue and maxValue.
14367      * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)
14368      * @param {Boolean} animate Turn on or off animation, defaults to true
14369      */
14370     setValue: function(value, animate) {
14371         var args = Ext.toArray(arguments),
14372             len  = args.length;
14373
14374         //this is to maintain backwards compatiblity for sliders with only one thunb. Usually you must pass the thumb
14375         //index to setValue, but if we only have one thumb we inject the index here first if given the multi-slider
14376         //signature without the required index. The index will always be 0 for a single slider
14377         if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
14378             args.unshift(0);
14379         }
14380
14381         return Ext.slider.SingleSlider.superclass.setValue.apply(this, args);
14382     },
14383
14384     /**
14385      * Synchronizes the thumb position to the proper proportion of the total component width based
14386      * on the current slider {@link #value}.  This will be called automatically when the Slider
14387      * is resized by a layout, but if it is rendered auto width, this method can be called from
14388      * another resize handler to sync the Slider if necessary.
14389      */
14390     syncThumb : function() {
14391         return Ext.slider.SingleSlider.superclass.syncThumb.apply(this, [0].concat(arguments));
14392     },
14393     
14394     // private
14395     getNearest : function(){
14396         // Since there's only 1 thumb, it's always the nearest
14397         return this.thumbs[0];    
14398     }
14399 });
14400
14401 //backwards compatibility
14402 Ext.Slider = Ext.slider.SingleSlider;
14403
14404 Ext.reg('slider', Ext.slider.SingleSlider);
14405
14406 // private class to support vertical sliders
14407 Ext.slider.Vertical = {
14408     onResize : function(w, h){
14409         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
14410         this.syncThumb();
14411     },
14412
14413     getRatio : function(){
14414         var h = this.innerEl.getHeight(),
14415             v = this.maxValue - this.minValue;
14416         return h/v;
14417     },
14418
14419     moveThumb: function(index, v, animate) {
14420         var thumb = this.thumbs[index],
14421             el    = thumb.el;
14422
14423         if (!animate || this.animate === false) {
14424             el.setBottom(v);
14425         } else {
14426             el.shift({bottom: v, stopFx: true, duration:.35});
14427         }
14428     },
14429
14430     onClickChange : function(local) {
14431         if (local.left > this.clickRange[0] && local.left < this.clickRange[1]) {
14432             var thumb = this.getNearest(local, 'top'),
14433                 index = thumb.index,
14434                 value = this.minValue + this.reverseValue(this.innerEl.getHeight() - local.top);
14435
14436             this.setValue(index, Ext.util.Format.round(value, this.decimalPrecision), undefined, true);
14437         }
14438     }
14439 };
14440
14441 //private class to support vertical dragging of thumbs within a slider
14442 Ext.slider.Thumb.Vertical = {
14443     getNewValue: function() {
14444         var slider   = this.slider,
14445             innerEl  = slider.innerEl,
14446             pos      = innerEl.translatePoints(this.tracker.getXY()),
14447             bottom   = innerEl.getHeight() - pos.top;
14448
14449         return slider.minValue + Ext.util.Format.round(bottom / slider.getRatio(), slider.decimalPrecision);
14450     }
14451 };
14452 /**
14453  * @class Ext.ProgressBar
14454  * @extends Ext.BoxComponent
14455  * <p>An updateable progress bar component.  The progress bar supports two different modes: manual and automatic.</p>
14456  * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the
14457  * progress bar as needed from your own code.  This method is most appropriate when you want to show progress
14458  * throughout an operation that has predictable points of interest at which you can update the control.</p>
14459  * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it
14460  * once the operation is complete.  You can optionally have the progress bar wait for a specific amount of time
14461  * and then clear itself.  Automatic mode is most appropriate for timed operations or asynchronous operations in
14462  * which you have no need for indicating intermediate progress.</p>
14463  * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0)
14464  * @cfg {String} text The progress bar text (defaults to '')
14465  * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress
14466  * bar's internal text element)
14467  * @cfg {String} id The progress bar element's id (defaults to an auto-generated id)
14468  * @xtype progress
14469  */
14470 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
14471    /**
14472     * @cfg {String} baseCls
14473     * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress')
14474     */
14475     baseCls : 'x-progress',
14476     
14477     /**
14478     * @cfg {Boolean} animate
14479     * True to animate the progress bar during transitions (defaults to false)
14480     */
14481     animate : false,
14482
14483     // private
14484     waitTimer : null,
14485
14486     // private
14487     initComponent : function(){
14488         Ext.ProgressBar.superclass.initComponent.call(this);
14489         this.addEvents(
14490             /**
14491              * @event update
14492              * Fires after each update interval
14493              * @param {Ext.ProgressBar} this
14494              * @param {Number} The current progress value
14495              * @param {String} The current progress text
14496              */
14497             "update"
14498         );
14499     },
14500
14501     // private
14502     onRender : function(ct, position){
14503         var tpl = new Ext.Template(
14504             '<div class="{cls}-wrap">',
14505                 '<div class="{cls}-inner">',
14506                     '<div class="{cls}-bar">',
14507                         '<div class="{cls}-text">',
14508                             '<div>&#160;</div>',
14509                         '</div>',
14510                     '</div>',
14511                     '<div class="{cls}-text {cls}-text-back">',
14512                         '<div>&#160;</div>',
14513                     '</div>',
14514                 '</div>',
14515             '</div>'
14516         );
14517
14518         this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
14519             : tpl.append(ct, {cls: this.baseCls}, true);
14520                 
14521         if(this.id){
14522             this.el.dom.id = this.id;
14523         }
14524         var inner = this.el.dom.firstChild;
14525         this.progressBar = Ext.get(inner.firstChild);
14526
14527         if(this.textEl){
14528             //use an external text el
14529             this.textEl = Ext.get(this.textEl);
14530             delete this.textTopEl;
14531         }else{
14532             //setup our internal layered text els
14533             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
14534             var textBackEl = Ext.get(inner.childNodes[1]);
14535             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
14536             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
14537             this.textEl.setWidth(inner.offsetWidth);
14538         }
14539         this.progressBar.setHeight(inner.offsetHeight);
14540     },
14541     
14542     // private
14543     afterRender : function(){
14544         Ext.ProgressBar.superclass.afterRender.call(this);
14545         if(this.value){
14546             this.updateProgress(this.value, this.text);
14547         }else{
14548             this.updateText(this.text);
14549         }
14550     },
14551
14552     /**
14553      * Updates the progress bar value, and optionally its text.  If the text argument is not specified,
14554      * any existing text value will be unchanged.  To blank out existing text, pass ''.  Note that even
14555      * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for
14556      * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control.
14557      * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0)
14558      * @param {String} text (optional) The string to display in the progress text element (defaults to '')
14559      * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is
14560      * not specified, the default for the class is used (default to false)
14561      * @return {Ext.ProgressBar} this
14562      */
14563     updateProgress : function(value, text, animate){
14564         this.value = value || 0;
14565         if(text){
14566             this.updateText(text);
14567         }
14568         if(this.rendered && !this.isDestroyed){
14569             var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
14570             this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
14571             if(this.textTopEl){
14572                 //textTopEl should be the same width as the bar so overflow will clip as the bar moves
14573                 this.textTopEl.removeClass('x-hidden').setWidth(w);
14574             }
14575         }
14576         this.fireEvent('update', this, value, text);
14577         return this;
14578     },
14579
14580     /**
14581      * Initiates an auto-updating progress bar.  A duration can be specified, in which case the progress
14582      * bar will automatically reset after a fixed amount of time and optionally call a callback function
14583      * if specified.  If no duration is passed in, then the progress bar will run indefinitely and must
14584      * be manually cleared by calling {@link #reset}.  The wait method accepts a config object with
14585      * the following properties:
14586      * <pre>
14587 Property   Type          Description
14588 ---------- ------------  ----------------------------------------------------------------------
14589 duration   Number        The length of time in milliseconds that the progress bar should
14590                          run before resetting itself (defaults to undefined, in which case it
14591                          will run indefinitely until reset is called)
14592 interval   Number        The length of time in milliseconds between each progress update
14593                          (defaults to 1000 ms)
14594 animate    Boolean       Whether to animate the transition of the progress bar. If this value is
14595                          not specified, the default for the class is used.                                                   
14596 increment  Number        The number of progress update segments to display within the progress
14597                          bar (defaults to 10).  If the bar reaches the end and is still
14598                          updating, it will automatically wrap back to the beginning.
14599 text       String        Optional text to display in the progress bar element (defaults to '').
14600 fn         Function      A callback function to execute after the progress bar finishes auto-
14601                          updating.  The function will be called with no arguments.  This function
14602                          will be ignored if duration is not specified since in that case the
14603                          progress bar can only be stopped programmatically, so any required function
14604                          should be called by the same code after it resets the progress bar.
14605 scope      Object        The scope that is passed to the callback function (only applies when
14606                          duration and fn are both passed).
14607 </pre>
14608          *
14609          * Example usage:
14610          * <pre><code>
14611 var p = new Ext.ProgressBar({
14612    renderTo: 'my-el'
14613 });
14614
14615 //Wait for 5 seconds, then update the status el (progress bar will auto-reset)
14616 p.wait({
14617    interval: 100, //bar will move fast!
14618    duration: 5000,
14619    increment: 15,
14620    text: 'Updating...',
14621    scope: this,
14622    fn: function(){
14623       Ext.fly('status').update('Done!');
14624    }
14625 });
14626
14627 //Or update indefinitely until some async action completes, then reset manually
14628 p.wait();
14629 myAction.on('complete', function(){
14630     p.reset();
14631     Ext.fly('status').update('Done!');
14632 });
14633 </code></pre>
14634      * @param {Object} config (optional) Configuration options
14635      * @return {Ext.ProgressBar} this
14636      */
14637     wait : function(o){
14638         if(!this.waitTimer){
14639             var scope = this;
14640             o = o || {};
14641             this.updateText(o.text);
14642             this.waitTimer = Ext.TaskMgr.start({
14643                 run: function(i){
14644                     var inc = o.increment || 10;
14645                     i -= 1;
14646                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
14647                 },
14648                 interval: o.interval || 1000,
14649                 duration: o.duration,
14650                 onStop: function(){
14651                     if(o.fn){
14652                         o.fn.apply(o.scope || this);
14653                     }
14654                     this.reset();
14655                 },
14656                 scope: scope
14657             });
14658         }
14659         return this;
14660     },
14661
14662     /**
14663      * Returns true if the progress bar is currently in a {@link #wait} operation
14664      * @return {Boolean} True if waiting, else false
14665      */
14666     isWaiting : function(){
14667         return this.waitTimer !== null;
14668     },
14669
14670     /**
14671      * Updates the progress bar text.  If specified, textEl will be updated, otherwise the progress
14672      * bar itself will display the updated text.
14673      * @param {String} text (optional) The string to display in the progress text element (defaults to '')
14674      * @return {Ext.ProgressBar} this
14675      */
14676     updateText : function(text){
14677         this.text = text || '&#160;';
14678         if(this.rendered){
14679             this.textEl.update(this.text);
14680         }
14681         return this;
14682     },
14683     
14684     /**
14685      * Synchronizes the inner bar width to the proper proportion of the total componet width based
14686      * on the current progress {@link #value}.  This will be called automatically when the ProgressBar
14687      * is resized by a layout, but if it is rendered auto width, this method can be called from
14688      * another resize handler to sync the ProgressBar if necessary.
14689      */
14690     syncProgressBar : function(){
14691         if(this.value){
14692             this.updateProgress(this.value, this.text);
14693         }
14694         return this;
14695     },
14696
14697     /**
14698      * Sets the size of the progress bar.
14699      * @param {Number} width The new width in pixels
14700      * @param {Number} height The new height in pixels
14701      * @return {Ext.ProgressBar} this
14702      */
14703     setSize : function(w, h){
14704         Ext.ProgressBar.superclass.setSize.call(this, w, h);
14705         if(this.textTopEl){
14706             var inner = this.el.dom.firstChild;
14707             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
14708         }
14709         this.syncProgressBar();
14710         return this;
14711     },
14712
14713     /**
14714      * Resets the progress bar value to 0 and text to empty string.  If hide = true, the progress
14715      * bar will also be hidden (using the {@link #hideMode} property internally).
14716      * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false)
14717      * @return {Ext.ProgressBar} this
14718      */
14719     reset : function(hide){
14720         this.updateProgress(0);
14721         if(this.textTopEl){
14722             this.textTopEl.addClass('x-hidden');
14723         }
14724         this.clearTimer();
14725         if(hide === true){
14726             this.hide();
14727         }
14728         return this;
14729     },
14730     
14731     // private
14732     clearTimer : function(){
14733         if(this.waitTimer){
14734             this.waitTimer.onStop = null; //prevent recursion
14735             Ext.TaskMgr.stop(this.waitTimer);
14736             this.waitTimer = null;
14737         }
14738     },
14739     
14740     onDestroy: function(){
14741         this.clearTimer();
14742         if(this.rendered){
14743             if(this.textEl.isComposite){
14744                 this.textEl.clear();
14745             }
14746             Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
14747         }
14748         Ext.ProgressBar.superclass.onDestroy.call(this);
14749     }
14750 });
14751 Ext.reg('progress', Ext.ProgressBar);