Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / pkgs / cmp-foundation-debug.js
1 /*!
2  * Ext JS Library 3.3.1
3  * Copyright(c) 2006-2010 Sencha Inc.
4  * licensing@sencha.com
5  * http://www.sencha.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.isAction ? c.initialConfig : 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(this.container) {
5198             this.container.un(this.container.resizeEvent, this.onResize, this);
5199         }
5200         if(!Ext.isEmpty(this.targetCls)){
5201             var target = this.container.getLayoutTarget();
5202             if(target){
5203                 target.removeClass(this.targetCls);
5204             }
5205         }
5206     }
5207 });/**
5208  * @class Ext.layout.AutoLayout
5209  * <p>The AutoLayout is the default layout manager delegated by {@link Ext.Container} to
5210  * render any child Components when no <tt>{@link Ext.Container#layout layout}</tt> is configured into
5211  * a {@link Ext.Container Container}.</tt>.  AutoLayout provides only a passthrough of any layout calls
5212  * to any child containers.</p>
5213  */
5214 Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
5215     type: 'auto',
5216
5217     monitorResize: true,
5218
5219     onLayout : function(ct, target){
5220         Ext.layout.AutoLayout.superclass.onLayout.call(this, ct, target);
5221         var cs = this.getRenderedItems(ct), len = cs.length, i, c;
5222         for(i = 0; i < len; i++){
5223             c = cs[i];
5224             if (c.doLayout){
5225                 // Shallow layout children
5226                 c.doLayout(true);
5227             }
5228         }
5229     }
5230 });
5231
5232 Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
5233 /**
5234  * @class Ext.layout.FitLayout
5235  * @extends Ext.layout.ContainerLayout
5236  * <p>This is a base class for layouts that contain <b>a single item</b> that automatically expands to fill the layout's
5237  * container.  This class is intended to be extended or created via the <tt>layout:'fit'</tt> {@link Ext.Container#layout}
5238  * config, and should generally not need to be created directly via the new keyword.</p>
5239  * <p>FitLayout does not have any direct config options (other than inherited ones).  To fit a panel to a container
5240  * using FitLayout, simply set layout:'fit' on the container and add a single panel to it.  If the container has
5241  * multiple panels, only the first one will be displayed.  Example usage:</p>
5242  * <pre><code>
5243 var p = new Ext.Panel({
5244     title: 'Fit Layout',
5245     layout:'fit',
5246     items: {
5247         title: 'Inner Panel',
5248         html: '&lt;p&gt;This is the inner panel content&lt;/p&gt;',
5249         border: false
5250     }
5251 });
5252 </code></pre>
5253  */
5254 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
5255     // private
5256     monitorResize:true,
5257
5258     type: 'fit',
5259
5260     getLayoutTargetSize : function() {
5261         var target = this.container.getLayoutTarget();
5262         if (!target) {
5263             return {};
5264         }
5265         // Style Sized (scrollbars not included)
5266         return target.getStyleSize();
5267     },
5268
5269     // private
5270     onLayout : function(ct, target){
5271         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
5272         if(!ct.collapsed){
5273             this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());
5274         }
5275     },
5276
5277     // private
5278     setItemSize : function(item, size){
5279         if(item && size.height > 0){ // display none?
5280             item.setSize(size);
5281         }
5282     }
5283 });
5284 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;/**
5285  * @class Ext.layout.CardLayout
5286  * @extends Ext.layout.FitLayout
5287  * <p>This layout manages multiple child Components, each fitted to the Container, where only a single child Component can be
5288  * visible at any given time.  This layout style is most commonly used for wizards, tab implementations, etc.
5289  * This class is intended to be extended or created via the layout:'card' {@link Ext.Container#layout} config,
5290  * and should generally not need to be created directly via the new keyword.</p>
5291  * <p>The CardLayout's focal method is {@link #setActiveItem}.  Since only one panel is displayed at a time,
5292  * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of
5293  * the next panel to display.  The layout itself does not provide a user interface for handling this navigation,
5294  * so that functionality must be provided by the developer.</p>
5295  * <p>In the following example, a simplistic wizard setup is demonstrated.  A button bar is added
5296  * to the footer of the containing panel to provide navigation buttons.  The buttons will be handled by a
5297  * common navigation routine -- for this example, the implementation of that routine has been ommitted since
5298  * it can be any type of custom logic.  Note that other uses of a CardLayout (like a tab control) would require a
5299  * completely different implementation.  For serious implementations, a better approach would be to extend
5300  * CardLayout to provide the custom functionality needed.  Example usage:</p>
5301  * <pre><code>
5302 var navHandler = function(direction){
5303     // This routine could contain business logic required to manage the navigation steps.
5304     // It would call setActiveItem as needed, manage navigation button state, handle any
5305     // branching logic that might be required, handle alternate actions like cancellation
5306     // or finalization, etc.  A complete wizard implementation could get pretty
5307     // sophisticated depending on the complexity required, and should probably be
5308     // done as a subclass of CardLayout in a real-world implementation.
5309 };
5310
5311 var card = new Ext.Panel({
5312     title: 'Example Wizard',
5313     layout:'card',
5314     activeItem: 0, // make sure the active item is set on the container config!
5315     bodyStyle: 'padding:15px',
5316     defaults: {
5317         // applied to each contained panel
5318         border:false
5319     },
5320     // just an example of one possible navigation scheme, using buttons
5321     bbar: [
5322         {
5323             id: 'move-prev',
5324             text: 'Back',
5325             handler: navHandler.createDelegate(this, [-1]),
5326             disabled: true
5327         },
5328         '->', // greedy spacer so that the buttons are aligned to each side
5329         {
5330             id: 'move-next',
5331             text: 'Next',
5332             handler: navHandler.createDelegate(this, [1])
5333         }
5334     ],
5335     // the panels (or "cards") within the layout
5336     items: [{
5337         id: 'card-0',
5338         html: '&lt;h1&gt;Welcome to the Wizard!&lt;/h1&gt;&lt;p&gt;Step 1 of 3&lt;/p&gt;'
5339     },{
5340         id: 'card-1',
5341         html: '&lt;p&gt;Step 2 of 3&lt;/p&gt;'
5342     },{
5343         id: 'card-2',
5344         html: '&lt;h1&gt;Congratulations!&lt;/h1&gt;&lt;p&gt;Step 3 of 3 - Complete&lt;/p&gt;'
5345     }]
5346 });
5347 </code></pre>
5348  */
5349 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
5350     /**
5351      * @cfg {Boolean} deferredRender
5352      * True to render each contained item at the time it becomes active, false to render all contained items
5353      * as soon as the layout is rendered (defaults to false).  If there is a significant amount of content or
5354      * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to
5355      * true might improve performance.
5356      */
5357     deferredRender : false,
5358
5359     /**
5360      * @cfg {Boolean} layoutOnCardChange
5361      * True to force a layout of the active item when the active card is changed. Defaults to false.
5362      */
5363     layoutOnCardChange : false,
5364
5365     /**
5366      * @cfg {Boolean} renderHidden @hide
5367      */
5368     // private
5369     renderHidden : true,
5370
5371     type: 'card',
5372
5373     /**
5374      * Sets the active (visible) item in the layout.
5375      * @param {String/Number} item The string component id or numeric index of the item to activate
5376      */
5377     setActiveItem : function(item){
5378         var ai = this.activeItem,
5379             ct = this.container;
5380         item = ct.getComponent(item);
5381
5382         // Is this a valid, different card?
5383         if(item && ai != item){
5384
5385             // Changing cards, hide the current one
5386             if(ai){
5387                 ai.hide();
5388                 if (ai.hidden !== true) {
5389                     return false;
5390                 }
5391                 ai.fireEvent('deactivate', ai);
5392             }
5393
5394             var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);
5395
5396             // Change activeItem reference
5397             this.activeItem = item;
5398
5399             // The container is about to get a recursive layout, remove any deferLayout reference
5400             // because it will trigger a redundant layout.
5401             delete item.deferLayout;
5402
5403             // Show the new component
5404             item.show();
5405
5406             this.layout();
5407
5408             if(layout){
5409                 item.doLayout();
5410             }
5411             item.fireEvent('activate', item);
5412         }
5413     },
5414
5415     // private
5416     renderAll : function(ct, target){
5417         if(this.deferredRender){
5418             this.renderItem(this.activeItem, undefined, target);
5419         }else{
5420             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
5421         }
5422     }
5423 });
5424 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;
5425 /**
5426  * @class Ext.layout.AnchorLayout
5427  * @extends Ext.layout.ContainerLayout
5428  * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.
5429  * If the container is resized, all anchored items are automatically rerendered according to their
5430  * <b><tt>{@link #anchor}</tt></b> rules.</p>
5431  * <p>This class is intended to be extended or created via the layout:'anchor' {@link Ext.Container#layout}
5432  * config, and should generally not need to be created directly via the new keyword.</p>
5433  * <p>AnchorLayout does not have any direct config options (other than inherited ones). By default,
5434  * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the
5435  * container using the AnchorLayout can supply an anchoring-specific config property of <b>anchorSize</b>.
5436  * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating
5437  * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring
5438  * logic if necessary.  For example:</p>
5439  * <pre><code>
5440 var viewport = new Ext.Viewport({
5441     layout:'anchor',
5442     anchorSize: {width:800, height:600},
5443     items:[{
5444         title:'Item 1',
5445         html:'Content 1',
5446         width:800,
5447         anchor:'right 20%'
5448     },{
5449         title:'Item 2',
5450         html:'Content 2',
5451         width:300,
5452         anchor:'50% 30%'
5453     },{
5454         title:'Item 3',
5455         html:'Content 3',
5456         width:600,
5457         anchor:'-100 50%'
5458     }]
5459 });
5460  * </code></pre>
5461  */
5462 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
5463     /**
5464      * @cfg {String} anchor
5465      * <p>This configuation option is to be applied to <b>child <tt>items</tt></b> of a container managed by
5466      * this layout (ie. configured with <tt>layout:'anchor'</tt>).</p><br/>
5467      *
5468      * <p>This value is what tells the layout how an item should be anchored to the container. <tt>items</tt>
5469      * added to an AnchorLayout accept an anchoring-specific config property of <b>anchor</b> which is a string
5470      * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').
5471      * The following types of anchor values are supported:<div class="mdetail-params"><ul>
5472      *
5473      * <li><b>Percentage</b> : Any value between 1 and 100, expressed as a percentage.<div class="sub-desc">
5474      * The first anchor is the percentage width that the item should take up within the container, and the
5475      * second is the percentage height.  For example:<pre><code>
5476 // two values specified
5477 anchor: '100% 50%' // render item complete width of the container and
5478                    // 1/2 height of the container
5479 // one value specified
5480 anchor: '100%'     // the width value; the height will default to auto
5481      * </code></pre></div></li>
5482      *
5483      * <li><b>Offsets</b> : Any positive or negative integer value.<div class="sub-desc">
5484      * This is a raw adjustment where the first anchor is the offset from the right edge of the container,
5485      * and the second is the offset from the bottom edge. For example:<pre><code>
5486 // two values specified
5487 anchor: '-50 -100' // render item the complete width of the container
5488                    // minus 50 pixels and
5489                    // the complete height minus 100 pixels.
5490 // one value specified
5491 anchor: '-50'      // anchor value is assumed to be the right offset value
5492                    // bottom offset will default to 0
5493      * </code></pre></div></li>
5494      *
5495      * <li><b>Sides</b> : Valid values are <tt>'right'</tt> (or <tt>'r'</tt>) and <tt>'bottom'</tt>
5496      * (or <tt>'b'</tt>).<div class="sub-desc">
5497      * Either the container must have a fixed size or an anchorSize config value defined at render time in
5498      * order for these to have any effect.</div></li>
5499      *
5500      * <li><b>Mixed</b> : <div class="sub-desc">
5501      * Anchor values can also be mixed as needed.  For example, to render the width offset from the container
5502      * right edge by 50 pixels and 75% of the container's height use:
5503      * <pre><code>
5504 anchor: '-50 75%'
5505      * </code></pre></div></li>
5506      *
5507      *
5508      * </ul></div>
5509      */
5510
5511     // private
5512     monitorResize : true,
5513
5514     type : 'anchor',
5515
5516     /**
5517      * @cfg {String} defaultAnchor
5518      *
5519      * default anchor for all child container items applied if no anchor or specific width is set on the child item.  Defaults to '100%'.
5520      *
5521      */
5522     defaultAnchor : '100%',
5523
5524     parseAnchorRE : /^(r|right|b|bottom)$/i,
5525
5526
5527     getLayoutTargetSize : function() {
5528         var target = this.container.getLayoutTarget(), ret = {};
5529         if (target) {
5530             ret = target.getViewSize();
5531
5532             // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
5533             // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
5534             // with getViewSize
5535             if (Ext.isIE && Ext.isStrict && ret.width == 0){
5536                 ret =  target.getStyleSize();
5537             }
5538             ret.width -= target.getPadding('lr');
5539             ret.height -= target.getPadding('tb');
5540         }
5541         return ret;
5542     },
5543
5544     // private
5545     onLayout : function(container, target) {
5546         Ext.layout.AnchorLayout.superclass.onLayout.call(this, container, target);
5547
5548         var size = this.getLayoutTargetSize(),
5549             containerWidth = size.width,
5550             containerHeight = size.height,
5551             overflow = target.getStyle('overflow'),
5552             components = this.getRenderedItems(container),
5553             len = components.length,
5554             boxes = [],
5555             box,
5556             anchorWidth,
5557             anchorHeight,
5558             component,
5559             anchorSpec,
5560             calcWidth,
5561             calcHeight,
5562             anchorsArray,
5563             totalHeight = 0,
5564             i,
5565             el;
5566
5567         if(containerWidth < 20 && containerHeight < 20){
5568             return;
5569         }
5570
5571         // find the container anchoring size
5572         if(container.anchorSize) {
5573             if(typeof container.anchorSize == 'number') {
5574                 anchorWidth = container.anchorSize;
5575             } else {
5576                 anchorWidth = container.anchorSize.width;
5577                 anchorHeight = container.anchorSize.height;
5578             }
5579         } else {
5580             anchorWidth = container.initialConfig.width;
5581             anchorHeight = container.initialConfig.height;
5582         }
5583
5584         for(i = 0; i < len; i++) {
5585             component = components[i];
5586             el = component.getPositionEl();
5587
5588             // If a child container item has no anchor and no specific width, set the child to the default anchor size
5589             if (!component.anchor && component.items && !Ext.isNumber(component.width) && !(Ext.isIE6 && Ext.isStrict)){
5590                 component.anchor = this.defaultAnchor;
5591             }
5592
5593             if(component.anchor) {
5594                 anchorSpec = component.anchorSpec;
5595                 // cache all anchor values
5596                 if(!anchorSpec){
5597                     anchorsArray = component.anchor.split(' ');
5598                     component.anchorSpec = anchorSpec = {
5599                         right: this.parseAnchor(anchorsArray[0], component.initialConfig.width, anchorWidth),
5600                         bottom: this.parseAnchor(anchorsArray[1], component.initialConfig.height, anchorHeight)
5601                     };
5602                 }
5603                 calcWidth = anchorSpec.right ? this.adjustWidthAnchor(anchorSpec.right(containerWidth) - el.getMargins('lr'), component) : undefined;
5604                 calcHeight = anchorSpec.bottom ? this.adjustHeightAnchor(anchorSpec.bottom(containerHeight) - el.getMargins('tb'), component) : undefined;
5605
5606                 if(calcWidth || calcHeight) {
5607                     boxes.push({
5608                         component: component,
5609                         width: calcWidth || undefined,
5610                         height: calcHeight || undefined
5611                     });
5612                 }
5613             }
5614         }
5615         for (i = 0, len = boxes.length; i < len; i++) {
5616             box = boxes[i];
5617             box.component.setSize(box.width, box.height);
5618         }
5619
5620         if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
5621             var newTargetSize = this.getLayoutTargetSize();
5622             if (newTargetSize.width != size.width || newTargetSize.height != size.height){
5623                 this.adjustmentPass = true;
5624                 this.onLayout(container, target);
5625             }
5626         }
5627
5628         delete this.adjustmentPass;
5629     },
5630
5631     // private
5632     parseAnchor : function(a, start, cstart) {
5633         if (a && a != 'none') {
5634             var last;
5635             // standard anchor
5636             if (this.parseAnchorRE.test(a)) {
5637                 var diff = cstart - start;
5638                 return function(v){
5639                     if(v !== last){
5640                         last = v;
5641                         return v - diff;
5642                     }
5643                 };
5644             // percentage
5645             } else if(a.indexOf('%') != -1) {
5646                 var ratio = parseFloat(a.replace('%', ''))*.01;
5647                 return function(v){
5648                     if(v !== last){
5649                         last = v;
5650                         return Math.floor(v*ratio);
5651                     }
5652                 };
5653             // simple offset adjustment
5654             } else {
5655                 a = parseInt(a, 10);
5656                 if (!isNaN(a)) {
5657                     return function(v) {
5658                         if (v !== last) {
5659                             last = v;
5660                             return v + a;
5661                         }
5662                     };
5663                 }
5664             }
5665         }
5666         return false;
5667     },
5668
5669     // private
5670     adjustWidthAnchor : function(value, comp){
5671         return value;
5672     },
5673
5674     // private
5675     adjustHeightAnchor : function(value, comp){
5676         return value;
5677     }
5678
5679     /**
5680      * @property activeItem
5681      * @hide
5682      */
5683 });
5684 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
5685 /**
5686  * @class Ext.layout.ColumnLayout
5687  * @extends Ext.layout.ContainerLayout
5688  * <p>This is the layout style of choice for creating structural layouts in a multi-column format where the width of
5689  * each column can be specified as a percentage or fixed width, but the height is allowed to vary based on the content.
5690  * This class is intended to be extended or created via the layout:'column' {@link Ext.Container#layout} config,
5691  * and should generally not need to be created directly via the new keyword.</p>
5692  * <p>ColumnLayout does not have any direct config options (other than inherited ones), but it does support a
5693  * specific config property of <b><tt>columnWidth</tt></b> that can be included in the config of any panel added to it.  The
5694  * layout will use the columnWidth (if present) or width of each panel during layout to determine how to size each panel.
5695  * If width or columnWidth is not specified for a given panel, its width will default to the panel's width (or auto).</p>
5696  * <p>The width property is always evaluated as pixels, and must be a number greater than or equal to 1.
5697  * The columnWidth property is always evaluated as a percentage, and must be a decimal value greater than 0 and
5698  * less than 1 (e.g., .25).</p>
5699  * <p>The basic rules for specifying column widths are pretty simple.  The logic makes two passes through the
5700  * set of contained panels.  During the first layout pass, all panels that either have a fixed width or none
5701  * specified (auto) are skipped, but their widths are subtracted from the overall container width.  During the second
5702  * pass, all panels with columnWidths are assigned pixel widths in proportion to their percentages based on
5703  * the total <b>remaining</b> container width.  In other words, percentage width panels are designed to fill the space
5704  * left over by all the fixed-width and/or auto-width panels.  Because of this, while you can specify any number of columns
5705  * with different percentages, the columnWidths must always add up to 1 (or 100%) when added together, otherwise your
5706  * layout may not render as expected.  Example usage:</p>
5707  * <pre><code>
5708 // All columns are percentages -- they must add up to 1
5709 var p = new Ext.Panel({
5710     title: 'Column Layout - Percentage Only',
5711     layout:'column',
5712     items: [{
5713         title: 'Column 1',
5714         columnWidth: .25
5715     },{
5716         title: 'Column 2',
5717         columnWidth: .6
5718     },{
5719         title: 'Column 3',
5720         columnWidth: .15
5721     }]
5722 });
5723
5724 // Mix of width and columnWidth -- all columnWidth values must add up
5725 // to 1. The first column will take up exactly 120px, and the last two
5726 // columns will fill the remaining container width.
5727 var p = new Ext.Panel({
5728     title: 'Column Layout - Mixed',
5729     layout:'column',
5730     items: [{
5731         title: 'Column 1',
5732         width: 120
5733     },{
5734         title: 'Column 2',
5735         columnWidth: .8
5736     },{
5737         title: 'Column 3',
5738         columnWidth: .2
5739     }]
5740 });
5741 </code></pre>
5742  */
5743 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
5744     // private
5745     monitorResize:true,
5746
5747     type: 'column',
5748
5749     extraCls: 'x-column',
5750
5751     scrollOffset : 0,
5752
5753     // private
5754
5755     targetCls: 'x-column-layout-ct',
5756
5757     isValidParent : function(c, target){
5758         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
5759     },
5760
5761     getLayoutTargetSize : function() {
5762         var target = this.container.getLayoutTarget(), ret;
5763         if (target) {
5764             ret = target.getViewSize();
5765
5766             // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
5767             // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
5768             // with getViewSize
5769             if (Ext.isIE && Ext.isStrict && ret.width == 0){
5770                 ret =  target.getStyleSize();
5771             }
5772
5773             ret.width -= target.getPadding('lr');
5774             ret.height -= target.getPadding('tb');
5775         }
5776         return ret;
5777     },
5778
5779     renderAll : function(ct, target) {
5780         if(!this.innerCt){
5781             // the innerCt prevents wrapping and shuffling while
5782             // the container is resizing
5783             this.innerCt = target.createChild({cls:'x-column-inner'});
5784             this.innerCt.createChild({cls:'x-clear'});
5785         }
5786         Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);
5787     },
5788
5789     // private
5790     onLayout : function(ct, target){
5791         var cs = ct.items.items,
5792             len = cs.length,
5793             c,
5794             i,
5795             m,
5796             margins = [];
5797
5798         this.renderAll(ct, target);
5799
5800         var size = this.getLayoutTargetSize();
5801
5802         if(size.width < 1 && size.height < 1){ // display none?
5803             return;
5804         }
5805
5806         var w = size.width - this.scrollOffset,
5807             h = size.height,
5808             pw = w;
5809
5810         this.innerCt.setWidth(w);
5811
5812         // some columns can be percentages while others are fixed
5813         // so we need to make 2 passes
5814
5815         for(i = 0; i < len; i++){
5816             c = cs[i];
5817             m = c.getPositionEl().getMargins('lr');
5818             margins[i] = m;
5819             if(!c.columnWidth){
5820                 pw -= (c.getWidth() + m);
5821             }
5822         }
5823
5824         pw = pw < 0 ? 0 : pw;
5825
5826         for(i = 0; i < len; i++){
5827             c = cs[i];
5828             m = margins[i];
5829             if(c.columnWidth){
5830                 c.setSize(Math.floor(c.columnWidth * pw) - m);
5831             }
5832         }
5833
5834         // Browsers differ as to when they account for scrollbars.  We need to re-measure to see if the scrollbar
5835         // spaces were accounted for properly.  If not, re-layout.
5836         if (Ext.isIE) {
5837             if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
5838                 var ts = this.getLayoutTargetSize();
5839                 if (ts.width != size.width){
5840                     this.adjustmentPass = true;
5841                     this.onLayout(ct, target);
5842                 }
5843             }
5844         }
5845         delete this.adjustmentPass;
5846     }
5847
5848     /**
5849      * @property activeItem
5850      * @hide
5851      */
5852 });
5853
5854 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;
5855 /**
5856  * @class Ext.layout.BorderLayout
5857  * @extends Ext.layout.ContainerLayout
5858  * <p>This is a multi-pane, application-oriented UI layout style that supports multiple
5859  * nested panels, automatic {@link Ext.layout.BorderLayout.Region#split split} bars between
5860  * {@link Ext.layout.BorderLayout.Region#BorderLayout.Region regions} and built-in
5861  * {@link Ext.layout.BorderLayout.Region#collapsible expanding and collapsing} of regions.</p>
5862  * <p>This class is intended to be extended or created via the <tt>layout:'border'</tt>
5863  * {@link Ext.Container#layout} config, and should generally not need to be created directly
5864  * via the new keyword.</p>
5865  * <p>BorderLayout does not have any direct config options (other than inherited ones).
5866  * All configuration options available for customizing the BorderLayout are at the
5867  * {@link Ext.layout.BorderLayout.Region} and {@link Ext.layout.BorderLayout.SplitRegion}
5868  * levels.</p>
5869  * <p>Example usage:</p>
5870  * <pre><code>
5871 var myBorderPanel = new Ext.Panel({
5872     {@link Ext.Component#renderTo renderTo}: document.body,
5873     {@link Ext.BoxComponent#width width}: 700,
5874     {@link Ext.BoxComponent#height height}: 500,
5875     {@link Ext.Panel#title title}: 'Border Layout',
5876     {@link Ext.Container#layout layout}: 'border',
5877     {@link Ext.Container#items items}: [{
5878         {@link Ext.Panel#title title}: 'South Region is resizable',
5879         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south',     // position for region
5880         {@link Ext.BoxComponent#height height}: 100,
5881         {@link Ext.layout.BorderLayout.Region#split split}: true,         // enable resizing
5882         {@link Ext.SplitBar#minSize minSize}: 75,         // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50}
5883         {@link Ext.SplitBar#maxSize maxSize}: 150,
5884         {@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5'
5885     },{
5886         // xtype: 'panel' implied by default
5887         {@link Ext.Panel#title title}: 'West Region is collapsible',
5888         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}:'west',
5889         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 0 0 5',
5890         {@link Ext.BoxComponent#width width}: 200,
5891         {@link Ext.layout.BorderLayout.Region#collapsible collapsible}: true,   // make collapsible
5892         {@link Ext.layout.BorderLayout.Region#cmargins cmargins}: '5 5 0 5', // adjust top margin when collapsed
5893         {@link Ext.Component#id id}: 'west-region-container',
5894         {@link Ext.Container#layout layout}: 'fit',
5895         {@link Ext.Panel#unstyled unstyled}: true
5896     },{
5897         {@link Ext.Panel#title title}: 'Center Region',
5898         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'center',     // center region is required, no width/height specified
5899         {@link Ext.Component#xtype xtype}: 'container',
5900         {@link Ext.Container#layout layout}: 'fit',
5901         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 5 0 0'
5902     }]
5903 });
5904 </code></pre>
5905  * <p><b><u>Notes</u></b>:</p><div class="mdetail-params"><ul>
5906  * <li>Any container using the BorderLayout <b>must</b> have a child item with <tt>region:'center'</tt>.
5907  * The child item in the center region will always be resized to fill the remaining space not used by
5908  * the other regions in the layout.</li>
5909  * <li>Any child items with a region of <tt>west</tt> or <tt>east</tt> must have <tt>width</tt> defined
5910  * (an integer representing the number of pixels that the region should take up).</li>
5911  * <li>Any child items with a region of <tt>north</tt> or <tt>south</tt> must have <tt>height</tt> defined.</li>
5912  * <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
5913  * Components within a BorderLayout, have them wrapped by an additional Container which is directly
5914  * managed by the BorderLayout.  If the region is to be collapsible, the Container used directly
5915  * by the BorderLayout manager should be a Panel.  In the following example a Container (an Ext.Panel)
5916  * is added to the west region:
5917  * <div style="margin-left:16px"><pre><code>
5918 wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container');
5919 wrc.{@link Ext.Panel#removeAll removeAll}();
5920 wrc.{@link Ext.Container#add add}({
5921     title: 'Added Panel',
5922     html: 'Some content'
5923 });
5924 wrc.{@link Ext.Container#doLayout doLayout}();
5925  * </code></pre></div>
5926  * </li>
5927  * <li> To reference a {@link Ext.layout.BorderLayout.Region Region}:
5928  * <div style="margin-left:16px"><pre><code>
5929 wr = myBorderPanel.layout.west;
5930  * </code></pre></div>
5931  * </li>
5932  * </ul></div>
5933  */
5934 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
5935     // private
5936     monitorResize:true,
5937     // private
5938     rendered : false,
5939
5940     type: 'border',
5941
5942     targetCls: 'x-border-layout-ct',
5943
5944     getLayoutTargetSize : function() {
5945         var target = this.container.getLayoutTarget();
5946         return target ? target.getViewSize() : {};
5947     },
5948
5949     // private
5950     onLayout : function(ct, target){
5951         var collapsed, i, c, pos, items = ct.items.items, len = items.length;
5952         if(!this.rendered){
5953             collapsed = [];
5954             for(i = 0; i < len; i++) {
5955                 c = items[i];
5956                 pos = c.region;
5957                 if(c.collapsed){
5958                     collapsed.push(c);
5959                 }
5960                 c.collapsed = false;
5961                 if(!c.rendered){
5962                     c.render(target, i);
5963                     c.getPositionEl().addClass('x-border-panel');
5964                 }
5965                 this[pos] = pos != 'center' && c.split ?
5966                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
5967                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
5968                 this[pos].render(target, c);
5969             }
5970             this.rendered = true;
5971         }
5972
5973         var size = this.getLayoutTargetSize();
5974         if(size.width < 20 || size.height < 20){ // display none?
5975             if(collapsed){
5976                 this.restoreCollapsed = collapsed;
5977             }
5978             return;
5979         }else if(this.restoreCollapsed){
5980             collapsed = this.restoreCollapsed;
5981             delete this.restoreCollapsed;
5982         }
5983
5984         var w = size.width, h = size.height,
5985             centerW = w, centerH = h, centerY = 0, centerX = 0,
5986             n = this.north, s = this.south, west = this.west, e = this.east, c = this.center,
5987             b, m, totalWidth, totalHeight;
5988         if(!c && Ext.layout.BorderLayout.WARN !== false){
5989             throw 'No center region defined in BorderLayout ' + ct.id;
5990         }
5991
5992         if(n && n.isVisible()){
5993             b = n.getSize();
5994             m = n.getMargins();
5995             b.width = w - (m.left+m.right);
5996             b.x = m.left;
5997             b.y = m.top;
5998             centerY = b.height + b.y + m.bottom;
5999             centerH -= centerY;
6000             n.applyLayout(b);
6001         }
6002         if(s && s.isVisible()){
6003             b = s.getSize();
6004             m = s.getMargins();
6005             b.width = w - (m.left+m.right);
6006             b.x = m.left;
6007             totalHeight = (b.height + m.top + m.bottom);
6008             b.y = h - totalHeight + m.top;
6009             centerH -= totalHeight;
6010             s.applyLayout(b);
6011         }
6012         if(west && west.isVisible()){
6013             b = west.getSize();
6014             m = west.getMargins();
6015             b.height = centerH - (m.top+m.bottom);
6016             b.x = m.left;
6017             b.y = centerY + m.top;
6018             totalWidth = (b.width + m.left + m.right);
6019             centerX += totalWidth;
6020             centerW -= totalWidth;
6021             west.applyLayout(b);
6022         }
6023         if(e && e.isVisible()){
6024             b = e.getSize();
6025             m = e.getMargins();
6026             b.height = centerH - (m.top+m.bottom);
6027             totalWidth = (b.width + m.left + m.right);
6028             b.x = w - totalWidth + m.left;
6029             b.y = centerY + m.top;
6030             centerW -= totalWidth;
6031             e.applyLayout(b);
6032         }
6033         if(c){
6034             m = c.getMargins();
6035             var centerBox = {
6036                 x: centerX + m.left,
6037                 y: centerY + m.top,
6038                 width: centerW - (m.left+m.right),
6039                 height: centerH - (m.top+m.bottom)
6040             };
6041             c.applyLayout(centerBox);
6042         }
6043         if(collapsed){
6044             for(i = 0, len = collapsed.length; i < len; i++){
6045                 collapsed[i].collapse(false);
6046             }
6047         }
6048         if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue
6049             target.repaint();
6050         }
6051         // Putting a border layout into an overflowed container is NOT correct and will make a second layout pass necessary.
6052         if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
6053             var ts = this.getLayoutTargetSize();
6054             if (ts.width != size.width || ts.height != size.height){
6055                 this.adjustmentPass = true;
6056                 this.onLayout(ct, target);
6057             }
6058         }
6059         delete this.adjustmentPass;
6060     },
6061
6062     destroy: function() {
6063         var r = ['north', 'south', 'east', 'west'], i, region;
6064         for (i = 0; i < r.length; i++) {
6065             region = this[r[i]];
6066             if(region){
6067                 if(region.destroy){
6068                     region.destroy();
6069                 }else if (region.split){
6070                     region.split.destroy(true);
6071                 }
6072             }
6073         }
6074         Ext.layout.BorderLayout.superclass.destroy.call(this);
6075     }
6076
6077     /**
6078      * @property activeItem
6079      * @hide
6080      */
6081 });
6082
6083 /**
6084  * @class Ext.layout.BorderLayout.Region
6085  * <p>This is a region of a {@link Ext.layout.BorderLayout BorderLayout} that acts as a subcontainer
6086  * within the layout.  Each region has its own {@link Ext.layout.ContainerLayout layout} that is
6087  * independent of other regions and the containing BorderLayout, and can be any of the
6088  * {@link Ext.layout.ContainerLayout valid Ext layout types}.</p>
6089  * <p>Region size is managed automatically and cannot be changed by the user -- for
6090  * {@link #split resizable regions}, see {@link Ext.layout.BorderLayout.SplitRegion}.</p>
6091  * @constructor
6092  * Create a new Region.
6093  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
6094  * @param {Object} config The configuration options
6095  * @param {String} position The region position.  Valid values are: <tt>north</tt>, <tt>south</tt>,
6096  * <tt>east</tt>, <tt>west</tt> and <tt>center</tt>.  Every {@link Ext.layout.BorderLayout BorderLayout}
6097  * <b>must have a center region</b> for the primary content -- all other regions are optional.
6098  */
6099 Ext.layout.BorderLayout.Region = function(layout, config, pos){
6100     Ext.apply(this, config);
6101     this.layout = layout;
6102     this.position = pos;
6103     this.state = {};
6104     if(typeof this.margins == 'string'){
6105         this.margins = this.layout.parseMargins(this.margins);
6106     }
6107     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
6108     if(this.collapsible){
6109         if(typeof this.cmargins == 'string'){
6110             this.cmargins = this.layout.parseMargins(this.cmargins);
6111         }
6112         if(this.collapseMode == 'mini' && !this.cmargins){
6113             this.cmargins = {left:0,top:0,right:0,bottom:0};
6114         }else{
6115             this.cmargins = Ext.applyIf(this.cmargins || {},
6116                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
6117         }
6118     }
6119 };
6120
6121 Ext.layout.BorderLayout.Region.prototype = {
6122     /**
6123      * @cfg {Boolean} animFloat
6124      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
6125      * panel that will close again once the user mouses out of that panel (or clicks out if
6126      * <tt>{@link #autoHide} = false</tt>).  Setting <tt>{@link #animFloat} = false</tt> will
6127      * prevent the open and close of these floated panels from being animated (defaults to <tt>true</tt>).
6128      */
6129     /**
6130      * @cfg {Boolean} autoHide
6131      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
6132      * panel.  If <tt>autoHide = true</tt>, the panel will automatically hide after the user mouses
6133      * out of the panel.  If <tt>autoHide = false</tt>, the panel will continue to display until the
6134      * user clicks outside of the panel (defaults to <tt>true</tt>).
6135      */
6136     /**
6137      * @cfg {String} collapseMode
6138      * <tt>collapseMode</tt> supports two configuration values:<div class="mdetail-params"><ul>
6139      * <li><b><tt>undefined</tt></b> (default)<div class="sub-desc">By default, {@link #collapsible}
6140      * regions are collapsed by clicking the expand/collapse tool button that renders into the region's
6141      * title bar.</div></li>
6142      * <li><b><tt>'mini'</tt></b><div class="sub-desc">Optionally, when <tt>collapseMode</tt> is set to
6143      * <tt>'mini'</tt> the region's split bar will also display a small collapse button in the center of
6144      * the bar. In <tt>'mini'</tt> mode the region will collapse to a thinner bar than in normal mode.
6145      * </div></li>
6146      * </ul></div></p>
6147      * <p><b>Note</b>: if a collapsible region does not have a title bar, then set <tt>collapseMode =
6148      * 'mini'</tt> and <tt>{@link #split} = true</tt> in order for the region to be {@link #collapsible}
6149      * by the user as the expand/collapse tool button (that would go in the title bar) will not be rendered.</p>
6150      * <p>See also <tt>{@link #cmargins}</tt>.</p>
6151      */
6152     /**
6153      * @cfg {Object} margins
6154      * An object containing margins to apply to the region when in the expanded state in the
6155      * format:<pre><code>
6156 {
6157     top: (top margin),
6158     right: (right margin),
6159     bottom: (bottom margin),
6160     left: (left margin)
6161 }</code></pre>
6162      * <p>May also be a string containing space-separated, numeric margin values. The order of the
6163      * sides associated with each value matches the way CSS processes margin values:</p>
6164      * <p><div class="mdetail-params"><ul>
6165      * <li>If there is only one value, it applies to all sides.</li>
6166      * <li>If there are two values, the top and bottom borders are set to the first value and the
6167      * right and left are set to the second.</li>
6168      * <li>If there are three values, the top is set to the first value, the left and right are set
6169      * to the second, and the bottom is set to the third.</li>
6170      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
6171      * </ul></div></p>
6172      * <p>Defaults to:</p><pre><code>
6173      * {top:0, right:0, bottom:0, left:0}
6174      * </code></pre>
6175      */
6176     /**
6177      * @cfg {Object} cmargins
6178      * An object containing margins to apply to the region when in the collapsed state in the
6179      * format:<pre><code>
6180 {
6181     top: (top margin),
6182     right: (right margin),
6183     bottom: (bottom margin),
6184     left: (left margin)
6185 }</code></pre>
6186      * <p>May also be a string containing space-separated, numeric margin values. The order of the
6187      * sides associated with each value matches the way CSS processes margin values.</p>
6188      * <p><ul>
6189      * <li>If there is only one value, it applies to all sides.</li>
6190      * <li>If there are two values, the top and bottom borders are set to the first value and the
6191      * right and left are set to the second.</li>
6192      * <li>If there are three values, the top is set to the first value, the left and right are set
6193      * to the second, and the bottom is set to the third.</li>
6194      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
6195      * </ul></p>
6196      */
6197     /**
6198      * @cfg {Boolean} collapsible
6199      * <p><tt>true</tt> to allow the user to collapse this region (defaults to <tt>false</tt>).  If
6200      * <tt>true</tt>, an expand/collapse tool button will automatically be rendered into the title
6201      * bar of the region, otherwise the button will not be shown.</p>
6202      * <p><b>Note</b>: that a title bar is required to display the collapse/expand toggle button -- if
6203      * no <tt>title</tt> is specified for the region's panel, the region will only be collapsible if
6204      * <tt>{@link #collapseMode} = 'mini'</tt> and <tt>{@link #split} = true</tt>.
6205      */
6206     collapsible : false,
6207     /**
6208      * @cfg {Boolean} split
6209      * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and
6210      * display a 5px wide {@link Ext.SplitBar} between this region and its neighbor, allowing the user to
6211      * resize the regions dynamically.  Defaults to <tt>false</tt> creating a
6212      * {@link Ext.layout.BorderLayout.Region Region}.</p><br>
6213      * <p><b>Notes</b>:</p><div class="mdetail-params"><ul>
6214      * <li>this configuration option is ignored if <tt>region='center'</tt></li>
6215      * <li>when <tt>split == true</tt>, it is common to specify a
6216      * <tt>{@link Ext.SplitBar#minSize minSize}</tt> and <tt>{@link Ext.SplitBar#maxSize maxSize}</tt>
6217      * for the {@link Ext.BoxComponent BoxComponent} representing the region. These are not native
6218      * configs of {@link Ext.BoxComponent BoxComponent}, and are used only by this class.</li>
6219      * <li>if <tt>{@link #collapseMode} = 'mini'</tt> requires <tt>split = true</tt> to reserve space
6220      * for the collapse tool</tt></li>
6221      * </ul></div>
6222      */
6223     split:false,
6224     /**
6225      * @cfg {Boolean} floatable
6226      * <tt>true</tt> to allow clicking a collapsed region's bar to display the region's panel floated
6227      * above the layout, <tt>false</tt> to force the user to fully expand a collapsed region by
6228      * clicking the expand button to see it again (defaults to <tt>true</tt>).
6229      */
6230     floatable: true,
6231     /**
6232      * @cfg {Number} minWidth
6233      * <p>The minimum allowable width in pixels for this region (defaults to <tt>50</tt>).
6234      * <tt>maxWidth</tt> may also be specified.</p><br>
6235      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
6236      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
6237      * <tt>minWidth</tt> / <tt>maxWidth</tt>.</p>
6238      */
6239     minWidth:50,
6240     /**
6241      * @cfg {Number} minHeight
6242      * The minimum allowable height in pixels for this region (defaults to <tt>50</tt>)
6243      * <tt>maxHeight</tt> may also be specified.</p><br>
6244      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
6245      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
6246      * <tt>minHeight</tt> / <tt>maxHeight</tt>.</p>
6247      */
6248     minHeight:50,
6249
6250     // private
6251     defaultMargins : {left:0,top:0,right:0,bottom:0},
6252     // private
6253     defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
6254     // private
6255     defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
6256     floatingZIndex: 100,
6257
6258     /**
6259      * True if this region is collapsed. Read-only.
6260      * @type Boolean
6261      * @property
6262      */
6263     isCollapsed : false,
6264
6265     /**
6266      * This region's panel.  Read-only.
6267      * @type Ext.Panel
6268      * @property panel
6269      */
6270     /**
6271      * This region's layout.  Read-only.
6272      * @type Layout
6273      * @property layout
6274      */
6275     /**
6276      * This region's layout position (north, south, east, west or center).  Read-only.
6277      * @type String
6278      * @property position
6279      */
6280
6281     // private
6282     render : function(ct, p){
6283         this.panel = p;
6284         p.el.enableDisplayMode();
6285         this.targetEl = ct;
6286         this.el = p.el;
6287
6288         var gs = p.getState, ps = this.position;
6289         p.getState = function(){
6290             return Ext.apply(gs.call(p) || {}, this.state);
6291         }.createDelegate(this);
6292
6293         if(ps != 'center'){
6294             p.allowQueuedExpand = false;
6295             p.on({
6296                 beforecollapse: this.beforeCollapse,
6297                 collapse: this.onCollapse,
6298                 beforeexpand: this.beforeExpand,
6299                 expand: this.onExpand,
6300                 hide: this.onHide,
6301                 show: this.onShow,
6302                 scope: this
6303             });
6304             if(this.collapsible || this.floatable){
6305                 p.collapseEl = 'el';
6306                 p.slideAnchor = this.getSlideAnchor();
6307             }
6308             if(p.tools && p.tools.toggle){
6309                 p.tools.toggle.addClass('x-tool-collapse-'+ps);
6310                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
6311             }
6312         }
6313     },
6314
6315     // private
6316     getCollapsedEl : function(){
6317         if(!this.collapsedEl){
6318             if(!this.toolTemplate){
6319                 var tt = new Ext.Template(
6320                      '<div class="x-tool x-tool-{id}">&#160;</div>'
6321                 );
6322                 tt.disableFormats = true;
6323                 tt.compile();
6324                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
6325             }
6326             this.collapsedEl = this.targetEl.createChild({
6327                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
6328                 id: this.panel.id + '-xcollapsed'
6329             });
6330             this.collapsedEl.enableDisplayMode('block');
6331
6332             if(this.collapseMode == 'mini'){
6333                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
6334                 this.miniCollapsedEl = this.collapsedEl.createChild({
6335                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
6336                 });
6337                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
6338                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
6339                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
6340             }else {
6341                 if(this.collapsible !== false && !this.hideCollapseTool) {
6342                     var t = this.expandToolEl = this.toolTemplate.append(
6343                             this.collapsedEl.dom,
6344                             {id:'expand-'+this.position}, true);
6345                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
6346                     t.on('click', this.onExpandClick, this, {stopEvent:true});
6347                 }
6348                 if(this.floatable !== false || this.titleCollapse){
6349                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
6350                    this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
6351                 }
6352             }
6353         }
6354         return this.collapsedEl;
6355     },
6356
6357     // private
6358     onExpandClick : function(e){
6359         if(this.isSlid){
6360             this.panel.expand(false);
6361         }else{
6362             this.panel.expand();
6363         }
6364     },
6365
6366     // private
6367     onCollapseClick : function(e){
6368         this.panel.collapse();
6369     },
6370
6371     // private
6372     beforeCollapse : function(p, animate){
6373         this.lastAnim = animate;
6374         if(this.splitEl){
6375             this.splitEl.hide();
6376         }
6377         this.getCollapsedEl().show();
6378         var el = this.panel.getEl();
6379         this.originalZIndex = el.getStyle('z-index');
6380         el.setStyle('z-index', 100);
6381         this.isCollapsed = true;
6382         this.layout.layout();
6383     },
6384
6385     // private
6386     onCollapse : function(animate){
6387         this.panel.el.setStyle('z-index', 1);
6388         if(this.lastAnim === false || this.panel.animCollapse === false){
6389             this.getCollapsedEl().dom.style.visibility = 'visible';
6390         }else{
6391             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
6392         }
6393         this.state.collapsed = true;
6394         this.panel.saveState();
6395     },
6396
6397     // private
6398     beforeExpand : function(animate){
6399         if(this.isSlid){
6400             this.afterSlideIn();
6401         }
6402         var c = this.getCollapsedEl();
6403         this.el.show();
6404         if(this.position == 'east' || this.position == 'west'){
6405             this.panel.setSize(undefined, c.getHeight());
6406         }else{
6407             this.panel.setSize(c.getWidth(), undefined);
6408         }
6409         c.hide();
6410         c.dom.style.visibility = 'hidden';
6411         this.panel.el.setStyle('z-index', this.floatingZIndex);
6412     },
6413
6414     // private
6415     onExpand : function(){
6416         this.isCollapsed = false;
6417         if(this.splitEl){
6418             this.splitEl.show();
6419         }
6420         this.layout.layout();
6421         this.panel.el.setStyle('z-index', this.originalZIndex);
6422         this.state.collapsed = false;
6423         this.panel.saveState();
6424     },
6425
6426     // private
6427     collapseClick : function(e){
6428         if(this.isSlid){
6429            e.stopPropagation();
6430            this.slideIn();
6431         }else{
6432            e.stopPropagation();
6433            this.slideOut();
6434         }
6435     },
6436
6437     // private
6438     onHide : function(){
6439         if(this.isCollapsed){
6440             this.getCollapsedEl().hide();
6441         }else if(this.splitEl){
6442             this.splitEl.hide();
6443         }
6444     },
6445
6446     // private
6447     onShow : function(){
6448         if(this.isCollapsed){
6449             this.getCollapsedEl().show();
6450         }else if(this.splitEl){
6451             this.splitEl.show();
6452         }
6453     },
6454
6455     /**
6456      * True if this region is currently visible, else false.
6457      * @return {Boolean}
6458      */
6459     isVisible : function(){
6460         return !this.panel.hidden;
6461     },
6462
6463     /**
6464      * Returns the current margins for this region.  If the region is collapsed, the
6465      * {@link #cmargins} (collapsed margins) value will be returned, otherwise the
6466      * {@link #margins} value will be returned.
6467      * @return {Object} An object containing the element's margins: <tt>{left: (left
6468      * margin), top: (top margin), right: (right margin), bottom: (bottom margin)}</tt>
6469      */
6470     getMargins : function(){
6471         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
6472     },
6473
6474     /**
6475      * Returns the current size of this region.  If the region is collapsed, the size of the
6476      * collapsedEl will be returned, otherwise the size of the region's panel will be returned.
6477      * @return {Object} An object containing the element's size: <tt>{width: (element width),
6478      * height: (element height)}</tt>
6479      */
6480     getSize : function(){
6481         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
6482     },
6483
6484     /**
6485      * Sets the specified panel as the container element for this region.
6486      * @param {Ext.Panel} panel The new panel
6487      */
6488     setPanel : function(panel){
6489         this.panel = panel;
6490     },
6491
6492     /**
6493      * Returns the minimum allowable width for this region.
6494      * @return {Number} The minimum width
6495      */
6496     getMinWidth: function(){
6497         return this.minWidth;
6498     },
6499
6500     /**
6501      * Returns the minimum allowable height for this region.
6502      * @return {Number} The minimum height
6503      */
6504     getMinHeight: function(){
6505         return this.minHeight;
6506     },
6507
6508     // private
6509     applyLayoutCollapsed : function(box){
6510         var ce = this.getCollapsedEl();
6511         ce.setLeftTop(box.x, box.y);
6512         ce.setSize(box.width, box.height);
6513     },
6514
6515     // private
6516     applyLayout : function(box){
6517         if(this.isCollapsed){
6518             this.applyLayoutCollapsed(box);
6519         }else{
6520             this.panel.setPosition(box.x, box.y);
6521             this.panel.setSize(box.width, box.height);
6522         }
6523     },
6524
6525     // private
6526     beforeSlide: function(){
6527         this.panel.beforeEffect();
6528     },
6529
6530     // private
6531     afterSlide : function(){
6532         this.panel.afterEffect();
6533     },
6534
6535     // private
6536     initAutoHide : function(){
6537         if(this.autoHide !== false){
6538             if(!this.autoHideHd){
6539                 this.autoHideSlideTask = new Ext.util.DelayedTask(this.slideIn, this);
6540                 this.autoHideHd = {
6541                     "mouseout": function(e){
6542                         if(!e.within(this.el, true)){
6543                             this.autoHideSlideTask.delay(500);
6544                         }
6545                     },
6546                     "mouseover" : function(e){
6547                         this.autoHideSlideTask.cancel();
6548                     },
6549                     scope : this
6550                 };
6551             }
6552             this.el.on(this.autoHideHd);
6553             this.collapsedEl.on(this.autoHideHd);
6554         }
6555     },
6556
6557     // private
6558     clearAutoHide : function(){
6559         if(this.autoHide !== false){
6560             this.el.un("mouseout", this.autoHideHd.mouseout);
6561             this.el.un("mouseover", this.autoHideHd.mouseover);
6562             this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
6563             this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
6564         }
6565     },
6566
6567     // private
6568     clearMonitor : function(){
6569         Ext.getDoc().un("click", this.slideInIf, this);
6570     },
6571
6572     /**
6573      * If this Region is {@link #floatable}, this method slides this Region into full visibility <i>over the top
6574      * of the center Region</i> where it floats until either {@link #slideIn} is called, or other regions of the layout
6575      * are clicked, or the mouse exits the Region.
6576      */
6577     slideOut : function(){
6578         if(this.isSlid || this.el.hasActiveFx()){
6579             return;
6580         }
6581         this.isSlid = true;
6582         var ts = this.panel.tools, dh, pc;
6583         if(ts && ts.toggle){
6584             ts.toggle.hide();
6585         }
6586         this.el.show();
6587
6588         // Temporarily clear the collapsed flag so we can onResize the panel on the slide
6589         pc = this.panel.collapsed;
6590         this.panel.collapsed = false;
6591
6592         if(this.position == 'east' || this.position == 'west'){
6593             // Temporarily clear the deferHeight flag so we can size the height on the slide
6594             dh = this.panel.deferHeight;
6595             this.panel.deferHeight = false;
6596
6597             this.panel.setSize(undefined, this.collapsedEl.getHeight());
6598
6599             // Put the deferHeight flag back after setSize
6600             this.panel.deferHeight = dh;
6601         }else{
6602             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
6603         }
6604
6605         // Put the collapsed flag back after onResize
6606         this.panel.collapsed = pc;
6607
6608         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
6609         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
6610         this.el.setStyle("z-index", this.floatingZIndex+2);
6611         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
6612         if(this.animFloat !== false){
6613             this.beforeSlide();
6614             this.el.slideIn(this.getSlideAnchor(), {
6615                 callback: function(){
6616                     this.afterSlide();
6617                     this.initAutoHide();
6618                     Ext.getDoc().on("click", this.slideInIf, this);
6619                 },
6620                 scope: this,
6621                 block: true
6622             });
6623         }else{
6624             this.initAutoHide();
6625              Ext.getDoc().on("click", this.slideInIf, this);
6626         }
6627     },
6628
6629     // private
6630     afterSlideIn : function(){
6631         this.clearAutoHide();
6632         this.isSlid = false;
6633         this.clearMonitor();
6634         this.el.setStyle("z-index", "");
6635         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
6636         this.el.dom.style.left = this.restoreLT[0];
6637         this.el.dom.style.top = this.restoreLT[1];
6638
6639         var ts = this.panel.tools;
6640         if(ts && ts.toggle){
6641             ts.toggle.show();
6642         }
6643     },
6644
6645     /**
6646      * If this Region is {@link #floatable}, and this Region has been slid into floating visibility, then this method slides
6647      * this region back into its collapsed state.
6648      */
6649     slideIn : function(cb){
6650         if(!this.isSlid || this.el.hasActiveFx()){
6651             Ext.callback(cb);
6652             return;
6653         }
6654         this.isSlid = false;
6655         if(this.animFloat !== false){
6656             this.beforeSlide();
6657             this.el.slideOut(this.getSlideAnchor(), {
6658                 callback: function(){
6659                     this.el.hide();
6660                     this.afterSlide();
6661                     this.afterSlideIn();
6662                     Ext.callback(cb);
6663                 },
6664                 scope: this,
6665                 block: true
6666             });
6667         }else{
6668             this.el.hide();
6669             this.afterSlideIn();
6670         }
6671     },
6672
6673     // private
6674     slideInIf : function(e){
6675         if(!e.within(this.el)){
6676             this.slideIn();
6677         }
6678     },
6679
6680     // private
6681     anchors : {
6682         "west" : "left",
6683         "east" : "right",
6684         "north" : "top",
6685         "south" : "bottom"
6686     },
6687
6688     // private
6689     sanchors : {
6690         "west" : "l",
6691         "east" : "r",
6692         "north" : "t",
6693         "south" : "b"
6694     },
6695
6696     // private
6697     canchors : {
6698         "west" : "tl-tr",
6699         "east" : "tr-tl",
6700         "north" : "tl-bl",
6701         "south" : "bl-tl"
6702     },
6703
6704     // private
6705     getAnchor : function(){
6706         return this.anchors[this.position];
6707     },
6708
6709     // private
6710     getCollapseAnchor : function(){
6711         return this.canchors[this.position];
6712     },
6713
6714     // private
6715     getSlideAnchor : function(){
6716         return this.sanchors[this.position];
6717     },
6718
6719     // private
6720     getAlignAdj : function(){
6721         var cm = this.cmargins;
6722         switch(this.position){
6723             case "west":
6724                 return [0, 0];
6725             break;
6726             case "east":
6727                 return [0, 0];
6728             break;
6729             case "north":
6730                 return [0, 0];
6731             break;
6732             case "south":
6733                 return [0, 0];
6734             break;
6735         }
6736     },
6737
6738     // private
6739     getExpandAdj : function(){
6740         var c = this.collapsedEl, cm = this.cmargins;
6741         switch(this.position){
6742             case "west":
6743                 return [-(cm.right+c.getWidth()+cm.left), 0];
6744             break;
6745             case "east":
6746                 return [cm.right+c.getWidth()+cm.left, 0];
6747             break;
6748             case "north":
6749                 return [0, -(cm.top+cm.bottom+c.getHeight())];
6750             break;
6751             case "south":
6752                 return [0, cm.top+cm.bottom+c.getHeight()];
6753             break;
6754         }
6755     },
6756
6757     destroy : function(){
6758         if (this.autoHideSlideTask && this.autoHideSlideTask.cancel){
6759             this.autoHideSlideTask.cancel();
6760         }
6761         Ext.destroyMembers(this, 'miniCollapsedEl', 'collapsedEl', 'expandToolEl');
6762     }
6763 };
6764
6765 /**
6766  * @class Ext.layout.BorderLayout.SplitRegion
6767  * @extends Ext.layout.BorderLayout.Region
6768  * <p>This is a specialized type of {@link Ext.layout.BorderLayout.Region BorderLayout region} that
6769  * has a built-in {@link Ext.SplitBar} for user resizing of regions.  The movement of the split bar
6770  * is configurable to move either {@link #tickSize smooth or incrementally}.</p>
6771  * @constructor
6772  * Create a new SplitRegion.
6773  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
6774  * @param {Object} config The configuration options
6775  * @param {String} position The region position.  Valid values are: north, south, east, west and center.  Every
6776  * BorderLayout must have a center region for the primary content -- all other regions are optional.
6777  */
6778 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
6779     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
6780     // prevent switch
6781     this.applyLayout = this.applyFns[pos];
6782 };
6783
6784 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
6785     /**
6786      * @cfg {Number} tickSize
6787      * The increment, in pixels by which to move this Region's {@link Ext.SplitBar SplitBar}.
6788      * By default, the {@link Ext.SplitBar SplitBar} moves smoothly.
6789      */
6790     /**
6791      * @cfg {String} splitTip
6792      * The tooltip to display when the user hovers over a
6793      * {@link Ext.layout.BorderLayout.Region#collapsible non-collapsible} region's split bar
6794      * (defaults to <tt>"Drag to resize."</tt>).  Only applies if
6795      * <tt>{@link #useSplitTips} = true</tt>.
6796      */
6797     splitTip : "Drag to resize.",
6798     /**
6799      * @cfg {String} collapsibleSplitTip
6800      * The tooltip to display when the user hovers over a
6801      * {@link Ext.layout.BorderLayout.Region#collapsible collapsible} region's split bar
6802      * (defaults to "Drag to resize. Double click to hide."). Only applies if
6803      * <tt>{@link #useSplitTips} = true</tt>.
6804      */
6805     collapsibleSplitTip : "Drag to resize. Double click to hide.",
6806     /**
6807      * @cfg {Boolean} useSplitTips
6808      * <tt>true</tt> to display a tooltip when the user hovers over a region's split bar
6809      * (defaults to <tt>false</tt>).  The tooltip text will be the value of either
6810      * <tt>{@link #splitTip}</tt> or <tt>{@link #collapsibleSplitTip}</tt> as appropriate.
6811      */
6812     useSplitTips : false,
6813
6814     // private
6815     splitSettings : {
6816         north : {
6817             orientation: Ext.SplitBar.VERTICAL,
6818             placement: Ext.SplitBar.TOP,
6819             maxFn : 'getVMaxSize',
6820             minProp: 'minHeight',
6821             maxProp: 'maxHeight'
6822         },
6823         south : {
6824             orientation: Ext.SplitBar.VERTICAL,
6825             placement: Ext.SplitBar.BOTTOM,
6826             maxFn : 'getVMaxSize',
6827             minProp: 'minHeight',
6828             maxProp: 'maxHeight'
6829         },
6830         east : {
6831             orientation: Ext.SplitBar.HORIZONTAL,
6832             placement: Ext.SplitBar.RIGHT,
6833             maxFn : 'getHMaxSize',
6834             minProp: 'minWidth',
6835             maxProp: 'maxWidth'
6836         },
6837         west : {
6838             orientation: Ext.SplitBar.HORIZONTAL,
6839             placement: Ext.SplitBar.LEFT,
6840             maxFn : 'getHMaxSize',
6841             minProp: 'minWidth',
6842             maxProp: 'maxWidth'
6843         }
6844     },
6845
6846     // private
6847     applyFns : {
6848         west : function(box){
6849             if(this.isCollapsed){
6850                 return this.applyLayoutCollapsed(box);
6851             }
6852             var sd = this.splitEl.dom, s = sd.style;
6853             this.panel.setPosition(box.x, box.y);
6854             var sw = sd.offsetWidth;
6855             s.left = (box.x+box.width-sw)+'px';
6856             s.top = (box.y)+'px';
6857             s.height = Math.max(0, box.height)+'px';
6858             this.panel.setSize(box.width-sw, box.height);
6859         },
6860         east : function(box){
6861             if(this.isCollapsed){
6862                 return this.applyLayoutCollapsed(box);
6863             }
6864             var sd = this.splitEl.dom, s = sd.style;
6865             var sw = sd.offsetWidth;
6866             this.panel.setPosition(box.x+sw, box.y);
6867             s.left = (box.x)+'px';
6868             s.top = (box.y)+'px';
6869             s.height = Math.max(0, box.height)+'px';
6870             this.panel.setSize(box.width-sw, box.height);
6871         },
6872         north : function(box){
6873             if(this.isCollapsed){
6874                 return this.applyLayoutCollapsed(box);
6875             }
6876             var sd = this.splitEl.dom, s = sd.style;
6877             var sh = sd.offsetHeight;
6878             this.panel.setPosition(box.x, box.y);
6879             s.left = (box.x)+'px';
6880             s.top = (box.y+box.height-sh)+'px';
6881             s.width = Math.max(0, box.width)+'px';
6882             this.panel.setSize(box.width, box.height-sh);
6883         },
6884         south : function(box){
6885             if(this.isCollapsed){
6886                 return this.applyLayoutCollapsed(box);
6887             }
6888             var sd = this.splitEl.dom, s = sd.style;
6889             var sh = sd.offsetHeight;
6890             this.panel.setPosition(box.x, box.y+sh);
6891             s.left = (box.x)+'px';
6892             s.top = (box.y)+'px';
6893             s.width = Math.max(0, box.width)+'px';
6894             this.panel.setSize(box.width, box.height-sh);
6895         }
6896     },
6897
6898     // private
6899     render : function(ct, p){
6900         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
6901
6902         var ps = this.position;
6903
6904         this.splitEl = ct.createChild({
6905             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
6906             id: this.panel.id + '-xsplit'
6907         });
6908
6909         if(this.collapseMode == 'mini'){
6910             this.miniSplitEl = this.splitEl.createChild({
6911                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
6912             });
6913             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
6914             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
6915         }
6916
6917         var s = this.splitSettings[ps];
6918
6919         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
6920         this.split.tickSize = this.tickSize;
6921         this.split.placement = s.placement;
6922         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
6923         this.split.minSize = this.minSize || this[s.minProp];
6924         this.split.on("beforeapply", this.onSplitMove, this);
6925         this.split.useShim = this.useShim === true;
6926         this.maxSize = this.maxSize || this[s.maxProp];
6927
6928         if(p.hidden){
6929             this.splitEl.hide();
6930         }
6931
6932         if(this.useSplitTips){
6933             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
6934         }
6935         if(this.collapsible){
6936             this.splitEl.on("dblclick", this.onCollapseClick,  this);
6937         }
6938     },
6939
6940     //docs inherit from superclass
6941     getSize : function(){
6942         if(this.isCollapsed){
6943             return this.collapsedEl.getSize();
6944         }
6945         var s = this.panel.getSize();
6946         if(this.position == 'north' || this.position == 'south'){
6947             s.height += this.splitEl.dom.offsetHeight;
6948         }else{
6949             s.width += this.splitEl.dom.offsetWidth;
6950         }
6951         return s;
6952     },
6953
6954     // private
6955     getHMaxSize : function(){
6956          var cmax = this.maxSize || 10000;
6957          var center = this.layout.center;
6958          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
6959     },
6960
6961     // private
6962     getVMaxSize : function(){
6963         var cmax = this.maxSize || 10000;
6964         var center = this.layout.center;
6965         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
6966     },
6967
6968     // private
6969     onSplitMove : function(split, newSize){
6970         var s = this.panel.getSize();
6971         this.lastSplitSize = newSize;
6972         if(this.position == 'north' || this.position == 'south'){
6973             this.panel.setSize(s.width, newSize);
6974             this.state.height = newSize;
6975         }else{
6976             this.panel.setSize(newSize, s.height);
6977             this.state.width = newSize;
6978         }
6979         this.layout.layout();
6980         this.panel.saveState();
6981         return false;
6982     },
6983
6984     /**
6985      * Returns a reference to the split bar in use by this region.
6986      * @return {Ext.SplitBar} The split bar
6987      */
6988     getSplitBar : function(){
6989         return this.split;
6990     },
6991
6992     // inherit docs
6993     destroy : function() {
6994         Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
6995         Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
6996     }
6997 });
6998
6999 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;
7000 /**
7001  * @class Ext.layout.FormLayout
7002  * @extends Ext.layout.AnchorLayout
7003  * <p>This layout manager is specifically designed for rendering and managing child Components of
7004  * {@link Ext.form.FormPanel forms}. It is responsible for rendering the labels of
7005  * {@link Ext.form.Field Field}s.</p>
7006  *
7007  * <p>This layout manager is used when a Container is configured with the <tt>layout:'form'</tt>
7008  * {@link Ext.Container#layout layout} config option, and should generally not need to be created directly
7009  * via the new keyword. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
7010  *
7011  * <p>In an application, it will usually be preferrable to use a {@link Ext.form.FormPanel FormPanel}
7012  * (which is configured with FormLayout as its layout class by default) since it also provides built-in
7013  * functionality for {@link Ext.form.BasicForm#doAction loading, validating and submitting} the form.</p>
7014  *
7015  * <p>A {@link Ext.Container Container} <i>using</i> the FormLayout layout manager (e.g.
7016  * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) can also accept the following
7017  * layout-specific config properties:<div class="mdetail-params"><ul>
7018  * <li><b><tt>{@link Ext.form.FormPanel#hideLabels hideLabels}</tt></b></li>
7019  * <li><b><tt>{@link Ext.form.FormPanel#labelAlign labelAlign}</tt></b></li>
7020  * <li><b><tt>{@link Ext.form.FormPanel#labelPad labelPad}</tt></b></li>
7021  * <li><b><tt>{@link Ext.form.FormPanel#labelSeparator labelSeparator}</tt></b></li>
7022  * <li><b><tt>{@link Ext.form.FormPanel#labelWidth labelWidth}</tt></b></li>
7023  * </ul></div></p>
7024  *
7025  * <p>Any Component (including Fields) managed by FormLayout accepts the following as a config option:
7026  * <div class="mdetail-params"><ul>
7027  * <li><b><tt>{@link Ext.Component#anchor anchor}</tt></b></li>
7028  * </ul></div></p>
7029  *
7030  * <p>Any Component managed by FormLayout may be rendered as a form field (with an associated label) by
7031  * configuring it with a non-null <b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b>. Components configured
7032  * in this way may be configured with the following options which affect the way the FormLayout renders them:
7033  * <div class="mdetail-params"><ul>
7034  * <li><b><tt>{@link Ext.Component#clearCls clearCls}</tt></b></li>
7035  * <li><b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b></li>
7036  * <li><b><tt>{@link Ext.Component#hideLabel hideLabel}</tt></b></li>
7037  * <li><b><tt>{@link Ext.Component#itemCls itemCls}</tt></b></li>
7038  * <li><b><tt>{@link Ext.Component#labelSeparator labelSeparator}</tt></b></li>
7039  * <li><b><tt>{@link Ext.Component#labelStyle labelStyle}</tt></b></li>
7040  * </ul></div></p>
7041  *
7042  * <p>Example usage:</p>
7043  * <pre><code>
7044 // Required if showing validation messages
7045 Ext.QuickTips.init();
7046
7047 // While you can create a basic Panel with layout:'form', practically
7048 // you should usually use a FormPanel to also get its form functionality
7049 // since it already creates a FormLayout internally.
7050 var form = new Ext.form.FormPanel({
7051     title: 'Form Layout',
7052     bodyStyle: 'padding:15px',
7053     width: 350,
7054     defaultType: 'textfield',
7055     defaults: {
7056         // applied to each contained item
7057         width: 230,
7058         msgTarget: 'side'
7059     },
7060     items: [{
7061             fieldLabel: 'First Name',
7062             name: 'first',
7063             allowBlank: false,
7064             {@link Ext.Component#labelSeparator labelSeparator}: ':' // override labelSeparator layout config
7065         },{
7066             fieldLabel: 'Last Name',
7067             name: 'last'
7068         },{
7069             fieldLabel: 'Email',
7070             name: 'email',
7071             vtype:'email'
7072         }, {
7073             xtype: 'textarea',
7074             hideLabel: true,     // override hideLabels layout config
7075             name: 'msg',
7076             anchor: '100% -53'
7077         }
7078     ],
7079     buttons: [
7080         {text: 'Save'},
7081         {text: 'Cancel'}
7082     ],
7083     layoutConfig: {
7084         {@link #labelSeparator}: '~' // superseded by assignment below
7085     },
7086     // config options applicable to container when layout='form':
7087     hideLabels: false,
7088     labelAlign: 'left',   // or 'right' or 'top'
7089     {@link Ext.form.FormPanel#labelSeparator labelSeparator}: '>>', // takes precedence over layoutConfig value
7090     labelWidth: 65,       // defaults to 100
7091     labelPad: 8           // defaults to 5, must specify labelWidth to be honored
7092 });
7093 </code></pre>
7094  */
7095 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
7096
7097     /**
7098      * @cfg {String} labelSeparator
7099      * See {@link Ext.form.FormPanel}.{@link Ext.form.FormPanel#labelSeparator labelSeparator}.  Configuration
7100      * of this property at the <b>container</b> level takes precedence.
7101      */
7102     labelSeparator : ':',
7103
7104     /**
7105      * Read only. The CSS style specification string added to field labels in this layout if not
7106      * otherwise {@link Ext.Component#labelStyle specified by each contained field}.
7107      * @type String
7108      * @property labelStyle
7109      */
7110
7111     /**
7112      * @cfg {Boolean} trackLabels
7113      * True to show/hide the field label when the field is hidden. Defaults to <tt>true</tt>.
7114      */
7115     trackLabels: true,
7116
7117     type: 'form',
7118
7119     onRemove: function(c){
7120         Ext.layout.FormLayout.superclass.onRemove.call(this, c);
7121         if(this.trackLabels){
7122             c.un('show', this.onFieldShow, this);
7123             c.un('hide', this.onFieldHide, this);
7124         }
7125         // check for itemCt, since we may be removing a fieldset or something similar
7126         var el = c.getPositionEl(),
7127             ct = c.getItemCt && c.getItemCt();
7128         if (c.rendered && ct) {
7129             if (el && el.dom) {
7130                 el.insertAfter(ct);
7131             }
7132             Ext.destroy(ct);
7133             Ext.destroyMembers(c, 'label', 'itemCt');
7134             if (c.customItemCt) {
7135                 Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
7136             }
7137         }
7138     },
7139
7140     // private
7141     setContainer : function(ct){
7142         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
7143         if(ct.labelAlign){
7144             ct.addClass('x-form-label-'+ct.labelAlign);
7145         }
7146
7147         if(ct.hideLabels){
7148             Ext.apply(this, {
7149                 labelStyle: 'display:none',
7150                 elementStyle: 'padding-left:0;',
7151                 labelAdjust: 0
7152             });
7153         }else{
7154             this.labelSeparator = Ext.isDefined(ct.labelSeparator) ? ct.labelSeparator : this.labelSeparator;
7155             ct.labelWidth = ct.labelWidth || 100;
7156             if(Ext.isNumber(ct.labelWidth)){
7157                 var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
7158                 Ext.apply(this, {
7159                     labelAdjust: ct.labelWidth + pad,
7160                     labelStyle: 'width:' + ct.labelWidth + 'px;',
7161                     elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
7162                 });
7163             }
7164             if(ct.labelAlign == 'top'){
7165                 Ext.apply(this, {
7166                     labelStyle: 'width:auto;',
7167                     labelAdjust: 0,
7168                     elementStyle: 'padding-left:0;'
7169                 });
7170             }
7171         }
7172     },
7173
7174     // private
7175     isHide: function(c){
7176         return c.hideLabel || this.container.hideLabels;
7177     },
7178
7179     onFieldShow: function(c){
7180         c.getItemCt().removeClass('x-hide-' + c.hideMode);
7181
7182         // Composite fields will need to layout after the container is made visible
7183         if (c.isComposite) {
7184             c.doLayout();
7185         }
7186     },
7187
7188     onFieldHide: function(c){
7189         c.getItemCt().addClass('x-hide-' + c.hideMode);
7190     },
7191
7192     //private
7193     getLabelStyle: function(s){
7194         var ls = '', items = [this.labelStyle, s];
7195         for (var i = 0, len = items.length; i < len; ++i){
7196             if (items[i]){
7197                 ls += items[i];
7198                 if (ls.substr(-1, 1) != ';'){
7199                     ls += ';';
7200                 }
7201             }
7202         }
7203         return ls;
7204     },
7205
7206     /**
7207      * @cfg {Ext.Template} fieldTpl
7208      * A {@link Ext.Template#compile compile}d {@link Ext.Template} for rendering
7209      * the fully wrapped, labeled and styled form Field. Defaults to:</p><pre><code>
7210 new Ext.Template(
7211     &#39;&lt;div class="x-form-item {itemCls}" tabIndex="-1">&#39;,
7212         &#39;&lt;&#108;abel for="{id}" style="{labelStyle}" class="x-form-item-&#108;abel">{&#108;abel}{labelSeparator}&lt;/&#108;abel>&#39;,
7213         &#39;&lt;div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">&#39;,
7214         &#39;&lt;/div>&lt;div class="{clearCls}">&lt;/div>&#39;,
7215     '&lt;/div>'
7216 );
7217 </code></pre>
7218      * <p>This may be specified to produce a different DOM structure when rendering form Fields.</p>
7219      * <p>A description of the properties within the template follows:</p><div class="mdetail-params"><ul>
7220      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
7221      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
7222      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
7223      * supplied at the container level.</div></li>
7224      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
7225      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
7226      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
7227      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
7228      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
7229      * field (defaults to <tt>''</tt>)</div></li>
7230      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
7231      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
7232      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
7233      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
7234      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
7235      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
7236      * </ul></div>
7237      * <p>Also see <tt>{@link #getTemplateArgs}</tt></p>
7238      */
7239
7240     /**
7241      * @private
7242      *
7243      */
7244     renderItem : function(c, position, target){
7245         if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
7246             var args = this.getTemplateArgs(c);
7247             if(Ext.isNumber(position)){
7248                 position = target.dom.childNodes[position] || null;
7249             }
7250             if(position){
7251                 c.itemCt = this.fieldTpl.insertBefore(position, args, true);
7252             }else{
7253                 c.itemCt = this.fieldTpl.append(target, args, true);
7254             }
7255             if(!c.getItemCt){
7256                 // Non form fields don't have getItemCt, apply it here
7257                 // This will get cleaned up in onRemove
7258                 Ext.apply(c, {
7259                     getItemCt: function(){
7260                         return c.itemCt;
7261                     },
7262                     customItemCt: true
7263                 });
7264             }
7265             c.label = c.getItemCt().child('label.x-form-item-label');
7266             if(!c.rendered){
7267                 c.render('x-form-el-' + c.id);
7268             }else if(!this.isValidParent(c, target)){
7269                 Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
7270             }
7271             if(this.trackLabels){
7272                 if(c.hidden){
7273                     this.onFieldHide(c);
7274                 }
7275                 c.on({
7276                     scope: this,
7277                     show: this.onFieldShow,
7278                     hide: this.onFieldHide
7279                 });
7280             }
7281             this.configureItem(c);
7282         }else {
7283             Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
7284         }
7285     },
7286
7287     /**
7288      * <p>Provides template arguments for rendering the fully wrapped, labeled and styled form Field.</p>
7289      * <p>This method returns an object hash containing properties used by the layout's {@link #fieldTpl}
7290      * to create a correctly wrapped, labeled and styled form Field. This may be overriden to
7291      * create custom layouts. The properties which must be returned are:</p><div class="mdetail-params"><ul>
7292      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
7293      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
7294      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
7295      * supplied at the container level.</div></li>
7296      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
7297      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
7298      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
7299      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
7300      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
7301      * field (defaults to the field's configured fieldLabel property)</div></li>
7302      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
7303      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
7304      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
7305      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
7306      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
7307      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
7308      * </ul></div>
7309      * @param (Ext.form.Field} field The {@link Ext.form.Field Field} being rendered.
7310      * @return {Object} An object hash containing the properties required to render the Field.
7311      */
7312     getTemplateArgs: function(field) {
7313         var noLabelSep = !field.fieldLabel || field.hideLabel;
7314
7315         return {
7316             id            : field.id,
7317             label         : field.fieldLabel,
7318             itemCls       : (field.itemCls || this.container.itemCls || '') + (field.hideLabel ? ' x-hide-label' : ''),
7319             clearCls      : field.clearCls || 'x-form-clear-left',
7320             labelStyle    : this.getLabelStyle(field.labelStyle),
7321             elementStyle  : this.elementStyle || '',
7322             labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator)
7323         };
7324     },
7325
7326     // private
7327     adjustWidthAnchor: function(value, c){
7328         if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){
7329             var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
7330             return value - this.labelAdjust + (adjust ? -3 : 0);
7331         }
7332         return value;
7333     },
7334
7335     adjustHeightAnchor : function(value, c){
7336         if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
7337             return value - c.label.getHeight();
7338         }
7339         return value;
7340     },
7341
7342     // private
7343     isValidParent : function(c, target){
7344         return target && this.container.getEl().contains(c.getPositionEl());
7345     }
7346
7347     /**
7348      * @property activeItem
7349      * @hide
7350      */
7351 });
7352
7353 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
7354 /**
7355  * @class Ext.layout.AccordionLayout
7356  * @extends Ext.layout.FitLayout
7357  * <p>This is a layout that manages multiple Panels in an expandable accordion style such that only
7358  * <b>one Panel can be expanded at any given time</b>. Each Panel has built-in support for expanding and collapsing.</p>
7359  * <p>Note: Only Ext.Panels <b>and all subclasses of Ext.Panel</b> may be used in an accordion layout Container.</p>
7360  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
7361  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
7362  * <p>Example usage:</p>
7363  * <pre><code>
7364 var accordion = new Ext.Panel({
7365     title: 'Accordion Layout',
7366     layout:'accordion',
7367     defaults: {
7368         // applied to each contained panel
7369         bodyStyle: 'padding:15px'
7370     },
7371     layoutConfig: {
7372         // layout-specific configs go here
7373         titleCollapse: false,
7374         animate: true,
7375         activeOnTop: true
7376     },
7377     items: [{
7378         title: 'Panel 1',
7379         html: '&lt;p&gt;Panel content!&lt;/p&gt;'
7380     },{
7381         title: 'Panel 2',
7382         html: '&lt;p&gt;Panel content!&lt;/p&gt;'
7383     },{
7384         title: 'Panel 3',
7385         html: '&lt;p&gt;Panel content!&lt;/p&gt;'
7386     }]
7387 });
7388 </code></pre>
7389  */
7390 Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
7391     /**
7392      * @cfg {Boolean} fill
7393      * True to adjust the active item's height to fill the available space in the container, false to use the
7394      * item's current height, or auto height if not explicitly set (defaults to true).
7395      */
7396     fill : true,
7397     /**
7398      * @cfg {Boolean} autoWidth
7399      * True to set each contained item's width to 'auto', false to use the item's current width (defaults to true).
7400      * Note that some components, in particular the {@link Ext.grid.GridPanel grid}, will not function properly within
7401      * layouts if they have auto width, so in such cases this config should be set to false.
7402      */
7403     autoWidth : true,
7404     /**
7405      * @cfg {Boolean} titleCollapse
7406      * True to allow expand/collapse of each contained panel by clicking anywhere on the title bar, false to allow
7407      * expand/collapse only when the toggle tool button is clicked (defaults to true).  When set to false,
7408      * {@link #hideCollapseTool} should be false also.
7409      */
7410     titleCollapse : true,
7411     /**
7412      * @cfg {Boolean} hideCollapseTool
7413      * True to hide the contained panels' collapse/expand toggle buttons, false to display them (defaults to false).
7414      * When set to true, {@link #titleCollapse} should be true also.
7415      */
7416     hideCollapseTool : false,
7417     /**
7418      * @cfg {Boolean} collapseFirst
7419      * True to make sure the collapse/expand toggle button always renders first (to the left of) any other tools
7420      * in the contained panels' title bars, false to render it last (defaults to false).
7421      */
7422     collapseFirst : false,
7423     /**
7424      * @cfg {Boolean} animate
7425      * True to slide the contained panels open and closed during expand/collapse using animation, false to open and
7426      * close directly with no animation (defaults to false).  Note: to defer to the specific config setting of each
7427      * contained panel for this property, set this to undefined at the layout level.
7428      */
7429     animate : false,
7430     /**
7431      * @cfg {Boolean} sequence
7432      * <b>Experimental</b>. If animate is set to true, this will result in each animation running in sequence.
7433      */
7434     sequence : false,
7435     /**
7436      * @cfg {Boolean} activeOnTop
7437      * True to swap the position of each panel as it is expanded so that it becomes the first item in the container,
7438      * false to keep the panels in the rendered order. <b>This is NOT compatible with "animate:true"</b> (defaults to false).
7439      */
7440     activeOnTop : false,
7441
7442     type: 'accordion',
7443
7444     renderItem : function(c){
7445         if(this.animate === false){
7446             c.animCollapse = false;
7447         }
7448         c.collapsible = true;
7449         if(this.autoWidth){
7450             c.autoWidth = true;
7451         }
7452         if(this.titleCollapse){
7453             c.titleCollapse = true;
7454         }
7455         if(this.hideCollapseTool){
7456             c.hideCollapseTool = true;
7457         }
7458         if(this.collapseFirst !== undefined){
7459             c.collapseFirst = this.collapseFirst;
7460         }
7461         if(!this.activeItem && !c.collapsed){
7462             this.setActiveItem(c, true);
7463         }else if(this.activeItem && this.activeItem != c){
7464             c.collapsed = true;
7465         }
7466         Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
7467         c.header.addClass('x-accordion-hd');
7468         c.on('beforeexpand', this.beforeExpand, this);
7469     },
7470
7471     onRemove: function(c){
7472         Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
7473         if(c.rendered){
7474             c.header.removeClass('x-accordion-hd');
7475         }
7476         c.un('beforeexpand', this.beforeExpand, this);
7477     },
7478
7479     // private
7480     beforeExpand : function(p, anim){
7481         var ai = this.activeItem;
7482         if(ai){
7483             if(this.sequence){
7484                 delete this.activeItem;
7485                 if (!ai.collapsed){
7486                     ai.collapse({callback:function(){
7487                         p.expand(anim || true);
7488                     }, scope: this});
7489                     return false;
7490                 }
7491             }else{
7492                 ai.collapse(this.animate);
7493             }
7494         }
7495         this.setActive(p);
7496         if(this.activeOnTop){
7497             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
7498         }
7499         // Items have been hidden an possibly rearranged, we need to get the container size again.
7500         this.layout();
7501     },
7502
7503     // private
7504     setItemSize : function(item, size){
7505         if(this.fill && item){
7506             var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;
7507             // Add up all the header heights
7508             for (i = 0; i < len; i++) {
7509                 if((p = ct[i]) != item && !p.hidden){
7510                     hh += p.header.getHeight();
7511                 }
7512             };
7513             // Subtract the header heights from the container size
7514             size.height -= hh;
7515             // Call setSize on the container to set the correct height.  For Panels, deferedHeight
7516             // will simply store this size for when the expansion is done.
7517             item.setSize(size);
7518         }
7519     },
7520
7521     /**
7522      * Sets the active (expanded) item in the layout.
7523      * @param {String/Number} item The string component id or numeric index of the item to activate
7524      */
7525     setActiveItem : function(item){
7526         this.setActive(item, true);
7527     },
7528
7529     // private
7530     setActive : function(item, expand){
7531         var ai = this.activeItem;
7532         item = this.container.getComponent(item);
7533         if(ai != item){
7534             if(item.rendered && item.collapsed && expand){
7535                 item.expand();
7536             }else{
7537                 if(ai){
7538                    ai.fireEvent('deactivate', ai);
7539                 }
7540                 this.activeItem = item;
7541                 item.fireEvent('activate', item);
7542             }
7543         }
7544     }
7545 });
7546 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
7547
7548 //backwards compat
7549 Ext.layout.Accordion = Ext.layout.AccordionLayout;/**
7550  * @class Ext.layout.TableLayout
7551  * @extends Ext.layout.ContainerLayout
7552  * <p>This layout allows you to easily render content into an HTML table.  The total number of columns can be
7553  * specified, and rowspan and colspan can be used to create complex layouts within the table.
7554  * This class is intended to be extended or created via the layout:'table' {@link Ext.Container#layout} config,
7555  * and should generally not need to be created directly via the new keyword.</p>
7556  * <p>Note that when creating a layout via config, the layout-specific config properties must be passed in via
7557  * the {@link Ext.Container#layoutConfig} object which will then be applied internally to the layout.  In the
7558  * case of TableLayout, the only valid layout config property is {@link #columns}.  However, the items added to a
7559  * TableLayout can supply the following table-specific config properties:</p>
7560  * <ul>
7561  * <li><b>rowspan</b> Applied to the table cell containing the item.</li>
7562  * <li><b>colspan</b> Applied to the table cell containing the item.</li>
7563  * <li><b>cellId</b> An id applied to the table cell containing the item.</li>
7564  * <li><b>cellCls</b> A CSS class name added to the table cell containing the item.</li>
7565  * </ul>
7566  * <p>The basic concept of building up a TableLayout is conceptually very similar to building up a standard
7567  * HTML table.  You simply add each panel (or "cell") that you want to include along with any span attributes
7568  * specified as the special config properties of rowspan and colspan which work exactly like their HTML counterparts.
7569  * Rather than explicitly creating and nesting rows and columns as you would in HTML, you simply specify the
7570  * total column count in the layoutConfig and start adding panels in their natural order from left to right,
7571  * top to bottom.  The layout will automatically figure out, based on the column count, rowspans and colspans,
7572  * how to position each panel within the table.  Just like with HTML tables, your rowspans and colspans must add
7573  * up correctly in your overall layout or you'll end up with missing and/or extra cells!  Example usage:</p>
7574  * <pre><code>
7575 // This code will generate a layout table that is 3 columns by 2 rows
7576 // with some spanning included.  The basic layout will be:
7577 // +--------+-----------------+
7578 // |   A    |   B             |
7579 // |        |--------+--------|
7580 // |        |   C    |   D    |
7581 // +--------+--------+--------+
7582 var table = new Ext.Panel({
7583     title: 'Table Layout',
7584     layout:'table',
7585     defaults: {
7586         // applied to each contained panel
7587         bodyStyle:'padding:20px'
7588     },
7589     layoutConfig: {
7590         // The total column count must be specified here
7591         columns: 3
7592     },
7593     items: [{
7594         html: '&lt;p&gt;Cell A content&lt;/p&gt;',
7595         rowspan: 2
7596     },{
7597         html: '&lt;p&gt;Cell B content&lt;/p&gt;',
7598         colspan: 2
7599     },{
7600         html: '&lt;p&gt;Cell C content&lt;/p&gt;',
7601         cellCls: 'highlight'
7602     },{
7603         html: '&lt;p&gt;Cell D content&lt;/p&gt;'
7604     }]
7605 });
7606 </code></pre>
7607  */
7608 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
7609     /**
7610      * @cfg {Number} columns
7611      * The total number of columns to create in the table for this layout.  If not specified, all Components added to
7612      * this layout will be rendered into a single row using one column per Component.
7613      */
7614
7615     // private
7616     monitorResize:false,
7617
7618     type: 'table',
7619
7620     targetCls: 'x-table-layout-ct',
7621
7622     /**
7623      * @cfg {Object} tableAttrs
7624      * <p>An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification
7625      * used to create the layout's <tt>&lt;table&gt;</tt> element. Example:</p><pre><code>
7626 {
7627     xtype: 'panel',
7628     layout: 'table',
7629     layoutConfig: {
7630         tableAttrs: {
7631             style: {
7632                 width: '100%'
7633             }
7634         },
7635         columns: 3
7636     }
7637 }</code></pre>
7638      */
7639     tableAttrs:null,
7640
7641     // private
7642     setContainer : function(ct){
7643         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
7644
7645         this.currentRow = 0;
7646         this.currentColumn = 0;
7647         this.cells = [];
7648     },
7649     
7650     // private
7651     onLayout : function(ct, target){
7652         var cs = ct.items.items, len = cs.length, c, i;
7653
7654         if(!this.table){
7655             target.addClass('x-table-layout-ct');
7656
7657             this.table = target.createChild(
7658                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
7659         }
7660         this.renderAll(ct, target);
7661     },
7662
7663     // private
7664     getRow : function(index){
7665         var row = this.table.tBodies[0].childNodes[index];
7666         if(!row){
7667             row = document.createElement('tr');
7668             this.table.tBodies[0].appendChild(row);
7669         }
7670         return row;
7671     },
7672
7673     // private
7674     getNextCell : function(c){
7675         var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
7676         var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
7677         for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
7678             if(!this.cells[rowIndex]){
7679                 this.cells[rowIndex] = [];
7680             }
7681             for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
7682                 this.cells[rowIndex][colIndex] = true;
7683             }
7684         }
7685         var td = document.createElement('td');
7686         if(c.cellId){
7687             td.id = c.cellId;
7688         }
7689         var cls = 'x-table-layout-cell';
7690         if(c.cellCls){
7691             cls += ' ' + c.cellCls;
7692         }
7693         td.className = cls;
7694         if(c.colspan){
7695             td.colSpan = c.colspan;
7696         }
7697         if(c.rowspan){
7698             td.rowSpan = c.rowspan;
7699         }
7700         this.getRow(curRow).appendChild(td);
7701         return td;
7702     },
7703
7704     // private
7705     getNextNonSpan: function(colIndex, rowIndex){
7706         var cols = this.columns;
7707         while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
7708             if(cols && colIndex >= cols){
7709                 rowIndex++;
7710                 colIndex = 0;
7711             }else{
7712                 colIndex++;
7713             }
7714         }
7715         return [colIndex, rowIndex];
7716     },
7717
7718     // private
7719     renderItem : function(c, position, target){
7720         // Ensure we have our inner table to get cells to render into.
7721         if(!this.table){
7722             this.table = target.createChild(
7723                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
7724         }
7725         if(c && !c.rendered){
7726             c.render(this.getNextCell(c));
7727             this.configureItem(c);
7728         }else if(c && !this.isValidParent(c, target)){
7729             var container = this.getNextCell(c);
7730             container.insertBefore(c.getPositionEl().dom, null);
7731             c.container = Ext.get(container);
7732             this.configureItem(c);
7733         }
7734     },
7735
7736     // private
7737     isValidParent : function(c, target){
7738         return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);
7739     },
7740     
7741     destroy: function(){
7742         delete this.table;
7743         Ext.layout.TableLayout.superclass.destroy.call(this);
7744     }
7745
7746     /**
7747      * @property activeItem
7748      * @hide
7749      */
7750 });
7751
7752 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;/**
7753  * @class Ext.layout.AbsoluteLayout
7754  * @extends Ext.layout.AnchorLayout
7755  * <p>This is a layout that inherits the anchoring of <b>{@link Ext.layout.AnchorLayout}</b> and adds the
7756  * ability for x/y positioning using the standard x and y component config options.</p>
7757  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
7758  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
7759  * <p>Example usage:</p>
7760  * <pre><code>
7761 var form = new Ext.form.FormPanel({
7762     title: 'Absolute Layout',
7763     layout:'absolute',
7764     layoutConfig: {
7765         // layout-specific configs go here
7766         extraCls: 'x-abs-layout-item',
7767     },
7768     baseCls: 'x-plain',
7769     url:'save-form.php',
7770     defaultType: 'textfield',
7771     items: [{
7772         x: 0,
7773         y: 5,
7774         xtype:'label',
7775         text: 'Send To:'
7776     },{
7777         x: 60,
7778         y: 0,
7779         name: 'to',
7780         anchor:'100%'  // anchor width by percentage
7781     },{
7782         x: 0,
7783         y: 35,
7784         xtype:'label',
7785         text: 'Subject:'
7786     },{
7787         x: 60,
7788         y: 30,
7789         name: 'subject',
7790         anchor: '100%'  // anchor width by percentage
7791     },{
7792         x:0,
7793         y: 60,
7794         xtype: 'textarea',
7795         name: 'msg',
7796         anchor: '100% 100%'  // anchor width and height
7797     }]
7798 });
7799 </code></pre>
7800  */
7801 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
7802
7803     extraCls: 'x-abs-layout-item',
7804
7805     type: 'absolute',
7806
7807     onLayout : function(ct, target){
7808         target.position();
7809         this.paddingLeft = target.getPadding('l');
7810         this.paddingTop = target.getPadding('t');
7811         Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
7812     },
7813
7814     // private
7815     adjustWidthAnchor : function(value, comp){
7816         return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
7817     },
7818
7819     // private
7820     adjustHeightAnchor : function(value, comp){
7821         return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
7822     }
7823     /**
7824      * @property activeItem
7825      * @hide
7826      */
7827 });
7828 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
7829 /**
7830  * @class Ext.layout.BoxLayout
7831  * @extends Ext.layout.ContainerLayout
7832  * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
7833  */
7834 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
7835     /**
7836      * @cfg {Object} defaultMargins
7837      * <p>If the individual contained items do not have a <tt>margins</tt>
7838      * property specified, the default margins from this property will be
7839      * applied to each item.</p>
7840      * <br><p>This property may be specified as an object containing margins
7841      * to apply in the format:</p><pre><code>
7842 {
7843     top: (top margin),
7844     right: (right margin),
7845     bottom: (bottom margin),
7846     left: (left margin)
7847 }</code></pre>
7848      * <p>This property may also be specified as a string containing
7849      * space-separated, numeric margin values. The order of the sides associated
7850      * with each value matches the way CSS processes margin values:</p>
7851      * <div class="mdetail-params"><ul>
7852      * <li>If there is only one value, it applies to all sides.</li>
7853      * <li>If there are two values, the top and bottom borders are set to the
7854      * first value and the right and left are set to the second.</li>
7855      * <li>If there are three values, the top is set to the first value, the left
7856      * and right are set to the second, and the bottom is set to the third.</li>
7857      * <li>If there are four values, they apply to the top, right, bottom, and
7858      * left, respectively.</li>
7859      * </ul></div>
7860      * <p>Defaults to:</p><pre><code>
7861      * {top:0, right:0, bottom:0, left:0}
7862      * </code></pre>
7863      */
7864     defaultMargins : {left:0,top:0,right:0,bottom:0},
7865     /**
7866      * @cfg {String} padding
7867      * <p>Sets the padding to be applied to all child items managed by this layout.</p>
7868      * <p>This property must be specified as a string containing
7869      * space-separated, numeric padding values. The order of the sides associated
7870      * with each value matches the way CSS processes padding values:</p>
7871      * <div class="mdetail-params"><ul>
7872      * <li>If there is only one value, it applies to all sides.</li>
7873      * <li>If there are two values, the top and bottom borders are set to the
7874      * first value and the right and left are set to the second.</li>
7875      * <li>If there are three values, the top is set to the first value, the left
7876      * and right are set to the second, and the bottom is set to the third.</li>
7877      * <li>If there are four values, they apply to the top, right, bottom, and
7878      * left, respectively.</li>
7879      * </ul></div>
7880      * <p>Defaults to: <code>"0"</code></p>
7881      */
7882     padding : '0',
7883     // documented in subclasses
7884     pack : 'start',
7885
7886     // private
7887     monitorResize : true,
7888     type: 'box',
7889     scrollOffset : 0,
7890     extraCls : 'x-box-item',
7891     targetCls : 'x-box-layout-ct',
7892     innerCls : 'x-box-inner',
7893
7894     constructor : function(config){
7895         Ext.layout.BoxLayout.superclass.constructor.call(this, config);
7896
7897         if (Ext.isString(this.defaultMargins)) {
7898             this.defaultMargins = this.parseMargins(this.defaultMargins);
7899         }
7900         
7901         var handler = this.overflowHandler;
7902         
7903         if (typeof handler == 'string') {
7904             handler = {
7905                 type: handler
7906             };
7907         }
7908         
7909         var handlerType = 'none';
7910         if (handler && handler.type != undefined) {
7911             handlerType = handler.type;
7912         }
7913         
7914         var constructor = Ext.layout.boxOverflow[handlerType];
7915         if (constructor[this.type]) {
7916             constructor = constructor[this.type];
7917         }
7918         
7919         this.overflowHandler = new constructor(this, handler);
7920     },
7921
7922     /**
7923      * @private
7924      * Runs the child box calculations and caches them in childBoxCache. Subclasses can used these cached values
7925      * when laying out
7926      */
7927     onLayout: function(container, target) {
7928         Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);
7929
7930         var tSize = this.getLayoutTargetSize(),
7931             items = this.getVisibleItems(container),
7932             calcs = this.calculateChildBoxes(items, tSize),
7933             boxes = calcs.boxes,
7934             meta  = calcs.meta;
7935         
7936         //invoke the overflow handler, if one is configured
7937         if (tSize.width > 0) {
7938             var handler = this.overflowHandler,
7939                 method  = meta.tooNarrow ? 'handleOverflow' : 'clearOverflow';
7940             
7941             var results = handler[method](calcs, tSize);
7942             
7943             if (results) {
7944                 if (results.targetSize) {
7945                     tSize = results.targetSize;
7946                 }
7947                 
7948                 if (results.recalculate) {
7949                     items = this.getVisibleItems(container);
7950                     calcs = this.calculateChildBoxes(items, tSize);
7951                     boxes = calcs.boxes;
7952                 }
7953             }
7954         }
7955         
7956         /**
7957          * @private
7958          * @property layoutTargetLastSize
7959          * @type Object
7960          * Private cache of the last measured size of the layout target. This should never be used except by
7961          * BoxLayout subclasses during their onLayout run.
7962          */
7963         this.layoutTargetLastSize = tSize;
7964         
7965         /**
7966          * @private
7967          * @property childBoxCache
7968          * @type Array
7969          * Array of the last calculated height, width, top and left positions of each visible rendered component
7970          * within the Box layout.
7971          */
7972         this.childBoxCache = calcs;
7973         
7974         this.updateInnerCtSize(tSize, calcs);
7975         this.updateChildBoxes(boxes);
7976
7977         // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
7978         this.handleTargetOverflow(tSize, container, target);
7979     },
7980
7981     /**
7982      * Resizes and repositions each child component
7983      * @param {Array} boxes The box measurements
7984      */
7985     updateChildBoxes: function(boxes) {
7986         for (var i = 0, length = boxes.length; i < length; i++) {
7987             var box  = boxes[i],
7988                 comp = box.component;
7989             
7990             if (box.dirtySize) {
7991                 comp.setSize(box.width, box.height);
7992             }
7993             // Don't set positions to NaN
7994             if (isNaN(box.left) || isNaN(box.top)) {
7995                 continue;
7996             }
7997             
7998             comp.setPosition(box.left, box.top);
7999         }
8000     },
8001
8002     /**
8003      * @private
8004      * Called by onRender just before the child components are sized and positioned. This resizes the innerCt
8005      * to make sure all child items fit within it. We call this before sizing the children because if our child
8006      * items are larger than the previous innerCt size the browser will insert scrollbars and then remove them
8007      * again immediately afterwards, giving a performance hit.
8008      * Subclasses should provide an implementation.
8009      * @param {Object} currentSize The current height and width of the innerCt
8010      * @param {Array} calculations The new box calculations of all items to be laid out
8011      */
8012     updateInnerCtSize: function(tSize, calcs) {
8013         var align   = this.align,
8014             padding = this.padding,
8015             width   = tSize.width,
8016             height  = tSize.height;
8017         
8018         if (this.type == 'hbox') {
8019             var innerCtWidth  = width,
8020                 innerCtHeight = calcs.meta.maxHeight + padding.top + padding.bottom;
8021
8022             if (align == 'stretch') {
8023                 innerCtHeight = height;
8024             } else if (align == 'middle') {
8025                 innerCtHeight = Math.max(height, innerCtHeight);
8026             }
8027         } else {
8028             var innerCtHeight = height,
8029                 innerCtWidth  = calcs.meta.maxWidth + padding.left + padding.right;
8030
8031             if (align == 'stretch') {
8032                 innerCtWidth = width;
8033             } else if (align == 'center') {
8034                 innerCtWidth = Math.max(width, innerCtWidth);
8035             }
8036         }
8037
8038         this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
8039     },
8040
8041     /**
8042      * @private
8043      * This should be called after onLayout of any BoxLayout subclass. If the target's overflow is not set to 'hidden',
8044      * we need to lay out a second time because the scrollbars may have modified the height and width of the layout
8045      * target. Having a Box layout inside such a target is therefore not recommended.
8046      * @param {Object} previousTargetSize The size and height of the layout target before we just laid out
8047      * @param {Ext.Container} container The container
8048      * @param {Ext.Element} target The target element
8049      */
8050     handleTargetOverflow: function(previousTargetSize, container, target) {
8051         var overflow = target.getStyle('overflow');
8052
8053         if (overflow && overflow != 'hidden' &&!this.adjustmentPass) {
8054             var newTargetSize = this.getLayoutTargetSize();
8055             if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){
8056                 this.adjustmentPass = true;
8057                 this.onLayout(container, target);
8058             }
8059         }
8060
8061         delete this.adjustmentPass;
8062     },
8063
8064     // private
8065     isValidParent : function(c, target) {
8066         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
8067     },
8068
8069     /**
8070      * @private
8071      * Returns all items that are both rendered and visible
8072      * @return {Array} All matching items
8073      */
8074     getVisibleItems: function(ct) {
8075         var ct  = ct || this.container,
8076             t   = ct.getLayoutTarget(),
8077             cti = ct.items.items,
8078             len = cti.length,
8079
8080             i, c, items = [];
8081
8082         for (i = 0; i < len; i++) {
8083             if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true  && c.collapsed !== true && c.shouldLayout !== false){
8084                 items.push(c);
8085             }
8086         }
8087
8088         return items;
8089     },
8090
8091     // private
8092     renderAll : function(ct, target) {
8093         if (!this.innerCt) {
8094             // the innerCt prevents wrapping and shuffling while the container is resizing
8095             this.innerCt = target.createChild({cls:this.innerCls});
8096             this.padding = this.parseMargins(this.padding);
8097         }
8098         Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
8099     },
8100
8101     getLayoutTargetSize : function() {
8102         var target = this.container.getLayoutTarget(), ret;
8103         
8104         if (target) {
8105             ret = target.getViewSize();
8106
8107             // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
8108             // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
8109             // with getViewSize
8110             if (Ext.isIE && Ext.isStrict && ret.width == 0){
8111                 ret =  target.getStyleSize();
8112             }
8113
8114             ret.width  -= target.getPadding('lr');
8115             ret.height -= target.getPadding('tb');
8116         }
8117         
8118         return ret;
8119     },
8120
8121     // private
8122     renderItem : function(c) {
8123         if(Ext.isString(c.margins)){
8124             c.margins = this.parseMargins(c.margins);
8125         }else if(!c.margins){
8126             c.margins = this.defaultMargins;
8127         }
8128         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
8129     },
8130     
8131     /**
8132      * @private
8133      */
8134     destroy: function() {
8135         Ext.destroy(this.overflowHandler);
8136         
8137         Ext.layout.BoxLayout.superclass.destroy.apply(this, arguments);
8138     }
8139 });
8140
8141
8142
8143 Ext.ns('Ext.layout.boxOverflow');
8144
8145 /**
8146  * @class Ext.layout.boxOverflow.None
8147  * @extends Object
8148  * Base class for Box Layout overflow handlers. These specialized classes are invoked when a Box Layout
8149  * (either an HBox or a VBox) has child items that are either too wide (for HBox) or too tall (for VBox)
8150  * for its container.
8151  */
8152
8153 Ext.layout.boxOverflow.None = Ext.extend(Object, {
8154     constructor: function(layout, config) {
8155         this.layout = layout;
8156         
8157         Ext.apply(this, config || {});
8158     },
8159     
8160     handleOverflow: Ext.emptyFn,
8161     
8162     clearOverflow: Ext.emptyFn
8163 });
8164
8165
8166 Ext.layout.boxOverflow.none = Ext.layout.boxOverflow.None;
8167 /**
8168  * @class Ext.layout.boxOverflow.Menu
8169  * @extends Ext.layout.boxOverflow.None
8170  * Description
8171  */
8172 Ext.layout.boxOverflow.Menu = Ext.extend(Ext.layout.boxOverflow.None, {
8173     /**
8174      * @cfg afterCls
8175      * @type String
8176      * CSS class added to the afterCt element. This is the element that holds any special items such as scrollers,
8177      * which must always be present at the rightmost edge of the Container
8178      */
8179     afterCls: 'x-strip-right',
8180     
8181     /**
8182      * @property noItemsMenuText
8183      * @type String
8184      * HTML fragment to render into the toolbar overflow menu if there are no items to display
8185      */
8186     noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
8187     
8188     constructor: function(layout) {
8189         Ext.layout.boxOverflow.Menu.superclass.constructor.apply(this, arguments);
8190         
8191         /**
8192          * @property menuItems
8193          * @type Array
8194          * Array of all items that are currently hidden and should go into the dropdown menu
8195          */
8196         this.menuItems = [];
8197     },
8198     
8199     /**
8200      * @private
8201      * Creates the beforeCt, innerCt and afterCt elements if they have not already been created
8202      * @param {Ext.Container} container The Container attached to this Layout instance
8203      * @param {Ext.Element} target The target Element
8204      */
8205     createInnerElements: function() {
8206         if (!this.afterCt) {
8207             this.afterCt  = this.layout.innerCt.insertSibling({cls: this.afterCls},  'before');
8208         }
8209     },
8210     
8211     /**
8212      * @private
8213      */
8214     clearOverflow: function(calculations, targetSize) {
8215         var newWidth = targetSize.width + (this.afterCt ? this.afterCt.getWidth() : 0),
8216             items    = this.menuItems;
8217         
8218         this.hideTrigger();
8219         
8220         for (var index = 0, length = items.length; index < length; index++) {
8221             items.pop().component.show();
8222         }
8223         
8224         return {
8225             targetSize: {
8226                 height: targetSize.height,
8227                 width : newWidth
8228             }
8229         };
8230     },
8231     
8232     /**
8233      * @private
8234      */
8235     showTrigger: function() {
8236         this.createMenu();
8237         this.menuTrigger.show();
8238     },
8239     
8240     /**
8241      * @private
8242      */
8243     hideTrigger: function() {
8244         if (this.menuTrigger != undefined) {
8245             this.menuTrigger.hide();
8246         }
8247     },
8248     
8249     /**
8250      * @private
8251      * Called before the overflow menu is shown. This constructs the menu's items, caching them for as long as it can.
8252      */
8253     beforeMenuShow: function(menu) {
8254         var items = this.menuItems,
8255             len   = items.length,
8256             item,
8257             prev;
8258
8259         var needsSep = function(group, item){
8260             return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
8261         };
8262         
8263         this.clearMenu();
8264         menu.removeAll();
8265         
8266         for (var i = 0; i < len; i++) {
8267             item = items[i].component;
8268             
8269             if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
8270                 menu.add('-');
8271             }
8272             
8273             this.addComponentToMenu(menu, item);
8274             prev = item;
8275         }
8276
8277         // put something so the menu isn't empty if no compatible items found
8278         if (menu.items.length < 1) {
8279             menu.add(this.noItemsMenuText);
8280         }
8281     },
8282     
8283     /**
8284      * @private
8285      * Returns a menu config for a given component. This config is used to create a menu item
8286      * to be added to the expander menu
8287      * @param {Ext.Component} component The component to create the config for
8288      * @param {Boolean} hideOnClick Passed through to the menu item
8289      */
8290     createMenuConfig : function(component, hideOnClick){
8291         var config = Ext.apply({}, component.initialConfig),
8292             group  = component.toggleGroup;
8293
8294         Ext.copyTo(config, component, [
8295             'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
8296         ]);
8297
8298         Ext.apply(config, {
8299             text       : component.overflowText || component.text,
8300             hideOnClick: hideOnClick
8301         });
8302
8303         if (group || component.enableToggle) {
8304             Ext.apply(config, {
8305                 group  : group,
8306                 checked: component.pressed,
8307                 listeners: {
8308                     checkchange: function(item, checked){
8309                         component.toggle(checked);
8310                     }
8311                 }
8312             });
8313         }
8314
8315         delete config.ownerCt;
8316         delete config.xtype;
8317         delete config.id;
8318
8319         return config;
8320     },
8321
8322     /**
8323      * @private
8324      * Adds the given Toolbar item to the given menu. Buttons inside a buttongroup are added individually.
8325      * @param {Ext.menu.Menu} menu The menu to add to
8326      * @param {Ext.Component} component The component to add
8327      */
8328     addComponentToMenu : function(menu, component) {
8329         if (component instanceof Ext.Toolbar.Separator) {
8330             menu.add('-');
8331
8332         } else if (Ext.isFunction(component.isXType)) {
8333             if (component.isXType('splitbutton')) {
8334                 menu.add(this.createMenuConfig(component, true));
8335
8336             } else if (component.isXType('button')) {
8337                 menu.add(this.createMenuConfig(component, !component.menu));
8338
8339             } else if (component.isXType('buttongroup')) {
8340                 component.items.each(function(item){
8341                      this.addComponentToMenu(menu, item);
8342                 }, this);
8343             }
8344         }
8345     },
8346     
8347     /**
8348      * @private
8349      * Deletes the sub-menu of each item in the expander menu. Submenus are created for items such as
8350      * splitbuttons and buttongroups, where the Toolbar item cannot be represented by a single menu item
8351      */
8352     clearMenu : function(){
8353         var menu = this.moreMenu;
8354         if (menu && menu.items) {
8355             menu.items.each(function(item){
8356                 delete item.menu;
8357             });
8358         }
8359     },
8360     
8361     /**
8362      * @private
8363      * Creates the overflow trigger and menu used when enableOverflow is set to true and the items
8364      * in the layout are too wide to fit in the space available
8365      */
8366     createMenu: function() {
8367         if (!this.menuTrigger) {
8368             this.createInnerElements();
8369             
8370             /**
8371              * @private
8372              * @property menu
8373              * @type Ext.menu.Menu
8374              * The expand menu - holds items for every item that cannot be shown
8375              * because the container is currently not large enough.
8376              */
8377             this.menu = new Ext.menu.Menu({
8378                 ownerCt : this.layout.container,
8379                 listeners: {
8380                     scope: this,
8381                     beforeshow: this.beforeMenuShow
8382                 }
8383             });
8384
8385             /**
8386              * @private
8387              * @property menuTrigger
8388              * @type Ext.Button
8389              * The expand button which triggers the overflow menu to be shown
8390              */
8391             this.menuTrigger = new Ext.Button({
8392                 iconCls : 'x-toolbar-more-icon',
8393                 cls     : 'x-toolbar-more',
8394                 menu    : this.menu,
8395                 renderTo: this.afterCt
8396             });
8397         }
8398     },
8399     
8400     /**
8401      * @private
8402      */
8403     destroy: function() {
8404         Ext.destroy(this.menu, this.menuTrigger);
8405     }
8406 });
8407
8408 Ext.layout.boxOverflow.menu = Ext.layout.boxOverflow.Menu;
8409
8410
8411 /**
8412  * @class Ext.layout.boxOverflow.HorizontalMenu
8413  * @extends Ext.layout.boxOverflow.Menu
8414  * Description
8415  */
8416 Ext.layout.boxOverflow.HorizontalMenu = Ext.extend(Ext.layout.boxOverflow.Menu, {
8417     
8418     constructor: function() {
8419         Ext.layout.boxOverflow.HorizontalMenu.superclass.constructor.apply(this, arguments);
8420         
8421         var me = this,
8422             layout = me.layout,
8423             origFunction = layout.calculateChildBoxes;
8424         
8425         layout.calculateChildBoxes = function(visibleItems, targetSize) {
8426             var calcs = origFunction.apply(layout, arguments),
8427                 meta  = calcs.meta,
8428                 items = me.menuItems;
8429             
8430             //calculate the width of the items currently hidden solely because there is not enough space
8431             //to display them
8432             var hiddenWidth = 0;
8433             for (var index = 0, length = items.length; index < length; index++) {
8434                 hiddenWidth += items[index].width;
8435             }
8436             
8437             meta.minimumWidth += hiddenWidth;
8438             meta.tooNarrow = meta.minimumWidth > targetSize.width;
8439             
8440             return calcs;
8441         };        
8442     },
8443     
8444     handleOverflow: function(calculations, targetSize) {
8445         this.showTrigger();
8446         
8447         var newWidth    = targetSize.width - this.afterCt.getWidth(),
8448             boxes       = calculations.boxes,
8449             usedWidth   = 0,
8450             recalculate = false;
8451         
8452         //calculate the width of all visible items and any spare width
8453         for (var index = 0, length = boxes.length; index < length; index++) {
8454             usedWidth += boxes[index].width;
8455         }
8456         
8457         var spareWidth = newWidth - usedWidth,
8458             showCount  = 0;
8459         
8460         //see if we can re-show any of the hidden components
8461         for (var index = 0, length = this.menuItems.length; index < length; index++) {
8462             var hidden = this.menuItems[index],
8463                 comp   = hidden.component,
8464                 width  = hidden.width;
8465             
8466             if (width < spareWidth) {
8467                 comp.show();
8468                 
8469                 spareWidth -= width;
8470                 showCount ++;
8471                 recalculate = true;
8472             } else {
8473                 break;
8474             }
8475         }
8476                 
8477         if (recalculate) {
8478             this.menuItems = this.menuItems.slice(showCount);
8479         } else {
8480             for (var i = boxes.length - 1; i >= 0; i--) {
8481                 var item  = boxes[i].component,
8482                     right = boxes[i].left + boxes[i].width;
8483
8484                 if (right >= newWidth) {
8485                     this.menuItems.unshift({
8486                         component: item,
8487                         width    : boxes[i].width
8488                     });
8489
8490                     item.hide();
8491                 } else {
8492                     break;
8493                 }
8494             }
8495         }
8496         
8497         if (this.menuItems.length == 0) {
8498             this.hideTrigger();
8499         }
8500         
8501         return {
8502             targetSize: {
8503                 height: targetSize.height,
8504                 width : newWidth
8505             },
8506             recalculate: recalculate
8507         };
8508     }
8509 });
8510
8511 Ext.layout.boxOverflow.menu.hbox = Ext.layout.boxOverflow.HorizontalMenu;/**
8512  * @class Ext.layout.boxOverflow.Scroller
8513  * @extends Ext.layout.boxOverflow.None
8514  * Description
8515  */
8516 Ext.layout.boxOverflow.Scroller = Ext.extend(Ext.layout.boxOverflow.None, {
8517     /**
8518      * @cfg animateScroll
8519      * @type Boolean
8520      * True to animate the scrolling of items within the layout (defaults to true, ignored if enableScroll is false)
8521      */
8522     animateScroll: true,
8523     
8524     /**
8525      * @cfg scrollIncrement
8526      * @type Number
8527      * The number of pixels to scroll by on scroller click (defaults to 100)
8528      */
8529     scrollIncrement: 100,
8530     
8531     /**
8532      * @cfg wheelIncrement
8533      * @type Number
8534      * The number of pixels to increment on mouse wheel scrolling (defaults to <tt>3</tt>).
8535      */
8536     wheelIncrement: 3,
8537     
8538     /**
8539      * @cfg scrollRepeatInterval
8540      * @type Number
8541      * Number of milliseconds between each scroll while a scroller button is held down (defaults to 400)
8542      */
8543     scrollRepeatInterval: 400,
8544     
8545     /**
8546      * @cfg scrollDuration
8547      * @type Number
8548      * Number of seconds that each scroll animation lasts (defaults to 0.4)
8549      */
8550     scrollDuration: 0.4,
8551     
8552     /**
8553      * @cfg beforeCls
8554      * @type String
8555      * CSS class added to the beforeCt element. This is the element that holds any special items such as scrollers,
8556      * which must always be present at the leftmost edge of the Container
8557      */
8558     beforeCls: 'x-strip-left',
8559     
8560     /**
8561      * @cfg afterCls
8562      * @type String
8563      * CSS class added to the afterCt element. This is the element that holds any special items such as scrollers,
8564      * which must always be present at the rightmost edge of the Container
8565      */
8566     afterCls: 'x-strip-right',
8567     
8568     /**
8569      * @cfg scrollerCls
8570      * @type String
8571      * CSS class added to both scroller elements if enableScroll is used
8572      */
8573     scrollerCls: 'x-strip-scroller',
8574     
8575     /**
8576      * @cfg beforeScrollerCls
8577      * @type String
8578      * CSS class added to the left scroller element if enableScroll is used
8579      */
8580     beforeScrollerCls: 'x-strip-scroller-left',
8581     
8582     /**
8583      * @cfg afterScrollerCls
8584      * @type String
8585      * CSS class added to the right scroller element if enableScroll is used
8586      */
8587     afterScrollerCls: 'x-strip-scroller-right',
8588     
8589     /**
8590      * @private
8591      * Sets up an listener to scroll on the layout's innerCt mousewheel event
8592      */
8593     createWheelListener: function() {
8594         this.layout.innerCt.on({
8595             scope     : this,
8596             mousewheel: function(e) {
8597                 e.stopEvent();
8598
8599                 this.scrollBy(e.getWheelDelta() * this.wheelIncrement * -1, false);
8600             }
8601         });
8602     },
8603     
8604     /**
8605      * @private
8606      * Most of the heavy lifting is done in the subclasses
8607      */
8608     handleOverflow: function(calculations, targetSize) {
8609         this.createInnerElements();
8610         this.showScrollers();
8611     },
8612     
8613     /**
8614      * @private
8615      */
8616     clearOverflow: function() {
8617         this.hideScrollers();
8618     },
8619     
8620     /**
8621      * @private
8622      * Shows the scroller elements in the beforeCt and afterCt. Creates the scrollers first if they are not already
8623      * present. 
8624      */
8625     showScrollers: function() {
8626         this.createScrollers();
8627         
8628         this.beforeScroller.show();
8629         this.afterScroller.show();
8630         
8631         this.updateScrollButtons();
8632     },
8633     
8634     /**
8635      * @private
8636      * Hides the scroller elements in the beforeCt and afterCt
8637      */
8638     hideScrollers: function() {
8639         if (this.beforeScroller != undefined) {
8640             this.beforeScroller.hide();
8641             this.afterScroller.hide();          
8642         }
8643     },
8644     
8645     /**
8646      * @private
8647      * Creates the clickable scroller elements and places them into the beforeCt and afterCt
8648      */
8649     createScrollers: function() {
8650         if (!this.beforeScroller && !this.afterScroller) {
8651             var before = this.beforeCt.createChild({
8652                 cls: String.format("{0} {1} ", this.scrollerCls, this.beforeScrollerCls)
8653             });
8654             
8655             var after = this.afterCt.createChild({
8656                 cls: String.format("{0} {1}", this.scrollerCls, this.afterScrollerCls)
8657             });
8658             
8659             before.addClassOnOver(this.beforeScrollerCls + '-hover');
8660             after.addClassOnOver(this.afterScrollerCls + '-hover');
8661             
8662             before.setVisibilityMode(Ext.Element.DISPLAY);
8663             after.setVisibilityMode(Ext.Element.DISPLAY);
8664             
8665             this.beforeRepeater = new Ext.util.ClickRepeater(before, {
8666                 interval: this.scrollRepeatInterval,
8667                 handler : this.scrollLeft,
8668                 scope   : this
8669             });
8670             
8671             this.afterRepeater = new Ext.util.ClickRepeater(after, {
8672                 interval: this.scrollRepeatInterval,
8673                 handler : this.scrollRight,
8674                 scope   : this
8675             });
8676             
8677             /**
8678              * @property beforeScroller
8679              * @type Ext.Element
8680              * The left scroller element. Only created when needed.
8681              */
8682             this.beforeScroller = before;
8683             
8684             /**
8685              * @property afterScroller
8686              * @type Ext.Element
8687              * The left scroller element. Only created when needed.
8688              */
8689             this.afterScroller = after;
8690         }
8691     },
8692     
8693     /**
8694      * @private
8695      */
8696     destroy: function() {
8697         Ext.destroy(this.beforeScroller, this.afterScroller, this.beforeRepeater, this.afterRepeater, this.beforeCt, this.afterCt);
8698     },
8699     
8700     /**
8701      * @private
8702      * Scrolls left or right by the number of pixels specified
8703      * @param {Number} delta Number of pixels to scroll to the right by. Use a negative number to scroll left
8704      */
8705     scrollBy: function(delta, animate) {
8706         this.scrollTo(this.getScrollPosition() + delta, animate);
8707     },
8708     
8709     /**
8710      * @private
8711      * Normalizes an item reference, string id or numerical index into a reference to the item
8712      * @param {Ext.Component|String|Number} item The item reference, id or index
8713      * @return {Ext.Component} The item
8714      */
8715     getItem: function(item) {
8716         if (Ext.isString(item)) {
8717             item = Ext.getCmp(item);
8718         } else if (Ext.isNumber(item)) {
8719             item = this.items[item];
8720         }
8721         
8722         return item;
8723     },
8724     
8725     /**
8726      * @private
8727      * @return {Object} Object passed to scrollTo when scrolling
8728      */
8729     getScrollAnim: function() {
8730         return {
8731             duration: this.scrollDuration, 
8732             callback: this.updateScrollButtons, 
8733             scope   : this
8734         };
8735     },
8736     
8737     /**
8738      * @private
8739      * Enables or disables each scroller button based on the current scroll position
8740      */
8741     updateScrollButtons: function() {
8742         if (this.beforeScroller == undefined || this.afterScroller == undefined) {
8743             return;
8744         }
8745         
8746         var beforeMeth = this.atExtremeBefore()  ? 'addClass' : 'removeClass',
8747             afterMeth  = this.atExtremeAfter() ? 'addClass' : 'removeClass',
8748             beforeCls  = this.beforeScrollerCls + '-disabled',
8749             afterCls   = this.afterScrollerCls  + '-disabled';
8750         
8751         this.beforeScroller[beforeMeth](beforeCls);
8752         this.afterScroller[afterMeth](afterCls);
8753         this.scrolling = false;
8754     },
8755     
8756     /**
8757      * @private
8758      * Returns true if the innerCt scroll is already at its left-most point
8759      * @return {Boolean} True if already at furthest left point
8760      */
8761     atExtremeBefore: function() {
8762         return this.getScrollPosition() === 0;
8763     },
8764     
8765     /**
8766      * @private
8767      * Scrolls to the left by the configured amount
8768      */
8769     scrollLeft: function(animate) {
8770         this.scrollBy(-this.scrollIncrement, animate);
8771     },
8772     
8773     /**
8774      * @private
8775      * Scrolls to the right by the configured amount
8776      */
8777     scrollRight: function(animate) {
8778         this.scrollBy(this.scrollIncrement, animate);
8779     },
8780     
8781     /**
8782      * Scrolls to the given component.
8783      * @param {String|Number|Ext.Component} item The item to scroll to. Can be a numerical index, component id 
8784      * or a reference to the component itself.
8785      * @param {Boolean} animate True to animate the scrolling
8786      */
8787     scrollToItem: function(item, animate) {
8788         item = this.getItem(item);
8789         
8790         if (item != undefined) {
8791             var visibility = this.getItemVisibility(item);
8792             
8793             if (!visibility.fullyVisible) {
8794                 var box  = item.getBox(true, true),
8795                     newX = box.x;
8796                     
8797                 if (visibility.hiddenRight) {
8798                     newX -= (this.layout.innerCt.getWidth() - box.width);
8799                 }
8800                 
8801                 this.scrollTo(newX, animate);
8802             }
8803         }
8804     },
8805     
8806     /**
8807      * @private
8808      * For a given item in the container, return an object with information on whether the item is visible
8809      * with the current innerCt scroll value.
8810      * @param {Ext.Component} item The item
8811      * @return {Object} Values for fullyVisible, hiddenLeft and hiddenRight
8812      */
8813     getItemVisibility: function(item) {
8814         var box         = this.getItem(item).getBox(true, true),
8815             itemLeft    = box.x,
8816             itemRight   = box.x + box.width,
8817             scrollLeft  = this.getScrollPosition(),
8818             scrollRight = this.layout.innerCt.getWidth() + scrollLeft;
8819         
8820         return {
8821             hiddenLeft  : itemLeft < scrollLeft,
8822             hiddenRight : itemRight > scrollRight,
8823             fullyVisible: itemLeft > scrollLeft && itemRight < scrollRight
8824         };
8825     }
8826 });
8827
8828 Ext.layout.boxOverflow.scroller = Ext.layout.boxOverflow.Scroller;
8829
8830
8831 /**\r
8832  * @class Ext.layout.boxOverflow.VerticalScroller\r
8833  * @extends Ext.layout.boxOverflow.Scroller\r
8834  * Description\r
8835  */\r
8836 Ext.layout.boxOverflow.VerticalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
8837     scrollIncrement: 75,
8838     wheelIncrement : 2,
8839     
8840     handleOverflow: function(calculations, targetSize) {
8841         Ext.layout.boxOverflow.VerticalScroller.superclass.handleOverflow.apply(this, arguments);
8842         
8843         return {
8844             targetSize: {
8845                 height: targetSize.height - (this.beforeCt.getHeight() + this.afterCt.getHeight()),
8846                 width : targetSize.width
8847             }
8848         };
8849     },
8850     
8851     /**
8852      * @private
8853      * Creates the beforeCt and afterCt elements if they have not already been created
8854      */
8855     createInnerElements: function() {
8856         var target = this.layout.innerCt;
8857         
8858         //normal items will be rendered to the innerCt. beforeCt and afterCt allow for fixed positioning of
8859         //special items such as scrollers or dropdown menu triggers
8860         if (!this.beforeCt) {
8861             this.beforeCt = target.insertSibling({cls: this.beforeCls}, 'before');
8862             this.afterCt  = target.insertSibling({cls: this.afterCls},  'after');
8863
8864             this.createWheelListener();
8865         }
8866     },
8867     
8868     /**
8869      * @private
8870      * Scrolls to the given position. Performs bounds checking.
8871      * @param {Number} position The position to scroll to. This is constrained.
8872      * @param {Boolean} animate True to animate. If undefined, falls back to value of this.animateScroll
8873      */
8874     scrollTo: function(position, animate) {
8875         var oldPosition = this.getScrollPosition(),
8876             newPosition = position.constrain(0, this.getMaxScrollBottom());
8877         
8878         if (newPosition != oldPosition && !this.scrolling) {
8879             if (animate == undefined) {
8880                 animate = this.animateScroll;
8881             }
8882             
8883             this.layout.innerCt.scrollTo('top', newPosition, animate ? this.getScrollAnim() : false);
8884             
8885             if (animate) {
8886                 this.scrolling = true;
8887             } else {
8888                 this.scrolling = false;
8889                 this.updateScrollButtons();
8890             }
8891         }
8892     },
8893     
8894     /**
8895      * Returns the current scroll position of the innerCt element
8896      * @return {Number} The current scroll position
8897      */
8898     getScrollPosition: function(){
8899         return parseInt(this.layout.innerCt.dom.scrollTop, 10) || 0;
8900     },
8901     
8902     /**
8903      * @private
8904      * Returns the maximum value we can scrollTo
8905      * @return {Number} The max scroll value
8906      */
8907     getMaxScrollBottom: function() {
8908         return this.layout.innerCt.dom.scrollHeight - this.layout.innerCt.getHeight();
8909     },
8910     
8911     /**
8912      * @private
8913      * Returns true if the innerCt scroll is already at its right-most point
8914      * @return {Boolean} True if already at furthest right point
8915      */
8916     atExtremeAfter: function() {
8917         return this.getScrollPosition() >= this.getMaxScrollBottom();
8918     }
8919 });
8920
8921 Ext.layout.boxOverflow.scroller.vbox = Ext.layout.boxOverflow.VerticalScroller;
8922
8923
8924 /**
8925  * @class Ext.layout.boxOverflow.HorizontalScroller
8926  * @extends Ext.layout.boxOverflow.Scroller
8927  * Description
8928  */
8929 Ext.layout.boxOverflow.HorizontalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, {
8930     handleOverflow: function(calculations, targetSize) {
8931         Ext.layout.boxOverflow.HorizontalScroller.superclass.handleOverflow.apply(this, arguments);
8932         
8933         return {
8934             targetSize: {
8935                 height: targetSize.height,
8936                 width : targetSize.width - (this.beforeCt.getWidth() + this.afterCt.getWidth())
8937             }
8938         };
8939     },
8940     
8941     /**
8942      * @private
8943      * Creates the beforeCt and afterCt elements if they have not already been created
8944      */
8945     createInnerElements: function() {
8946         var target = this.layout.innerCt;
8947         
8948         //normal items will be rendered to the innerCt. beforeCt and afterCt allow for fixed positioning of
8949         //special items such as scrollers or dropdown menu triggers
8950         if (!this.beforeCt) {
8951             this.afterCt  = target.insertSibling({cls: this.afterCls},  'before');
8952             this.beforeCt = target.insertSibling({cls: this.beforeCls}, 'before');
8953             
8954             this.createWheelListener();
8955         }
8956     },
8957     
8958     /**
8959      * @private
8960      * Scrolls to the given position. Performs bounds checking.
8961      * @param {Number} position The position to scroll to. This is constrained.
8962      * @param {Boolean} animate True to animate. If undefined, falls back to value of this.animateScroll
8963      */
8964     scrollTo: function(position, animate) {
8965         var oldPosition = this.getScrollPosition(),
8966             newPosition = position.constrain(0, this.getMaxScrollRight());
8967         
8968         if (newPosition != oldPosition && !this.scrolling) {
8969             if (animate == undefined) {
8970                 animate = this.animateScroll;
8971             }
8972             
8973             this.layout.innerCt.scrollTo('left', newPosition, animate ? this.getScrollAnim() : false);
8974             
8975             if (animate) {
8976                 this.scrolling = true;
8977             } else {
8978                 this.scrolling = false;
8979                 this.updateScrollButtons();
8980             }
8981         }
8982     },
8983     
8984     /**
8985      * Returns the current scroll position of the innerCt element
8986      * @return {Number} The current scroll position
8987      */
8988     getScrollPosition: function(){
8989         return parseInt(this.layout.innerCt.dom.scrollLeft, 10) || 0;
8990     },
8991     
8992     /**
8993      * @private
8994      * Returns the maximum value we can scrollTo
8995      * @return {Number} The max scroll value
8996      */
8997     getMaxScrollRight: function() {
8998         return this.layout.innerCt.dom.scrollWidth - this.layout.innerCt.getWidth();
8999     },
9000     
9001     /**
9002      * @private
9003      * Returns true if the innerCt scroll is already at its right-most point
9004      * @return {Boolean} True if already at furthest right point
9005      */
9006     atExtremeAfter: function() {
9007         return this.getScrollPosition() >= this.getMaxScrollRight();
9008     }
9009 });
9010
9011 Ext.layout.boxOverflow.scroller.hbox = Ext.layout.boxOverflow.HorizontalScroller;/**
9012  * @class Ext.layout.HBoxLayout
9013  * @extends Ext.layout.BoxLayout
9014  * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal
9015  * space between child items containing a numeric <code>flex</code> configuration.</p>
9016  * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option.
9017  */
9018 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
9019     /**
9020      * @cfg {String} align
9021      * Controls how the child items of the container are aligned. Acceptable configuration values for this
9022      * property are:
9023      * <div class="mdetail-params"><ul>
9024      * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically
9025      * at the <b>top</b> of the container</div></li>
9026      * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically in the
9027      * <b>middle</b> of the container</div></li>
9028      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill
9029      * the height of the container</div></li>
9030      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to
9031      * the height of the largest item.</div></li>
9032      */
9033     align: 'top', // top, middle, stretch, strechmax
9034
9035     type : 'hbox',
9036
9037     /**
9038      * @cfg {String} pack
9039      * Controls how the child items of the container are packed together. Acceptable configuration values
9040      * for this property are:
9041      * <div class="mdetail-params"><ul>
9042      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
9043      * <b>left</b> side of container</div></li>
9044      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
9045      * <b>mid-width</b> of container</div></li>
9046      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>
9047      * side of container</div></li>
9048      * </ul></div>
9049      */
9050     /**
9051      * @cfg {Number} flex
9052      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
9053      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>
9054      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
9055      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
9056      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
9057      */
9058
9059     /**
9060      * @private
9061      * Calculates the size and positioning of each item in the HBox. This iterates over all of the rendered,
9062      * visible items and returns a height, width, top and left for each, as well as a reference to each. Also
9063      * returns meta data such as maxHeight which are useful when resizing layout wrappers such as this.innerCt.
9064      * @param {Array} visibleItems The array of all rendered, visible items to be calculated for
9065      * @param {Object} targetSize Object containing target size and height
9066      * @return {Object} Object containing box measurements for each child, plus meta data
9067      */
9068     calculateChildBoxes: function(visibleItems, targetSize) {
9069         var visibleCount = visibleItems.length,
9070
9071             padding      = this.padding,
9072             topOffset    = padding.top,
9073             leftOffset   = padding.left,
9074             paddingVert  = topOffset  + padding.bottom,
9075             paddingHoriz = leftOffset + padding.right,
9076
9077             width        = targetSize.width - this.scrollOffset,
9078             height       = targetSize.height,
9079             availHeight  = Math.max(0, height - paddingVert),
9080
9081             isStart      = this.pack == 'start',
9082             isCenter     = this.pack == 'center',
9083             isEnd        = this.pack == 'end',
9084
9085             nonFlexWidth = 0,
9086             maxHeight    = 0,
9087             totalFlex    = 0,
9088             desiredWidth = 0,
9089             minimumWidth = 0,
9090
9091             //used to cache the calculated size and position values for each child item
9092             boxes        = [],
9093
9094             //used in the for loops below, just declared here for brevity
9095             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, 
9096             horizMargins, vertMargins, stretchHeight;
9097
9098         //gather the total flex of all flexed items and the width taken up by fixed width items
9099         for (i = 0; i < visibleCount; i++) {
9100             child       = visibleItems[i];
9101             childHeight = child.height;
9102             childWidth  = child.width;
9103             canLayout   = !child.hasLayout && typeof child.doLayout == 'function';
9104
9105             // Static width (numeric) requires no calcs
9106             if (typeof childWidth != 'number') {
9107
9108                 // flex and not 'auto' width
9109                 if (child.flex && !childWidth) {
9110                     totalFlex += child.flex;
9111
9112                 // Not flexed or 'auto' width or undefined width
9113                 } else {
9114                     //Render and layout sub-containers without a flex or width defined, as otherwise we
9115                     //don't know how wide the sub-container should be and cannot calculate flexed widths
9116                     if (!childWidth && canLayout) {
9117                         child.doLayout();
9118                     }
9119
9120                     childSize   = child.getSize();
9121                     childWidth  = childSize.width;
9122                     childHeight = childSize.height;
9123                 }
9124             }
9125
9126             childMargins = child.margins;
9127             horizMargins = childMargins.left + childMargins.right;
9128
9129             nonFlexWidth += horizMargins + (childWidth || 0);
9130             desiredWidth += horizMargins + (child.flex ? child.minWidth || 0 : childWidth);
9131             minimumWidth += horizMargins + (child.minWidth || childWidth || 0);
9132
9133             // Max height for align - force layout of non-laid out subcontainers without a numeric height
9134             if (typeof childHeight != 'number') {
9135                 if (canLayout) {
9136                     child.doLayout();
9137                 }
9138                 childHeight = child.getHeight();
9139             }
9140
9141             maxHeight = Math.max(maxHeight, childHeight + childMargins.top + childMargins.bottom);
9142
9143             //cache the size of each child component. Don't set height or width to 0, keep undefined instead
9144             boxes.push({
9145                 component: child,
9146                 height   : childHeight || undefined,
9147                 width    : childWidth  || undefined
9148             });
9149         }
9150                 
9151         var shortfall = desiredWidth - width,
9152             tooNarrow = minimumWidth > width;
9153             
9154         //the width available to the flexed items
9155         var availableWidth = Math.max(0, width - nonFlexWidth - paddingHoriz);
9156         
9157         if (tooNarrow) {
9158             for (i = 0; i < visibleCount; i++) {
9159                 boxes[i].width = visibleItems[i].minWidth || visibleItems[i].width || boxes[i].width;
9160             }
9161         } else {
9162             //all flexed items should be sized to their minimum width, other items should be shrunk down until
9163             //the shortfall has been accounted for
9164             if (shortfall > 0) {
9165                 var minWidths = [];
9166                 
9167                 /**
9168                  * When we have a shortfall but are not tooNarrow, we need to shrink the width of each non-flexed item.
9169                  * Flexed items are immediately reduced to their minWidth and anything already at minWidth is ignored.
9170                  * The remaining items are collected into the minWidths array, which is later used to distribute the shortfall.
9171                  */
9172                 for (var index = 0, length = visibleCount; index < length; index++) {
9173                     var item     = visibleItems[index],
9174                         minWidth = item.minWidth || 0;
9175
9176                     //shrink each non-flex tab by an equal amount to make them all fit. Flexed items are all
9177                     //shrunk to their minWidth because they're flexible and should be the first to lose width
9178                     if (item.flex) {
9179                         boxes[index].width = minWidth;
9180                     } else {
9181                         minWidths.push({
9182                             minWidth : minWidth,
9183                             available: boxes[index].width - minWidth,
9184                             index    : index
9185                         });
9186                     }
9187                 }
9188                 
9189                 //sort by descending amount of width remaining before minWidth is reached
9190                 minWidths.sort(function(a, b) {
9191                     return a.available > b.available ? 1 : -1;
9192                 });
9193                 
9194                 /*
9195                  * Distribute the shortfall (difference between total desired with of all items and actual width available)
9196                  * between the non-flexed items. We try to distribute the shortfall evenly, but apply it to items with the
9197                  * smallest difference between their width and minWidth first, so that if reducing the width by the average
9198                  * amount would make that item less than its minWidth, we carry the remainder over to the next item.
9199                  */
9200                 for (var i = 0, length = minWidths.length; i < length; i++) {
9201                     var itemIndex = minWidths[i].index;
9202                     
9203                     if (itemIndex == undefined) {
9204                         continue;
9205                     }
9206                         
9207                     var item      = visibleItems[itemIndex],
9208                         box       = boxes[itemIndex],
9209                         oldWidth  = box.width,
9210                         minWidth  = item.minWidth,
9211                         newWidth  = Math.max(minWidth, oldWidth - Math.ceil(shortfall / (length - i))),
9212                         reduction = oldWidth - newWidth;
9213                     
9214                     boxes[itemIndex].width = newWidth;
9215                     shortfall -= reduction;                    
9216                 }
9217             } else {
9218                 //temporary variables used in the flex width calculations below
9219                 var remainingWidth = availableWidth,
9220                     remainingFlex  = totalFlex;
9221
9222                 //calculate the widths of each flexed item
9223                 for (i = 0; i < visibleCount; i++) {
9224                     child = visibleItems[i];
9225                     calcs = boxes[i];
9226
9227                     childMargins = child.margins;
9228                     vertMargins  = childMargins.top + childMargins.bottom;
9229
9230                     if (isStart && child.flex && !child.width) {
9231                         flexedWidth     = Math.ceil((child.flex / remainingFlex) * remainingWidth);
9232                         remainingWidth -= flexedWidth;
9233                         remainingFlex  -= child.flex;
9234
9235                         calcs.width = flexedWidth;
9236                         calcs.dirtySize = true;
9237                     }
9238                 }
9239             }
9240         }
9241         
9242         if (isCenter) {
9243             leftOffset += availableWidth / 2;
9244         } else if (isEnd) {
9245             leftOffset += availableWidth;
9246         }
9247         
9248         //finally, calculate the left and top position of each item
9249         for (i = 0; i < visibleCount; i++) {
9250             child = visibleItems[i];
9251             calcs = boxes[i];
9252             
9253             childMargins = child.margins;
9254             leftOffset  += childMargins.left;
9255             vertMargins  = childMargins.top + childMargins.bottom;
9256             
9257             calcs.left = leftOffset;
9258             calcs.top  = topOffset + childMargins.top;
9259
9260             switch (this.align) {
9261                 case 'stretch':
9262                     stretchHeight = availHeight - vertMargins;
9263                     calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
9264                     calcs.dirtySize = true;
9265                     break;
9266                 case 'stretchmax':
9267                     stretchHeight = maxHeight - vertMargins;
9268                     calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
9269                     calcs.dirtySize = true;
9270                     break;
9271                 case 'middle':
9272                     var diff = availHeight - calcs.height - vertMargins;
9273                     if (diff > 0) {
9274                         calcs.top = topOffset + vertMargins + (diff / 2);
9275                     }
9276             }
9277             
9278             leftOffset += calcs.width + childMargins.right;
9279         }
9280
9281         return {
9282             boxes: boxes,
9283             meta : {
9284                 maxHeight   : maxHeight,
9285                 nonFlexWidth: nonFlexWidth,
9286                 desiredWidth: desiredWidth,
9287                 minimumWidth: minimumWidth,
9288                 shortfall   : desiredWidth - width,
9289                 tooNarrow   : tooNarrow
9290             }
9291         };
9292     }
9293 });
9294
9295 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;/**
9296  * @class Ext.layout.VBoxLayout
9297  * @extends Ext.layout.BoxLayout
9298  * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical
9299  * space between child items containing a numeric <code>flex</code> configuration.</p>
9300  * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option.
9301  */
9302 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
9303     /**
9304      * @cfg {String} align
9305      * Controls how the child items of the container are aligned. Acceptable configuration values for this
9306      * property are:
9307      * <div class="mdetail-params"><ul>
9308      * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally
9309      * at the <b>left</b> side of the container</div></li>
9310      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the
9311      * <b>mid-width</b> of the container</div></li>
9312      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill
9313      * the width of the container</div></li>
9314      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to
9315      * the size of the largest item.</div></li>
9316      * </ul></div>
9317      */
9318     align : 'left', // left, center, stretch, strechmax
9319     type: 'vbox',
9320
9321     /**
9322      * @cfg {String} pack
9323      * Controls how the child items of the container are packed together. Acceptable configuration values
9324      * for this property are:
9325      * <div class="mdetail-params"><ul>
9326      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
9327      * <b>top</b> side of container</div></li>
9328      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
9329      * <b>mid-height</b> of container</div></li>
9330      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>
9331      * side of container</div></li>
9332      * </ul></div>
9333      */
9334
9335     /**
9336      * @cfg {Number} flex
9337      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
9338      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>
9339      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
9340      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
9341      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
9342      */
9343
9344     /**
9345      * @private
9346      * Calculates the size and positioning of each item in the VBox. This iterates over all of the rendered,
9347      * visible items and returns a height, width, top and left for each, as well as a reference to each. Also
9348      * returns meta data such as maxHeight which are useful when resizing layout wrappers such as this.innerCt.
9349      * @param {Array} visibleItems The array of all rendered, visible items to be calculated for
9350      * @param {Object} targetSize Object containing target size and height
9351      * @return {Object} Object containing box measurements for each child, plus meta data
9352      */
9353     calculateChildBoxes: function(visibleItems, targetSize) {
9354         var visibleCount = visibleItems.length,
9355
9356             padding      = this.padding,
9357             topOffset    = padding.top,
9358             leftOffset   = padding.left,
9359             paddingVert  = topOffset  + padding.bottom,
9360             paddingHoriz = leftOffset + padding.right,
9361
9362             width        = targetSize.width - this.scrollOffset,
9363             height       = targetSize.height,
9364             availWidth   = Math.max(0, width - paddingHoriz),
9365
9366             isStart      = this.pack == 'start',
9367             isCenter     = this.pack == 'center',
9368             isEnd        = this.pack == 'end',
9369
9370             nonFlexHeight= 0,
9371             maxWidth     = 0,
9372             totalFlex    = 0,
9373             desiredHeight= 0,
9374             minimumHeight= 0,
9375
9376             //used to cache the calculated size and position values for each child item
9377             boxes        = [],
9378             
9379             //used in the for loops below, just declared here for brevity
9380             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, 
9381             horizMargins, vertMargins, stretchWidth;
9382
9383         //gather the total flex of all flexed items and the width taken up by fixed width items
9384         for (i = 0; i < visibleCount; i++) {
9385             child = visibleItems[i];
9386             childHeight = child.height;
9387             childWidth  = child.width;
9388             canLayout   = !child.hasLayout && typeof child.doLayout == 'function';
9389
9390             // Static height (numeric) requires no calcs
9391             if (typeof childHeight != 'number') {
9392
9393                 // flex and not 'auto' height
9394                 if (child.flex && !childHeight) {
9395                     totalFlex += child.flex;
9396
9397                 // Not flexed or 'auto' height or undefined height
9398                 } else {
9399                     //Render and layout sub-containers without a flex or width defined, as otherwise we
9400                     //don't know how wide the sub-container should be and cannot calculate flexed widths
9401                     if (!childHeight && canLayout) {
9402                         child.doLayout();
9403                     }
9404
9405                     childSize = child.getSize();
9406                     childWidth = childSize.width;
9407                     childHeight = childSize.height;
9408                 }
9409             }
9410             
9411             childMargins = child.margins;
9412             vertMargins  = childMargins.top + childMargins.bottom;
9413
9414             nonFlexHeight += vertMargins + (childHeight || 0);
9415             desiredHeight += vertMargins + (child.flex ? child.minHeight || 0 : childHeight);
9416             minimumHeight += vertMargins + (child.minHeight || childHeight || 0);
9417
9418             // Max width for align - force layout of non-layed out subcontainers without a numeric width
9419             if (typeof childWidth != 'number') {
9420                 if (canLayout) {
9421                     child.doLayout();
9422                 }
9423                 childWidth = child.getWidth();
9424             }
9425
9426             maxWidth = Math.max(maxWidth, childWidth + childMargins.left + childMargins.right);
9427
9428             //cache the size of each child component
9429             boxes.push({
9430                 component: child,
9431                 height   : childHeight || undefined,
9432                 width    : childWidth || undefined
9433             });
9434         }
9435                 
9436         var shortfall = desiredHeight - height,
9437             tooNarrow = minimumHeight > height;
9438
9439         //the height available to the flexed items
9440         var availableHeight = Math.max(0, (height - nonFlexHeight - paddingVert));
9441         
9442         if (tooNarrow) {
9443             for (i = 0, length = visibleCount; i < length; i++) {
9444                 boxes[i].height = visibleItems[i].minHeight || visibleItems[i].height || boxes[i].height;
9445             }
9446         } else {
9447             //all flexed items should be sized to their minimum width, other items should be shrunk down until
9448             //the shortfall has been accounted for
9449             if (shortfall > 0) {
9450                 var minHeights = [];
9451
9452                 /**
9453                  * When we have a shortfall but are not tooNarrow, we need to shrink the height of each non-flexed item.
9454                  * Flexed items are immediately reduced to their minHeight and anything already at minHeight is ignored.
9455                  * The remaining items are collected into the minHeights array, which is later used to distribute the shortfall.
9456                  */
9457                 for (var index = 0, length = visibleCount; index < length; index++) {
9458                     var item      = visibleItems[index],
9459                         minHeight = item.minHeight || 0;
9460
9461                     //shrink each non-flex tab by an equal amount to make them all fit. Flexed items are all
9462                     //shrunk to their minHeight because they're flexible and should be the first to lose height
9463                     if (item.flex) {
9464                         boxes[index].height = minHeight;
9465                     } else {
9466                         minHeights.push({
9467                             minHeight: minHeight, 
9468                             available: boxes[index].height - minHeight,
9469                             index    : index
9470                         });
9471                     }
9472                 }
9473
9474                 //sort by descending minHeight value
9475                 minHeights.sort(function(a, b) {
9476                     return a.available > b.available ? 1 : -1;
9477                 });
9478
9479                 /*
9480                  * Distribute the shortfall (difference between total desired with of all items and actual height available)
9481                  * between the non-flexed items. We try to distribute the shortfall evenly, but apply it to items with the
9482                  * smallest difference between their height and minHeight first, so that if reducing the height by the average
9483                  * amount would make that item less than its minHeight, we carry the remainder over to the next item.
9484                  */
9485                 for (var i = 0, length = minHeights.length; i < length; i++) {
9486                     var itemIndex = minHeights[i].index;
9487
9488                     if (itemIndex == undefined) {
9489                         continue;
9490                     }
9491
9492                     var item      = visibleItems[itemIndex],
9493                         box       = boxes[itemIndex],
9494                         oldHeight  = box.height,
9495                         minHeight  = item.minHeight,
9496                         newHeight  = Math.max(minHeight, oldHeight - Math.ceil(shortfall / (length - i))),
9497                         reduction = oldHeight - newHeight;
9498
9499                     boxes[itemIndex].height = newHeight;
9500                     shortfall -= reduction;
9501                 }
9502             } else {
9503                 //temporary variables used in the flex height calculations below
9504                 var remainingHeight = availableHeight,
9505                     remainingFlex   = totalFlex;
9506                 
9507                 //calculate the height of each flexed item
9508                 for (i = 0; i < visibleCount; i++) {
9509                     child = visibleItems[i];
9510                     calcs = boxes[i];
9511
9512                     childMargins = child.margins;
9513                     horizMargins = childMargins.left + childMargins.right;
9514
9515                     if (isStart && child.flex && !child.height) {
9516                         flexedHeight     = Math.ceil((child.flex / remainingFlex) * remainingHeight);
9517                         remainingHeight -= flexedHeight;
9518                         remainingFlex   -= child.flex;
9519
9520                         calcs.height = flexedHeight;
9521                         calcs.dirtySize = true;
9522                     }
9523                 }
9524             }
9525         }
9526
9527         if (isCenter) {
9528             topOffset += availableHeight / 2;
9529         } else if (isEnd) {
9530             topOffset += availableHeight;
9531         }
9532
9533         //finally, calculate the left and top position of each item
9534         for (i = 0; i < visibleCount; i++) {
9535             child = visibleItems[i];
9536             calcs = boxes[i];
9537
9538             childMargins = child.margins;
9539             topOffset   += childMargins.top;
9540             horizMargins = childMargins.left + childMargins.right;
9541             
9542
9543             calcs.left = leftOffset + childMargins.left;
9544             calcs.top  = topOffset;
9545             
9546             switch (this.align) {
9547                 case 'stretch':
9548                     stretchWidth = availWidth - horizMargins;
9549                     calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
9550                     calcs.dirtySize = true;
9551                     break;
9552                 case 'stretchmax':
9553                     stretchWidth = maxWidth - horizMargins;
9554                     calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
9555                     calcs.dirtySize = true;
9556                     break;
9557                 case 'center':
9558                     var diff = availWidth - calcs.width - horizMargins;
9559                     if (diff > 0) {
9560                         calcs.left = leftOffset + horizMargins + (diff / 2);
9561                     }
9562             }
9563
9564             topOffset += calcs.height + childMargins.bottom;
9565         }
9566         
9567         return {
9568             boxes: boxes,
9569             meta : {
9570                 maxWidth     : maxWidth,
9571                 nonFlexHeight: nonFlexHeight,
9572                 desiredHeight: desiredHeight,
9573                 minimumHeight: minimumHeight,
9574                 shortfall    : desiredHeight - height,
9575                 tooNarrow    : tooNarrow
9576             }
9577         };
9578     }
9579 });
9580
9581 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
9582 /**
9583  * @class Ext.layout.ToolbarLayout
9584  * @extends Ext.layout.ContainerLayout
9585  * Layout manager used by Ext.Toolbar. This is highly specialised for use by Toolbars and would not
9586  * usually be used by any other class.
9587  */
9588 Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
9589     monitorResize : true,
9590
9591     type: 'toolbar',
9592
9593     /**
9594      * @property triggerWidth
9595      * @type Number
9596      * The width allocated for the menu trigger at the extreme right end of the Toolbar
9597      */
9598     triggerWidth: 18,
9599
9600     /**
9601      * @property noItemsMenuText
9602      * @type String
9603      * HTML fragment to render into the toolbar overflow menu if there are no items to display
9604      */
9605     noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
9606
9607     /**
9608      * @private
9609      * @property lastOverflow
9610      * @type Boolean
9611      * Used internally to record whether the last layout caused an overflow or not
9612      */
9613     lastOverflow: false,
9614
9615     /**
9616      * @private
9617      * @property tableHTML
9618      * @type String
9619      * String used to build the HTML injected to support the Toolbar's layout. The align property is
9620      * injected into this string inside the td.x-toolbar-left element during onLayout.
9621      */
9622     tableHTML: [
9623         '<table cellspacing="0" class="x-toolbar-ct">',
9624             '<tbody>',
9625                 '<tr>',
9626                     '<td class="x-toolbar-left" align="{0}">',
9627                         '<table cellspacing="0">',
9628                             '<tbody>',
9629                                 '<tr class="x-toolbar-left-row"></tr>',
9630                             '</tbody>',
9631                         '</table>',
9632                     '</td>',
9633                     '<td class="x-toolbar-right" align="right">',
9634                         '<table cellspacing="0" class="x-toolbar-right-ct">',
9635                             '<tbody>',
9636                                 '<tr>',
9637                                     '<td>',
9638                                         '<table cellspacing="0">',
9639                                             '<tbody>',
9640                                                 '<tr class="x-toolbar-right-row"></tr>',
9641                                             '</tbody>',
9642                                         '</table>',
9643                                     '</td>',
9644                                     '<td>',
9645                                         '<table cellspacing="0">',
9646                                             '<tbody>',
9647                                                 '<tr class="x-toolbar-extras-row"></tr>',
9648                                             '</tbody>',
9649                                         '</table>',
9650                                     '</td>',
9651                                 '</tr>',
9652                             '</tbody>',
9653                         '</table>',
9654                     '</td>',
9655                 '</tr>',
9656             '</tbody>',
9657         '</table>'
9658     ].join(""),
9659
9660     /**
9661      * @private
9662      * Create the wrapping Toolbar HTML and render/move all the items into the correct places
9663      */
9664     onLayout : function(ct, target) {
9665         //render the Toolbar <table> HTML if it's not already present
9666         if (!this.leftTr) {
9667             var align = ct.buttonAlign == 'center' ? 'center' : 'left';
9668
9669             target.addClass('x-toolbar-layout-ct');
9670             target.insertHtml('beforeEnd', String.format(this.tableHTML, align));
9671
9672             this.leftTr   = target.child('tr.x-toolbar-left-row', true);
9673             this.rightTr  = target.child('tr.x-toolbar-right-row', true);
9674             this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
9675
9676             if (this.hiddenItem == undefined) {
9677                 /**
9678                  * @property hiddenItems
9679                  * @type Array
9680                  * Holds all items that are currently hidden due to there not being enough space to render them
9681                  * These items will appear on the expand menu.
9682                  */
9683                 this.hiddenItems = [];
9684             }
9685         }
9686
9687         var side     = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
9688             items    = ct.items.items,
9689             position = 0;
9690
9691         //render each item if not already rendered, place it into the correct (left or right) target
9692         for (var i = 0, len = items.length, c; i < len; i++, position++) {
9693             c = items[i];
9694
9695             if (c.isFill) {
9696                 side   = this.rightTr;
9697                 position = -1;
9698             } else if (!c.rendered) {
9699                 c.render(this.insertCell(c, side, position));
9700                 this.configureItem(c);
9701             } else {
9702                 if (!c.xtbHidden && !this.isValidParent(c, side.childNodes[position])) {
9703                     var td = this.insertCell(c, side, position);
9704                     td.appendChild(c.getPositionEl().dom);
9705                     c.container = Ext.get(td);
9706                 }
9707             }
9708         }
9709
9710         //strip extra empty cells
9711         this.cleanup(this.leftTr);
9712         this.cleanup(this.rightTr);
9713         this.cleanup(this.extrasTr);
9714         this.fitToSize(target);
9715     },
9716
9717     /**
9718      * @private
9719      * Removes any empty nodes from the given element
9720      * @param {Ext.Element} el The element to clean up
9721      */
9722     cleanup : function(el) {
9723         var cn = el.childNodes, i, c;
9724
9725         for (i = cn.length-1; i >= 0 && (c = cn[i]); i--) {
9726             if (!c.firstChild) {
9727                 el.removeChild(c);
9728             }
9729         }
9730     },
9731
9732     /**
9733      * @private
9734      * Inserts the given Toolbar item into the given element
9735      * @param {Ext.Component} c The component to add
9736      * @param {Ext.Element} target The target to add the component to
9737      * @param {Number} position The position to add the component at
9738      */
9739     insertCell : function(c, target, position) {
9740         var td = document.createElement('td');
9741         td.className = 'x-toolbar-cell';
9742
9743         target.insertBefore(td, target.childNodes[position] || null);
9744
9745         return td;
9746     },
9747
9748     /**
9749      * @private
9750      * Hides an item because it will not fit in the available width. The item will be unhidden again
9751      * if the Toolbar is resized to be large enough to show it
9752      * @param {Ext.Component} item The item to hide
9753      */
9754     hideItem : function(item) {
9755         this.hiddenItems.push(item);
9756
9757         item.xtbHidden = true;
9758         item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
9759         item.hide();
9760     },
9761
9762     /**
9763      * @private
9764      * Unhides an item that was previously hidden due to there not being enough space left on the Toolbar
9765      * @param {Ext.Component} item The item to show
9766      */
9767     unhideItem : function(item) {
9768         item.show();
9769         item.xtbHidden = false;
9770         this.hiddenItems.remove(item);
9771     },
9772
9773     /**
9774      * @private
9775      * Returns the width of the given toolbar item. If the item is currently hidden because there
9776      * is not enough room to render it, its previous width is returned
9777      * @param {Ext.Component} c The component to measure
9778      * @return {Number} The width of the item
9779      */
9780     getItemWidth : function(c) {
9781         return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
9782     },
9783
9784     /**
9785      * @private
9786      * Called at the end of onLayout. At this point the Toolbar has already been resized, so we need
9787      * to fit the items into the available width. We add up the width required by all of the items in
9788      * the toolbar - if we don't have enough space we hide the extra items and render the expand menu
9789      * trigger.
9790      * @param {Ext.Element} target The Element the Toolbar is currently laid out within
9791      */
9792     fitToSize : function(target) {
9793         if (this.container.enableOverflow === false) {
9794             return;
9795         }
9796
9797         var width       = target.dom.clientWidth,
9798             tableWidth  = target.dom.firstChild.offsetWidth,
9799             clipWidth   = width - this.triggerWidth,
9800             lastWidth   = this.lastWidth || 0,
9801
9802             hiddenItems = this.hiddenItems,
9803             hasHiddens  = hiddenItems.length != 0,
9804             isLarger    = width >= lastWidth;
9805
9806         this.lastWidth  = width;
9807
9808         if (tableWidth > width || (hasHiddens && isLarger)) {
9809             var items     = this.container.items.items,
9810                 len       = items.length,
9811                 loopWidth = 0,
9812                 item;
9813
9814             for (var i = 0; i < len; i++) {
9815                 item = items[i];
9816
9817                 if (!item.isFill) {
9818                     loopWidth += this.getItemWidth(item);
9819                     if (loopWidth > clipWidth) {
9820                         if (!(item.hidden || item.xtbHidden)) {
9821                             this.hideItem(item);
9822                         }
9823                     } else if (item.xtbHidden) {
9824                         this.unhideItem(item);
9825                     }
9826                 }
9827             }
9828         }
9829
9830         //test for number of hidden items again here because they may have changed above
9831         hasHiddens = hiddenItems.length != 0;
9832
9833         if (hasHiddens) {
9834             this.initMore();
9835
9836             if (!this.lastOverflow) {
9837                 this.container.fireEvent('overflowchange', this.container, true);
9838                 this.lastOverflow = true;
9839             }
9840         } else if (this.more) {
9841             this.clearMenu();
9842             this.more.destroy();
9843             delete this.more;
9844
9845             if (this.lastOverflow) {
9846                 this.container.fireEvent('overflowchange', this.container, false);
9847                 this.lastOverflow = false;
9848             }
9849         }
9850     },
9851
9852     /**
9853      * @private
9854      * Returns a menu config for a given component. This config is used to create a menu item
9855      * to be added to the expander menu
9856      * @param {Ext.Component} component The component to create the config for
9857      * @param {Boolean} hideOnClick Passed through to the menu item
9858      */
9859     createMenuConfig : function(component, hideOnClick){
9860         var config = Ext.apply({}, component.initialConfig),
9861             group  = component.toggleGroup;
9862
9863         Ext.copyTo(config, component, [
9864             'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
9865         ]);
9866
9867         Ext.apply(config, {
9868             text       : component.overflowText || component.text,
9869             hideOnClick: hideOnClick
9870         });
9871
9872         if (group || component.enableToggle) {
9873             Ext.apply(config, {
9874                 group  : group,
9875                 checked: component.pressed,
9876                 listeners: {
9877                     checkchange: function(item, checked){
9878                         component.toggle(checked);
9879                     }
9880                 }
9881             });
9882         }
9883
9884         delete config.ownerCt;
9885         delete config.xtype;
9886         delete config.id;
9887
9888         return config;
9889     },
9890
9891     /**
9892      * @private
9893      * Adds the given Toolbar item to the given menu. Buttons inside a buttongroup are added individually.
9894      * @param {Ext.menu.Menu} menu The menu to add to
9895      * @param {Ext.Component} component The component to add
9896      */
9897     addComponentToMenu : function(menu, component) {
9898         if (component instanceof Ext.Toolbar.Separator) {
9899             menu.add('-');
9900
9901         } else if (Ext.isFunction(component.isXType)) {
9902             if (component.isXType('splitbutton')) {
9903                 menu.add(this.createMenuConfig(component, true));
9904
9905             } else if (component.isXType('button')) {
9906                 menu.add(this.createMenuConfig(component, !component.menu));
9907
9908             } else if (component.isXType('buttongroup')) {
9909                 component.items.each(function(item){
9910                      this.addComponentToMenu(menu, item);
9911                 }, this);
9912             }
9913         }
9914     },
9915
9916     /**
9917      * @private
9918      * Deletes the sub-menu of each item in the expander menu. Submenus are created for items such as
9919      * splitbuttons and buttongroups, where the Toolbar item cannot be represented by a single menu item
9920      */
9921     clearMenu : function(){
9922         var menu = this.moreMenu;
9923         if (menu && menu.items) {
9924             menu.items.each(function(item){
9925                 delete item.menu;
9926             });
9927         }
9928     },
9929
9930     /**
9931      * @private
9932      * Called before the expand menu is shown, this rebuilds the menu since it was last shown because
9933      * it is possible that the items hidden due to space limitations on the Toolbar have changed since.
9934      * @param {Ext.menu.Menu} m The menu
9935      */
9936     beforeMoreShow : function(menu) {
9937         var items = this.container.items.items,
9938             len   = items.length,
9939             item,
9940             prev;
9941
9942         var needsSep = function(group, item){
9943             return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
9944         };
9945
9946         this.clearMenu();
9947         menu.removeAll();
9948         for (var i = 0; i < len; i++) {
9949             item = items[i];
9950             if (item.xtbHidden) {
9951                 if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
9952                     menu.add('-');
9953                 }
9954                 this.addComponentToMenu(menu, item);
9955                 prev = item;
9956             }
9957         }
9958
9959         // put something so the menu isn't empty if no compatible items found
9960         if (menu.items.length < 1) {
9961             menu.add(this.noItemsMenuText);
9962         }
9963     },
9964
9965     /**
9966      * @private
9967      * Creates the expand trigger and menu, adding them to the <tr> at the extreme right of the
9968      * Toolbar table
9969      */
9970     initMore : function(){
9971         if (!this.more) {
9972             /**
9973              * @private
9974              * @property moreMenu
9975              * @type Ext.menu.Menu
9976              * The expand menu - holds items for every Toolbar item that cannot be shown
9977              * because the Toolbar is currently not wide enough.
9978              */
9979             this.moreMenu = new Ext.menu.Menu({
9980                 ownerCt : this.container,
9981                 listeners: {
9982                     beforeshow: this.beforeMoreShow,
9983                     scope: this
9984                 }
9985             });
9986
9987             /**
9988              * @private
9989              * @property more
9990              * @type Ext.Button
9991              * The expand button which triggers the overflow menu to be shown
9992              */
9993             this.more = new Ext.Button({
9994                 iconCls: 'x-toolbar-more-icon',
9995                 cls    : 'x-toolbar-more',
9996                 menu   : this.moreMenu,
9997                 ownerCt: this.container
9998             });
9999
10000             var td = this.insertCell(this.more, this.extrasTr, 100);
10001             this.more.render(td);
10002         }
10003     },
10004
10005     destroy : function(){
10006         Ext.destroy(this.more, this.moreMenu);
10007         delete this.leftTr;
10008         delete this.rightTr;
10009         delete this.extrasTr;
10010         Ext.layout.ToolbarLayout.superclass.destroy.call(this);
10011     }
10012 });
10013
10014 Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;
10015 /**
10016  * @class Ext.layout.MenuLayout
10017  * @extends Ext.layout.ContainerLayout
10018  * <p>Layout manager used by {@link Ext.menu.Menu}. Generally this class should not need to be used directly.</p>
10019  */
10020  Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
10021     monitorResize : true,
10022
10023     type: 'menu',
10024
10025     setContainer : function(ct){
10026         this.monitorResize = !ct.floating;
10027         // This event is only fired by the menu in IE, used so we don't couple
10028         // the menu with the layout.
10029         ct.on('autosize', this.doAutoSize, this);
10030         Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
10031     },
10032
10033     renderItem : function(c, position, target){
10034         if (!this.itemTpl) {
10035             this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
10036                 '<li id="{itemId}" class="{itemCls}">',
10037                     '<tpl if="needsIcon">',
10038                         '<img alt="{altText}" src="{icon}" class="{iconCls}"/>',
10039                     '</tpl>',
10040                 '</li>'
10041             );
10042         }
10043
10044         if(c && !c.rendered){
10045             if(Ext.isNumber(position)){
10046                 position = target.dom.childNodes[position];
10047             }
10048             var a = this.getItemArgs(c);
10049
10050 //          The Component's positionEl is the <li> it is rendered into
10051             c.render(c.positionEl = position ?
10052                 this.itemTpl.insertBefore(position, a, true) :
10053                 this.itemTpl.append(target, a, true));
10054
10055 //          Link the containing <li> to the item.
10056             c.positionEl.menuItemId = c.getItemId();
10057
10058 //          If rendering a regular Component, and it needs an icon,
10059 //          move the Component rightwards.
10060             if (!a.isMenuItem && a.needsIcon) {
10061                 c.positionEl.addClass('x-menu-list-item-indent');
10062             }
10063             this.configureItem(c);
10064         }else if(c && !this.isValidParent(c, target)){
10065             if(Ext.isNumber(position)){
10066                 position = target.dom.childNodes[position];
10067             }
10068             target.dom.insertBefore(c.getActionEl().dom, position || null);
10069         }
10070     },
10071
10072     getItemArgs : function(c) {
10073         var isMenuItem = c instanceof Ext.menu.Item,
10074             canHaveIcon = !(isMenuItem || c instanceof Ext.menu.Separator);
10075
10076         return {
10077             isMenuItem: isMenuItem,
10078             needsIcon: canHaveIcon && (c.icon || c.iconCls),
10079             icon: c.icon || Ext.BLANK_IMAGE_URL,
10080             iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
10081             itemId: 'x-menu-el-' + c.id,
10082             itemCls: 'x-menu-list-item ',
10083             altText: c.altText || ''
10084         };
10085     },
10086
10087     //  Valid if the Component is in a <li> which is part of our target <ul>
10088     isValidParent : function(c, target) {
10089         return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
10090     },
10091
10092     onLayout : function(ct, target){
10093         Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
10094         this.doAutoSize();
10095     },
10096
10097     doAutoSize : function(){
10098         var ct = this.container, w = ct.width;
10099         if(ct.floating){
10100             if(w){
10101                 ct.setWidth(w);
10102             }else if(Ext.isIE){
10103                 ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
10104                 var el = ct.getEl(), t = el.dom.offsetWidth; // force recalc
10105                 ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
10106             }
10107         }
10108     }
10109 });
10110 Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;
10111 /**
10112  * @class Ext.Viewport
10113  * @extends Ext.Container
10114  * <p>A specialized container representing the viewable application area (the browser viewport).</p>
10115  * <p>The Viewport renders itself to the document body, and automatically sizes itself to the size of
10116  * the browser viewport and manages window resizing. There may only be one Viewport created
10117  * in a page. Inner layouts are available by virtue of the fact that all {@link Ext.Panel Panel}s
10118  * added to the Viewport, either through its {@link #items}, or through the items, or the {@link #add}
10119  * method of any of its child Panels may themselves have a layout.</p>
10120  * <p>The Viewport does not provide scrolling, so child Panels within the Viewport should provide
10121  * for scrolling if needed using the {@link #autoScroll} config.</p>
10122  * <p>An example showing a classic application border layout:</p><pre><code>
10123 new Ext.Viewport({
10124     layout: 'border',
10125     items: [{
10126         region: 'north',
10127         html: '&lt;h1 class="x-panel-header">Page Title&lt;/h1>',
10128         autoHeight: true,
10129         border: false,
10130         margins: '0 0 5 0'
10131     }, {
10132         region: 'west',
10133         collapsible: true,
10134         title: 'Navigation',
10135         width: 200
10136         // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout}
10137     }, {
10138         region: 'south',
10139         title: 'Title for Panel',
10140         collapsible: true,
10141         html: 'Information goes here',
10142         split: true,
10143         height: 100,
10144         minHeight: 100
10145     }, {
10146         region: 'east',
10147         title: 'Title for the Grid Panel',
10148         collapsible: true,
10149         split: true,
10150         width: 200,
10151         xtype: 'grid',
10152         // remaining grid configuration not shown ...
10153         // notice that the GridPanel is added directly as the region
10154         // it is not "overnested" inside another Panel
10155     }, {
10156         region: 'center',
10157         xtype: 'tabpanel', // TabPanel itself has no title
10158         items: {
10159             title: 'Default Tab',
10160             html: 'The first tab\'s content. Others may be added dynamically'
10161         }
10162     }]
10163 });
10164 </code></pre>
10165  * @constructor
10166  * Create a new Viewport
10167  * @param {Object} config The config object
10168  * @xtype viewport
10169  */
10170 Ext.Viewport = Ext.extend(Ext.Container, {
10171     /*
10172      * Privatize config options which, if used, would interfere with the
10173      * correct operation of the Viewport as the sole manager of the
10174      * layout of the document body.
10175      */
10176     /**
10177      * @cfg {Mixed} applyTo @hide
10178      */
10179     /**
10180      * @cfg {Boolean} allowDomMove @hide
10181      */
10182     /**
10183      * @cfg {Boolean} hideParent @hide
10184      */
10185     /**
10186      * @cfg {Mixed} renderTo @hide
10187      */
10188     /**
10189      * @cfg {Boolean} hideParent @hide
10190      */
10191     /**
10192      * @cfg {Number} height @hide
10193      */
10194     /**
10195      * @cfg {Number} width @hide
10196      */
10197     /**
10198      * @cfg {Boolean} autoHeight @hide
10199      */
10200     /**
10201      * @cfg {Boolean} autoWidth @hide
10202      */
10203     /**
10204      * @cfg {Boolean} deferHeight @hide
10205      */
10206     /**
10207      * @cfg {Boolean} monitorResize @hide
10208      */
10209
10210     initComponent : function() {
10211         Ext.Viewport.superclass.initComponent.call(this);
10212         document.getElementsByTagName('html')[0].className += ' x-viewport';
10213         this.el = Ext.getBody();
10214         this.el.setHeight = Ext.emptyFn;
10215         this.el.setWidth = Ext.emptyFn;
10216         this.el.setSize = Ext.emptyFn;
10217         this.el.dom.scroll = 'no';
10218         this.allowDomMove = false;
10219         this.autoWidth = true;
10220         this.autoHeight = true;
10221         Ext.EventManager.onWindowResize(this.fireResize, this);
10222         this.renderTo = this.el;
10223     },
10224
10225     fireResize : function(w, h){
10226         this.fireEvent('resize', this, w, h, w, h);
10227     }
10228 });
10229 Ext.reg('viewport', Ext.Viewport);
10230 /**
10231  * @class Ext.Panel
10232  * @extends Ext.Container
10233  * <p>Panel is a container that has specific functionality and structural components that make
10234  * it the perfect building block for application-oriented user interfaces.</p>
10235  * <p>Panels are, by virtue of their inheritance from {@link Ext.Container}, capable
10236  * of being configured with a {@link Ext.Container#layout layout}, and containing child Components.</p>
10237  * <p>When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.Container#add adding} Components
10238  * to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether
10239  * 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
10240  * default, Panels use the {@link Ext.layout.ContainerLayout ContainerLayout} scheme. This simply renders
10241  * child components, appending them one after the other inside the Container, and <b>does not apply any sizing</b>
10242  * at all.</p>
10243  * <p>A Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate
10244  * {@link #header}, {@link #footer} and {@link #body} sections (see {@link #frame} for additional
10245  * information).</p>
10246  * <p>Panel also provides built-in {@link #collapsible expandable and collapsible behavior}, along with
10247  * a variety of {@link #tools prebuilt tool buttons} that can be wired up to provide other customized
10248  * behavior.  Panels can be easily dropped into any {@link Ext.Container Container} or layout, and the
10249  * layout and rendering pipeline is {@link Ext.Container#add completely managed by the framework}.</p>
10250  * @constructor
10251  * @param {Object} config The config object
10252  * @xtype panel
10253  */
10254 Ext.Panel = Ext.extend(Ext.Container, {
10255     /**
10256      * The Panel's header {@link Ext.Element Element}. Read-only.
10257      * <p>This Element is used to house the {@link #title} and {@link #tools}</p>
10258      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
10259      * @type Ext.Element
10260      * @property header
10261      */
10262     /**
10263      * The Panel's body {@link Ext.Element Element} which may be used to contain HTML content.
10264      * The content may be specified in the {@link #html} config, or it may be loaded using the
10265      * {@link autoLoad} config, or through the Panel's {@link #getUpdater Updater}. Read-only.
10266      * <p>If this is used to load visible HTML elements in either way, then
10267      * the Panel may not be used as a Layout for hosting nested Panels.</p>
10268      * <p>If this Panel is intended to be used as the host of a Layout (See {@link #layout}
10269      * then the body Element must not be loaded or changed - it is under the control
10270      * of the Panel's Layout.
10271      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
10272      * @type Ext.Element
10273      * @property body
10274      */
10275     /**
10276      * The Panel's bwrap {@link Ext.Element Element} used to contain other Panel elements
10277      * (tbar, body, bbar, footer). See {@link #bodyCfg}. Read-only.
10278      * @type Ext.Element
10279      * @property bwrap
10280      */
10281     /**
10282      * True if this panel is collapsed. Read-only.
10283      * @type Boolean
10284      * @property collapsed
10285      */
10286     /**
10287      * @cfg {Object} bodyCfg
10288      * <p>A {@link Ext.DomHelper DomHelper} element specification object may be specified for any
10289      * Panel Element.</p>
10290      * <p>By default, the Default element in the table below will be used for the html markup to
10291      * create a child element with the commensurate Default class name (<code>baseCls</code> will be
10292      * replaced by <code>{@link #baseCls}</code>):</p>
10293      * <pre>
10294      * Panel      Default  Default             Custom      Additional       Additional
10295      * Element    element  class               element     class            style
10296      * ========   ==========================   =========   ==============   ===========
10297      * {@link #header}     div      {@link #baseCls}+'-header'   {@link #headerCfg}   headerCssClass   headerStyle
10298      * {@link #bwrap}      div      {@link #baseCls}+'-bwrap'     {@link #bwrapCfg}    bwrapCssClass    bwrapStyle
10299      * + tbar     div      {@link #baseCls}+'-tbar'       {@link #tbarCfg}     tbarCssClass     tbarStyle
10300      * + {@link #body}     div      {@link #baseCls}+'-body'       {@link #bodyCfg}     {@link #bodyCssClass}     {@link #bodyStyle}
10301      * + bbar     div      {@link #baseCls}+'-bbar'       {@link #bbarCfg}     bbarCssClass     bbarStyle
10302      * + {@link #footer}   div      {@link #baseCls}+'-footer'   {@link #footerCfg}   footerCssClass   footerStyle
10303      * </pre>
10304      * <p>Configuring a Custom element may be used, for example, to force the {@link #body} Element
10305      * to use a different form of markup than is created by default. An example of this might be
10306      * to {@link Ext.Element#createChild create a child} Panel containing a custom content, such as
10307      * a header, or forcing centering of all Panel content by having the body be a &lt;center&gt;
10308      * element:</p>
10309      * <pre><code>
10310 new Ext.Panel({
10311     title: 'Message Title',
10312     renderTo: Ext.getBody(),
10313     width: 200, height: 130,
10314     <b>bodyCfg</b>: {
10315         tag: 'center',
10316         cls: 'x-panel-body',  // Default class not applied if Custom element specified
10317         html: 'Message'
10318     },
10319     footerCfg: {
10320         tag: 'h2',
10321         cls: 'x-panel-footer',        // same as the Default class
10322         html: 'footer html'
10323     },
10324     footerCssClass: 'custom-footer', // additional css class, see {@link Ext.element#addClass addClass}
10325     footerStyle:    'background-color:red' // see {@link #bodyStyle}
10326 });
10327      * </code></pre>
10328      * <p>The example above also explicitly creates a <code>{@link #footer}</code> with custom markup and
10329      * styling applied.</p>
10330      */
10331     /**
10332      * @cfg {Object} headerCfg
10333      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
10334      * of this Panel's {@link #header} Element.  See <code>{@link #bodyCfg}</code> also.</p>
10335      */
10336     /**
10337      * @cfg {Object} bwrapCfg
10338      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
10339      * of this Panel's {@link #bwrap} Element.  See <code>{@link #bodyCfg}</code> also.</p>
10340      */
10341     /**
10342      * @cfg {Object} tbarCfg
10343      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
10344      * of this Panel's {@link #tbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
10345      */
10346     /**
10347      * @cfg {Object} bbarCfg
10348      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
10349      * of this Panel's {@link #bbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
10350      */
10351     /**
10352      * @cfg {Object} footerCfg
10353      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
10354      * of this Panel's {@link #footer} Element.  See <code>{@link #bodyCfg}</code> also.</p>
10355      */
10356     /**
10357      * @cfg {Boolean} closable
10358      * Panels themselves do not directly support being closed, but some Panel subclasses do (like
10359      * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}.  Specify <code>true</code>
10360      * to enable closing in such situations. Defaults to <code>false</code>.
10361      */
10362     /**
10363      * The Panel's footer {@link Ext.Element Element}. Read-only.
10364      * <p>This Element is used to house the Panel's <code>{@link #buttons}</code> or <code>{@link #fbar}</code>.</p>
10365      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
10366      * @type Ext.Element
10367      * @property footer
10368      */
10369     /**
10370      * @cfg {Mixed} applyTo
10371      * <p>The id of the node, a DOM node or an existing Element corresponding to a DIV that is already present in
10372      * the document that specifies some panel-specific structural markup.  When <code>applyTo</code> is used,
10373      * constituent parts of the panel can be specified by CSS class name within the main element, and the panel
10374      * will automatically create those components from that markup. Any required components not specified in the
10375      * markup will be autogenerated if necessary.</p>
10376      * <p>The following class names are supported (baseCls will be replaced by {@link #baseCls}):</p>
10377      * <ul><li>baseCls + '-header'</li>
10378      * <li>baseCls + '-header-text'</li>
10379      * <li>baseCls + '-bwrap'</li>
10380      * <li>baseCls + '-tbar'</li>
10381      * <li>baseCls + '-body'</li>
10382      * <li>baseCls + '-bbar'</li>
10383      * <li>baseCls + '-footer'</li></ul>
10384      * <p>Using this config, a call to render() is not required.  If applyTo is specified, any value passed for
10385      * {@link #renderTo} will be ignored and the target element's parent node will automatically be used as the
10386      * panel's container.</p>
10387      */
10388     /**
10389      * @cfg {Object/Array} tbar
10390      * <p>The top toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
10391      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
10392      * To access the top toolbar after render, use {@link #getTopToolbar}.</p>
10393      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
10394      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
10395      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
10396      * submission parameters are collected from the DOM tree.</p>
10397      */
10398     /**
10399      * @cfg {Object/Array} bbar
10400      * <p>The bottom toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
10401      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
10402      * To access the bottom toolbar after render, use {@link #getBottomToolbar}.</p>
10403      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
10404      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
10405      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
10406      * submission parameters are collected from the DOM tree.</p>
10407      */
10408     /** @cfg {Object/Array} fbar
10409      * <p>A {@link Ext.Toolbar Toolbar} object, a Toolbar config, or an array of
10410      * {@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>
10411      * <p>After render, the <code>fbar</code> property will be an {@link Ext.Toolbar Toolbar} instance.</p>
10412      * <p>If <code>{@link #buttons}</code> are specified, they will supersede the <code>fbar</code> configuration property.</p>
10413      * The Panel's <code>{@link #buttonAlign}</code> configuration affects the layout of these items, for example:
10414      * <pre><code>
10415 var w = new Ext.Window({
10416     height: 250,
10417     width: 500,
10418     bbar: new Ext.Toolbar({
10419         items: [{
10420             text: 'bbar Left'
10421         },'->',{
10422             text: 'bbar Right'
10423         }]
10424     }),
10425     {@link #buttonAlign}: 'left', // anything but 'center' or 'right' and you can use '-', and '->'
10426                                   // to control the alignment of fbar items
10427     fbar: [{
10428         text: 'fbar Left'
10429     },'->',{
10430         text: 'fbar Right'
10431     }]
10432 }).show();
10433      * </code></pre>
10434      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
10435      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
10436      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
10437      * submission parameters are collected from the DOM tree.</p>
10438      */
10439     /**
10440      * @cfg {Boolean} header
10441      * <code>true</code> to create the Panel's header element explicitly, <code>false</code> to skip creating
10442      * it.  If a <code>{@link #title}</code> is set the header will be created automatically, otherwise it will not.
10443      * If a <code>{@link #title}</code> is set but <code>header</code> is explicitly set to <code>false</code>, the header
10444      * will not be rendered.
10445      */
10446     /**
10447      * @cfg {Boolean} footer
10448      * <code>true</code> to create the footer element explicitly, false to skip creating it. The footer
10449      * will be created automatically if <code>{@link #buttons}</code> or a <code>{@link #fbar}</code> have
10450      * been configured.  See <code>{@link #bodyCfg}</code> for an example.
10451      */
10452     /**
10453      * @cfg {String} title
10454      * The title text to be used as innerHTML (html tags are accepted) to display in the panel
10455      * <code>{@link #header}</code> (defaults to ''). When a <code>title</code> is specified the
10456      * <code>{@link #header}</code> element will automatically be created and displayed unless
10457      * {@link #header} is explicitly set to <code>false</code>.  If you do not want to specify a
10458      * <code>title</code> at config time, but you may want one later, you must either specify a non-empty
10459      * <code>title</code> (a blank space ' ' will do) or <code>header:true</code> so that the container
10460      * element will get created.
10461      */
10462     /**
10463      * @cfg {Array} buttons
10464      * <code>buttons</code> will be used as <code>{@link Ext.Container#items items}</code> for the toolbar in
10465      * the footer (<code>{@link #fbar}</code>). Typically the value of this configuration property will be
10466      * an array of {@link Ext.Button}s or {@link Ext.Button} configuration objects.
10467      * If an item is configured with <code>minWidth</code> or the Panel is configured with <code>minButtonWidth</code>,
10468      * that width will be applied to the item.
10469      */
10470     /**
10471      * @cfg {Object/String/Function} autoLoad
10472      * A valid url spec according to the Updater {@link Ext.Updater#update} method.
10473      * If autoLoad is not null, the panel will attempt to load its contents
10474      * immediately upon render.<p>
10475      * The URL will become the default URL for this panel's {@link #body} element,
10476      * so it may be {@link Ext.Element#refresh refresh}ed at any time.</p>
10477      */
10478     /**
10479      * @cfg {Boolean} frame
10480      * <code>false</code> by default to render with plain 1px square borders. <code>true</code> to render with
10481      * 9 elements, complete with custom rounded corners (also see {@link Ext.Element#boxWrap}).
10482      * <p>The template generated for each condition is depicted below:</p><pre><code>
10483      *
10484 // frame = false
10485 &lt;div id="developer-specified-id-goes-here" class="x-panel">
10486
10487     &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:false)&lt;/span>&lt;/div>
10488
10489     &lt;div class="x-panel-bwrap">
10490         &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
10491     &lt;/div>
10492 &lt;/div>
10493
10494 // frame = true (create 9 elements)
10495 &lt;div id="developer-specified-id-goes-here" class="x-panel">
10496     &lt;div class="x-panel-tl">&lt;div class="x-panel-tr">&lt;div class="x-panel-tc">
10497         &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:true)&lt;/span>&lt;/div>
10498     &lt;/div>&lt;/div>&lt;/div>
10499
10500     &lt;div class="x-panel-bwrap">
10501         &lt;div class="x-panel-ml">&lt;div class="x-panel-mr">&lt;div class="x-panel-mc">
10502             &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
10503         &lt;/div>&lt;/div>&lt;/div>
10504
10505         &lt;div class="x-panel-bl">&lt;div class="x-panel-br">&lt;div class="x-panel-bc"/>
10506         &lt;/div>&lt;/div>&lt;/div>
10507 &lt;/div>
10508      * </code></pre>
10509      */
10510     /**
10511      * @cfg {Boolean} border
10512      * True to display the borders of the panel's body element, false to hide them (defaults to true).  By default,
10513      * the border is a 2px wide inset border, but this can be further altered by setting {@link #bodyBorder} to false.
10514      */
10515     /**
10516      * @cfg {Boolean} bodyBorder
10517      * True to display an interior border on the body element of the panel, false to hide it (defaults to true).
10518      * This only applies when {@link #border} == true.  If border == true and bodyBorder == false, the border will display
10519      * as a 1px wide inset border, giving the entire body element an inset appearance.
10520      */
10521     /**
10522      * @cfg {String/Object/Function} bodyCssClass
10523      * Additional css class selector to be applied to the {@link #body} element in the format expected by
10524      * {@link Ext.Element#addClass} (defaults to null). See {@link #bodyCfg}.
10525      */
10526     /**
10527      * @cfg {String/Object/Function} bodyStyle
10528      * Custom CSS styles to be applied to the {@link #body} element in the format expected by
10529      * {@link Ext.Element#applyStyles} (defaults to null). See {@link #bodyCfg}.
10530      */
10531     /**
10532      * @cfg {String} iconCls
10533      * The CSS class selector that specifies a background image to be used as the header icon (defaults to '').
10534      * <p>An example of specifying a custom icon class would be something like:
10535      * </p><pre><code>
10536 // specify the property in the config for the class:
10537      ...
10538      iconCls: 'my-icon'
10539
10540 // css class that specifies background image to be used as the icon image:
10541 .my-icon { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
10542 </code></pre>
10543      */
10544     /**
10545      * @cfg {Boolean} collapsible
10546      * True to make the panel collapsible and have the expand/collapse toggle button automatically rendered into
10547      * the header tool button area, false to keep the panel statically sized with no button (defaults to false).
10548      */
10549     /**
10550      * @cfg {Array} tools
10551      * An array of tool button configs to be added to the header tool area. When rendered, each tool is
10552      * stored as an {@link Ext.Element Element} referenced by a public property called <code><b></b>tools.<i>&lt;tool-type&gt;</i></code>
10553      * <p>Each tool config may contain the following properties:
10554      * <div class="mdetail-params"><ul>
10555      * <li><b>id</b> : String<div class="sub-desc"><b>Required.</b> The type
10556      * 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
10557      * resulting tool Element. Ext provides CSS rules, and an icon sprite containing images for the tool types listed below.
10558      * The developer may implement custom tools by supplying alternate CSS rules and background images:
10559      * <ul>
10560      * <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>
10561      * <div class="x-tool x-tool-close" style="float:left; margin-right:5;"> </div><div><code> close</code></div>
10562      * <div class="x-tool x-tool-minimize" style="float:left; margin-right:5;"> </div><div><code> minimize</code></div>
10563      * <div class="x-tool x-tool-maximize" style="float:left; margin-right:5;"> </div><div><code> maximize</code></div>
10564      * <div class="x-tool x-tool-restore" style="float:left; margin-right:5;"> </div><div><code> restore</code></div>
10565      * <div class="x-tool x-tool-gear" style="float:left; margin-right:5;"> </div><div><code> gear</code></div>
10566      * <div class="x-tool x-tool-pin" style="float:left; margin-right:5;"> </div><div><code> pin</code></div>
10567      * <div class="x-tool x-tool-unpin" style="float:left; margin-right:5;"> </div><div><code> unpin</code></div>
10568      * <div class="x-tool x-tool-right" style="float:left; margin-right:5;"> </div><div><code> right</code></div>
10569      * <div class="x-tool x-tool-left" style="float:left; margin-right:5;"> </div><div><code> left</code></div>
10570      * <div class="x-tool x-tool-up" style="float:left; margin-right:5;"> </div><div><code> up</code></div>
10571      * <div class="x-tool x-tool-down" style="float:left; margin-right:5;"> </div><div><code> down</code></div>
10572      * <div class="x-tool x-tool-refresh" style="float:left; margin-right:5;"> </div><div><code> refresh</code></div>
10573      * <div class="x-tool x-tool-minus" style="float:left; margin-right:5;"> </div><div><code> minus</code></div>
10574      * <div class="x-tool x-tool-plus" style="float:left; margin-right:5;"> </div><div><code> plus</code></div>
10575      * <div class="x-tool x-tool-help" style="float:left; margin-right:5;"> </div><div><code> help</code></div>
10576      * <div class="x-tool x-tool-search" style="float:left; margin-right:5;"> </div><div><code> search</code></div>
10577      * <div class="x-tool x-tool-save" style="float:left; margin-right:5;"> </div><div><code> save</code></div>
10578      * <div class="x-tool x-tool-print" style="float:left; margin-right:5;"> </div><div><code> print</code></div>
10579      * </ul></div></li>
10580      * <li><b>handler</b> : Function<div class="sub-desc"><b>Required.</b> The function to
10581      * call when clicked. Arguments passed are:<ul>
10582      * <li><b>event</b> : Ext.EventObject<div class="sub-desc">The click event.</div></li>
10583      * <li><b>toolEl</b> : Ext.Element<div class="sub-desc">The tool Element.</div></li>
10584      * <li><b>panel</b> : Ext.Panel<div class="sub-desc">The host Panel</div></li>
10585      * <li><b>tc</b> : Object<div class="sub-desc">The tool configuration object</div></li>
10586      * </ul></div></li>
10587      * <li><b>stopEvent</b> : Boolean<div class="sub-desc">Defaults to true. Specify as false to allow click event to propagate.</div></li>
10588      * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the handler.</div></li>
10589      * <li><b>qtip</b> : String/Object<div class="sub-desc">A tip string, or
10590      * a config argument to {@link Ext.QuickTip#register}</div></li>
10591      * <li><b>hidden</b> : Boolean<div class="sub-desc">True to initially render hidden.</div></li>
10592      * <li><b>on</b> : Object<div class="sub-desc">A listener config object specifiying
10593      * event listeners in the format of an argument to {@link #addListener}</div></li>
10594      * </ul></div>
10595      * <p>Note that, apart from the toggle tool which is provided when a panel is collapsible, these
10596      * tools only provide the visual button. Any required functionality must be provided by adding
10597      * handlers that implement the necessary behavior.</p>
10598      * <p>Example usage:</p>
10599      * <pre><code>
10600 tools:[{
10601     id:'refresh',
10602     qtip: 'Refresh form Data',
10603     // hidden:true,
10604     handler: function(event, toolEl, panel){
10605         // refresh logic
10606     }
10607 },
10608 {
10609     id:'help',
10610     qtip: 'Get Help',
10611     handler: function(event, toolEl, panel){
10612         // whatever
10613     }
10614 }]
10615 </code></pre>
10616      * <p>For the custom id of <code>'help'</code> define two relevant css classes with a link to
10617      * a 15x15 image:</p>
10618      * <pre><code>
10619 .x-tool-help {background-image: url(images/help.png);}
10620 .x-tool-help-over {background-image: url(images/help_over.png);}
10621 // if using an image sprite:
10622 .x-tool-help {background-image: url(images/help.png) no-repeat 0 0;}
10623 .x-tool-help-over {background-position:-15px 0;}
10624 </code></pre>
10625      */
10626     /**
10627      * @cfg {Ext.Template/Ext.XTemplate} toolTemplate
10628      * <p>A Template used to create {@link #tools} in the {@link #header} Element. Defaults to:</p><pre><code>
10629 new Ext.Template('&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>')</code></pre>
10630      * <p>This may may be overridden to provide a custom DOM structure for tools based upon a more
10631      * complex XTemplate. The template's data is a single tool configuration object (Not the entire Array)
10632      * as specified in {@link #tools}.  In the following example an &lt;a> tag is used to provide a
10633      * visual indication when hovering over the tool:</p><pre><code>
10634 var win = new Ext.Window({
10635     tools: [{
10636         id: 'download',
10637         href: '/MyPdfDoc.pdf'
10638     }],
10639     toolTemplate: new Ext.XTemplate(
10640         '&lt;tpl if="id==\'download\'">',
10641             '&lt;a class="x-tool x-tool-pdf" href="{href}">&lt;/a>',
10642         '&lt;/tpl>',
10643         '&lt;tpl if="id!=\'download\'">',
10644             '&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>',
10645         '&lt;/tpl>'
10646     ),
10647     width:500,
10648     height:300,
10649     closeAction:'hide'
10650 });</code></pre>
10651      * <p>Note that the CSS class 'x-tool-pdf' should have an associated style rule which provides an
10652      * appropriate background image, something like:</p>
10653     <pre><code>
10654     a.x-tool-pdf {background-image: url(../shared/extjs/images/pdf.gif)!important;}
10655     </code></pre>
10656      */
10657     /**
10658      * @cfg {Boolean} hideCollapseTool
10659      * <code>true</code> to hide the expand/collapse toggle button when <code>{@link #collapsible} == true</code>,
10660      * <code>false</code> to display it (defaults to <code>false</code>).
10661      */
10662     /**
10663      * @cfg {Boolean} titleCollapse
10664      * <code>true</code> to allow expanding and collapsing the panel (when <code>{@link #collapsible} = true</code>)
10665      * by clicking anywhere in the header bar, <code>false</code>) to allow it only by clicking to tool button
10666      * (defaults to <code>false</code>)). If this panel is a child item of a border layout also see the
10667      * {@link Ext.layout.BorderLayout.Region BorderLayout.Region}
10668      * <code>{@link Ext.layout.BorderLayout.Region#floatable floatable}</code> config option.
10669      */
10670
10671     /**
10672      * @cfg {Mixed} floating
10673      * <p>This property is used to configure the underlying {@link Ext.Layer}. Acceptable values for this
10674      * configuration property are:</p><div class="mdetail-params"><ul>
10675      * <li><b><code>false</code></b> : <b>Default.</b><div class="sub-desc">Display the panel inline where it is
10676      * rendered.</div></li>
10677      * <li><b><code>true</code></b> : <div class="sub-desc">Float the panel (absolute position it with automatic
10678      * shimming and shadow).<ul>
10679      * <div class="sub-desc">Setting floating to true will create an Ext.Layer for this panel and display the
10680      * panel at negative offsets so that it is hidden.</div>
10681      * <div class="sub-desc">Since the panel will be absolute positioned, the position must be set explicitly
10682      * <i>after</i> render (e.g., <code>myPanel.setPosition(100,100);</code>).</div>
10683      * <div class="sub-desc"><b>Note</b>: when floating a panel you should always assign a fixed width,
10684      * otherwise it will be auto width and will expand to fill to the right edge of the viewport.</div>
10685      * </ul></div></li>
10686      * <li><b><code>{@link Ext.Layer object}</code></b> : <div class="sub-desc">The specified object will be used
10687      * as the configuration object for the {@link Ext.Layer} that will be created.</div></li>
10688      * </ul></div>
10689      */
10690     /**
10691      * @cfg {Boolean/String} shadow
10692      * <code>true</code> (or a valid Ext.Shadow {@link Ext.Shadow#mode} value) to display a shadow behind the
10693      * panel, <code>false</code> to display no shadow (defaults to <code>'sides'</code>).  Note that this option
10694      * only applies when <code>{@link #floating} = true</code>.
10695      */
10696     /**
10697      * @cfg {Number} shadowOffset
10698      * The number of pixels to offset the shadow if displayed (defaults to <code>4</code>). Note that this
10699      * option only applies when <code>{@link #floating} = true</code>.
10700      */
10701     /**
10702      * @cfg {Boolean} shim
10703      * <code>false</code> to disable the iframe shim in browsers which need one (defaults to <code>true</code>).
10704      * Note that this option only applies when <code>{@link #floating} = true</code>.
10705      */
10706     /**
10707      * @cfg {Object/Array} keys
10708      * A {@link Ext.KeyMap} config object (in the format expected by {@link Ext.KeyMap#addBinding}
10709      * used to assign custom key handling to this panel (defaults to <code>null</code>).
10710      */
10711     /**
10712      * @cfg {Boolean/Object} draggable
10713      * <p><code>true</code> to enable dragging of this Panel (defaults to <code>false</code>).</p>
10714      * <p>For custom drag/drop implementations, an <b>Ext.Panel.DD</b> config could also be passed
10715      * in this config instead of <code>true</code>. Ext.Panel.DD is an internal, undocumented class which
10716      * moves a proxy Element around in place of the Panel's element, but provides no other behaviour
10717      * during dragging or on drop. It is a subclass of {@link Ext.dd.DragSource}, so behaviour may be
10718      * added by implementing the interface methods of {@link Ext.dd.DragDrop} e.g.:
10719      * <pre><code>
10720 new Ext.Panel({
10721     title: 'Drag me',
10722     x: 100,
10723     y: 100,
10724     renderTo: Ext.getBody(),
10725     floating: true,
10726     frame: true,
10727     width: 400,
10728     height: 200,
10729     draggable: {
10730 //      Config option of Ext.Panel.DD class.
10731 //      It&#39;s a floating Panel, so do not show a placeholder proxy in the original position.
10732         insertProxy: false,
10733
10734 //      Called for each mousemove event while dragging the DD object.
10735         onDrag : function(e){
10736 //          Record the x,y position of the drag proxy so that we can
10737 //          position the Panel at end of drag.
10738             var pel = this.proxy.getEl();
10739             this.x = pel.getLeft(true);
10740             this.y = pel.getTop(true);
10741
10742 //          Keep the Shadow aligned if there is one.
10743             var s = this.panel.getEl().shadow;
10744             if (s) {
10745                 s.realign(this.x, this.y, pel.getWidth(), pel.getHeight());
10746             }
10747         },
10748
10749 //      Called on the mouseup event.
10750         endDrag : function(e){
10751             this.panel.setPosition(this.x, this.y);
10752         }
10753     }
10754 }).show();
10755 </code></pre>
10756      */
10757     /**
10758      * @cfg {Boolean} disabled
10759      * Render this panel disabled (default is <code>false</code>). An important note when using the disabled
10760      * config on panels is that IE will often fail to initialize the disabled mask element correectly if
10761      * the panel's layout has not yet completed by the time the Panel is disabled during the render process.
10762      * If you experience this issue, you may need to instead use the {@link #afterlayout} event to initialize
10763      * the disabled state:
10764      * <pre><code>
10765 new Ext.Panel({
10766     ...
10767     listeners: {
10768         'afterlayout': {
10769             fn: function(p){
10770                 p.disable();
10771             },
10772             single: true // important, as many layouts can occur
10773         }
10774     }
10775 });
10776 </code></pre>
10777      */
10778     /**
10779      * @cfg {Boolean} autoHeight
10780      * <code>true</code> to use height:'auto', <code>false</code> to use fixed height (defaults to <code>false</code>).
10781      * <b>Note</b>: Setting <code>autoHeight: true</code> means that the browser will manage the panel's height
10782      * based on its contents, and that Ext will not manage it at all. If the panel is within a layout that
10783      * manages dimensions (<code>fit</code>, <code>border</code>, etc.) then setting <code>autoHeight: true</code>
10784      * can cause issues with scrolling and will not generally work as expected since the panel will take
10785      * on the height of its contents rather than the height required by the Ext layout.
10786      */
10787
10788
10789     /**
10790      * @cfg {String} baseCls
10791      * The base CSS class to apply to this panel's element (defaults to <code>'x-panel'</code>).
10792      * <p>Another option available by default is to specify <code>'x-plain'</code> which strips all styling
10793      * except for required attributes for Ext layouts to function (e.g. overflow:hidden).
10794      * See <code>{@link #unstyled}</code> also.</p>
10795      */
10796     baseCls : 'x-panel',
10797     /**
10798      * @cfg {String} collapsedCls
10799      * A CSS class to add to the panel's element after it has been collapsed (defaults to
10800      * <code>'x-panel-collapsed'</code>).
10801      */
10802     collapsedCls : 'x-panel-collapsed',
10803     /**
10804      * @cfg {Boolean} maskDisabled
10805      * <code>true</code> to mask the panel when it is {@link #disabled}, <code>false</code> to not mask it (defaults
10806      * to <code>true</code>).  Either way, the panel will always tell its contained elements to disable themselves
10807      * when it is disabled, but masking the panel can provide an additional visual cue that the panel is
10808      * disabled.
10809      */
10810     maskDisabled : true,
10811     /**
10812      * @cfg {Boolean} animCollapse
10813      * <code>true</code> to animate the transition when the panel is collapsed, <code>false</code> to skip the
10814      * animation (defaults to <code>true</code> if the {@link Ext.Fx} class is available, otherwise <code>false</code>).
10815      */
10816     animCollapse : Ext.enableFx,
10817     /**
10818      * @cfg {Boolean} headerAsText
10819      * <code>true</code> to display the panel <code>{@link #title}</code> in the <code>{@link #header}</code>,
10820      * <code>false</code> to hide it (defaults to <code>true</code>).
10821      */
10822     headerAsText : true,
10823     /**
10824      * @cfg {String} buttonAlign
10825      * The alignment of any {@link #buttons} added to this panel.  Valid values are <code>'right'</code>,
10826      * <code>'left'</code> and <code>'center'</code> (defaults to <code>'right'</code>).
10827      */
10828     buttonAlign : 'right',
10829     /**
10830      * @cfg {Boolean} collapsed
10831      * <code>true</code> to render the panel collapsed, <code>false</code> to render it expanded (defaults to
10832      * <code>false</code>).
10833      */
10834     collapsed : false,
10835     /**
10836      * @cfg {Boolean} collapseFirst
10837      * <code>true</code> to make sure the collapse/expand toggle button always renders first (to the left of)
10838      * any other tools in the panel's title bar, <code>false</code> to render it last (defaults to <code>true</code>).
10839      */
10840     collapseFirst : true,
10841     /**
10842      * @cfg {Number} minButtonWidth
10843      * Minimum width in pixels of all {@link #buttons} in this panel (defaults to <code>75</code>)
10844      */
10845     minButtonWidth : 75,
10846     /**
10847      * @cfg {Boolean} unstyled
10848      * Overrides the <code>{@link #baseCls}</code> setting to <code>{@link #baseCls} = 'x-plain'</code> which renders
10849      * the panel unstyled except for required attributes for Ext layouts to function (e.g. overflow:hidden).
10850      */
10851     /**
10852      * @cfg {String} elements
10853      * A comma-delimited list of panel elements to initialize when the panel is rendered.  Normally, this list will be
10854      * generated automatically based on the items added to the panel at config time, but sometimes it might be useful to
10855      * make sure a structural element is rendered even if not specified at config time (for example, you may want
10856      * to add a button or toolbar dynamically after the panel has been rendered).  Adding those elements to this
10857      * list will allocate the required placeholders in the panel when it is rendered.  Valid values are<div class="mdetail-params"><ul>
10858      * <li><code>header</code></li>
10859      * <li><code>tbar</code> (top bar)</li>
10860      * <li><code>body</code></li>
10861      * <li><code>bbar</code> (bottom bar)</li>
10862      * <li><code>footer</code></li>
10863      * </ul></div>
10864      * Defaults to '<code>body</code>'.
10865      */
10866     elements : 'body',
10867     /**
10868      * @cfg {Boolean} preventBodyReset
10869      * Defaults to <code>false</code>.  When set to <code>true</code>, an extra css class <code>'x-panel-normal'</code>
10870      * will be added to the panel's element, effectively applying css styles suggested by the W3C
10871      * (see http://www.w3.org/TR/CSS21/sample.html) to the Panel's <b>body</b> element (not the header,
10872      * footer, etc.).
10873      */
10874     preventBodyReset : false,
10875
10876     /**
10877      * @cfg {Number/String} padding
10878      * A shortcut for setting a padding style on the body element. The value can either be
10879      * a number to be applied to all sides, or a normal css string describing padding.
10880      * Defaults to <tt>undefined</tt>.
10881      *
10882      */
10883     padding: undefined,
10884
10885     /** @cfg {String} resizeEvent
10886      * The event to listen to for resizing in layouts. Defaults to <tt>'bodyresize'</tt>.
10887      */
10888     resizeEvent: 'bodyresize',
10889
10890     // protected - these could be used to customize the behavior of the window,
10891     // but changing them would not be useful without further mofifications and
10892     // could lead to unexpected or undesirable results.
10893     toolTarget : 'header',
10894     collapseEl : 'bwrap',
10895     slideAnchor : 't',
10896     disabledClass : '',
10897
10898     // private, notify box this class will handle heights
10899     deferHeight : true,
10900     // private
10901     expandDefaults: {
10902         duration : 0.25
10903     },
10904     // private
10905     collapseDefaults : {
10906         duration : 0.25
10907     },
10908
10909     // private
10910     initComponent : function(){
10911         Ext.Panel.superclass.initComponent.call(this);
10912
10913         this.addEvents(
10914             /**
10915              * @event bodyresize
10916              * Fires after the Panel has been resized.
10917              * @param {Ext.Panel} p the Panel which has been resized.
10918              * @param {Number} width The Panel body's new width.
10919              * @param {Number} height The Panel body's new height.
10920              */
10921             'bodyresize',
10922             /**
10923              * @event titlechange
10924              * Fires after the Panel title has been {@link #title set} or {@link #setTitle changed}.
10925              * @param {Ext.Panel} p the Panel which has had its title changed.
10926              * @param {String} The new title.
10927              */
10928             'titlechange',
10929             /**
10930              * @event iconchange
10931              * Fires after the Panel icon class has been {@link #iconCls set} or {@link #setIconClass changed}.
10932              * @param {Ext.Panel} p the Panel which has had its {@link #iconCls icon class} changed.
10933              * @param {String} The new icon class.
10934              * @param {String} The old icon class.
10935              */
10936             'iconchange',
10937             /**
10938              * @event collapse
10939              * Fires after the Panel has been collapsed.
10940              * @param {Ext.Panel} p the Panel that has been collapsed.
10941              */
10942             'collapse',
10943             /**
10944              * @event expand
10945              * Fires after the Panel has been expanded.
10946              * @param {Ext.Panel} p The Panel that has been expanded.
10947              */
10948             'expand',
10949             /**
10950              * @event beforecollapse
10951              * Fires before the Panel is collapsed.  A handler can return false to cancel the collapse.
10952              * @param {Ext.Panel} p the Panel being collapsed.
10953              * @param {Boolean} animate True if the collapse is animated, else false.
10954              */
10955             'beforecollapse',
10956             /**
10957              * @event beforeexpand
10958              * Fires before the Panel is expanded.  A handler can return false to cancel the expand.
10959              * @param {Ext.Panel} p The Panel being expanded.
10960              * @param {Boolean} animate True if the expand is animated, else false.
10961              */
10962             'beforeexpand',
10963             /**
10964              * @event beforeclose
10965              * Fires before the Panel is closed.  Note that Panels do not directly support being closed, but some
10966              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.  This event only
10967              * applies to such subclasses.
10968              * A handler can return false to cancel the close.
10969              * @param {Ext.Panel} p The Panel being closed.
10970              */
10971             'beforeclose',
10972             /**
10973              * @event close
10974              * Fires after the Panel is closed.  Note that Panels do not directly support being closed, but some
10975              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.
10976              * @param {Ext.Panel} p The Panel that has been closed.
10977              */
10978             'close',
10979             /**
10980              * @event activate
10981              * Fires after the Panel has been visually activated.
10982              * Note that Panels do not directly support being activated, but some Panel subclasses
10983              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
10984              * activate and deactivate events under the control of the TabPanel.
10985              * @param {Ext.Panel} p The Panel that has been activated.
10986              */
10987             'activate',
10988             /**
10989              * @event deactivate
10990              * Fires after the Panel has been visually deactivated.
10991              * Note that Panels do not directly support being deactivated, but some Panel subclasses
10992              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
10993              * activate and deactivate events under the control of the TabPanel.
10994              * @param {Ext.Panel} p The Panel that has been deactivated.
10995              */
10996             'deactivate'
10997         );
10998
10999         if(this.unstyled){
11000             this.baseCls = 'x-plain';
11001         }
11002
11003
11004         this.toolbars = [];
11005         // shortcuts
11006         if(this.tbar){
11007             this.elements += ',tbar';
11008             this.topToolbar = this.createToolbar(this.tbar);
11009             this.tbar = null;
11010
11011         }
11012         if(this.bbar){
11013             this.elements += ',bbar';
11014             this.bottomToolbar = this.createToolbar(this.bbar);
11015             this.bbar = null;
11016         }
11017
11018         if(this.header === true){
11019             this.elements += ',header';
11020             this.header = null;
11021         }else if(this.headerCfg || (this.title && this.header !== false)){
11022             this.elements += ',header';
11023         }
11024
11025         if(this.footerCfg || this.footer === true){
11026             this.elements += ',footer';
11027             this.footer = null;
11028         }
11029
11030         if(this.buttons){
11031             this.fbar = this.buttons;
11032             this.buttons = null;
11033         }
11034         if(this.fbar){
11035             this.createFbar(this.fbar);
11036         }
11037         if(this.autoLoad){
11038             this.on('render', this.doAutoLoad, this, {delay:10});
11039         }
11040     },
11041
11042     // private
11043     createFbar : function(fbar){
11044         var min = this.minButtonWidth;
11045         this.elements += ',footer';
11046         this.fbar = this.createToolbar(fbar, {
11047             buttonAlign: this.buttonAlign,
11048             toolbarCls: 'x-panel-fbar',
11049             enableOverflow: false,
11050             defaults: function(c){
11051                 return {
11052                     minWidth: c.minWidth || min
11053                 };
11054             }
11055         });
11056         // @compat addButton and buttons could possibly be removed
11057         // @target 4.0
11058         /**
11059          * This Panel's Array of buttons as created from the <code>{@link #buttons}</code>
11060          * config property. Read only.
11061          * @type Array
11062          * @property buttons
11063          */
11064         this.fbar.items.each(function(c){
11065             c.minWidth = c.minWidth || this.minButtonWidth;
11066         }, this);
11067         this.buttons = this.fbar.items.items;
11068     },
11069
11070     // private
11071     createToolbar: function(tb, options){
11072         var result;
11073         // Convert array to proper toolbar config
11074         if(Ext.isArray(tb)){
11075             tb = {
11076                 items: tb
11077             };
11078         }
11079         result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
11080         this.toolbars.push(result);
11081         return result;
11082     },
11083
11084     // private
11085     createElement : function(name, pnode){
11086         if(this[name]){
11087             pnode.appendChild(this[name].dom);
11088             return;
11089         }
11090
11091         if(name === 'bwrap' || this.elements.indexOf(name) != -1){
11092             if(this[name+'Cfg']){
11093                 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
11094             }else{
11095                 var el = document.createElement('div');
11096                 el.className = this[name+'Cls'];
11097                 this[name] = Ext.get(pnode.appendChild(el));
11098             }
11099             if(this[name+'CssClass']){
11100                 this[name].addClass(this[name+'CssClass']);
11101             }
11102             if(this[name+'Style']){
11103                 this[name].applyStyles(this[name+'Style']);
11104             }
11105         }
11106     },
11107
11108     // private
11109     onRender : function(ct, position){
11110         Ext.Panel.superclass.onRender.call(this, ct, position);
11111         this.createClasses();
11112
11113         var el = this.el,
11114             d = el.dom,
11115             bw,
11116             ts;
11117
11118
11119         if(this.collapsible && !this.hideCollapseTool){
11120             this.tools = this.tools ? this.tools.slice(0) : [];
11121             this.tools[this.collapseFirst?'unshift':'push']({
11122                 id: 'toggle',
11123                 handler : this.toggleCollapse,
11124                 scope: this
11125             });
11126         }
11127
11128         if(this.tools){
11129             ts = this.tools;
11130             this.elements += (this.header !== false) ? ',header' : '';
11131         }
11132         this.tools = {};
11133
11134         el.addClass(this.baseCls);
11135         if(d.firstChild){ // existing markup
11136             this.header = el.down('.'+this.headerCls);
11137             this.bwrap = el.down('.'+this.bwrapCls);
11138             var cp = this.bwrap ? this.bwrap : el;
11139             this.tbar = cp.down('.'+this.tbarCls);
11140             this.body = cp.down('.'+this.bodyCls);
11141             this.bbar = cp.down('.'+this.bbarCls);
11142             this.footer = cp.down('.'+this.footerCls);
11143             this.fromMarkup = true;
11144         }
11145         if (this.preventBodyReset === true) {
11146             el.addClass('x-panel-reset');
11147         }
11148         if(this.cls){
11149             el.addClass(this.cls);
11150         }
11151
11152         if(this.buttons){
11153             this.elements += ',footer';
11154         }
11155
11156         // This block allows for maximum flexibility and performance when using existing markup
11157
11158         // framing requires special markup
11159         if(this.frame){
11160             el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
11161
11162             this.createElement('header', d.firstChild.firstChild.firstChild);
11163             this.createElement('bwrap', d);
11164
11165             // append the mid and bottom frame to the bwrap
11166             bw = this.bwrap.dom;
11167             var ml = d.childNodes[1], bl = d.childNodes[2];
11168             bw.appendChild(ml);
11169             bw.appendChild(bl);
11170
11171             var mc = bw.firstChild.firstChild.firstChild;
11172             this.createElement('tbar', mc);
11173             this.createElement('body', mc);
11174             this.createElement('bbar', mc);
11175             this.createElement('footer', bw.lastChild.firstChild.firstChild);
11176
11177             if(!this.footer){
11178                 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
11179             }
11180             /*
11181              * Store a reference to this element so:
11182              * a) We aren't looking it up all the time
11183              * b) The last element is reported incorrectly when using a loadmask
11184              */
11185             this.ft = Ext.get(this.bwrap.dom.lastChild);
11186             this.mc = Ext.get(mc);
11187         }else{
11188             this.createElement('header', d);
11189             this.createElement('bwrap', d);
11190
11191             // append the mid and bottom frame to the bwrap
11192             bw = this.bwrap.dom;
11193             this.createElement('tbar', bw);
11194             this.createElement('body', bw);
11195             this.createElement('bbar', bw);
11196             this.createElement('footer', bw);
11197
11198             if(!this.header){
11199                 this.body.addClass(this.bodyCls + '-noheader');
11200                 if(this.tbar){
11201                     this.tbar.addClass(this.tbarCls + '-noheader');
11202                 }
11203             }
11204         }
11205
11206         if(Ext.isDefined(this.padding)){
11207             this.body.setStyle('padding', this.body.addUnits(this.padding));
11208         }
11209
11210         if(this.border === false){
11211             this.el.addClass(this.baseCls + '-noborder');
11212             this.body.addClass(this.bodyCls + '-noborder');
11213             if(this.header){
11214                 this.header.addClass(this.headerCls + '-noborder');
11215             }
11216             if(this.footer){
11217                 this.footer.addClass(this.footerCls + '-noborder');
11218             }
11219             if(this.tbar){
11220                 this.tbar.addClass(this.tbarCls + '-noborder');
11221             }
11222             if(this.bbar){
11223                 this.bbar.addClass(this.bbarCls + '-noborder');
11224             }
11225         }
11226
11227         if(this.bodyBorder === false){
11228            this.body.addClass(this.bodyCls + '-noborder');
11229         }
11230
11231         this.bwrap.enableDisplayMode('block');
11232
11233         if(this.header){
11234             this.header.unselectable();
11235
11236             // for tools, we need to wrap any existing header markup
11237             if(this.headerAsText){
11238                 this.header.dom.innerHTML =
11239                     '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
11240
11241                 if(this.iconCls){
11242                     this.setIconClass(this.iconCls);
11243                 }
11244             }
11245         }
11246
11247         if(this.floating){
11248             this.makeFloating(this.floating);
11249         }
11250
11251         if(this.collapsible && this.titleCollapse && this.header){
11252             this.mon(this.header, 'click', this.toggleCollapse, this);
11253             this.header.setStyle('cursor', 'pointer');
11254         }
11255         if(ts){
11256             this.addTool.apply(this, ts);
11257         }
11258
11259         // Render Toolbars.
11260         if(this.fbar){
11261             this.footer.addClass('x-panel-btns');
11262             this.fbar.ownerCt = this;
11263             this.fbar.render(this.footer);
11264             this.footer.createChild({cls:'x-clear'});
11265         }
11266         if(this.tbar && this.topToolbar){
11267             this.topToolbar.ownerCt = this;
11268             this.topToolbar.render(this.tbar);
11269         }
11270         if(this.bbar && this.bottomToolbar){
11271             this.bottomToolbar.ownerCt = this;
11272             this.bottomToolbar.render(this.bbar);
11273         }
11274     },
11275
11276     /**
11277      * Sets the CSS class that provides the icon image for this panel.  This method will replace any existing
11278      * icon class if one has already been set and fire the {@link #iconchange} event after completion.
11279      * @param {String} cls The new CSS class name
11280      */
11281     setIconClass : function(cls){
11282         var old = this.iconCls;
11283         this.iconCls = cls;
11284         if(this.rendered && this.header){
11285             if(this.frame){
11286                 this.header.addClass('x-panel-icon');
11287                 this.header.replaceClass(old, this.iconCls);
11288             }else{
11289                 var hd = this.header,
11290                     img = hd.child('img.x-panel-inline-icon');
11291                 if(img){
11292                     Ext.fly(img).replaceClass(old, this.iconCls);
11293                 }else{
11294                     var hdspan = hd.child('span.' + this.headerTextCls);
11295                     if (hdspan) {
11296                         Ext.DomHelper.insertBefore(hdspan.dom, {
11297                             tag:'img', alt: '', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
11298                         });
11299                     }
11300                  }
11301             }
11302         }
11303         this.fireEvent('iconchange', this, cls, old);
11304     },
11305
11306     // private
11307     makeFloating : function(cfg){
11308         this.floating = true;
11309         this.el = new Ext.Layer(Ext.apply({}, cfg, {
11310             shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
11311             shadowOffset: this.shadowOffset,
11312             constrain:false,
11313             shim: this.shim === false ? false : undefined
11314         }), this.el);
11315     },
11316
11317     /**
11318      * Returns the {@link Ext.Toolbar toolbar} from the top (<code>{@link #tbar}</code>) section of the panel.
11319      * @return {Ext.Toolbar} The toolbar
11320      */
11321     getTopToolbar : function(){
11322         return this.topToolbar;
11323     },
11324
11325     /**
11326      * Returns the {@link Ext.Toolbar toolbar} from the bottom (<code>{@link #bbar}</code>) section of the panel.
11327      * @return {Ext.Toolbar} The toolbar
11328      */
11329     getBottomToolbar : function(){
11330         return this.bottomToolbar;
11331     },
11332
11333     /**
11334      * Returns the {@link Ext.Toolbar toolbar} from the footer (<code>{@link #fbar}</code>) section of the panel.
11335      * @return {Ext.Toolbar} The toolbar
11336      */
11337     getFooterToolbar : function() {
11338         return this.fbar;
11339     },
11340
11341     /**
11342      * Adds a button to this panel.  Note that this method must be called prior to rendering.  The preferred
11343      * approach is to add buttons via the {@link #buttons} config.
11344      * @param {String/Object} config A valid {@link Ext.Button} config.  A string will become the text for a default
11345      * button config, an object will be treated as a button config object.
11346      * @param {Function} handler The function to be called on button {@link Ext.Button#click}
11347      * @param {Object} scope The scope (<code>this</code> reference) in which the button handler function is executed. Defaults to the Button.
11348      * @return {Ext.Button} The button that was added
11349      */
11350     addButton : function(config, handler, scope){
11351         if(!this.fbar){
11352             this.createFbar([]);
11353         }
11354         if(handler){
11355             if(Ext.isString(config)){
11356                 config = {text: config};
11357             }
11358             config = Ext.apply({
11359                 handler: handler,
11360                 scope: scope
11361             }, config);
11362         }
11363         return this.fbar.add(config);
11364     },
11365
11366     // private
11367     addTool : function(){
11368         if(!this.rendered){
11369             if(!this.tools){
11370                 this.tools = [];
11371             }
11372             Ext.each(arguments, function(arg){
11373                 this.tools.push(arg);
11374             }, this);
11375             return;
11376         }
11377          // nowhere to render tools!
11378         if(!this[this.toolTarget]){
11379             return;
11380         }
11381         if(!this.toolTemplate){
11382             // initialize the global tool template on first use
11383             var tt = new Ext.Template(
11384                  '<div class="x-tool x-tool-{id}">&#160;</div>'
11385             );
11386             tt.disableFormats = true;
11387             tt.compile();
11388             Ext.Panel.prototype.toolTemplate = tt;
11389         }
11390         for(var i = 0, a = arguments, len = a.length; i < len; i++) {
11391             var tc = a[i];
11392             if(!this.tools[tc.id]){
11393                 var overCls = 'x-tool-'+tc.id+'-over';
11394                 var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
11395                 this.tools[tc.id] = t;
11396                 t.enableDisplayMode('block');
11397                 this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
11398                 if(tc.on){
11399                     this.mon(t, tc.on);
11400                 }
11401                 if(tc.hidden){
11402                     t.hide();
11403                 }
11404                 if(tc.qtip){
11405                     if(Ext.isObject(tc.qtip)){
11406                         Ext.QuickTips.register(Ext.apply({
11407                               target: t.id
11408                         }, tc.qtip));
11409                     } else {
11410                         t.dom.qtip = tc.qtip;
11411                     }
11412                 }
11413                 t.addClassOnOver(overCls);
11414             }
11415         }
11416     },
11417
11418     onLayout : function(shallow, force){
11419         Ext.Panel.superclass.onLayout.apply(this, arguments);
11420         if(this.hasLayout && this.toolbars.length > 0){
11421             Ext.each(this.toolbars, function(tb){
11422                 tb.doLayout(undefined, force);
11423             });
11424             this.syncHeight();
11425         }
11426     },
11427
11428     syncHeight : function(){
11429         var h = this.toolbarHeight,
11430                 bd = this.body,
11431                 lsh = this.lastSize.height,
11432                 sz;
11433
11434         if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
11435             return;
11436         }
11437
11438
11439         if(h != this.getToolbarHeight()){
11440             h = Math.max(0, lsh - this.getFrameHeight());
11441             bd.setHeight(h);
11442             sz = bd.getSize();
11443             this.toolbarHeight = this.getToolbarHeight();
11444             this.onBodyResize(sz.width, sz.height);
11445         }
11446     },
11447
11448     // private
11449     onShow : function(){
11450         if(this.floating){
11451             return this.el.show();
11452         }
11453         Ext.Panel.superclass.onShow.call(this);
11454     },
11455
11456     // private
11457     onHide : function(){
11458         if(this.floating){
11459             return this.el.hide();
11460         }
11461         Ext.Panel.superclass.onHide.call(this);
11462     },
11463
11464     // private
11465     createToolHandler : function(t, tc, overCls, panel){
11466         return function(e){
11467             t.removeClass(overCls);
11468             if(tc.stopEvent !== false){
11469                 e.stopEvent();
11470             }
11471             if(tc.handler){
11472                 tc.handler.call(tc.scope || t, e, t, panel, tc);
11473             }
11474         };
11475     },
11476
11477     // private
11478     afterRender : function(){
11479         if(this.floating && !this.hidden){
11480             this.el.show();
11481         }
11482         if(this.title){
11483             this.setTitle(this.title);
11484         }
11485         Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
11486         if (this.collapsed) {
11487             this.collapsed = false;
11488             this.collapse(false);
11489         }
11490         this.initEvents();
11491     },
11492
11493     // private
11494     getKeyMap : function(){
11495         if(!this.keyMap){
11496             this.keyMap = new Ext.KeyMap(this.el, this.keys);
11497         }
11498         return this.keyMap;
11499     },
11500
11501     // private
11502     initEvents : function(){
11503         if(this.keys){
11504             this.getKeyMap();
11505         }
11506         if(this.draggable){
11507             this.initDraggable();
11508         }
11509         if(this.toolbars.length > 0){
11510             Ext.each(this.toolbars, function(tb){
11511                 tb.doLayout();
11512                 tb.on({
11513                     scope: this,
11514                     afterlayout: this.syncHeight,
11515                     remove: this.syncHeight
11516                 });
11517             }, this);
11518             this.syncHeight();
11519         }
11520
11521     },
11522
11523     // private
11524     initDraggable : function(){
11525         /**
11526          * <p>If this Panel is configured {@link #draggable}, this property will contain
11527          * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.</p>
11528          * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource}
11529          * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
11530          * @type Ext.dd.DragSource.
11531          * @property dd
11532          */
11533         this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
11534     },
11535
11536     // private
11537     beforeEffect : function(anim){
11538         if(this.floating){
11539             this.el.beforeAction();
11540         }
11541         if(anim !== false){
11542             this.el.addClass('x-panel-animated');
11543         }
11544     },
11545
11546     // private
11547     afterEffect : function(anim){
11548         this.syncShadow();
11549         this.el.removeClass('x-panel-animated');
11550     },
11551
11552     // private - wraps up an animation param with internal callbacks
11553     createEffect : function(a, cb, scope){
11554         var o = {
11555             scope:scope,
11556             block:true
11557         };
11558         if(a === true){
11559             o.callback = cb;
11560             return o;
11561         }else if(!a.callback){
11562             o.callback = cb;
11563         }else { // wrap it up
11564             o.callback = function(){
11565                 cb.call(scope);
11566                 Ext.callback(a.callback, a.scope);
11567             };
11568         }
11569         return Ext.applyIf(o, a);
11570     },
11571
11572     /**
11573      * Collapses the panel body so that it becomes hidden.  Fires the {@link #beforecollapse} event which will
11574      * cancel the collapse action if it returns false.
11575      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
11576      * {@link #animCollapse} panel config)
11577      * @return {Ext.Panel} this
11578      */
11579     collapse : function(animate){
11580         if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
11581             return;
11582         }
11583         var doAnim = animate === true || (animate !== false && this.animCollapse);
11584         this.beforeEffect(doAnim);
11585         this.onCollapse(doAnim, animate);
11586         return this;
11587     },
11588
11589     // private
11590     onCollapse : function(doAnim, animArg){
11591         if(doAnim){
11592             this[this.collapseEl].slideOut(this.slideAnchor,
11593                     Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
11594                         this.collapseDefaults));
11595         }else{
11596             this[this.collapseEl].hide(this.hideMode);
11597             this.afterCollapse(false);
11598         }
11599     },
11600
11601     // private
11602     afterCollapse : function(anim){
11603         this.collapsed = true;
11604         this.el.addClass(this.collapsedCls);
11605         if(anim !== false){
11606             this[this.collapseEl].hide(this.hideMode);
11607         }
11608         this.afterEffect(anim);
11609
11610         // Reset lastSize of all sub-components so they KNOW they are in a collapsed container
11611         this.cascade(function(c) {
11612             if (c.lastSize) {
11613                 c.lastSize = { width: undefined, height: undefined };
11614             }
11615         });
11616         this.fireEvent('collapse', this);
11617     },
11618
11619     /**
11620      * Expands the panel body so that it becomes visible.  Fires the {@link #beforeexpand} event which will
11621      * cancel the expand action if it returns false.
11622      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
11623      * {@link #animCollapse} panel config)
11624      * @return {Ext.Panel} this
11625      */
11626     expand : function(animate){
11627         if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
11628             return;
11629         }
11630         var doAnim = animate === true || (animate !== false && this.animCollapse);
11631         this.el.removeClass(this.collapsedCls);
11632         this.beforeEffect(doAnim);
11633         this.onExpand(doAnim, animate);
11634         return this;
11635     },
11636
11637     // private
11638     onExpand : function(doAnim, animArg){
11639         if(doAnim){
11640             this[this.collapseEl].slideIn(this.slideAnchor,
11641                     Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
11642                         this.expandDefaults));
11643         }else{
11644             this[this.collapseEl].show(this.hideMode);
11645             this.afterExpand(false);
11646         }
11647     },
11648
11649     // private
11650     afterExpand : function(anim){
11651         this.collapsed = false;
11652         if(anim !== false){
11653             this[this.collapseEl].show(this.hideMode);
11654         }
11655         this.afterEffect(anim);
11656         if (this.deferLayout) {
11657             delete this.deferLayout;
11658             this.doLayout(true);
11659         }
11660         this.fireEvent('expand', this);
11661     },
11662
11663     /**
11664      * Shortcut for performing an {@link #expand} or {@link #collapse} based on the current state of the panel.
11665      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
11666      * {@link #animCollapse} panel config)
11667      * @return {Ext.Panel} this
11668      */
11669     toggleCollapse : function(animate){
11670         this[this.collapsed ? 'expand' : 'collapse'](animate);
11671         return this;
11672     },
11673
11674     // private
11675     onDisable : function(){
11676         if(this.rendered && this.maskDisabled){
11677             this.el.mask();
11678         }
11679         Ext.Panel.superclass.onDisable.call(this);
11680     },
11681
11682     // private
11683     onEnable : function(){
11684         if(this.rendered && this.maskDisabled){
11685             this.el.unmask();
11686         }
11687         Ext.Panel.superclass.onEnable.call(this);
11688     },
11689
11690     // private
11691     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
11692         var w = adjWidth,
11693             h = adjHeight;
11694
11695         if(Ext.isDefined(w) || Ext.isDefined(h)){
11696             if(!this.collapsed){
11697                 // First, set the the Panel's body width.
11698                 // If we have auto-widthed it, get the resulting full offset width so we can size the Toolbars to match
11699                 // The Toolbars must not buffer this resize operation because we need to know their heights.
11700
11701                 if(Ext.isNumber(w)){
11702                     this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
11703                 } else if (w == 'auto') {
11704                     w = this.body.setWidth('auto').dom.offsetWidth;
11705                 } else {
11706                     w = this.body.dom.offsetWidth;
11707                 }
11708
11709                 if(this.tbar){
11710                     this.tbar.setWidth(w);
11711                     if(this.topToolbar){
11712                         this.topToolbar.setSize(w);
11713                     }
11714                 }
11715                 if(this.bbar){
11716                     this.bbar.setWidth(w);
11717                     if(this.bottomToolbar){
11718                         this.bottomToolbar.setSize(w);
11719                         // The bbar does not move on resize without this.
11720                         if (Ext.isIE) {
11721                             this.bbar.setStyle('position', 'static');
11722                             this.bbar.setStyle('position', '');
11723                         }
11724                     }
11725                 }
11726                 if(this.footer){
11727                     this.footer.setWidth(w);
11728                     if(this.fbar){
11729                         this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
11730                     }
11731                 }
11732
11733                 // At this point, the Toolbars must be layed out for getFrameHeight to find a result.
11734                 if(Ext.isNumber(h)){
11735                     h = Math.max(0, h - this.getFrameHeight());
11736                     //h = Math.max(0, h - (this.getHeight() - this.body.getHeight()));
11737                     this.body.setHeight(h);
11738                 }else if(h == 'auto'){
11739                     this.body.setHeight(h);
11740                 }
11741
11742                 if(this.disabled && this.el._mask){
11743                     this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
11744                 }
11745             }else{
11746                 // Adds an event to set the correct height afterExpand.  This accounts for the deferHeight flag in panel
11747                 this.queuedBodySize = {width: w, height: h};
11748                 if(!this.queuedExpand && this.allowQueuedExpand !== false){
11749                     this.queuedExpand = true;
11750                     this.on('expand', function(){
11751                         delete this.queuedExpand;
11752                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
11753                     }, this, {single:true});
11754                 }
11755             }
11756             this.onBodyResize(w, h);
11757         }
11758         this.syncShadow();
11759         Ext.Panel.superclass.onResize.call(this, adjWidth, adjHeight, rawWidth, rawHeight);
11760
11761     },
11762
11763     // private
11764     onBodyResize: function(w, h){
11765         this.fireEvent('bodyresize', this, w, h);
11766     },
11767
11768     // private
11769     getToolbarHeight: function(){
11770         var h = 0;
11771         if(this.rendered){
11772             Ext.each(this.toolbars, function(tb){
11773                 h += tb.getHeight();
11774             }, this);
11775         }
11776         return h;
11777     },
11778
11779     // deprecate
11780     adjustBodyHeight : function(h){
11781         return h;
11782     },
11783
11784     // private
11785     adjustBodyWidth : function(w){
11786         return w;
11787     },
11788
11789     // private
11790     onPosition : function(){
11791         this.syncShadow();
11792     },
11793
11794     /**
11795      * Returns the width in pixels of the framing elements of this panel (not including the body width).  To
11796      * retrieve the body width see {@link #getInnerWidth}.
11797      * @return {Number} The frame width
11798      */
11799     getFrameWidth : function(){
11800         var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
11801
11802         if(this.frame){
11803             var l = this.bwrap.dom.firstChild;
11804             w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
11805             w += this.mc.getFrameWidth('lr');
11806         }
11807         return w;
11808     },
11809
11810     /**
11811      * Returns the height in pixels of the framing elements of this panel (including any top and bottom bars and
11812      * header and footer elements, but not including the body height).  To retrieve the body height see {@link #getInnerHeight}.
11813      * @return {Number} The frame height
11814      */
11815     getFrameHeight : function() {
11816         var h  = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
11817         h += (this.tbar ? this.tbar.getHeight() : 0) +
11818              (this.bbar ? this.bbar.getHeight() : 0);
11819
11820         if(this.frame){
11821             h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
11822         }else{
11823             h += (this.header ? this.header.getHeight() : 0) +
11824                 (this.footer ? this.footer.getHeight() : 0);
11825         }
11826         return h;
11827     },
11828
11829     /**
11830      * Returns the width in pixels of the body element (not including the width of any framing elements).
11831      * For the frame width see {@link #getFrameWidth}.
11832      * @return {Number} The body width
11833      */
11834     getInnerWidth : function(){
11835         return this.getSize().width - this.getFrameWidth();
11836     },
11837
11838     /**
11839      * Returns the height in pixels of the body element (not including the height of any framing elements).
11840      * For the frame height see {@link #getFrameHeight}.
11841      * @return {Number} The body height
11842      */
11843     getInnerHeight : function(){
11844         return this.body.getHeight();
11845         /* Deprecate
11846             return this.getSize().height - this.getFrameHeight();
11847         */
11848     },
11849
11850     // private
11851     syncShadow : function(){
11852         if(this.floating){
11853             this.el.sync(true);
11854         }
11855     },
11856
11857     // private
11858     getLayoutTarget : function(){
11859         return this.body;
11860     },
11861
11862     // private
11863     getContentTarget : function(){
11864         return this.body;
11865     },
11866
11867     /**
11868      * <p>Sets the title text for the panel and optionally the {@link #iconCls icon class}.</p>
11869      * <p>In order to be able to set the title, a header element must have been created
11870      * for the Panel. This is triggered either by configuring the Panel with a non-blank <code>{@link #title}</code>,
11871      * or configuring it with <code><b>{@link #header}: true</b></code>.</p>
11872      * @param {String} title The title text to set
11873      * @param {String} iconCls (optional) {@link #iconCls iconCls} A user-defined CSS class that provides the icon image for this panel
11874      */
11875     setTitle : function(title, iconCls){
11876         this.title = title;
11877         if(this.header && this.headerAsText){
11878             this.header.child('span').update(title);
11879         }
11880         if(iconCls){
11881             this.setIconClass(iconCls);
11882         }
11883         this.fireEvent('titlechange', this, title);
11884         return this;
11885     },
11886
11887     /**
11888      * Get the {@link Ext.Updater} for this panel. Enables you to perform Ajax updates of this panel's body.
11889      * @return {Ext.Updater} The Updater
11890      */
11891     getUpdater : function(){
11892         return this.body.getUpdater();
11893     },
11894
11895      /**
11896      * Loads this content panel immediately with content returned from an XHR call.
11897      * @param {Object/String/Function} config A config object containing any of the following options:
11898 <pre><code>
11899 panel.load({
11900     url: 'your-url.php',
11901     params: {param1: 'foo', param2: 'bar'}, // or a URL encoded string
11902     callback: yourFunction,
11903     scope: yourObject, // optional scope for the callback
11904     discardUrl: false,
11905     nocache: false,
11906     text: 'Loading...',
11907     timeout: 30,
11908     scripts: false
11909 });
11910 </code></pre>
11911      * The only required property is url. The optional properties nocache, text and scripts
11912      * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their
11913      * associated property on this panel Updater instance.
11914      * @return {Ext.Panel} this
11915      */
11916     load : function(){
11917         var um = this.body.getUpdater();
11918         um.update.apply(um, arguments);
11919         return this;
11920     },
11921
11922     // private
11923     beforeDestroy : function(){
11924         Ext.Panel.superclass.beforeDestroy.call(this);
11925         if(this.header){
11926             this.header.removeAllListeners();
11927         }
11928         if(this.tools){
11929             for(var k in this.tools){
11930                 Ext.destroy(this.tools[k]);
11931             }
11932         }
11933         if(this.toolbars.length > 0){
11934             Ext.each(this.toolbars, function(tb){
11935                 tb.un('afterlayout', this.syncHeight, this);
11936                 tb.un('remove', this.syncHeight, this);
11937             }, this);
11938         }
11939         if(Ext.isArray(this.buttons)){
11940             while(this.buttons.length) {
11941                 Ext.destroy(this.buttons[0]);
11942             }
11943         }
11944         if(this.rendered){
11945             Ext.destroy(
11946                 this.ft,
11947                 this.header,
11948                 this.footer,
11949                 this.tbar,
11950                 this.bbar,
11951                 this.body,
11952                 this.mc,
11953                 this.bwrap,
11954                 this.dd
11955             );
11956             if (this.fbar) {
11957                 Ext.destroy(
11958                     this.fbar,
11959                     this.fbar.el
11960                 );
11961             }
11962         }
11963         Ext.destroy(this.toolbars);
11964     },
11965
11966     // private
11967     createClasses : function(){
11968         this.headerCls = this.baseCls + '-header';
11969         this.headerTextCls = this.baseCls + '-header-text';
11970         this.bwrapCls = this.baseCls + '-bwrap';
11971         this.tbarCls = this.baseCls + '-tbar';
11972         this.bodyCls = this.baseCls + '-body';
11973         this.bbarCls = this.baseCls + '-bbar';
11974         this.footerCls = this.baseCls + '-footer';
11975     },
11976
11977     // private
11978     createGhost : function(cls, useShim, appendTo){
11979         var el = document.createElement('div');
11980         el.className = 'x-panel-ghost ' + (cls ? cls : '');
11981         if(this.header){
11982             el.appendChild(this.el.dom.firstChild.cloneNode(true));
11983         }
11984         Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
11985         el.style.width = this.el.dom.offsetWidth + 'px';;
11986         if(!appendTo){
11987             this.container.dom.appendChild(el);
11988         }else{
11989             Ext.getDom(appendTo).appendChild(el);
11990         }
11991         if(useShim !== false && this.el.useShim !== false){
11992             var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
11993             layer.show();
11994             return layer;
11995         }else{
11996             return new Ext.Element(el);
11997         }
11998     },
11999
12000     // private
12001     doAutoLoad : function(){
12002         var u = this.body.getUpdater();
12003         if(this.renderer){
12004             u.setRenderer(this.renderer);
12005         }
12006         u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
12007     },
12008
12009     /**
12010      * Retrieve a tool by id.
12011      * @param {String} id
12012      * @return {Object} tool
12013      */
12014     getTool : function(id) {
12015         return this.tools[id];
12016     }
12017
12018 /**
12019  * @cfg {String} autoEl @hide
12020  */
12021 });
12022 Ext.reg('panel', Ext.Panel);
12023 /**
12024  * @class Ext.Editor
12025  * @extends Ext.Component
12026  * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
12027  * @constructor
12028  * Create a new Editor
12029  * @param {Object} config The config object
12030  * @xtype editor
12031  */
12032 Ext.Editor = function(field, config){
12033     if(field.field){
12034         this.field = Ext.create(field.field, 'textfield');
12035         config = Ext.apply({}, field); // copy so we don't disturb original config
12036         delete config.field;
12037     }else{
12038         this.field = field;
12039     }
12040     Ext.Editor.superclass.constructor.call(this, config);
12041 };
12042
12043 Ext.extend(Ext.Editor, Ext.Component, {
12044     /**
12045     * @cfg {Ext.form.Field} field
12046     * The Field object (or descendant) or config object for field
12047     */
12048     /**
12049      * @cfg {Boolean} allowBlur
12050      * True to {@link #completeEdit complete the editing process} if in edit mode when the
12051      * field is blurred. Defaults to <tt>true</tt>.
12052      */
12053     allowBlur: true,
12054     /**
12055      * @cfg {Boolean/String} autoSize
12056      * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only,
12057      * or "height" to adopt the height only, "none" to always use the field dimensions. (defaults to false)
12058      */
12059     /**
12060      * @cfg {Boolean} revertInvalid
12061      * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
12062      * validation fails (defaults to true)
12063      */
12064     /**
12065      * @cfg {Boolean} ignoreNoChange
12066      * True to skip the edit completion process (no save, no events fired) if the user completes an edit and
12067      * the value has not changed (defaults to false).  Applies only to string values - edits for other data types
12068      * will never be ignored.
12069      */
12070     /**
12071      * @cfg {Boolean} hideEl
12072      * False to keep the bound element visible while the editor is displayed (defaults to true)
12073      */
12074     /**
12075      * @cfg {Mixed} value
12076      * The data value of the underlying field (defaults to "")
12077      */
12078     value : "",
12079     /**
12080      * @cfg {String} alignment
12081      * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?").
12082      */
12083     alignment: "c-c?",
12084     /**
12085      * @cfg {Array} offsets
12086      * The offsets to use when aligning (see {@link Ext.Element#alignTo} for more details. Defaults to <tt>[0, 0]</tt>.
12087      */
12088     offsets: [0, 0],
12089     /**
12090      * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
12091      * for bottom-right shadow (defaults to "frame")
12092      */
12093     shadow : "frame",
12094     /**
12095      * @cfg {Boolean} constrain True to constrain the editor to the viewport
12096      */
12097     constrain : false,
12098     /**
12099      * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true)
12100      */
12101     swallowKeys : true,
12102     /**
12103      * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed. Defaults to <tt>true</tt>.
12104      */
12105     completeOnEnter : true,
12106     /**
12107      * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed. Defaults to <tt>true</tt>.
12108      */
12109     cancelOnEsc : true,
12110     /**
12111      * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
12112      */
12113     updateEl : false,
12114
12115     initComponent : function(){
12116         Ext.Editor.superclass.initComponent.call(this);
12117         this.addEvents(
12118             /**
12119              * @event beforestartedit
12120              * Fires when editing is initiated, but before the value changes.  Editing can be canceled by returning
12121              * false from the handler of this event.
12122              * @param {Editor} this
12123              * @param {Ext.Element} boundEl The underlying element bound to this editor
12124              * @param {Mixed} value The field value being set
12125              */
12126             "beforestartedit",
12127             /**
12128              * @event startedit
12129              * Fires when this editor is displayed
12130              * @param {Ext.Element} boundEl The underlying element bound to this editor
12131              * @param {Mixed} value The starting field value
12132              */
12133             "startedit",
12134             /**
12135              * @event beforecomplete
12136              * Fires after a change has been made to the field, but before the change is reflected in the underlying
12137              * field.  Saving the change to the field can be canceled by returning false from the handler of this event.
12138              * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
12139              * event will not fire since no edit actually occurred.
12140              * @param {Editor} this
12141              * @param {Mixed} value The current field value
12142              * @param {Mixed} startValue The original field value
12143              */
12144             "beforecomplete",
12145             /**
12146              * @event complete
12147              * Fires after editing is complete and any changed value has been written to the underlying field.
12148              * @param {Editor} this
12149              * @param {Mixed} value The current field value
12150              * @param {Mixed} startValue The original field value
12151              */
12152             "complete",
12153             /**
12154              * @event canceledit
12155              * Fires after editing has been canceled and the editor's value has been reset.
12156              * @param {Editor} this
12157              * @param {Mixed} value The user-entered field value that was discarded
12158              * @param {Mixed} startValue The original field value that was set back into the editor after cancel
12159              */
12160             "canceledit",
12161             /**
12162              * @event specialkey
12163              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
12164              * {@link Ext.EventObject#getKey} to determine which key was pressed.
12165              * @param {Ext.form.Field} this
12166              * @param {Ext.EventObject} e The event object
12167              */
12168             "specialkey"
12169         );
12170     },
12171
12172     // private
12173     onRender : function(ct, position){
12174         this.el = new Ext.Layer({
12175             shadow: this.shadow,
12176             cls: "x-editor",
12177             parentEl : ct,
12178             shim : this.shim,
12179             shadowOffset: this.shadowOffset || 4,
12180             id: this.id,
12181             constrain: this.constrain
12182         });
12183         if(this.zIndex){
12184             this.el.setZIndex(this.zIndex);
12185         }
12186         this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
12187         if(this.field.msgTarget != 'title'){
12188             this.field.msgTarget = 'qtip';
12189         }
12190         this.field.inEditor = true;
12191         this.mon(this.field, {
12192             scope: this,
12193             blur: this.onBlur,
12194             specialkey: this.onSpecialKey
12195         });
12196         if(this.field.grow){
12197             this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
12198         }
12199         this.field.render(this.el).show();
12200         this.field.getEl().dom.name = '';
12201         if(this.swallowKeys){
12202             this.field.el.swallowEvent([
12203                 'keypress', // *** Opera
12204                 'keydown'   // *** all other browsers
12205             ]);
12206         }
12207     },
12208
12209     // private
12210     onSpecialKey : function(field, e){
12211         var key = e.getKey(),
12212             complete = this.completeOnEnter && key == e.ENTER,
12213             cancel = this.cancelOnEsc && key == e.ESC;
12214         if(complete || cancel){
12215             e.stopEvent();
12216             if(complete){
12217                 this.completeEdit();
12218             }else{
12219                 this.cancelEdit();
12220             }
12221             if(field.triggerBlur){
12222                 field.triggerBlur();
12223             }
12224         }
12225         this.fireEvent('specialkey', field, e);
12226     },
12227
12228     /**
12229      * Starts the editing process and shows the editor.
12230      * @param {Mixed} el The element to edit
12231      * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
12232       * to the innerHTML of el.
12233      */
12234     startEdit : function(el, value){
12235         if(this.editing){
12236             this.completeEdit();
12237         }
12238         this.boundEl = Ext.get(el);
12239         var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
12240         if(!this.rendered){
12241             this.render(this.parentEl || document.body);
12242         }
12243         if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
12244             this.startValue = v;
12245             this.field.reset();
12246             this.field.setValue(v);
12247             this.realign(true);
12248             this.editing = true;
12249             this.show();
12250         }
12251     },
12252
12253     // private
12254     doAutoSize : function(){
12255         if(this.autoSize){
12256             var sz = this.boundEl.getSize(),
12257                 fs = this.field.getSize();
12258
12259             switch(this.autoSize){
12260                 case "width":
12261                     this.setSize(sz.width, fs.height);
12262                     break;
12263                 case "height":
12264                     this.setSize(fs.width, sz.height);
12265                     break;
12266                 case "none":
12267                     this.setSize(fs.width, fs.height);
12268                     break;
12269                 default:
12270                     this.setSize(sz.width, sz.height);
12271             }
12272         }
12273     },
12274
12275     /**
12276      * Sets the height and width of this editor.
12277      * @param {Number} width The new width
12278      * @param {Number} height The new height
12279      */
12280     setSize : function(w, h){
12281         delete this.field.lastSize;
12282         this.field.setSize(w, h);
12283         if(this.el){
12284             // IE7 in strict mode doesn't size properly.
12285             if(Ext.isGecko2 || Ext.isOpera || (Ext.isIE7 && Ext.isStrict)){
12286                 // prevent layer scrollbars
12287                 this.el.setSize(w, h);
12288             }
12289             this.el.sync();
12290         }
12291     },
12292
12293     /**
12294      * Realigns the editor to the bound field based on the current alignment config value.
12295      * @param {Boolean} autoSize (optional) True to size the field to the dimensions of the bound element.
12296      */
12297     realign : function(autoSize){
12298         if(autoSize === true){
12299             this.doAutoSize();
12300         }
12301         this.el.alignTo(this.boundEl, this.alignment, this.offsets);
12302     },
12303
12304     /**
12305      * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
12306      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
12307      */
12308     completeEdit : function(remainVisible){
12309         if(!this.editing){
12310             return;
12311         }
12312         // Assert combo values first
12313         if (this.field.assertValue) {
12314             this.field.assertValue();
12315         }
12316         var v = this.getValue();
12317         if(!this.field.isValid()){
12318             if(this.revertInvalid !== false){
12319                 this.cancelEdit(remainVisible);
12320             }
12321             return;
12322         }
12323         if(String(v) === String(this.startValue) && this.ignoreNoChange){
12324             this.hideEdit(remainVisible);
12325             return;
12326         }
12327         if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
12328             v = this.getValue();
12329             if(this.updateEl && this.boundEl){
12330                 this.boundEl.update(v);
12331             }
12332             this.hideEdit(remainVisible);
12333             this.fireEvent("complete", this, v, this.startValue);
12334         }
12335     },
12336
12337     // private
12338     onShow : function(){
12339         this.el.show();
12340         if(this.hideEl !== false){
12341             this.boundEl.hide();
12342         }
12343         this.field.show().focus(false, true);
12344         this.fireEvent("startedit", this.boundEl, this.startValue);
12345     },
12346
12347     /**
12348      * Cancels the editing process and hides the editor without persisting any changes.  The field value will be
12349      * reverted to the original starting value.
12350      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
12351      * cancel (defaults to false)
12352      */
12353     cancelEdit : function(remainVisible){
12354         if(this.editing){
12355             var v = this.getValue();
12356             this.setValue(this.startValue);
12357             this.hideEdit(remainVisible);
12358             this.fireEvent("canceledit", this, v, this.startValue);
12359         }
12360     },
12361
12362     // private
12363     hideEdit: function(remainVisible){
12364         if(remainVisible !== true){
12365             this.editing = false;
12366             this.hide();
12367         }
12368     },
12369
12370     // private
12371     onBlur : function(){
12372         // selectSameEditor flag allows the same editor to be started without onBlur firing on itself
12373         if(this.allowBlur === true && this.editing && this.selectSameEditor !== true){
12374             this.completeEdit();
12375         }
12376     },
12377
12378     // private
12379     onHide : function(){
12380         if(this.editing){
12381             this.completeEdit();
12382             return;
12383         }
12384         this.field.blur();
12385         if(this.field.collapse){
12386             this.field.collapse();
12387         }
12388         this.el.hide();
12389         if(this.hideEl !== false){
12390             this.boundEl.show();
12391         }
12392     },
12393
12394     /**
12395      * Sets the data value of the editor
12396      * @param {Mixed} value Any valid value supported by the underlying field
12397      */
12398     setValue : function(v){
12399         this.field.setValue(v);
12400     },
12401
12402     /**
12403      * Gets the data value of the editor
12404      * @return {Mixed} The data value
12405      */
12406     getValue : function(){
12407         return this.field.getValue();
12408     },
12409
12410     beforeDestroy : function(){
12411         Ext.destroyMembers(this, 'field');
12412
12413         delete this.parentEl;
12414         delete this.boundEl;
12415     }
12416 });
12417 Ext.reg('editor', Ext.Editor);
12418 /**
12419  * @class Ext.ColorPalette
12420  * @extends Ext.Component
12421  * Simple color palette class for choosing colors.  The palette can be rendered to any container.<br />
12422  * Here's an example of typical usage:
12423  * <pre><code>
12424 var cp = new Ext.ColorPalette({value:'993300'});  // initial selected color
12425 cp.render('my-div');
12426
12427 cp.on('select', function(palette, selColor){
12428     // do something with selColor
12429 });
12430 </code></pre>
12431  * @constructor
12432  * Create a new ColorPalette
12433  * @param {Object} config The config object
12434  * @xtype colorpalette
12435  */
12436 Ext.ColorPalette = Ext.extend(Ext.Component, {
12437         /**
12438          * @cfg {String} tpl An existing XTemplate instance to be used in place of the default template for rendering the component.
12439          */
12440     /**
12441      * @cfg {String} itemCls
12442      * The CSS class to apply to the containing element (defaults to 'x-color-palette')
12443      */
12444     itemCls : 'x-color-palette',
12445     /**
12446      * @cfg {String} value
12447      * The initial color to highlight (should be a valid 6-digit color hex code without the # symbol).  Note that
12448      * the hex codes are case-sensitive.
12449      */
12450     value : null,
12451     /**
12452      * @cfg {String} clickEvent
12453      * The DOM event that will cause a color to be selected. This can be any valid event name (dblclick, contextmenu). 
12454      * Defaults to <tt>'click'</tt>.
12455      */
12456     clickEvent :'click',
12457     // private
12458     ctype : 'Ext.ColorPalette',
12459
12460     /**
12461      * @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the {@link #select} event
12462      */
12463     allowReselect : false,
12464
12465     /**
12466      * <p>An array of 6-digit color hex code strings (without the # symbol).  This array can contain any number
12467      * of colors, and each hex code should be unique.  The width of the palette is controlled via CSS by adjusting
12468      * the width property of the 'x-color-palette' class (or assigning a custom class), so you can balance the number
12469      * of colors with the width setting until the box is symmetrical.</p>
12470      * <p>You can override individual colors if needed:</p>
12471      * <pre><code>
12472 var cp = new Ext.ColorPalette();
12473 cp.colors[0] = 'FF0000';  // change the first box to red
12474 </code></pre>
12475
12476 Or you can provide a custom array of your own for complete control:
12477 <pre><code>
12478 var cp = new Ext.ColorPalette();
12479 cp.colors = ['000000', '993300', '333300'];
12480 </code></pre>
12481      * @type Array
12482      */
12483     colors : [
12484         '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
12485         '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
12486         'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
12487         'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
12488         'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
12489     ],
12490
12491     /**
12492      * @cfg {Function} handler
12493      * Optional. A function that will handle the select event of this palette.
12494      * The handler is passed the following parameters:<div class="mdetail-params"><ul>
12495      * <li><code>palette</code> : ColorPalette<div class="sub-desc">The {@link #palette Ext.ColorPalette}.</div></li>
12496      * <li><code>color</code> : String<div class="sub-desc">The 6-digit color hex code (without the # symbol).</div></li>
12497      * </ul></div>
12498      */
12499     /**
12500      * @cfg {Object} scope
12501      * The scope (<tt><b>this</b></tt> reference) in which the <code>{@link #handler}</code>
12502      * function will be called.  Defaults to this ColorPalette instance.
12503      */
12504     
12505     // private
12506     initComponent : function(){
12507         Ext.ColorPalette.superclass.initComponent.call(this);
12508         this.addEvents(
12509             /**
12510              * @event select
12511              * Fires when a color is selected
12512              * @param {ColorPalette} this
12513              * @param {String} color The 6-digit color hex code (without the # symbol)
12514              */
12515             'select'
12516         );
12517
12518         if(this.handler){
12519             this.on('select', this.handler, this.scope, true);
12520         }    
12521     },
12522
12523     // private
12524     onRender : function(container, position){
12525         this.autoEl = {
12526             tag: 'div',
12527             cls: this.itemCls
12528         };
12529         Ext.ColorPalette.superclass.onRender.call(this, container, position);
12530         var t = this.tpl || new Ext.XTemplate(
12531             '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
12532         );
12533         t.overwrite(this.el, this.colors);
12534         this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
12535         if(this.clickEvent != 'click'){
12536                 this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
12537         }
12538     },
12539
12540     // private
12541     afterRender : function(){
12542         Ext.ColorPalette.superclass.afterRender.call(this);
12543         if(this.value){
12544             var s = this.value;
12545             this.value = null;
12546             this.select(s, true);
12547         }
12548     },
12549
12550     // private
12551     handleClick : function(e, t){
12552         e.preventDefault();
12553         if(!this.disabled){
12554             var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
12555             this.select(c.toUpperCase());
12556         }
12557     },
12558
12559     /**
12560      * Selects the specified color in the palette (fires the {@link #select} event)
12561      * @param {String} color A valid 6-digit color hex code (# will be stripped if included)
12562      * @param {Boolean} suppressEvent (optional) True to stop the select event from firing. Defaults to <tt>false</tt>.
12563      */
12564     select : function(color, suppressEvent){
12565         color = color.replace('#', '');
12566         if(color != this.value || this.allowReselect){
12567             var el = this.el;
12568             if(this.value){
12569                 el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
12570             }
12571             el.child('a.color-'+color).addClass('x-color-palette-sel');
12572             this.value = color;
12573             if(suppressEvent !== true){
12574                 this.fireEvent('select', this, color);
12575             }
12576         }
12577     }
12578
12579     /**
12580      * @cfg {String} autoEl @hide
12581      */
12582 });
12583 Ext.reg('colorpalette', Ext.ColorPalette);/**
12584  * @class Ext.DatePicker
12585  * @extends Ext.Component
12586  * <p>A popup date picker. This class is used by the {@link Ext.form.DateField DateField} class
12587  * to allow browsing and selection of valid dates.</p>
12588  * <p>All the string values documented below may be overridden by including an Ext locale file in
12589  * your page.</p>
12590  * @constructor
12591  * Create a new DatePicker
12592  * @param {Object} config The config object
12593  * @xtype datepicker
12594  */
12595 Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
12596     /**
12597      * @cfg {String} todayText
12598      * The text to display on the button that selects the current date (defaults to <code>'Today'</code>)
12599      */
12600     todayText : 'Today',
12601     /**
12602      * @cfg {String} okText
12603      * The text to display on the ok button (defaults to <code>'&#160;OK&#160;'</code> to give the user extra clicking room)
12604      */
12605     okText : '&#160;OK&#160;',
12606     /**
12607      * @cfg {String} cancelText
12608      * The text to display on the cancel button (defaults to <code>'Cancel'</code>)
12609      */
12610     cancelText : 'Cancel',
12611     /**
12612      * @cfg {Function} handler
12613      * Optional. A function that will handle the select event of this picker.
12614      * The handler is passed the following parameters:<div class="mdetail-params"><ul>
12615      * <li><code>picker</code> : DatePicker<div class="sub-desc">This DatePicker.</div></li>
12616      * <li><code>date</code> : Date<div class="sub-desc">The selected date.</div></li>
12617      * </ul></div>
12618      */
12619     /**
12620      * @cfg {Object} scope
12621      * The scope (<code><b>this</b></code> reference) in which the <code>{@link #handler}</code>
12622      * function will be called.  Defaults to this DatePicker instance.
12623      */
12624     /**
12625      * @cfg {String} todayTip
12626      * A string used to format the message for displaying in a tooltip over the button that
12627      * selects the current date. Defaults to <code>'{0} (Spacebar)'</code> where
12628      * the <code>{0}</code> token is replaced by today's date.
12629      */
12630     todayTip : '{0} (Spacebar)',
12631     /**
12632      * @cfg {String} minText
12633      * The error text to display if the minDate validation fails (defaults to <code>'This date is before the minimum date'</code>)
12634      */
12635     minText : 'This date is before the minimum date',
12636     /**
12637      * @cfg {String} maxText
12638      * The error text to display if the maxDate validation fails (defaults to <code>'This date is after the maximum date'</code>)
12639      */
12640     maxText : 'This date is after the maximum date',
12641     /**
12642      * @cfg {String} format
12643      * The default date format string which can be overriden for localization support.  The format must be
12644      * valid according to {@link Date#parseDate} (defaults to <code>'m/d/y'</code>).
12645      */
12646     format : 'm/d/y',
12647     /**
12648      * @cfg {String} disabledDaysText
12649      * The tooltip to display when the date falls on a disabled day (defaults to <code>'Disabled'</code>)
12650      */
12651     disabledDaysText : 'Disabled',
12652     /**
12653      * @cfg {String} disabledDatesText
12654      * The tooltip text to display when the date falls on a disabled date (defaults to <code>'Disabled'</code>)
12655      */
12656     disabledDatesText : 'Disabled',
12657     /**
12658      * @cfg {Array} monthNames
12659      * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
12660      */
12661     monthNames : Date.monthNames,
12662     /**
12663      * @cfg {Array} dayNames
12664      * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
12665      */
12666     dayNames : Date.dayNames,
12667     /**
12668      * @cfg {String} nextText
12669      * The next month navigation button tooltip (defaults to <code>'Next Month (Control+Right)'</code>)
12670      */
12671     nextText : 'Next Month (Control+Right)',
12672     /**
12673      * @cfg {String} prevText
12674      * The previous month navigation button tooltip (defaults to <code>'Previous Month (Control+Left)'</code>)
12675      */
12676     prevText : 'Previous Month (Control+Left)',
12677     /**
12678      * @cfg {String} monthYearText
12679      * The header month selector tooltip (defaults to <code>'Choose a month (Control+Up/Down to move years)'</code>)
12680      */
12681     monthYearText : 'Choose a month (Control+Up/Down to move years)',
12682     /**
12683      * @cfg {Number} startDay
12684      * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
12685      */
12686     startDay : 0,
12687     /**
12688      * @cfg {Boolean} showToday
12689      * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar
12690      * that selects the current date (defaults to <code>true</code>).
12691      */
12692     showToday : true,
12693     /**
12694      * @cfg {Date} minDate
12695      * Minimum allowable date (JavaScript date object, defaults to null)
12696      */
12697     /**
12698      * @cfg {Date} maxDate
12699      * Maximum allowable date (JavaScript date object, defaults to null)
12700      */
12701     /**
12702      * @cfg {Array} disabledDays
12703      * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
12704      */
12705     /**
12706      * @cfg {RegExp} disabledDatesRE
12707      * JavaScript regular expression used to disable a pattern of dates (defaults to null).  The {@link #disabledDates}
12708      * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the
12709      * disabledDates value.
12710      */
12711     /**
12712      * @cfg {Array} disabledDates
12713      * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular
12714      * expression so they are very powerful. Some examples:
12715      * <ul>
12716      * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>
12717      * <li>['03/08', '09/16'] would disable those days for every year</li>
12718      * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>
12719      * <li>['03/../2006'] would disable every day in March 2006</li>
12720      * <li>['^03'] would disable every day in every March</li>
12721      * </ul>
12722      * Note that the format of the dates included in the array should exactly match the {@link #format} config.
12723      * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to
12724      * escape the dot when restricting dates. For example: ['03\\.08\\.03'].
12725      */
12726
12727     // private
12728     // Set by other components to stop the picker focus being updated when the value changes.
12729     focusOnSelect: true,
12730
12731     // default value used to initialise each date in the DatePicker
12732     // (note: 12 noon was chosen because it steers well clear of all DST timezone changes)
12733     initHour: 12, // 24-hour format
12734
12735     // private
12736     initComponent : function(){
12737         Ext.DatePicker.superclass.initComponent.call(this);
12738
12739         this.value = this.value ?
12740                  this.value.clearTime(true) : new Date().clearTime();
12741
12742         this.addEvents(
12743             /**
12744              * @event select
12745              * Fires when a date is selected
12746              * @param {DatePicker} this DatePicker
12747              * @param {Date} date The selected date
12748              */
12749             'select'
12750         );
12751
12752         if(this.handler){
12753             this.on('select', this.handler,  this.scope || this);
12754         }
12755
12756         this.initDisabledDays();
12757     },
12758
12759     // private
12760     initDisabledDays : function(){
12761         if(!this.disabledDatesRE && this.disabledDates){
12762             var dd = this.disabledDates,
12763                 len = dd.length - 1,
12764                 re = '(?:';
12765
12766             Ext.each(dd, function(d, i){
12767                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
12768                 if(i != len){
12769                     re += '|';
12770                 }
12771             }, this);
12772             this.disabledDatesRE = new RegExp(re + ')');
12773         }
12774     },
12775
12776     /**
12777      * Replaces any existing disabled dates with new values and refreshes the DatePicker.
12778      * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config
12779      * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.
12780      */
12781     setDisabledDates : function(dd){
12782         if(Ext.isArray(dd)){
12783             this.disabledDates = dd;
12784             this.disabledDatesRE = null;
12785         }else{
12786             this.disabledDatesRE = dd;
12787         }
12788         this.initDisabledDays();
12789         this.update(this.value, true);
12790     },
12791
12792     /**
12793      * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.
12794      * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config
12795      * for details on supported values.
12796      */
12797     setDisabledDays : function(dd){
12798         this.disabledDays = dd;
12799         this.update(this.value, true);
12800     },
12801
12802     /**
12803      * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
12804      * @param {Date} value The minimum date that can be selected
12805      */
12806     setMinDate : function(dt){
12807         this.minDate = dt;
12808         this.update(this.value, true);
12809     },
12810
12811     /**
12812      * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
12813      * @param {Date} value The maximum date that can be selected
12814      */
12815     setMaxDate : function(dt){
12816         this.maxDate = dt;
12817         this.update(this.value, true);
12818     },
12819
12820     /**
12821      * Sets the value of the date field
12822      * @param {Date} value The date to set
12823      */
12824     setValue : function(value){
12825         this.value = value.clearTime(true);
12826         this.update(this.value);
12827     },
12828
12829     /**
12830      * Gets the current selected value of the date field
12831      * @return {Date} The selected date
12832      */
12833     getValue : function(){
12834         return this.value;
12835     },
12836
12837     // private
12838     focus : function(){
12839         this.update(this.activeDate);
12840     },
12841
12842     // private
12843     onEnable: function(initial){
12844         Ext.DatePicker.superclass.onEnable.call(this);
12845         this.doDisabled(false);
12846         this.update(initial ? this.value : this.activeDate);
12847         if(Ext.isIE){
12848             this.el.repaint();
12849         }
12850
12851     },
12852
12853     // private
12854     onDisable : function(){
12855         Ext.DatePicker.superclass.onDisable.call(this);
12856         this.doDisabled(true);
12857         if(Ext.isIE && !Ext.isIE8){
12858             /* Really strange problem in IE6/7, when disabled, have to explicitly
12859              * repaint each of the nodes to get them to display correctly, simply
12860              * calling repaint on the main element doesn't appear to be enough.
12861              */
12862              Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
12863                  Ext.fly(el).repaint();
12864              });
12865         }
12866     },
12867
12868     // private
12869     doDisabled : function(disabled){
12870         this.keyNav.setDisabled(disabled);
12871         this.prevRepeater.setDisabled(disabled);
12872         this.nextRepeater.setDisabled(disabled);
12873         if(this.showToday){
12874             this.todayKeyListener.setDisabled(disabled);
12875             this.todayBtn.setDisabled(disabled);
12876         }
12877     },
12878
12879     // private
12880     onRender : function(container, position){
12881         var m = [
12882              '<table cellspacing="0">',
12883                 '<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>',
12884                 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
12885                 dn = this.dayNames,
12886                 i;
12887         for(i = 0; i < 7; i++){
12888             var d = this.startDay+i;
12889             if(d > 6){
12890                 d = d-7;
12891             }
12892             m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
12893         }
12894         m[m.length] = '</tr></thead><tbody><tr>';
12895         for(i = 0; i < 42; i++) {
12896             if(i % 7 === 0 && i !== 0){
12897                 m[m.length] = '</tr><tr>';
12898             }
12899             m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
12900         }
12901         m.push('</tr></tbody></table></td></tr>',
12902                 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
12903                 '</table><div class="x-date-mp"></div>');
12904
12905         var el = document.createElement('div');
12906         el.className = 'x-date-picker';
12907         el.innerHTML = m.join('');
12908
12909         container.dom.insertBefore(el, position);
12910
12911         this.el = Ext.get(el);
12912         this.eventEl = Ext.get(el.firstChild);
12913
12914         this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
12915             handler: this.showPrevMonth,
12916             scope: this,
12917             preventDefault:true,
12918             stopDefault:true
12919         });
12920
12921         this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
12922             handler: this.showNextMonth,
12923             scope: this,
12924             preventDefault:true,
12925             stopDefault:true
12926         });
12927
12928         this.monthPicker = this.el.down('div.x-date-mp');
12929         this.monthPicker.enableDisplayMode('block');
12930
12931         this.keyNav = new Ext.KeyNav(this.eventEl, {
12932             'left' : function(e){
12933                 if(e.ctrlKey){
12934                     this.showPrevMonth();
12935                 }else{
12936                     this.update(this.activeDate.add('d', -1));
12937                 }
12938             },
12939
12940             'right' : function(e){
12941                 if(e.ctrlKey){
12942                     this.showNextMonth();
12943                 }else{
12944                     this.update(this.activeDate.add('d', 1));
12945                 }
12946             },
12947
12948             'up' : function(e){
12949                 if(e.ctrlKey){
12950                     this.showNextYear();
12951                 }else{
12952                     this.update(this.activeDate.add('d', -7));
12953                 }
12954             },
12955
12956             'down' : function(e){
12957                 if(e.ctrlKey){
12958                     this.showPrevYear();
12959                 }else{
12960                     this.update(this.activeDate.add('d', 7));
12961                 }
12962             },
12963
12964             'pageUp' : function(e){
12965                 this.showNextMonth();
12966             },
12967
12968             'pageDown' : function(e){
12969                 this.showPrevMonth();
12970             },
12971
12972             'enter' : function(e){
12973                 e.stopPropagation();
12974                 return true;
12975             },
12976
12977             scope : this
12978         });
12979
12980         this.el.unselectable();
12981
12982         this.cells = this.el.select('table.x-date-inner tbody td');
12983         this.textNodes = this.el.query('table.x-date-inner tbody span');
12984
12985         this.mbtn = new Ext.Button({
12986             text: '&#160;',
12987             tooltip: this.monthYearText,
12988             renderTo: this.el.child('td.x-date-middle', true)
12989         });
12990         this.mbtn.el.child('em').addClass('x-btn-arrow');
12991
12992         if(this.showToday){
12993             this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);
12994             var today = (new Date()).dateFormat(this.format);
12995             this.todayBtn = new Ext.Button({
12996                 renderTo: this.el.child('td.x-date-bottom', true),
12997                 text: String.format(this.todayText, today),
12998                 tooltip: String.format(this.todayTip, today),
12999                 handler: this.selectToday,
13000                 scope: this
13001             });
13002         }
13003         this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
13004         this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});
13005         this.mon(this.mbtn, 'click', this.showMonthPicker, this);
13006         this.onEnable(true);
13007     },
13008
13009     // private
13010     createMonthPicker : function(){
13011         if(!this.monthPicker.dom.firstChild){
13012             var buf = ['<table border="0" cellspacing="0">'];
13013             for(var i = 0; i < 6; i++){
13014                 buf.push(
13015                     '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
13016                     '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
13017                     i === 0 ?
13018                     '<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>' :
13019                     '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
13020                 );
13021             }
13022             buf.push(
13023                 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
13024                     this.okText,
13025                     '</button><button type="button" class="x-date-mp-cancel">',
13026                     this.cancelText,
13027                     '</button></td></tr>',
13028                 '</table>'
13029             );
13030             this.monthPicker.update(buf.join(''));
13031
13032             this.mon(this.monthPicker, 'click', this.onMonthClick, this);
13033             this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
13034
13035             this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
13036             this.mpYears = this.monthPicker.select('td.x-date-mp-year');
13037
13038             this.mpMonths.each(function(m, a, i){
13039                 i += 1;
13040                 if((i%2) === 0){
13041                     m.dom.xmonth = 5 + Math.round(i * 0.5);
13042                 }else{
13043                     m.dom.xmonth = Math.round((i-1) * 0.5);
13044                 }
13045             });
13046         }
13047     },
13048
13049     // private
13050     showMonthPicker : function(){
13051         if(!this.disabled){
13052             this.createMonthPicker();
13053             var size = this.el.getSize();
13054             this.monthPicker.setSize(size);
13055             this.monthPicker.child('table').setSize(size);
13056
13057             this.mpSelMonth = (this.activeDate || this.value).getMonth();
13058             this.updateMPMonth(this.mpSelMonth);
13059             this.mpSelYear = (this.activeDate || this.value).getFullYear();
13060             this.updateMPYear(this.mpSelYear);
13061
13062             this.monthPicker.slideIn('t', {duration:0.2});
13063         }
13064     },
13065
13066     // private
13067     updateMPYear : function(y){
13068         this.mpyear = y;
13069         var ys = this.mpYears.elements;
13070         for(var i = 1; i <= 10; i++){
13071             var td = ys[i-1], y2;
13072             if((i%2) === 0){
13073                 y2 = y + Math.round(i * 0.5);
13074                 td.firstChild.innerHTML = y2;
13075                 td.xyear = y2;
13076             }else{
13077                 y2 = y - (5-Math.round(i * 0.5));
13078                 td.firstChild.innerHTML = y2;
13079                 td.xyear = y2;
13080             }
13081             this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
13082         }
13083     },
13084
13085     // private
13086     updateMPMonth : function(sm){
13087         this.mpMonths.each(function(m, a, i){
13088             m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
13089         });
13090     },
13091
13092     // private
13093     selectMPMonth : function(m){
13094
13095     },
13096
13097     // private
13098     onMonthClick : function(e, t){
13099         e.stopEvent();
13100         var el = new Ext.Element(t), pn;
13101         if(el.is('button.x-date-mp-cancel')){
13102             this.hideMonthPicker();
13103         }
13104         else if(el.is('button.x-date-mp-ok')){
13105             var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
13106             if(d.getMonth() != this.mpSelMonth){
13107                 // 'fix' the JS rolling date conversion if needed
13108                 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
13109             }
13110             this.update(d);
13111             this.hideMonthPicker();
13112         }
13113         else if((pn = el.up('td.x-date-mp-month', 2))){
13114             this.mpMonths.removeClass('x-date-mp-sel');
13115             pn.addClass('x-date-mp-sel');
13116             this.mpSelMonth = pn.dom.xmonth;
13117         }
13118         else if((pn = el.up('td.x-date-mp-year', 2))){
13119             this.mpYears.removeClass('x-date-mp-sel');
13120             pn.addClass('x-date-mp-sel');
13121             this.mpSelYear = pn.dom.xyear;
13122         }
13123         else if(el.is('a.x-date-mp-prev')){
13124             this.updateMPYear(this.mpyear-10);
13125         }
13126         else if(el.is('a.x-date-mp-next')){
13127             this.updateMPYear(this.mpyear+10);
13128         }
13129     },
13130
13131     // private
13132     onMonthDblClick : function(e, t){
13133         e.stopEvent();
13134         var el = new Ext.Element(t), pn;
13135         if((pn = el.up('td.x-date-mp-month', 2))){
13136             this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
13137             this.hideMonthPicker();
13138         }
13139         else if((pn = el.up('td.x-date-mp-year', 2))){
13140             this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
13141             this.hideMonthPicker();
13142         }
13143     },
13144
13145     // private
13146     hideMonthPicker : function(disableAnim){
13147         if(this.monthPicker){
13148             if(disableAnim === true){
13149                 this.monthPicker.hide();
13150             }else{
13151                 this.monthPicker.slideOut('t', {duration:0.2});
13152             }
13153         }
13154     },
13155
13156     // private
13157     showPrevMonth : function(e){
13158         this.update(this.activeDate.add('mo', -1));
13159     },
13160
13161     // private
13162     showNextMonth : function(e){
13163         this.update(this.activeDate.add('mo', 1));
13164     },
13165
13166     // private
13167     showPrevYear : function(){
13168         this.update(this.activeDate.add('y', -1));
13169     },
13170
13171     // private
13172     showNextYear : function(){
13173         this.update(this.activeDate.add('y', 1));
13174     },
13175
13176     // private
13177     handleMouseWheel : function(e){
13178         e.stopEvent();
13179         if(!this.disabled){
13180             var delta = e.getWheelDelta();
13181             if(delta > 0){
13182                 this.showPrevMonth();
13183             } else if(delta < 0){
13184                 this.showNextMonth();
13185             }
13186         }
13187     },
13188
13189     // private
13190     handleDateClick : function(e, t){
13191         e.stopEvent();
13192         if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
13193             this.cancelFocus = this.focusOnSelect === false;
13194             this.setValue(new Date(t.dateValue));
13195             delete this.cancelFocus;
13196             this.fireEvent('select', this, this.value);
13197         }
13198     },
13199
13200     // private
13201     selectToday : function(){
13202         if(this.todayBtn && !this.todayBtn.disabled){
13203             this.setValue(new Date().clearTime());
13204             this.fireEvent('select', this, this.value);
13205         }
13206     },
13207
13208     // private
13209     update : function(date, forceRefresh){
13210         if(this.rendered){
13211             var vd = this.activeDate, vis = this.isVisible();
13212             this.activeDate = date;
13213             if(!forceRefresh && vd && this.el){
13214                 var t = date.getTime();
13215                 if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
13216                     this.cells.removeClass('x-date-selected');
13217                     this.cells.each(function(c){
13218                        if(c.dom.firstChild.dateValue == t){
13219                            c.addClass('x-date-selected');
13220                            if(vis && !this.cancelFocus){
13221                                Ext.fly(c.dom.firstChild).focus(50);
13222                            }
13223                            return false;
13224                        }
13225                     }, this);
13226                     return;
13227                 }
13228             }
13229             var days = date.getDaysInMonth(),
13230                 firstOfMonth = date.getFirstDateOfMonth(),
13231                 startingPos = firstOfMonth.getDay()-this.startDay;
13232
13233             if(startingPos < 0){
13234                 startingPos += 7;
13235             }
13236             days += startingPos;
13237
13238             var pm = date.add('mo', -1),
13239                 prevStart = pm.getDaysInMonth()-startingPos,
13240                 cells = this.cells.elements,
13241                 textEls = this.textNodes,
13242                 // convert everything to numbers so it's fast
13243                 d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart, this.initHour)),
13244                 today = new Date().clearTime().getTime(),
13245                 sel = date.clearTime(true).getTime(),
13246                 min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
13247                 max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
13248                 ddMatch = this.disabledDatesRE,
13249                 ddText = this.disabledDatesText,
13250                 ddays = this.disabledDays ? this.disabledDays.join('') : false,
13251                 ddaysText = this.disabledDaysText,
13252                 format = this.format;
13253
13254             if(this.showToday){
13255                 var td = new Date().clearTime(),
13256                     disable = (td < min || td > max ||
13257                     (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
13258                     (ddays && ddays.indexOf(td.getDay()) != -1));
13259
13260                 if(!this.disabled){
13261                     this.todayBtn.setDisabled(disable);
13262                     this.todayKeyListener[disable ? 'disable' : 'enable']();
13263                 }
13264             }
13265
13266             var setCellClass = function(cal, cell){
13267                 cell.title = '';
13268                 var t = d.clearTime(true).getTime();
13269                 cell.firstChild.dateValue = t;
13270                 if(t == today){
13271                     cell.className += ' x-date-today';
13272                     cell.title = cal.todayText;
13273                 }
13274                 if(t == sel){
13275                     cell.className += ' x-date-selected';
13276                     if(vis){
13277                         Ext.fly(cell.firstChild).focus(50);
13278                     }
13279                 }
13280                 // disabling
13281                 if(t < min) {
13282                     cell.className = ' x-date-disabled';
13283                     cell.title = cal.minText;
13284                     return;
13285                 }
13286                 if(t > max) {
13287                     cell.className = ' x-date-disabled';
13288                     cell.title = cal.maxText;
13289                     return;
13290                 }
13291                 if(ddays){
13292                     if(ddays.indexOf(d.getDay()) != -1){
13293                         cell.title = ddaysText;
13294                         cell.className = ' x-date-disabled';
13295                     }
13296                 }
13297                 if(ddMatch && format){
13298                     var fvalue = d.dateFormat(format);
13299                     if(ddMatch.test(fvalue)){
13300                         cell.title = ddText.replace('%0', fvalue);
13301                         cell.className = ' x-date-disabled';
13302                     }
13303                 }
13304             };
13305
13306             var i = 0;
13307             for(; i < startingPos; i++) {
13308                 textEls[i].innerHTML = (++prevStart);
13309                 d.setDate(d.getDate()+1);
13310                 cells[i].className = 'x-date-prevday';
13311                 setCellClass(this, cells[i]);
13312             }
13313             for(; i < days; i++){
13314                 var intDay = i - startingPos + 1;
13315                 textEls[i].innerHTML = (intDay);
13316                 d.setDate(d.getDate()+1);
13317                 cells[i].className = 'x-date-active';
13318                 setCellClass(this, cells[i]);
13319             }
13320             var extraDays = 0;
13321             for(; i < 42; i++) {
13322                  textEls[i].innerHTML = (++extraDays);
13323                  d.setDate(d.getDate()+1);
13324                  cells[i].className = 'x-date-nextday';
13325                  setCellClass(this, cells[i]);
13326             }
13327
13328             this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
13329
13330             if(!this.internalRender){
13331                 var main = this.el.dom.firstChild,
13332                     w = main.offsetWidth;
13333                 this.el.setWidth(w + this.el.getBorderWidth('lr'));
13334                 Ext.fly(main).setWidth(w);
13335                 this.internalRender = true;
13336                 // opera does not respect the auto grow header center column
13337                 // then, after it gets a width opera refuses to recalculate
13338                 // without a second pass
13339                 if(Ext.isOpera && !this.secondPass){
13340                     main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
13341                     this.secondPass = true;
13342                     this.update.defer(10, this, [date]);
13343                 }
13344             }
13345         }
13346     },
13347
13348     // private
13349     beforeDestroy : function() {
13350         if(this.rendered){
13351             Ext.destroy(
13352                 this.keyNav,
13353                 this.monthPicker,
13354                 this.eventEl,
13355                 this.mbtn,
13356                 this.nextRepeater,
13357                 this.prevRepeater,
13358                 this.cells.el,
13359                 this.todayBtn
13360             );
13361             delete this.textNodes;
13362             delete this.cells.elements;
13363         }
13364     }
13365
13366     /**
13367      * @cfg {String} autoEl @hide
13368      */
13369 });
13370
13371 Ext.reg('datepicker', Ext.DatePicker);
13372 /**
13373  * @class Ext.LoadMask
13374  * A simple utility class for generically masking elements while loading data.  If the {@link #store}
13375  * config option is specified, the masking will be automatically synchronized with the store's loading
13376  * process and the mask element will be cached for reuse.  For all other elements, this mask will replace the
13377  * element's Updater load indicator and will be destroyed after the initial load.
13378  * <p>Example usage:</p>
13379  *<pre><code>
13380 // Basic mask:
13381 var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
13382 myMask.show();
13383 </code></pre>
13384  * @constructor
13385  * Create a new LoadMask
13386  * @param {Mixed} el The element or DOM node, or its id
13387  * @param {Object} config The config object
13388  */
13389 Ext.LoadMask = function(el, config){
13390     this.el = Ext.get(el);
13391     Ext.apply(this, config);
13392     if(this.store){
13393         this.store.on({
13394             scope: this,
13395             beforeload: this.onBeforeLoad,
13396             load: this.onLoad,
13397             exception: this.onLoad
13398         });
13399         this.removeMask = Ext.value(this.removeMask, false);
13400     }else{
13401         var um = this.el.getUpdater();
13402         um.showLoadIndicator = false; // disable the default indicator
13403         um.on({
13404             scope: this,
13405             beforeupdate: this.onBeforeLoad,
13406             update: this.onLoad,
13407             failure: this.onLoad
13408         });
13409         this.removeMask = Ext.value(this.removeMask, true);
13410     }
13411 };
13412
13413 Ext.LoadMask.prototype = {
13414     /**
13415      * @cfg {Ext.data.Store} store
13416      * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and
13417      * hidden on either load sucess, or load fail.
13418      */
13419     /**
13420      * @cfg {Boolean} removeMask
13421      * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
13422      * False to persist the mask element reference for multiple uses (e.g., for paged data widgets).  Defaults to false.
13423      */
13424     /**
13425      * @cfg {String} msg
13426      * The text to display in a centered loading message box (defaults to 'Loading...')
13427      */
13428     msg : 'Loading...',
13429     /**
13430      * @cfg {String} msgCls
13431      * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
13432      */
13433     msgCls : 'x-mask-loading',
13434
13435     /**
13436      * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
13437      * @type Boolean
13438      */
13439     disabled: false,
13440
13441     /**
13442      * Disables the mask to prevent it from being displayed
13443      */
13444     disable : function(){
13445        this.disabled = true;
13446     },
13447
13448     /**
13449      * Enables the mask so that it can be displayed
13450      */
13451     enable : function(){
13452         this.disabled = false;
13453     },
13454
13455     // private
13456     onLoad : function(){
13457         this.el.unmask(this.removeMask);
13458     },
13459
13460     // private
13461     onBeforeLoad : function(){
13462         if(!this.disabled){
13463             this.el.mask(this.msg, this.msgCls);
13464         }
13465     },
13466
13467     /**
13468      * Show this LoadMask over the configured Element.
13469      */
13470     show: function(){
13471         this.onBeforeLoad();
13472     },
13473
13474     /**
13475      * Hide this LoadMask.
13476      */
13477     hide: function(){
13478         this.onLoad();
13479     },
13480
13481     // private
13482     destroy : function(){
13483         if(this.store){
13484             this.store.un('beforeload', this.onBeforeLoad, this);
13485             this.store.un('load', this.onLoad, this);
13486             this.store.un('exception', this.onLoad, this);
13487         }else{
13488             var um = this.el.getUpdater();
13489             um.un('beforeupdate', this.onBeforeLoad, this);
13490             um.un('update', this.onLoad, this);
13491             um.un('failure', this.onLoad, this);
13492         }
13493     }
13494 };Ext.ns('Ext.slider');
13495
13496 /**
13497  * @class Ext.slider.Thumb
13498  * @extends Object
13499  * Represents a single thumb element on a Slider. This would not usually be created manually and would instead
13500  * be created internally by an {@link Ext.slider.MultiSlider Ext.Slider}.
13501  */
13502 Ext.slider.Thumb = Ext.extend(Object, {
13503     
13504     /**
13505      * True while the thumb is in a drag operation
13506      * @type Boolean
13507      */
13508     dragging: false,
13509
13510     /**
13511      * @constructor
13512      * @cfg {Ext.slider.MultiSlider} slider The Slider to render to (required)
13513      */
13514     constructor: function(config) {
13515         /**
13516          * @property slider
13517          * @type Ext.slider.MultiSlider
13518          * The slider this thumb is contained within
13519          */
13520         Ext.apply(this, config || {}, {
13521             cls: 'x-slider-thumb',
13522
13523             /**
13524              * @cfg {Boolean} constrain True to constrain the thumb so that it cannot overlap its siblings
13525              */
13526             constrain: false
13527         });
13528
13529         Ext.slider.Thumb.superclass.constructor.call(this, config);
13530
13531         if (this.slider.vertical) {
13532             Ext.apply(this, Ext.slider.Thumb.Vertical);
13533         }
13534     },
13535
13536     /**
13537      * Renders the thumb into a slider
13538      */
13539     render: function() {
13540         this.el = this.slider.innerEl.insertFirst({cls: this.cls});
13541
13542         this.initEvents();
13543     },
13544
13545     /**
13546      * Enables the thumb if it is currently disabled
13547      */
13548     enable: function() {
13549         this.disabled = false;
13550         this.el.removeClass(this.slider.disabledClass);
13551     },
13552
13553     /**
13554      * Disables the thumb if it is currently enabled
13555      */
13556     disable: function() {
13557         this.disabled = true;
13558         this.el.addClass(this.slider.disabledClass);
13559     },
13560
13561     /**
13562      * Sets up an Ext.dd.DragTracker for this thumb
13563      */
13564     initEvents: function() {
13565         var el = this.el;
13566
13567         el.addClassOnOver('x-slider-thumb-over');
13568
13569         this.tracker = new Ext.dd.DragTracker({
13570             onBeforeStart: this.onBeforeDragStart.createDelegate(this),
13571             onStart      : this.onDragStart.createDelegate(this),
13572             onDrag       : this.onDrag.createDelegate(this),
13573             onEnd        : this.onDragEnd.createDelegate(this),
13574             tolerance    : 3,
13575             autoStart    : 300
13576         });
13577
13578         this.tracker.initEl(el);
13579     },
13580
13581     /**
13582      * @private
13583      * This is tied into the internal Ext.dd.DragTracker. If the slider is currently disabled,
13584      * this returns false to disable the DragTracker too.
13585      * @return {Boolean} False if the slider is currently disabled
13586      */
13587     onBeforeDragStart : function(e) {
13588         if (this.disabled) {
13589             return false;
13590         } else {
13591             this.slider.promoteThumb(this);
13592             return true;
13593         }
13594     },
13595
13596     /**
13597      * @private
13598      * This is tied into the internal Ext.dd.DragTracker's onStart template method. Adds the drag CSS class
13599      * to the thumb and fires the 'dragstart' event
13600      */
13601     onDragStart: function(e){
13602         this.el.addClass('x-slider-thumb-drag');
13603         this.dragging = true;
13604         this.dragStartValue = this.value;
13605
13606         this.slider.fireEvent('dragstart', this.slider, e, this);
13607     },
13608
13609     /**
13610      * @private
13611      * This is tied into the internal Ext.dd.DragTracker's onDrag template method. This is called every time
13612      * the DragTracker detects a drag movement. It updates the Slider's value using the position of the drag
13613      */
13614     onDrag: function(e) {
13615         var slider   = this.slider,
13616             index    = this.index,
13617             newValue = this.getNewValue();
13618
13619         if (this.constrain) {
13620             var above = slider.thumbs[index + 1],
13621                 below = slider.thumbs[index - 1];
13622
13623             if (below != undefined && newValue <= below.value) newValue = below.value;
13624             if (above != undefined && newValue >= above.value) newValue = above.value;
13625         }
13626
13627         slider.setValue(index, newValue, false);
13628         slider.fireEvent('drag', slider, e, this);
13629     },
13630
13631     getNewValue: function() {
13632         var slider   = this.slider,
13633             pos      = slider.innerEl.translatePoints(this.tracker.getXY());
13634
13635         return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
13636     },
13637
13638     /**
13639      * @private
13640      * This is tied to the internal Ext.dd.DragTracker's onEnd template method. Removes the drag CSS class and
13641      * fires the 'changecomplete' event with the new value
13642      */
13643     onDragEnd: function(e) {
13644         var slider = this.slider,
13645             value  = this.value;
13646
13647         this.el.removeClass('x-slider-thumb-drag');
13648
13649         this.dragging = false;
13650         slider.fireEvent('dragend', slider, e);
13651
13652         if (this.dragStartValue != value) {
13653             slider.fireEvent('changecomplete', slider, value, this);
13654         }
13655     },
13656     
13657     /**
13658      * @private
13659      * Destroys the thumb
13660      */
13661     destroy: function(){
13662         Ext.destroyMembers(this, 'tracker', 'el');
13663     }
13664 });
13665
13666 /**
13667  * @class Ext.slider.MultiSlider
13668  * @extends Ext.BoxComponent
13669  * 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:
13670 <pre>
13671 new Ext.Slider({
13672     renderTo: Ext.getBody(),
13673     width: 200,
13674     value: 50,
13675     increment: 10,
13676     minValue: 0,
13677     maxValue: 100
13678 });
13679 </pre>
13680  * Sliders can be created with more than one thumb handle by passing an array of values instead of a single one:
13681 <pre>
13682 new Ext.Slider({
13683     renderTo: Ext.getBody(),
13684     width: 200,
13685     values: [25, 50, 75],
13686     minValue: 0,
13687     maxValue: 100,
13688
13689     //this defaults to true, setting to false allows the thumbs to pass each other
13690     {@link #constrainThumbs}: false
13691 });
13692 </pre>
13693  */
13694 Ext.slider.MultiSlider = Ext.extend(Ext.BoxComponent, {
13695     /**
13696      * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.
13697      */
13698     /**
13699      * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.
13700      */
13701     vertical: false,
13702     /**
13703      * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.
13704      */
13705     minValue: 0,
13706     /**
13707      * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.
13708      */
13709     maxValue: 100,
13710     /**
13711      * @cfg {Number/Boolean} decimalPrecision.
13712      * <p>The number of decimal places to which to round the Slider's value. Defaults to 0.</p>
13713      * <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>
13714      */
13715     decimalPrecision: 0,
13716     /**
13717      * @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.
13718      */
13719     keyIncrement: 1,
13720     /**
13721      * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.
13722      */
13723     increment: 0,
13724
13725     /**
13726      * @private
13727      * @property clickRange
13728      * @type Array
13729      * 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],
13730      * 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'
13731      * 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
13732      */
13733     clickRange: [5,15],
13734
13735     /**
13736      * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true
13737      */
13738     clickToChange : true,
13739     /**
13740      * @cfg {Boolean} animate Turn on or off animation. Defaults to true
13741      */
13742     animate: true,
13743     /**
13744      * @cfg {Boolean} constrainThumbs True to disallow thumbs from overlapping one another. Defaults to true
13745      */
13746     constrainThumbs: true,
13747
13748     /**
13749      * @private
13750      * @property topThumbZIndex
13751      * @type Number
13752      * The number used internally to set the z index of the top thumb (see promoteThumb for details)
13753      */
13754     topThumbZIndex: 10000,
13755
13756     // private override
13757     initComponent : function(){
13758         if(!Ext.isDefined(this.value)){
13759             this.value = this.minValue;
13760         }
13761
13762         /**
13763          * @property thumbs
13764          * @type Array
13765          * Array containing references to each thumb
13766          */
13767         this.thumbs = [];
13768
13769         Ext.slider.MultiSlider.superclass.initComponent.call(this);
13770
13771         this.keyIncrement = Math.max(this.increment, this.keyIncrement);
13772         this.addEvents(
13773             /**
13774              * @event beforechange
13775              * Fires before the slider value is changed. By returning false from an event handler,
13776              * you can cancel the event and prevent the slider from changing.
13777              * @param {Ext.slider.MultiSlider} slider The slider
13778              * @param {Number} newValue The new value which the slider is being changed to.
13779              * @param {Number} oldValue The old value which the slider was previously.
13780              */
13781             'beforechange',
13782
13783             /**
13784              * @event change
13785              * Fires when the slider value is changed.
13786              * @param {Ext.slider.MultiSlider} slider The slider
13787              * @param {Number} newValue The new value which the slider has been changed to.
13788              * @param {Ext.slider.Thumb} thumb The thumb that was changed
13789              */
13790             'change',
13791
13792             /**
13793              * @event changecomplete
13794              * Fires when the slider value is changed by the user and any drag operations have completed.
13795              * @param {Ext.slider.MultiSlider} slider The slider
13796              * @param {Number} newValue The new value which the slider has been changed to.
13797              * @param {Ext.slider.Thumb} thumb The thumb that was changed
13798              */
13799             'changecomplete',
13800
13801             /**
13802              * @event dragstart
13803              * Fires after a drag operation has started.
13804              * @param {Ext.slider.MultiSlider} slider The slider
13805              * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
13806              */
13807             'dragstart',
13808
13809             /**
13810              * @event drag
13811              * Fires continuously during the drag operation while the mouse is moving.
13812              * @param {Ext.slider.MultiSlider} slider The slider
13813              * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
13814              */
13815             'drag',
13816
13817             /**
13818              * @event dragend
13819              * Fires after the drag operation has completed.
13820              * @param {Ext.slider.MultiSlider} slider The slider
13821              * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
13822              */
13823             'dragend'
13824         );
13825
13826         /**
13827          * @property values
13828          * @type Array
13829          * Array of values to initalize the thumbs with
13830          */
13831         if (this.values == undefined || Ext.isEmpty(this.values)) this.values = [0];
13832
13833         var values = this.values;
13834
13835         for (var i=0; i < values.length; i++) {
13836             this.addThumb(values[i]);
13837         }
13838
13839         if(this.vertical){
13840             Ext.apply(this, Ext.slider.Vertical);
13841         }
13842     },
13843
13844     /**
13845      * Creates a new thumb and adds it to the slider
13846      * @param {Number} value The initial value to set on the thumb. Defaults to 0
13847      */
13848     addThumb: function(value) {
13849         var thumb = new Ext.slider.Thumb({
13850             value    : value,
13851             slider   : this,
13852             index    : this.thumbs.length,
13853             constrain: this.constrainThumbs
13854         });
13855         this.thumbs.push(thumb);
13856
13857         //render the thumb now if needed
13858         if (this.rendered) thumb.render();
13859     },
13860
13861     /**
13862      * @private
13863      * Moves the given thumb above all other by increasing its z-index. This is called when as drag
13864      * any thumb, so that the thumb that was just dragged is always at the highest z-index. This is
13865      * required when the thumbs are stacked on top of each other at one of the ends of the slider's
13866      * range, which can result in the user not being able to move any of them.
13867      * @param {Ext.slider.Thumb} topThumb The thumb to move to the top
13868      */
13869     promoteThumb: function(topThumb) {
13870         var thumbs = this.thumbs,
13871             zIndex, thumb;
13872
13873         for (var i = 0, j = thumbs.length; i < j; i++) {
13874             thumb = thumbs[i];
13875
13876             if (thumb == topThumb) {
13877                 zIndex = this.topThumbZIndex;
13878             } else {
13879                 zIndex = '';
13880             }
13881
13882             thumb.el.setStyle('zIndex', zIndex);
13883         }
13884     },
13885
13886     // private override
13887     onRender : function() {
13888         this.autoEl = {
13889             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
13890             cn : {
13891                 cls: 'x-slider-end',
13892                 cn : {
13893                     cls:'x-slider-inner',
13894                     cn : [{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]
13895                 }
13896             }
13897         };
13898
13899         Ext.slider.MultiSlider.superclass.onRender.apply(this, arguments);
13900
13901         this.endEl   = this.el.first();
13902         this.innerEl = this.endEl.first();
13903         this.focusEl = this.innerEl.child('.x-slider-focus');
13904
13905         //render each thumb
13906         for (var i=0; i < this.thumbs.length; i++) {
13907             this.thumbs[i].render();
13908         }
13909
13910         //calculate the size of half a thumb
13911         var thumb      = this.innerEl.child('.x-slider-thumb');
13912         this.halfThumb = (this.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
13913
13914         this.initEvents();
13915     },
13916
13917     /**
13918      * @private
13919      * Adds keyboard and mouse listeners on this.el. Ignores click events on the internal focus element.
13920      * Creates a new DragTracker which is used to control what happens when the user drags the thumb around.
13921      */
13922     initEvents : function(){
13923         this.mon(this.el, {
13924             scope    : this,
13925             mousedown: this.onMouseDown,
13926             keydown  : this.onKeyDown
13927         });
13928
13929         this.focusEl.swallowEvent("click", true);
13930     },
13931
13932     /**
13933      * @private
13934      * Mousedown handler for the slider. If the clickToChange is enabled and the click was not on the draggable 'thumb',
13935      * this calculates the new value of the slider and tells the implementation (Horizontal or Vertical) to move the thumb
13936      * @param {Ext.EventObject} e The click event
13937      */
13938     onMouseDown : function(e){
13939         if(this.disabled){
13940             return;
13941         }
13942
13943         //see if the click was on any of the thumbs
13944         var thumbClicked = false;
13945         for (var i=0; i < this.thumbs.length; i++) {
13946             thumbClicked = thumbClicked || e.target == this.thumbs[i].el.dom;
13947         }
13948
13949         if (this.clickToChange && !thumbClicked) {
13950             var local = this.innerEl.translatePoints(e.getXY());
13951             this.onClickChange(local);
13952         }
13953         this.focus();
13954     },
13955
13956     /**
13957      * @private
13958      * Moves the thumb to the indicated position. Note that a Vertical implementation is provided in Ext.slider.Vertical.
13959      * Only changes the value if the click was within this.clickRange.
13960      * @param {Object} local Object containing top and left values for the click event.
13961      */
13962     onClickChange : function(local) {
13963         if (local.top > this.clickRange[0] && local.top < this.clickRange[1]) {
13964             //find the nearest thumb to the click event
13965             var thumb = this.getNearest(local, 'left'),
13966                 index = thumb.index;
13967
13968             this.setValue(index, Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
13969         }
13970     },
13971
13972     /**
13973      * @private
13974      * Returns the nearest thumb to a click event, along with its distance
13975      * @param {Object} local Object containing top and left values from a click event
13976      * @param {String} prop The property of local to compare on. Use 'left' for horizontal sliders, 'top' for vertical ones
13977      * @return {Object} The closest thumb object and its distance from the click event
13978      */
13979     getNearest: function(local, prop) {
13980         var localValue = prop == 'top' ? this.innerEl.getHeight() - local[prop] : local[prop],
13981             clickValue = this.reverseValue(localValue),
13982             nearestDistance = (this.maxValue - this.minValue) + 5, //add a small fudge for the end of the slider 
13983             index = 0,
13984             nearest = null;
13985
13986         for (var i=0; i < this.thumbs.length; i++) {
13987             var thumb = this.thumbs[i],
13988                 value = thumb.value,
13989                 dist  = Math.abs(value - clickValue);
13990
13991             if (Math.abs(dist <= nearestDistance)) {
13992                 nearest = thumb;
13993                 index = i;
13994                 nearestDistance = dist;
13995             }
13996         }
13997         return nearest;
13998     },
13999
14000     /**
14001      * @private
14002      * Handler for any keypresses captured by the slider. If the key is UP or RIGHT, the thumb is moved along to the right
14003      * by this.keyIncrement. If DOWN or LEFT it is moved left. Pressing CTRL moves the slider to the end in either direction
14004      * @param {Ext.EventObject} e The Event object
14005      */
14006     onKeyDown : function(e){
14007         /*
14008          * The behaviour for keyboard handling with multiple thumbs is currently undefined.
14009          * There's no real sane default for it, so leave it like this until we come up
14010          * with a better way of doing it.
14011          */
14012         if(this.disabled || this.thumbs.length !== 1){
14013             e.preventDefault();
14014             return;
14015         }
14016         var k = e.getKey(),
14017             val;
14018         switch(k){
14019             case e.UP:
14020             case e.RIGHT:
14021                 e.stopEvent();
14022                 val = e.ctrlKey ? this.maxValue : this.getValue(0) + this.keyIncrement;
14023                 this.setValue(0, val, undefined, true);
14024             break;
14025             case e.DOWN:
14026             case e.LEFT:
14027                 e.stopEvent();
14028                 val = e.ctrlKey ? this.minValue : this.getValue(0) - this.keyIncrement;
14029                 this.setValue(0, val, undefined, true);
14030             break;
14031             default:
14032                 e.preventDefault();
14033         }
14034     },
14035
14036     /**
14037      * @private
14038      * If using snapping, this takes a desired new value and returns the closest snapped
14039      * value to it
14040      * @param {Number} value The unsnapped value
14041      * @return {Number} The value of the nearest snap target
14042      */
14043     doSnap : function(value){
14044         if (!(this.increment && value)) {
14045             return value;
14046         }
14047         var newValue = value,
14048             inc = this.increment,
14049             m = value % inc;
14050         if (m != 0) {
14051             newValue -= m;
14052             if (m * 2 >= inc) {
14053                 newValue += inc;
14054             } else if (m * 2 < -inc) {
14055                 newValue -= inc;
14056             }
14057         }
14058         return newValue.constrain(this.minValue,  this.maxValue);
14059     },
14060
14061     // private
14062     afterRender : function(){
14063         Ext.slider.MultiSlider.superclass.afterRender.apply(this, arguments);
14064
14065         for (var i=0; i < this.thumbs.length; i++) {
14066             var thumb = this.thumbs[i];
14067
14068             if (thumb.value !== undefined) {
14069                 var v = this.normalizeValue(thumb.value);
14070
14071                 if (v !== thumb.value) {
14072                     // delete this.value;
14073                     this.setValue(i, v, false);
14074                 } else {
14075                     this.moveThumb(i, this.translateValue(v), false);
14076                 }
14077             }
14078         };
14079     },
14080
14081     /**
14082      * @private
14083      * Returns the ratio of pixels to mapped values. e.g. if the slider is 200px wide and maxValue - minValue is 100,
14084      * the ratio is 2
14085      * @return {Number} The ratio of pixels to mapped values
14086      */
14087     getRatio : function(){
14088         var w = this.innerEl.getWidth(),
14089             v = this.maxValue - this.minValue;
14090         return v == 0 ? w : (w/v);
14091     },
14092
14093     /**
14094      * @private
14095      * Returns a snapped, constrained value when given a desired value
14096      * @param {Number} value Raw number value
14097      * @return {Number} The raw value rounded to the correct d.p. and constrained within the set max and min values
14098      */
14099     normalizeValue : function(v){
14100         v = this.doSnap(v);
14101         v = Ext.util.Format.round(v, this.decimalPrecision);
14102         v = v.constrain(this.minValue, this.maxValue);
14103         return v;
14104     },
14105
14106     /**
14107      * Sets the minimum value for the slider instance. If the current value is less than the
14108      * minimum value, the current value will be changed.
14109      * @param {Number} val The new minimum value
14110      */
14111     setMinValue : function(val){
14112         this.minValue = val;
14113         var i = 0,
14114             thumbs = this.thumbs,
14115             len = thumbs.length,
14116             t;
14117             
14118         for(; i < len; ++i){
14119             t = thumbs[i];
14120             t.value = t.value < val ? val : t.value;
14121         }
14122         this.syncThumb();
14123     },
14124
14125     /**
14126      * Sets the maximum value for the slider instance. If the current value is more than the
14127      * maximum value, the current value will be changed.
14128      * @param {Number} val The new maximum value
14129      */
14130     setMaxValue : function(val){
14131         this.maxValue = val;
14132         var i = 0,
14133             thumbs = this.thumbs,
14134             len = thumbs.length,
14135             t;
14136             
14137         for(; i < len; ++i){
14138             t = thumbs[i];
14139             t.value = t.value > val ? val : t.value;
14140         }
14141         this.syncThumb();
14142     },
14143
14144     /**
14145      * Programmatically sets the value of the Slider. Ensures that the value is constrained within
14146      * the minValue and maxValue.
14147      * @param {Number} index Index of the thumb to move
14148      * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)
14149      * @param {Boolean} animate Turn on or off animation, defaults to true
14150      */
14151     setValue : function(index, v, animate, changeComplete) {
14152         var thumb = this.thumbs[index],
14153             el    = thumb.el;
14154
14155         v = this.normalizeValue(v);
14156
14157         if (v !== thumb.value && this.fireEvent('beforechange', this, v, thumb.value, thumb) !== false) {
14158             thumb.value = v;
14159             if(this.rendered){
14160                 this.moveThumb(index, this.translateValue(v), animate !== false);
14161                 this.fireEvent('change', this, v, thumb);
14162                 if(changeComplete){
14163                     this.fireEvent('changecomplete', this, v, thumb);
14164                 }
14165             }
14166         }
14167     },
14168
14169     /**
14170      * @private
14171      */
14172     translateValue : function(v) {
14173         var ratio = this.getRatio();
14174         return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
14175     },
14176
14177     /**
14178      * @private
14179      * Given a pixel location along the slider, returns the mapped slider value for that pixel.
14180      * E.g. if we have a slider 200px wide with minValue = 100 and maxValue = 500, reverseValue(50)
14181      * returns 200
14182      * @param {Number} pos The position along the slider to return a mapped value for
14183      * @return {Number} The mapped value for the given position
14184      */
14185     reverseValue : function(pos){
14186         var ratio = this.getRatio();
14187         return (pos + (this.minValue * ratio)) / ratio;
14188     },
14189
14190     /**
14191      * @private
14192      * @param {Number} index Index of the thumb to move
14193      */
14194     moveThumb: function(index, v, animate){
14195         var thumb = this.thumbs[index].el;
14196
14197         if(!animate || this.animate === false){
14198             thumb.setLeft(v);
14199         }else{
14200             thumb.shift({left: v, stopFx: true, duration:.35});
14201         }
14202     },
14203
14204     // private
14205     focus : function(){
14206         this.focusEl.focus(10);
14207     },
14208
14209     // private
14210     onResize : function(w, h){
14211         var thumbs = this.thumbs,
14212             len = thumbs.length,
14213             i = 0;
14214             
14215         /*
14216          * If we happen to be animating during a resize, the position of the thumb will likely be off
14217          * when the animation stops. As such, just stop any animations before syncing the thumbs.
14218          */
14219         for(; i < len; ++i){
14220             thumbs[i].el.stopFx();    
14221         }
14222         // check to see if we're using an auto width
14223         if(Ext.isNumber(w)){
14224             this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
14225         }
14226         this.syncThumb();
14227         Ext.slider.MultiSlider.superclass.onResize.apply(this, arguments);
14228     },
14229
14230     //private
14231     onDisable: function(){
14232         Ext.slider.MultiSlider.superclass.onDisable.call(this);
14233
14234         for (var i=0; i < this.thumbs.length; i++) {
14235             var thumb = this.thumbs[i],
14236                 el    = thumb.el;
14237
14238             thumb.disable();
14239
14240             if(Ext.isIE){
14241                 //IE breaks when using overflow visible and opacity other than 1.
14242                 //Create a place holder for the thumb and display it.
14243                 var xy = el.getXY();
14244                 el.hide();
14245
14246                 this.innerEl.addClass(this.disabledClass).dom.disabled = true;
14247
14248                 if (!this.thumbHolder) {
14249                     this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});
14250                 }
14251
14252                 this.thumbHolder.show().setXY(xy);
14253             }
14254         }
14255     },
14256
14257     //private
14258     onEnable: function(){
14259         Ext.slider.MultiSlider.superclass.onEnable.call(this);
14260
14261         for (var i=0; i < this.thumbs.length; i++) {
14262             var thumb = this.thumbs[i],
14263                 el    = thumb.el;
14264
14265             thumb.enable();
14266
14267             if (Ext.isIE) {
14268                 this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
14269
14270                 if (this.thumbHolder) this.thumbHolder.hide();
14271
14272                 el.show();
14273                 this.syncThumb();
14274             }
14275         }
14276     },
14277
14278     /**
14279      * Synchronizes the thumb position to the proper proportion of the total component width based
14280      * on the current slider {@link #value}.  This will be called automatically when the Slider
14281      * is resized by a layout, but if it is rendered auto width, this method can be called from
14282      * another resize handler to sync the Slider if necessary.
14283      */
14284     syncThumb : function() {
14285         if (this.rendered) {
14286             for (var i=0; i < this.thumbs.length; i++) {
14287                 this.moveThumb(i, this.translateValue(this.thumbs[i].value));
14288             }
14289         }
14290     },
14291
14292     /**
14293      * Returns the current value of the slider
14294      * @param {Number} index The index of the thumb to return a value for
14295      * @return {Number} The current value of the slider
14296      */
14297     getValue : function(index) {
14298         return this.thumbs[index].value;
14299     },
14300
14301     /**
14302      * Returns an array of values - one for the location of each thumb
14303      * @return {Array} The set of thumb values
14304      */
14305     getValues: function() {
14306         var values = [];
14307
14308         for (var i=0; i < this.thumbs.length; i++) {
14309             values.push(this.thumbs[i].value);
14310         }
14311
14312         return values;
14313     },
14314
14315     // private
14316     beforeDestroy : function(){
14317         var thumbs = this.thumbs;
14318         for(var i = 0, len = thumbs.length; i < len; ++i){
14319             thumbs[i].destroy();
14320             thumbs[i] = null;
14321         }
14322         Ext.destroyMembers(this, 'endEl', 'innerEl', 'focusEl', 'thumbHolder');
14323         Ext.slider.MultiSlider.superclass.beforeDestroy.call(this);
14324     }
14325 });
14326
14327 Ext.reg('multislider', Ext.slider.MultiSlider);
14328
14329 /**
14330  * @class Ext.slider.SingleSlider
14331  * @extends Ext.slider.MultiSlider
14332  * Slider which supports vertical or horizontal orientation, keyboard adjustments,
14333  * configurable snapping, axis clicking and animation. Can be added as an item to
14334  * any container. Example usage:
14335 <pre><code>
14336 new Ext.slider.SingleSlider({
14337     renderTo: Ext.getBody(),
14338     width: 200,
14339     value: 50,
14340     increment: 10,
14341     minValue: 0,
14342     maxValue: 100
14343 });
14344 </code></pre>
14345  * The class Ext.slider.SingleSlider is aliased to Ext.Slider for backwards compatibility.
14346  */
14347 Ext.slider.SingleSlider = Ext.extend(Ext.slider.MultiSlider, {
14348     constructor: function(config) {
14349       config = config || {};
14350
14351       Ext.applyIf(config, {
14352           values: [config.value || 0]
14353       });
14354
14355       Ext.slider.SingleSlider.superclass.constructor.call(this, config);
14356     },
14357
14358     /**
14359      * Returns the current value of the slider
14360      * @return {Number} The current value of the slider
14361      */
14362     getValue: function() {
14363         //just returns the value of the first thumb, which should be the only one in a single slider
14364         return Ext.slider.SingleSlider.superclass.getValue.call(this, 0);
14365     },
14366
14367     /**
14368      * Programmatically sets the value of the Slider. Ensures that the value is constrained within
14369      * the minValue and maxValue.
14370      * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)
14371      * @param {Boolean} animate Turn on or off animation, defaults to true
14372      */
14373     setValue: function(value, animate) {
14374         var args = Ext.toArray(arguments),
14375             len  = args.length;
14376
14377         //this is to maintain backwards compatiblity for sliders with only one thunb. Usually you must pass the thumb
14378         //index to setValue, but if we only have one thumb we inject the index here first if given the multi-slider
14379         //signature without the required index. The index will always be 0 for a single slider
14380         if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
14381             args.unshift(0);
14382         }
14383
14384         return Ext.slider.SingleSlider.superclass.setValue.apply(this, args);
14385     },
14386
14387     /**
14388      * Synchronizes the thumb position to the proper proportion of the total component width based
14389      * on the current slider {@link #value}.  This will be called automatically when the Slider
14390      * is resized by a layout, but if it is rendered auto width, this method can be called from
14391      * another resize handler to sync the Slider if necessary.
14392      */
14393     syncThumb : function() {
14394         return Ext.slider.SingleSlider.superclass.syncThumb.apply(this, [0].concat(arguments));
14395     },
14396     
14397     // private
14398     getNearest : function(){
14399         // Since there's only 1 thumb, it's always the nearest
14400         return this.thumbs[0];    
14401     }
14402 });
14403
14404 //backwards compatibility
14405 Ext.Slider = Ext.slider.SingleSlider;
14406
14407 Ext.reg('slider', Ext.slider.SingleSlider);
14408
14409 // private class to support vertical sliders
14410 Ext.slider.Vertical = {
14411     onResize : function(w, h){
14412         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
14413         this.syncThumb();
14414     },
14415
14416     getRatio : function(){
14417         var h = this.innerEl.getHeight(),
14418             v = this.maxValue - this.minValue;
14419         return h/v;
14420     },
14421
14422     moveThumb: function(index, v, animate) {
14423         var thumb = this.thumbs[index],
14424             el    = thumb.el;
14425
14426         if (!animate || this.animate === false) {
14427             el.setBottom(v);
14428         } else {
14429             el.shift({bottom: v, stopFx: true, duration:.35});
14430         }
14431     },
14432
14433     onClickChange : function(local) {
14434         if (local.left > this.clickRange[0] && local.left < this.clickRange[1]) {
14435             var thumb = this.getNearest(local, 'top'),
14436                 index = thumb.index,
14437                 value = this.minValue + this.reverseValue(this.innerEl.getHeight() - local.top);
14438
14439             this.setValue(index, Ext.util.Format.round(value, this.decimalPrecision), undefined, true);
14440         }
14441     }
14442 };
14443
14444 //private class to support vertical dragging of thumbs within a slider
14445 Ext.slider.Thumb.Vertical = {
14446     getNewValue: function() {
14447         var slider   = this.slider,
14448             innerEl  = slider.innerEl,
14449             pos      = innerEl.translatePoints(this.tracker.getXY()),
14450             bottom   = innerEl.getHeight() - pos.top;
14451
14452         return slider.minValue + Ext.util.Format.round(bottom / slider.getRatio(), slider.decimalPrecision);
14453     }
14454 };
14455 /**
14456  * @class Ext.ProgressBar
14457  * @extends Ext.BoxComponent
14458  * <p>An updateable progress bar component.  The progress bar supports two different modes: manual and automatic.</p>
14459  * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the
14460  * progress bar as needed from your own code.  This method is most appropriate when you want to show progress
14461  * throughout an operation that has predictable points of interest at which you can update the control.</p>
14462  * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it
14463  * once the operation is complete.  You can optionally have the progress bar wait for a specific amount of time
14464  * and then clear itself.  Automatic mode is most appropriate for timed operations or asynchronous operations in
14465  * which you have no need for indicating intermediate progress.</p>
14466  * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0)
14467  * @cfg {String} text The progress bar text (defaults to '')
14468  * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress
14469  * bar's internal text element)
14470  * @cfg {String} id The progress bar element's id (defaults to an auto-generated id)
14471  * @xtype progress
14472  */
14473 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
14474    /**
14475     * @cfg {String} baseCls
14476     * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress')
14477     */
14478     baseCls : 'x-progress',
14479     
14480     /**
14481     * @cfg {Boolean} animate
14482     * True to animate the progress bar during transitions (defaults to false)
14483     */
14484     animate : false,
14485
14486     // private
14487     waitTimer : null,
14488
14489     // private
14490     initComponent : function(){
14491         Ext.ProgressBar.superclass.initComponent.call(this);
14492         this.addEvents(
14493             /**
14494              * @event update
14495              * Fires after each update interval
14496              * @param {Ext.ProgressBar} this
14497              * @param {Number} The current progress value
14498              * @param {String} The current progress text
14499              */
14500             "update"
14501         );
14502     },
14503
14504     // private
14505     onRender : function(ct, position){
14506         var tpl = new Ext.Template(
14507             '<div class="{cls}-wrap">',
14508                 '<div class="{cls}-inner">',
14509                     '<div class="{cls}-bar">',
14510                         '<div class="{cls}-text">',
14511                             '<div>&#160;</div>',
14512                         '</div>',
14513                     '</div>',
14514                     '<div class="{cls}-text {cls}-text-back">',
14515                         '<div>&#160;</div>',
14516                     '</div>',
14517                 '</div>',
14518             '</div>'
14519         );
14520
14521         this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
14522             : tpl.append(ct, {cls: this.baseCls}, true);
14523                 
14524         if(this.id){
14525             this.el.dom.id = this.id;
14526         }
14527         var inner = this.el.dom.firstChild;
14528         this.progressBar = Ext.get(inner.firstChild);
14529
14530         if(this.textEl){
14531             //use an external text el
14532             this.textEl = Ext.get(this.textEl);
14533             delete this.textTopEl;
14534         }else{
14535             //setup our internal layered text els
14536             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
14537             var textBackEl = Ext.get(inner.childNodes[1]);
14538             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
14539             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
14540             this.textEl.setWidth(inner.offsetWidth);
14541         }
14542         this.progressBar.setHeight(inner.offsetHeight);
14543     },
14544     
14545     // private
14546     afterRender : function(){
14547         Ext.ProgressBar.superclass.afterRender.call(this);
14548         if(this.value){
14549             this.updateProgress(this.value, this.text);
14550         }else{
14551             this.updateText(this.text);
14552         }
14553     },
14554
14555     /**
14556      * Updates the progress bar value, and optionally its text.  If the text argument is not specified,
14557      * any existing text value will be unchanged.  To blank out existing text, pass ''.  Note that even
14558      * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for
14559      * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control.
14560      * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0)
14561      * @param {String} text (optional) The string to display in the progress text element (defaults to '')
14562      * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is
14563      * not specified, the default for the class is used (default to false)
14564      * @return {Ext.ProgressBar} this
14565      */
14566     updateProgress : function(value, text, animate){
14567         this.value = value || 0;
14568         if(text){
14569             this.updateText(text);
14570         }
14571         if(this.rendered && !this.isDestroyed){
14572             var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
14573             this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
14574             if(this.textTopEl){
14575                 //textTopEl should be the same width as the bar so overflow will clip as the bar moves
14576                 this.textTopEl.removeClass('x-hidden').setWidth(w);
14577             }
14578         }
14579         this.fireEvent('update', this, value, text);
14580         return this;
14581     },
14582
14583     /**
14584      * Initiates an auto-updating progress bar.  A duration can be specified, in which case the progress
14585      * bar will automatically reset after a fixed amount of time and optionally call a callback function
14586      * if specified.  If no duration is passed in, then the progress bar will run indefinitely and must
14587      * be manually cleared by calling {@link #reset}.  The wait method accepts a config object with
14588      * the following properties:
14589      * <pre>
14590 Property   Type          Description
14591 ---------- ------------  ----------------------------------------------------------------------
14592 duration   Number        The length of time in milliseconds that the progress bar should
14593                          run before resetting itself (defaults to undefined, in which case it
14594                          will run indefinitely until reset is called)
14595 interval   Number        The length of time in milliseconds between each progress update
14596                          (defaults to 1000 ms)
14597 animate    Boolean       Whether to animate the transition of the progress bar. If this value is
14598                          not specified, the default for the class is used.                                                   
14599 increment  Number        The number of progress update segments to display within the progress
14600                          bar (defaults to 10).  If the bar reaches the end and is still
14601                          updating, it will automatically wrap back to the beginning.
14602 text       String        Optional text to display in the progress bar element (defaults to '').
14603 fn         Function      A callback function to execute after the progress bar finishes auto-
14604                          updating.  The function will be called with no arguments.  This function
14605                          will be ignored if duration is not specified since in that case the
14606                          progress bar can only be stopped programmatically, so any required function
14607                          should be called by the same code after it resets the progress bar.
14608 scope      Object        The scope that is passed to the callback function (only applies when
14609                          duration and fn are both passed).
14610 </pre>
14611          *
14612          * Example usage:
14613          * <pre><code>
14614 var p = new Ext.ProgressBar({
14615    renderTo: 'my-el'
14616 });
14617
14618 //Wait for 5 seconds, then update the status el (progress bar will auto-reset)
14619 p.wait({
14620    interval: 100, //bar will move fast!
14621    duration: 5000,
14622    increment: 15,
14623    text: 'Updating...',
14624    scope: this,
14625    fn: function(){
14626       Ext.fly('status').update('Done!');
14627    }
14628 });
14629
14630 //Or update indefinitely until some async action completes, then reset manually
14631 p.wait();
14632 myAction.on('complete', function(){
14633     p.reset();
14634     Ext.fly('status').update('Done!');
14635 });
14636 </code></pre>
14637      * @param {Object} config (optional) Configuration options
14638      * @return {Ext.ProgressBar} this
14639      */
14640     wait : function(o){
14641         if(!this.waitTimer){
14642             var scope = this;
14643             o = o || {};
14644             this.updateText(o.text);
14645             this.waitTimer = Ext.TaskMgr.start({
14646                 run: function(i){
14647                     var inc = o.increment || 10;
14648                     i -= 1;
14649                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
14650                 },
14651                 interval: o.interval || 1000,
14652                 duration: o.duration,
14653                 onStop: function(){
14654                     if(o.fn){
14655                         o.fn.apply(o.scope || this);
14656                     }
14657                     this.reset();
14658                 },
14659                 scope: scope
14660             });
14661         }
14662         return this;
14663     },
14664
14665     /**
14666      * Returns true if the progress bar is currently in a {@link #wait} operation
14667      * @return {Boolean} True if waiting, else false
14668      */
14669     isWaiting : function(){
14670         return this.waitTimer !== null;
14671     },
14672
14673     /**
14674      * Updates the progress bar text.  If specified, textEl will be updated, otherwise the progress
14675      * bar itself will display the updated text.
14676      * @param {String} text (optional) The string to display in the progress text element (defaults to '')
14677      * @return {Ext.ProgressBar} this
14678      */
14679     updateText : function(text){
14680         this.text = text || '&#160;';
14681         if(this.rendered){
14682             this.textEl.update(this.text);
14683         }
14684         return this;
14685     },
14686     
14687     /**
14688      * Synchronizes the inner bar width to the proper proportion of the total componet width based
14689      * on the current progress {@link #value}.  This will be called automatically when the ProgressBar
14690      * is resized by a layout, but if it is rendered auto width, this method can be called from
14691      * another resize handler to sync the ProgressBar if necessary.
14692      */
14693     syncProgressBar : function(){
14694         if(this.value){
14695             this.updateProgress(this.value, this.text);
14696         }
14697         return this;
14698     },
14699
14700     /**
14701      * Sets the size of the progress bar.
14702      * @param {Number} width The new width in pixels
14703      * @param {Number} height The new height in pixels
14704      * @return {Ext.ProgressBar} this
14705      */
14706     setSize : function(w, h){
14707         Ext.ProgressBar.superclass.setSize.call(this, w, h);
14708         if(this.textTopEl){
14709             var inner = this.el.dom.firstChild;
14710             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
14711         }
14712         this.syncProgressBar();
14713         return this;
14714     },
14715
14716     /**
14717      * Resets the progress bar value to 0 and text to empty string.  If hide = true, the progress
14718      * bar will also be hidden (using the {@link #hideMode} property internally).
14719      * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false)
14720      * @return {Ext.ProgressBar} this
14721      */
14722     reset : function(hide){
14723         this.updateProgress(0);
14724         if(this.textTopEl){
14725             this.textTopEl.addClass('x-hidden');
14726         }
14727         this.clearTimer();
14728         if(hide === true){
14729             this.hide();
14730         }
14731         return this;
14732     },
14733     
14734     // private
14735     clearTimer : function(){
14736         if(this.waitTimer){
14737             this.waitTimer.onStop = null; //prevent recursion
14738             Ext.TaskMgr.stop(this.waitTimer);
14739             this.waitTimer = null;
14740         }
14741     },
14742     
14743     onDestroy: function(){
14744         this.clearTimer();
14745         if(this.rendered){
14746             if(this.textEl.isComposite){
14747                 this.textEl.clear();
14748             }
14749             Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
14750         }
14751         Ext.ProgressBar.superclass.onDestroy.call(this);
14752     }
14753 });
14754 Ext.reg('progress', Ext.ProgressBar);