Upgrade to ExtJS 3.0.3 - Released 10/11/2009
[extjs.git] / pkgs / cmp-foundation-debug.js
1 /*!
2  * Ext JS Library 3.0.3
3  * Copyright(c) 2006-2009 Ext JS, LLC
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**
8  * @class Ext.ComponentMgr
9  * <p>Provides a registry of all Components (instances of {@link Ext.Component} or any subclass
10  * thereof) on a page so that they can be easily accessed by {@link Ext.Component component}
11  * {@link Ext.Component#id id} (see {@link #get}, or the convenience method {@link Ext#getCmp Ext.getCmp}).</p>
12  * <p>This object also provides a registry of available Component <i>classes</i>
13  * indexed by a mnemonic code known as the Component's {@link Ext.Component#xtype xtype}.
14  * The <code>{@link Ext.Component#xtype xtype}</code> provides a way to avoid instantiating child Components
15  * when creating a full, nested config object for a complete Ext page.</p>
16  * <p>A child Component may be specified simply as a <i>config object</i>
17  * as long as the correct <code>{@link Ext.Component#xtype xtype}</code> is specified so that if and when the Component
18  * needs rendering, the correct type can be looked up for lazy instantiation.</p>
19  * <p>For a list of all available <code>{@link Ext.Component#xtype xtypes}</code>, see {@link Ext.Component}.</p>
20  * @singleton
21  */
22 Ext.ComponentMgr = function(){
23     var all = new Ext.util.MixedCollection();
24     var types = {};
25     var ptypes = {};
26
27     return {
28         /**
29          * Registers a component.
30          * @param {Ext.Component} c The component
31          */
32         register : function(c){
33             all.add(c);
34         },
35
36         /**
37          * Unregisters a component.
38          * @param {Ext.Component} c The component
39          */
40         unregister : function(c){
41             all.remove(c);
42         },
43
44         /**
45          * Returns a component by {@link Ext.Component#id id}.
46          * For additional details see {@link Ext.util.MixedCollection#get}.
47          * @param {String} id The component {@link Ext.Component#id id}
48          * @return Ext.Component The Component, <code>undefined</code> if not found, or <code>null</code> if a
49          * Class was found.
50          */
51         get : function(id){
52             return all.get(id);
53         },
54
55         /**
56          * Registers a function that will be called when a specified component is added to ComponentMgr
57          * @param {String} id The component {@link Ext.Component#id id}
58          * @param {Function} fn The callback function
59          * @param {Object} scope The scope of the callback
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          * Checks if a Component type is registered.
79          * @param {Ext.Component} xtype The mnemonic string by which the Component class may be looked up
80          * @return {Boolean} Whether the type is registered.
81          */
82         isRegistered : function(xtype){
83             return types[xtype] !== undefined;    
84         },
85
86         /**
87          * <p>Registers a new Component constructor, keyed by a new
88          * {@link Ext.Component#xtype}.</p>
89          * <p>Use this method (or its alias {@link Ext#reg Ext.reg}) to register new
90          * subclasses of {@link Ext.Component} so that lazy instantiation may be used when specifying
91          * child Components.
92          * see {@link Ext.Container#items}</p>
93          * @param {String} xtype The mnemonic string by which the Component class may be looked up.
94          * @param {Constructor} cls The new Component class.
95          */
96         registerType : function(xtype, cls){
97             types[xtype] = cls;
98             cls.xtype = xtype;
99         },
100
101         /**
102          * Creates a new Component from the specified config object using the
103          * config object's {@link Ext.component#xtype xtype} to determine the class to instantiate.
104          * @param {Object} config A configuration object for the Component you wish to create.
105          * @param {Constructor} defaultType The constructor to provide the default Component type if
106          * the config object does not contain a <code>xtype</code>. (Optional if the config contains a <code>xtype</code>).
107          * @return {Ext.Component} The newly instantiated Component.
108          */
109         create : function(config, defaultType){
110             return config.render ? config : new types[config.xtype || defaultType](config);
111         },
112
113         /**
114          * <p>Registers a new Plugin constructor, keyed by a new
115          * {@link Ext.Component#ptype}.</p>
116          * <p>Use this method (or its alias {@link Ext#preg Ext.preg}) to register new
117          * plugins for {@link Ext.Component}s so that lazy instantiation may be used when specifying
118          * Plugins.</p>
119          * @param {String} ptype The mnemonic string by which the Plugin class may be looked up.
120          * @param {Constructor} cls The new Plugin class.
121          */
122         registerPlugin : function(ptype, cls){
123             ptypes[ptype] = cls;
124             cls.ptype = ptype;
125         },
126
127         /**
128          * Creates a new Plugin from the specified config object using the
129          * config object's {@link Ext.component#ptype ptype} to determine the class to instantiate.
130          * @param {Object} config A configuration object for the Plugin you wish to create.
131          * @param {Constructor} defaultType The constructor to provide the default Plugin type if
132          * the config object does not contain a <code>ptype</code>. (Optional if the config contains a <code>ptype</code>).
133          * @return {Ext.Component} The newly instantiated Plugin.
134          */
135         createPlugin : function(config, defaultType){
136             return new ptypes[config.ptype || defaultType](config);
137         }
138     };
139 }();
140
141 /**
142  * Shorthand for {@link Ext.ComponentMgr#registerType}
143  * @param {String} xtype The {@link Ext.component#xtype mnemonic string} by which the Component class
144  * may be looked up.
145  * @param {Constructor} cls The new Component class.
146  * @member Ext
147  * @method reg
148  */
149 Ext.reg = Ext.ComponentMgr.registerType; // this will be called a lot internally, shorthand to keep the bytes down
150 /**
151  * Shorthand for {@link Ext.ComponentMgr#registerPlugin}
152  * @param {String} ptype The {@link Ext.component#ptype mnemonic string} by which the Plugin class
153  * may be looked up.
154  * @param {Constructor} cls The new Plugin class.
155  * @member Ext
156  * @method preg
157  */
158 Ext.preg = Ext.ComponentMgr.registerPlugin;
159 /**
160  * Shorthand for {@link Ext.ComponentMgr#create}
161  * Creates a new Component from the specified config object using the
162  * config object's {@link Ext.component#xtype xtype} to determine the class to instantiate.
163  * @param {Object} config A configuration object for the Component you wish to create.
164  * @param {Constructor} defaultType The constructor to provide the default Component type if
165  * the config object does not contain a <code>xtype</code>. (Optional if the config contains a <code>xtype</code>).
166  * @return {Ext.Component} The newly instantiated Component.
167  * @member Ext
168  * @method create
169  */
170 Ext.create = Ext.ComponentMgr.create;/**
171  * @class Ext.Component
172  * @extends Ext.util.Observable
173  * <p>Base class for all Ext components.  All subclasses of Component may participate in the automated
174  * Ext component lifecycle of creation, rendering and destruction which is provided by the {@link Ext.Container Container} class.
175  * Components may be added to a Container through the {@link Ext.Container#items items} config option at the time the Container is created,
176  * or they may be added dynamically via the {@link Ext.Container#add add} method.</p>
177  * <p>The Component base class has built-in support for basic hide/show and enable/disable behavior.</p>
178  * <p>All Components are registered with the {@link Ext.ComponentMgr} on construction so that they can be referenced at any time via
179  * {@link Ext#getCmp}, passing the {@link #id}.</p>
180  * <p>All user-developed visual widgets that are required to participate in automated lifecycle and size management should subclass Component (or
181  * {@link Ext.BoxComponent} if managed box model handling is required, ie height and width management).</p>
182  * <p>See the <a href="http://extjs.com/learn/Tutorial:Creating_new_UI_controls">Creating new UI controls</a> tutorial for details on how
183  * and to either extend or augment ExtJs base classes to create custom Components.</p>
184  * <p>Every component has a specific xtype, which is its Ext-specific type name, along with methods for checking the
185  * xtype like {@link #getXType} and {@link #isXType}. This is the list of all valid xtypes:</p>
186  * <pre>
187 xtype            Class
188 -------------    ------------------
189 box              {@link Ext.BoxComponent}
190 button           {@link Ext.Button}
191 buttongroup      {@link Ext.ButtonGroup}
192 colorpalette     {@link Ext.ColorPalette}
193 component        {@link Ext.Component}
194 container        {@link Ext.Container}
195 cycle            {@link Ext.CycleButton}
196 dataview         {@link Ext.DataView}
197 datepicker       {@link Ext.DatePicker}
198 editor           {@link Ext.Editor}
199 editorgrid       {@link Ext.grid.EditorGridPanel}
200 flash            {@link Ext.FlashComponent}
201 grid             {@link Ext.grid.GridPanel}
202 listview         {@link Ext.ListView}
203 panel            {@link Ext.Panel}
204 progress         {@link Ext.ProgressBar}
205 propertygrid     {@link Ext.grid.PropertyGrid}
206 slider           {@link Ext.Slider}
207 spacer           {@link Ext.Spacer}
208 splitbutton      {@link Ext.SplitButton}
209 tabpanel         {@link Ext.TabPanel}
210 treepanel        {@link Ext.tree.TreePanel}
211 viewport         {@link Ext.ViewPort}
212 window           {@link Ext.Window}
213
214 Toolbar components
215 ---------------------------------------
216 paging           {@link Ext.PagingToolbar}
217 toolbar          {@link Ext.Toolbar}
218 tbbutton         {@link Ext.Toolbar.Button}        (deprecated; use button)
219 tbfill           {@link Ext.Toolbar.Fill}
220 tbitem           {@link Ext.Toolbar.Item}
221 tbseparator      {@link Ext.Toolbar.Separator}
222 tbspacer         {@link Ext.Toolbar.Spacer}
223 tbsplit          {@link Ext.Toolbar.SplitButton}   (deprecated; use splitbutton)
224 tbtext           {@link Ext.Toolbar.TextItem}
225
226 Menu components
227 ---------------------------------------
228 menu             {@link Ext.menu.Menu}
229 colormenu        {@link Ext.menu.ColorMenu}
230 datemenu         {@link Ext.menu.DateMenu}
231 menubaseitem     {@link Ext.menu.BaseItem}
232 menucheckitem    {@link Ext.menu.CheckItem}
233 menuitem         {@link Ext.menu.Item}
234 menuseparator    {@link Ext.menu.Separator}
235 menutextitem     {@link Ext.menu.TextItem}
236
237 Form components
238 ---------------------------------------
239 form             {@link Ext.FormPanel}
240 checkbox         {@link Ext.form.Checkbox}
241 checkboxgroup    {@link Ext.form.CheckboxGroup}
242 combo            {@link Ext.form.ComboBox}
243 datefield        {@link Ext.form.DateField}
244 displayfield     {@link Ext.form.DisplayField}
245 field            {@link Ext.form.Field}
246 fieldset         {@link Ext.form.FieldSet}
247 hidden           {@link Ext.form.Hidden}
248 htmleditor       {@link Ext.form.HtmlEditor}
249 label            {@link Ext.form.Label}
250 numberfield      {@link Ext.form.NumberField}
251 radio            {@link Ext.form.Radio}
252 radiogroup       {@link Ext.form.RadioGroup}
253 textarea         {@link Ext.form.TextArea}
254 textfield        {@link Ext.form.TextField}
255 timefield        {@link Ext.form.TimeField}
256 trigger          {@link Ext.form.TriggerField}
257
258 Chart components
259 ---------------------------------------
260 chart            {@link Ext.chart.Chart}
261 barchart         {@link Ext.chart.BarChart}
262 cartesianchart   {@link Ext.chart.CartesianChart}
263 columnchart      {@link Ext.chart.ColumnChart}
264 linechart        {@link Ext.chart.LineChart}
265 piechart         {@link Ext.chart.PieChart}
266
267 Store xtypes
268 ---------------------------------------
269 arraystore       {@link Ext.data.ArrayStore}
270 directstore      {@link Ext.data.DirectStore}
271 groupingstore    {@link Ext.data.GroupingStore}
272 jsonstore        {@link Ext.data.JsonStore}
273 simplestore      {@link Ext.data.SimpleStore}      (deprecated; use arraystore)
274 store            {@link Ext.data.Store}
275 xmlstore         {@link Ext.data.XmlStore}
276 </pre>
277  * @constructor
278  * @param {Ext.Element/String/Object} config The configuration options may be specified as either:
279  * <div class="mdetail-params"><ul>
280  * <li><b>an element</b> :
281  * <p class="sub-desc">it is set as the internal element and its id used as the component id</p></li>
282  * <li><b>a string</b> :
283  * <p class="sub-desc">it is assumed to be the id of an existing element and is used as the component id</p></li>
284  * <li><b>anything else</b> :
285  * <p class="sub-desc">it is assumed to be a standard config object and is applied to the component</p></li>
286  * </ul></div>
287  */
288 Ext.Component = function(config){
289     config = config || {};
290     if(config.initialConfig){
291         if(config.isAction){           // actions
292             this.baseAction = config;
293         }
294         config = config.initialConfig; // component cloning / action set up
295     }else if(config.tagName || config.dom || Ext.isString(config)){ // element object
296         config = {applyTo: config, id: config.id || config};
297     }
298
299     /**
300      * This Component's initial configuration specification. Read-only.
301      * @type Object
302      * @property initialConfig
303      */
304     this.initialConfig = config;
305
306     Ext.apply(this, config);
307     this.addEvents(
308         /**
309          * @event disable
310          * Fires after the component is disabled.
311          * @param {Ext.Component} this
312          */
313         'disable',
314         /**
315          * @event enable
316          * Fires after the component is enabled.
317          * @param {Ext.Component} this
318          */
319         'enable',
320         /**
321          * @event beforeshow
322          * Fires before the component is shown by calling the {@link #show} method.
323          * Return false from an event handler to stop the show.
324          * @param {Ext.Component} this
325          */
326         'beforeshow',
327         /**
328          * @event show
329          * Fires after the component is shown when calling the {@link #show} method.
330          * @param {Ext.Component} this
331          */
332         'show',
333         /**
334          * @event beforehide
335          * Fires before the component is hidden by calling the {@link #hide} method.
336          * Return false from an event handler to stop the hide.
337          * @param {Ext.Component} this
338          */
339         'beforehide',
340         /**
341          * @event hide
342          * Fires after the component is hidden.
343          * Fires after the component is hidden when calling the {@link #hide} method.
344          * @param {Ext.Component} this
345          */
346         'hide',
347         /**
348          * @event beforerender
349          * Fires before the component is {@link #rendered}. Return false from an
350          * event handler to stop the {@link #render}.
351          * @param {Ext.Component} this
352          */
353         'beforerender',
354         /**
355          * @event render
356          * Fires after the component markup is {@link #rendered}.
357          * @param {Ext.Component} this
358          */
359         'render',
360         /**
361          * @event afterrender
362          * <p>Fires after the component rendering is finished.</p>
363          * <p>The afterrender event is fired after this Component has been {@link #rendered}, been postprocesed
364          * by any afterRender method defined for the Component, and, if {@link #stateful}, after state
365          * has been restored.</p>
366          * @param {Ext.Component} this
367          */
368         'afterrender',
369         /**
370          * @event beforedestroy
371          * Fires before the component is {@link #destroy}ed. Return false from an event handler to stop the {@link #destroy}.
372          * @param {Ext.Component} this
373          */
374         'beforedestroy',
375         /**
376          * @event destroy
377          * Fires after the component is {@link #destroy}ed.
378          * @param {Ext.Component} this
379          */
380         'destroy',
381         /**
382          * @event beforestaterestore
383          * Fires before the state of the component is restored. Return false from an event handler to stop the restore.
384          * @param {Ext.Component} this
385          * @param {Object} state The hash of state values returned from the StateProvider. If this
386          * event is not vetoed, then the state object is passed to <b><tt>applyState</tt></b>. By default,
387          * that simply copies property values into this Component. The method maybe overriden to
388          * provide custom state restoration.
389          */
390         'beforestaterestore',
391         /**
392          * @event staterestore
393          * Fires after the state of the component is restored.
394          * @param {Ext.Component} this
395          * @param {Object} state The hash of state values returned from the StateProvider. This is passed
396          * to <b><tt>applyState</tt></b>. By default, that simply copies property values into this
397          * Component. The method maybe overriden to provide custom state restoration.
398          */
399         'staterestore',
400         /**
401          * @event beforestatesave
402          * Fires before the state of the component is saved to the configured state provider. Return false to stop the save.
403          * @param {Ext.Component} this
404          * @param {Object} state The hash of state values. This is determined by calling
405          * <b><tt>getState()</tt></b> on the Component. This method must be provided by the
406          * developer to return whetever representation of state is required, by default, Ext.Component
407          * has a null implementation.
408          */
409         'beforestatesave',
410         /**
411          * @event statesave
412          * Fires after the state of the component is saved to the configured state provider.
413          * @param {Ext.Component} this
414          * @param {Object} state The hash of state values. This is determined by calling
415          * <b><tt>getState()</tt></b> on the Component. This method must be provided by the
416          * developer to return whetever representation of state is required, by default, Ext.Component
417          * has a null implementation.
418          */
419         'statesave'
420     );
421     this.getId();
422     Ext.ComponentMgr.register(this);
423     Ext.Component.superclass.constructor.call(this);
424
425     if(this.baseAction){
426         this.baseAction.addComponent(this);
427     }
428
429     this.initComponent();
430
431     if(this.plugins){
432         if(Ext.isArray(this.plugins)){
433             for(var i = 0, len = this.plugins.length; i < len; i++){
434                 this.plugins[i] = this.initPlugin(this.plugins[i]);
435             }
436         }else{
437             this.plugins = this.initPlugin(this.plugins);
438         }
439     }
440
441     if(this.stateful !== false){
442         this.initState(config);
443     }
444
445     if(this.applyTo){
446         this.applyToMarkup(this.applyTo);
447         delete this.applyTo;
448     }else if(this.renderTo){
449         this.render(this.renderTo);
450         delete this.renderTo;
451     }
452 };
453
454 // private
455 Ext.Component.AUTO_ID = 1000;
456
457 Ext.extend(Ext.Component, Ext.util.Observable, {
458     // Configs below are used for all Components when rendered by FormLayout.
459     /**
460      * @cfg {String} fieldLabel <p>The label text to display next to this Component (defaults to '').</p>
461      * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container which
462      * has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout manager (e.g.
463      * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>).</p><br>
464      * <p>Also see <tt>{@link #hideLabel}</tt> and
465      * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</p>
466      * Example use:<pre><code>
467 new Ext.FormPanel({
468     height: 100,
469     renderTo: Ext.getBody(),
470     items: [{
471         xtype: 'textfield',
472         fieldLabel: 'Name'
473     }]
474 });
475 </code></pre>
476      */
477     /**
478      * @cfg {String} labelStyle <p>A CSS style specification string to apply directly to this field's
479      * label.  Defaults to the container's labelStyle value if set (e.g.,
480      * <tt>{@link Ext.layout.FormLayout#labelStyle}</tt> , or '').</p>
481      * <br><p><b>Note</b>: see the note for <code>{@link #clearCls}</code>.</p><br>
482      * <p>Also see <code>{@link #hideLabel}</code> and
483      * <code>{@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</code></p>
484      * Example use:<pre><code>
485 new Ext.FormPanel({
486     height: 100,
487     renderTo: Ext.getBody(),
488     items: [{
489         xtype: 'textfield',
490         fieldLabel: 'Name',
491         labelStyle: 'font-weight:bold;'
492     }]
493 });
494 </code></pre>
495      */
496     /**
497      * @cfg {String} labelSeparator <p>The separator to display after the text of each
498      * <tt>{@link #fieldLabel}</tt>.  This property may be configured at various levels.
499      * The order of precedence is:
500      * <div class="mdetail-params"><ul>
501      * <li>field / component level</li>
502      * <li>container level</li>
503      * <li>{@link Ext.layout.FormLayout#labelSeparator layout level} (defaults to colon <tt>':'</tt>)</li>
504      * </ul></div>
505      * To display no separator for this field's label specify empty string ''.</p>
506      * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</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     layoutConfig: {
514         labelSeparator: '~'   // layout config has lowest priority (defaults to ':')
515     },
516     {@link Ext.layout.FormLayout#labelSeparator labelSeparator}: '>>',     // config at container level
517     items: [{
518         xtype: 'textfield',
519         fieldLabel: 'Field 1',
520         labelSeparator: '...' // field/component level config supersedes others
521     },{
522         xtype: 'textfield',
523         fieldLabel: 'Field 2' // labelSeparator will be '='
524     }]
525 });
526 </code></pre>
527      */
528     /**
529      * @cfg {Boolean} hideLabel <p><tt>true</tt> to completely hide the label element
530      * ({@link #fieldLabel label} and {@link #labelSeparator separator}). Defaults to <tt>false</tt>.
531      * By default, even if you do not specify a <tt>{@link #fieldLabel}</tt> the space will still be
532      * reserved so that the field will line up with other fields that do have labels.
533      * Setting this to <tt>true</tt> will cause the field to not reserve that space.</p>
534      * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</tt>.</p><br>
535      * Example use:<pre><code>
536 new Ext.FormPanel({
537     height: 100,
538     renderTo: Ext.getBody(),
539     items: [{
540         xtype: 'textfield'
541         hideLabel: true
542     }]
543 });
544 </code></pre>
545      */
546     /**
547      * @cfg {String} clearCls <p>The CSS class used to to apply to the special clearing div rendered
548      * directly after each form field wrapper to provide field clearing (defaults to
549      * <tt>'x-form-clear-left'</tt>).</p>
550      * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container
551      * which has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout
552      * manager (e.g. {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) and either a
553      * <tt>{@link #fieldLabel}</tt> is specified or <tt>isFormField=true</tt> is specified.</p><br>
554      * <p>See {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl} also.</p>
555      */
556     /**
557      * @cfg {String} itemCls
558      * <p><b>Note</b>: this config is only used when this Component is rendered by a Container which
559      * has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout manager (e.g.
560      * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>).</p><br>
561      * <p>An additional CSS class to apply to the div wrapping the form item
562      * element of this field.  If supplied, <tt>itemCls</tt> at the <b>field</b> level will override
563      * the default <tt>itemCls</tt> supplied at the <b>container</b> level. The value specified for
564      * <tt>itemCls</tt> will be added to the default class (<tt>'x-form-item'</tt>).</p>
565      * <p>Since it is applied to the item wrapper (see
566      * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}), it allows
567      * you to write standard CSS rules that can apply to the field, the label (if specified), or
568      * any other element within the markup for the field.</p>
569      * <br><p><b>Note</b>: see the note for <tt>{@link #fieldLabel}</tt>.</p><br>
570      * Example use:<pre><code>
571 // Apply a style to the field&#39;s label:
572 &lt;style>
573     .required .x-form-item-label {font-weight:bold;color:red;}
574 &lt;/style>
575
576 new Ext.FormPanel({
577     height: 100,
578     renderTo: Ext.getBody(),
579     items: [{
580         xtype: 'textfield',
581         fieldLabel: 'Name',
582         itemCls: 'required' //this label will be styled
583     },{
584         xtype: 'textfield',
585         fieldLabel: 'Favorite Color'
586     }]
587 });
588 </code></pre>
589      */
590
591     // Configs below are used for all Components when rendered by AnchorLayout.
592     /**
593      * @cfg {String} anchor <p><b>Note</b>: this config is only used when this Component is rendered
594      * by a Container which has been configured to use an <b>{@link Ext.layout.AnchorLayout AnchorLayout}</b>
595      * based layout manager, for example:<div class="mdetail-params"><ul>
596      * <li>{@link Ext.form.FormPanel}</li>
597      * <li>specifying <code>layout: 'anchor' // or 'form', or 'absolute'</code></li>
598      * </ul></div></p>
599      * <p>See {@link Ext.layout.AnchorLayout}.{@link Ext.layout.AnchorLayout#anchor anchor} also.</p>
600      */
601
602     /**
603      * @cfg {String} id
604      * <p>The <b>unique</b> id of this component (defaults to an {@link #getId auto-assigned id}).
605      * You should assign an id if you need to be able to access the component later and you do
606      * not have an object reference available (e.g., using {@link Ext}.{@link Ext#getCmp getCmp}).</p>
607      * <p>Note that this id will also be used as the element id for the containing HTML element
608      * that is rendered to the page for this component. This allows you to write id-based CSS
609      * rules to style the specific instance of this component uniquely, and also to select
610      * sub-elements using this component's id as the parent.</p>
611      * <p><b>Note</b>: to avoid complications imposed by a unique <tt>id</tt> also see
612      * <code>{@link #itemId}</code> and <code>{@link #ref}</code>.</p>
613      * <p><b>Note</b>: to access the container of an item see <code>{@link #ownerCt}</code>.</p>
614      */
615     /**
616      * @cfg {String} itemId
617      * <p>An <tt>itemId</tt> can be used as an alternative way to get a reference to a component
618      * when no object reference is available.  Instead of using an <code>{@link #id}</code> with
619      * {@link Ext}.{@link Ext#getCmp getCmp}, use <code>itemId</code> with
620      * {@link Ext.Container}.{@link Ext.Container#getComponent getComponent} which will retrieve
621      * <code>itemId</code>'s or <tt>{@link #id}</tt>'s. Since <code>itemId</code>'s are an index to the
622      * container's internal MixedCollection, the <code>itemId</code> is scoped locally to the container --
623      * avoiding potential conflicts with {@link Ext.ComponentMgr} which requires a <b>unique</b>
624      * <code>{@link #id}</code>.</p>
625      * <pre><code>
626 var c = new Ext.Panel({ //
627     {@link Ext.BoxComponent#height height}: 300,
628     {@link #renderTo}: document.body,
629     {@link Ext.Container#layout layout}: 'auto',
630     {@link Ext.Container#items items}: [
631         {
632             itemId: 'p1',
633             {@link Ext.Panel#title title}: 'Panel 1',
634             {@link Ext.BoxComponent#height height}: 150
635         },
636         {
637             itemId: 'p2',
638             {@link Ext.Panel#title title}: 'Panel 2',
639             {@link Ext.BoxComponent#height height}: 150
640         }
641     ]
642 })
643 p1 = c.{@link Ext.Container#getComponent getComponent}('p1'); // not the same as {@link Ext#getCmp Ext.getCmp()}
644 p2 = p1.{@link #ownerCt}.{@link Ext.Container#getComponent getComponent}('p2'); // reference via a sibling
645      * </code></pre>
646      * <p>Also see <tt>{@link #id}</tt> and <code>{@link #ref}</code>.</p>
647      * <p><b>Note</b>: to access the container of an item see <tt>{@link #ownerCt}</tt>.</p>
648      */
649     /**
650      * @cfg {String} xtype
651      * The registered <tt>xtype</tt> to create. This config option is not used when passing
652      * a config object into a constructor. This config option is used only when
653      * lazy instantiation is being used, and a child item of a Container is being
654      * specified not as a fully instantiated Component, but as a <i>Component config
655      * object</i>. The <tt>xtype</tt> will be looked up at render time up to determine what
656      * type of child Component to create.<br><br>
657      * The predefined xtypes are listed {@link Ext.Component here}.
658      * <br><br>
659      * If you subclass Components to create your own Components, you may register
660      * them using {@link Ext.ComponentMgr#registerType} in order to be able to
661      * take advantage of lazy instantiation and rendering.
662      */
663     /**
664      * @cfg {String} ptype
665      * The registered <tt>ptype</tt> to create. This config option is not used when passing
666      * a config object into a constructor. This config option is used only when
667      * lazy instantiation is being used, and a Plugin is being
668      * specified not as a fully instantiated Component, but as a <i>Component config
669      * object</i>. The <tt>ptype</tt> will be looked up at render time up to determine what
670      * type of Plugin to create.<br><br>
671      * If you create your own Plugins, you may register them using
672      * {@link Ext.ComponentMgr#registerPlugin} in order to be able to
673      * take advantage of lazy instantiation and rendering.
674      */
675     /**
676      * @cfg {String} cls
677      * An optional extra CSS class that will be added to this component's Element (defaults to '').  This can be
678      * useful for adding customized styles to the component or any of its children using standard CSS rules.
679      */
680     /**
681      * @cfg {String} overCls
682      * An optional extra CSS class that will be added to this component's Element when the mouse moves
683      * over the Element, and removed when the mouse moves out. (defaults to '').  This can be
684      * useful for adding customized 'active' or 'hover' styles to the component or any of its children using standard CSS rules.
685      */
686     /**
687      * @cfg {String} style
688      * A custom style specification to be applied to this component's Element.  Should be a valid argument to
689      * {@link Ext.Element#applyStyles}.
690      * <pre><code>
691 new Ext.Panel({
692     title: 'Some Title',
693     renderTo: Ext.getBody(),
694     width: 400, height: 300,
695     layout: 'form',
696     items: [{
697         xtype: 'textarea',
698         style: {
699             width: '95%',
700             marginBottom: '10px'
701         }
702     },
703         new Ext.Button({
704             text: 'Send',
705             minWidth: '100',
706             style: {
707                 marginBottom: '10px'
708             }
709         })
710     ]
711 });
712      * </code></pre>
713      */
714     /**
715      * @cfg {String} ctCls
716      * <p>An optional extra CSS class that will be added to this component's container. This can be useful for
717      * adding customized styles to the container or any of its children using standard CSS rules.  See
718      * {@link Ext.layout.ContainerLayout}.{@link Ext.layout.ContainerLayout#extraCls extraCls} also.</p>
719      * <p><b>Note</b>: <tt>ctCls</tt> defaults to <tt>''</tt> except for the following class
720      * which assigns a value by default:
721      * <div class="mdetail-params"><ul>
722      * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-layout-ct'</tt></li>
723      * </ul></div>
724      * To configure the above Class with an extra CSS class append to the default.  For example,
725      * for BoxLayout (Hbox and Vbox):<pre><code>
726      * ctCls: 'x-box-layout-ct custom-class'
727      * </code></pre>
728      * </p>
729      */
730     /**
731      * @cfg {Boolean} disabled
732      * Render this component disabled (default is false).
733      */
734     disabled : false,
735     /**
736      * @cfg {Boolean} hidden
737      * Render this component hidden (default is false). If <tt>true</tt>, the
738      * {@link #hide} method will be called internally.
739      */
740     hidden : false,
741     /**
742      * @cfg {Object/Array} plugins
743      * An object or array of objects that will provide custom functionality for this component.  The only
744      * requirement for a valid plugin is that it contain an init method that accepts a reference of type Ext.Component.
745      * When a component is created, if any plugins are available, the component will call the init method on each
746      * plugin, passing a reference to itself.  Each plugin can then call methods or respond to events on the
747      * component as needed to provide its functionality.
748      */
749     /**
750      * @cfg {Mixed} applyTo
751      * <p>Specify the id of the element, a DOM element or an existing Element corresponding to a DIV
752      * that is already present in the document that specifies some structural markup for this
753      * component.</p><div><ul>
754      * <li><b>Description</b> : <ul>
755      * <div class="sub-desc">When <tt>applyTo</tt> is used, constituent parts of the component can also be specified
756      * by id or CSS class name within the main element, and the component being created may attempt
757      * to create its subcomponents from that markup if applicable.</div>
758      * </ul></li>
759      * <li><b>Notes</b> : <ul>
760      * <div class="sub-desc">When using this config, a call to render() is not required.</div>
761      * <div class="sub-desc">If applyTo is specified, any value passed for {@link #renderTo} will be ignored and the target
762      * element's parent node will automatically be used as the component's container.</div>
763      * </ul></li>
764      * </ul></div>
765      */
766     /**
767      * @cfg {Mixed} renderTo
768      * <p>Specify the id of the element, a DOM element or an existing Element that this component
769      * will be rendered into.</p><div><ul>
770      * <li><b>Notes</b> : <ul>
771      * <div class="sub-desc">Do <u>not</u> use this option if the Component is to be a child item of
772      * a {@link Ext.Container Container}. It is the responsibility of the
773      * {@link Ext.Container Container}'s {@link Ext.Container#layout layout manager}
774      * to render and manage its child items.</div>
775      * <div class="sub-desc">When using this config, a call to render() is not required.</div>
776      * </ul></li>
777      * </ul></div>
778      * <p>See <tt>{@link #render}</tt> also.</p>
779      */
780     /**
781      * @cfg {Boolean} stateful
782      * <p>A flag which causes the Component to attempt to restore the state of
783      * internal properties from a saved state on startup. The component must have
784      * either a <code>{@link #stateId}</code> or <code>{@link #id}</code> assigned
785      * for state to be managed. Auto-generated ids are not guaranteed to be stable
786      * across page loads and cannot be relied upon to save and restore the same
787      * state for a component.<p>
788      * <p>For state saving to work, the state manager's provider must have been
789      * set to an implementation of {@link Ext.state.Provider} which overrides the
790      * {@link Ext.state.Provider#set set} and {@link Ext.state.Provider#get get}
791      * methods to save and recall name/value pairs. A built-in implementation,
792      * {@link Ext.state.CookieProvider} is available.</p>
793      * <p>To set the state provider for the current page:</p>
794      * <pre><code>
795 Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
796     expires: new Date(new Date().getTime()+(1000*60*60*24*7)), //7 days from now
797 }));
798      * </code></pre>
799      * <p>A stateful Component attempts to save state when one of the events
800      * listed in the <code>{@link #stateEvents}</code> configuration fires.</p>
801      * <p>To save state, a stateful Component first serializes its state by
802      * calling <b><code>getState</code></b>. By default, this function does
803      * nothing. The developer must provide an implementation which returns an
804      * object hash which represents the Component's restorable state.</p>
805      * <p>The value yielded by getState is passed to {@link Ext.state.Manager#set}
806      * which uses the configured {@link Ext.state.Provider} to save the object
807      * keyed by the Component's <code>{@link stateId}</code>, or, if that is not
808      * specified, its <code>{@link #id}</code>.</p>
809      * <p>During construction, a stateful Component attempts to <i>restore</i>
810      * its state by calling {@link Ext.state.Manager#get} passing the
811      * <code>{@link #stateId}</code>, or, if that is not specified, the
812      * <code>{@link #id}</code>.</p>
813      * <p>The resulting object is passed to <b><code>applyState</code></b>.
814      * The default implementation of <code>applyState</code> simply copies
815      * properties into the object, but a developer may override this to support
816      * more behaviour.</p>
817      * <p>You can perform extra processing on state save and restore by attaching
818      * handlers to the {@link #beforestaterestore}, {@link #staterestore},
819      * {@link #beforestatesave} and {@link #statesave} events.</p>
820      */
821     /**
822      * @cfg {String} stateId
823      * The unique id for this component to use for state management purposes
824      * (defaults to the component id if one was set, otherwise null if the
825      * component is using a generated id).
826      * <p>See <code>{@link #stateful}</code> for an explanation of saving and
827      * restoring Component state.</p>
828      */
829     /**
830      * @cfg {Array} stateEvents
831      * <p>An array of events that, when fired, should trigger this component to
832      * save its state (defaults to none). <code>stateEvents</code> may be any type
833      * of event supported by this component, including browser or custom events
834      * (e.g., <tt>['click', 'customerchange']</tt>).</p>
835      * <p>See <code>{@link #stateful}</code> for an explanation of saving and
836      * restoring Component state.</p>
837      */
838     /**
839      * @cfg {Mixed} autoEl
840      * <p>A tag name or {@link Ext.DomHelper DomHelper} spec used to create the {@link #getEl Element} which will
841      * encapsulate this Component.</p>
842      * <p>You do not normally need to specify this. For the base classes {@link Ext.Component}, {@link Ext.BoxComponent},
843      * and {@link Ext.Container}, this defaults to <b><tt>'div'</tt></b>. The more complex Ext classes use a more complex
844      * DOM structure created by their own onRender methods.</p>
845      * <p>This is intended to allow the developer to create application-specific utility Components encapsulated by
846      * different DOM elements. Example usage:</p><pre><code>
847 {
848     xtype: 'box',
849     autoEl: {
850         tag: 'img',
851         src: 'http://www.example.com/example.jpg'
852     }
853 }, {
854     xtype: 'box',
855     autoEl: {
856         tag: 'blockquote',
857         html: 'autoEl is cool!'
858     }
859 }, {
860     xtype: 'container',
861     autoEl: 'ul',
862     cls: 'ux-unordered-list',
863     items: {
864         xtype: 'box',
865         autoEl: 'li',
866         html: 'First list item'
867     }
868 }
869 </code></pre>
870      */
871     autoEl : 'div',
872
873     /**
874      * @cfg {String} disabledClass
875      * CSS class added to the component when it is disabled (defaults to 'x-item-disabled').
876      */
877     disabledClass : 'x-item-disabled',
878     /**
879      * @cfg {Boolean} allowDomMove
880      * Whether the component can move the Dom node when rendering (defaults to true).
881      */
882     allowDomMove : true,
883     /**
884      * @cfg {Boolean} autoShow
885      * True if the component should check for hidden classes (e.g. 'x-hidden' or 'x-hide-display') and remove
886      * them on render (defaults to false).
887      */
888     autoShow : false,
889     /**
890      * @cfg {String} hideMode
891      * <p>How this component should be hidden. Supported values are <tt>'visibility'</tt>
892      * (css visibility), <tt>'offsets'</tt> (negative offset position) and <tt>'display'</tt>
893      * (css display).</p>
894      * <br><p><b>Note</b>: the default of <tt>'display'</tt> is generally preferred
895      * since items are automatically laid out when they are first shown (no sizing
896      * is done while hidden).</p>
897      */
898     hideMode : 'display',
899     /**
900      * @cfg {Boolean} hideParent
901      * True to hide and show the component's container when hide/show is called on the component, false to hide
902      * and show the component itself (defaults to false).  For example, this can be used as a shortcut for a hide
903      * button on a window by setting hide:true on the button when adding it to its parent container.
904      */
905     hideParent : false,
906     /**
907      * <p>The {@link Ext.Element} which encapsulates this Component. Read-only.</p>
908      * <p>This will <i>usually</i> be a &lt;DIV> element created by the class's onRender method, but
909      * that may be overridden using the <code>{@link #autoEl}</code> config.</p>
910      * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br>
911      * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners
912      * for this Component's own Observable events), see the {@link Ext.util.Observable#listeners listeners}
913      * config for a suggestion, or use a render listener directly:</p><pre><code>
914 new Ext.Panel({
915     title: 'The Clickable Panel',
916     listeners: {
917         render: function(p) {
918             // Append the Panel to the click handler&#39;s argument list.
919             p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));
920         },
921         single: true  // Remove the listener after first invocation
922     }
923 });
924 </code></pre>
925      * <p>See also <tt>{@link #getEl getEl}</p>
926      * @type Ext.Element
927      * @property el
928      */
929     /**
930      * This Component's owner {@link Ext.Container Container} (defaults to undefined, and is set automatically when
931      * this Component is added to a Container).  Read-only.
932      * <p><b>Note</b>: to access items within the Container see <tt>{@link #itemId}</tt>.</p>
933      * @type Ext.Container
934      * @property ownerCt
935      */
936     /**
937      * True if this component is hidden. Read-only.
938      * @type Boolean
939      * @property hidden
940      */
941     /**
942      * True if this component is disabled. Read-only.
943      * @type Boolean
944      * @property disabled
945      */
946     /**
947      * True if this component has been rendered. Read-only.
948      * @type Boolean
949      * @property rendered
950      */
951     rendered : false,
952
953     // private
954     ctype : 'Ext.Component',
955
956     // private
957     actionMode : 'el',
958
959     // private
960     getActionEl : function(){
961         return this[this.actionMode];
962     },
963
964     initPlugin : function(p){
965         if(p.ptype && !Ext.isFunction(p.init)){
966             p = Ext.ComponentMgr.createPlugin(p);
967         }else if(Ext.isString(p)){
968             p = Ext.ComponentMgr.createPlugin({
969                 ptype: p
970             });
971         }
972         p.init(this);
973         return p;
974     },
975
976     /* // protected
977      * Function to be implemented by Component subclasses to be part of standard component initialization flow (it is empty by default).
978      * <pre><code>
979 // Traditional constructor:
980 Ext.Foo = function(config){
981     // call superclass constructor:
982     Ext.Foo.superclass.constructor.call(this, config);
983
984     this.addEvents({
985         // add events
986     });
987 };
988 Ext.extend(Ext.Foo, Ext.Bar, {
989    // class body
990 }
991
992 // initComponent replaces the constructor:
993 Ext.Foo = Ext.extend(Ext.Bar, {
994     initComponent : function(){
995         // call superclass initComponent
996         Ext.Container.superclass.initComponent.call(this);
997
998         this.addEvents({
999             // add events
1000         });
1001     }
1002 }
1003 </code></pre>
1004      */
1005     initComponent : Ext.emptyFn,
1006
1007     /**
1008      * <p>Render this Component into the passed HTML element.</p>
1009      * <p><b>If you are using a {@link Ext.Container Container} object to house this Component, then
1010      * do not use the render method.</b></p>
1011      * <p>A Container's child Components are rendered by that Container's
1012      * {@link Ext.Container#layout layout} manager when the Container is first rendered.</p>
1013      * <p>Certain layout managers allow dynamic addition of child components. Those that do
1014      * include {@link Ext.layout.CardLayout}, {@link Ext.layout.AnchorLayout},
1015      * {@link Ext.layout.FormLayout}, {@link Ext.layout.TableLayout}.</p>
1016      * <p>If the Container is already rendered when a new child Component is added, you may need to call
1017      * the Container's {@link Ext.Container#doLayout doLayout} to refresh the view which causes any
1018      * unrendered child Components to be rendered. This is required so that you can add multiple
1019      * child components if needed while only refreshing the layout once.</p>
1020      * <p>When creating complex UIs, it is important to remember that sizing and positioning
1021      * of child items is the responsibility of the Container's {@link Ext.Container#layout layout} manager.
1022      * If you expect child items to be sized in response to user interactions, you must
1023      * configure the Container with a layout manager which creates and manages the type of layout you
1024      * have in mind.</p>
1025      * <p><b>Omitting the Container's {@link Ext.Container#layout layout} config means that a basic
1026      * layout manager is used which does nothing but render child components sequentially into the
1027      * Container. No sizing or positioning will be performed in this situation.</b></p>
1028      * @param {Element/HTMLElement/String} container (optional) The element this Component should be
1029      * rendered into. If it is being created from existing markup, this should be omitted.
1030      * @param {String/Number} position (optional) The element ID or DOM node index within the container <b>before</b>
1031      * which this component will be inserted (defaults to appending to the end of the container)
1032      */
1033     render : function(container, position){
1034         if(!this.rendered && this.fireEvent('beforerender', this) !== false){
1035             if(!container && this.el){
1036                 this.el = Ext.get(this.el);
1037                 container = this.el.dom.parentNode;
1038                 this.allowDomMove = false;
1039             }
1040             this.container = Ext.get(container);
1041             if(this.ctCls){
1042                 this.container.addClass(this.ctCls);
1043             }
1044             this.rendered = true;
1045             if(position !== undefined){
1046                 if(Ext.isNumber(position)){
1047                     position = this.container.dom.childNodes[position];
1048                 }else{
1049                     position = Ext.getDom(position);
1050                 }
1051             }
1052             this.onRender(this.container, position || null);
1053             if(this.autoShow){
1054                 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
1055             }
1056             if(this.cls){
1057                 this.el.addClass(this.cls);
1058                 delete this.cls;
1059             }
1060             if(this.style){
1061                 this.el.applyStyles(this.style);
1062                 delete this.style;
1063             }
1064             if(this.overCls){
1065                 this.el.addClassOnOver(this.overCls);
1066             }
1067             this.fireEvent('render', this);
1068             this.afterRender(this.container);
1069             if(this.hidden){
1070                 // call this so we don't fire initial hide events.
1071                 this.doHide();
1072             }
1073             if(this.disabled){
1074                 // pass silent so the event doesn't fire the first time.
1075                 this.disable(true);
1076             }
1077
1078             if(this.stateful !== false){
1079                 this.initStateEvents();
1080             }
1081             this.initRef();
1082             this.fireEvent('afterrender', this);
1083         }
1084         return this;
1085     },
1086
1087     initRef : function(){
1088         /**
1089          * @cfg {String} ref
1090          * <p>A path specification, relative to the Component's {@link #ownerCt} specifying into which
1091          * ancestor Container to place a named reference to this Component.</p>
1092          * <p>The ancestor axis can be traversed by using '/' characters in the path.
1093          * For example, to put a reference to a Toolbar Button into <i>the Panel which owns the Toolbar</i>:</p><pre><code>
1094 var myGrid = new Ext.grid.EditorGridPanel({
1095     title: 'My EditorGridPanel',
1096     store: myStore,
1097     colModel: myColModel,
1098     tbar: [{
1099         text: 'Save',
1100         handler: saveChanges,
1101         disabled: true,
1102         ref: '../saveButton'
1103     }],
1104     listeners: {
1105         afteredit: function() {
1106 //          The button reference is in the GridPanel
1107             myGrid.saveButton.enable();
1108         }
1109     }
1110 });
1111 </code></pre>
1112          * <p>In the code above, if the ref had been <code>'saveButton'</code> the reference would
1113          * have been placed into the Toolbar. Each '/' in the ref moves up one level from the
1114          * Component's {@link #ownerCt}.</p>
1115          */
1116         if(this.ref){
1117             var levels = this.ref.split('/');
1118             var last = levels.length, i = 0;
1119             var t = this;
1120             while(i < last){
1121                 if(t.ownerCt){
1122                     t = t.ownerCt;
1123                 }
1124                 i++;
1125             }
1126             t[levels[--i]] = this;
1127         }
1128     },
1129
1130     // private
1131     initState : function(config){
1132         if(Ext.state.Manager){
1133             var id = this.getStateId();
1134             if(id){
1135                 var state = Ext.state.Manager.get(id);
1136                 if(state){
1137                     if(this.fireEvent('beforestaterestore', this, state) !== false){
1138                         this.applyState(state);
1139                         this.fireEvent('staterestore', this, state);
1140                     }
1141                 }
1142             }
1143         }
1144     },
1145
1146     // private
1147     getStateId : function(){
1148         return this.stateId || ((this.id.indexOf('ext-comp-') == 0 || this.id.indexOf('ext-gen') == 0) ? null : this.id);
1149     },
1150
1151     // private
1152     initStateEvents : function(){
1153         if(this.stateEvents){
1154             for(var i = 0, e; e = this.stateEvents[i]; i++){
1155                 this.on(e, this.saveState, this, {delay:100});
1156             }
1157         }
1158     },
1159
1160     // private
1161     applyState : function(state){
1162         if(state){
1163             Ext.apply(this, state);
1164         }
1165     },
1166
1167     // private
1168     getState : function(){
1169         return null;
1170     },
1171
1172     // private
1173     saveState : function(){
1174         if(Ext.state.Manager && this.stateful !== false){
1175             var id = this.getStateId();
1176             if(id){
1177                 var state = this.getState();
1178                 if(this.fireEvent('beforestatesave', this, state) !== false){
1179                     Ext.state.Manager.set(id, state);
1180                     this.fireEvent('statesave', this, state);
1181                 }
1182             }
1183         }
1184     },
1185
1186     /**
1187      * Apply this component to existing markup that is valid. With this function, no call to render() is required.
1188      * @param {String/HTMLElement} el
1189      */
1190     applyToMarkup : function(el){
1191         this.allowDomMove = false;
1192         this.el = Ext.get(el);
1193         this.render(this.el.dom.parentNode);
1194     },
1195
1196     /**
1197      * Adds a CSS class to the component's underlying element.
1198      * @param {string} cls The CSS class name to add
1199      * @return {Ext.Component} this
1200      */
1201     addClass : function(cls){
1202         if(this.el){
1203             this.el.addClass(cls);
1204         }else{
1205             this.cls = this.cls ? this.cls + ' ' + cls : cls;
1206         }
1207         return this;
1208     },
1209
1210     /**
1211      * Removes a CSS class from the component's underlying element.
1212      * @param {string} cls The CSS class name to remove
1213      * @return {Ext.Component} this
1214      */
1215     removeClass : function(cls){
1216         if(this.el){
1217             this.el.removeClass(cls);
1218         }else if(this.cls){
1219             this.cls = this.cls.split(' ').remove(cls).join(' ');
1220         }
1221         return this;
1222     },
1223
1224     // private
1225     // default function is not really useful
1226     onRender : function(ct, position){
1227         if(!this.el && this.autoEl){
1228             if(Ext.isString(this.autoEl)){
1229                 this.el = document.createElement(this.autoEl);
1230             }else{
1231                 var div = document.createElement('div');
1232                 Ext.DomHelper.overwrite(div, this.autoEl);
1233                 this.el = div.firstChild;
1234             }
1235             if (!this.el.id) {
1236                 this.el.id = this.getId();
1237             }
1238         }
1239         if(this.el){
1240             this.el = Ext.get(this.el);
1241             if(this.allowDomMove !== false){
1242                 ct.dom.insertBefore(this.el.dom, position);
1243             }
1244         }
1245     },
1246
1247     // private
1248     getAutoCreate : function(){
1249         var cfg = Ext.isObject(this.autoCreate) ?
1250                       this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
1251         if(this.id && !cfg.id){
1252             cfg.id = this.id;
1253         }
1254         return cfg;
1255     },
1256
1257     // private
1258     afterRender : Ext.emptyFn,
1259
1260     /**
1261      * Destroys this component by purging any event listeners, removing the component's element from the DOM,
1262      * removing the component from its {@link Ext.Container} (if applicable) and unregistering it from
1263      * {@link Ext.ComponentMgr}.  Destruction is generally handled automatically by the framework and this method
1264      * should usually not need to be called directly.
1265      *
1266      */
1267     destroy : function(){
1268         if(!this.isDestroyed){
1269             if(this.fireEvent('beforedestroy', this) !== false){
1270                 this.beforeDestroy();
1271                 if(this.rendered){
1272                     this.el.removeAllListeners();
1273                     this.el.remove();
1274                     if(this.actionMode == 'container' || this.removeMode == 'container'){
1275                         this.container.remove();
1276                     }
1277                 }
1278                 this.onDestroy();
1279                 Ext.ComponentMgr.unregister(this);
1280                 this.fireEvent('destroy', this);
1281                 this.purgeListeners();
1282                 this.isDestroyed = true;
1283             }
1284         }
1285     },
1286
1287     // private
1288     beforeDestroy : Ext.emptyFn,
1289
1290     // private
1291     onDestroy  : Ext.emptyFn,
1292
1293     /**
1294      * <p>Returns the {@link Ext.Element} which encapsulates this Component.</p>
1295      * <p>This will <i>usually</i> be a &lt;DIV> element created by the class's onRender method, but
1296      * that may be overridden using the {@link #autoEl} config.</p>
1297      * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br>
1298      * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners
1299      * for this Component's own Observable events), see the {@link #listeners} config for a suggestion,
1300      * or use a render listener directly:</p><pre><code>
1301 new Ext.Panel({
1302     title: 'The Clickable Panel',
1303     listeners: {
1304         render: function(p) {
1305             // Append the Panel to the click handler&#39;s argument list.
1306             p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));
1307         },
1308         single: true  // Remove the listener after first invocation
1309     }
1310 });
1311 </code></pre>
1312      * @return {Ext.Element} The Element which encapsulates this Component.
1313      */
1314     getEl : function(){
1315         return this.el;
1316     },
1317
1318     /**
1319      * Returns the <code>id</code> of this component or automatically generates and
1320      * returns an <code>id</code> if an <code>id</code> is not defined yet:<pre><code>
1321      * 'ext-comp-' + (++Ext.Component.AUTO_ID)
1322      * </code></pre>
1323      * @return {String} id
1324      */
1325     getId : function(){
1326         return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
1327     },
1328
1329     /**
1330      * Returns the <code>{@link #itemId}</code> of this component.  If an
1331      * <code>{@link #itemId}</code> was not assigned through configuration the
1332      * <code>id</code> is returned using <code>{@link #getId}</code>.
1333      * @return {String}
1334      */
1335     getItemId : function(){
1336         return this.itemId || this.getId();
1337     },
1338
1339     /**
1340      * Try to focus this component.
1341      * @param {Boolean} selectText (optional) If applicable, true to also select the text in this component
1342      * @param {Boolean/Number} delay (optional) Delay the focus this number of milliseconds (true for 10 milliseconds)
1343      * @return {Ext.Component} this
1344      */
1345     focus : function(selectText, delay){
1346         if(delay){
1347             this.focus.defer(Ext.isNumber(delay) ? delay : 10, this, [selectText, false]);
1348             return;
1349         }
1350         if(this.rendered){
1351             this.el.focus();
1352             if(selectText === true){
1353                 this.el.dom.select();
1354             }
1355         }
1356         return this;
1357     },
1358
1359     // private
1360     blur : function(){
1361         if(this.rendered){
1362             this.el.blur();
1363         }
1364         return this;
1365     },
1366
1367     /**
1368      * Disable this component and fire the 'disable' event.
1369      * @return {Ext.Component} this
1370      */
1371     disable : function(/* private */ silent){
1372         if(this.rendered){
1373             this.onDisable();
1374         }
1375         this.disabled = true;
1376         if(silent !== true){
1377             this.fireEvent('disable', this);
1378         }
1379         return this;
1380     },
1381
1382     // private
1383     onDisable : function(){
1384         this.getActionEl().addClass(this.disabledClass);
1385         this.el.dom.disabled = true;
1386     },
1387
1388     /**
1389      * Enable this component and fire the 'enable' event.
1390      * @return {Ext.Component} this
1391      */
1392     enable : function(){
1393         if(this.rendered){
1394             this.onEnable();
1395         }
1396         this.disabled = false;
1397         this.fireEvent('enable', this);
1398         return this;
1399     },
1400
1401     // private
1402     onEnable : function(){
1403         this.getActionEl().removeClass(this.disabledClass);
1404         this.el.dom.disabled = false;
1405     },
1406
1407     /**
1408      * Convenience function for setting disabled/enabled by boolean.
1409      * @param {Boolean} disabled
1410      * @return {Ext.Component} this
1411      */
1412     setDisabled : function(disabled){
1413         return this[disabled ? 'disable' : 'enable']();
1414     },
1415
1416     /**
1417      * Show this component.  Listen to the '{@link #beforeshow}' event and return
1418      * <tt>false</tt> to cancel showing the component.  Fires the '{@link #show}'
1419      * event after showing the component.
1420      * @return {Ext.Component} this
1421      */
1422     show : function(){
1423         if(this.fireEvent('beforeshow', this) !== false){
1424             this.hidden = false;
1425             if(this.autoRender){
1426                 this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
1427             }
1428             if(this.rendered){
1429                 this.onShow();
1430             }
1431             this.fireEvent('show', this);
1432         }
1433         return this;
1434     },
1435
1436     // private
1437     onShow : function(){
1438         this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);
1439     },
1440
1441     /**
1442      * Hide this component.  Listen to the '{@link #beforehide}' event and return
1443      * <tt>false</tt> to cancel hiding the component.  Fires the '{@link #hide}'
1444      * event after hiding the component. Note this method is called internally if
1445      * the component is configured to be <code>{@link #hidden}</code>.
1446      * @return {Ext.Component} this
1447      */
1448     hide : function(){
1449         if(this.fireEvent('beforehide', this) !== false){
1450             this.doHide();
1451             this.fireEvent('hide', this);
1452         }
1453         return this;
1454     },
1455
1456     // private
1457     doHide: function(){
1458         this.hidden = true;
1459         if(this.rendered){
1460             this.onHide();
1461         }
1462     },
1463
1464     // private
1465     onHide : function(){
1466         this.getVisibilityEl().addClass('x-hide-' + this.hideMode);
1467     },
1468
1469     // private
1470     getVisibilityEl : function(){
1471         return this.hideParent ? this.container : this.getActionEl();
1472     },
1473
1474     /**
1475      * Convenience function to hide or show this component by boolean.
1476      * @param {Boolean} visible True to show, false to hide
1477      * @return {Ext.Component} this
1478      */
1479     setVisible : function(visible){
1480         return this[visible ? 'show' : 'hide']();
1481     },
1482
1483     /**
1484      * Returns true if this component is visible.
1485      * @return {Boolean} True if this component is visible, false otherwise.
1486      */
1487     isVisible : function(){
1488         return this.rendered && this.getVisibilityEl().isVisible();
1489     },
1490
1491     /**
1492      * Clone the current component using the original config values passed into this instance by default.
1493      * @param {Object} overrides A new config containing any properties to override in the cloned version.
1494      * An id property can be passed on this object, otherwise one will be generated to avoid duplicates.
1495      * @return {Ext.Component} clone The cloned copy of this component
1496      */
1497     cloneConfig : function(overrides){
1498         overrides = overrides || {};
1499         var id = overrides.id || Ext.id();
1500         var cfg = Ext.applyIf(overrides, this.initialConfig);
1501         cfg.id = id; // prevent dup id
1502         return new this.constructor(cfg);
1503     },
1504
1505     /**
1506      * Gets the xtype for this component as registered with {@link Ext.ComponentMgr}. For a list of all
1507      * available xtypes, see the {@link Ext.Component} header. Example usage:
1508      * <pre><code>
1509 var t = new Ext.form.TextField();
1510 alert(t.getXType());  // alerts 'textfield'
1511 </code></pre>
1512      * @return {String} The xtype
1513      */
1514     getXType : function(){
1515         return this.constructor.xtype;
1516     },
1517
1518     /**
1519      * <p>Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended
1520      * from the xtype (default) or whether it is directly of the xtype specified (shallow = true).</p>
1521      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1522      * to participate in determination of inherited xtypes.</b></p>
1523      * <p>For a list of all available xtypes, see the {@link Ext.Component} header.</p>
1524      * <p>Example usage:</p>
1525      * <pre><code>
1526 var t = new Ext.form.TextField();
1527 var isText = t.isXType('textfield');        // true
1528 var isBoxSubclass = t.isXType('box');       // true, descended from BoxComponent
1529 var isBoxInstance = t.isXType('box', true); // false, not a direct BoxComponent instance
1530 </code></pre>
1531      * @param {String} xtype The xtype to check for this Component
1532      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
1533      * the default), or true to check whether this Component is directly of the specified xtype.
1534      * @return {Boolean} True if this component descends from the specified xtype, false otherwise.
1535      */
1536     isXType : function(xtype, shallow){
1537         //assume a string by default
1538         if (Ext.isFunction(xtype)){
1539             xtype = xtype.xtype; //handle being passed the class, e.g. Ext.Component
1540         }else if (Ext.isObject(xtype)){
1541             xtype = xtype.constructor.xtype; //handle being passed an instance
1542         }
1543
1544         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
1545     },
1546
1547     /**
1548      * <p>Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all
1549      * available xtypes, see the {@link Ext.Component} header.</p>
1550      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1551      * to participate in determination of inherited xtypes.</b></p>
1552      * <p>Example usage:</p>
1553      * <pre><code>
1554 var t = new Ext.form.TextField();
1555 alert(t.getXTypes());  // alerts 'component/box/field/textfield'
1556 </code></pre>
1557      * @return {String} The xtype hierarchy string
1558      */
1559     getXTypes : function(){
1560         var tc = this.constructor;
1561         if(!tc.xtypes){
1562             var c = [], sc = this;
1563             while(sc && sc.constructor.xtype){
1564                 c.unshift(sc.constructor.xtype);
1565                 sc = sc.constructor.superclass;
1566             }
1567             tc.xtypeChain = c;
1568             tc.xtypes = c.join('/');
1569         }
1570         return tc.xtypes;
1571     },
1572
1573     /**
1574      * Find a container above this component at any level by a custom function. If the passed function returns
1575      * true, the container will be returned.
1576      * @param {Function} fn The custom function to call with the arguments (container, this component).
1577      * @return {Ext.Container} The first Container for which the custom function returns true
1578      */
1579     findParentBy : function(fn) {
1580         for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
1581         return p || null;
1582     },
1583
1584     /**
1585      * Find a container above this component at any level by xtype or class
1586      * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
1587      * @return {Ext.Container} The first Container which matches the given xtype or class
1588      */
1589     findParentByType : function(xtype) {
1590         return Ext.isFunction(xtype) ?
1591             this.findParentBy(function(p){
1592                 return p.constructor === xtype;
1593             }) :
1594             this.findParentBy(function(p){
1595                 return p.constructor.xtype === xtype;
1596             });
1597     },
1598
1599     getDomPositionEl : function(){
1600         return this.getPositionEl ? this.getPositionEl() : this.getEl();
1601     },
1602
1603     // private
1604     purgeListeners : function(){
1605         Ext.Component.superclass.purgeListeners.call(this);
1606         if(this.mons){
1607             this.on('beforedestroy', this.clearMons, this, {single: true});
1608         }
1609     },
1610
1611     // private
1612     clearMons : function(){
1613         Ext.each(this.mons, function(m){
1614             m.item.un(m.ename, m.fn, m.scope);
1615         }, this);
1616         this.mons = [];
1617     },
1618     
1619     // private
1620     createMons: function(){
1621         if(!this.mons){
1622             this.mons = [];
1623             this.on('beforedestroy', this.clearMons, this, {single: true});
1624         }
1625     },
1626
1627     // internal function for auto removal of assigned event handlers on destruction
1628     mon : function(item, ename, fn, scope, opt){
1629         this.createMons();
1630         if(Ext.isObject(ename)){
1631             var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
1632
1633             var o = ename;
1634             for(var e in o){
1635                 if(propRe.test(e)){
1636                     continue;
1637                 }
1638                 if(Ext.isFunction(o[e])){
1639                     // shared options
1640                     this.mons.push({
1641                         item: item, ename: e, fn: o[e], scope: o.scope
1642                     });
1643                     item.on(e, o[e], o.scope, o);
1644                 }else{
1645                     // individual options
1646                     this.mons.push({
1647                         item: item, ename: e, fn: o[e], scope: o.scope
1648                     });
1649                     item.on(e, o[e]);
1650                 }
1651             }
1652             return;
1653         }
1654
1655         this.mons.push({
1656             item: item, ename: ename, fn: fn, scope: scope
1657         });
1658         item.on(ename, fn, scope, opt);
1659     },
1660
1661     // protected, opposite of mon
1662     mun : function(item, ename, fn, scope){
1663         var found, mon;
1664         this.createMons();
1665         for(var i = 0, len = this.mons.length; i < len; ++i){
1666             mon = this.mons[i];
1667             if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){
1668                 this.mons.splice(i, 1);
1669                 item.un(ename, fn, scope);
1670                 found = true;
1671                 break;
1672             }
1673         }
1674         return found;
1675     },
1676
1677     /**
1678      * Returns the next component in the owning container
1679      * @return Ext.Component
1680      */
1681     nextSibling : function(){
1682         if(this.ownerCt){
1683             var index = this.ownerCt.items.indexOf(this);
1684             if(index != -1 && index+1 < this.ownerCt.items.getCount()){
1685                 return this.ownerCt.items.itemAt(index+1);
1686             }
1687         }
1688         return null;
1689     },
1690
1691     /**
1692      * Returns the previous component in the owning container
1693      * @return Ext.Component
1694      */
1695     previousSibling : function(){
1696         if(this.ownerCt){
1697             var index = this.ownerCt.items.indexOf(this);
1698             if(index > 0){
1699                 return this.ownerCt.items.itemAt(index-1);
1700             }
1701         }
1702         return null;
1703     },
1704
1705     /**
1706      * Provides the link for Observable's fireEvent method to bubble up the ownership hierarchy.
1707      * @return {Ext.Container} the Container which owns this Component.
1708      */
1709     getBubbleTarget : function(){
1710         return this.ownerCt;
1711     }
1712 });
1713
1714 Ext.reg('component', Ext.Component);
1715 /**\r
1716  * @class Ext.Action\r
1717  * <p>An Action is a piece of reusable functionality that can be abstracted out of any particular component so that it\r
1718  * can be usefully shared among multiple components.  Actions let you share handlers, configuration options and UI\r
1719  * updates across any components that support the Action interface (primarily {@link Ext.Toolbar}, {@link Ext.Button}\r
1720  * and {@link Ext.menu.Menu} components).</p>\r
1721  * <p>Aside from supporting the config object interface, any component that needs to use Actions must also support\r
1722  * the following method list, as these will be called as needed by the Action class: setText(string), setIconCls(string),\r
1723  * setDisabled(boolean), setVisible(boolean) and setHandler(function).</p>\r
1724  * Example usage:<br>\r
1725  * <pre><code>\r
1726 // Define the shared action.  Each component below will have the same\r
1727 // display text and icon, and will display the same message on click.\r
1728 var action = new Ext.Action({\r
1729     {@link #text}: 'Do something',\r
1730     {@link #handler}: function(){\r
1731         Ext.Msg.alert('Click', 'You did something.');\r
1732     },\r
1733     {@link #iconCls}: 'do-something',\r
1734     {@link #itemId}: 'myAction'\r
1735 });\r
1736 \r
1737 var panel = new Ext.Panel({\r
1738     title: 'Actions',\r
1739     width: 500,\r
1740     height: 300,\r
1741     tbar: [\r
1742         // Add the action directly to a toolbar as a menu button\r
1743         action,\r
1744         {\r
1745             text: 'Action Menu',\r
1746             // Add the action to a menu as a text item\r
1747             menu: [action]\r
1748         }\r
1749     ],\r
1750     items: [\r
1751         // Add the action to the panel body as a standard button\r
1752         new Ext.Button(action)\r
1753     ],\r
1754     renderTo: Ext.getBody()\r
1755 });\r
1756 \r
1757 // Change the text for all components using the action\r
1758 action.setText('Something else');\r
1759 \r
1760 // Reference an action through a container using the itemId\r
1761 var btn = panel.getComponent('myAction');\r
1762 var aRef = btn.baseAction;\r
1763 aRef.setText('New text');\r
1764 </code></pre>\r
1765  * @constructor\r
1766  * @param {Object} config The configuration options\r
1767  */\r
1768 Ext.Action = function(config){\r
1769     this.initialConfig = config;\r
1770     this.itemId = config.itemId = (config.itemId || config.id || Ext.id());\r
1771     this.items = [];\r
1772 }\r
1773 \r
1774 Ext.Action.prototype = {\r
1775     /**\r
1776      * @cfg {String} text The text to set for all components using this action (defaults to '').\r
1777      */\r
1778     /**\r
1779      * @cfg {String} iconCls\r
1780      * The CSS class selector that specifies a background image to be used as the header icon for\r
1781      * all components using this action (defaults to '').\r
1782      * <p>An example of specifying a custom icon class would be something like:\r
1783      * </p><pre><code>\r
1784 // specify the property in the config for the class:\r
1785      ...\r
1786      iconCls: 'do-something'\r
1787 \r
1788 // css class that specifies background image to be used as the icon image:\r
1789 .do-something { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }\r
1790 </code></pre>\r
1791      */\r
1792     /**\r
1793      * @cfg {Boolean} disabled True to disable all components using this action, false to enable them (defaults to false).\r
1794      */\r
1795     /**\r
1796      * @cfg {Boolean} hidden True to hide all components using this action, false to show them (defaults to false).\r
1797      */\r
1798     /**\r
1799      * @cfg {Function} handler The function that will be invoked by each component tied to this action\r
1800      * when the component's primary event is triggered (defaults to undefined).\r
1801      */\r
1802     /**\r
1803      * @cfg {String} itemId\r
1804      * See {@link Ext.Component}.{@link Ext.Component#itemId itemId}.\r
1805      */\r
1806     /**\r
1807      * @cfg {Object} scope The scope in which the {@link #handler} function will execute.\r
1808      */\r
1809 \r
1810     // private\r
1811     isAction : true,\r
1812 \r
1813     /**\r
1814      * Sets the text to be displayed by all components using this action.\r
1815      * @param {String} text The text to display\r
1816      */\r
1817     setText : function(text){\r
1818         this.initialConfig.text = text;\r
1819         this.callEach('setText', [text]);\r
1820     },\r
1821 \r
1822     /**\r
1823      * Gets the text currently displayed by all components using this action.\r
1824      */\r
1825     getText : function(){\r
1826         return this.initialConfig.text;\r
1827     },\r
1828 \r
1829     /**\r
1830      * Sets the icon CSS class for all components using this action.  The class should supply\r
1831      * a background image that will be used as the icon image.\r
1832      * @param {String} cls The CSS class supplying the icon image\r
1833      */\r
1834     setIconClass : function(cls){\r
1835         this.initialConfig.iconCls = cls;\r
1836         this.callEach('setIconClass', [cls]);\r
1837     },\r
1838 \r
1839     /**\r
1840      * Gets the icon CSS class currently used by all components using this action.\r
1841      */\r
1842     getIconClass : function(){\r
1843         return this.initialConfig.iconCls;\r
1844     },\r
1845 \r
1846     /**\r
1847      * Sets the disabled state of all components using this action.  Shortcut method\r
1848      * for {@link #enable} and {@link #disable}.\r
1849      * @param {Boolean} disabled True to disable the component, false to enable it\r
1850      */\r
1851     setDisabled : function(v){\r
1852         this.initialConfig.disabled = v;\r
1853         this.callEach('setDisabled', [v]);\r
1854     },\r
1855 \r
1856     /**\r
1857      * Enables all components using this action.\r
1858      */\r
1859     enable : function(){\r
1860         this.setDisabled(false);\r
1861     },\r
1862 \r
1863     /**\r
1864      * Disables all components using this action.\r
1865      */\r
1866     disable : function(){\r
1867         this.setDisabled(true);\r
1868     },\r
1869 \r
1870     /**\r
1871      * Returns true if the components using this action are currently disabled, else returns false.  \r
1872      */\r
1873     isDisabled : function(){\r
1874         return this.initialConfig.disabled;\r
1875     },\r
1876 \r
1877     /**\r
1878      * Sets the hidden state of all components using this action.  Shortcut method\r
1879      * for <code>{@link #hide}</code> and <code>{@link #show}</code>.\r
1880      * @param {Boolean} hidden True to hide the component, false to show it\r
1881      */\r
1882     setHidden : function(v){\r
1883         this.initialConfig.hidden = v;\r
1884         this.callEach('setVisible', [!v]);\r
1885     },\r
1886 \r
1887     /**\r
1888      * Shows all components using this action.\r
1889      */\r
1890     show : function(){\r
1891         this.setHidden(false);\r
1892     },\r
1893 \r
1894     /**\r
1895      * Hides all components using this action.\r
1896      */\r
1897     hide : function(){\r
1898         this.setHidden(true);\r
1899     },\r
1900 \r
1901     /**\r
1902      * Returns true if the components using this action are currently hidden, else returns false.  \r
1903      */\r
1904     isHidden : function(){\r
1905         return this.initialConfig.hidden;\r
1906     },\r
1907 \r
1908     /**\r
1909      * Sets the function that will be called by each component using this action when its primary event is triggered.\r
1910      * @param {Function} fn The function that will be invoked by the action's components.  The function\r
1911      * will be called with no arguments.\r
1912      * @param {Object} scope The scope in which the function will execute\r
1913      */\r
1914     setHandler : function(fn, scope){\r
1915         this.initialConfig.handler = fn;\r
1916         this.initialConfig.scope = scope;\r
1917         this.callEach('setHandler', [fn, scope]);\r
1918     },\r
1919 \r
1920     /**\r
1921      * Executes the specified function once for each component currently tied to this action.  The function passed\r
1922      * in should accept a single argument that will be an object that supports the basic Action config/method interface.\r
1923      * @param {Function} fn The function to execute for each component\r
1924      * @param {Object} scope The scope in which the function will execute\r
1925      */\r
1926     each : function(fn, scope){\r
1927         Ext.each(this.items, fn, scope);\r
1928     },\r
1929 \r
1930     // private\r
1931     callEach : function(fnName, args){\r
1932         var cs = this.items;\r
1933         for(var i = 0, len = cs.length; i < len; i++){\r
1934             cs[i][fnName].apply(cs[i], args);\r
1935         }\r
1936     },\r
1937 \r
1938     // private\r
1939     addComponent : function(comp){\r
1940         this.items.push(comp);\r
1941         comp.on('destroy', this.removeComponent, this);\r
1942     },\r
1943 \r
1944     // private\r
1945     removeComponent : function(comp){\r
1946         this.items.remove(comp);\r
1947     },\r
1948 \r
1949     /**\r
1950      * Executes this action manually using the handler function specified in the original config object\r
1951      * or the handler function set with <code>{@link #setHandler}</code>.  Any arguments passed to this\r
1952      * function will be passed on to the handler function.\r
1953      * @param {Mixed} arg1 (optional) Variable number of arguments passed to the handler function\r
1954      * @param {Mixed} arg2 (optional)\r
1955      * @param {Mixed} etc... (optional)\r
1956      */\r
1957     execute : function(){\r
1958         this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);\r
1959     }\r
1960 };
1961 /**
1962  * @class Ext.Layer
1963  * @extends Ext.Element
1964  * An extended {@link Ext.Element} object that supports a shadow and shim, constrain to viewport and
1965  * automatic maintaining of shadow/shim positions.
1966  * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true)
1967  * @cfg {String/Boolean} shadow True to automatically create an {@link Ext.Shadow}, or a string indicating the
1968  * shadow's display {@link Ext.Shadow#mode}. False to disable the shadow. (defaults to false)
1969  * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: 'div', cls: 'x-layer'}).
1970  * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true)
1971  * @cfg {String} cls CSS class to add to the element
1972  * @cfg {Number} zindex Starting z-index (defaults to 11000)
1973  * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 4)
1974  * @cfg {Boolean} useDisplay
1975  * Defaults to use css offsets to hide the Layer. Specify <tt>true</tt>
1976  * to use css style <tt>'display:none;'</tt> to hide the Layer.
1977  * @constructor
1978  * @param {Object} config An object with config options.
1979  * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element. If the element is not found it creates it.
1980  */
1981 (function(){
1982 Ext.Layer = function(config, existingEl){
1983     config = config || {};
1984     var dh = Ext.DomHelper;
1985     var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
1986     if(existingEl){
1987         this.dom = Ext.getDom(existingEl);
1988     }
1989     if(!this.dom){
1990         var o = config.dh || {tag: 'div', cls: 'x-layer'};
1991         this.dom = dh.append(pel, o);
1992     }
1993     if(config.cls){
1994         this.addClass(config.cls);
1995     }
1996     this.constrain = config.constrain !== false;
1997     this.setVisibilityMode(Ext.Element.VISIBILITY);
1998     if(config.id){
1999         this.id = this.dom.id = config.id;
2000     }else{
2001         this.id = Ext.id(this.dom);
2002     }
2003     this.zindex = config.zindex || this.getZIndex();
2004     this.position('absolute', this.zindex);
2005     if(config.shadow){
2006         this.shadowOffset = config.shadowOffset || 4;
2007         this.shadow = new Ext.Shadow({
2008             offset : this.shadowOffset,
2009             mode : config.shadow
2010         });
2011     }else{
2012         this.shadowOffset = 0;
2013     }
2014     this.useShim = config.shim !== false && Ext.useShims;
2015     this.useDisplay = config.useDisplay;
2016     this.hide();
2017 };
2018
2019 var supr = Ext.Element.prototype;
2020
2021 // shims are shared among layer to keep from having 100 iframes
2022 var shims = [];
2023
2024 Ext.extend(Ext.Layer, Ext.Element, {
2025
2026     getZIndex : function(){
2027         return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
2028     },
2029
2030     getShim : function(){
2031         if(!this.useShim){
2032             return null;
2033         }
2034         if(this.shim){
2035             return this.shim;
2036         }
2037         var shim = shims.shift();
2038         if(!shim){
2039             shim = this.createShim();
2040             shim.enableDisplayMode('block');
2041             shim.dom.style.display = 'none';
2042             shim.dom.style.visibility = 'visible';
2043         }
2044         var pn = this.dom.parentNode;
2045         if(shim.dom.parentNode != pn){
2046             pn.insertBefore(shim.dom, this.dom);
2047         }
2048         shim.setStyle('z-index', this.getZIndex()-2);
2049         this.shim = shim;
2050         return shim;
2051     },
2052
2053     hideShim : function(){
2054         if(this.shim){
2055             this.shim.setDisplayed(false);
2056             shims.push(this.shim);
2057             delete this.shim;
2058         }
2059     },
2060
2061     disableShadow : function(){
2062         if(this.shadow){
2063             this.shadowDisabled = true;
2064             this.shadow.hide();
2065             this.lastShadowOffset = this.shadowOffset;
2066             this.shadowOffset = 0;
2067         }
2068     },
2069
2070     enableShadow : function(show){
2071         if(this.shadow){
2072             this.shadowDisabled = false;
2073             this.shadowOffset = this.lastShadowOffset;
2074             delete this.lastShadowOffset;
2075             if(show){
2076                 this.sync(true);
2077             }
2078         }
2079     },
2080
2081     // private
2082     // this code can execute repeatedly in milliseconds (i.e. during a drag) so
2083     // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
2084     sync : function(doShow){
2085         var sw = this.shadow;
2086         if(!this.updating && this.isVisible() && (sw || this.useShim)){
2087             var sh = this.getShim();
2088
2089             var w = this.getWidth(),
2090                 h = this.getHeight();
2091
2092             var l = this.getLeft(true),
2093                 t = this.getTop(true);
2094
2095             if(sw && !this.shadowDisabled){
2096                 if(doShow && !sw.isVisible()){
2097                     sw.show(this);
2098                 }else{
2099                     sw.realign(l, t, w, h);
2100                 }
2101                 if(sh){
2102                     if(doShow){
2103                        sh.show();
2104                     }
2105                     // fit the shim behind the shadow, so it is shimmed too
2106                     var a = sw.adjusts, s = sh.dom.style;
2107                     s.left = (Math.min(l, l+a.l))+'px';
2108                     s.top = (Math.min(t, t+a.t))+'px';
2109                     s.width = (w+a.w)+'px';
2110                     s.height = (h+a.h)+'px';
2111                 }
2112             }else if(sh){
2113                 if(doShow){
2114                    sh.show();
2115                 }
2116                 sh.setSize(w, h);
2117                 sh.setLeftTop(l, t);
2118             }
2119
2120         }
2121     },
2122
2123     // private
2124     destroy : function(){
2125         this.hideShim();
2126         if(this.shadow){
2127             this.shadow.hide();
2128         }
2129         this.removeAllListeners();
2130         Ext.removeNode(this.dom);
2131         Ext.Element.uncache(this.id);
2132     },
2133
2134     remove : function(){
2135         this.destroy();
2136     },
2137
2138     // private
2139     beginUpdate : function(){
2140         this.updating = true;
2141     },
2142
2143     // private
2144     endUpdate : function(){
2145         this.updating = false;
2146         this.sync(true);
2147     },
2148
2149     // private
2150     hideUnders : function(negOffset){
2151         if(this.shadow){
2152             this.shadow.hide();
2153         }
2154         this.hideShim();
2155     },
2156
2157     // private
2158     constrainXY : function(){
2159         if(this.constrain){
2160             var vw = Ext.lib.Dom.getViewWidth(),
2161                 vh = Ext.lib.Dom.getViewHeight();
2162             var s = Ext.getDoc().getScroll();
2163
2164             var xy = this.getXY();
2165             var x = xy[0], y = xy[1];
2166             var so = this.shadowOffset;
2167             var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so;
2168             // only move it if it needs it
2169             var moved = false;
2170             // first validate right/bottom
2171             if((x + w) > vw+s.left){
2172                 x = vw - w - so;
2173                 moved = true;
2174             }
2175             if((y + h) > vh+s.top){
2176                 y = vh - h - so;
2177                 moved = true;
2178             }
2179             // then make sure top/left isn't negative
2180             if(x < s.left){
2181                 x = s.left;
2182                 moved = true;
2183             }
2184             if(y < s.top){
2185                 y = s.top;
2186                 moved = true;
2187             }
2188             if(moved){
2189                 if(this.avoidY){
2190                     var ay = this.avoidY;
2191                     if(y <= ay && (y+h) >= ay){
2192                         y = ay-h-5;
2193                     }
2194                 }
2195                 xy = [x, y];
2196                 this.storeXY(xy);
2197                 supr.setXY.call(this, xy);
2198                 this.sync();
2199             }
2200         }
2201         return this;
2202     },
2203
2204     isVisible : function(){
2205         return this.visible;
2206     },
2207
2208     // private
2209     showAction : function(){
2210         this.visible = true; // track visibility to prevent getStyle calls
2211         if(this.useDisplay === true){
2212             this.setDisplayed('');
2213         }else if(this.lastXY){
2214             supr.setXY.call(this, this.lastXY);
2215         }else if(this.lastLT){
2216             supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
2217         }
2218     },
2219
2220     // private
2221     hideAction : function(){
2222         this.visible = false;
2223         if(this.useDisplay === true){
2224             this.setDisplayed(false);
2225         }else{
2226             this.setLeftTop(-10000,-10000);
2227         }
2228     },
2229
2230     // overridden Element method
2231     setVisible : function(v, a, d, c, e){
2232         if(v){
2233             this.showAction();
2234         }
2235         if(a && v){
2236             var cb = function(){
2237                 this.sync(true);
2238                 if(c){
2239                     c();
2240                 }
2241             }.createDelegate(this);
2242             supr.setVisible.call(this, true, true, d, cb, e);
2243         }else{
2244             if(!v){
2245                 this.hideUnders(true);
2246             }
2247             var cb = c;
2248             if(a){
2249                 cb = function(){
2250                     this.hideAction();
2251                     if(c){
2252                         c();
2253                     }
2254                 }.createDelegate(this);
2255             }
2256             supr.setVisible.call(this, v, a, d, cb, e);
2257             if(v){
2258                 this.sync(true);
2259             }else if(!a){
2260                 this.hideAction();
2261             }
2262         }
2263         return this;
2264     },
2265
2266     storeXY : function(xy){
2267         delete this.lastLT;
2268         this.lastXY = xy;
2269     },
2270
2271     storeLeftTop : function(left, top){
2272         delete this.lastXY;
2273         this.lastLT = [left, top];
2274     },
2275
2276     // private
2277     beforeFx : function(){
2278         this.beforeAction();
2279         return Ext.Layer.superclass.beforeFx.apply(this, arguments);
2280     },
2281
2282     // private
2283     afterFx : function(){
2284         Ext.Layer.superclass.afterFx.apply(this, arguments);
2285         this.sync(this.isVisible());
2286     },
2287
2288     // private
2289     beforeAction : function(){
2290         if(!this.updating && this.shadow){
2291             this.shadow.hide();
2292         }
2293     },
2294
2295     // overridden Element method
2296     setLeft : function(left){
2297         this.storeLeftTop(left, this.getTop(true));
2298         supr.setLeft.apply(this, arguments);
2299         this.sync();
2300         return this;
2301     },
2302
2303     setTop : function(top){
2304         this.storeLeftTop(this.getLeft(true), top);
2305         supr.setTop.apply(this, arguments);
2306         this.sync();
2307         return this;
2308     },
2309
2310     setLeftTop : function(left, top){
2311         this.storeLeftTop(left, top);
2312         supr.setLeftTop.apply(this, arguments);
2313         this.sync();
2314         return this;
2315     },
2316
2317     setXY : function(xy, a, d, c, e){
2318         this.fixDisplay();
2319         this.beforeAction();
2320         this.storeXY(xy);
2321         var cb = this.createCB(c);
2322         supr.setXY.call(this, xy, a, d, cb, e);
2323         if(!a){
2324             cb();
2325         }
2326         return this;
2327     },
2328
2329     // private
2330     createCB : function(c){
2331         var el = this;
2332         return function(){
2333             el.constrainXY();
2334             el.sync(true);
2335             if(c){
2336                 c();
2337             }
2338         };
2339     },
2340
2341     // overridden Element method
2342     setX : function(x, a, d, c, e){
2343         this.setXY([x, this.getY()], a, d, c, e);
2344         return this;
2345     },
2346
2347     // overridden Element method
2348     setY : function(y, a, d, c, e){
2349         this.setXY([this.getX(), y], a, d, c, e);
2350         return this;
2351     },
2352
2353     // overridden Element method
2354     setSize : function(w, h, a, d, c, e){
2355         this.beforeAction();
2356         var cb = this.createCB(c);
2357         supr.setSize.call(this, w, h, a, d, cb, e);
2358         if(!a){
2359             cb();
2360         }
2361         return this;
2362     },
2363
2364     // overridden Element method
2365     setWidth : function(w, a, d, c, e){
2366         this.beforeAction();
2367         var cb = this.createCB(c);
2368         supr.setWidth.call(this, w, a, d, cb, e);
2369         if(!a){
2370             cb();
2371         }
2372         return this;
2373     },
2374
2375     // overridden Element method
2376     setHeight : function(h, a, d, c, e){
2377         this.beforeAction();
2378         var cb = this.createCB(c);
2379         supr.setHeight.call(this, h, a, d, cb, e);
2380         if(!a){
2381             cb();
2382         }
2383         return this;
2384     },
2385
2386     // overridden Element method
2387     setBounds : function(x, y, w, h, a, d, c, e){
2388         this.beforeAction();
2389         var cb = this.createCB(c);
2390         if(!a){
2391             this.storeXY([x, y]);
2392             supr.setXY.call(this, [x, y]);
2393             supr.setSize.call(this, w, h, a, d, cb, e);
2394             cb();
2395         }else{
2396             supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
2397         }
2398         return this;
2399     },
2400
2401     /**
2402      * Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
2403      * incremented by two more than the value passed in so that it always shows above any shadow or shim (the shadow
2404      * element, if any, will be assigned z-index + 1, and the shim element, if any, will be assigned the unmodified z-index).
2405      * @param {Number} zindex The new z-index to set
2406      * @return {this} The Layer
2407      */
2408     setZIndex : function(zindex){
2409         this.zindex = zindex;
2410         this.setStyle('z-index', zindex + 2);
2411         if(this.shadow){
2412             this.shadow.setZIndex(zindex + 1);
2413         }
2414         if(this.shim){
2415             this.shim.setStyle('z-index', zindex);
2416         }
2417         return this;
2418     }
2419 });
2420 })();/**
2421  * @class Ext.Shadow
2422  * Simple class that can provide a shadow effect for any element.  Note that the element MUST be absolutely positioned,
2423  * and the shadow does not provide any shimming.  This should be used only in simple cases -- for more advanced
2424  * functionality that can also provide the same shadow effect, see the {@link Ext.Layer} class.
2425  * @constructor
2426  * Create a new Shadow
2427  * @param {Object} config The config object
2428  */
2429 Ext.Shadow = function(config){
2430     Ext.apply(this, config);
2431     if(typeof this.mode != "string"){
2432         this.mode = this.defaultMode;
2433     }
2434     var o = this.offset, a = {h: 0};
2435     var rad = Math.floor(this.offset/2);
2436     switch(this.mode.toLowerCase()){ // all this hideous nonsense calculates the various offsets for shadows
2437         case "drop":
2438             a.w = 0;
2439             a.l = a.t = o;
2440             a.t -= 1;
2441             if(Ext.isIE){
2442                 a.l -= this.offset + rad;
2443                 a.t -= this.offset + rad;
2444                 a.w -= rad;
2445                 a.h -= rad;
2446                 a.t += 1;
2447             }
2448         break;
2449         case "sides":
2450             a.w = (o*2);
2451             a.l = -o;
2452             a.t = o-1;
2453             if(Ext.isIE){
2454                 a.l -= (this.offset - rad);
2455                 a.t -= this.offset + rad;
2456                 a.l += 1;
2457                 a.w -= (this.offset - rad)*2;
2458                 a.w -= rad + 1;
2459                 a.h -= 1;
2460             }
2461         break;
2462         case "frame":
2463             a.w = a.h = (o*2);
2464             a.l = a.t = -o;
2465             a.t += 1;
2466             a.h -= 2;
2467             if(Ext.isIE){
2468                 a.l -= (this.offset - rad);
2469                 a.t -= (this.offset - rad);
2470                 a.l += 1;
2471                 a.w -= (this.offset + rad + 1);
2472                 a.h -= (this.offset + rad);
2473                 a.h += 1;
2474             }
2475         break;
2476     };
2477
2478     this.adjusts = a;
2479 };
2480
2481 Ext.Shadow.prototype = {
2482     /**
2483      * @cfg {String} mode
2484      * The shadow display mode.  Supports the following options:<div class="mdetail-params"><ul>
2485      * <li><b><tt>sides</tt></b> : Shadow displays on both sides and bottom only</li>
2486      * <li><b><tt>frame</tt></b> : Shadow displays equally on all four sides</li>
2487      * <li><b><tt>drop</tt></b> : Traditional bottom-right drop shadow</li>
2488      * </ul></div>
2489      */
2490     /**
2491      * @cfg {String} offset
2492      * The number of pixels to offset the shadow from the element (defaults to <tt>4</tt>)
2493      */
2494     offset: 4,
2495
2496     // private
2497     defaultMode: "drop",
2498
2499     /**
2500      * Displays the shadow under the target element
2501      * @param {Mixed} targetEl The id or element under which the shadow should display
2502      */
2503     show : function(target){
2504         target = Ext.get(target);
2505         if(!this.el){
2506             this.el = Ext.Shadow.Pool.pull();
2507             if(this.el.dom.nextSibling != target.dom){
2508                 this.el.insertBefore(target);
2509             }
2510         }
2511         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
2512         if(Ext.isIE){
2513             this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
2514         }
2515         this.realign(
2516             target.getLeft(true),
2517             target.getTop(true),
2518             target.getWidth(),
2519             target.getHeight()
2520         );
2521         this.el.dom.style.display = "block";
2522     },
2523
2524     /**
2525      * Returns true if the shadow is visible, else false
2526      */
2527     isVisible : function(){
2528         return this.el ? true : false;  
2529     },
2530
2531     /**
2532      * Direct alignment when values are already available. Show must be called at least once before
2533      * calling this method to ensure it is initialized.
2534      * @param {Number} left The target element left position
2535      * @param {Number} top The target element top position
2536      * @param {Number} width The target element width
2537      * @param {Number} height The target element height
2538      */
2539     realign : function(l, t, w, h){
2540         if(!this.el){
2541             return;
2542         }
2543         var a = this.adjusts, d = this.el.dom, s = d.style;
2544         var iea = 0;
2545         s.left = (l+a.l)+"px";
2546         s.top = (t+a.t)+"px";
2547         var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
2548         if(s.width != sws || s.height != shs){
2549             s.width = sws;
2550             s.height = shs;
2551             if(!Ext.isIE){
2552                 var cn = d.childNodes;
2553                 var sww = Math.max(0, (sw-12))+"px";
2554                 cn[0].childNodes[1].style.width = sww;
2555                 cn[1].childNodes[1].style.width = sww;
2556                 cn[2].childNodes[1].style.width = sww;
2557                 cn[1].style.height = Math.max(0, (sh-12))+"px";
2558             }
2559         }
2560     },
2561
2562     /**
2563      * Hides this shadow
2564      */
2565     hide : function(){
2566         if(this.el){
2567             this.el.dom.style.display = "none";
2568             Ext.Shadow.Pool.push(this.el);
2569             delete this.el;
2570         }
2571     },
2572
2573     /**
2574      * Adjust the z-index of this shadow
2575      * @param {Number} zindex The new z-index
2576      */
2577     setZIndex : function(z){
2578         this.zIndex = z;
2579         if(this.el){
2580             this.el.setStyle("z-index", z);
2581         }
2582     }
2583 };
2584
2585 // Private utility class that manages the internal Shadow cache
2586 Ext.Shadow.Pool = function(){
2587     var p = [];
2588     var markup = Ext.isIE ?
2589                  '<div class="x-ie-shadow"></div>' :
2590                  '<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>';
2591     return {
2592         pull : function(){
2593             var sh = p.shift();
2594             if(!sh){
2595                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
2596                 sh.autoBoxAdjust = false;
2597             }
2598             return sh;
2599         },
2600
2601         push : function(sh){
2602             p.push(sh);
2603         }
2604     };
2605 }();/**
2606  * @class Ext.BoxComponent
2607  * @extends Ext.Component
2608  * <p>Base class for any {@link Ext.Component Component} that is to be sized as a box, using width and height.</p>
2609  * <p>BoxComponent provides automatic box model adjustments for sizing and positioning and will work correctly
2610  * within the Component rendering model.</p>
2611  * <p>A BoxComponent may be created as a custom Component which encapsulates any HTML element, either a pre-existing
2612  * element, or one that is created to your specifications at render time. Usually, to participate in layouts,
2613  * a Component will need to be a <b>Box</b>Component in order to have its width and height managed.</p>
2614  * <p>To use a pre-existing element as a BoxComponent, configure it so that you preset the <b>el</b> property to the
2615  * element to reference:<pre><code>
2616 var pageHeader = new Ext.BoxComponent({
2617     el: 'my-header-div'
2618 });</code></pre>
2619  * This may then be {@link Ext.Container#add added} to a {@link Ext.Container Container} as a child item.</p>
2620  * <p>To create a BoxComponent based around a HTML element to be created at render time, use the
2621  * {@link Ext.Component#autoEl autoEl} config option which takes the form of a
2622  * {@link Ext.DomHelper DomHelper} specification:<pre><code>
2623 var myImage = new Ext.BoxComponent({
2624     autoEl: {
2625         tag: 'img',
2626         src: '/images/my-image.jpg'
2627     }
2628 });</code></pre></p>
2629  * @constructor
2630  * @param {Ext.Element/String/Object} config The configuration options.
2631  * @xtype box
2632  */
2633 Ext.BoxComponent = Ext.extend(Ext.Component, {
2634
2635     // tabTip config is used when a BoxComponent is a child of a TabPanel
2636     /**
2637      * @cfg {String} tabTip
2638      * <p><b>Note</b>: this config is only used when this BoxComponent is a child item of a TabPanel.</p>
2639      * A string to be used as innerHTML (html tags are accepted) to show in a tooltip when mousing over
2640      * the associated tab selector element. {@link Ext.QuickTips}.init()
2641      * must be called in order for the tips to render.
2642      */
2643     // Configs below are used for all Components when rendered by BorderLayout.
2644     /**
2645      * @cfg {String} region <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2646      * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2647      * layout manager (e.g. specifying <tt>layout:'border'</tt>).</p><br>
2648      * <p>See {@link Ext.layout.BorderLayout} also.</p>
2649      */
2650     // margins config is used when a BoxComponent is rendered by BorderLayout or BoxLayout.
2651     /**
2652      * @cfg {Object} margins <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2653      * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2654      * or one of the two <b>{@link Ext.layout.BoxLayout BoxLayout} subclasses.</b></p>
2655      * <p>An object containing margins to apply to this BoxComponent in the
2656      * format:</p><pre><code>
2657 {
2658     top: (top margin),
2659     right: (right margin),
2660     bottom: (bottom margin),
2661     left: (left margin)
2662 }</code></pre>
2663      * <p>May also be a string containing space-separated, numeric margin values. The order of the
2664      * sides associated with each value matches the way CSS processes margin values:</p>
2665      * <p><div class="mdetail-params"><ul>
2666      * <li>If there is only one value, it applies to all sides.</li>
2667      * <li>If there are two values, the top and bottom borders are set to the first value and the
2668      * right and left are set to the second.</li>
2669      * <li>If there are three values, the top is set to the first value, the left and right are set
2670      * to the second, and the bottom is set to the third.</li>
2671      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
2672      * </ul></div></p>
2673      * <p>Defaults to:</p><pre><code>
2674      * {top:0, right:0, bottom:0, left:0}
2675      * </code></pre>
2676      */
2677     /**
2678      * @cfg {Number} x
2679      * The local x (left) coordinate for this component if contained within a positioning container.
2680      */
2681     /**
2682      * @cfg {Number} y
2683      * The local y (top) coordinate for this component if contained within a positioning container.
2684      */
2685     /**
2686      * @cfg {Number} pageX
2687      * The page level x coordinate for this component if contained within a positioning container.
2688      */
2689     /**
2690      * @cfg {Number} pageY
2691      * The page level y coordinate for this component if contained within a positioning container.
2692      */
2693     /**
2694      * @cfg {Number} height
2695      * The height of this component in pixels (defaults to auto).
2696      * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
2697      */
2698     /**
2699      * @cfg {Number} width
2700      * The width of this component in pixels (defaults to auto).
2701      * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
2702      */
2703     /**
2704      * @cfg {Boolean} autoHeight
2705      * <p>True to use height:'auto', false to use fixed height (or allow it to be managed by its parent
2706      * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
2707      * <p><b>Note</b>: Although many components inherit this config option, not all will
2708      * function as expected with a height of 'auto'. Setting autoHeight:true means that the
2709      * browser will manage height based on the element's contents, and that Ext will not manage it at all.</p>
2710      * <p>If the <i>browser</i> is managing the height, be aware that resizes performed by the browser in response
2711      * to changes within the structure of the Component cannot be detected. Therefore changes to the height might
2712      * result in elements needing to be synchronized with the new height. Example:</p><pre><code>
2713 var w = new Ext.Window({
2714     title: 'Window',
2715     width: 600,
2716     autoHeight: true,
2717     items: {
2718         title: 'Collapse Me',
2719         height: 400,
2720         collapsible: true,
2721         border: false,
2722         listeners: {
2723             beforecollapse: function() {
2724                 w.el.shadow.hide();
2725             },
2726             beforeexpand: function() {
2727                 w.el.shadow.hide();
2728             },
2729             collapse: function() {
2730                 w.syncShadow();
2731             },
2732             expand: function() {
2733                 w.syncShadow();
2734             }
2735         }
2736     }
2737 }).show();
2738 </code></pre>
2739      */
2740     /**
2741      * @cfg {Boolean} autoWidth
2742      * <p>True to use width:'auto', false to use fixed width (or allow it to be managed by its parent
2743      * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
2744      * <p><b>Note</b>: Although many components  inherit this config option, not all will
2745      * function as expected with a width of 'auto'. Setting autoWidth:true means that the
2746      * browser will manage width based on the element's contents, and that Ext will not manage it at all.</p>
2747      * <p>If the <i>browser</i> is managing the width, be aware that resizes performed by the browser in response
2748      * to changes within the structure of the Component cannot be detected. Therefore changes to the width might
2749      * result in elements needing to be synchronized with the new width. For example, where the target element is:</p><pre><code>
2750 &lt;div id='grid-container' style='margin-left:25%;width:50%'>&lt;/div>
2751 </code></pre>
2752      * A Panel rendered into that target element must listen for browser window resize in order to relay its
2753       * child items when the browser changes its width:<pre><code>
2754 var myPanel = new Ext.Panel({
2755     renderTo: 'grid-container',
2756     monitorResize: true, // relay on browser resize
2757     title: 'Panel',
2758     height: 400,
2759     autoWidth: true,
2760     layout: 'hbox',
2761     layoutConfig: {
2762         align: 'stretch'
2763     },
2764     defaults: {
2765         flex: 1
2766     },
2767     items: [{
2768         title: 'Box 1',
2769     }, {
2770         title: 'Box 2'
2771     }, {
2772         title: 'Box 3'
2773     }],
2774 });
2775 </code></pre>
2776      */
2777
2778     /* // private internal config
2779      * {Boolean} deferHeight
2780      * True to defer height calculations to an external component, false to allow this component to set its own
2781      * height (defaults to false).
2782      */
2783
2784     // private
2785     initComponent : function(){
2786         Ext.BoxComponent.superclass.initComponent.call(this);
2787         this.addEvents(
2788             /**
2789              * @event resize
2790              * Fires after the component is resized.
2791              * @param {Ext.Component} this
2792              * @param {Number} adjWidth The box-adjusted width that was set
2793              * @param {Number} adjHeight The box-adjusted height that was set
2794              * @param {Number} rawWidth The width that was originally specified
2795              * @param {Number} rawHeight The height that was originally specified
2796              */
2797             'resize',
2798             /**
2799              * @event move
2800              * Fires after the component is moved.
2801              * @param {Ext.Component} this
2802              * @param {Number} x The new x position
2803              * @param {Number} y The new y position
2804              */
2805             'move'
2806         );
2807     },
2808
2809     // private, set in afterRender to signify that the component has been rendered
2810     boxReady : false,
2811     // private, used to defer height settings to subclasses
2812     deferHeight: false,
2813
2814     /**
2815      * Sets the width and height of this BoxComponent. This method fires the {@link #resize} event. This method can accept
2816      * either width and height as separate arguments, or you can pass a size object like <code>{width:10, height:20}</code>.
2817      * @param {Mixed} width The new width to set. This may be one of:<div class="mdetail-params"><ul>
2818      * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
2819      * <li>A String used to set the CSS width style.</li>
2820      * <li>A size object in the format <code>{width: widthValue, height: heightValue}</code>.</li>
2821      * <li><code>undefined</code> to leave the width unchanged.</li>
2822      * </ul></div>
2823      * @param {Mixed} height The new height to set (not required if a size object is passed as the first arg).
2824      * This may be one of:<div class="mdetail-params"><ul>
2825      * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
2826      * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
2827      * <li><code>undefined</code> to leave the height unchanged.</li>
2828      * </ul></div>
2829      * @return {Ext.BoxComponent} this
2830      */
2831     setSize : function(w, h){
2832         // support for standard size objects
2833         if(typeof w == 'object'){
2834             h = w.height;
2835             w = w.width;
2836         }
2837         // not rendered
2838         if(!this.boxReady){
2839             this.width = w;
2840             this.height = h;
2841             return this;
2842         }
2843
2844         // prevent recalcs when not needed
2845         if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
2846             return this;
2847         }
2848         this.lastSize = {width: w, height: h};
2849         var adj = this.adjustSize(w, h);
2850         var aw = adj.width, ah = adj.height;
2851         if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
2852             var rz = this.getResizeEl();
2853             if(!this.deferHeight && aw !== undefined && ah !== undefined){
2854                 rz.setSize(aw, ah);
2855             }else if(!this.deferHeight && ah !== undefined){
2856                 rz.setHeight(ah);
2857             }else if(aw !== undefined){
2858                 rz.setWidth(aw);
2859             }
2860             this.onResize(aw, ah, w, h);
2861             this.fireEvent('resize', this, aw, ah, w, h);
2862         }
2863         return this;
2864     },
2865
2866     /**
2867      * Sets the width of the component.  This method fires the {@link #resize} event.
2868      * @param {Number} width The new width to setThis may be one of:<div class="mdetail-params"><ul>
2869      * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
2870      * <li>A String used to set the CSS width style.</li>
2871      * </ul></div>
2872      * @return {Ext.BoxComponent} this
2873      */
2874     setWidth : function(width){
2875         return this.setSize(width);
2876     },
2877
2878     /**
2879      * Sets the height of the component.  This method fires the {@link #resize} event.
2880      * @param {Number} height The new height to set. This may be one of:<div class="mdetail-params"><ul>
2881      * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
2882      * <li>A String used to set the CSS height style.</li>
2883      * <li><i>undefined</i> to leave the height unchanged.</li>
2884      * </ul></div>
2885      * @return {Ext.BoxComponent} this
2886      */
2887     setHeight : function(height){
2888         return this.setSize(undefined, height);
2889     },
2890
2891     /**
2892      * Gets the current size of the component's underlying element.
2893      * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
2894      */
2895     getSize : function(){
2896         return this.getResizeEl().getSize();
2897     },
2898
2899     /**
2900      * Gets the current width of the component's underlying element.
2901      * @return {Number}
2902      */
2903     getWidth : function(){
2904         return this.getResizeEl().getWidth();
2905     },
2906
2907     /**
2908      * Gets the current height of the component's underlying element.
2909      * @return {Number}
2910      */
2911     getHeight : function(){
2912         return this.getResizeEl().getHeight();
2913     },
2914
2915     /**
2916      * Gets the current size of the component's underlying element, including space taken by its margins.
2917      * @return {Object} An object containing the element's size {width: (element width + left/right margins), height: (element height + top/bottom margins)}
2918      */
2919     getOuterSize : function(){
2920         var el = this.getResizeEl();
2921         return {width: el.getWidth() + el.getMargins('lr'),
2922                 height: el.getHeight() + el.getMargins('tb')};
2923     },
2924
2925     /**
2926      * Gets the current XY position of the component's underlying element.
2927      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
2928      * @return {Array} The XY position of the element (e.g., [100, 200])
2929      */
2930     getPosition : function(local){
2931         var el = this.getPositionEl();
2932         if(local === true){
2933             return [el.getLeft(true), el.getTop(true)];
2934         }
2935         return this.xy || el.getXY();
2936     },
2937
2938     /**
2939      * Gets the current box measurements of the component's underlying element.
2940      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
2941      * @return {Object} box An object in the format {x, y, width, height}
2942      */
2943     getBox : function(local){
2944         var pos = this.getPosition(local);
2945         var s = this.getSize();
2946         s.x = pos[0];
2947         s.y = pos[1];
2948         return s;
2949     },
2950
2951     /**
2952      * Sets the current box measurements of the component's underlying element.
2953      * @param {Object} box An object in the format {x, y, width, height}
2954      * @return {Ext.BoxComponent} this
2955      */
2956     updateBox : function(box){
2957         this.setSize(box.width, box.height);
2958         this.setPagePosition(box.x, box.y);
2959         return this;
2960     },
2961
2962     /**
2963      * <p>Returns the outermost Element of this Component which defines the Components overall size.</p>
2964      * <p><i>Usually</i> this will return the same Element as <code>{@link #getEl}</code>,
2965      * but in some cases, a Component may have some more wrapping Elements around its main
2966      * active Element.</p>
2967      * <p>An example is a ComboBox. It is encased in a <i>wrapping</i> Element which
2968      * contains both the <code>&lt;input></code> Element (which is what would be returned
2969      * by its <code>{@link #getEl}</code> method, <i>and</i> the trigger button Element.
2970      * This Element is returned as the <code>resizeEl</code>.
2971      */
2972     getResizeEl : function(){
2973         return this.resizeEl || this.el;
2974     },
2975
2976     // protected
2977     getPositionEl : function(){
2978         return this.positionEl || this.el;
2979     },
2980
2981     /**
2982      * Sets the left and top of the component.  To set the page XY position instead, use {@link #setPagePosition}.
2983      * This method fires the {@link #move} event.
2984      * @param {Number} left The new left
2985      * @param {Number} top The new top
2986      * @return {Ext.BoxComponent} this
2987      */
2988     setPosition : function(x, y){
2989         if(x && typeof x[1] == 'number'){
2990             y = x[1];
2991             x = x[0];
2992         }
2993         this.x = x;
2994         this.y = y;
2995         if(!this.boxReady){
2996             return this;
2997         }
2998         var adj = this.adjustPosition(x, y);
2999         var ax = adj.x, ay = adj.y;
3000
3001         var el = this.getPositionEl();
3002         if(ax !== undefined || ay !== undefined){
3003             if(ax !== undefined && ay !== undefined){
3004                 el.setLeftTop(ax, ay);
3005             }else if(ax !== undefined){
3006                 el.setLeft(ax);
3007             }else if(ay !== undefined){
3008                 el.setTop(ay);
3009             }
3010             this.onPosition(ax, ay);
3011             this.fireEvent('move', this, ax, ay);
3012         }
3013         return this;
3014     },
3015
3016     /**
3017      * Sets the page XY position of the component.  To set the left and top instead, use {@link #setPosition}.
3018      * This method fires the {@link #move} event.
3019      * @param {Number} x The new x position
3020      * @param {Number} y The new y position
3021      * @return {Ext.BoxComponent} this
3022      */
3023     setPagePosition : function(x, y){
3024         if(x && typeof x[1] == 'number'){
3025             y = x[1];
3026             x = x[0];
3027         }
3028         this.pageX = x;
3029         this.pageY = y;
3030         if(!this.boxReady){
3031             return;
3032         }
3033         if(x === undefined || y === undefined){ // cannot translate undefined points
3034             return;
3035         }
3036         var p = this.getPositionEl().translatePoints(x, y);
3037         this.setPosition(p.left, p.top);
3038         return this;
3039     },
3040
3041     // private
3042     afterRender : function(){
3043         Ext.BoxComponent.superclass.afterRender.call(this);
3044         if(this.resizeEl){
3045             this.resizeEl = Ext.get(this.resizeEl);
3046         }
3047         if(this.positionEl){
3048             this.positionEl = Ext.get(this.positionEl);
3049         }
3050         this.boxReady = true;
3051         this.setSize(this.width, this.height);
3052         if(this.x || this.y){
3053             this.setPosition(this.x, this.y);
3054         }else if(this.pageX || this.pageY){
3055             this.setPagePosition(this.pageX, this.pageY);
3056         }
3057     },
3058
3059     /**
3060      * Force the component's size to recalculate based on the underlying element's current height and width.
3061      * @return {Ext.BoxComponent} this
3062      */
3063     syncSize : function(){
3064         delete this.lastSize;
3065         this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
3066         return this;
3067     },
3068
3069     /* // protected
3070      * Called after the component is resized, this method is empty by default but can be implemented by any
3071      * subclass that needs to perform custom logic after a resize occurs.
3072      * @param {Number} adjWidth The box-adjusted width that was set
3073      * @param {Number} adjHeight The box-adjusted height that was set
3074      * @param {Number} rawWidth The width that was originally specified
3075      * @param {Number} rawHeight The height that was originally specified
3076      */
3077     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
3078
3079     },
3080
3081     /* // protected
3082      * Called after the component is moved, this method is empty by default but can be implemented by any
3083      * subclass that needs to perform custom logic after a move occurs.
3084      * @param {Number} x The new x position
3085      * @param {Number} y The new y position
3086      */
3087     onPosition : function(x, y){
3088
3089     },
3090
3091     // private
3092     adjustSize : function(w, h){
3093         if(this.autoWidth){
3094             w = 'auto';
3095         }
3096         if(this.autoHeight){
3097             h = 'auto';
3098         }
3099         return {width : w, height: h};
3100     },
3101
3102     // private
3103     adjustPosition : function(x, y){
3104         return {x : x, y: y};
3105     }
3106 });
3107 Ext.reg('box', Ext.BoxComponent);
3108
3109
3110 /**
3111  * @class Ext.Spacer
3112  * @extends Ext.BoxComponent
3113  * <p>Used to provide a sizable space in a layout.</p>
3114  * @constructor
3115  * @param {Object} config
3116  */
3117 Ext.Spacer = Ext.extend(Ext.BoxComponent, {
3118     autoEl:'div'
3119 });
3120 Ext.reg('spacer', Ext.Spacer);/**\r
3121  * @class Ext.SplitBar\r
3122  * @extends Ext.util.Observable\r
3123  * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).\r
3124  * <br><br>\r
3125  * Usage:\r
3126  * <pre><code>\r
3127 var split = new Ext.SplitBar("elementToDrag", "elementToSize",\r
3128                    Ext.SplitBar.HORIZONTAL, Ext.SplitBar.LEFT);\r
3129 split.setAdapter(new Ext.SplitBar.AbsoluteLayoutAdapter("container"));\r
3130 split.minSize = 100;\r
3131 split.maxSize = 600;\r
3132 split.animate = true;\r
3133 split.on('moved', splitterMoved);\r
3134 </code></pre>\r
3135  * @constructor\r
3136  * Create a new SplitBar\r
3137  * @param {Mixed} dragElement The element to be dragged and act as the SplitBar.\r
3138  * @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged\r
3139  * @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)\r
3140  * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or  \r
3141                         Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial\r
3142                         position of the SplitBar).\r
3143  */\r
3144 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){\r
3145     \r
3146     /** @private */\r
3147     this.el = Ext.get(dragElement, true);\r
3148     this.el.dom.unselectable = "on";\r
3149     /** @private */\r
3150     this.resizingEl = Ext.get(resizingElement, true);\r
3151 \r
3152     /**\r
3153      * @private\r
3154      * The orientation of the split. Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)\r
3155      * Note: If this is changed after creating the SplitBar, the placement property must be manually updated\r
3156      * @type Number\r
3157      */\r
3158     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;\r
3159     \r
3160     /**\r
3161      * The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.\r
3162      * @type Number\r
3163      * @property tickSize\r
3164      */\r
3165     /**\r
3166      * The minimum size of the resizing element. (Defaults to 0)\r
3167      * @type Number\r
3168      */\r
3169     this.minSize = 0;\r
3170     \r
3171     /**\r
3172      * The maximum size of the resizing element. (Defaults to 2000)\r
3173      * @type Number\r
3174      */\r
3175     this.maxSize = 2000;\r
3176     \r
3177     /**\r
3178      * Whether to animate the transition to the new size\r
3179      * @type Boolean\r
3180      */\r
3181     this.animate = false;\r
3182     \r
3183     /**\r
3184      * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.\r
3185      * @type Boolean\r
3186      */\r
3187     this.useShim = false;\r
3188     \r
3189     /** @private */\r
3190     this.shim = null;\r
3191     \r
3192     if(!existingProxy){\r
3193         /** @private */\r
3194         this.proxy = Ext.SplitBar.createProxy(this.orientation);\r
3195     }else{\r
3196         this.proxy = Ext.get(existingProxy).dom;\r
3197     }\r
3198     /** @private */\r
3199     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});\r
3200     \r
3201     /** @private */\r
3202     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);\r
3203     \r
3204     /** @private */\r
3205     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);\r
3206     \r
3207     /** @private */\r
3208     this.dragSpecs = {};\r
3209     \r
3210     /**\r
3211      * @private The adapter to use to positon and resize elements\r
3212      */\r
3213     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();\r
3214     this.adapter.init(this);\r
3215     \r
3216     if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
3217         /** @private */\r
3218         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);\r
3219         this.el.addClass("x-splitbar-h");\r
3220     }else{\r
3221         /** @private */\r
3222         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);\r
3223         this.el.addClass("x-splitbar-v");\r
3224     }\r
3225     \r
3226     this.addEvents(\r
3227         /**\r
3228          * @event resize\r
3229          * Fires when the splitter is moved (alias for {@link #moved})\r
3230          * @param {Ext.SplitBar} this\r
3231          * @param {Number} newSize the new width or height\r
3232          */\r
3233         "resize",\r
3234         /**\r
3235          * @event moved\r
3236          * Fires when the splitter is moved\r
3237          * @param {Ext.SplitBar} this\r
3238          * @param {Number} newSize the new width or height\r
3239          */\r
3240         "moved",\r
3241         /**\r
3242          * @event beforeresize\r
3243          * Fires before the splitter is dragged\r
3244          * @param {Ext.SplitBar} this\r
3245          */\r
3246         "beforeresize",\r
3247 \r
3248         "beforeapply"\r
3249     );\r
3250 \r
3251     Ext.SplitBar.superclass.constructor.call(this);\r
3252 };\r
3253 \r
3254 Ext.extend(Ext.SplitBar, Ext.util.Observable, {\r
3255     onStartProxyDrag : function(x, y){\r
3256         this.fireEvent("beforeresize", this);\r
3257         this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);\r
3258         this.overlay.unselectable();\r
3259         this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));\r
3260         this.overlay.show();\r
3261         Ext.get(this.proxy).setDisplayed("block");\r
3262         var size = this.adapter.getElementSize(this);\r
3263         this.activeMinSize = this.getMinimumSize();\r
3264         this.activeMaxSize = this.getMaximumSize();\r
3265         var c1 = size - this.activeMinSize;\r
3266         var c2 = Math.max(this.activeMaxSize - size, 0);\r
3267         if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
3268             this.dd.resetConstraints();\r
3269             this.dd.setXConstraint(\r
3270                 this.placement == Ext.SplitBar.LEFT ? c1 : c2, \r
3271                 this.placement == Ext.SplitBar.LEFT ? c2 : c1,\r
3272                 this.tickSize\r
3273             );\r
3274             this.dd.setYConstraint(0, 0);\r
3275         }else{\r
3276             this.dd.resetConstraints();\r
3277             this.dd.setXConstraint(0, 0);\r
3278             this.dd.setYConstraint(\r
3279                 this.placement == Ext.SplitBar.TOP ? c1 : c2, \r
3280                 this.placement == Ext.SplitBar.TOP ? c2 : c1,\r
3281                 this.tickSize\r
3282             );\r
3283          }\r
3284         this.dragSpecs.startSize = size;\r
3285         this.dragSpecs.startPoint = [x, y];\r
3286         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);\r
3287     },\r
3288     \r
3289     /** \r
3290      * @private Called after the drag operation by the DDProxy\r
3291      */\r
3292     onEndProxyDrag : function(e){\r
3293         Ext.get(this.proxy).setDisplayed(false);\r
3294         var endPoint = Ext.lib.Event.getXY(e);\r
3295         if(this.overlay){\r
3296             Ext.destroy(this.overlay);\r
3297             delete this.overlay;\r
3298         }\r
3299         var newSize;\r
3300         if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
3301             newSize = this.dragSpecs.startSize + \r
3302                 (this.placement == Ext.SplitBar.LEFT ?\r
3303                     endPoint[0] - this.dragSpecs.startPoint[0] :\r
3304                     this.dragSpecs.startPoint[0] - endPoint[0]\r
3305                 );\r
3306         }else{\r
3307             newSize = this.dragSpecs.startSize + \r
3308                 (this.placement == Ext.SplitBar.TOP ?\r
3309                     endPoint[1] - this.dragSpecs.startPoint[1] :\r
3310                     this.dragSpecs.startPoint[1] - endPoint[1]\r
3311                 );\r
3312         }\r
3313         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);\r
3314         if(newSize != this.dragSpecs.startSize){\r
3315             if(this.fireEvent('beforeapply', this, newSize) !== false){\r
3316                 this.adapter.setElementSize(this, newSize);\r
3317                 this.fireEvent("moved", this, newSize);\r
3318                 this.fireEvent("resize", this, newSize);\r
3319             }\r
3320         }\r
3321     },\r
3322     \r
3323     /**\r
3324      * Get the adapter this SplitBar uses\r
3325      * @return The adapter object\r
3326      */\r
3327     getAdapter : function(){\r
3328         return this.adapter;\r
3329     },\r
3330     \r
3331     /**\r
3332      * Set the adapter this SplitBar uses\r
3333      * @param {Object} adapter A SplitBar adapter object\r
3334      */\r
3335     setAdapter : function(adapter){\r
3336         this.adapter = adapter;\r
3337         this.adapter.init(this);\r
3338     },\r
3339     \r
3340     /**\r
3341      * Gets the minimum size for the resizing element\r
3342      * @return {Number} The minimum size\r
3343      */\r
3344     getMinimumSize : function(){\r
3345         return this.minSize;\r
3346     },\r
3347     \r
3348     /**\r
3349      * Sets the minimum size for the resizing element\r
3350      * @param {Number} minSize The minimum size\r
3351      */\r
3352     setMinimumSize : function(minSize){\r
3353         this.minSize = minSize;\r
3354     },\r
3355     \r
3356     /**\r
3357      * Gets the maximum size for the resizing element\r
3358      * @return {Number} The maximum size\r
3359      */\r
3360     getMaximumSize : function(){\r
3361         return this.maxSize;\r
3362     },\r
3363     \r
3364     /**\r
3365      * Sets the maximum size for the resizing element\r
3366      * @param {Number} maxSize The maximum size\r
3367      */\r
3368     setMaximumSize : function(maxSize){\r
3369         this.maxSize = maxSize;\r
3370     },\r
3371     \r
3372     /**\r
3373      * Sets the initialize size for the resizing element\r
3374      * @param {Number} size The initial size\r
3375      */\r
3376     setCurrentSize : function(size){\r
3377         var oldAnimate = this.animate;\r
3378         this.animate = false;\r
3379         this.adapter.setElementSize(this, size);\r
3380         this.animate = oldAnimate;\r
3381     },\r
3382     \r
3383     /**\r
3384      * Destroy this splitbar. \r
3385      * @param {Boolean} removeEl True to remove the element\r
3386      */\r
3387     destroy : function(removeEl){\r
3388                 Ext.destroy(this.shim, Ext.get(this.proxy));\r
3389         this.dd.unreg();\r
3390         if(removeEl){\r
3391             this.el.remove();\r
3392         }\r
3393                 this.purgeListeners();\r
3394     }\r
3395 });\r
3396 \r
3397 /**\r
3398  * @private static Create our own proxy element element. So it will be the same same size on all browsers, we won't use borders. Instead we use a background color.\r
3399  */\r
3400 Ext.SplitBar.createProxy = function(dir){\r
3401     var proxy = new Ext.Element(document.createElement("div"));\r
3402     proxy.unselectable();\r
3403     var cls = 'x-splitbar-proxy';\r
3404     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));\r
3405     document.body.appendChild(proxy.dom);\r
3406     return proxy.dom;\r
3407 };\r
3408 \r
3409 /** \r
3410  * @class Ext.SplitBar.BasicLayoutAdapter\r
3411  * Default Adapter. It assumes the splitter and resizing element are not positioned\r
3412  * elements and only gets/sets the width of the element. Generally used for table based layouts.\r
3413  */\r
3414 Ext.SplitBar.BasicLayoutAdapter = function(){\r
3415 };\r
3416 \r
3417 Ext.SplitBar.BasicLayoutAdapter.prototype = {\r
3418     // do nothing for now\r
3419     init : function(s){\r
3420     \r
3421     },\r
3422     /**\r
3423      * Called before drag operations to get the current size of the resizing element. \r
3424      * @param {Ext.SplitBar} s The SplitBar using this adapter\r
3425      */\r
3426      getElementSize : function(s){\r
3427         if(s.orientation == Ext.SplitBar.HORIZONTAL){\r
3428             return s.resizingEl.getWidth();\r
3429         }else{\r
3430             return s.resizingEl.getHeight();\r
3431         }\r
3432     },\r
3433     \r
3434     /**\r
3435      * Called after drag operations to set the size of the resizing element.\r
3436      * @param {Ext.SplitBar} s The SplitBar using this adapter\r
3437      * @param {Number} newSize The new size to set\r
3438      * @param {Function} onComplete A function to be invoked when resizing is complete\r
3439      */\r
3440     setElementSize : function(s, newSize, onComplete){\r
3441         if(s.orientation == Ext.SplitBar.HORIZONTAL){\r
3442             if(!s.animate){\r
3443                 s.resizingEl.setWidth(newSize);\r
3444                 if(onComplete){\r
3445                     onComplete(s, newSize);\r
3446                 }\r
3447             }else{\r
3448                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');\r
3449             }\r
3450         }else{\r
3451             \r
3452             if(!s.animate){\r
3453                 s.resizingEl.setHeight(newSize);\r
3454                 if(onComplete){\r
3455                     onComplete(s, newSize);\r
3456                 }\r
3457             }else{\r
3458                 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');\r
3459             }\r
3460         }\r
3461     }\r
3462 };\r
3463 \r
3464 /** \r
3465  *@class Ext.SplitBar.AbsoluteLayoutAdapter\r
3466  * @extends Ext.SplitBar.BasicLayoutAdapter\r
3467  * Adapter that  moves the splitter element to align with the resized sizing element. \r
3468  * Used with an absolute positioned SplitBar.\r
3469  * @param {Mixed} container The container that wraps around the absolute positioned content. If it's\r
3470  * document.body, make sure you assign an id to the body element.\r
3471  */\r
3472 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){\r
3473     this.basic = new Ext.SplitBar.BasicLayoutAdapter();\r
3474     this.container = Ext.get(container);\r
3475 };\r
3476 \r
3477 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {\r
3478     init : function(s){\r
3479         this.basic.init(s);\r
3480     },\r
3481     \r
3482     getElementSize : function(s){\r
3483         return this.basic.getElementSize(s);\r
3484     },\r
3485     \r
3486     setElementSize : function(s, newSize, onComplete){\r
3487         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));\r
3488     },\r
3489     \r
3490     moveSplitter : function(s){\r
3491         var yes = Ext.SplitBar;\r
3492         switch(s.placement){\r
3493             case yes.LEFT:\r
3494                 s.el.setX(s.resizingEl.getRight());\r
3495                 break;\r
3496             case yes.RIGHT:\r
3497                 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");\r
3498                 break;\r
3499             case yes.TOP:\r
3500                 s.el.setY(s.resizingEl.getBottom());\r
3501                 break;\r
3502             case yes.BOTTOM:\r
3503                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());\r
3504                 break;\r
3505         }\r
3506     }\r
3507 };\r
3508 \r
3509 /**\r
3510  * Orientation constant - Create a vertical SplitBar\r
3511  * @static\r
3512  * @type Number\r
3513  */\r
3514 Ext.SplitBar.VERTICAL = 1;\r
3515 \r
3516 /**\r
3517  * Orientation constant - Create a horizontal SplitBar\r
3518  * @static\r
3519  * @type Number\r
3520  */\r
3521 Ext.SplitBar.HORIZONTAL = 2;\r
3522 \r
3523 /**\r
3524  * Placement constant - The resizing element is to the left of the splitter element\r
3525  * @static\r
3526  * @type Number\r
3527  */\r
3528 Ext.SplitBar.LEFT = 1;\r
3529 \r
3530 /**\r
3531  * Placement constant - The resizing element is to the right of the splitter element\r
3532  * @static\r
3533  * @type Number\r
3534  */\r
3535 Ext.SplitBar.RIGHT = 2;\r
3536 \r
3537 /**\r
3538  * Placement constant - The resizing element is positioned above the splitter element\r
3539  * @static\r
3540  * @type Number\r
3541  */\r
3542 Ext.SplitBar.TOP = 3;\r
3543 \r
3544 /**\r
3545  * Placement constant - The resizing element is positioned under splitter element\r
3546  * @static\r
3547  * @type Number\r
3548  */\r
3549 Ext.SplitBar.BOTTOM = 4;\r
3550 /**\r
3551  * @class Ext.Container\r
3552  * @extends Ext.BoxComponent\r
3553  * <p>Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the\r
3554  * basic behavior of containing items, namely adding, inserting and removing items.</p>\r
3555  *\r
3556  * <p>The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}.\r
3557  * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight\r
3558  * Container to be encapsulated by an HTML element to your specifications by using the\r
3559  * <tt><b>{@link Ext.Component#autoEl autoEl}</b></tt> config option. This is a useful technique when creating\r
3560  * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels}\r
3561  * for example.</p>\r
3562  *\r
3563  * <p>The code below illustrates both how to explicitly create a Container, and how to implicitly\r
3564  * create one using the <b><tt>'container'</tt></b> xtype:<pre><code>\r
3565 // explicitly create a Container\r
3566 var embeddedColumns = new Ext.Container({\r
3567     autoEl: 'div',  // This is the default\r
3568     layout: 'column',\r
3569     defaults: {\r
3570         // implicitly create Container by specifying xtype\r
3571         xtype: 'container',\r
3572         autoEl: 'div', // This is the default.\r
3573         layout: 'form',\r
3574         columnWidth: 0.5,\r
3575         style: {\r
3576             padding: '10px'\r
3577         }\r
3578     },\r
3579 //  The two items below will be Ext.Containers, each encapsulated by a &lt;DIV> element.\r
3580     items: [{\r
3581         items: {\r
3582             xtype: 'datefield',\r
3583             name: 'startDate',\r
3584             fieldLabel: 'Start date'\r
3585         }\r
3586     }, {\r
3587         items: {\r
3588             xtype: 'datefield',\r
3589             name: 'endDate',\r
3590             fieldLabel: 'End date'\r
3591         }\r
3592     }]\r
3593 });</code></pre></p>\r
3594  *\r
3595  * <p><u><b>Layout</b></u></p>\r
3596  * <p>Container classes delegate the rendering of child Components to a layout\r
3597  * manager class which must be configured into the Container using the\r
3598  * <code><b>{@link #layout}</b></code> configuration property.</p>\r
3599  * <p>When either specifying child <code>{@link #items}</code> of a Container,\r
3600  * or dynamically {@link #add adding} Components to a Container, remember to\r
3601  * consider how you wish the Container to arrange those child elements, and\r
3602  * whether those child elements need to be sized using one of Ext's built-in\r
3603  * <b><code>{@link #layout}</code></b> schemes. By default, Containers use the\r
3604  * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only\r
3605  * renders child components, appending them one after the other inside the\r
3606  * Container, and <b>does not apply any sizing</b> at all.</p>\r
3607  * <p>A common mistake is when a developer neglects to specify a\r
3608  * <b><code>{@link #layout}</code></b> (e.g. widgets like GridPanels or\r
3609  * TreePanels are added to Containers for which no <tt><b>{@link #layout}</b></tt>\r
3610  * has been specified). If a Container is left to use the default\r
3611  * {@link Ext.layout.ContainerLayout ContainerLayout} scheme, none of its\r
3612  * child components will be resized, or changed in any way when the Container\r
3613  * is resized.</p>\r
3614  * <p>Certain layout managers allow dynamic addition of child components.\r
3615  * Those that do include {@link Ext.layout.CardLayout},\r
3616  * {@link Ext.layout.AnchorLayout}, {@link Ext.layout.FormLayout}, and\r
3617  * {@link Ext.layout.TableLayout}. For example:<pre><code>\r
3618 //  Create the GridPanel.\r
3619 var myNewGrid = new Ext.grid.GridPanel({\r
3620     store: myStore,\r
3621     columns: myColumnModel,\r
3622     title: 'Results', // the title becomes the title of the tab\r
3623 });\r
3624 \r
3625 myTabPanel.add(myNewGrid); // {@link Ext.TabPanel} implicitly uses {@link Ext.layout.CardLayout CardLayout}\r
3626 myTabPanel.{@link Ext.TabPanel#setActiveTab setActiveTab}(myNewGrid);\r
3627  * </code></pre></p>\r
3628  * <p>The example above adds a newly created GridPanel to a TabPanel. Note that\r
3629  * a TabPanel uses {@link Ext.layout.CardLayout} as its layout manager which\r
3630  * means all its child items are sized to {@link Ext.layout.FitLayout fit}\r
3631  * exactly into its client area.\r
3632  * <p><b><u>Overnesting is a common problem</u></b>.\r
3633  * An example of overnesting occurs when a GridPanel is added to a TabPanel\r
3634  * by wrapping the GridPanel <i>inside</i> a wrapping Panel (that has no\r
3635  * <tt><b>{@link #layout}</b></tt> specified) and then add that wrapping Panel\r
3636  * to the TabPanel. The point to realize is that a GridPanel <b>is</b> a\r
3637  * Component which can be added directly to a Container. If the wrapping Panel\r
3638  * has no <tt><b>{@link #layout}</b></tt> configuration, then the overnested\r
3639  * GridPanel will not be sized as expected.<p>\r
3640  *\r
3641  * <p><u><b>Adding via remote configuration</b></u></p>\r
3642  *\r
3643  * <p>A server side script can be used to add Components which are generated dynamically on the server.\r
3644  * An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server\r
3645  * based on certain parameters:\r
3646  * </p><pre><code>\r
3647 // execute an Ajax request to invoke server side script:\r
3648 Ext.Ajax.request({\r
3649     url: 'gen-invoice-grid.php',\r
3650     // send additional parameters to instruct server script\r
3651     params: {\r
3652         startDate: Ext.getCmp('start-date').getValue(),\r
3653         endDate: Ext.getCmp('end-date').getValue()\r
3654     },\r
3655     // process the response object to add it to the TabPanel:\r
3656     success: function(xhr) {\r
3657         var newComponent = eval(xhr.responseText); // see discussion below\r
3658         myTabPanel.add(newComponent); // add the component to the TabPanel\r
3659         myTabPanel.setActiveTab(newComponent);\r
3660     },\r
3661     failure: function() {\r
3662         Ext.Msg.alert("Grid create failed", "Server communication failure");\r
3663     }\r
3664 });\r
3665 </code></pre>\r
3666  * <p>The server script needs to return an executable Javascript statement which, when processed\r
3667  * using <tt>eval()</tt>, will return either a config object with an {@link Ext.Component#xtype xtype},\r
3668  * or an instantiated Component. The server might return this for example:</p><pre><code>\r
3669 (function() {\r
3670     function formatDate(value){\r
3671         return value ? value.dateFormat('M d, Y') : '';\r
3672     };\r
3673 \r
3674     var store = new Ext.data.Store({\r
3675         url: 'get-invoice-data.php',\r
3676         baseParams: {\r
3677             startDate: '01/01/2008',\r
3678             endDate: '01/31/2008'\r
3679         },\r
3680         reader: new Ext.data.JsonReader({\r
3681             record: 'transaction',\r
3682             idProperty: 'id',\r
3683             totalRecords: 'total'\r
3684         }, [\r
3685            'customer',\r
3686            'invNo',\r
3687            {name: 'date', type: 'date', dateFormat: 'm/d/Y'},\r
3688            {name: 'value', type: 'float'}\r
3689         ])\r
3690     });\r
3691 \r
3692     var grid = new Ext.grid.GridPanel({\r
3693         title: 'Invoice Report',\r
3694         bbar: new Ext.PagingToolbar(store),\r
3695         store: store,\r
3696         columns: [\r
3697             {header: "Customer", width: 250, dataIndex: 'customer', sortable: true},\r
3698             {header: "Invoice Number", width: 120, dataIndex: 'invNo', sortable: true},\r
3699             {header: "Invoice Date", width: 100, dataIndex: 'date', renderer: formatDate, sortable: true},\r
3700             {header: "Value", width: 120, dataIndex: 'value', renderer: 'usMoney', sortable: true}\r
3701         ],\r
3702     });\r
3703     store.load();\r
3704     return grid;  // return instantiated component\r
3705 })();\r
3706 </code></pre>\r
3707  * <p>When the above code fragment is passed through the <tt>eval</tt> function in the success handler\r
3708  * of the Ajax request, the code is executed by the Javascript processor, and the anonymous function\r
3709  * runs, and returns the instantiated grid component.</p>\r
3710  * <p>Note: since the code above is <i>generated</i> by a server script, the <tt>baseParams</tt> for\r
3711  * the Store, the metadata to allow generation of the Record layout, and the ColumnModel\r
3712  * can all be generated into the code since these are all known on the server.</p>\r
3713  *\r
3714  * @xtype container\r
3715  */\r
3716 Ext.Container = Ext.extend(Ext.BoxComponent, {\r
3717     /**\r
3718      * @cfg {Boolean} monitorResize\r
3719      * True to automatically monitor window resize events to handle anything that is sensitive to the current size\r
3720      * of the viewport.  This value is typically managed by the chosen <code>{@link #layout}</code> and should not need\r
3721      * to be set manually.\r
3722      */\r
3723     /**\r
3724      * @cfg {String/Object} layout\r
3725      * <p><b>*Important</b>: In order for child items to be correctly sized and\r
3726      * positioned, typically a layout manager <b>must</b> be specified through\r
3727      * the <code>layout</code> configuration option.</p>\r
3728      * <br><p>The sizing and positioning of child {@link items} is the responsibility of\r
3729      * the Container's layout manager which creates and manages the type of layout\r
3730      * you have in mind.  For example:</p><pre><code>\r
3731 new Ext.Window({\r
3732     width:300, height: 300,\r
3733     layout: 'fit', // explicitly set layout manager: override the default (layout:'auto')\r
3734     items: [{\r
3735         title: 'Panel inside a Window'\r
3736     }]\r
3737 }).show();\r
3738      * </code></pre>\r
3739      * <p>If the {@link #layout} configuration is not explicitly specified for\r
3740      * a general purpose container (e.g. Container or Panel) the\r
3741      * {@link Ext.layout.ContainerLayout default layout manager} will be used\r
3742      * which does nothing but render child components sequentially into the\r
3743      * Container (no sizing or positioning will be performed in this situation).\r
3744      * Some container classes implicitly specify a default layout\r
3745      * (e.g. FormPanel specifies <code>layout:'form'</code>). Other specific\r
3746      * purpose classes internally specify/manage their internal layout (e.g.\r
3747      * GridPanel, TabPanel, TreePanel, Toolbar, Menu, etc.).</p>\r
3748      * <br><p><b><code>layout</code></b> may be specified as either as an Object or\r
3749      * as a String:</p><div><ul class="mdetail-params">\r
3750      *\r
3751      * <li><u>Specify as an Object</u></li>\r
3752      * <div><ul class="mdetail-params">\r
3753      * <li>Example usage:</li>\r
3754 <pre><code>\r
3755 layout: {\r
3756     type: 'vbox',\r
3757     padding: '5',\r
3758     align: 'left'\r
3759 }\r
3760 </code></pre>\r
3761      *\r
3762      * <li><tt><b>type</b></tt></li>\r
3763      * <br/><p>The layout type to be used for this container.  If not specified,\r
3764      * a default {@link Ext.layout.ContainerLayout} will be created and used.</p>\r
3765      * <br/><p>Valid layout <tt>type</tt> values are:</p>\r
3766      * <div class="sub-desc"><ul class="mdetail-params">\r
3767      * <li><tt><b>{@link Ext.layout.AbsoluteLayout absolute}</b></tt></li>\r
3768      * <li><tt><b>{@link Ext.layout.AccordionLayout accordion}</b></tt></li>\r
3769      * <li><tt><b>{@link Ext.layout.AnchorLayout anchor}</b></tt></li>\r
3770      * <li><tt><b>{@link Ext.layout.ContainerLayout auto}</b></tt> &nbsp;&nbsp;&nbsp; <b>Default</b></li>\r
3771      * <li><tt><b>{@link Ext.layout.BorderLayout border}</b></tt></li>\r
3772      * <li><tt><b>{@link Ext.layout.CardLayout card}</b></tt></li>\r
3773      * <li><tt><b>{@link Ext.layout.ColumnLayout column}</b></tt></li>\r
3774      * <li><tt><b>{@link Ext.layout.FitLayout fit}</b></tt></li>\r
3775      * <li><tt><b>{@link Ext.layout.FormLayout form}</b></tt></li>\r
3776      * <li><tt><b>{@link Ext.layout.HBoxLayout hbox}</b></tt></li>\r
3777      * <li><tt><b>{@link Ext.layout.MenuLayout menu}</b></tt></li>\r
3778      * <li><tt><b>{@link Ext.layout.TableLayout table}</b></tt></li>\r
3779      * <li><tt><b>{@link Ext.layout.ToolbarLayout toolbar}</b></tt></li>\r
3780      * <li><tt><b>{@link Ext.layout.VBoxLayout vbox}</b></tt></li>\r
3781      * </ul></div>\r
3782      *\r
3783      * <li>Layout specific configuration properties</li>\r
3784      * <br/><p>Additional layout specific configuration properties may also be\r
3785      * specified. For complete details regarding the valid config options for\r
3786      * each layout type, see the layout class corresponding to the <tt>type</tt>\r
3787      * specified.</p>\r
3788      *\r
3789      * </ul></div>\r
3790      *\r
3791      * <li><u>Specify as a String</u></li>\r
3792      * <div><ul class="mdetail-params">\r
3793      * <li>Example usage:</li>\r
3794 <pre><code>\r
3795 layout: 'vbox',\r
3796 layoutConfig: {\r
3797     padding: '5',\r
3798     align: 'left'\r
3799 }\r
3800 </code></pre>\r
3801      * <li><tt><b>layout</b></tt></li>\r
3802      * <br/><p>The layout <tt>type</tt> to be used for this container (see list\r
3803      * of valid layout type values above).</p><br/>\r
3804      * <li><tt><b>{@link #layoutConfig}</b></tt></li>\r
3805      * <br/><p>Additional layout specific configuration properties. For complete\r
3806      * details regarding the valid config options for each layout type, see the\r
3807      * layout class corresponding to the <tt>layout</tt> specified.</p>\r
3808      * </ul></div></ul></div>\r
3809      */\r
3810     /**\r
3811      * @cfg {Object} layoutConfig\r
3812      * This is a config object containing properties specific to the chosen\r
3813      * <b><code>{@link #layout}</code></b> if <b><code>{@link #layout}</code></b>\r
3814      * has been specified as a <i>string</i>.</p>\r
3815      */\r
3816     /**\r
3817      * @cfg {Boolean/Number} bufferResize\r
3818      * When set to true (50 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer\r
3819      * the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers\r
3820      * with a large quantity of sub-components for which frequent layout calls would be expensive. Defaults to <tt>50</tt>.\r
3821      */\r
3822     bufferResize: 50,\r
3823 \r
3824     /**\r
3825      * @cfg {String/Number} activeItem\r
3826      * A string component id or the numeric index of the component that should be initially activated within the\r
3827      * container's layout on render.  For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first\r
3828      * item in the container's collection).  activeItem only applies to layout styles that can display\r
3829      * items one at a time (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout} and\r
3830      * {@link Ext.layout.FitLayout}).  Related to {@link Ext.layout.ContainerLayout#activeItem}.\r
3831      */\r
3832     /**\r
3833      * @cfg {Object/Array} items\r
3834      * <pre><b>** IMPORTANT</b>: be sure to <b>{@link #layout specify a <code>layout</code>} if needed ! **</b></pre>\r
3835      * <p>A single item, or an array of child Components to be added to this container,\r
3836      * for example:</p>\r
3837      * <pre><code>\r
3838 // specifying a single item\r
3839 items: {...},\r
3840 layout: 'fit',    // specify a layout!\r
3841 \r
3842 // specifying multiple items\r
3843 items: [{...}, {...}],\r
3844 layout: 'anchor', // specify a layout!\r
3845      * </code></pre>\r
3846      * <p>Each item may be:</p>\r
3847      * <div><ul class="mdetail-params">\r
3848      * <li>any type of object based on {@link Ext.Component}</li>\r
3849      * <li>a fully instanciated object or</li>\r
3850      * <li>an object literal that:</li>\r
3851      * <div><ul class="mdetail-params">\r
3852      * <li>has a specified <code>{@link Ext.Component#xtype xtype}</code></li>\r
3853      * <li>the {@link Ext.Component#xtype} specified is associated with the Component\r
3854      * desired and should be chosen from one of the available xtypes as listed\r
3855      * in {@link Ext.Component}.</li>\r
3856      * <li>If an <code>{@link Ext.Component#xtype xtype}</code> is not explicitly\r
3857      * specified, the {@link #defaultType} for that Container is used.</li>\r
3858      * <li>will be "lazily instanciated", avoiding the overhead of constructing a fully\r
3859      * instanciated Component object</li>\r
3860      * </ul></div></ul></div>\r
3861      * <p><b>Notes</b>:</p>\r
3862      * <div><ul class="mdetail-params">\r
3863      * <li>Ext uses lazy rendering. Child Components will only be rendered\r
3864      * should it become necessary. Items are automatically laid out when they are first\r
3865      * shown (no sizing is done while hidden), or in response to a {@link #doLayout} call.</li>\r
3866      * <li>Do not specify <code>{@link Ext.Panel#contentEl contentEl}</code>/\r
3867      * <code>{@link Ext.Panel#html html}</code> with <code>items</code>.</li>\r
3868      * </ul></div>\r
3869      */\r
3870     /**\r
3871      * @cfg {Object} defaults\r
3872      * <p>A config object that will be applied to all components added to this container either via the {@link #items}\r
3873      * config or via the {@link #add} or {@link #insert} methods.  The <tt>defaults</tt> config can contain any\r
3874      * number of name/value property pairs to be added to each item, and should be valid for the types of items\r
3875      * being added to the container.  For example, to automatically apply padding to the body of each of a set of\r
3876      * contained {@link Ext.Panel} items, you could pass: <tt>defaults: {bodyStyle:'padding:15px'}</tt>.</p><br/>\r
3877      * <p><b>Note</b>: <tt>defaults</tt> will not be applied to config objects if the option is already specified.\r
3878      * For example:</p><pre><code>\r
3879 defaults: {               // defaults are applied to items, not the container\r
3880     autoScroll:true\r
3881 },\r
3882 items: [\r
3883     {\r
3884         xtype: 'panel',   // defaults <b>do not</b> have precedence over\r
3885         id: 'panel1',     // options in config objects, so the defaults\r
3886         autoScroll: false // will not be applied here, panel1 will be autoScroll:false\r
3887     },\r
3888     new Ext.Panel({       // defaults <b>do</b> have precedence over options\r
3889         id: 'panel2',     // options in components, so the defaults\r
3890         autoScroll: false // will be applied here, panel2 will be autoScroll:true.\r
3891     })\r
3892 ]\r
3893      * </code></pre>\r
3894      */\r
3895 \r
3896 \r
3897     /** @cfg {Boolean} autoDestroy\r
3898      * If true the container will automatically destroy any contained component that is removed from it, else\r
3899      * destruction must be handled manually (defaults to true).\r
3900      */\r
3901     autoDestroy : true,\r
3902 \r
3903     /** @cfg {Boolean} forceLayout\r
3904      * If true the container will force a layout initially even if hidden or collapsed. This option\r
3905      * is useful for forcing forms to render in collapsed or hidden containers. (defaults to false).\r
3906      */\r
3907     forceLayout: false,\r
3908 \r
3909     /** @cfg {Boolean} hideBorders\r
3910      * True to hide the borders of each contained component, false to defer to the component's existing\r
3911      * border settings (defaults to false).\r
3912      */\r
3913     /** @cfg {String} defaultType\r
3914      * <p>The default {@link Ext.Component xtype} of child Components to create in this Container when\r
3915      * a child item is specified as a raw configuration object, rather than as an instantiated Component.</p>\r
3916      * <p>Defaults to <tt>'panel'</tt>, except {@link Ext.menu.Menu} which defaults to <tt>'menuitem'</tt>,\r
3917      * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to <tt>'button'</tt>.</p>\r
3918      */\r
3919     defaultType : 'panel',\r
3920 \r
3921     /** @cfg {String} resizeEvent\r
3922      * The event to listen to for resizing in layouts. Defaults to <tt>'resize'</tt>.\r
3923      */\r
3924     resizeEvent: 'resize',\r
3925     \r
3926     /**\r
3927      * @cfg {Array} bubbleEvents\r
3928      * <p>An array of events that, when fired, should be bubbled to any parent container.\r
3929      * Defaults to <tt>['add', 'remove']</tt>.\r
3930      */\r
3931     bubbleEvents: ['add', 'remove'],\r
3932 \r
3933     // private\r
3934     initComponent : function(){\r
3935         Ext.Container.superclass.initComponent.call(this);\r
3936 \r
3937         this.addEvents(\r
3938             /**\r
3939              * @event afterlayout\r
3940              * Fires when the components in this container are arranged by the associated layout manager.\r
3941              * @param {Ext.Container} this\r
3942              * @param {ContainerLayout} layout The ContainerLayout implementation for this container\r
3943              */\r
3944             'afterlayout',\r
3945             /**\r
3946              * @event beforeadd\r
3947              * Fires before any {@link Ext.Component} is added or inserted into the container.\r
3948              * A handler can return false to cancel the add.\r
3949              * @param {Ext.Container} this\r
3950              * @param {Ext.Component} component The component being added\r
3951              * @param {Number} index The index at which the component will be added to the container's items collection\r
3952              */\r
3953             'beforeadd',\r
3954             /**\r
3955              * @event beforeremove\r
3956              * Fires before any {@link Ext.Component} is removed from the container.  A handler can return\r
3957              * false to cancel the remove.\r
3958              * @param {Ext.Container} this\r
3959              * @param {Ext.Component} component The component being removed\r
3960              */\r
3961             'beforeremove',\r
3962             /**\r
3963              * @event add\r
3964              * @bubbles\r
3965              * Fires after any {@link Ext.Component} is added or inserted into the container.\r
3966              * @param {Ext.Container} this\r
3967              * @param {Ext.Component} component The component that was added\r
3968              * @param {Number} index The index at which the component was added to the container's items collection\r
3969              */\r
3970             'add',\r
3971             /**\r
3972              * @event remove\r
3973              * @bubbles\r
3974              * Fires after any {@link Ext.Component} is removed from the container.\r
3975              * @param {Ext.Container} this\r
3976              * @param {Ext.Component} component The component that was removed\r
3977              */\r
3978             'remove'\r
3979         );\r
3980 \r
3981         this.enableBubble(this.bubbleEvents);\r
3982 \r
3983         /**\r
3984          * The collection of components in this container as a {@link Ext.util.MixedCollection}\r
3985          * @type MixedCollection\r
3986          * @property items\r
3987          */\r
3988         var items = this.items;\r
3989         if(items){\r
3990             delete this.items;\r
3991             this.add(items);\r
3992         }\r
3993     },\r
3994 \r
3995     // private\r
3996     initItems : function(){\r
3997         if(!this.items){\r
3998             this.items = new Ext.util.MixedCollection(false, this.getComponentId);\r
3999             this.getLayout(); // initialize the layout\r
4000         }\r
4001     },\r
4002 \r
4003     // private\r
4004     setLayout : function(layout){\r
4005         if(this.layout && this.layout != layout){\r
4006             this.layout.setContainer(null);\r
4007         }\r
4008         this.initItems();\r
4009         this.layout = layout;\r
4010         layout.setContainer(this);\r
4011     },\r
4012 \r
4013     afterRender: function(){\r
4014         Ext.Container.superclass.afterRender.call(this);\r
4015         if(!this.layout){\r
4016             this.layout = 'auto';\r
4017         }\r
4018         if(Ext.isObject(this.layout) && !this.layout.layout){\r
4019             this.layoutConfig = this.layout;\r
4020             this.layout = this.layoutConfig.type;\r
4021         }\r
4022         if(Ext.isString(this.layout)){\r
4023             this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);\r
4024         }\r
4025         this.setLayout(this.layout);\r
4026 \r
4027         if(this.activeItem !== undefined){\r
4028             var item = this.activeItem;\r
4029             delete this.activeItem;\r
4030             this.layout.setActiveItem(item);\r
4031         }\r
4032         if(!this.ownerCt){\r
4033             // force a layout if no ownerCt is set\r
4034             this.doLayout(false, true);\r
4035         }\r
4036         if(this.monitorResize === true){\r
4037             Ext.EventManager.onWindowResize(this.doLayout, this, [false]);\r
4038         }\r
4039     },\r
4040 \r
4041     /**\r
4042      * <p>Returns the Element to be used to contain the child Components of this Container.</p>\r
4043      * <p>An implementation is provided which returns the Container's {@link #getEl Element}, but\r
4044      * if there is a more complex structure to a Container, this may be overridden to return\r
4045      * the element into which the {@link #layout layout} renders child Components.</p>\r
4046      * @return {Ext.Element} The Element to render child Components into.\r
4047      */\r
4048     getLayoutTarget : function(){\r
4049         return this.el;\r
4050     },\r
4051 \r
4052     // private - used as the key lookup function for the items collection\r
4053     getComponentId : function(comp){\r
4054         return comp.getItemId();\r
4055     },\r
4056 \r
4057     /**\r
4058      * <p>Adds {@link Ext.Component Component}(s) to this Container.</p>\r
4059      * <br><p><b>Description</b></u> :\r
4060      * <div><ul class="mdetail-params">\r
4061      * <li>Fires the {@link #beforeadd} event before adding</li>\r
4062      * <li>The Container's {@link #defaults default config values} will be applied\r
4063      * accordingly (see <code>{@link #defaults}</code> for details).</li>\r
4064      * <li>Fires the {@link #add} event after the component has been added.</li>\r
4065      * </ul></div>\r
4066      * <br><p><b>Notes</b></u> :\r
4067      * <div><ul class="mdetail-params">\r
4068      * <li>If the Container is <i>already rendered</i> when <tt>add</tt>\r
4069      * is called, you may need to call {@link #doLayout} to refresh the view which causes\r
4070      * any unrendered child Components to be rendered. This is required so that you can\r
4071      * <tt>add</tt> multiple child components if needed while only refreshing the layout\r
4072      * once. For example:<pre><code>\r
4073 var tb = new {@link Ext.Toolbar}();\r
4074 tb.render(document.body);  // toolbar is rendered\r
4075 tb.add({text:'Button 1'}); // add multiple items ({@link #defaultType} for {@link Ext.Toolbar Toolbar} is 'button')\r
4076 tb.add({text:'Button 2'});\r
4077 tb.{@link #doLayout}();             // refresh the layout\r
4078      * </code></pre></li>\r
4079      * <li><i>Warning:</i> Containers directly managed by the BorderLayout layout manager\r
4080      * may not be removed or added.  See the Notes for {@link Ext.layout.BorderLayout BorderLayout}\r
4081      * for more details.</li>\r
4082      * </ul></div>\r
4083      * @param {Object/Array} component\r
4084      * <p>Either a single component or an Array of components to add.  See\r
4085      * <code>{@link #items}</code> for additional information.</p>\r
4086      * @param {Object} (Optional) component_2\r
4087      * @param {Object} (Optional) component_n\r
4088      * @return {Ext.Component} component The Component (or config object) that was added.\r
4089      */\r
4090     add : function(comp){\r
4091         this.initItems();\r
4092         var args = arguments.length > 1;\r
4093         if(args || Ext.isArray(comp)){\r
4094             Ext.each(args ? arguments : comp, function(c){\r
4095                 this.add(c);\r
4096             }, this);\r
4097             return;\r
4098         }\r
4099         var c = this.lookupComponent(this.applyDefaults(comp));\r
4100         var pos = this.items.length;\r
4101         if(this.fireEvent('beforeadd', this, c, pos) !== false && this.onBeforeAdd(c) !== false){\r
4102             this.items.add(c);\r
4103             c.ownerCt = this;\r
4104             this.onAdd(c);\r
4105             this.fireEvent('add', this, c, pos);\r
4106         }\r
4107         return c;\r
4108     },\r
4109 \r
4110     onAdd : function(c){\r
4111         // Empty template method\r
4112     },\r
4113 \r
4114     /**\r
4115      * Inserts a Component into this Container at a specified index. Fires the\r
4116      * {@link #beforeadd} event before inserting, then fires the {@link #add} event after the\r
4117      * Component has been inserted.\r
4118      * @param {Number} index The index at which the Component will be inserted\r
4119      * into the Container's items collection\r
4120      * @param {Ext.Component} component The child Component to insert.<br><br>\r
4121      * Ext uses lazy rendering, and will only render the inserted Component should\r
4122      * it become necessary.<br><br>\r
4123      * A Component config object may be passed in order to avoid the overhead of\r
4124      * constructing a real Component object if lazy rendering might mean that the\r
4125      * inserted Component will not be rendered immediately. To take advantage of\r
4126      * this 'lazy instantiation', set the {@link Ext.Component#xtype} config\r
4127      * property to the registered type of the Component wanted.<br><br>\r
4128      * For a list of all available xtypes, see {@link Ext.Component}.\r
4129      * @return {Ext.Component} component The Component (or config object) that was\r
4130      * inserted with the Container's default config values applied.\r
4131      */\r
4132     insert : function(index, comp){\r
4133         this.initItems();\r
4134         var a = arguments, len = a.length;\r
4135         if(len > 2){\r
4136             for(var i = len-1; i >= 1; --i) {\r
4137                 this.insert(index, a[i]);\r
4138             }\r
4139             return;\r
4140         }\r
4141         var c = this.lookupComponent(this.applyDefaults(comp));\r
4142         index = Math.min(index, this.items.length);\r
4143         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){\r
4144             if(c.ownerCt == this){\r
4145                 this.items.remove(c);\r
4146             }\r
4147             this.items.insert(index, c);\r
4148             c.ownerCt = this;\r
4149             this.onAdd(c);\r
4150             this.fireEvent('add', this, c, index);\r
4151         }\r
4152         return c;\r
4153     },\r
4154 \r
4155     // private\r
4156     applyDefaults : function(c){\r
4157         if(this.defaults){\r
4158             if(Ext.isString(c)){\r
4159                 c = Ext.ComponentMgr.get(c);\r
4160                 Ext.apply(c, this.defaults);\r
4161             }else if(!c.events){\r
4162                 Ext.applyIf(c, this.defaults);\r
4163             }else{\r
4164                 Ext.apply(c, this.defaults);\r
4165             }\r
4166         }\r
4167         return c;\r
4168     },\r
4169 \r
4170     // private\r
4171     onBeforeAdd : function(item){\r
4172         if(item.ownerCt){\r
4173             item.ownerCt.remove(item, false);\r
4174         }\r
4175         if(this.hideBorders === true){\r
4176             item.border = (item.border === true);\r
4177         }\r
4178     },\r
4179 \r
4180     /**\r
4181      * Removes a component from this container.  Fires the {@link #beforeremove} event before removing, then fires\r
4182      * the {@link #remove} event after the component has been removed.\r
4183      * @param {Component/String} component The component reference or id to remove.\r
4184      * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.\r
4185      * Defaults to the value of this Container's {@link #autoDestroy} config.\r
4186      * @return {Ext.Component} component The Component that was removed.\r
4187      */\r
4188     remove : function(comp, autoDestroy){\r
4189         this.initItems();\r
4190         var c = this.getComponent(comp);\r
4191         if(c && this.fireEvent('beforeremove', this, c) !== false){\r
4192             delete c.ownerCt;\r
4193             if(this.layout && this.rendered){\r
4194                 this.layout.onRemove(c);\r
4195             }\r
4196             this.onRemove(c);\r
4197             this.items.remove(c);\r
4198             if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){\r
4199                 c.destroy();\r
4200             }\r
4201             this.fireEvent('remove', this, c);\r
4202         }\r
4203         return c;\r
4204     },\r
4205 \r
4206     onRemove: function(c){\r
4207         // Empty template method\r
4208     },\r
4209 \r
4210     /**\r
4211      * Removes all components from this container.\r
4212      * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.\r
4213      * Defaults to the value of this Container's {@link #autoDestroy} config.\r
4214      * @return {Array} Array of the destroyed components\r
4215      */\r
4216     removeAll: function(autoDestroy){\r
4217         this.initItems();\r
4218         var item, rem = [], items = [];\r
4219         this.items.each(function(i){\r
4220             rem.push(i);\r
4221         });\r
4222         for (var i = 0, len = rem.length; i < len; ++i){\r
4223             item = rem[i];\r
4224             this.remove(item, autoDestroy);\r
4225             if(item.ownerCt !== this){\r
4226                 items.push(item);\r
4227             }\r
4228         }\r
4229         return items;\r
4230     },\r
4231 \r
4232     /**\r
4233      * Examines this container's <code>{@link #items}</code> <b>property</b>\r
4234      * and gets a direct child component of this container.\r
4235      * @param {String/Number} comp This parameter may be any of the following:\r
4236      * <div><ul class="mdetail-params">\r
4237      * <li>a <b><tt>String</tt></b> : representing the <code>{@link Ext.Component#itemId itemId}</code>\r
4238      * or <code>{@link Ext.Component#id id}</code> of the child component </li>\r
4239      * <li>a <b><tt>Number</tt></b> : representing the position of the child component\r
4240      * within the <code>{@link #items}</code> <b>property</b></li>\r
4241      * </ul></div>\r
4242      * <p>For additional information see {@link Ext.util.MixedCollection#get}.\r
4243      * @return Ext.Component The component (if found).\r
4244      */\r
4245     getComponent : function(comp){\r
4246         if(Ext.isObject(comp)){\r
4247             comp = comp.getItemId();\r
4248         }\r
4249         return this.items.get(comp);\r
4250     },\r
4251 \r
4252     // private\r
4253     lookupComponent : function(comp){\r
4254         if(Ext.isString(comp)){\r
4255             return Ext.ComponentMgr.get(comp);\r
4256         }else if(!comp.events){\r
4257             return this.createComponent(comp);\r
4258         }\r
4259         return comp;\r
4260     },\r
4261 \r
4262     // private\r
4263     createComponent : function(config){\r
4264         return Ext.create(config, this.defaultType);\r
4265     },\r
4266 \r
4267     // private\r
4268     canLayout: function() {\r
4269         var el = this.getVisibilityEl();\r
4270         return el && !el.isStyle("display", "none");\r
4271     },\r
4272 \r
4273 \r
4274     /**\r
4275      * Force this container's layout to be recalculated. A call to this function is required after adding a new component\r
4276      * to an already rendered container, or possibly after changing sizing/position properties of child components.\r
4277      * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto\r
4278      * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer)\r
4279      * @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden.\r
4280      * @return {Ext.Container} this\r
4281      */\r
4282     doLayout: function(shallow, force){\r
4283         var rendered = this.rendered;\r
4284         forceLayout = force || this.forceLayout;\r
4285 \r
4286         if(!this.canLayout() || this.collapsed){\r
4287             this.deferLayout = this.deferLayout || !shallow;\r
4288             if(!forceLayout){\r
4289                 return;\r
4290             }\r
4291             shallow = shallow && !this.deferLayout;\r
4292         } else {\r
4293             delete this.deferLayout;\r
4294         }\r
4295         if(rendered && this.layout){\r
4296             this.layout.layout();\r
4297         }\r
4298         if(shallow !== true && this.items){\r
4299             var cs = this.items.items;\r
4300             for(var i = 0, len = cs.length; i < len; i++){\r
4301                 var c = cs[i];\r
4302                 if(c.doLayout){\r
4303                     c.doLayout(false, forceLayout);\r
4304                 }\r
4305             }\r
4306         }\r
4307         if(rendered){\r
4308             this.onLayout(shallow, forceLayout);\r
4309         }\r
4310         // Initial layout completed\r
4311         this.hasLayout = true;\r
4312         delete this.forceLayout;\r
4313     },\r
4314 \r
4315     //private\r
4316     onLayout : Ext.emptyFn,\r
4317 \r
4318     // private\r
4319     shouldBufferLayout: function(){\r
4320         /*\r
4321          * Returns true if the container should buffer a layout.\r
4322          * This is true only if the container has previously been laid out\r
4323          * and has a parent container that is pending a layout.\r
4324          */\r
4325         var hl = this.hasLayout;\r
4326         if(this.ownerCt){\r
4327             // Only ever buffer if we've laid out the first time and we have one pending.\r
4328             return hl ? !this.hasLayoutPending() : false;\r
4329         }\r
4330         // Never buffer initial layout\r
4331         return hl;\r
4332     },\r
4333 \r
4334     // private\r
4335     hasLayoutPending: function(){\r
4336         // Traverse hierarchy to see if any parent container has a pending layout.\r
4337         var pending = false;\r
4338         this.ownerCt.bubble(function(c){\r
4339             if(c.layoutPending){\r
4340                 pending = true;\r
4341                 return false;\r
4342             }\r
4343         });\r
4344         return pending;\r
4345     },\r
4346 \r
4347     onShow : function(){\r
4348         Ext.Container.superclass.onShow.call(this);\r
4349         if(this.deferLayout !== undefined){\r
4350             this.doLayout(true);\r
4351         }\r
4352     },\r
4353 \r
4354     /**\r
4355      * Returns the layout currently in use by the container.  If the container does not currently have a layout\r
4356      * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout.\r
4357      * @return {ContainerLayout} layout The container's layout\r
4358      */\r
4359     getLayout : function(){\r
4360         if(!this.layout){\r
4361             var layout = new Ext.layout.ContainerLayout(this.layoutConfig);\r
4362             this.setLayout(layout);\r
4363         }\r
4364         return this.layout;\r
4365     },\r
4366 \r
4367     // private\r
4368     beforeDestroy : function(){\r
4369         if(this.items){\r
4370             Ext.destroy.apply(Ext, this.items.items);\r
4371         }\r
4372         if(this.monitorResize){\r
4373             Ext.EventManager.removeResizeListener(this.doLayout, this);\r
4374         }\r
4375         Ext.destroy(this.layout);\r
4376         Ext.Container.superclass.beforeDestroy.call(this);\r
4377     },\r
4378 \r
4379     /**\r
4380      * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of\r
4381      * function call will be the scope provided or the current component. The arguments to the function\r
4382      * will be the args provided or the current component. If the function returns false at any point,\r
4383      * the bubble is stopped.\r
4384      * @param {Function} fn The function to call\r
4385      * @param {Object} scope (optional) The scope of the function (defaults to current node)\r
4386      * @param {Array} args (optional) The args to call the function with (default to passing the current component)\r
4387      * @return {Ext.Container} this\r
4388      */\r
4389     bubble : function(fn, scope, args){\r
4390         var p = this;\r
4391         while(p){\r
4392             if(fn.apply(scope || p, args || [p]) === false){\r
4393                 break;\r
4394             }\r
4395             p = p.ownerCt;\r
4396         }\r
4397         return this;\r
4398     },\r
4399 \r
4400     /**\r
4401      * Cascades down the component/container heirarchy from this component (called first), calling the specified function with\r
4402      * each component. The scope (<i>this</i>) of\r
4403      * function call will be the scope provided or the current component. The arguments to the function\r
4404      * will be the args provided or the current component. If the function returns false at any point,\r
4405      * the cascade is stopped on that branch.\r
4406      * @param {Function} fn The function to call\r
4407      * @param {Object} scope (optional) The scope of the function (defaults to current component)\r
4408      * @param {Array} args (optional) The args to call the function with (defaults to passing the current component)\r
4409      * @return {Ext.Container} this\r
4410      */\r
4411     cascade : function(fn, scope, args){\r
4412         if(fn.apply(scope || this, args || [this]) !== false){\r
4413             if(this.items){\r
4414                 var cs = this.items.items;\r
4415                 for(var i = 0, len = cs.length; i < len; i++){\r
4416                     if(cs[i].cascade){\r
4417                         cs[i].cascade(fn, scope, args);\r
4418                     }else{\r
4419                         fn.apply(scope || cs[i], args || [cs[i]]);\r
4420                     }\r
4421                 }\r
4422             }\r
4423         }\r
4424         return this;\r
4425     },\r
4426 \r
4427     /**\r
4428      * Find a component under this container at any level by id\r
4429      * @param {String} id\r
4430      * @return Ext.Component\r
4431      */\r
4432     findById : function(id){\r
4433         var m, ct = this;\r
4434         this.cascade(function(c){\r
4435             if(ct != c && c.id === id){\r
4436                 m = c;\r
4437                 return false;\r
4438             }\r
4439         });\r
4440         return m || null;\r
4441     },\r
4442 \r
4443     /**\r
4444      * Find a component under this container at any level by xtype or class\r
4445      * @param {String/Class} xtype The xtype string for a component, or the class of the component directly\r
4446      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is\r
4447      * the default), or true to check whether this Component is directly of the specified xtype.\r
4448      * @return {Array} Array of Ext.Components\r
4449      */\r
4450     findByType : function(xtype, shallow){\r
4451         return this.findBy(function(c){\r
4452             return c.isXType(xtype, shallow);\r
4453         });\r
4454     },\r
4455 \r
4456     /**\r
4457      * Find a component under this container at any level by property\r
4458      * @param {String} prop\r
4459      * @param {String} value\r
4460      * @return {Array} Array of Ext.Components\r
4461      */\r
4462     find : function(prop, value){\r
4463         return this.findBy(function(c){\r
4464             return c[prop] === value;\r
4465         });\r
4466     },\r
4467 \r
4468     /**\r
4469      * Find a component under this container at any level by a custom function. If the passed function returns\r
4470      * true, the component will be included in the results. The passed function is called with the arguments (component, this container).\r
4471      * @param {Function} fn The function to call\r
4472      * @param {Object} scope (optional)\r
4473      * @return {Array} Array of Ext.Components\r
4474      */\r
4475     findBy : function(fn, scope){\r
4476         var m = [], ct = this;\r
4477         this.cascade(function(c){\r
4478             if(ct != c && fn.call(scope || c, c, ct) === true){\r
4479                 m.push(c);\r
4480             }\r
4481         });\r
4482         return m;\r
4483     },\r
4484 \r
4485     /**\r
4486      * Get a component contained by this container (alias for items.get(key))\r
4487      * @param {String/Number} key The index or id of the component\r
4488      * @return {Ext.Component} Ext.Component\r
4489      */\r
4490     get : function(key){\r
4491         return this.items.get(key);\r
4492     }\r
4493 });\r
4494 \r
4495 Ext.Container.LAYOUTS = {};\r
4496 Ext.reg('container', Ext.Container);\r
4497 /**
4498  * @class Ext.layout.ContainerLayout
4499  * <p>The ContainerLayout class is the default layout manager delegated by {@link Ext.Container} to
4500  * render any child Components when no <tt>{@link Ext.Container#layout layout}</tt> is configured into
4501  * a {@link Ext.Container Container}. ContainerLayout provides the basic foundation for all other layout
4502  * classes in Ext. It simply renders all child Components into the Container, performing no sizing or
4503  * positioning services. To utilize a layout that provides sizing and positioning of child Components,
4504  * specify an appropriate <tt>{@link Ext.Container#layout layout}</tt>.</p>
4505  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
4506  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
4507  */
4508 Ext.layout.ContainerLayout = function(config){
4509     Ext.apply(this, config);
4510 };
4511
4512 Ext.layout.ContainerLayout.prototype = {
4513     /**
4514      * @cfg {String} extraCls
4515      * <p>An optional extra CSS class that will be added to the container. This can be useful for adding
4516      * customized styles to the container or any of its children using standard CSS rules. See
4517      * {@link Ext.Component}.{@link Ext.Component#ctCls ctCls} also.</p>
4518      * <p><b>Note</b>: <tt>extraCls</tt> defaults to <tt>''</tt> except for the following classes
4519      * which assign a value by default:
4520      * <div class="mdetail-params"><ul>
4521      * <li>{@link Ext.layout.AbsoluteLayout Absolute Layout} : <tt>'x-abs-layout-item'</tt></li>
4522      * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-item'</tt></li>
4523      * <li>{@link Ext.layout.ColumnLayout Column Layout} : <tt>'x-column'</tt></li>
4524      * </ul></div>
4525      * To configure the above Classes with an extra CSS class append to the default.  For example,
4526      * for ColumnLayout:<pre><code>
4527      * extraCls: 'x-column custom-class'
4528      * </code></pre>
4529      * </p>
4530      */
4531     /**
4532      * @cfg {Boolean} renderHidden
4533      * True to hide each contained item on render (defaults to false).
4534      */
4535
4536     /**
4537      * A reference to the {@link Ext.Component} that is active.  For example, <pre><code>
4538      * if(myPanel.layout.activeItem.id == 'item-1') { ... }
4539      * </code></pre>
4540      * <tt>activeItem</tt> only applies to layout styles that can display items one at a time
4541      * (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout}
4542      * and {@link Ext.layout.FitLayout}).  Read-only.  Related to {@link Ext.Container#activeItem}.
4543      * @type {Ext.Component}
4544      * @property activeItem
4545      */
4546
4547     // private
4548     monitorResize:false,
4549     // private
4550     activeItem : null,
4551
4552     // private
4553     layout : function(){
4554         var target = this.container.getLayoutTarget();
4555         this.onLayout(this.container, target);
4556         this.container.fireEvent('afterlayout', this.container, this);
4557     },
4558
4559     // private
4560     onLayout : function(ct, target){
4561         this.renderAll(ct, target);
4562     },
4563
4564     // private
4565     isValidParent : function(c, target){
4566                 return target && c.getDomPositionEl().dom.parentNode == (target.dom || target);
4567     },
4568
4569     // private
4570     renderAll : function(ct, target){
4571         var items = ct.items.items;
4572         for(var i = 0, len = items.length; i < len; i++) {
4573             var c = items[i];
4574             if(c && (!c.rendered || !this.isValidParent(c, target))){
4575                 this.renderItem(c, i, target);
4576             }
4577         }
4578     },
4579
4580     // private
4581     renderItem : function(c, position, target){
4582         if(c && !c.rendered){
4583             c.render(target, position);
4584             this.configureItem(c, position);
4585         }else if(c && !this.isValidParent(c, target)){
4586             if(Ext.isNumber(position)){
4587                 position = target.dom.childNodes[position];
4588             }
4589             target.dom.insertBefore(c.getDomPositionEl().dom, position || null);
4590             c.container = target;
4591             this.configureItem(c, position);
4592         }
4593     },
4594     
4595     // private
4596     configureItem: function(c, position){
4597         if(this.extraCls){
4598             var t = c.getPositionEl ? c.getPositionEl() : c;
4599             t.addClass(this.extraCls);
4600         }
4601         if (this.renderHidden && c != this.activeItem) {
4602             c.hide();
4603         }
4604         if(c.doLayout && this.forceLayout){
4605             c.doLayout(false, true);
4606         }
4607     },
4608     
4609     onRemove: function(c){
4610          if(this.activeItem == c){
4611             delete this.activeItem;
4612          }
4613          if(c.rendered && this.extraCls){
4614             var t = c.getPositionEl ? c.getPositionEl() : c;
4615             t.removeClass(this.extraCls);
4616         }
4617     },
4618
4619     // private
4620     onResize: function(){
4621         var ct = this.container,
4622             b;
4623             
4624         if(ct.collapsed){
4625             return;
4626         }
4627         if(b = ct.bufferResize){
4628             // Only allow if we should buffer the layout
4629             if(ct.shouldBufferLayout()){
4630                 if(!this.resizeTask){
4631                     this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
4632                     this.resizeBuffer = Ext.isNumber(b) ? b : 50;
4633                 }
4634                 ct.layoutPending = true;
4635                 this.resizeTask.delay(this.resizeBuffer);
4636             }
4637         }else{
4638             ct.doLayout();
4639         }
4640     },
4641     
4642     // private
4643     runLayout: function(){
4644         var ct = this.container;
4645         ct.doLayout();
4646         delete ct.layoutPending;
4647     },
4648
4649     // private
4650     setContainer : function(ct){
4651         if(this.monitorResize && ct != this.container){
4652             var old = this.container;
4653             if(old){
4654                 old.un(old.resizeEvent, this.onResize, this);
4655             }
4656             if(ct){
4657                 ct.on(ct.resizeEvent, this.onResize, this);
4658             }
4659         }
4660         this.container = ct;
4661     },
4662
4663     // private
4664     parseMargins : function(v){
4665         if(Ext.isNumber(v)){
4666             v = v.toString();
4667         }
4668         var ms = v.split(' ');
4669         var len = ms.length;
4670         if(len == 1){
4671             ms[1] = ms[0];
4672             ms[2] = ms[0];
4673             ms[3] = ms[0];
4674         }
4675         if(len == 2){
4676             ms[2] = ms[0];
4677             ms[3] = ms[1];
4678         }
4679         if(len == 3){
4680             ms[3] = ms[1];
4681         }
4682         return {
4683             top:parseInt(ms[0], 10) || 0,
4684             right:parseInt(ms[1], 10) || 0,
4685             bottom:parseInt(ms[2], 10) || 0,
4686             left:parseInt(ms[3], 10) || 0
4687         };
4688     },
4689
4690     /**
4691      * The {@link Ext.Template Ext.Template} used by Field rendering layout classes (such as
4692      * {@link Ext.layout.FormLayout}) to create the DOM structure of a fully wrapped,
4693      * labeled and styled form Field. A default Template is supplied, but this may be
4694      * overriden to create custom field structures. The template processes values returned from
4695      * {@link Ext.layout.FormLayout#getTemplateArgs}.
4696      * @property fieldTpl
4697      * @type Ext.Template
4698      */
4699     fieldTpl: (function() {
4700         var t = new Ext.Template(
4701             '<div class="x-form-item {itemCls}" tabIndex="-1">',
4702                 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
4703                 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
4704                 '</div><div class="{clearCls}"></div>',
4705             '</div>'
4706         );
4707         t.disableFormats = true;
4708         return t.compile();
4709     })(),
4710         
4711     /*
4712      * Destroys this layout. This is a template method that is empty by default, but should be implemented
4713      * by subclasses that require explicit destruction to purge event handlers or remove DOM nodes.
4714      * @protected
4715      */
4716     destroy : Ext.emptyFn
4717 };
4718 Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout;/**\r
4719  * @class Ext.layout.FitLayout\r
4720  * @extends Ext.layout.ContainerLayout\r
4721  * <p>This is a base class for layouts that contain <b>a single item</b> that automatically expands to fill the layout's\r
4722  * container.  This class is intended to be extended or created via the <tt>layout:'fit'</tt> {@link Ext.Container#layout}\r
4723  * config, and should generally not need to be created directly via the new keyword.</p>\r
4724  * <p>FitLayout does not have any direct config options (other than inherited ones).  To fit a panel to a container\r
4725  * using FitLayout, simply set layout:'fit' on the container and add a single panel to it.  If the container has\r
4726  * multiple panels, only the first one will be displayed.  Example usage:</p>\r
4727  * <pre><code>\r
4728 var p = new Ext.Panel({\r
4729     title: 'Fit Layout',\r
4730     layout:'fit',\r
4731     items: {\r
4732         title: 'Inner Panel',\r
4733         html: '&lt;p&gt;This is the inner panel content&lt;/p&gt;',\r
4734         border: false\r
4735     }\r
4736 });\r
4737 </code></pre>\r
4738  */\r
4739 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
4740     // private\r
4741     monitorResize:true,\r
4742 \r
4743     // private\r
4744     onLayout : function(ct, target){\r
4745         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);\r
4746         if(!this.container.collapsed){\r
4747             var sz = (Ext.isIE6 && Ext.isStrict && target.dom == document.body) ? target.getViewSize() : target.getStyleSize();\r
4748             this.setItemSize(this.activeItem || ct.items.itemAt(0), sz);\r
4749         }\r
4750     },\r
4751 \r
4752     // private\r
4753     setItemSize : function(item, size){\r
4754         if(item && size.height > 0){ // display none?\r
4755             item.setSize(size);\r
4756         }\r
4757     }\r
4758 });\r
4759 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;/**\r
4760  * @class Ext.layout.CardLayout\r
4761  * @extends Ext.layout.FitLayout\r
4762  * <p>This layout manages multiple child Components, each fitted to the Container, where only a single child Component can be\r
4763  * visible at any given time.  This layout style is most commonly used for wizards, tab implementations, etc.\r
4764  * This class is intended to be extended or created via the layout:'card' {@link Ext.Container#layout} config,\r
4765  * and should generally not need to be created directly via the new keyword.</p>\r
4766  * <p>The CardLayout's focal method is {@link #setActiveItem}.  Since only one panel is displayed at a time,\r
4767  * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of\r
4768  * the next panel to display.  The layout itself does not provide a user interface for handling this navigation,\r
4769  * so that functionality must be provided by the developer.</p>\r
4770  * <p>In the following example, a simplistic wizard setup is demonstrated.  A button bar is added\r
4771  * to the footer of the containing panel to provide navigation buttons.  The buttons will be handled by a\r
4772  * common navigation routine -- for this example, the implementation of that routine has been ommitted since\r
4773  * it can be any type of custom logic.  Note that other uses of a CardLayout (like a tab control) would require a\r
4774  * completely different implementation.  For serious implementations, a better approach would be to extend\r
4775  * CardLayout to provide the custom functionality needed.  Example usage:</p>\r
4776  * <pre><code>\r
4777 var navHandler = function(direction){\r
4778     // This routine could contain business logic required to manage the navigation steps.\r
4779     // It would call setActiveItem as needed, manage navigation button state, handle any\r
4780     // branching logic that might be required, handle alternate actions like cancellation\r
4781     // or finalization, etc.  A complete wizard implementation could get pretty\r
4782     // sophisticated depending on the complexity required, and should probably be\r
4783     // done as a subclass of CardLayout in a real-world implementation.\r
4784 };\r
4785 \r
4786 var card = new Ext.Panel({\r
4787     title: 'Example Wizard',\r
4788     layout:'card',\r
4789     activeItem: 0, // make sure the active item is set on the container config!\r
4790     bodyStyle: 'padding:15px',\r
4791     defaults: {\r
4792         // applied to each contained panel\r
4793         border:false\r
4794     },\r
4795     // just an example of one possible navigation scheme, using buttons\r
4796     bbar: [\r
4797         {\r
4798             id: 'move-prev',\r
4799             text: 'Back',\r
4800             handler: navHandler.createDelegate(this, [-1]),\r
4801             disabled: true\r
4802         },\r
4803         '->', // greedy spacer so that the buttons are aligned to each side\r
4804         {\r
4805             id: 'move-next',\r
4806             text: 'Next',\r
4807             handler: navHandler.createDelegate(this, [1])\r
4808         }\r
4809     ],\r
4810     // the panels (or "cards") within the layout\r
4811     items: [{\r
4812         id: 'card-0',\r
4813         html: '&lt;h1&gt;Welcome to the Wizard!&lt;/h1&gt;&lt;p&gt;Step 1 of 3&lt;/p&gt;'\r
4814     },{\r
4815         id: 'card-1',\r
4816         html: '&lt;p&gt;Step 2 of 3&lt;/p&gt;'\r
4817     },{\r
4818         id: 'card-2',\r
4819         html: '&lt;h1&gt;Congratulations!&lt;/h1&gt;&lt;p&gt;Step 3 of 3 - Complete&lt;/p&gt;'\r
4820     }]\r
4821 });\r
4822 </code></pre>\r
4823  */\r
4824 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {\r
4825     /**\r
4826      * @cfg {Boolean} deferredRender\r
4827      * True to render each contained item at the time it becomes active, false to render all contained items\r
4828      * as soon as the layout is rendered (defaults to false).  If there is a significant amount of content or\r
4829      * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to\r
4830      * true might improve performance.\r
4831      */\r
4832     deferredRender : false,\r
4833     \r
4834     /**\r
4835      * @cfg {Boolean} layoutOnCardChange\r
4836      * True to force a layout of the active item when the active card is changed. Defaults to false.\r
4837      */\r
4838     layoutOnCardChange : false,\r
4839 \r
4840     /**\r
4841      * @cfg {Boolean} renderHidden @hide\r
4842      */\r
4843     // private\r
4844     renderHidden : true,\r
4845     \r
4846     constructor: function(config){\r
4847         Ext.layout.CardLayout.superclass.constructor.call(this, config);\r
4848         this.forceLayout = (this.deferredRender === false);\r
4849     },\r
4850 \r
4851     /**\r
4852      * Sets the active (visible) item in the layout.\r
4853      * @param {String/Number} item The string component id or numeric index of the item to activate\r
4854      */\r
4855     setActiveItem : function(item){\r
4856         item = this.container.getComponent(item);\r
4857         if(this.activeItem != item){\r
4858             if(this.activeItem){\r
4859                 this.activeItem.hide();\r
4860             }\r
4861             var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);\r
4862             this.activeItem = item;\r
4863             item.show();\r
4864             this.layout();\r
4865             if(layout){\r
4866                 item.doLayout();\r
4867             }\r
4868         }\r
4869     },\r
4870 \r
4871     // private\r
4872     renderAll : function(ct, target){\r
4873         if(this.deferredRender){\r
4874             this.renderItem(this.activeItem, undefined, target);\r
4875         }else{\r
4876             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);\r
4877         }\r
4878     }\r
4879 });\r
4880 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;/**\r
4881  * @class Ext.layout.AnchorLayout\r
4882  * @extends Ext.layout.ContainerLayout\r
4883  * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.\r
4884  * If the container is resized, all anchored items are automatically rerendered according to their\r
4885  * <b><tt>{@link #anchor}</tt></b> rules.</p>\r
4886  * <p>This class is intended to be extended or created via the layout:'anchor' {@link Ext.Container#layout}\r
4887  * config, and should generally not need to be created directly via the new keyword.</p>\r
4888  * <p>AnchorLayout does not have any direct config options (other than inherited ones). By default,\r
4889  * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the\r
4890  * container using the AnchorLayout can supply an anchoring-specific config property of <b>anchorSize</b>.\r
4891  * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating\r
4892  * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring\r
4893  * logic if necessary.  For example:</p>\r
4894  * <pre><code>\r
4895 var viewport = new Ext.Viewport({\r
4896     layout:'anchor',\r
4897     anchorSize: {width:800, height:600},\r
4898     items:[{\r
4899         title:'Item 1',\r
4900         html:'Content 1',\r
4901         width:800,\r
4902         anchor:'right 20%'\r
4903     },{\r
4904         title:'Item 2',\r
4905         html:'Content 2',\r
4906         width:300,\r
4907         anchor:'50% 30%'\r
4908     },{\r
4909         title:'Item 3',\r
4910         html:'Content 3',\r
4911         width:600,\r
4912         anchor:'-100 50%'\r
4913     }]\r
4914 });\r
4915  * </code></pre>\r
4916  */\r
4917 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
4918     /**\r
4919      * @cfg {String} anchor\r
4920      * <p>This configuation option is to be applied to <b>child <tt>items</tt></b> of a container managed by\r
4921      * this layout (ie. configured with <tt>layout:'anchor'</tt>).</p><br/>\r
4922      * \r
4923      * <p>This value is what tells the layout how an item should be anchored to the container. <tt>items</tt>\r
4924      * added to an AnchorLayout accept an anchoring-specific config property of <b>anchor</b> which is a string\r
4925      * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').\r
4926      * The following types of anchor values are supported:<div class="mdetail-params"><ul>\r
4927      * \r
4928      * <li><b>Percentage</b> : Any value between 1 and 100, expressed as a percentage.<div class="sub-desc">\r
4929      * The first anchor is the percentage width that the item should take up within the container, and the\r
4930      * second is the percentage height.  For example:<pre><code>\r
4931 // two values specified\r
4932 anchor: '100% 50%' // render item complete width of the container and\r
4933                    // 1/2 height of the container\r
4934 // one value specified\r
4935 anchor: '100%'     // the width value; the height will default to auto\r
4936      * </code></pre></div></li>\r
4937      * \r
4938      * <li><b>Offsets</b> : Any positive or negative integer value.<div class="sub-desc">\r
4939      * This is a raw adjustment where the first anchor is the offset from the right edge of the container,\r
4940      * and the second is the offset from the bottom edge. For example:<pre><code>\r
4941 // two values specified\r
4942 anchor: '-50 -100' // render item the complete width of the container\r
4943                    // minus 50 pixels and\r
4944                    // the complete height minus 100 pixels.\r
4945 // one value specified\r
4946 anchor: '-50'      // anchor value is assumed to be the right offset value\r
4947                    // bottom offset will default to 0\r
4948      * </code></pre></div></li>\r
4949      * \r
4950      * <li><b>Sides</b> : Valid values are <tt>'right'</tt> (or <tt>'r'</tt>) and <tt>'bottom'</tt>\r
4951      * (or <tt>'b'</tt>).<div class="sub-desc">\r
4952      * Either the container must have a fixed size or an anchorSize config value defined at render time in\r
4953      * order for these to have any effect.</div></li>\r
4954      *\r
4955      * <li><b>Mixed</b> : <div class="sub-desc">\r
4956      * Anchor values can also be mixed as needed.  For example, to render the width offset from the container\r
4957      * right edge by 50 pixels and 75% of the container's height use:\r
4958      * <pre><code>\r
4959 anchor: '-50 75%' \r
4960      * </code></pre></div></li>\r
4961      * \r
4962      * \r
4963      * </ul></div>\r
4964      */\r
4965     \r
4966     // private\r
4967     monitorResize:true,\r
4968 \r
4969     // private\r
4970     getAnchorViewSize : function(ct, target){\r
4971         return target.dom == document.body ?\r
4972                    target.getViewSize() : target.getStyleSize();\r
4973     },\r
4974 \r
4975     // private\r
4976     onLayout : function(ct, target){\r
4977         Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);\r
4978 \r
4979         var size = this.getAnchorViewSize(ct, target);\r
4980 \r
4981         var w = size.width, h = size.height;\r
4982 \r
4983         if(w < 20 && h < 20){\r
4984             return;\r
4985         }\r
4986 \r
4987         // find the container anchoring size\r
4988         var aw, ah;\r
4989         if(ct.anchorSize){\r
4990             if(typeof ct.anchorSize == 'number'){\r
4991                 aw = ct.anchorSize;\r
4992             }else{\r
4993                 aw = ct.anchorSize.width;\r
4994                 ah = ct.anchorSize.height;\r
4995             }\r
4996         }else{\r
4997             aw = ct.initialConfig.width;\r
4998             ah = ct.initialConfig.height;\r
4999         }\r
5000 \r
5001         var cs = ct.items.items, len = cs.length, i, c, a, cw, ch;\r
5002         for(i = 0; i < len; i++){\r
5003             c = cs[i];\r
5004             if(c.anchor){\r
5005                 a = c.anchorSpec;\r
5006                 if(!a){ // cache all anchor values\r
5007                     var vs = c.anchor.split(' ');\r
5008                     c.anchorSpec = a = {\r
5009                         right: this.parseAnchor(vs[0], c.initialConfig.width, aw),\r
5010                         bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)\r
5011                     };\r
5012                 }\r
5013                 cw = a.right ? this.adjustWidthAnchor(a.right(w), c) : undefined;\r
5014                 ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h), c) : undefined;\r
5015 \r
5016                 if(cw || ch){\r
5017                     c.setSize(cw || undefined, ch || undefined);\r
5018                 }\r
5019             }\r
5020         }\r
5021     },\r
5022 \r
5023     // private\r
5024     parseAnchor : function(a, start, cstart){\r
5025         if(a && a != 'none'){\r
5026             var last;\r
5027             if(/^(r|right|b|bottom)$/i.test(a)){   // standard anchor\r
5028                 var diff = cstart - start;\r
5029                 return function(v){\r
5030                     if(v !== last){\r
5031                         last = v;\r
5032                         return v - diff;\r
5033                     }\r
5034                 }\r
5035             }else if(a.indexOf('%') != -1){\r
5036                 var ratio = parseFloat(a.replace('%', ''))*.01;   // percentage\r
5037                 return function(v){\r
5038                     if(v !== last){\r
5039                         last = v;\r
5040                         return Math.floor(v*ratio);\r
5041                     }\r
5042                 }\r
5043             }else{\r
5044                 a = parseInt(a, 10);\r
5045                 if(!isNaN(a)){                            // simple offset adjustment\r
5046                     return function(v){\r
5047                         if(v !== last){\r
5048                             last = v;\r
5049                             return v + a;\r
5050                         }\r
5051                     }\r
5052                 }\r
5053             }\r
5054         }\r
5055         return false;\r
5056     },\r
5057 \r
5058     // private\r
5059     adjustWidthAnchor : function(value, comp){\r
5060         return value;\r
5061     },\r
5062 \r
5063     // private\r
5064     adjustHeightAnchor : function(value, comp){\r
5065         return value;\r
5066     }\r
5067     \r
5068     /**\r
5069      * @property activeItem\r
5070      * @hide\r
5071      */\r
5072 });\r
5073 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;/**\r
5074  * @class Ext.layout.ColumnLayout\r
5075  * @extends Ext.layout.ContainerLayout\r
5076  * <p>This is the layout style of choice for creating structural layouts in a multi-column format where the width of\r
5077  * each column can be specified as a percentage or fixed width, but the height is allowed to vary based on the content.\r
5078  * This class is intended to be extended or created via the layout:'column' {@link Ext.Container#layout} config,\r
5079  * and should generally not need to be created directly via the new keyword.</p>\r
5080  * <p>ColumnLayout does not have any direct config options (other than inherited ones), but it does support a\r
5081  * specific config property of <b><tt>columnWidth</tt></b> that can be included in the config of any panel added to it.  The\r
5082  * layout will use the columnWidth (if present) or width of each panel during layout to determine how to size each panel.\r
5083  * If width or columnWidth is not specified for a given panel, its width will default to the panel's width (or auto).</p>\r
5084  * <p>The width property is always evaluated as pixels, and must be a number greater than or equal to 1.\r
5085  * The columnWidth property is always evaluated as a percentage, and must be a decimal value greater than 0 and\r
5086  * less than 1 (e.g., .25).</p>\r
5087  * <p>The basic rules for specifying column widths are pretty simple.  The logic makes two passes through the\r
5088  * set of contained panels.  During the first layout pass, all panels that either have a fixed width or none\r
5089  * specified (auto) are skipped, but their widths are subtracted from the overall container width.  During the second\r
5090  * pass, all panels with columnWidths are assigned pixel widths in proportion to their percentages based on\r
5091  * the total <b>remaining</b> container width.  In other words, percentage width panels are designed to fill the space\r
5092  * left over by all the fixed-width and/or auto-width panels.  Because of this, while you can specify any number of columns\r
5093  * with different percentages, the columnWidths must always add up to 1 (or 100%) when added together, otherwise your\r
5094  * layout may not render as expected.  Example usage:</p>\r
5095  * <pre><code>\r
5096 // All columns are percentages -- they must add up to 1\r
5097 var p = new Ext.Panel({\r
5098     title: 'Column Layout - Percentage Only',\r
5099     layout:'column',\r
5100     items: [{\r
5101         title: 'Column 1',\r
5102         columnWidth: .25 \r
5103     },{\r
5104         title: 'Column 2',\r
5105         columnWidth: .6\r
5106     },{\r
5107         title: 'Column 3',\r
5108         columnWidth: .15\r
5109     }]\r
5110 });\r
5111 \r
5112 // Mix of width and columnWidth -- all columnWidth values must add up\r
5113 // to 1. The first column will take up exactly 120px, and the last two\r
5114 // columns will fill the remaining container width.\r
5115 var p = new Ext.Panel({\r
5116     title: 'Column Layout - Mixed',\r
5117     layout:'column',\r
5118     items: [{\r
5119         title: 'Column 1',\r
5120         width: 120\r
5121     },{\r
5122         title: 'Column 2',\r
5123         columnWidth: .8\r
5124     },{\r
5125         title: 'Column 3',\r
5126         columnWidth: .2\r
5127     }]\r
5128 });\r
5129 </code></pre>\r
5130  */\r
5131 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
5132     // private\r
5133     monitorResize:true,\r
5134     \r
5135     extraCls: 'x-column',\r
5136 \r
5137     scrollOffset : 0,\r
5138 \r
5139     // private\r
5140     isValidParent : function(c, target){\r
5141         return (c.getPositionEl ? c.getPositionEl() : c.getEl()).dom.parentNode == this.innerCt.dom;\r
5142     },\r
5143 \r
5144     // private\r
5145     onLayout : function(ct, target){\r
5146         var cs = ct.items.items, len = cs.length, c, i;\r
5147 \r
5148         if(!this.innerCt){\r
5149             target.addClass('x-column-layout-ct');\r
5150 \r
5151             // the innerCt prevents wrapping and shuffling while\r
5152             // the container is resizing\r
5153             this.innerCt = target.createChild({cls:'x-column-inner'});\r
5154             this.innerCt.createChild({cls:'x-clear'});\r
5155         }\r
5156         this.renderAll(ct, this.innerCt);\r
5157 \r
5158         var size = Ext.isIE && target.dom != Ext.getBody().dom ? target.getStyleSize() : target.getViewSize();\r
5159 \r
5160         if(size.width < 1 && size.height < 1){ // display none?\r
5161             return;\r
5162         }\r
5163 \r
5164         var w = size.width - target.getPadding('lr') - this.scrollOffset,\r
5165             h = size.height - target.getPadding('tb'),\r
5166             pw = w;\r
5167 \r
5168         this.innerCt.setWidth(w);\r
5169         \r
5170         // some columns can be percentages while others are fixed\r
5171         // so we need to make 2 passes\r
5172 \r
5173         for(i = 0; i < len; i++){\r
5174             c = cs[i];\r
5175             if(!c.columnWidth){\r
5176                 pw -= (c.getSize().width + c.getEl().getMargins('lr'));\r
5177             }\r
5178         }\r
5179 \r
5180         pw = pw < 0 ? 0 : pw;\r
5181 \r
5182         for(i = 0; i < len; i++){\r
5183             c = cs[i];\r
5184             if(c.columnWidth){\r
5185                 c.setSize(Math.floor(c.columnWidth*pw) - c.getEl().getMargins('lr'));\r
5186             }\r
5187         }\r
5188     }\r
5189     \r
5190     /**\r
5191      * @property activeItem\r
5192      * @hide\r
5193      */\r
5194 });\r
5195 \r
5196 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;/**
5197  * @class Ext.layout.BorderLayout
5198  * @extends Ext.layout.ContainerLayout
5199  * <p>This is a multi-pane, application-oriented UI layout style that supports multiple
5200  * nested panels, automatic {@link Ext.layout.BorderLayout.Region#split split} bars between
5201  * {@link Ext.layout.BorderLayout.Region#BorderLayout.Region regions} and built-in
5202  * {@link Ext.layout.BorderLayout.Region#collapsible expanding and collapsing} of regions.</p>
5203  * <p>This class is intended to be extended or created via the <tt>layout:'border'</tt>
5204  * {@link Ext.Container#layout} config, and should generally not need to be created directly
5205  * via the new keyword.</p>
5206  * <p>BorderLayout does not have any direct config options (other than inherited ones).
5207  * All configuration options available for customizing the BorderLayout are at the
5208  * {@link Ext.layout.BorderLayout.Region} and {@link Ext.layout.BorderLayout.SplitRegion}
5209  * levels.</p>
5210  * <p>Example usage:</p>
5211  * <pre><code>
5212 var myBorderPanel = new Ext.Panel({
5213     {@link Ext.Component#renderTo renderTo}: document.body,
5214     {@link Ext.BoxComponent#width width}: 700,
5215     {@link Ext.BoxComponent#height height}: 500,
5216     {@link Ext.Panel#title title}: 'Border Layout',
5217     {@link Ext.Container#layout layout}: 'border',
5218     {@link Ext.Container#items items}: [{
5219         {@link Ext.Panel#title title}: 'South Region is resizable',
5220         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south',     // position for region
5221         {@link Ext.BoxComponent#height height}: 100,
5222         {@link Ext.layout.BorderLayout.Region#split split}: true,         // enable resizing
5223         {@link Ext.SplitBar#minSize minSize}: 75,         // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50} 
5224         {@link Ext.SplitBar#maxSize maxSize}: 150,
5225         {@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5'
5226     },{
5227         // xtype: 'panel' implied by default
5228         {@link Ext.Panel#title title}: 'West Region is collapsible',
5229         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}:'west',
5230         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 0 0 5',
5231         {@link Ext.BoxComponent#width width}: 200,
5232         {@link Ext.layout.BorderLayout.Region#collapsible collapsible}: true,   // make collapsible
5233         {@link Ext.layout.BorderLayout.Region#cmargins cmargins}: '5 5 0 5', // adjust top margin when collapsed
5234         {@link Ext.Component#id id}: 'west-region-container',
5235         {@link Ext.Container#layout layout}: 'fit',
5236         {@link Ext.Panel#unstyled unstyled}: true
5237     },{
5238         {@link Ext.Panel#title title}: 'Center Region',
5239         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'center',     // center region is required, no width/height specified
5240         {@link Ext.Component#xtype xtype}: 'container',
5241         {@link Ext.Container#layout layout}: 'fit',
5242         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 5 0 0'
5243     }]
5244 });
5245 </code></pre>
5246  * <p><b><u>Notes</u></b>:</p><div class="mdetail-params"><ul>
5247  * <li>Any container using the BorderLayout <b>must</b> have a child item with <tt>region:'center'</tt>.
5248  * The child item in the center region will always be resized to fill the remaining space not used by
5249  * the other regions in the layout.</li>
5250  * <li>Any child items with a region of <tt>west</tt> or <tt>east</tt> must have <tt>width</tt> defined
5251  * (an integer representing the number of pixels that the region should take up).</li>
5252  * <li>Any child items with a region of <tt>north</tt> or <tt>south</tt> must have <tt>height</tt> defined.</li>
5253  * <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
5254  * Components within a BorderLayout, have them wrapped by an additional Container which is directly
5255  * managed by the BorderLayout.  If the region is to be collapsible, the Container used directly
5256  * by the BorderLayout manager should be a Panel.  In the following example a Container (an Ext.Panel)
5257  * is added to the west region:
5258  * <div style="margin-left:16px"><pre><code>
5259 wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container');
5260 wrc.{@link Ext.Panel#removeAll removeAll}();
5261 wrc.{@link Ext.Container#add add}({
5262     title: 'Added Panel',
5263     html: 'Some content'
5264 });
5265 wrc.{@link Ext.Container#doLayout doLayout}();
5266  * </code></pre></div>
5267  * </li>
5268  * <li> To reference a {@link Ext.layout.BorderLayout.Region Region}:
5269  * <div style="margin-left:16px"><pre><code>
5270 wr = myBorderPanel.layout.west;
5271  * </code></pre></div>
5272  * </li>
5273  * </ul></div>
5274  */
5275 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
5276     // private
5277     monitorResize:true,
5278     // private
5279     rendered : false,
5280
5281     // private
5282     onLayout : function(ct, target){
5283         var collapsed;
5284         if(!this.rendered){
5285             target.addClass('x-border-layout-ct');
5286             var items = ct.items.items;
5287             collapsed = [];
5288             for(var i = 0, len = items.length; i < len; i++) {
5289                 var c = items[i];
5290                 var pos = c.region;
5291                 if(c.collapsed){
5292                     collapsed.push(c);
5293                 }
5294                 c.collapsed = false;
5295                 if(!c.rendered){
5296                     c.render(target, i);
5297                     c.getDomPositionEl().addClass('x-border-panel');
5298                 }
5299                 this[pos] = pos != 'center' && c.split ?
5300                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
5301                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
5302                 this[pos].render(target, c);
5303             }
5304             this.rendered = true;
5305         }
5306
5307         var size = target.getViewSize();
5308         if(size.width < 20 || size.height < 20){ // display none?
5309             if(collapsed){
5310                 this.restoreCollapsed = collapsed;
5311             }
5312             return;
5313         }else if(this.restoreCollapsed){
5314             collapsed = this.restoreCollapsed;
5315             delete this.restoreCollapsed;
5316         }
5317
5318         var w = size.width, h = size.height;
5319         var centerW = w, centerH = h, centerY = 0, centerX = 0;
5320
5321         var n = this.north, s = this.south, west = this.west, e = this.east, c = this.center;
5322         if(!c && Ext.layout.BorderLayout.WARN !== false){
5323             throw 'No center region defined in BorderLayout ' + ct.id;
5324         }
5325
5326         if(n && n.isVisible()){
5327             var b = n.getSize();
5328             var m = n.getMargins();
5329             b.width = w - (m.left+m.right);
5330             b.x = m.left;
5331             b.y = m.top;
5332             centerY = b.height + b.y + m.bottom;
5333             centerH -= centerY;
5334             n.applyLayout(b);
5335         }
5336         if(s && s.isVisible()){
5337             var b = s.getSize();
5338             var m = s.getMargins();
5339             b.width = w - (m.left+m.right);
5340             b.x = m.left;
5341             var totalHeight = (b.height + m.top + m.bottom);
5342             b.y = h - totalHeight + m.top;
5343             centerH -= totalHeight;
5344             s.applyLayout(b);
5345         }
5346         if(west && west.isVisible()){
5347             var b = west.getSize();
5348             var m = west.getMargins();
5349             b.height = centerH - (m.top+m.bottom);
5350             b.x = m.left;
5351             b.y = centerY + m.top;
5352             var totalWidth = (b.width + m.left + m.right);
5353             centerX += totalWidth;
5354             centerW -= totalWidth;
5355             west.applyLayout(b);
5356         }
5357         if(e && e.isVisible()){
5358             var b = e.getSize();
5359             var m = e.getMargins();
5360             b.height = centerH - (m.top+m.bottom);
5361             var totalWidth = (b.width + m.left + m.right);
5362             b.x = w - totalWidth + m.left;
5363             b.y = centerY + m.top;
5364             centerW -= totalWidth;
5365             e.applyLayout(b);
5366         }
5367         if(c){
5368             var m = c.getMargins();
5369             var centerBox = {
5370                 x: centerX + m.left,
5371                 y: centerY + m.top,
5372                 width: centerW - (m.left+m.right),
5373                 height: centerH - (m.top+m.bottom)
5374             };
5375             c.applyLayout(centerBox);
5376         }
5377         if(collapsed){
5378             for(var i = 0, len = collapsed.length; i < len; i++){
5379                 collapsed[i].collapse(false);
5380             }
5381         }
5382         if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue
5383             target.repaint();
5384         }
5385     },
5386
5387     destroy: function() {
5388         var r = ['north', 'south', 'east', 'west'];
5389         for (var i = 0; i < r.length; i++) {
5390             var region = this[r[i]];
5391             if(region){
5392                 if(region.destroy){
5393                     region.destroy();
5394                 }else if (region.split){
5395                     region.split.destroy(true);
5396                 }
5397             }
5398         }
5399         Ext.layout.BorderLayout.superclass.destroy.call(this);
5400     }
5401
5402     /**
5403      * @property activeItem
5404      * @hide
5405      */
5406 });
5407
5408 /**
5409  * @class Ext.layout.BorderLayout.Region
5410  * <p>This is a region of a {@link Ext.layout.BorderLayout BorderLayout} that acts as a subcontainer
5411  * within the layout.  Each region has its own {@link Ext.layout.ContainerLayout layout} that is
5412  * independent of other regions and the containing BorderLayout, and can be any of the
5413  * {@link Ext.layout.ContainerLayout valid Ext layout types}.</p>
5414  * <p>Region size is managed automatically and cannot be changed by the user -- for
5415  * {@link #split resizable regions}, see {@link Ext.layout.BorderLayout.SplitRegion}.</p>
5416  * @constructor
5417  * Create a new Region.
5418  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
5419  * @param {Object} config The configuration options
5420  * @param {String} position The region position.  Valid values are: <tt>north</tt>, <tt>south</tt>,
5421  * <tt>east</tt>, <tt>west</tt> and <tt>center</tt>.  Every {@link Ext.layout.BorderLayout BorderLayout}
5422  * <b>must have a center region</b> for the primary content -- all other regions are optional.
5423  */
5424 Ext.layout.BorderLayout.Region = function(layout, config, pos){
5425     Ext.apply(this, config);
5426     this.layout = layout;
5427     this.position = pos;
5428     this.state = {};
5429     if(typeof this.margins == 'string'){
5430         this.margins = this.layout.parseMargins(this.margins);
5431     }
5432     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
5433     if(this.collapsible){
5434         if(typeof this.cmargins == 'string'){
5435             this.cmargins = this.layout.parseMargins(this.cmargins);
5436         }
5437         if(this.collapseMode == 'mini' && !this.cmargins){
5438             this.cmargins = {left:0,top:0,right:0,bottom:0};
5439         }else{
5440             this.cmargins = Ext.applyIf(this.cmargins || {},
5441                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
5442         }
5443     }
5444 };
5445
5446 Ext.layout.BorderLayout.Region.prototype = {
5447     /**
5448      * @cfg {Boolean} animFloat
5449      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
5450      * panel that will close again once the user mouses out of that panel (or clicks out if
5451      * <tt>{@link #autoHide} = false</tt>).  Setting <tt>{@link #animFloat} = false</tt> will
5452      * prevent the open and close of these floated panels from being animated (defaults to <tt>true</tt>).
5453      */
5454     /**
5455      * @cfg {Boolean} autoHide
5456      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
5457      * panel.  If <tt>autoHide = true</tt>, the panel will automatically hide after the user mouses
5458      * out of the panel.  If <tt>autoHide = false</tt>, the panel will continue to display until the
5459      * user clicks outside of the panel (defaults to <tt>true</tt>).
5460      */
5461     /**
5462      * @cfg {String} collapseMode
5463      * <tt>collapseMode</tt> supports two configuration values:<div class="mdetail-params"><ul>
5464      * <li><b><tt>undefined</tt></b> (default)<div class="sub-desc">By default, {@link #collapsible}
5465      * regions are collapsed by clicking the expand/collapse tool button that renders into the region's
5466      * title bar.</div></li>
5467      * <li><b><tt>'mini'</tt></b><div class="sub-desc">Optionally, when <tt>collapseMode</tt> is set to
5468      * <tt>'mini'</tt> the region's split bar will also display a small collapse button in the center of
5469      * the bar. In <tt>'mini'</tt> mode the region will collapse to a thinner bar than in normal mode.
5470      * </div></li>
5471      * </ul></div></p>
5472      * <p><b>Note</b>: if a collapsible region does not have a title bar, then set <tt>collapseMode =
5473      * 'mini'</tt> and <tt>{@link #split} = true</tt> in order for the region to be {@link #collapsible}
5474      * by the user as the expand/collapse tool button (that would go in the title bar) will not be rendered.</p>
5475      * <p>See also <tt>{@link #cmargins}</tt>.</p>
5476      */
5477     /**
5478      * @cfg {Object} margins
5479      * An object containing margins to apply to the region when in the expanded state in the
5480      * format:<pre><code>
5481 {
5482     top: (top margin),
5483     right: (right margin),
5484     bottom: (bottom margin),
5485     left: (left margin)
5486 }</code></pre>
5487      * <p>May also be a string containing space-separated, numeric margin values. The order of the
5488      * sides associated with each value matches the way CSS processes margin values:</p>
5489      * <p><div class="mdetail-params"><ul>
5490      * <li>If there is only one value, it applies to all sides.</li>
5491      * <li>If there are two values, the top and bottom borders are set to the first value and the
5492      * right and left are set to the second.</li>
5493      * <li>If there are three values, the top is set to the first value, the left and right are set
5494      * to the second, and the bottom is set to the third.</li>
5495      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
5496      * </ul></div></p>
5497      * <p>Defaults to:</p><pre><code>
5498      * {top:0, right:0, bottom:0, left:0}
5499      * </code></pre>
5500      */
5501     /**
5502      * @cfg {Object} cmargins
5503      * An object containing margins to apply to the region when in the collapsed state in the
5504      * format:<pre><code>
5505 {
5506     top: (top margin),
5507     right: (right margin),
5508     bottom: (bottom margin),
5509     left: (left margin)
5510 }</code></pre>
5511      * <p>May also be a string containing space-separated, numeric margin values. The order of the
5512      * sides associated with each value matches the way CSS processes margin values.</p>
5513      * <p><ul>
5514      * <li>If there is only one value, it applies to all sides.</li>
5515      * <li>If there are two values, the top and bottom borders are set to the first value and the
5516      * right and left are set to the second.</li>
5517      * <li>If there are three values, the top is set to the first value, the left and right are set
5518      * to the second, and the bottom is set to the third.</li>
5519      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
5520      * </ul></p>
5521      */
5522     /**
5523      * @cfg {Boolean} collapsible
5524      * <p><tt>true</tt> to allow the user to collapse this region (defaults to <tt>false</tt>).  If
5525      * <tt>true</tt>, an expand/collapse tool button will automatically be rendered into the title
5526      * bar of the region, otherwise the button will not be shown.</p>
5527      * <p><b>Note</b>: that a title bar is required to display the collapse/expand toggle button -- if
5528      * no <tt>title</tt> is specified for the region's panel, the region will only be collapsible if
5529      * <tt>{@link #collapseMode} = 'mini'</tt> and <tt>{@link #split} = true</tt>.
5530      */
5531     collapsible : false,
5532     /**
5533      * @cfg {Boolean} split
5534      * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and 
5535      * display a 5px wide {@link Ext.SplitBar} between this region and its neighbor, allowing the user to
5536      * resize the regions dynamically.  Defaults to <tt>false</tt> creating a
5537      * {@link Ext.layout.BorderLayout.Region Region}.</p><br>
5538      * <p><b>Notes</b>:</p><div class="mdetail-params"><ul>
5539      * <li>this configuration option is ignored if <tt>region='center'</tt></li> 
5540      * <li>when <tt>split == true</tt>, it is common to specify a
5541      * <tt>{@link Ext.SplitBar#minSize minSize}</tt> and <tt>{@link Ext.SplitBar#maxSize maxSize}</tt>
5542      * for the {@link Ext.BoxComponent BoxComponent} representing the region. These are not native
5543      * configs of {@link Ext.BoxComponent BoxComponent}, and are used only by this class.</li>
5544      * <li>if <tt>{@link #collapseMode} = 'mini'</tt> requires <tt>split = true</tt> to reserve space
5545      * for the collapse tool</tt></li> 
5546      * </ul></div> 
5547      */
5548     split:false,
5549     /**
5550      * @cfg {Boolean} floatable
5551      * <tt>true</tt> to allow clicking a collapsed region's bar to display the region's panel floated
5552      * above the layout, <tt>false</tt> to force the user to fully expand a collapsed region by
5553      * clicking the expand button to see it again (defaults to <tt>true</tt>).
5554      */
5555     floatable: true,
5556     /**
5557      * @cfg {Number} minWidth
5558      * <p>The minimum allowable width in pixels for this region (defaults to <tt>50</tt>).
5559      * <tt>maxWidth</tt> may also be specified.</p><br>
5560      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> / 
5561      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified 
5562      * <tt>minWidth</tt> / <tt>maxWidth</tt>.</p>
5563      */
5564     minWidth:50,
5565     /**
5566      * @cfg {Number} minHeight
5567      * The minimum allowable height in pixels for this region (defaults to <tt>50</tt>)
5568      * <tt>maxHeight</tt> may also be specified.</p><br>
5569      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> / 
5570      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified 
5571      * <tt>minHeight</tt> / <tt>maxHeight</tt>.</p>
5572      */
5573     minHeight:50,
5574
5575     // private
5576     defaultMargins : {left:0,top:0,right:0,bottom:0},
5577     // private
5578     defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
5579     // private
5580     defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
5581     floatingZIndex: 100,
5582
5583     /**
5584      * True if this region is collapsed. Read-only.
5585      * @type Boolean
5586      * @property
5587      */
5588     isCollapsed : false,
5589
5590     /**
5591      * This region's panel.  Read-only.
5592      * @type Ext.Panel
5593      * @property panel
5594      */
5595     /**
5596      * This region's layout.  Read-only.
5597      * @type Layout
5598      * @property layout
5599      */
5600     /**
5601      * This region's layout position (north, south, east, west or center).  Read-only.
5602      * @type String
5603      * @property position
5604      */
5605
5606     // private
5607     render : function(ct, p){
5608         this.panel = p;
5609         p.el.enableDisplayMode();
5610         this.targetEl = ct;
5611         this.el = p.el;
5612
5613         var gs = p.getState, ps = this.position;
5614         p.getState = function(){
5615             return Ext.apply(gs.call(p) || {}, this.state);
5616         }.createDelegate(this);
5617
5618         if(ps != 'center'){
5619             p.allowQueuedExpand = false;
5620             p.on({
5621                 beforecollapse: this.beforeCollapse,
5622                 collapse: this.onCollapse,
5623                 beforeexpand: this.beforeExpand,
5624                 expand: this.onExpand,
5625                 hide: this.onHide,
5626                 show: this.onShow,
5627                 scope: this
5628             });
5629             if(this.collapsible || this.floatable){
5630                 p.collapseEl = 'el';
5631                 p.slideAnchor = this.getSlideAnchor();
5632             }
5633             if(p.tools && p.tools.toggle){
5634                 p.tools.toggle.addClass('x-tool-collapse-'+ps);
5635                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
5636             }
5637         }
5638     },
5639
5640     // private
5641     getCollapsedEl : function(){
5642         if(!this.collapsedEl){
5643             if(!this.toolTemplate){
5644                 var tt = new Ext.Template(
5645                      '<div class="x-tool x-tool-{id}">&#160;</div>'
5646                 );
5647                 tt.disableFormats = true;
5648                 tt.compile();
5649                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
5650             }
5651             this.collapsedEl = this.targetEl.createChild({
5652                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
5653                 id: this.panel.id + '-xcollapsed'
5654             });
5655             this.collapsedEl.enableDisplayMode('block');
5656
5657             if(this.collapseMode == 'mini'){
5658                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
5659                 this.miniCollapsedEl = this.collapsedEl.createChild({
5660                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
5661                 });
5662                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
5663                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
5664                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
5665             }else {
5666                 if(this.collapsible !== false && !this.hideCollapseTool) {
5667                     var t = this.toolTemplate.append(
5668                             this.collapsedEl.dom,
5669                             {id:'expand-'+this.position}, true);
5670                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
5671                     t.on('click', this.onExpandClick, this, {stopEvent:true});
5672                 }
5673                 if(this.floatable !== false || this.titleCollapse){
5674                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
5675                    this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
5676                 }
5677             }
5678         }
5679         return this.collapsedEl;
5680     },
5681
5682     // private
5683     onExpandClick : function(e){
5684         if(this.isSlid){
5685             this.afterSlideIn();
5686             this.panel.expand(false);
5687         }else{
5688             this.panel.expand();
5689         }
5690     },
5691
5692     // private
5693     onCollapseClick : function(e){
5694         this.panel.collapse();
5695     },
5696
5697     // private
5698     beforeCollapse : function(p, animate){
5699         this.lastAnim = animate;
5700         if(this.splitEl){
5701             this.splitEl.hide();
5702         }
5703         this.getCollapsedEl().show();
5704         this.panel.el.setStyle('z-index', 100);
5705         this.isCollapsed = true;
5706         this.layout.layout();
5707     },
5708
5709     // private
5710     onCollapse : function(animate){
5711         this.panel.el.setStyle('z-index', 1);
5712         if(this.lastAnim === false || this.panel.animCollapse === false){
5713             this.getCollapsedEl().dom.style.visibility = 'visible';
5714         }else{
5715             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
5716         }
5717         this.state.collapsed = true;
5718         this.panel.saveState();
5719     },
5720
5721     // private
5722     beforeExpand : function(animate){
5723         var c = this.getCollapsedEl();
5724         this.el.show();
5725         if(this.position == 'east' || this.position == 'west'){
5726             this.panel.setSize(undefined, c.getHeight());
5727         }else{
5728             this.panel.setSize(c.getWidth(), undefined);
5729         }
5730         c.hide();
5731         c.dom.style.visibility = 'hidden';
5732         this.panel.el.setStyle('z-index', this.floatingZIndex);
5733     },
5734
5735     // private
5736     onExpand : function(){
5737         this.isCollapsed = false;
5738         if(this.splitEl){
5739             this.splitEl.show();
5740         }
5741         this.layout.layout();
5742         this.panel.el.setStyle('z-index', 1);
5743         this.state.collapsed = false;
5744         this.panel.saveState();
5745     },
5746
5747     // private
5748     collapseClick : function(e){
5749         if(this.isSlid){
5750            e.stopPropagation();
5751            this.slideIn();
5752         }else{
5753            e.stopPropagation();
5754            this.slideOut();
5755         }
5756     },
5757
5758     // private
5759     onHide : function(){
5760         if(this.isCollapsed){
5761             this.getCollapsedEl().hide();
5762         }else if(this.splitEl){
5763             this.splitEl.hide();
5764         }
5765     },
5766
5767     // private
5768     onShow : function(){
5769         if(this.isCollapsed){
5770             this.getCollapsedEl().show();
5771         }else if(this.splitEl){
5772             this.splitEl.show();
5773         }
5774     },
5775
5776     /**
5777      * True if this region is currently visible, else false.
5778      * @return {Boolean}
5779      */
5780     isVisible : function(){
5781         return !this.panel.hidden;
5782     },
5783
5784     /**
5785      * Returns the current margins for this region.  If the region is collapsed, the
5786      * {@link #cmargins} (collapsed margins) value will be returned, otherwise the
5787      * {@link #margins} value will be returned.
5788      * @return {Object} An object containing the element's margins: <tt>{left: (left
5789      * margin), top: (top margin), right: (right margin), bottom: (bottom margin)}</tt>
5790      */
5791     getMargins : function(){
5792         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
5793     },
5794
5795     /**
5796      * Returns the current size of this region.  If the region is collapsed, the size of the
5797      * collapsedEl will be returned, otherwise the size of the region's panel will be returned.
5798      * @return {Object} An object containing the element's size: <tt>{width: (element width),
5799      * height: (element height)}</tt>
5800      */
5801     getSize : function(){
5802         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
5803     },
5804
5805     /**
5806      * Sets the specified panel as the container element for this region.
5807      * @param {Ext.Panel} panel The new panel
5808      */
5809     setPanel : function(panel){
5810         this.panel = panel;
5811     },
5812
5813     /**
5814      * Returns the minimum allowable width for this region.
5815      * @return {Number} The minimum width
5816      */
5817     getMinWidth: function(){
5818         return this.minWidth;
5819     },
5820
5821     /**
5822      * Returns the minimum allowable height for this region.
5823      * @return {Number} The minimum height
5824      */
5825     getMinHeight: function(){
5826         return this.minHeight;
5827     },
5828
5829     // private
5830     applyLayoutCollapsed : function(box){
5831         var ce = this.getCollapsedEl();
5832         ce.setLeftTop(box.x, box.y);
5833         ce.setSize(box.width, box.height);
5834     },
5835
5836     // private
5837     applyLayout : function(box){
5838         if(this.isCollapsed){
5839             this.applyLayoutCollapsed(box);
5840         }else{
5841             this.panel.setPosition(box.x, box.y);
5842             this.panel.setSize(box.width, box.height);
5843         }
5844     },
5845
5846     // private
5847     beforeSlide: function(){
5848         this.panel.beforeEffect();
5849     },
5850
5851     // private
5852     afterSlide : function(){
5853         this.panel.afterEffect();
5854     },
5855
5856     // private
5857     initAutoHide : function(){
5858         if(this.autoHide !== false){
5859             if(!this.autoHideHd){
5860                 var st = new Ext.util.DelayedTask(this.slideIn, this);
5861                 this.autoHideHd = {
5862                     "mouseout": function(e){
5863                         if(!e.within(this.el, true)){
5864                             st.delay(500);
5865                         }
5866                     },
5867                     "mouseover" : function(e){
5868                         st.cancel();
5869                     },
5870                     scope : this
5871                 };
5872             }
5873             this.el.on(this.autoHideHd);
5874         }
5875     },
5876
5877     // private
5878     clearAutoHide : function(){
5879         if(this.autoHide !== false){
5880             this.el.un("mouseout", this.autoHideHd.mouseout);
5881             this.el.un("mouseover", this.autoHideHd.mouseover);
5882         }
5883     },
5884
5885     // private
5886     clearMonitor : function(){
5887         Ext.getDoc().un("click", this.slideInIf, this);
5888     },
5889
5890     /**
5891      * If this Region is {@link #floatable}, this method slides this Region into full visibility <i>over the top
5892      * of the center Region</i> where it floats until either {@link #slideIn} is called, or other regions of the layout
5893      * are clicked, or the mouse exits the Region.
5894      */
5895     slideOut : function(){
5896         if(this.isSlid || this.el.hasActiveFx()){
5897             return;
5898         }
5899         this.isSlid = true;
5900         var ts = this.panel.tools;
5901         if(ts && ts.toggle){
5902             ts.toggle.hide();
5903         }
5904         this.el.show();
5905         if(this.position == 'east' || this.position == 'west'){
5906             this.panel.setSize(undefined, this.collapsedEl.getHeight());
5907         }else{
5908             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
5909         }
5910         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
5911         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
5912         this.el.setStyle("z-index", this.floatingZIndex+2);
5913         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
5914         if(this.animFloat !== false){
5915             this.beforeSlide();
5916             this.el.slideIn(this.getSlideAnchor(), {
5917                 callback: function(){
5918                     this.afterSlide();
5919                     this.initAutoHide();
5920                     Ext.getDoc().on("click", this.slideInIf, this);
5921                 },
5922                 scope: this,
5923                 block: true
5924             });
5925         }else{
5926             this.initAutoHide();
5927              Ext.getDoc().on("click", this.slideInIf, this);
5928         }
5929     },
5930
5931     // private
5932     afterSlideIn : function(){
5933         this.clearAutoHide();
5934         this.isSlid = false;
5935         this.clearMonitor();
5936         this.el.setStyle("z-index", "");
5937         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
5938         this.el.dom.style.left = this.restoreLT[0];
5939         this.el.dom.style.top = this.restoreLT[1];
5940
5941         var ts = this.panel.tools;
5942         if(ts && ts.toggle){
5943             ts.toggle.show();
5944         }
5945     },
5946
5947     /**
5948      * If this Region is {@link #floatable}, and this Region has been slid into floating visibility, then this method slides
5949      * this region back into its collapsed state.
5950      */
5951     slideIn : function(cb){
5952         if(!this.isSlid || this.el.hasActiveFx()){
5953             Ext.callback(cb);
5954             return;
5955         }
5956         this.isSlid = false;
5957         if(this.animFloat !== false){
5958             this.beforeSlide();
5959             this.el.slideOut(this.getSlideAnchor(), {
5960                 callback: function(){
5961                     this.el.hide();
5962                     this.afterSlide();
5963                     this.afterSlideIn();
5964                     Ext.callback(cb);
5965                 },
5966                 scope: this,
5967                 block: true
5968             });
5969         }else{
5970             this.el.hide();
5971             this.afterSlideIn();
5972         }
5973     },
5974
5975     // private
5976     slideInIf : function(e){
5977         if(!e.within(this.el)){
5978             this.slideIn();
5979         }
5980     },
5981
5982     // private
5983     anchors : {
5984         "west" : "left",
5985         "east" : "right",
5986         "north" : "top",
5987         "south" : "bottom"
5988     },
5989
5990     // private
5991     sanchors : {
5992         "west" : "l",
5993         "east" : "r",
5994         "north" : "t",
5995         "south" : "b"
5996     },
5997
5998     // private
5999     canchors : {
6000         "west" : "tl-tr",
6001         "east" : "tr-tl",
6002         "north" : "tl-bl",
6003         "south" : "bl-tl"
6004     },
6005
6006     // private
6007     getAnchor : function(){
6008         return this.anchors[this.position];
6009     },
6010
6011     // private
6012     getCollapseAnchor : function(){
6013         return this.canchors[this.position];
6014     },
6015
6016     // private
6017     getSlideAnchor : function(){
6018         return this.sanchors[this.position];
6019     },
6020
6021     // private
6022     getAlignAdj : function(){
6023         var cm = this.cmargins;
6024         switch(this.position){
6025             case "west":
6026                 return [0, 0];
6027             break;
6028             case "east":
6029                 return [0, 0];
6030             break;
6031             case "north":
6032                 return [0, 0];
6033             break;
6034             case "south":
6035                 return [0, 0];
6036             break;
6037         }
6038     },
6039
6040     // private
6041     getExpandAdj : function(){
6042         var c = this.collapsedEl, cm = this.cmargins;
6043         switch(this.position){
6044             case "west":
6045                 return [-(cm.right+c.getWidth()+cm.left), 0];
6046             break;
6047             case "east":
6048                 return [cm.right+c.getWidth()+cm.left, 0];
6049             break;
6050             case "north":
6051                 return [0, -(cm.top+cm.bottom+c.getHeight())];
6052             break;
6053             case "south":
6054                 return [0, cm.top+cm.bottom+c.getHeight()];
6055             break;
6056         }
6057     }
6058 };
6059
6060 /**
6061  * @class Ext.layout.BorderLayout.SplitRegion
6062  * @extends Ext.layout.BorderLayout.Region
6063  * <p>This is a specialized type of {@link Ext.layout.BorderLayout.Region BorderLayout region} that
6064  * has a built-in {@link Ext.SplitBar} for user resizing of regions.  The movement of the split bar
6065  * is configurable to move either {@link #tickSize smooth or incrementally}.</p>
6066  * @constructor
6067  * Create a new SplitRegion.
6068  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
6069  * @param {Object} config The configuration options
6070  * @param {String} position The region position.  Valid values are: north, south, east, west and center.  Every
6071  * BorderLayout must have a center region for the primary content -- all other regions are optional.
6072  */
6073 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
6074     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
6075     // prevent switch
6076     this.applyLayout = this.applyFns[pos];
6077 };
6078
6079 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
6080     /**
6081      * @cfg {Number} tickSize
6082      * The increment, in pixels by which to move this Region's {@link Ext.SplitBar SplitBar}.
6083      * By default, the {@link Ext.SplitBar SplitBar} moves smoothly.
6084      */
6085     /**
6086      * @cfg {String} splitTip
6087      * The tooltip to display when the user hovers over a
6088      * {@link Ext.layout.BorderLayout.Region#collapsible non-collapsible} region's split bar
6089      * (defaults to <tt>"Drag to resize."</tt>).  Only applies if
6090      * <tt>{@link #useSplitTips} = true</tt>.
6091      */
6092     splitTip : "Drag to resize.",
6093     /**
6094      * @cfg {String} collapsibleSplitTip
6095      * The tooltip to display when the user hovers over a
6096      * {@link Ext.layout.BorderLayout.Region#collapsible collapsible} region's split bar
6097      * (defaults to "Drag to resize. Double click to hide."). Only applies if
6098      * <tt>{@link #useSplitTips} = true</tt>.
6099      */
6100     collapsibleSplitTip : "Drag to resize. Double click to hide.",
6101     /**
6102      * @cfg {Boolean} useSplitTips
6103      * <tt>true</tt> to display a tooltip when the user hovers over a region's split bar
6104      * (defaults to <tt>false</tt>).  The tooltip text will be the value of either
6105      * <tt>{@link #splitTip}</tt> or <tt>{@link #collapsibleSplitTip}</tt> as appropriate.
6106      */
6107     useSplitTips : false,
6108
6109     // private
6110     splitSettings : {
6111         north : {
6112             orientation: Ext.SplitBar.VERTICAL,
6113             placement: Ext.SplitBar.TOP,
6114             maxFn : 'getVMaxSize',
6115             minProp: 'minHeight',
6116             maxProp: 'maxHeight'
6117         },
6118         south : {
6119             orientation: Ext.SplitBar.VERTICAL,
6120             placement: Ext.SplitBar.BOTTOM,
6121             maxFn : 'getVMaxSize',
6122             minProp: 'minHeight',
6123             maxProp: 'maxHeight'
6124         },
6125         east : {
6126             orientation: Ext.SplitBar.HORIZONTAL,
6127             placement: Ext.SplitBar.RIGHT,
6128             maxFn : 'getHMaxSize',
6129             minProp: 'minWidth',
6130             maxProp: 'maxWidth'
6131         },
6132         west : {
6133             orientation: Ext.SplitBar.HORIZONTAL,
6134             placement: Ext.SplitBar.LEFT,
6135             maxFn : 'getHMaxSize',
6136             minProp: 'minWidth',
6137             maxProp: 'maxWidth'
6138         }
6139     },
6140
6141     // private
6142     applyFns : {
6143         west : function(box){
6144             if(this.isCollapsed){
6145                 return this.applyLayoutCollapsed(box);
6146             }
6147             var sd = this.splitEl.dom, s = sd.style;
6148             this.panel.setPosition(box.x, box.y);
6149             var sw = sd.offsetWidth;
6150             s.left = (box.x+box.width-sw)+'px';
6151             s.top = (box.y)+'px';
6152             s.height = Math.max(0, box.height)+'px';
6153             this.panel.setSize(box.width-sw, box.height);
6154         },
6155         east : function(box){
6156             if(this.isCollapsed){
6157                 return this.applyLayoutCollapsed(box);
6158             }
6159             var sd = this.splitEl.dom, s = sd.style;
6160             var sw = sd.offsetWidth;
6161             this.panel.setPosition(box.x+sw, box.y);
6162             s.left = (box.x)+'px';
6163             s.top = (box.y)+'px';
6164             s.height = Math.max(0, box.height)+'px';
6165             this.panel.setSize(box.width-sw, box.height);
6166         },
6167         north : function(box){
6168             if(this.isCollapsed){
6169                 return this.applyLayoutCollapsed(box);
6170             }
6171             var sd = this.splitEl.dom, s = sd.style;
6172             var sh = sd.offsetHeight;
6173             this.panel.setPosition(box.x, box.y);
6174             s.left = (box.x)+'px';
6175             s.top = (box.y+box.height-sh)+'px';
6176             s.width = Math.max(0, box.width)+'px';
6177             this.panel.setSize(box.width, box.height-sh);
6178         },
6179         south : function(box){
6180             if(this.isCollapsed){
6181                 return this.applyLayoutCollapsed(box);
6182             }
6183             var sd = this.splitEl.dom, s = sd.style;
6184             var sh = sd.offsetHeight;
6185             this.panel.setPosition(box.x, box.y+sh);
6186             s.left = (box.x)+'px';
6187             s.top = (box.y)+'px';
6188             s.width = Math.max(0, box.width)+'px';
6189             this.panel.setSize(box.width, box.height-sh);
6190         }
6191     },
6192
6193     // private
6194     render : function(ct, p){
6195         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
6196
6197         var ps = this.position;
6198
6199         this.splitEl = ct.createChild({
6200             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
6201             id: this.panel.id + '-xsplit'
6202         });
6203
6204         if(this.collapseMode == 'mini'){
6205             this.miniSplitEl = this.splitEl.createChild({
6206                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
6207             });
6208             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
6209             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
6210         }
6211
6212         var s = this.splitSettings[ps];
6213
6214         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
6215         this.split.tickSize = this.tickSize;
6216         this.split.placement = s.placement;
6217         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
6218         this.split.minSize = this.minSize || this[s.minProp];
6219         this.split.on("beforeapply", this.onSplitMove, this);
6220         this.split.useShim = this.useShim === true;
6221         this.maxSize = this.maxSize || this[s.maxProp];
6222
6223         if(p.hidden){
6224             this.splitEl.hide();
6225         }
6226
6227         if(this.useSplitTips){
6228             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
6229         }
6230         if(this.collapsible){
6231             this.splitEl.on("dblclick", this.onCollapseClick,  this);
6232         }
6233     },
6234
6235     //docs inherit from superclass
6236     getSize : function(){
6237         if(this.isCollapsed){
6238             return this.collapsedEl.getSize();
6239         }
6240         var s = this.panel.getSize();
6241         if(this.position == 'north' || this.position == 'south'){
6242             s.height += this.splitEl.dom.offsetHeight;
6243         }else{
6244             s.width += this.splitEl.dom.offsetWidth;
6245         }
6246         return s;
6247     },
6248
6249     // private
6250     getHMaxSize : function(){
6251          var cmax = this.maxSize || 10000;
6252          var center = this.layout.center;
6253          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
6254     },
6255
6256     // private
6257     getVMaxSize : function(){
6258         var cmax = this.maxSize || 10000;
6259         var center = this.layout.center;
6260         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
6261     },
6262
6263     // private
6264     onSplitMove : function(split, newSize){
6265         var s = this.panel.getSize();
6266         this.lastSplitSize = newSize;
6267         if(this.position == 'north' || this.position == 'south'){
6268             this.panel.setSize(s.width, newSize);
6269             this.state.height = newSize;
6270         }else{
6271             this.panel.setSize(newSize, s.height);
6272             this.state.width = newSize;
6273         }
6274         this.layout.layout();
6275         this.panel.saveState();
6276         return false;
6277     },
6278
6279     /**
6280      * Returns a reference to the split bar in use by this region.
6281      * @return {Ext.SplitBar} The split bar
6282      */
6283     getSplitBar : function(){
6284         return this.split;
6285     },
6286
6287     // inherit docs
6288     destroy : function() {
6289         Ext.destroy(
6290             this.miniSplitEl,
6291             this.split,
6292             this.splitEl
6293         );
6294     }
6295 });
6296
6297 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;/**
6298  * @class Ext.layout.FormLayout
6299  * @extends Ext.layout.AnchorLayout
6300  * <p>This layout manager is specifically designed for rendering and managing child Components of
6301  * {@link Ext.form.FormPanel forms}. It is responsible for rendering the labels of
6302  * {@link Ext.form.Field Field}s.</p>
6303  *
6304  * <p>This layout manager is used when a Container is configured with the <tt>layout:'form'</tt>
6305  * {@link Ext.Container#layout layout} config option, and should generally not need to be created directly
6306  * via the new keyword. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
6307  *
6308  * <p>In an application, it will usually be preferrable to use a {@link Ext.form.FormPanel FormPanel}
6309  * (which is configured with FormLayout as its layout class by default) since it also provides built-in
6310  * functionality for {@link Ext.form.BasicForm#doAction loading, validating and submitting} the form.</p>
6311  *
6312  * <p>A {@link Ext.Container Container} <i>using</i> the FormLayout layout manager (e.g.
6313  * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) can also accept the following
6314  * layout-specific config properties:<div class="mdetail-params"><ul>
6315  * <li><b><tt>{@link Ext.form.FormPanel#hideLabels hideLabels}</tt></b></li>
6316  * <li><b><tt>{@link Ext.form.FormPanel#labelAlign labelAlign}</tt></b></li>
6317  * <li><b><tt>{@link Ext.form.FormPanel#labelPad labelPad}</tt></b></li>
6318  * <li><b><tt>{@link Ext.form.FormPanel#labelSeparator labelSeparator}</tt></b></li>
6319  * <li><b><tt>{@link Ext.form.FormPanel#labelWidth labelWidth}</tt></b></li>
6320  * </ul></div></p>
6321  *
6322  * <p>Any Component (including Fields) managed by FormLayout accepts the following as a config option:
6323  * <div class="mdetail-params"><ul>
6324  * <li><b><tt>{@link Ext.Component#anchor anchor}</tt></b></li>
6325  * </ul></div></p>
6326  *
6327  * <p>Any Component managed by FormLayout may be rendered as a form field (with an associated label) by
6328  * configuring it with a non-null <b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b>. Components configured
6329  * in this way may be configured with the following options which affect the way the FormLayout renders them:
6330  * <div class="mdetail-params"><ul>
6331  * <li><b><tt>{@link Ext.Component#clearCls clearCls}</tt></b></li>
6332  * <li><b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b></li>
6333  * <li><b><tt>{@link Ext.Component#hideLabel hideLabel}</tt></b></li>
6334  * <li><b><tt>{@link Ext.Component#itemCls itemCls}</tt></b></li>
6335  * <li><b><tt>{@link Ext.Component#labelSeparator labelSeparator}</tt></b></li>
6336  * <li><b><tt>{@link Ext.Component#labelStyle labelStyle}</tt></b></li>
6337  * </ul></div></p>
6338  *
6339  * <p>Example usage:</p>
6340  * <pre><code>
6341 // Required if showing validation messages
6342 Ext.QuickTips.init();
6343
6344 // While you can create a basic Panel with layout:'form', practically
6345 // you should usually use a FormPanel to also get its form functionality
6346 // since it already creates a FormLayout internally.
6347 var form = new Ext.form.FormPanel({
6348     title: 'Form Layout',
6349     bodyStyle: 'padding:15px',
6350     width: 350,
6351     defaultType: 'textfield',
6352     defaults: {
6353         // applied to each contained item
6354         width: 230,
6355         msgTarget: 'side'
6356     },
6357     items: [{
6358             fieldLabel: 'First Name',
6359             name: 'first',
6360             allowBlank: false,
6361             {@link Ext.Component#labelSeparator labelSeparator}: ':' // override labelSeparator layout config
6362         },{
6363             fieldLabel: 'Last Name',
6364             name: 'last'
6365         },{
6366             fieldLabel: 'Email',
6367             name: 'email',
6368             vtype:'email'
6369         }, {
6370             xtype: 'textarea',
6371             hideLabel: true,     // override hideLabels layout config
6372             name: 'msg',
6373             anchor: '100% -53'
6374         }
6375     ],
6376     buttons: [
6377         {text: 'Save'},
6378         {text: 'Cancel'}
6379     ],
6380     layoutConfig: {
6381         {@link #labelSeparator}: '~' // superseded by assignment below
6382     },
6383     // config options applicable to container when layout='form':
6384     hideLabels: false,
6385     labelAlign: 'left',   // or 'right' or 'top'
6386     {@link Ext.form.FormPanel#labelSeparator labelSeparator}: '>>', // takes precedence over layoutConfig value
6387     labelWidth: 65,       // defaults to 100
6388     labelPad: 8           // defaults to 5, must specify labelWidth to be honored
6389 });
6390 </code></pre>
6391  */
6392 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
6393
6394     /**
6395      * @cfg {String} labelSeparator
6396      * See {@link Ext.form.FormPanel}.{@link Ext.form.FormPanel#labelSeparator labelSeparator}.  Configuration
6397      * of this property at the <b>container</b> level takes precedence.
6398      */
6399     labelSeparator : ':',
6400
6401     /**
6402      * Read only. The CSS style specification string added to field labels in this layout if not
6403      * otherwise {@link Ext.Component#labelStyle specified by each contained field}.
6404      * @type String
6405      * @property labelStyle
6406      */
6407     
6408     /**
6409      * @cfg {Boolean} trackLabels
6410      * True to show/hide the field label when the field is hidden. Defaults to <tt>false</tt>.
6411      */
6412     trackLabels: false,
6413     
6414
6415     onRemove: function(c){
6416         Ext.layout.FormLayout.superclass.onRemove.call(this, c);
6417         if(this.trackLabels && !this.isHide(c)){
6418             c.un('show', this.onFieldShow, this);
6419             c.un('hide', this.onFieldHide, this);
6420         }
6421         // check for itemCt, since we may be removing a fieldset or something similar
6422         var el = c.getPositionEl(),
6423                 ct = c.getItemCt && c.getItemCt();
6424         if(c.rendered && ct){
6425             el.insertAfter(ct);
6426             Ext.destroy(ct);
6427             Ext.destroyMembers(c, 'label', 'itemCt');
6428             if(c.customItemCt){
6429                 Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
6430             }
6431         }
6432     },
6433     
6434     // private
6435     setContainer : function(ct){
6436         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
6437         if(ct.labelAlign){
6438             ct.addClass('x-form-label-'+ct.labelAlign);
6439         }
6440
6441         if(ct.hideLabels){
6442             Ext.apply(this, {
6443                 labelStyle: 'display:none',
6444                 elementStyle: 'padding-left:0;',
6445                 labelAdjust: 0
6446             });
6447         }else{
6448             this.labelSeparator = ct.labelSeparator || this.labelSeparator;
6449             ct.labelWidth = ct.labelWidth || 100;
6450             if(Ext.isNumber(ct.labelWidth)){
6451                 var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
6452                 Ext.apply(this, {
6453                     labelAdjust: ct.labelWidth + pad,
6454                     labelStyle: 'width:' + ct.labelWidth + 'px;',
6455                     elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
6456                 });
6457             }
6458             if(ct.labelAlign == 'top'){
6459                 Ext.apply(this, {
6460                     labelStyle: 'width:auto;',
6461                     labelAdjust: 0,
6462                     elementStyle: 'padding-left:0;'
6463                 });
6464             }
6465         }
6466     },
6467     
6468     isHide: function(c){
6469         return c.hideLabel || this.container.hideLabels;
6470     },
6471     
6472     onFieldShow: function(c){
6473         c.getItemCt().removeClass('x-hide-' + c.hideMode);
6474     },
6475     
6476     onFieldHide: function(c){
6477         c.getItemCt().addClass('x-hide-' + c.hideMode);   
6478     },
6479
6480     //private
6481     getLabelStyle: function(s){
6482         var ls = '', items = [this.labelStyle, s];
6483         for (var i = 0, len = items.length; i < len; ++i){
6484             if (items[i]){
6485                 ls += items[i];
6486                 if (ls.substr(-1, 1) != ';'){
6487                     ls += ';'
6488                 }
6489             }
6490         }
6491         return ls;
6492     },
6493
6494     /**
6495      * @cfg {Ext.Template} fieldTpl
6496      * A {@link Ext.Template#compile compile}d {@link Ext.Template} for rendering
6497      * the fully wrapped, labeled and styled form Field. Defaults to:</p><pre><code>
6498 new Ext.Template(
6499     &#39;&lt;div class="x-form-item {itemCls}" tabIndex="-1">&#39;,
6500         &#39;&lt;&#108;abel for="{id}" style="{labelStyle}" class="x-form-item-&#108;abel">{&#108;abel}{labelSeparator}&lt;/&#108;abel>&#39;,
6501         &#39;&lt;div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">&#39;,
6502         &#39;&lt;/div>&lt;div class="{clearCls}">&lt;/div>&#39;,
6503     '&lt;/div>'
6504 );
6505 </code></pre>
6506      * <p>This may be specified to produce a different DOM structure when rendering form Fields.</p>
6507      * <p>A description of the properties within the template follows:</p><div class="mdetail-params"><ul>
6508      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
6509      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
6510      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
6511      * supplied at the container level.</div></li>
6512      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
6513      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
6514      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
6515      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
6516      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
6517      * field (defaults to <tt>''</tt>)</div></li>
6518      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
6519      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
6520      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
6521      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
6522      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
6523      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
6524      * </ul></div>
6525      * <p>Also see <tt>{@link #getTemplateArgs}</tt></p>
6526      */
6527
6528     // private
6529     renderItem : function(c, position, target){
6530         if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
6531             var args = this.getTemplateArgs(c);
6532             if(Ext.isNumber(position)){
6533                 position = target.dom.childNodes[position] || null;
6534             }
6535             if(position){
6536                 c.itemCt = this.fieldTpl.insertBefore(position, args, true);
6537             }else{
6538                 c.itemCt = this.fieldTpl.append(target, args, true);
6539             }
6540             if(!c.rendered){
6541                 c.render('x-form-el-' + c.id);
6542             }else if(!this.isValidParent(c, target)){
6543                 Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
6544             }
6545             if(!c.getItemCt){
6546                 // Non form fields don't have getItemCt, apply it here
6547                 // This will get cleaned up in onRemove
6548                 Ext.apply(c, {
6549                     getItemCt: function(){
6550                         return c.itemCt;
6551                     },
6552                     customItemCt: true
6553                 });
6554             }
6555             c.label = c.getItemCt().child('label.x-form-item-label');
6556             if(this.trackLabels && !this.isHide(c)){
6557                 if(c.hidden){
6558                     this.onFieldHide(c);
6559                 }
6560                 c.on({
6561                     scope: this,
6562                     show: this.onFieldShow,
6563                     hide: this.onFieldHide
6564                 });
6565             }
6566             this.configureItem(c);
6567         }else {
6568             Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
6569         }
6570     },
6571
6572     /**
6573      * <p>Provides template arguments for rendering the fully wrapped, labeled and styled form Field.</p>
6574      * <p>This method returns an object hash containing properties used by the layout's {@link #fieldTpl}
6575      * to create a correctly wrapped, labeled and styled form Field. This may be overriden to
6576      * create custom layouts. The properties which must be returned are:</p><div class="mdetail-params"><ul>
6577      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
6578      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
6579      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
6580      * supplied at the container level.</div></li>
6581      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
6582      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
6583      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
6584      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
6585      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
6586      * field (defaults to <tt>''</tt>)</div></li>
6587      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
6588      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
6589      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
6590      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
6591      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
6592      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
6593      * </ul></div>
6594      * @param field The {@link Field Ext.form.Field} being rendered.
6595      * @return An object hash containing the properties required to render the Field.
6596      */
6597     getTemplateArgs: function(field) {
6598         var noLabelSep = !field.fieldLabel || field.hideLabel;
6599         return {
6600             id: field.id,
6601             label: field.fieldLabel,
6602             labelStyle: this.getLabelStyle(field.labelStyle),
6603             elementStyle: this.elementStyle||'',
6604             labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator),
6605             itemCls: (field.itemCls||this.container.itemCls||'') + (field.hideLabel ? ' x-hide-label' : ''),
6606             clearCls: field.clearCls || 'x-form-clear-left'
6607         };
6608     },
6609
6610     // private
6611     adjustWidthAnchor: function(value, c){
6612         if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){
6613             var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
6614             return value - this.labelAdjust + (adjust ? -3 : 0);
6615         }
6616         return value;
6617     },
6618     
6619     adjustHeightAnchor : function(value, c){
6620         if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
6621             return value - c.label.getHeight();
6622         }
6623         return value;
6624     },
6625
6626     // private
6627     isValidParent : function(c, target){
6628         return target && this.container.getEl().contains(c.getDomPositionEl());
6629     }
6630
6631     /**
6632      * @property activeItem
6633      * @hide
6634      */
6635 });
6636
6637 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;/**\r
6638  * @class Ext.layout.AccordionLayout\r
6639  * @extends Ext.layout.FitLayout\r
6640  * <p>This is a layout that manages multiple Panels in an expandable accordion style such that only\r
6641  * <b>one Panel can be expanded at any given time</b>. Each Panel has built-in support for expanding and collapsing.</p>\r
6642  * <p>Note: Only Ext.Panels <b>and all subclasses of Ext.Panel</b> may be used in an accordion layout Container.</p>\r
6643  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>\r
6644  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>\r
6645  * <p>Example usage:</p>\r
6646  * <pre><code>\r
6647 var accordion = new Ext.Panel({\r
6648     title: 'Accordion Layout',\r
6649     layout:'accordion',\r
6650     defaults: {\r
6651         // applied to each contained panel\r
6652         bodyStyle: 'padding:15px'\r
6653     },\r
6654     layoutConfig: {\r
6655         // layout-specific configs go here\r
6656         titleCollapse: false,\r
6657         animate: true,\r
6658         activeOnTop: true\r
6659     },\r
6660     items: [{\r
6661         title: 'Panel 1',\r
6662         html: '&lt;p&gt;Panel content!&lt;/p&gt;'\r
6663     },{\r
6664         title: 'Panel 2',\r
6665         html: '&lt;p&gt;Panel content!&lt;/p&gt;'\r
6666     },{\r
6667         title: 'Panel 3',\r
6668         html: '&lt;p&gt;Panel content!&lt;/p&gt;'\r
6669     }]\r
6670 });\r
6671 </code></pre>\r
6672  */\r
6673 Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {\r
6674     /**\r
6675      * @cfg {Boolean} fill\r
6676      * True to adjust the active item's height to fill the available space in the container, false to use the\r
6677      * item's current height, or auto height if not explicitly set (defaults to true).\r
6678      */\r
6679     fill : true,\r
6680     /**\r
6681      * @cfg {Boolean} autoWidth\r
6682      * True to set each contained item's width to 'auto', false to use the item's current width (defaults to true).\r
6683      * Note that some components, in particular the {@link Ext.grid.GridPanel grid}, will not function properly within\r
6684      * layouts if they have auto width, so in such cases this config should be set to false.\r
6685      */\r
6686     autoWidth : true,\r
6687     /**\r
6688      * @cfg {Boolean} titleCollapse\r
6689      * True to allow expand/collapse of each contained panel by clicking anywhere on the title bar, false to allow\r
6690      * expand/collapse only when the toggle tool button is clicked (defaults to true).  When set to false,\r
6691      * {@link #hideCollapseTool} should be false also.\r
6692      */\r
6693     titleCollapse : true,\r
6694     /**\r
6695      * @cfg {Boolean} hideCollapseTool\r
6696      * True to hide the contained panels' collapse/expand toggle buttons, false to display them (defaults to false).\r
6697      * When set to true, {@link #titleCollapse} should be true also.\r
6698      */\r
6699     hideCollapseTool : false,\r
6700     /**\r
6701      * @cfg {Boolean} collapseFirst\r
6702      * True to make sure the collapse/expand toggle button always renders first (to the left of) any other tools\r
6703      * in the contained panels' title bars, false to render it last (defaults to false).\r
6704      */\r
6705     collapseFirst : false,\r
6706     /**\r
6707      * @cfg {Boolean} animate\r
6708      * True to slide the contained panels open and closed during expand/collapse using animation, false to open and\r
6709      * close directly with no animation (defaults to false).  Note: to defer to the specific config setting of each\r
6710      * contained panel for this property, set this to undefined at the layout level.\r
6711      */\r
6712     animate : false,\r
6713     /**\r
6714      * @cfg {Boolean} sequence\r
6715      * <b>Experimental</b>. If animate is set to true, this will result in each animation running in sequence.\r
6716      */\r
6717     sequence : false,\r
6718     /**\r
6719      * @cfg {Boolean} activeOnTop\r
6720      * True to swap the position of each panel as it is expanded so that it becomes the first item in the container,\r
6721      * false to keep the panels in the rendered order. <b>This is NOT compatible with "animate:true"</b> (defaults to false).\r
6722      */\r
6723     activeOnTop : false,\r
6724 \r
6725     renderItem : function(c){\r
6726         if(this.animate === false){\r
6727             c.animCollapse = false;\r
6728         }\r
6729         c.collapsible = true;\r
6730         if(this.autoWidth){\r
6731             c.autoWidth = true;\r
6732         }\r
6733         if(this.titleCollapse){\r
6734             c.titleCollapse = true;\r
6735         }\r
6736         if(this.hideCollapseTool){\r
6737             c.hideCollapseTool = true;\r
6738         }\r
6739         if(this.collapseFirst !== undefined){\r
6740             c.collapseFirst = this.collapseFirst;\r
6741         }\r
6742         if(!this.activeItem && !c.collapsed){\r
6743             this.activeItem = c;\r
6744         }else if(this.activeItem && this.activeItem != c){\r
6745             c.collapsed = true;\r
6746         }\r
6747         Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);\r
6748         c.header.addClass('x-accordion-hd');\r
6749         c.on('beforeexpand', this.beforeExpand, this);\r
6750     },\r
6751     \r
6752     onRemove: function(c){\r
6753         Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);\r
6754         if(c.rendered){\r
6755             c.header.removeClass('x-accordion-hd');\r
6756         }\r
6757         c.un('beforeexpand', this.beforeExpand, this);\r
6758     },\r
6759 \r
6760     // private\r
6761     beforeExpand : function(p, anim){\r
6762         var ai = this.activeItem;\r
6763         if(ai){\r
6764             if(this.sequence){\r
6765                 delete this.activeItem;\r
6766                 if (!ai.collapsed){\r
6767                     ai.collapse({callback:function(){\r
6768                         p.expand(anim || true);\r
6769                     }, scope: this});\r
6770                     return false;\r
6771                 }\r
6772             }else{\r
6773                 ai.collapse(this.animate);\r
6774             }\r
6775         }\r
6776         this.activeItem = p;\r
6777         if(this.activeOnTop){\r
6778             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);\r
6779         }\r
6780         this.layout();\r
6781     },\r
6782 \r
6783     // private\r
6784     setItemSize : function(item, size){\r
6785         if(this.fill && item){\r
6786             var hh = 0;\r
6787             this.container.items.each(function(p){\r
6788                 if(p != item){\r
6789                     hh += p.header.getHeight();\r
6790                 }    \r
6791             });\r
6792             size.height -= hh;\r
6793             item.setSize(size);\r
6794         }\r
6795     },\r
6796 \r
6797     /**\r
6798      * Sets the active (expanded) item in the layout.\r
6799      * @param {String/Number} item The string component id or numeric index of the item to activate\r
6800      */\r
6801     setActiveItem : function(item){\r
6802         item = this.container.getComponent(item);\r
6803         if(this.activeItem != item){\r
6804             if(item.rendered && item.collapsed){\r
6805                 item.expand();\r
6806             }else{\r
6807                 this.activeItem = item;\r
6808             }\r
6809         }\r
6810 \r
6811     }\r
6812 });\r
6813 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;\r
6814 \r
6815 //backwards compat\r
6816 Ext.layout.Accordion = Ext.layout.AccordionLayout;/**\r
6817  * @class Ext.layout.TableLayout\r
6818  * @extends Ext.layout.ContainerLayout\r
6819  * <p>This layout allows you to easily render content into an HTML table.  The total number of columns can be\r
6820  * specified, and rowspan and colspan can be used to create complex layouts within the table.\r
6821  * This class is intended to be extended or created via the layout:'table' {@link Ext.Container#layout} config,\r
6822  * and should generally not need to be created directly via the new keyword.</p>\r
6823  * <p>Note that when creating a layout via config, the layout-specific config properties must be passed in via\r
6824  * the {@link Ext.Container#layoutConfig} object which will then be applied internally to the layout.  In the\r
6825  * case of TableLayout, the only valid layout config property is {@link #columns}.  However, the items added to a\r
6826  * TableLayout can supply the following table-specific config properties:</p>\r
6827  * <ul>\r
6828  * <li><b>rowspan</b> Applied to the table cell containing the item.</li>\r
6829  * <li><b>colspan</b> Applied to the table cell containing the item.</li>\r
6830  * <li><b>cellId</b> An id applied to the table cell containing the item.</li>\r
6831  * <li><b>cellCls</b> A CSS class name added to the table cell containing the item.</li>\r
6832  * </ul>\r
6833  * <p>The basic concept of building up a TableLayout is conceptually very similar to building up a standard\r
6834  * HTML table.  You simply add each panel (or "cell") that you want to include along with any span attributes\r
6835  * specified as the special config properties of rowspan and colspan which work exactly like their HTML counterparts.\r
6836  * Rather than explicitly creating and nesting rows and columns as you would in HTML, you simply specify the\r
6837  * total column count in the layoutConfig and start adding panels in their natural order from left to right,\r
6838  * top to bottom.  The layout will automatically figure out, based on the column count, rowspans and colspans,\r
6839  * how to position each panel within the table.  Just like with HTML tables, your rowspans and colspans must add\r
6840  * up correctly in your overall layout or you'll end up with missing and/or extra cells!  Example usage:</p>\r
6841  * <pre><code>\r
6842 // This code will generate a layout table that is 3 columns by 2 rows\r
6843 // with some spanning included.  The basic layout will be:\r
6844 // +--------+-----------------+\r
6845 // |   A    |   B             |\r
6846 // |        |--------+--------|\r
6847 // |        |   C    |   D    |\r
6848 // +--------+--------+--------+\r
6849 var table = new Ext.Panel({\r
6850     title: 'Table Layout',\r
6851     layout:'table',\r
6852     defaults: {\r
6853         // applied to each contained panel\r
6854         bodyStyle:'padding:20px'\r
6855     },\r
6856     layoutConfig: {\r
6857         // The total column count must be specified here\r
6858         columns: 3\r
6859     },\r
6860     items: [{\r
6861         html: '&lt;p&gt;Cell A content&lt;/p&gt;',\r
6862         rowspan: 2\r
6863     },{\r
6864         html: '&lt;p&gt;Cell B content&lt;/p&gt;',\r
6865         colspan: 2\r
6866     },{\r
6867         html: '&lt;p&gt;Cell C content&lt;/p&gt;',\r
6868         cellCls: 'highlight'\r
6869     },{\r
6870         html: '&lt;p&gt;Cell D content&lt;/p&gt;'\r
6871     }]\r
6872 });\r
6873 </code></pre>\r
6874  */\r
6875 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
6876     /**\r
6877      * @cfg {Number} columns\r
6878      * The total number of columns to create in the table for this layout.  If not specified, all Components added to\r
6879      * this layout will be rendered into a single row using one column per Component.\r
6880      */\r
6881 \r
6882     // private\r
6883     monitorResize:false,\r
6884 \r
6885     /**\r
6886      * @cfg {Object} tableAttrs\r
6887      * <p>An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification\r
6888      * used to create the layout's <tt>&lt;table&gt;</tt> element. Example:</p><pre><code>\r
6889 {\r
6890     xtype: 'panel',\r
6891     layout: 'table',\r
6892     layoutConfig: {\r
6893         tableAttrs: {\r
6894                 style: {\r
6895                         width: '100%'\r
6896                 }\r
6897         },\r
6898         columns: 3\r
6899     }\r
6900 }</code></pre>\r
6901      */\r
6902     tableAttrs:null,\r
6903     \r
6904     // private\r
6905     setContainer : function(ct){\r
6906         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);\r
6907 \r
6908         this.currentRow = 0;\r
6909         this.currentColumn = 0;\r
6910         this.cells = [];\r
6911     },\r
6912 \r
6913     // private\r
6914     onLayout : function(ct, target){\r
6915         var cs = ct.items.items, len = cs.length, c, i;\r
6916 \r
6917         if(!this.table){\r
6918             target.addClass('x-table-layout-ct');\r
6919 \r
6920             this.table = target.createChild(\r
6921                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);\r
6922         }\r
6923         this.renderAll(ct, target);\r
6924     },\r
6925 \r
6926     // private\r
6927     getRow : function(index){\r
6928         var row = this.table.tBodies[0].childNodes[index];\r
6929         if(!row){\r
6930             row = document.createElement('tr');\r
6931             this.table.tBodies[0].appendChild(row);\r
6932         }\r
6933         return row;\r
6934     },\r
6935 \r
6936     // private\r
6937     getNextCell : function(c){\r
6938         var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);\r
6939         var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];\r
6940         for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){\r
6941             if(!this.cells[rowIndex]){\r
6942                 this.cells[rowIndex] = [];\r
6943             }\r
6944             for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){\r
6945                 this.cells[rowIndex][colIndex] = true;\r
6946             }\r
6947         }\r
6948         var td = document.createElement('td');\r
6949         if(c.cellId){\r
6950             td.id = c.cellId;\r
6951         }\r
6952         var cls = 'x-table-layout-cell';\r
6953         if(c.cellCls){\r
6954             cls += ' ' + c.cellCls;\r
6955         }\r
6956         td.className = cls;\r
6957         if(c.colspan){\r
6958             td.colSpan = c.colspan;\r
6959         }\r
6960         if(c.rowspan){\r
6961             td.rowSpan = c.rowspan;\r
6962         }\r
6963         this.getRow(curRow).appendChild(td);\r
6964         return td;\r
6965     },\r
6966     \r
6967     // private\r
6968     getNextNonSpan: function(colIndex, rowIndex){\r
6969         var cols = this.columns;\r
6970         while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {\r
6971             if(cols && colIndex >= cols){\r
6972                 rowIndex++;\r
6973                 colIndex = 0;\r
6974             }else{\r
6975                 colIndex++;\r
6976             }\r
6977         }\r
6978         return [colIndex, rowIndex];\r
6979     },\r
6980 \r
6981     // private\r
6982     renderItem : function(c, position, target){\r
6983         if(c && !c.rendered){\r
6984             c.render(this.getNextCell(c));\r
6985             this.configureItem(c, position);\r
6986         }else if(c && !this.isValidParent(c, target)){\r
6987             var container = this.getNextCell(c);\r
6988             container.insertBefore(c.getDomPositionEl().dom, null);\r
6989             c.container = Ext.get(container);\r
6990             this.configureItem(c, position);\r
6991         }\r
6992     },\r
6993 \r
6994     // private\r
6995     isValidParent : function(c, target){\r
6996         return c.getDomPositionEl().up('table', 5).dom.parentNode === (target.dom || target);\r
6997     }\r
6998 \r
6999     /**\r
7000      * @property activeItem\r
7001      * @hide\r
7002      */\r
7003 });\r
7004 \r
7005 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;/**\r
7006  * @class Ext.layout.AbsoluteLayout\r
7007  * @extends Ext.layout.AnchorLayout\r
7008  * <p>This is a layout that inherits the anchoring of <b>{@link Ext.layout.AnchorLayout}</b> and adds the\r
7009  * ability for x/y positioning using the standard x and y component config options.</p>\r
7010  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>\r
7011  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>\r
7012  * <p>Example usage:</p>\r
7013  * <pre><code>\r
7014 var form = new Ext.form.FormPanel({\r
7015     title: 'Absolute Layout',\r
7016     layout:'absolute',\r
7017     layoutConfig: {\r
7018         // layout-specific configs go here\r
7019         extraCls: 'x-abs-layout-item',\r
7020     },\r
7021     baseCls: 'x-plain',\r
7022     url:'save-form.php',\r
7023     defaultType: 'textfield',\r
7024     items: [{\r
7025         x: 0,\r
7026         y: 5,\r
7027         xtype:'label',\r
7028         text: 'Send To:'\r
7029     },{\r
7030         x: 60,\r
7031         y: 0,\r
7032         name: 'to',\r
7033         anchor:'100%'  // anchor width by percentage\r
7034     },{\r
7035         x: 0,\r
7036         y: 35,\r
7037         xtype:'label',\r
7038         text: 'Subject:'\r
7039     },{\r
7040         x: 60,\r
7041         y: 30,\r
7042         name: 'subject',\r
7043         anchor: '100%'  // anchor width by percentage\r
7044     },{\r
7045         x:0,\r
7046         y: 60,\r
7047         xtype: 'textarea',\r
7048         name: 'msg',\r
7049         anchor: '100% 100%'  // anchor width and height\r
7050     }]\r
7051 });\r
7052 </code></pre>\r
7053  */\r
7054 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {\r
7055 \r
7056     extraCls: 'x-abs-layout-item',\r
7057 \r
7058     onLayout : function(ct, target){\r
7059         target.position();\r
7060         this.paddingLeft = target.getPadding('l');\r
7061         this.paddingTop = target.getPadding('t');\r
7062 \r
7063         Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);\r
7064     },\r
7065 \r
7066     // private\r
7067     adjustWidthAnchor : function(value, comp){\r
7068         return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;\r
7069     },\r
7070 \r
7071     // private\r
7072     adjustHeightAnchor : function(value, comp){\r
7073         return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;\r
7074     }\r
7075     /**\r
7076      * @property activeItem\r
7077      * @hide\r
7078      */\r
7079 });\r
7080 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
7081 /**\r
7082  * @class Ext.layout.BoxLayout\r
7083  * @extends Ext.layout.ContainerLayout\r
7084  * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>\r
7085  */\r
7086 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
7087     /**\r
7088      * @cfg {Object} defaultMargins\r
7089      * <p>If the individual contained items do not have a <tt>margins</tt>\r
7090      * property specified, the default margins from this property will be\r
7091      * applied to each item.</p>\r
7092      * <br><p>This property may be specified as an object containing margins\r
7093      * to apply in the format:</p><pre><code>\r
7094 {\r
7095     top: (top margin),\r
7096     right: (right margin),\r
7097     bottom: (bottom margin),\r
7098     left: (left margin)\r
7099 }</code></pre>\r
7100      * <p>This property may also be specified as a string containing\r
7101      * space-separated, numeric margin values. The order of the sides associated\r
7102      * with each value matches the way CSS processes margin values:</p>\r
7103      * <div class="mdetail-params"><ul>\r
7104      * <li>If there is only one value, it applies to all sides.</li>\r
7105      * <li>If there are two values, the top and bottom borders are set to the\r
7106      * first value and the right and left are set to the second.</li>\r
7107      * <li>If there are three values, the top is set to the first value, the left\r
7108      * and right are set to the second, and the bottom is set to the third.</li>\r
7109      * <li>If there are four values, they apply to the top, right, bottom, and\r
7110      * left, respectively.</li>\r
7111      * </ul></div>\r
7112      * <p>Defaults to:</p><pre><code>\r
7113      * {top:0, right:0, bottom:0, left:0}\r
7114      * </code></pre>\r
7115      */\r
7116     defaultMargins : {left:0,top:0,right:0,bottom:0},\r
7117     /**\r
7118      * @cfg {String} padding\r
7119      * <p>Sets the padding to be applied to all child items managed by this layout.</p> \r
7120      * <p>This property must be specified as a string containing\r
7121      * space-separated, numeric padding values. The order of the sides associated\r
7122      * with each value matches the way CSS processes padding values:</p>\r
7123      * <div class="mdetail-params"><ul>\r
7124      * <li>If there is only one value, it applies to all sides.</li>\r
7125      * <li>If there are two values, the top and bottom borders are set to the\r
7126      * first value and the right and left are set to the second.</li>\r
7127      * <li>If there are three values, the top is set to the first value, the left\r
7128      * and right are set to the second, and the bottom is set to the third.</li>\r
7129      * <li>If there are four values, they apply to the top, right, bottom, and\r
7130      * left, respectively.</li>\r
7131      * </ul></div>\r
7132      * <p>Defaults to: <code>"0"</code></p>\r
7133      */\r
7134     padding : '0',\r
7135     // documented in subclasses\r
7136     pack : 'start',\r
7137 \r
7138     // private\r
7139     monitorResize : true,\r
7140     scrollOffset : 0,\r
7141     extraCls : 'x-box-item',\r
7142     ctCls : 'x-box-layout-ct',\r
7143     innerCls : 'x-box-inner',\r
7144     \r
7145     constructor : function(config){\r
7146         Ext.layout.BoxLayout.superclass.constructor.call(this, config);\r
7147         if(Ext.isString(this.defaultMargins)){\r
7148             this.defaultMargins = this.parseMargins(this.defaultMargins);\r
7149         }\r
7150     },\r
7151 \r
7152     // private\r
7153     isValidParent : function(c, target){\r
7154         return c.getEl().dom.parentNode == this.innerCt.dom;\r
7155     },\r
7156 \r
7157     // private\r
7158     onLayout : function(ct, target){\r
7159         var cs = ct.items.items, len = cs.length, c, i, last = len-1, cm;\r
7160 \r
7161         if(!this.innerCt){\r
7162             target.addClass(this.ctCls);\r
7163 \r
7164             // the innerCt prevents wrapping and shuffling while\r
7165             // the container is resizing\r
7166             this.innerCt = target.createChild({cls:this.innerCls});\r
7167             this.padding = this.parseMargins(this.padding); \r
7168         }\r
7169         this.renderAll(ct, this.innerCt);\r
7170     },\r
7171 \r
7172     // private\r
7173     renderItem : function(c){\r
7174         if(Ext.isString(c.margins)){\r
7175             c.margins = this.parseMargins(c.margins);\r
7176         }else if(!c.margins){\r
7177             c.margins = this.defaultMargins;\r
7178         }\r
7179         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);\r
7180     },\r
7181 \r
7182     getTargetSize : function(target){
7183         return (Ext.isIE6 && Ext.isStrict && target.dom == document.body) ? target.getStyleSize() : target.getViewSize();\r
7184     },\r
7185     \r
7186     getItems: function(ct){\r
7187         var items = [];\r
7188         ct.items.each(function(c){\r
7189             if(c.isVisible()){\r
7190                 items.push(c);\r
7191             }\r
7192         });\r
7193         return items;\r
7194     }\r
7195 \r
7196     /**\r
7197      * @property activeItem\r
7198      * @hide\r
7199      */\r
7200 });\r
7201 \r
7202 /**\r
7203  * @class Ext.layout.VBoxLayout\r
7204  * @extends Ext.layout.BoxLayout\r
7205  * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical\r
7206  * space between child items containing a numeric <code>flex</code> configuration.</p>\r
7207  * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option.\r
7208  */\r
7209 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {\r
7210     /**\r
7211      * @cfg {String} align\r
7212      * Controls how the child items of the container are aligned. Acceptable configuration values for this\r
7213      * property are:\r
7214      * <div class="mdetail-params"><ul>\r
7215      * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally\r
7216      * at the <b>left</b> side of the container</div></li>\r
7217      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the\r
7218      * <b>mid-width</b> of the container</div></li>\r
7219      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill\r
7220      * the width of the container</div></li>\r
7221      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to\r
7222      * the size of the largest item.</div></li>\r
7223      * </ul></div>\r
7224      */\r
7225     align : 'left', // left, center, stretch, strechmax\r
7226     /**\r
7227      * @cfg {String} pack\r
7228      * Controls how the child items of the container are packed together. Acceptable configuration values\r
7229      * for this property are:\r
7230      * <div class="mdetail-params"><ul>\r
7231      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at\r
7232      * <b>top</b> side of container</div></li>\r
7233      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at\r
7234      * <b>mid-height</b> of container</div></li>\r
7235      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>\r
7236      * side of container</div></li>\r
7237      * </ul></div>\r
7238      */\r
7239     /**\r
7240      * @cfg {Number} flex\r
7241      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed\r
7242      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>\r
7243      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with\r
7244      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or\r
7245      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).\r
7246      */\r
7247 \r
7248     // private\r
7249     onLayout : function(ct, target){\r
7250         Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);\r
7251                     \r
7252         \r
7253         var cs = this.getItems(ct), cm, ch, margin,\r
7254             size = this.getTargetSize(target),\r
7255             w = size.width - target.getPadding('lr'),\r
7256             h = size.height - target.getPadding('tb') - this.scrollOffset,\r
7257             l = this.padding.left, t = this.padding.top,\r
7258             isStart = this.pack == 'start',\r
7259             isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,\r
7260             stretchWidth = w - (this.padding.left + this.padding.right),\r
7261             extraHeight = 0,\r
7262             maxWidth = 0,\r
7263             totalFlex = 0,\r
7264             flexHeight = 0,\r
7265             usedHeight = 0;\r
7266             \r
7267         Ext.each(cs, function(c){\r
7268             cm = c.margins;\r
7269             totalFlex += c.flex || 0;\r
7270             ch = c.getHeight();\r
7271             margin = cm.top + cm.bottom;\r
7272             extraHeight += ch + margin;\r
7273             flexHeight += margin + (c.flex ? 0 : ch);\r
7274             maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);\r
7275         });\r
7276         extraHeight = h - extraHeight - this.padding.top - this.padding.bottom;\r
7277         \r
7278         var innerCtWidth = maxWidth + this.padding.left + this.padding.right;\r
7279         switch(this.align){\r
7280             case 'stretch':\r
7281                 this.innerCt.setSize(w, h);\r
7282                 break;\r
7283             case 'stretchmax':\r
7284             case 'left':\r
7285                 this.innerCt.setSize(innerCtWidth, h);\r
7286                 break;\r
7287             case 'center':\r
7288                 this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);\r
7289                 break;\r
7290         }\r
7291 \r
7292         var availHeight = Math.max(0, h - this.padding.top - this.padding.bottom - flexHeight),\r
7293             leftOver = availHeight,\r
7294             heights = [],\r
7295             restore = [],\r
7296             idx = 0,\r
7297             availableWidth = Math.max(0, w - this.padding.left - this.padding.right);\r
7298             \r
7299 \r
7300         Ext.each(cs, function(c){\r
7301             if(isStart && c.flex){\r
7302                 ch = Math.floor(availHeight * (c.flex / totalFlex));\r
7303                 leftOver -= ch;\r
7304                 heights.push(ch);\r
7305             }\r
7306         }); \r
7307         \r
7308         if(this.pack == 'center'){\r
7309             t += extraHeight ? extraHeight / 2 : 0;\r
7310         }else if(this.pack == 'end'){\r
7311             t += extraHeight;\r
7312         }\r
7313         Ext.each(cs, function(c){\r
7314             cm = c.margins;\r
7315             t += cm.top;\r
7316             c.setPosition(l + cm.left, t);\r
7317             if(isStart && c.flex){\r
7318                 ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));\r
7319                 if(isRestore){\r
7320                     restore.push(c.getWidth());\r
7321                 }\r
7322                 c.setSize(availableWidth, ch);\r
7323             }else{\r
7324                 ch = c.getHeight();\r
7325             }\r
7326             t += ch + cm.bottom;\r
7327         });\r
7328         \r
7329         idx = 0;\r
7330         Ext.each(cs, function(c){\r
7331             cm = c.margins;\r
7332             if(this.align == 'stretch'){\r
7333                 c.setWidth((stretchWidth - (cm.left + cm.right)).constrain(\r
7334                     c.minWidth || 0, c.maxWidth || 1000000));\r
7335             }else if(this.align == 'stretchmax'){\r
7336                 c.setWidth((maxWidth - (cm.left + cm.right)).constrain(\r
7337                     c.minWidth || 0, c.maxWidth || 1000000));\r
7338             }else{\r
7339                 if(this.align == 'center'){\r
7340                     var diff = availableWidth - (c.getWidth() + cm.left + cm.right);\r
7341                     if(diff > 0){\r
7342                         c.setPosition(l + cm.left + (diff/2), c.y);\r
7343                     }\r
7344                 }\r
7345                 if(isStart && c.flex){\r
7346                     c.setWidth(restore[idx++]);\r
7347                 }\r
7348             }\r
7349         }, this);\r
7350     }\r
7351     /**\r
7352      * @property activeItem\r
7353      * @hide\r
7354      */\r
7355 });\r
7356 \r
7357 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;\r
7358 \r
7359 /**\r
7360  * @class Ext.layout.HBoxLayout\r
7361  * @extends Ext.layout.BoxLayout\r
7362  * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal\r
7363  * space between child items containing a numeric <code>flex</code> configuration.</p>\r
7364  * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option.\r
7365  */\r
7366 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {\r
7367     /**\r
7368      * @cfg {String} align\r
7369      * Controls how the child items of the container are aligned. Acceptable configuration values for this\r
7370      * property are:\r
7371      * <div class="mdetail-params"><ul>\r
7372      * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically\r
7373      * at the <b>left</b> side of the container</div></li>\r
7374      * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically at the\r
7375      * <b>mid-height</b> of the container</div></li>\r
7376      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill\r
7377      * the height of the container</div></li>\r
7378      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to\r
7379      * the size of the largest item.</div></li>\r
7380      */\r
7381     align : 'top', // top, middle, stretch, strechmax\r
7382     /**\r
7383      * @cfg {String} pack\r
7384      * Controls how the child items of the container are packed together. Acceptable configuration values\r
7385      * for this property are:\r
7386      * <div class="mdetail-params"><ul>\r
7387      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at\r
7388      * <b>left</b> side of container</div></li>\r
7389      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at\r
7390      * <b>mid-width</b> of container</div></li>\r
7391      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>\r
7392      * side of container</div></li>\r
7393      * </ul></div>\r
7394      */\r
7395     /**\r
7396      * @cfg {Number} flex\r
7397      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed\r
7398      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>\r
7399      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with\r
7400      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or\r
7401      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).\r
7402      */\r
7403 \r
7404     // private\r
7405     onLayout : function(ct, target){\r
7406         Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);\r
7407         \r
7408         var cs = this.getItems(ct), cm, cw, margin,\r
7409             size = this.getTargetSize(target),\r
7410             w = size.width - target.getPadding('lr') - this.scrollOffset,\r
7411             h = size.height - target.getPadding('tb'),\r
7412             l = this.padding.left, t = this.padding.top,\r
7413             isStart = this.pack == 'start',\r
7414             isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,\r
7415             stretchHeight = h - (this.padding.top + this.padding.bottom),\r
7416             extraWidth = 0,\r
7417             maxHeight = 0,\r
7418             totalFlex = 0,\r
7419             flexWidth = 0,\r
7420             usedWidth = 0;\r
7421         \r
7422         Ext.each(cs, function(c){\r
7423             cm = c.margins;\r
7424             totalFlex += c.flex || 0;\r
7425             cw = c.getWidth();\r
7426             margin = cm.left + cm.right;\r
7427             extraWidth += cw + margin;\r
7428             flexWidth += margin + (c.flex ? 0 : cw);\r
7429             maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom);\r
7430         });\r
7431         extraWidth = w - extraWidth - this.padding.left - this.padding.right;\r
7432         \r
7433         var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom;\r
7434         switch(this.align){\r
7435             case 'stretch':\r
7436                 this.innerCt.setSize(w, h);\r
7437                 break;\r
7438             case 'stretchmax':\r
7439             case 'top':\r
7440                 this.innerCt.setSize(w, innerCtHeight);\r
7441                 break;\r
7442             case 'middle':\r
7443                 this.innerCt.setSize(w, h = Math.max(h, innerCtHeight));\r
7444                 break;\r
7445         }\r
7446         \r
7447 \r
7448         var availWidth = Math.max(0, w - this.padding.left - this.padding.right - flexWidth),\r
7449             leftOver = availWidth,\r
7450             widths = [],\r
7451             restore = [],\r
7452             idx = 0,\r
7453             availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom);\r
7454             \r
7455 \r
7456         Ext.each(cs, function(c){\r
7457             if(isStart && c.flex){\r
7458                 cw = Math.floor(availWidth * (c.flex / totalFlex));\r
7459                 leftOver -= cw;\r
7460                 widths.push(cw);\r
7461             }\r
7462         }); \r
7463         \r
7464         if(this.pack == 'center'){\r
7465             l += extraWidth ? extraWidth / 2 : 0;\r
7466         }else if(this.pack == 'end'){\r
7467             l += extraWidth;\r
7468         }\r
7469         Ext.each(cs, function(c){\r
7470             cm = c.margins;\r
7471             l += cm.left;\r
7472             c.setPosition(l, t + cm.top);\r
7473             if(isStart && c.flex){\r
7474                 cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0));\r
7475                 if(isRestore){\r
7476                     restore.push(c.getHeight());\r
7477                 }\r
7478                 c.setSize(cw, availableHeight);\r
7479             }else{\r
7480                 cw = c.getWidth();\r
7481             }\r
7482             l += cw + cm.right;\r
7483         });\r
7484         \r
7485         idx = 0;\r
7486         Ext.each(cs, function(c){\r
7487             var cm = c.margins;\r
7488             if(this.align == 'stretch'){\r
7489                 c.setHeight((stretchHeight - (cm.top + cm.bottom)).constrain(\r
7490                     c.minHeight || 0, c.maxHeight || 1000000));\r
7491             }else if(this.align == 'stretchmax'){\r
7492                 c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain(\r
7493                     c.minHeight || 0, c.maxHeight || 1000000));\r
7494             }else{\r
7495                 if(this.align == 'middle'){\r
7496                     var diff = availableHeight - (c.getHeight() + cm.top + cm.bottom);\r
7497                     if(diff > 0){\r
7498                         c.setPosition(c.x, t + cm.top + (diff/2));\r
7499                     }\r
7500                 }\r
7501                 if(isStart && c.flex){\r
7502                     c.setHeight(restore[idx++]);\r
7503                 }\r
7504             }\r
7505         }, this);\r
7506     }\r
7507 \r
7508     /**\r
7509      * @property activeItem\r
7510      * @hide\r
7511      */\r
7512 });\r
7513 \r
7514 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
7515 /**\r
7516  * @class Ext.Viewport\r
7517  * @extends Ext.Container\r
7518  * <p>A specialized container representing the viewable application area (the browser viewport).</p>\r
7519  * <p>The Viewport renders itself to the document body, and automatically sizes itself to the size of\r
7520  * the browser viewport and manages window resizing. There may only be one Viewport created\r
7521  * in a page. Inner layouts are available by virtue of the fact that all {@link Ext.Panel Panel}s\r
7522  * added to the Viewport, either through its {@link #items}, or through the items, or the {@link #add}\r
7523  * method of any of its child Panels may themselves have a layout.</p>\r
7524  * <p>The Viewport does not provide scrolling, so child Panels within the Viewport should provide\r
7525  * for scrolling if needed using the {@link #autoScroll} config.</p>\r
7526  * <p>An example showing a classic application border layout:</p><pre><code>\r
7527 new Ext.Viewport({\r
7528     layout: 'border',\r
7529     items: [{\r
7530         region: 'north',\r
7531         html: '&lt;h1 class="x-panel-header">Page Title&lt;/h1>',\r
7532         autoHeight: true,\r
7533         border: false,\r
7534         margins: '0 0 5 0'\r
7535     }, {\r
7536         region: 'west',\r
7537         collapsible: true,\r
7538         title: 'Navigation',\r
7539         width: 200\r
7540         // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout} \r
7541     }, {\r
7542         region: 'south',\r
7543         title: 'Title for Panel',\r
7544         collapsible: true,\r
7545         html: 'Information goes here',\r
7546         split: true,\r
7547         height: 100,\r
7548         minHeight: 100\r
7549     }, {\r
7550         region: 'east',\r
7551         title: 'Title for the Grid Panel',\r
7552         collapsible: true,\r
7553         split: true,\r
7554         width: 200,\r
7555         xtype: 'grid',\r
7556         // remaining grid configuration not shown ...\r
7557         // notice that the GridPanel is added directly as the region\r
7558         // it is not "overnested" inside another Panel\r
7559     }, {\r
7560         region: 'center',\r
7561         xtype: 'tabpanel', // TabPanel itself has no title\r
7562         items: {\r
7563             title: 'Default Tab',\r
7564             html: 'The first tab\'s content. Others may be added dynamically'\r
7565         }\r
7566     }]\r
7567 });\r
7568 </code></pre>\r
7569  * @constructor\r
7570  * Create a new Viewport\r
7571  * @param {Object} config The config object\r
7572  * @xtype viewport\r
7573  */\r
7574 Ext.Viewport = Ext.extend(Ext.Container, {\r
7575         /*\r
7576          * Privatize config options which, if used, would interfere with the\r
7577          * correct operation of the Viewport as the sole manager of the\r
7578          * layout of the document body.\r
7579          */\r
7580     /**\r
7581      * @cfg {Mixed} applyTo @hide\r
7582          */\r
7583     /**\r
7584      * @cfg {Boolean} allowDomMove @hide\r
7585          */\r
7586     /**\r
7587      * @cfg {Boolean} hideParent @hide\r
7588          */\r
7589     /**\r
7590      * @cfg {Mixed} renderTo @hide\r
7591          */\r
7592     /**\r
7593      * @cfg {Boolean} hideParent @hide\r
7594          */\r
7595     /**\r
7596      * @cfg {Number} height @hide\r
7597          */\r
7598     /**\r
7599      * @cfg {Number} width @hide\r
7600          */\r
7601     /**\r
7602      * @cfg {Boolean} autoHeight @hide\r
7603          */\r
7604     /**\r
7605      * @cfg {Boolean} autoWidth @hide\r
7606          */\r
7607     /**\r
7608      * @cfg {Boolean} deferHeight @hide\r
7609          */\r
7610     /**\r
7611      * @cfg {Boolean} monitorResize @hide\r
7612          */\r
7613     initComponent : function() {\r
7614         Ext.Viewport.superclass.initComponent.call(this);\r
7615         document.getElementsByTagName('html')[0].className += ' x-viewport';\r
7616         this.el = Ext.getBody();\r
7617         this.el.setHeight = Ext.emptyFn;\r
7618         this.el.setWidth = Ext.emptyFn;\r
7619         this.el.setSize = Ext.emptyFn;\r
7620         this.el.dom.scroll = 'no';\r
7621         this.allowDomMove = false;\r
7622         this.autoWidth = true;\r
7623         this.autoHeight = true;\r
7624         Ext.EventManager.onWindowResize(this.fireResize, this);\r
7625         this.renderTo = this.el;\r
7626     },\r
7627 \r
7628     fireResize : function(w, h){\r
7629         this.fireEvent('resize', this, w, h, w, h);\r
7630     }\r
7631 });\r
7632 Ext.reg('viewport', Ext.Viewport);/**
7633  * @class Ext.Panel
7634  * @extends Ext.Container
7635  * <p>Panel is a container that has specific functionality and structural components that make
7636  * it the perfect building block for application-oriented user interfaces.</p>
7637  * <p>Panels are, by virtue of their inheritance from {@link Ext.Container}, capable
7638  * of being configured with a {@link Ext.Container#layout layout}, and containing child Components.</p>
7639  * <p>When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.Container#add adding} Components
7640  * to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether
7641  * 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
7642  * default, Panels use the {@link Ext.layout.ContainerLayout ContainerLayout} scheme. This simply renders
7643  * child components, appending them one after the other inside the Container, and <b>does not apply any sizing</b>
7644  * at all.</p>
7645  * <p>A Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate
7646  * {@link #header}, {@link #footer} and {@link #body} sections (see {@link #frame} for additional
7647  * information).</p>
7648  * <p>Panel also provides built-in {@link #collapsible expandable and collapsible behavior}, along with
7649  * a variety of {@link #tools prebuilt tool buttons} that can be wired up to provide other customized
7650  * behavior.  Panels can be easily dropped into any {@link Ext.Container Container} or layout, and the
7651  * layout and rendering pipeline is {@link Ext.Container#add completely managed by the framework}.</p>
7652  * @constructor
7653  * @param {Object} config The config object
7654  * @xtype panel
7655  */
7656 Ext.Panel = Ext.extend(Ext.Container, {
7657     /**
7658      * The Panel's header {@link Ext.Element Element}. Read-only.
7659      * <p>This Element is used to house the {@link #title} and {@link #tools}</p>
7660      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
7661      * @type Ext.Element
7662      * @property header
7663      */
7664     /**
7665      * The Panel's body {@link Ext.Element Element} which may be used to contain HTML content.
7666      * The content may be specified in the {@link #html} config, or it may be loaded using the
7667      * {@link autoLoad} config, or through the Panel's {@link #getUpdater Updater}. Read-only.
7668      * <p>If this is used to load visible HTML elements in either way, then
7669      * the Panel may not be used as a Layout for hosting nested Panels.</p>
7670      * <p>If this Panel is intended to be used as the host of a Layout (See {@link #layout}
7671      * then the body Element must not be loaded or changed - it is under the control
7672      * of the Panel's Layout.
7673      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
7674      * @type Ext.Element
7675      * @property body
7676      */
7677     /**
7678      * The Panel's bwrap {@link Ext.Element Element} used to contain other Panel elements
7679      * (tbar, body, bbar, footer). See {@link #bodyCfg}. Read-only.
7680      * @type Ext.Element
7681      * @property bwrap
7682      */
7683     /**
7684      * True if this panel is collapsed. Read-only.
7685      * @type Boolean
7686      * @property collapsed
7687      */
7688     /**
7689      * @cfg {Object} bodyCfg
7690      * <p>A {@link Ext.DomHelper DomHelper} element specification object may be specified for any
7691      * Panel Element.</p>
7692      * <p>By default, the Default element in the table below will be used for the html markup to
7693      * create a child element with the commensurate Default class name (<code>baseCls</code> will be
7694      * replaced by <code>{@link #baseCls}</code>):</p>
7695      * <pre>
7696      * Panel      Default  Default             Custom      Additional       Additional
7697      * Element    element  class               element     class            style
7698      * ========   ==========================   =========   ==============   ===========
7699      * {@link #header}     div      {@link #baseCls}+'-header'   {@link #headerCfg}   headerCssClass   headerStyle
7700      * {@link #bwrap}      div      {@link #baseCls}+'-bwrap'     {@link #bwrapCfg}    bwrapCssClass    bwrapStyle
7701      * + tbar     div      {@link #baseCls}+'-tbar'       {@link #tbarCfg}     tbarCssClass     tbarStyle
7702      * + {@link #body}     div      {@link #baseCls}+'-body'       {@link #bodyCfg}     {@link #bodyCssClass}     {@link #bodyStyle}
7703      * + bbar     div      {@link #baseCls}+'-bbar'       {@link #bbarCfg}     bbarCssClass     bbarStyle
7704      * + {@link #footer}   div      {@link #baseCls}+'-footer'   {@link #footerCfg}   footerCssClass   footerStyle
7705      * </pre>
7706      * <p>Configuring a Custom element may be used, for example, to force the {@link #body} Element
7707      * to use a different form of markup than is created by default. An example of this might be
7708      * to {@link Ext.Element#createChild create a child} Panel containing a custom content, such as
7709      * a header, or forcing centering of all Panel content by having the body be a &lt;center&gt;
7710      * element:</p>
7711      * <pre><code>
7712 new Ext.Panel({
7713     title: 'Message Title',
7714     renderTo: Ext.getBody(),
7715     width: 200, height: 130,
7716     <b>bodyCfg</b>: {
7717         tag: 'center',
7718         cls: 'x-panel-body',  // Default class not applied if Custom element specified
7719         html: 'Message'
7720     },
7721     footerCfg: {
7722         tag: 'h2',
7723         cls: 'x-panel-footer'        // same as the Default class
7724         html: 'footer html'
7725     },
7726     footerCssClass: 'custom-footer', // additional css class, see {@link Ext.element#addClass addClass}
7727     footerStyle:    'background-color:red' // see {@link #bodyStyle}
7728 });
7729      * </code></pre>
7730      * <p>The example above also explicitly creates a <code>{@link #footer}</code> with custom markup and
7731      * styling applied.</p>
7732      */
7733     /**
7734      * @cfg {Object} headerCfg
7735      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
7736      * of this Panel's {@link #header} Element.  See <code>{@link #bodyCfg}</code> also.</p>
7737      */
7738     /**
7739      * @cfg {Object} bwrapCfg
7740      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
7741      * of this Panel's {@link #bwrap} Element.  See <code>{@link #bodyCfg}</code> also.</p>
7742      */
7743     /**
7744      * @cfg {Object} tbarCfg
7745      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
7746      * of this Panel's {@link #tbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
7747      */
7748     /**
7749      * @cfg {Object} bbarCfg
7750      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
7751      * of this Panel's {@link #bbar} Element.  See <code>{@link #bodyCfg}</code> also.</p>
7752      */
7753     /**
7754      * @cfg {Object} footerCfg
7755      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
7756      * of this Panel's {@link #footer} Element.  See <code>{@link #bodyCfg}</code> also.</p>
7757      */
7758     /**
7759      * @cfg {Boolean} closable
7760      * Panels themselves do not directly support being closed, but some Panel subclasses do (like
7761      * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}.  Specify <code>true</code>
7762      * to enable closing in such situations. Defaults to <code>false</code>.
7763      */
7764     /**
7765      * The Panel's footer {@link Ext.Element Element}. Read-only.
7766      * <p>This Element is used to house the Panel's <code>{@link #buttons}</code> or <code>{@link #fbar}</code>.</p>
7767      * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
7768      * @type Ext.Element
7769      * @property footer
7770      */
7771     /**
7772      * @cfg {Mixed} applyTo
7773      * <p>The id of the node, a DOM node or an existing Element corresponding to a DIV that is already present in
7774      * the document that specifies some panel-specific structural markup.  When <code>applyTo</code> is used,
7775      * constituent parts of the panel can be specified by CSS class name within the main element, and the panel
7776      * will automatically create those components from that markup. Any required components not specified in the
7777      * markup will be autogenerated if necessary.</p>
7778      * <p>The following class names are supported (baseCls will be replaced by {@link #baseCls}):</p>
7779      * <ul><li>baseCls + '-header'</li>
7780      * <li>baseCls + '-header-text'</li>
7781      * <li>baseCls + '-bwrap'</li>
7782      * <li>baseCls + '-tbar'</li>
7783      * <li>baseCls + '-body'</li>
7784      * <li>baseCls + '-bbar'</li>
7785      * <li>baseCls + '-footer'</li></ul>
7786      * <p>Using this config, a call to render() is not required.  If applyTo is specified, any value passed for
7787      * {@link #renderTo} will be ignored and the target element's parent node will automatically be used as the
7788      * panel's container.</p>
7789      */
7790     /**
7791      * @cfg {Object/Array} tbar
7792      * <p>The top toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
7793      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
7794      * To access the top toolbar after render, use {@link #getTopToolbar}.</p>
7795      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
7796      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
7797      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
7798      * submission parameters are collected from the DOM tree.</p>
7799      */
7800     /**
7801      * @cfg {Object/Array} bbar
7802      * <p>The bottom toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
7803      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
7804      * To access the bottom toolbar after render, use {@link #getBottomToolbar}.</p>
7805      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
7806      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
7807      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
7808      * submission parameters are collected from the DOM tree.</p>
7809      */
7810     /** @cfg {Object/Array} fbar
7811      * <p>A {@link Ext.Toolbar Toolbar} object, a Toolbar config, or an array of
7812      * {@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>
7813      * <p>After render, the <code>fbar</code> property will be an {@link Ext.Toolbar Toolbar} instance.</p>
7814      * <p>If <code>{@link #buttons}</code> are specified, they will supersede the <code>fbar</code> configuration property.</p>
7815      * The Panel's <code>{@link #buttonAlign}</code> configuration affects the layout of these items, for example:
7816      * <pre><code>
7817 var w = new Ext.Window({
7818     height: 250,
7819     width: 500,
7820     bbar: new Ext.Toolbar({
7821         items: [{
7822             text: 'bbar Left'
7823         },'->',{
7824             text: 'bbar Right'
7825         }]
7826     }),
7827     {@link #buttonAlign}: 'left', // anything but 'center' or 'right' and you can use '-', and '->'
7828                                   // to control the alignment of fbar items
7829     fbar: [{
7830         text: 'fbar Left'
7831     },'->',{
7832         text: 'fbar Right'
7833     }]
7834 }).show();
7835      * </code></pre>
7836      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
7837      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
7838      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
7839      * submission parameters are collected from the DOM tree.</p>
7840      */
7841     /**
7842      * @cfg {Boolean} header
7843      * <code>true</code> to create the Panel's header element explicitly, <code>false</code> to skip creating
7844      * it.  If a <code>{@link #title}</code> is set the header will be created automatically, otherwise it will not.
7845      * If a <code>{@link #title}</code> is set but <code>header</code> is explicitly set to <code>false</code>, the header
7846      * will not be rendered.
7847      */
7848     /**
7849      * @cfg {Boolean} footer
7850      * <code>true</code> to create the footer element explicitly, false to skip creating it. The footer
7851      * will be created automatically if <code>{@link #buttons}</code> or a <code>{@link #fbar}</code> have
7852      * been configured.  See <code>{@link #bodyCfg}</code> for an example.
7853      */
7854     /**
7855      * @cfg {String} title
7856      * The title text to be used as innerHTML (html tags are accepted) to display in the panel
7857      * <code>{@link #header}</code> (defaults to ''). When a <code>title</code> is specified the
7858      * <code>{@link #header}</code> element will automatically be created and displayed unless
7859      * {@link #header} is explicitly set to <code>false</code>.  If you do not want to specify a
7860      * <code>title</code> at config time, but you may want one later, you must either specify a non-empty
7861      * <code>title</code> (a blank space ' ' will do) or <code>header:true</code> so that the container
7862      * element will get created.
7863      */
7864     /**
7865      * @cfg {Array} buttons
7866      * <code>buttons</code> will be used as <code>{@link Ext.Container#items items}</code> for the toolbar in
7867      * the footer (<code>{@link #fbar}</code>). Typically the value of this configuration property will be
7868      * an array of {@link Ext.Button}s or {@link Ext.Button} configuration objects.
7869      * If an item is configured with <code>minWidth</code> or the Panel is configured with <code>minButtonWidth</code>,
7870      * that width will be applied to the item.
7871      */
7872     /**
7873      * @cfg {Object/String/Function} autoLoad
7874      * A valid url spec according to the Updater {@link Ext.Updater#update} method.
7875      * If autoLoad is not null, the panel will attempt to load its contents
7876      * immediately upon render.<p>
7877      * The URL will become the default URL for this panel's {@link #body} element,
7878      * so it may be {@link Ext.Element#refresh refresh}ed at any time.</p>
7879      */
7880     /**
7881      * @cfg {Boolean} frame
7882      * <code>false</code> by default to render with plain 1px square borders. <code>true</code> to render with
7883      * 9 elements, complete with custom rounded corners (also see {@link Ext.Element#boxWrap}).
7884      * <p>The template generated for each condition is depicted below:</p><pre><code>
7885      *
7886 // frame = false
7887 &lt;div id="developer-specified-id-goes-here" class="x-panel">
7888
7889     &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:false)&lt;/span>&lt;/div>
7890
7891     &lt;div class="x-panel-bwrap">
7892         &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
7893     &lt;/div>
7894 &lt;/div>
7895
7896 // frame = true (create 9 elements)
7897 &lt;div id="developer-specified-id-goes-here" class="x-panel">
7898     &lt;div class="x-panel-tl">&lt;div class="x-panel-tr">&lt;div class="x-panel-tc">
7899         &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:true)&lt;/span>&lt;/div>
7900     &lt;/div>&lt;/div>&lt;/div>
7901
7902     &lt;div class="x-panel-bwrap">
7903         &lt;div class="x-panel-ml">&lt;div class="x-panel-mr">&lt;div class="x-panel-mc">
7904             &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
7905         &lt;/div>&lt;/div>&lt;/div>
7906
7907         &lt;div class="x-panel-bl">&lt;div class="x-panel-br">&lt;div class="x-panel-bc"/>
7908         &lt;/div>&lt;/div>&lt;/div>
7909 &lt;/div>
7910      * </code></pre>
7911      */
7912     /**
7913      * @cfg {Boolean} border
7914      * True to display the borders of the panel's body element, false to hide them (defaults to true).  By default,
7915      * the border is a 2px wide inset border, but this can be further altered by setting {@link #bodyBorder} to false.
7916      */
7917     /**
7918      * @cfg {Boolean} bodyBorder
7919      * True to display an interior border on the body element of the panel, false to hide it (defaults to true).
7920      * This only applies when {@link #border} == true.  If border == true and bodyBorder == false, the border will display
7921      * as a 1px wide inset border, giving the entire body element an inset appearance.
7922      */
7923     /**
7924      * @cfg {String/Object/Function} bodyCssClass
7925      * Additional css class selector to be applied to the {@link #body} element in the format expected by
7926      * {@link Ext.Element#addClass} (defaults to null). See {@link #bodyCfg}.
7927      */
7928     /**
7929      * @cfg {String/Object/Function} bodyStyle
7930      * Custom CSS styles to be applied to the {@link #body} element in the format expected by
7931      * {@link Ext.Element#applyStyles} (defaults to null). See {@link #bodyCfg}.
7932      */
7933     /**
7934      * @cfg {String} iconCls
7935      * The CSS class selector that specifies a background image to be used as the header icon (defaults to '').
7936      * <p>An example of specifying a custom icon class would be something like:
7937      * </p><pre><code>
7938 // specify the property in the config for the class:
7939      ...
7940      iconCls: 'my-icon'
7941
7942 // css class that specifies background image to be used as the icon image:
7943 .my-icon { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
7944 </code></pre>
7945      */
7946     /**
7947      * @cfg {Boolean} collapsible
7948      * True to make the panel collapsible and have the expand/collapse toggle button automatically rendered into
7949      * the header tool button area, false to keep the panel statically sized with no button (defaults to false).
7950      */
7951     /**
7952      * @cfg {Array} tools
7953      * An array of tool button configs to be added to the header tool area. When rendered, each tool is
7954      * stored as an {@link Ext.Element Element} referenced by a public property called <code><b></b>tools.<i>&lt;tool-type&gt;</i></code>
7955      * <p>Each tool config may contain the following properties:
7956      * <div class="mdetail-params"><ul>
7957      * <li><b>id</b> : String<div class="sub-desc"><b>Required.</b> The type
7958      * 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
7959      * resulting tool Element. Ext provides CSS rules, and an icon sprite containing images for the tool types listed below.
7960      * The developer may implement custom tools by supplying alternate CSS rules and background images:
7961      * <ul>
7962      * <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>
7963      * <div class="x-tool x-tool-close" style="float:left; margin-right:5;"> </div><div><code> close</code></div>
7964      * <div class="x-tool x-tool-minimize" style="float:left; margin-right:5;"> </div><div><code> minimize</code></div>
7965      * <div class="x-tool x-tool-maximize" style="float:left; margin-right:5;"> </div><div><code> maximize</code></div>
7966      * <div class="x-tool x-tool-restore" style="float:left; margin-right:5;"> </div><div><code> restore</code></div>
7967      * <div class="x-tool x-tool-gear" style="float:left; margin-right:5;"> </div><div><code> gear</code></div>
7968      * <div class="x-tool x-tool-pin" style="float:left; margin-right:5;"> </div><div><code> pin</code></div>
7969      * <div class="x-tool x-tool-unpin" style="float:left; margin-right:5;"> </div><div><code> unpin</code></div>
7970      * <div class="x-tool x-tool-right" style="float:left; margin-right:5;"> </div><div><code> right</code></div>
7971      * <div class="x-tool x-tool-left" style="float:left; margin-right:5;"> </div><div><code> left</code></div>
7972      * <div class="x-tool x-tool-up" style="float:left; margin-right:5;"> </div><div><code> up</code></div>
7973      * <div class="x-tool x-tool-down" style="float:left; margin-right:5;"> </div><div><code> down</code></div>
7974      * <div class="x-tool x-tool-refresh" style="float:left; margin-right:5;"> </div><div><code> refresh</code></div>
7975      * <div class="x-tool x-tool-minus" style="float:left; margin-right:5;"> </div><div><code> minus</code></div>
7976      * <div class="x-tool x-tool-plus" style="float:left; margin-right:5;"> </div><div><code> plus</code></div>
7977      * <div class="x-tool x-tool-help" style="float:left; margin-right:5;"> </div><div><code> help</code></div>
7978      * <div class="x-tool x-tool-search" style="float:left; margin-right:5;"> </div><div><code> search</code></div>
7979      * <div class="x-tool x-tool-save" style="float:left; margin-right:5;"> </div><div><code> save</code></div>
7980      * <div class="x-tool x-tool-print" style="float:left; margin-right:5;"> </div><div><code> print</code></div>
7981      * </ul></div></li>
7982      * <li><b>handler</b> : Function<div class="sub-desc"><b>Required.</b> The function to
7983      * call when clicked. Arguments passed are:<ul>
7984      * <li><b>event</b> : Ext.EventObject<div class="sub-desc">The click event.</div></li>
7985      * <li><b>toolEl</b> : Ext.Element<div class="sub-desc">The tool Element.</div></li>
7986      * <li><b>panel</b> : Ext.Panel<div class="sub-desc">The host Panel</div></li>
7987      * <li><b>tc</b> : Ext.Panel<div class="sub-desc">The tool configuration object</div></li>
7988      * </ul></div></li>
7989      * <li><b>stopEvent</b> : Boolean<div class="sub-desc">Defaults to true. Specify as false to allow click event to propagate.</div></li>
7990      * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the handler.</div></li>
7991      * <li><b>qtip</b> : String/Object<div class="sub-desc">A tip string, or
7992      * a config argument to {@link Ext.QuickTip#register}</div></li>
7993      * <li><b>hidden</b> : Boolean<div class="sub-desc">True to initially render hidden.</div></li>
7994      * <li><b>on</b> : Object<div class="sub-desc">A listener config object specifiying
7995      * event listeners in the format of an argument to {@link #addListener}</div></li>
7996      * </ul></div>
7997      * <p>Note that, apart from the toggle tool which is provided when a panel is collapsible, these
7998      * tools only provide the visual button. Any required functionality must be provided by adding
7999      * handlers that implement the necessary behavior.</p>
8000      * <p>Example usage:</p>
8001      * <pre><code>
8002 tools:[{
8003     id:'refresh',
8004     qtip: 'Refresh form Data',
8005     // hidden:true,
8006     handler: function(event, toolEl, panel){
8007         // refresh logic
8008     }
8009 },
8010 {
8011     id:'help',
8012     qtip: 'Get Help',
8013     handler: function(event, toolEl, panel){
8014         // whatever
8015     }
8016 }]
8017 </code></pre>
8018      * <p>For the custom id of <code>'help'</code> define two relevant css classes with a link to
8019      * a 15x15 image:</p>
8020      * <pre><code>
8021 .x-tool-help {background-image: url(images/help.png);}
8022 .x-tool-help-over {background-image: url(images/help_over.png);}
8023 // if using an image sprite:
8024 .x-tool-help {background-image: url(images/help.png) no-repeat 0 0;}
8025 .x-tool-help-over {background-position:-15px 0;}
8026 </code></pre>
8027      */
8028     /**
8029      * @cfg {Ext.Template/Ext.XTemplate} toolTemplate
8030      * <p>A Template used to create {@link #tools} in the {@link #header} Element. Defaults to:</p><pre><code>
8031 new Ext.Template('&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>')</code></pre>
8032      * <p>This may may be overridden to provide a custom DOM structure for tools based upon a more
8033      * complex XTemplate. The template's data is a single tool configuration object (Not the entire Array)
8034      * as specified in {@link #tools}.  In the following example an &lt;a> tag is used to provide a
8035      * visual indication when hovering over the tool:</p><pre><code>
8036 var win = new Ext.Window({
8037     tools: [{
8038         id: 'download',
8039         href: '/MyPdfDoc.pdf'
8040     }],
8041     toolTemplate: new Ext.XTemplate(
8042         '&lt;tpl if="id==\'download\'">',
8043             '&lt;a class="x-tool x-tool-pdf" href="{href}">&lt;/a>',
8044         '&lt;/tpl>',
8045         '&lt;tpl if="id!=\'download\'">',
8046             '&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>',
8047         '&lt;/tpl>'
8048     ),
8049     width:500,
8050     height:300,
8051     closeAction:'hide'
8052 });</code></pre>
8053      * <p>Note that the CSS class 'x-tool-pdf' should have an associated style rule which provides an
8054      * appropriate background image, something like:</p>
8055     <pre><code>
8056     a.x-tool-pdf {background-image: url(../shared/extjs/images/pdf.gif)!important;}
8057     </code></pre>
8058      */
8059     /**
8060      * @cfg {Boolean} hideCollapseTool
8061      * <code>true</code> to hide the expand/collapse toggle button when <code>{@link #collapsible} == true</code>,
8062      * <code>false</code> to display it (defaults to <code>false</code>).
8063      */
8064     /**
8065      * @cfg {Boolean} titleCollapse
8066      * <code>true</code> to allow expanding and collapsing the panel (when <code>{@link #collapsible} = true</code>)
8067      * by clicking anywhere in the header bar, <code>false</code>) to allow it only by clicking to tool button
8068      * (defaults to <code>false</code>)). If this panel is a child item of a border layout also see the
8069      * {@link Ext.layout.BorderLayout.Region BorderLayout.Region}
8070      * <code>{@link Ext.layout.BorderLayout.Region#floatable floatable}</code> config option.
8071      */
8072     /**
8073      * @cfg {Boolean} autoScroll
8074      * <code>true</code> to use overflow:'auto' on the panel's body element and show scroll bars automatically when
8075      * necessary, <code>false</code> to clip any overflowing content (defaults to <code>false</code>).
8076      */
8077     /**
8078      * @cfg {Mixed} floating
8079      * <p>This property is used to configure the underlying {@link Ext.Layer}. Acceptable values for this
8080      * configuration property are:</p><div class="mdetail-params"><ul>
8081      * <li><b><code>false</code></b> : <b>Default.</b><div class="sub-desc">Display the panel inline where it is
8082      * rendered.</div></li>
8083      * <li><b><code>true</code></b> : <div class="sub-desc">Float the panel (absolute position it with automatic
8084      * shimming and shadow).<ul>
8085      * <div class="sub-desc">Setting floating to true will create an Ext.Layer for this panel and display the
8086      * panel at negative offsets so that it is hidden.</div>
8087      * <div class="sub-desc">Since the panel will be absolute positioned, the position must be set explicitly
8088      * <i>after</i> render (e.g., <code>myPanel.setPosition(100,100);</code>).</div>
8089      * <div class="sub-desc"><b>Note</b>: when floating a panel you should always assign a fixed width,
8090      * otherwise it will be auto width and will expand to fill to the right edge of the viewport.</div>
8091      * </ul></div></li>
8092      * <li><b><code>{@link Ext.Layer object}</code></b> : <div class="sub-desc">The specified object will be used
8093      * as the configuration object for the {@link Ext.Layer} that will be created.</div></li>
8094      * </ul></div>
8095      */
8096     /**
8097      * @cfg {Boolean/String} shadow
8098      * <code>true</code> (or a valid Ext.Shadow {@link Ext.Shadow#mode} value) to display a shadow behind the
8099      * panel, <code>false</code> to display no shadow (defaults to <code>'sides'</code>).  Note that this option
8100      * only applies when <code>{@link #floating} = true</code>.
8101      */
8102     /**
8103      * @cfg {Number} shadowOffset
8104      * The number of pixels to offset the shadow if displayed (defaults to <code>4</code>). Note that this
8105      * option only applies when <code>{@link #floating} = true</code>.
8106      */
8107     /**
8108      * @cfg {Boolean} shim
8109      * <code>false</code> to disable the iframe shim in browsers which need one (defaults to <code>true</code>).
8110      * Note that this option only applies when <code>{@link #floating} = true</code>.
8111      */
8112     /**
8113      * @cfg {String/Object} html
8114      * An HTML fragment, or a {@link Ext.DomHelper DomHelper} specification to use as the panel's body
8115      * content (defaults to ''). The HTML content is added by the Panel's {@link #afterRender} method,
8116      * and so the document will not contain this HTML at the time the {@link #render} event is fired.
8117      * This content is inserted into the body <i>before</i> any configured {@link #contentEl} is appended.
8118      */
8119     /**
8120      * @cfg {String} contentEl
8121      * <p>Optional. Specify an existing HTML element, or the <code>id</code> of an existing HTML element to use as this Panel's
8122      * <code><b>{@link #body}</b></code> content.</p>
8123      * <ul>
8124      * <li><b>Description</b> :
8125      * <div class="sub-desc">This config option is used to take an existing HTML element and place it in the body
8126      * of a new panel (it simply moves the specified DOM element into the body element of the Panel
8127      * <i>after the Panel is rendered</i> to use as the content (it is not going to be the actual panel itself).</div></li>
8128      * <li><b>Notes</b> :
8129      * <div class="sub-desc">The specified HTML element is appended to the Panel's {@link #body} Element by the
8130      * Panel's <code>afterRender</code> method <i>after any configured {@link #html HTML} has
8131      * been inserted</i>, and so the document will not contain this element at the time the
8132      * {@link #render} event is fired.</div>
8133      * <div class="sub-desc">The specified HTML element used will not participate in any <code><b>{@link Ext.Container#layout layout}</b></code>
8134      * scheme that the Panel may use. It is just HTML. Layouts operate on child <code><b>{@link Ext.Container#items items}</b></code>.</div>
8135      * <div class="sub-desc">Add either the <code>x-hidden</code> or the <code>x-hide-display</code> CSS class to
8136      * prevent a brief flicker of the content before it is rendered to the panel.</div></li>
8137      * </ul>
8138      */
8139     /**
8140      * @cfg {Object/Array} keys
8141      * A {@link Ext.KeyMap} config object (in the format expected by {@link Ext.KeyMap#addBinding}
8142      * used to assign custom key handling to this panel (defaults to <code>null</code>).
8143      */
8144     /**
8145      * @cfg {Boolean/Object} draggable
8146      * <p><code>true</code> to enable dragging of this Panel (defaults to <code>false</code>).</p>
8147      * <p>For custom drag/drop implementations, an <b>Ext.Panel.DD</b> config could also be passed
8148      * in this config instead of <code>true</code>. Ext.Panel.DD is an internal, undocumented class which
8149      * moves a proxy Element around in place of the Panel's element, but provides no other behaviour
8150      * during dragging or on drop. It is a subclass of {@link Ext.dd.DragSource}, so behaviour may be
8151      * added by implementing the interface methods of {@link Ext.dd.DragDrop} e.g.:
8152      * <pre><code>
8153 new Ext.Panel({
8154     title: 'Drag me',
8155     x: 100,
8156     y: 100,
8157     renderTo: Ext.getBody(),
8158     floating: true,
8159     frame: true,
8160     width: 400,
8161     height: 200,
8162     draggable: {
8163 //      Config option of Ext.Panel.DD class.
8164 //      It&#39;s a floating Panel, so do not show a placeholder proxy in the original position.
8165         insertProxy: false,
8166
8167 //      Called for each mousemove event while dragging the DD object.
8168         onDrag : function(e){
8169 //          Record the x,y position of the drag proxy so that we can
8170 //          position the Panel at end of drag.
8171             var pel = this.proxy.getEl();
8172             this.x = pel.getLeft(true);
8173             this.y = pel.getTop(true);
8174
8175 //          Keep the Shadow aligned if there is one.
8176             var s = this.panel.getEl().shadow;
8177             if (s) {
8178                 s.realign(this.x, this.y, pel.getWidth(), pel.getHeight());
8179             }
8180         },
8181
8182 //      Called on the mouseup event.
8183         endDrag : function(e){
8184             this.panel.setPosition(this.x, this.y);
8185         }
8186     }
8187 }).show();
8188 </code></pre>
8189      */
8190     /**
8191      * @cfg {Boolean} disabled
8192      * Render this panel disabled (default is <code>false</code>). An important note when using the disabled
8193      * config on panels is that IE will often fail to initialize the disabled mask element correectly if
8194      * the panel's layout has not yet completed by the time the Panel is disabled during the render process.
8195      * If you experience this issue, you may need to instead use the {@link #afterlayout} event to initialize
8196      * the disabled state:
8197      * <pre><code>
8198 new Ext.Panel({
8199     ...
8200     listeners: {
8201         'afterlayout': {
8202             fn: function(p){
8203                 p.disable();
8204             },
8205             single: true // important, as many layouts can occur
8206         }
8207     }
8208 });
8209 </code></pre>
8210      */
8211     /**
8212      * @cfg {Boolean} autoHeight
8213      * <code>true</code> to use height:'auto', <code>false</code> to use fixed height (defaults to <code>false</code>).
8214      * <b>Note</b>: Setting <code>autoHeight: true</code> means that the browser will manage the panel's height
8215      * based on its contents, and that Ext will not manage it at all. If the panel is within a layout that
8216      * manages dimensions (<code>fit</code>, <code>border</code>, etc.) then setting <code>autoHeight: true</code>
8217      * can cause issues with scrolling and will not generally work as expected since the panel will take
8218      * on the height of its contents rather than the height required by the Ext layout.
8219      */
8220
8221
8222     /**
8223      * @cfg {String} baseCls
8224      * The base CSS class to apply to this panel's element (defaults to <code>'x-panel'</code>).
8225      * <p>Another option available by default is to specify <code>'x-plain'</code> which strips all styling
8226      * except for required attributes for Ext layouts to function (e.g. overflow:hidden).
8227      * See <code>{@link #unstyled}</code> also.</p>
8228      */
8229     baseCls : 'x-panel',
8230     /**
8231      * @cfg {String} collapsedCls
8232      * A CSS class to add to the panel's element after it has been collapsed (defaults to
8233      * <code>'x-panel-collapsed'</code>).
8234      */
8235     collapsedCls : 'x-panel-collapsed',
8236     /**
8237      * @cfg {Boolean} maskDisabled
8238      * <code>true</code> to mask the panel when it is {@link #disabled}, <code>false</code> to not mask it (defaults
8239      * to <code>true</code>).  Either way, the panel will always tell its contained elements to disable themselves
8240      * when it is disabled, but masking the panel can provide an additional visual cue that the panel is
8241      * disabled.
8242      */
8243     maskDisabled : true,
8244     /**
8245      * @cfg {Boolean} animCollapse
8246      * <code>true</code> to animate the transition when the panel is collapsed, <code>false</code> to skip the
8247      * animation (defaults to <code>true</code> if the {@link Ext.Fx} class is available, otherwise <code>false</code>).
8248      */
8249     animCollapse : Ext.enableFx,
8250     /**
8251      * @cfg {Boolean} headerAsText
8252      * <code>true</code> to display the panel <code>{@link #title}</code> in the <code>{@link #header}</code>,
8253      * <code>false</code> to hide it (defaults to <code>true</code>).
8254      */
8255     headerAsText : true,
8256     /**
8257      * @cfg {String} buttonAlign
8258      * The alignment of any {@link #buttons} added to this panel.  Valid values are <code>'right'</code>,
8259      * <code>'left'</code> and <code>'center'</code> (defaults to <code>'right'</code>).
8260      */
8261     buttonAlign : 'right',
8262     /**
8263      * @cfg {Boolean} collapsed
8264      * <code>true</code> to render the panel collapsed, <code>false</code> to render it expanded (defaults to
8265      * <code>false</code>).
8266      */
8267     collapsed : false,
8268     /**
8269      * @cfg {Boolean} collapseFirst
8270      * <code>true</code> to make sure the collapse/expand toggle button always renders first (to the left of)
8271      * any other tools in the panel's title bar, <code>false</code> to render it last (defaults to <code>true</code>).
8272      */
8273     collapseFirst : true,
8274     /**
8275      * @cfg {Number} minButtonWidth
8276      * Minimum width in pixels of all {@link #buttons} in this panel (defaults to <code>75</code>)
8277      */
8278     minButtonWidth : 75,
8279     /**
8280      * @cfg {Boolean} unstyled
8281      * Overrides the <code>{@link #baseCls}</code> setting to <code>{@link #baseCls} = 'x-plain'</code> which renders
8282      * the panel unstyled except for required attributes for Ext layouts to function (e.g. overflow:hidden).
8283      */
8284     /**
8285      * @cfg {String} elements
8286      * A comma-delimited list of panel elements to initialize when the panel is rendered.  Normally, this list will be
8287      * generated automatically based on the items added to the panel at config time, but sometimes it might be useful to
8288      * make sure a structural element is rendered even if not specified at config time (for example, you may want
8289      * to add a button or toolbar dynamically after the panel has been rendered).  Adding those elements to this
8290      * list will allocate the required placeholders in the panel when it is rendered.  Valid values are<div class="mdetail-params"><ul>
8291      * <li><code>header</code></li>
8292      * <li><code>tbar</code> (top bar)</li>
8293      * <li><code>body</code></li>
8294      * <li><code>bbar</code> (bottom bar)</li>
8295      * <li><code>footer</code></li>
8296      * </ul></div>
8297      * Defaults to '<code>body</code>'.
8298      */
8299     elements : 'body',
8300     /**
8301      * @cfg {Boolean} preventBodyReset
8302      * Defaults to <code>false</code>.  When set to <code>true</code>, an extra css class <code>'x-panel-normal'</code>
8303      * will be added to the panel's element, effectively applying css styles suggested by the W3C
8304      * (see http://www.w3.org/TR/CSS21/sample.html) to the Panel's <b>body</b> element (not the header,
8305      * footer, etc.).
8306      */
8307     preventBodyReset : false,
8308     
8309     /** @cfg {String} resizeEvent
8310      * The event to listen to for resizing in layouts. Defaults to <tt>'bodyresize'</tt>.
8311      */
8312     resizeEvent: 'bodyresize',
8313
8314     // protected - these could be used to customize the behavior of the window,
8315     // but changing them would not be useful without further mofifications and
8316     // could lead to unexpected or undesirable results.
8317     toolTarget : 'header',
8318     collapseEl : 'bwrap',
8319     slideAnchor : 't',
8320     disabledClass : '',
8321
8322     // private, notify box this class will handle heights
8323     deferHeight : true,
8324     // private
8325     expandDefaults: {
8326         duration : 0.25
8327     },
8328     // private
8329     collapseDefaults : {
8330         duration : 0.25
8331     },
8332
8333     // private
8334     initComponent : function(){
8335         Ext.Panel.superclass.initComponent.call(this);
8336
8337         this.addEvents(
8338             /**
8339              * @event bodyresize
8340              * Fires after the Panel has been resized.
8341              * @param {Ext.Panel} p the Panel which has been resized.
8342              * @param {Number} width The Panel's new width.
8343              * @param {Number} height The Panel's new height.
8344              */
8345             'bodyresize',
8346             /**
8347              * @event titlechange
8348              * Fires after the Panel title has been {@link #title set} or {@link #setTitle changed}.
8349              * @param {Ext.Panel} p the Panel which has had its title changed.
8350              * @param {String} The new title.
8351              */
8352             'titlechange',
8353             /**
8354              * @event iconchange
8355              * Fires after the Panel icon class has been {@link #iconCls set} or {@link #setIconClass changed}.
8356              * @param {Ext.Panel} p the Panel which has had its {@link #iconCls icon class} changed.
8357              * @param {String} The new icon class.
8358              * @param {String} The old icon class.
8359              */
8360             'iconchange',
8361             /**
8362              * @event collapse
8363              * Fires after the Panel has been collapsed.
8364              * @param {Ext.Panel} p the Panel that has been collapsed.
8365              */
8366             'collapse',
8367             /**
8368              * @event expand
8369              * Fires after the Panel has been expanded.
8370              * @param {Ext.Panel} p The Panel that has been expanded.
8371              */
8372             'expand',
8373             /**
8374              * @event beforecollapse
8375              * Fires before the Panel is collapsed.  A handler can return false to cancel the collapse.
8376              * @param {Ext.Panel} p the Panel being collapsed.
8377              * @param {Boolean} animate True if the collapse is animated, else false.
8378              */
8379             'beforecollapse',
8380             /**
8381              * @event beforeexpand
8382              * Fires before the Panel is expanded.  A handler can return false to cancel the expand.
8383              * @param {Ext.Panel} p The Panel being expanded.
8384              * @param {Boolean} animate True if the expand is animated, else false.
8385              */
8386             'beforeexpand',
8387             /**
8388              * @event beforeclose
8389              * Fires before the Panel is closed.  Note that Panels do not directly support being closed, but some
8390              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.  This event only
8391              * applies to such subclasses.
8392              * A handler can return false to cancel the close.
8393              * @param {Ext.Panel} p The Panel being closed.
8394              */
8395             'beforeclose',
8396             /**
8397              * @event close
8398              * Fires after the Panel is closed.  Note that Panels do not directly support being closed, but some
8399              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.
8400              * @param {Ext.Panel} p The Panel that has been closed.
8401              */
8402             'close',
8403             /**
8404              * @event activate
8405              * Fires after the Panel has been visually activated.
8406              * Note that Panels do not directly support being activated, but some Panel subclasses
8407              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
8408              * activate and deactivate events under the control of the TabPanel.
8409              * @param {Ext.Panel} p The Panel that has been activated.
8410              */
8411             'activate',
8412             /**
8413              * @event deactivate
8414              * Fires after the Panel has been visually deactivated.
8415              * Note that Panels do not directly support being deactivated, but some Panel subclasses
8416              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
8417              * activate and deactivate events under the control of the TabPanel.
8418              * @param {Ext.Panel} p The Panel that has been deactivated.
8419              */
8420             'deactivate'
8421         );
8422
8423         if(this.unstyled){
8424             this.baseCls = 'x-plain';
8425         }
8426
8427         // shortcuts
8428         if(this.tbar){
8429             this.elements += ',tbar';
8430             if(Ext.isObject(this.tbar)){
8431                 this.topToolbar = this.tbar;
8432             }
8433             delete this.tbar;
8434         }
8435         if(this.bbar){
8436             this.elements += ',bbar';
8437             if(Ext.isObject(this.bbar)){
8438                 this.bottomToolbar = this.bbar;
8439             }
8440             delete this.bbar;
8441         }
8442
8443         if(this.header === true){
8444             this.elements += ',header';
8445             delete this.header;
8446         }else if(this.headerCfg || (this.title && this.header !== false)){
8447             this.elements += ',header';
8448         }
8449
8450         if(this.footerCfg || this.footer === true){
8451             this.elements += ',footer';
8452             delete this.footer;
8453         }
8454
8455         if(this.buttons){
8456             this.elements += ',footer';
8457             var btns = this.buttons;
8458             /**
8459              * This Panel's Array of buttons as created from the <code>{@link #buttons}</code>
8460              * config property. Read only.
8461              * @type Array
8462              * @property buttons
8463              */
8464             this.buttons = [];
8465             Ext.each(btns, function(btn){
8466                 if(btn.render){ // button instance
8467                     this.buttons.push(btn);
8468                 }else if(btn.xtype){
8469                     this.buttons.push(Ext.create(btn, 'button'));
8470                 }else{
8471                     this.addButton(btn);
8472                 }
8473             }, this);
8474         }
8475         if(this.fbar){
8476             this.elements += ',footer';
8477         }
8478         if(this.autoLoad){
8479             this.on('render', this.doAutoLoad, this, {delay:10});
8480         }
8481     },
8482
8483     // private
8484     createElement : function(name, pnode){
8485         if(this[name]){
8486             pnode.appendChild(this[name].dom);
8487             return;
8488         }
8489
8490         if(name === 'bwrap' || this.elements.indexOf(name) != -1){
8491             if(this[name+'Cfg']){
8492                 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
8493             }else{
8494                 var el = document.createElement('div');
8495                 el.className = this[name+'Cls'];
8496                 this[name] = Ext.get(pnode.appendChild(el));
8497             }
8498             if(this[name+'CssClass']){
8499                 this[name].addClass(this[name+'CssClass']);
8500             }
8501             if(this[name+'Style']){
8502                 this[name].applyStyles(this[name+'Style']);
8503             }
8504         }
8505     },
8506
8507     // private
8508     onRender : function(ct, position){
8509         Ext.Panel.superclass.onRender.call(this, ct, position);
8510         this.createClasses();
8511
8512         var el = this.el,
8513             d = el.dom,
8514             bw,
8515             ts;
8516             
8517             
8518         if(this.collapsible && !this.hideCollapseTool){
8519             this.tools = this.tools ? this.tools.slice(0) : [];
8520             this.tools[this.collapseFirst?'unshift':'push']({
8521                 id: 'toggle',
8522                 handler : this.toggleCollapse,
8523                 scope: this
8524             });   
8525         }
8526         
8527         if(this.tools){
8528             ts = this.tools;
8529             this.elements += (this.header !== false) ? ',header' : '';
8530         }
8531         this.tools = {};
8532             
8533         el.addClass(this.baseCls);
8534         if(d.firstChild){ // existing markup
8535             this.header = el.down('.'+this.headerCls);
8536             this.bwrap = el.down('.'+this.bwrapCls);
8537             var cp = this.bwrap ? this.bwrap : el;
8538             this.tbar = cp.down('.'+this.tbarCls);
8539             this.body = cp.down('.'+this.bodyCls);
8540             this.bbar = cp.down('.'+this.bbarCls);
8541             this.footer = cp.down('.'+this.footerCls);
8542             this.fromMarkup = true;
8543         }
8544         if (this.preventBodyReset === true) {
8545             el.addClass('x-panel-reset');
8546         }
8547         if(this.cls){
8548             el.addClass(this.cls);
8549         }
8550
8551         if(this.buttons){
8552             this.elements += ',footer';
8553         }
8554
8555         // This block allows for maximum flexibility and performance when using existing markup
8556
8557         // framing requires special markup
8558         if(this.frame){
8559             el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
8560
8561             this.createElement('header', d.firstChild.firstChild.firstChild);
8562             this.createElement('bwrap', d);
8563
8564             // append the mid and bottom frame to the bwrap
8565             bw = this.bwrap.dom;
8566             var ml = d.childNodes[1], bl = d.childNodes[2];
8567             bw.appendChild(ml);
8568             bw.appendChild(bl);
8569
8570             var mc = bw.firstChild.firstChild.firstChild;
8571             this.createElement('tbar', mc);
8572             this.createElement('body', mc);
8573             this.createElement('bbar', mc);
8574             this.createElement('footer', bw.lastChild.firstChild.firstChild);
8575
8576             if(!this.footer){
8577                 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
8578             }
8579             /*
8580              * Store a reference to this element so:
8581              * a) We aren't looking it up all the time
8582              * b) The last element is reported incorrectly when using a loadmask
8583              */
8584             this.ft = Ext.get(this.bwrap.dom.lastChild);
8585             this.mc = Ext.get(this.bwrap.dom.firstChild.firstChild.firstChild);
8586         }else{
8587             this.createElement('header', d);
8588             this.createElement('bwrap', d);
8589
8590             // append the mid and bottom frame to the bwrap
8591             bw = this.bwrap.dom;
8592             this.createElement('tbar', bw);
8593             this.createElement('body', bw);
8594             this.createElement('bbar', bw);
8595             this.createElement('footer', bw);
8596
8597             if(!this.header){
8598                 this.body.addClass(this.bodyCls + '-noheader');
8599                 if(this.tbar){
8600                     this.tbar.addClass(this.tbarCls + '-noheader');
8601                 }
8602             }
8603         }
8604
8605         if(Ext.isDefined(this.padding)){
8606             this.body.setStyle('padding', this.body.addUnits(this.padding));
8607         }
8608
8609         if(this.border === false){
8610             this.el.addClass(this.baseCls + '-noborder');
8611             this.body.addClass(this.bodyCls + '-noborder');
8612             if(this.header){
8613                 this.header.addClass(this.headerCls + '-noborder');
8614             }
8615             if(this.footer){
8616                 this.footer.addClass(this.footerCls + '-noborder');
8617             }
8618             if(this.tbar){
8619                 this.tbar.addClass(this.tbarCls + '-noborder');
8620             }
8621             if(this.bbar){
8622                 this.bbar.addClass(this.bbarCls + '-noborder');
8623             }
8624         }
8625
8626         if(this.bodyBorder === false){
8627            this.body.addClass(this.bodyCls + '-noborder');
8628         }
8629
8630         this.bwrap.enableDisplayMode('block');
8631
8632         if(this.header){
8633             this.header.unselectable();
8634
8635             // for tools, we need to wrap any existing header markup
8636             if(this.headerAsText){
8637                 this.header.dom.innerHTML =
8638                     '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
8639
8640                 if(this.iconCls){
8641                     this.setIconClass(this.iconCls);
8642                 }
8643             }
8644         }
8645
8646         if(this.floating){
8647             this.makeFloating(this.floating);
8648         }
8649
8650         if(this.collapsible && this.titleCollapse && this.header){
8651             this.mon(this.header, 'click', this.toggleCollapse, this);
8652             this.header.setStyle('cursor', 'pointer');
8653         }
8654         if(ts){
8655             this.addTool.apply(this, ts);
8656         }
8657
8658         if(this.buttons && this.buttons.length > 0){
8659             this.fbar = new Ext.Toolbar({
8660                 items: this.buttons,
8661                 toolbarCls: 'x-panel-fbar'
8662             });
8663         }
8664         this.toolbars = [];
8665         if(this.fbar){
8666             this.fbar = Ext.create(this.fbar, 'toolbar');
8667             this.fbar.enableOverflow = false;
8668             if(this.fbar.items){
8669                 this.fbar.items.each(function(c){
8670                     c.minWidth = c.minWidth || this.minButtonWidth;
8671                 }, this);
8672             }
8673             this.fbar.toolbarCls = 'x-panel-fbar';
8674
8675             var bct = this.footer.createChild({cls: 'x-panel-btns x-panel-btns-'+this.buttonAlign});
8676             this.fbar.ownerCt = this;
8677             this.fbar.render(bct);
8678             bct.createChild({cls:'x-clear'});
8679             this.toolbars.push(this.fbar);
8680         }
8681
8682         if(this.tbar && this.topToolbar){
8683             if(Ext.isArray(this.topToolbar)){
8684                 this.topToolbar = new Ext.Toolbar(this.topToolbar);
8685             }else if(!this.topToolbar.events){
8686                 this.topToolbar = Ext.create(this.topToolbar, 'toolbar');
8687             }
8688             this.topToolbar.ownerCt = this;
8689             this.topToolbar.render(this.tbar);
8690             this.toolbars.push(this.topToolbar);
8691         }
8692         if(this.bbar && this.bottomToolbar){
8693             if(Ext.isArray(this.bottomToolbar)){
8694                 this.bottomToolbar = new Ext.Toolbar(this.bottomToolbar);
8695             }else if(!this.bottomToolbar.events){
8696                 this.bottomToolbar = Ext.create(this.bottomToolbar, 'toolbar');
8697             }
8698             this.bottomToolbar.ownerCt = this;
8699             this.bottomToolbar.render(this.bbar);
8700             this.toolbars.push(this.bottomToolbar);
8701         }
8702     },
8703
8704     /**
8705      * Sets the CSS class that provides the icon image for this panel.  This method will replace any existing
8706      * icon class if one has already been set and fire the {@link #iconchange} event after completion.
8707      * @param {String} cls The new CSS class name
8708      */
8709     setIconClass : function(cls){
8710         var old = this.iconCls;
8711         this.iconCls = cls;
8712         if(this.rendered && this.header){
8713             if(this.frame){
8714                 this.header.addClass('x-panel-icon');
8715                 this.header.replaceClass(old, this.iconCls);
8716             }else{
8717                 var hd = this.header,
8718                     img = hd.child('img.x-panel-inline-icon');
8719                 if(img){
8720                     Ext.fly(img).replaceClass(old, this.iconCls);
8721                 }else{
8722                     Ext.DomHelper.insertBefore(hd.dom.firstChild, {
8723                         tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
8724                     });
8725                  }
8726             }
8727         }
8728         this.fireEvent('iconchange', this, cls, old);
8729     },
8730
8731     // private
8732     makeFloating : function(cfg){
8733         this.floating = true;
8734         this.el = new Ext.Layer(
8735             Ext.isObject(cfg) ? cfg : {
8736                 shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
8737                 shadowOffset: this.shadowOffset,
8738                 constrain:false,
8739                 shim: this.shim === false ? false : undefined
8740             }, this.el
8741         );
8742     },
8743
8744     /**
8745      * Returns the {@link Ext.Toolbar toolbar} from the top (<code>{@link #tbar}</code>) section of the panel.
8746      * @return {Ext.Toolbar} The toolbar
8747      */
8748     getTopToolbar : function(){
8749         return this.topToolbar;
8750     },
8751
8752     /**
8753      * Returns the {@link Ext.Toolbar toolbar} from the bottom (<code>{@link #bbar}</code>) section of the panel.
8754      * @return {Ext.Toolbar} The toolbar
8755      */
8756     getBottomToolbar : function(){
8757         return this.bottomToolbar;
8758     },
8759
8760     /**
8761      * Adds a button to this panel.  Note that this method must be called prior to rendering.  The preferred
8762      * approach is to add buttons via the {@link #buttons} config.
8763      * @param {String/Object} config A valid {@link Ext.Button} config.  A string will become the text for a default
8764      * button config, an object will be treated as a button config object.
8765      * @param {Function} handler The function to be called on button {@link Ext.Button#click}
8766      * @param {Object} scope The scope to use for the button handler function
8767      * @return {Ext.Button} The button that was added
8768      */
8769     addButton : function(config, handler, scope){
8770         var bc = {
8771             handler: handler,
8772             scope: scope,
8773             minWidth: this.minButtonWidth,
8774             hideParent:true
8775         };
8776         if(Ext.isString(config)){
8777             bc.text = config;
8778         }else{
8779             Ext.apply(bc, config);
8780         }
8781         var btn = new Ext.Button(bc);
8782         if(!this.buttons){
8783             this.buttons = [];
8784         }
8785         this.buttons.push(btn);
8786         return btn;
8787     },
8788
8789     // private
8790     addTool : function(){
8791         if(!this.rendered){
8792             if(!this.tools){
8793                 this.tools = [];
8794             }
8795             Ext.each(arguments, function(arg){
8796                 this.tools.push(arg)
8797             }, this);
8798             return;
8799         }
8800          // nowhere to render tools!
8801         if(!this[this.toolTarget]){
8802             return;
8803         }
8804         if(!this.toolTemplate){
8805             // initialize the global tool template on first use
8806             var tt = new Ext.Template(
8807                  '<div class="x-tool x-tool-{id}">&#160;</div>'
8808             );
8809             tt.disableFormats = true;
8810             tt.compile();
8811             Ext.Panel.prototype.toolTemplate = tt;
8812         }
8813         for(var i = 0, a = arguments, len = a.length; i < len; i++) {
8814             var tc = a[i];
8815             if(!this.tools[tc.id]){
8816                 var overCls = 'x-tool-'+tc.id+'-over';
8817                 var t = this.toolTemplate.insertFirst((tc.align !== 'left') ? this[this.toolTarget] : this[this.toolTarget].child('span'), tc, true);
8818                 this.tools[tc.id] = t;
8819                 t.enableDisplayMode('block');
8820                 this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
8821                 if(tc.on){
8822                     this.mon(t, tc.on);
8823                 }
8824                 if(tc.hidden){
8825                     t.hide();
8826                 }
8827                 if(tc.qtip){
8828                     if(Ext.isObject(tc.qtip)){
8829                         Ext.QuickTips.register(Ext.apply({
8830                               target: t.id
8831                         }, tc.qtip));
8832                     } else {
8833                         t.dom.qtip = tc.qtip;
8834                     }
8835                 }
8836                 t.addClassOnOver(overCls);
8837             }
8838         }
8839     },
8840
8841     onLayout : function(shallow, force){
8842         if(this.hasLayout && this.toolbars.length > 0){
8843             Ext.each(this.toolbars, function(tb){
8844                 tb.doLayout(undefined, force);
8845             });
8846             this.syncHeight();
8847         }
8848     },
8849
8850     syncHeight : function(){
8851         var h = this.toolbarHeight,
8852                 bd = this.body,
8853                 lsh = this.lastSize.height;
8854                 
8855         if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
8856             return;
8857         }
8858             
8859            
8860         if(h != this.getToolbarHeight()){
8861             h = Math.max(0, this.adjustBodyHeight(lsh - this.getFrameHeight()));
8862             bd.setHeight(h);
8863             sz = bd.getSize();
8864             this.toolbarHeight = this.getToolbarHeight();
8865             this.onBodyResize(sz.width, sz.height);
8866         }
8867     },
8868
8869     // private
8870     onShow : function(){
8871         if(this.floating){
8872             return this.el.show();
8873         }
8874         Ext.Panel.superclass.onShow.call(this);
8875     },
8876
8877     // private
8878     onHide : function(){
8879         if(this.floating){
8880             return this.el.hide();
8881         }
8882         Ext.Panel.superclass.onHide.call(this);
8883     },
8884
8885     // private
8886     createToolHandler : function(t, tc, overCls, panel){
8887         return function(e){
8888             t.removeClass(overCls);
8889             if(tc.stopEvent !== false){
8890                 e.stopEvent();
8891             }
8892             if(tc.handler){
8893                 tc.handler.call(tc.scope || t, e, t, panel, tc);
8894             }
8895         };
8896     },
8897
8898     // private
8899     afterRender : function(){
8900         if(this.floating && !this.hidden){
8901             this.el.show();
8902         }
8903         if(this.title){
8904             this.setTitle(this.title);
8905         }
8906         this.setAutoScroll();
8907         if(this.html){
8908             this.body.update(Ext.isObject(this.html) ?
8909                              Ext.DomHelper.markup(this.html) :
8910                              this.html);
8911             delete this.html;
8912         }
8913         if(this.contentEl){
8914             var ce = Ext.getDom(this.contentEl);
8915             Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
8916             this.body.dom.appendChild(ce);
8917         }
8918         if(this.collapsed){
8919             this.collapsed = false;
8920             this.collapse(false);
8921         }
8922         Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
8923         this.initEvents();
8924     },
8925
8926     // private
8927     setAutoScroll : function(){
8928         if(this.rendered && this.autoScroll){
8929             var el = this.body || this.el;
8930             if(el){
8931                 el.setOverflow('auto');
8932             }
8933         }
8934     },
8935
8936     // private
8937     getKeyMap : function(){
8938         if(!this.keyMap){
8939             this.keyMap = new Ext.KeyMap(this.el, this.keys);
8940         }
8941         return this.keyMap;
8942     },
8943
8944     // private
8945     initEvents : function(){
8946         if(this.keys){
8947             this.getKeyMap();
8948         }
8949         if(this.draggable){
8950             this.initDraggable();
8951         }
8952         if(this.toolbars.length > 0){
8953             Ext.each(this.toolbars, function(tb){
8954                 tb.doLayout();
8955                 tb.on({
8956                     scope: this,
8957                     afterlayout: this.syncHeight,
8958                     remove: this.syncHeight
8959                 });
8960             }, this);
8961             if(!this.ownerCt){
8962                 this.syncHeight();
8963             }
8964         }
8965     },
8966
8967     // private
8968     initDraggable : function(){
8969         /**
8970          * <p>If this Panel is configured {@link #draggable}, this property will contain
8971          * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.</p>
8972          * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource}
8973          * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
8974          * @type Ext.dd.DragSource.
8975          * @property dd
8976          */
8977         this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
8978     },
8979
8980     // private
8981     beforeEffect : function(anim){
8982         if(this.floating){
8983             this.el.beforeAction();
8984         }
8985         if(anim !== false){
8986             this.el.addClass('x-panel-animated');
8987         }
8988     },
8989
8990     // private
8991     afterEffect : function(anim){
8992         this.syncShadow();
8993         if(anim !== false){
8994             this.el.removeClass('x-panel-animated');
8995         }
8996     },
8997
8998     // private - wraps up an animation param with internal callbacks
8999     createEffect : function(a, cb, scope){
9000         var o = {
9001             scope:scope,
9002             block:true
9003         };
9004         if(a === true){
9005             o.callback = cb;
9006             return o;
9007         }else if(!a.callback){
9008             o.callback = cb;
9009         }else { // wrap it up
9010             o.callback = function(){
9011                 cb.call(scope);
9012                 Ext.callback(a.callback, a.scope);
9013             };
9014         }
9015         return Ext.applyIf(o, a);
9016     },
9017
9018     /**
9019      * Collapses the panel body so that it becomes hidden.  Fires the {@link #beforecollapse} event which will
9020      * cancel the collapse action if it returns false.
9021      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
9022      * {@link #animCollapse} panel config)
9023      * @return {Ext.Panel} this
9024      */
9025     collapse : function(animate){
9026         if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
9027             return;
9028         }
9029         var doAnim = animate === true || (animate !== false && this.animCollapse);
9030         this.beforeEffect(doAnim);
9031         this.onCollapse(doAnim, animate);
9032         return this;
9033     },
9034
9035     // private
9036     onCollapse : function(doAnim, animArg){
9037         if(doAnim){
9038             this[this.collapseEl].slideOut(this.slideAnchor,
9039                     Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
9040                         this.collapseDefaults));
9041         }else{
9042             this[this.collapseEl].hide();
9043             this.afterCollapse(false);
9044         }
9045     },
9046
9047     // private
9048     afterCollapse : function(anim){
9049         this.collapsed = true;
9050         this.el.addClass(this.collapsedCls);
9051         this.afterEffect(anim);
9052         this.fireEvent('collapse', this);
9053     },
9054
9055     /**
9056      * Expands the panel body so that it becomes visible.  Fires the {@link #beforeexpand} event which will
9057      * cancel the expand action if it returns false.
9058      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
9059      * {@link #animCollapse} panel config)
9060      * @return {Ext.Panel} this
9061      */
9062     expand : function(animate){
9063         if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
9064             return;
9065         }
9066         var doAnim = animate === true || (animate !== false && this.animCollapse);
9067         this.el.removeClass(this.collapsedCls);
9068         this.beforeEffect(doAnim);
9069         this.onExpand(doAnim, animate);
9070         return this;
9071     },
9072
9073     // private
9074     onExpand : function(doAnim, animArg){
9075         if(doAnim){
9076             this[this.collapseEl].slideIn(this.slideAnchor,
9077                     Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
9078                         this.expandDefaults));
9079         }else{
9080             this[this.collapseEl].show();
9081             this.afterExpand(false);
9082         }
9083     },
9084
9085     // private
9086     afterExpand : function(anim){
9087         this.collapsed = false;
9088         this.afterEffect(anim);
9089         if(Ext.isDefined(this.deferLayout)){
9090             this.doLayout(true);
9091         }
9092         this.fireEvent('expand', this);
9093     },
9094
9095     /**
9096      * Shortcut for performing an {@link #expand} or {@link #collapse} based on the current state of the panel.
9097      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
9098      * {@link #animCollapse} panel config)
9099      * @return {Ext.Panel} this
9100      */
9101     toggleCollapse : function(animate){
9102         this[this.collapsed ? 'expand' : 'collapse'](animate);
9103         return this;
9104     },
9105
9106     // private
9107     onDisable : function(){
9108         if(this.rendered && this.maskDisabled){
9109             this.el.mask();
9110         }
9111         Ext.Panel.superclass.onDisable.call(this);
9112     },
9113
9114     // private
9115     onEnable : function(){
9116         if(this.rendered && this.maskDisabled){
9117             this.el.unmask();
9118         }
9119         Ext.Panel.superclass.onEnable.call(this);
9120     },
9121
9122     // private
9123     onResize : function(w, h){
9124         if(Ext.isDefined(w) || Ext.isDefined(h)){
9125             if(!this.collapsed){
9126                 if(Ext.isNumber(w)){
9127                     w = this.adjustBodyWidth(w - this.getFrameWidth());
9128                     if(this.tbar){
9129                         this.tbar.setWidth(w);
9130                         if(this.topToolbar){
9131                             this.topToolbar.setSize(w);
9132                         }
9133                     }
9134                     if(this.bbar){
9135                         this.bbar.setWidth(w);
9136                         if(this.bottomToolbar){
9137                             this.bottomToolbar.setSize(w);
9138                         }
9139                     }
9140                     if(this.fbar){
9141                         var f = this.fbar,
9142                             fWidth = 1,
9143                             strict = Ext.isStrict;
9144                         if(this.buttonAlign == 'left'){
9145                            fWidth = w - f.container.getFrameWidth('lr');
9146                         }else{
9147                             //center/right alignment off in webkit
9148                             if(Ext.isIE || Ext.isWebKit){
9149                                 //center alignment ok on webkit.
9150                                 //right broken in both, center on IE
9151                                 if(!(this.buttonAlign == 'center' && Ext.isWebKit) && (!strict || (!Ext.isIE8 && strict))){
9152                                     (function(){
9153                                         f.setWidth(f.getEl().child('.x-toolbar-ct').getWidth());
9154                                     }).defer(1);
9155                                 }else{
9156                                     fWidth = 'auto';
9157                                 }
9158                             }else{
9159                                 fWidth = 'auto';
9160                             }
9161                         }
9162                         f.setWidth(fWidth);
9163                     }
9164                     this.body.setWidth(w);
9165                 }else if(w == 'auto'){
9166                     this.body.setWidth(w);
9167                 }
9168
9169                 if(Ext.isNumber(h)){
9170                     h = Math.max(0, this.adjustBodyHeight(h - this.getFrameHeight()));
9171                     this.body.setHeight(h);
9172                 }else if(h == 'auto'){
9173                     this.body.setHeight(h);
9174                 }
9175
9176                 if(this.disabled && this.el._mask){
9177                     this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
9178                 }
9179             }else{
9180                 this.queuedBodySize = {width: w, height: h};
9181                 if(!this.queuedExpand && this.allowQueuedExpand !== false){
9182                     this.queuedExpand = true;
9183                     this.on('expand', function(){
9184                         delete this.queuedExpand;
9185                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
9186                         this.doLayout();
9187                     }, this, {single:true});
9188                 }
9189             }
9190             this.onBodyResize(w, h);
9191         }
9192         this.syncShadow();
9193     },
9194     
9195     // private
9196     onBodyResize: function(w, h){
9197         this.fireEvent('bodyresize', this, w, h);
9198     },
9199     
9200     // private
9201     getToolbarHeight: function(){
9202         var h = 0;
9203         if(this.rendered){
9204             Ext.each(this.toolbars, function(tb){
9205                 h += tb.getHeight();
9206             }, this);
9207         }
9208         return h;
9209     },
9210
9211     // private
9212     adjustBodyHeight : function(h){
9213         return h;
9214     },
9215
9216     // private
9217     adjustBodyWidth : function(w){
9218         return w;
9219     },
9220
9221     // private
9222     onPosition : function(){
9223         this.syncShadow();
9224     },
9225
9226     /**
9227      * Returns the width in pixels of the framing elements of this panel (not including the body width).  To
9228      * retrieve the body width see {@link #getInnerWidth}.
9229      * @return {Number} The frame width
9230      */
9231     getFrameWidth : function(){
9232         var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
9233
9234         if(this.frame){
9235             var l = this.bwrap.dom.firstChild;
9236             w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
9237             w += this.mc.getFrameWidth('lr');
9238         }
9239         return w;
9240     },
9241
9242     /**
9243      * Returns the height in pixels of the framing elements of this panel (including any top and bottom bars and
9244      * header and footer elements, but not including the body height).  To retrieve the body height see {@link #getInnerHeight}.
9245      * @return {Number} The frame height
9246      */
9247     getFrameHeight : function(){
9248         var h  = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
9249         h += (this.tbar ? this.tbar.getHeight() : 0) +
9250              (this.bbar ? this.bbar.getHeight() : 0);
9251
9252         if(this.frame){
9253             h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
9254         }else{
9255             h += (this.header ? this.header.getHeight() : 0) +
9256                 (this.footer ? this.footer.getHeight() : 0);
9257         }
9258         return h;
9259     },
9260
9261     /**
9262      * Returns the width in pixels of the body element (not including the width of any framing elements).
9263      * For the frame width see {@link #getFrameWidth}.
9264      * @return {Number} The body width
9265      */
9266     getInnerWidth : function(){
9267         return this.getSize().width - this.getFrameWidth();
9268     },
9269
9270     /**
9271      * Returns the height in pixels of the body element (not including the height of any framing elements).
9272      * For the frame height see {@link #getFrameHeight}.
9273      * @return {Number} The body height
9274      */
9275     getInnerHeight : function(){
9276         return this.getSize().height - this.getFrameHeight();
9277     },
9278
9279     // private
9280     syncShadow : function(){
9281         if(this.floating){
9282             this.el.sync(true);
9283         }
9284     },
9285
9286     // private
9287     getLayoutTarget : function(){
9288         return this.body;
9289     },
9290
9291     /**
9292      * <p>Sets the title text for the panel and optionally the {@link #iconCls icon class}.</p>
9293      * <p>In order to be able to set the title, a header element must have been created
9294      * for the Panel. This is triggered either by configuring the Panel with a non-blank <code>{@link #title}</code>,
9295      * or configuring it with <code><b>{@link #header}: true</b></code>.</p>
9296      * @param {String} title The title text to set
9297      * @param {String} iconCls (optional) {@link #iconCls iconCls} A user-defined CSS class that provides the icon image for this panel
9298      */
9299     setTitle : function(title, iconCls){
9300         this.title = title;
9301         if(this.header && this.headerAsText){
9302             this.header.child('span').update(title);
9303         }
9304         if(iconCls){
9305             this.setIconClass(iconCls);
9306         }
9307         this.fireEvent('titlechange', this, title);
9308         return this;
9309     },
9310
9311     /**
9312      * Get the {@link Ext.Updater} for this panel. Enables you to perform Ajax updates of this panel's body.
9313      * @return {Ext.Updater} The Updater
9314      */
9315     getUpdater : function(){
9316         return this.body.getUpdater();
9317     },
9318
9319      /**
9320      * Loads this content panel immediately with content returned from an XHR call.
9321      * @param {Object/String/Function} config A config object containing any of the following options:
9322 <pre><code>
9323 panel.load({
9324     url: 'your-url.php',
9325     params: {param1: 'foo', param2: 'bar'}, // or a URL encoded string
9326     callback: yourFunction,
9327     scope: yourObject, // optional scope for the callback
9328     discardUrl: false,
9329     nocache: false,
9330     text: 'Loading...',
9331     timeout: 30,
9332     scripts: false
9333 });
9334 </code></pre>
9335      * The only required property is url. The optional properties nocache, text and scripts
9336      * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their
9337      * associated property on this panel Updater instance.
9338      * @return {Ext.Panel} this
9339      */
9340     load : function(){
9341         var um = this.body.getUpdater();
9342         um.update.apply(um, arguments);
9343         return this;
9344     },
9345
9346     // private
9347     beforeDestroy : function(){
9348         if(this.header){
9349             this.header.removeAllListeners();
9350             if(this.headerAsText){
9351                 Ext.Element.uncache(this.header.child('span'));
9352             }
9353         }
9354         Ext.Element.uncache(
9355             this.ft,
9356             this.mc,
9357             this.header,
9358             this.tbar,
9359             this.bbar,
9360             this.footer,
9361             this.body,
9362             this.bwrap
9363         );
9364         if(this.tools){
9365             for(var k in this.tools){
9366                 Ext.destroy(this.tools[k]);
9367             }
9368         }
9369         if(this.buttons){
9370             for(var b in this.buttons){
9371                 Ext.destroy(this.buttons[b]);
9372             }
9373         }
9374         if(this.rendered){
9375             Ext.destroy(this.toolbars);
9376         }else{
9377             Ext.destroy(this.topToolbar, this.bottomToolbar);
9378         }
9379         Ext.Panel.superclass.beforeDestroy.call(this);
9380     },
9381
9382     // private
9383     createClasses : function(){
9384         this.headerCls = this.baseCls + '-header';
9385         this.headerTextCls = this.baseCls + '-header-text';
9386         this.bwrapCls = this.baseCls + '-bwrap';
9387         this.tbarCls = this.baseCls + '-tbar';
9388         this.bodyCls = this.baseCls + '-body';
9389         this.bbarCls = this.baseCls + '-bbar';
9390         this.footerCls = this.baseCls + '-footer';
9391     },
9392
9393     // private
9394     createGhost : function(cls, useShim, appendTo){
9395         var el = document.createElement('div');
9396         el.className = 'x-panel-ghost ' + (cls ? cls : '');
9397         if(this.header){
9398             el.appendChild(this.el.dom.firstChild.cloneNode(true));
9399         }
9400         Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
9401         el.style.width = this.el.dom.offsetWidth + 'px';;
9402         if(!appendTo){
9403             this.container.dom.appendChild(el);
9404         }else{
9405             Ext.getDom(appendTo).appendChild(el);
9406         }
9407         if(useShim !== false && this.el.useShim !== false){
9408             var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
9409             layer.show();
9410             return layer;
9411         }else{
9412             return new Ext.Element(el);
9413         }
9414     },
9415
9416     // private
9417     doAutoLoad : function(){
9418         var u = this.body.getUpdater();
9419         if(this.renderer){
9420             u.setRenderer(this.renderer);
9421         }
9422         u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
9423     },
9424
9425     /**
9426      * Retrieve a tool by id.
9427      * @param {String} id
9428      * @return {Object} tool
9429      */
9430     getTool : function(id) {
9431         return this.tools[id];
9432     }
9433
9434 /**
9435  * @cfg {String} autoEl @hide
9436  */
9437 });
9438 Ext.reg('panel', Ext.Panel);
9439 /**
9440  * @class Ext.Editor
9441  * @extends Ext.Component
9442  * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
9443  * @constructor
9444  * Create a new Editor
9445  * @param {Object} config The config object
9446  * @xtype editor
9447  */
9448 Ext.Editor = function(field, config){
9449     if(field.field){
9450         this.field = Ext.create(field.field, 'textfield');
9451         config = Ext.apply({}, field); // copy so we don't disturb original config
9452         delete config.field;
9453     }else{
9454         this.field = field;
9455     }
9456     Ext.Editor.superclass.constructor.call(this, config);
9457 };
9458
9459 Ext.extend(Ext.Editor, Ext.Component, {
9460     /**
9461     * @cfg {Ext.form.Field} field
9462     * The Field object (or descendant) or config object for field
9463     */
9464     /**
9465      * @cfg {Boolean} allowBlur
9466      * True to {@link #completeEdit complete the editing process} if in edit mode when the
9467      * field is blurred. Defaults to <tt>false</tt>.
9468      */
9469     /**
9470      * @cfg {Boolean/String} autoSize
9471      * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only,
9472      * or "height" to adopt the height only, "none" to always use the field dimensions. (defaults to false)
9473      */
9474     /**
9475      * @cfg {Boolean} revertInvalid
9476      * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
9477      * validation fails (defaults to true)
9478      */
9479     /**
9480      * @cfg {Boolean} ignoreNoChange
9481      * True to skip the edit completion process (no save, no events fired) if the user completes an edit and
9482      * the value has not changed (defaults to false).  Applies only to string values - edits for other data types
9483      * will never be ignored.
9484      */
9485     /**
9486      * @cfg {Boolean} hideEl
9487      * False to keep the bound element visible while the editor is displayed (defaults to true)
9488      */
9489     /**
9490      * @cfg {Mixed} value
9491      * The data value of the underlying field (defaults to "")
9492      */
9493     value : "",
9494     /**
9495      * @cfg {String} alignment
9496      * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?").
9497      */
9498     alignment: "c-c?",
9499     /**
9500      * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
9501      * for bottom-right shadow (defaults to "frame")
9502      */
9503     shadow : "frame",
9504     /**
9505      * @cfg {Boolean} constrain True to constrain the editor to the viewport
9506      */
9507     constrain : false,
9508     /**
9509      * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true)
9510      */
9511     swallowKeys : true,
9512     /**
9513      * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed. Defaults to <tt>true</tt>.
9514      */
9515     completeOnEnter : true,
9516     /**
9517      * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed. Defaults to <tt>true</tt>.
9518      */
9519     cancelOnEsc : true,
9520     /**
9521      * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
9522      */
9523     updateEl : false,
9524
9525     initComponent : function(){
9526         Ext.Editor.superclass.initComponent.call(this);
9527         this.addEvents(
9528             /**
9529              * @event beforestartedit
9530              * Fires when editing is initiated, but before the value changes.  Editing can be canceled by returning
9531              * false from the handler of this event.
9532              * @param {Editor} this
9533              * @param {Ext.Element} boundEl The underlying element bound to this editor
9534              * @param {Mixed} value The field value being set
9535              */
9536             "beforestartedit",
9537             /**
9538              * @event startedit
9539              * Fires when this editor is displayed
9540              * @param {Ext.Element} boundEl The underlying element bound to this editor
9541              * @param {Mixed} value The starting field value
9542              */
9543             "startedit",
9544             /**
9545              * @event beforecomplete
9546              * Fires after a change has been made to the field, but before the change is reflected in the underlying
9547              * field.  Saving the change to the field can be canceled by returning false from the handler of this event.
9548              * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
9549              * event will not fire since no edit actually occurred.
9550              * @param {Editor} this
9551              * @param {Mixed} value The current field value
9552              * @param {Mixed} startValue The original field value
9553              */
9554             "beforecomplete",
9555             /**
9556              * @event complete
9557              * Fires after editing is complete and any changed value has been written to the underlying field.
9558              * @param {Editor} this
9559              * @param {Mixed} value The current field value
9560              * @param {Mixed} startValue The original field value
9561              */
9562             "complete",
9563             /**
9564              * @event canceledit
9565              * Fires after editing has been canceled and the editor's value has been reset.
9566              * @param {Editor} this
9567              * @param {Mixed} value The user-entered field value that was discarded
9568              * @param {Mixed} startValue The original field value that was set back into the editor after cancel
9569              */
9570             "canceledit",
9571             /**
9572              * @event specialkey
9573              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
9574              * {@link Ext.EventObject#getKey} to determine which key was pressed.
9575              * @param {Ext.form.Field} this
9576              * @param {Ext.EventObject} e The event object
9577              */
9578             "specialkey"
9579         );
9580     },
9581
9582     // private
9583     onRender : function(ct, position){
9584         this.el = new Ext.Layer({
9585             shadow: this.shadow,
9586             cls: "x-editor",
9587             parentEl : ct,
9588             shim : this.shim,
9589             shadowOffset: this.shadowOffset || 4,
9590             id: this.id,
9591             constrain: this.constrain
9592         });
9593         if(this.zIndex){
9594             this.el.setZIndex(this.zIndex);
9595         }
9596         this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
9597         if(this.field.msgTarget != 'title'){
9598             this.field.msgTarget = 'qtip';
9599         }
9600         this.field.inEditor = true;
9601         this.mon(this.field, {
9602             scope: this,
9603             blur: this.onBlur,
9604             specialkey: this.onSpecialKey
9605         });
9606         if(this.field.grow){
9607             this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
9608         }
9609         this.field.render(this.el).show();
9610         this.field.getEl().dom.name = '';
9611         if(this.swallowKeys){
9612             this.field.el.swallowEvent([
9613                 'keypress', // *** Opera
9614                 'keydown'   // *** all other browsers
9615             ]);
9616         }
9617     },
9618
9619     // private
9620     onSpecialKey : function(field, e){
9621         var key = e.getKey(),
9622             complete = this.completeOnEnter && key == e.ENTER,
9623             cancel = this.cancelOnEsc && key == e.ESC;
9624         if(complete || cancel){
9625             e.stopEvent();
9626             if(complete){
9627                 this.completeEdit();
9628             }else{
9629                 this.cancelEdit();
9630             }
9631             if(field.triggerBlur){
9632                 field.triggerBlur(); 
9633             }
9634         }
9635         this.fireEvent('specialkey', field, e);
9636     },
9637
9638     /**
9639      * Starts the editing process and shows the editor.
9640      * @param {Mixed} el The element to edit
9641      * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
9642       * to the innerHTML of el.
9643      */
9644     startEdit : function(el, value){
9645         if(this.editing){
9646             this.completeEdit();
9647         }
9648         this.boundEl = Ext.get(el);
9649         var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
9650         if(!this.rendered){
9651             this.render(this.parentEl || document.body);
9652         }
9653         if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
9654             this.startValue = v;
9655             this.field.setValue(v);
9656             this.doAutoSize();
9657             this.el.alignTo(this.boundEl, this.alignment);
9658             this.editing = true;
9659             this.show();
9660         }
9661     },
9662
9663     // private
9664     doAutoSize : function(){
9665         if(this.autoSize){
9666             var sz = this.boundEl.getSize(),
9667                 fs = this.field.getSize();
9668
9669             switch(this.autoSize){
9670                 case "width":
9671                     this.setSize(sz.width, fs.height);
9672                     break;
9673                 case "height":
9674                     this.setSize(fs.width, sz.height);
9675                     break;
9676                 case "none":
9677                     this.setSize(fs.width, fs.height);
9678                     break;
9679                 default:
9680                     this.setSize(sz.width, sz.height);
9681             }
9682         }
9683     },
9684
9685     /**
9686      * Sets the height and width of this editor.
9687      * @param {Number} width The new width
9688      * @param {Number} height The new height
9689      */
9690     setSize : function(w, h){
9691         delete this.field.lastSize;
9692         this.field.setSize(w, h);
9693         if(this.el){
9694             if(Ext.isGecko2 || Ext.isOpera){
9695                 // prevent layer scrollbars
9696                 this.el.setSize(w, h);
9697             }
9698             this.el.sync();
9699         }
9700     },
9701
9702     /**
9703      * Realigns the editor to the bound field based on the current alignment config value.
9704      */
9705     realign : function(){
9706         this.el.alignTo(this.boundEl, this.alignment);
9707     },
9708
9709     /**
9710      * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
9711      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
9712      */
9713     completeEdit : function(remainVisible){
9714         if(!this.editing){
9715             return;
9716         }
9717         var v = this.getValue();
9718         if(!this.field.isValid()){
9719             if(this.revertInvalid !== false){
9720                 this.cancelEdit(remainVisible);
9721             }
9722             return;
9723         }
9724         if(String(v) === String(this.startValue) && this.ignoreNoChange){
9725             this.hideEdit(remainVisible);
9726             return;
9727         }
9728         if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
9729             v = this.getValue();
9730             if(this.updateEl && this.boundEl){
9731                 this.boundEl.update(v);
9732             }
9733             this.hideEdit(remainVisible);
9734             this.fireEvent("complete", this, v, this.startValue);
9735         }
9736     },
9737
9738     // private
9739     onShow : function(){
9740         this.el.show();
9741         if(this.hideEl !== false){
9742             this.boundEl.hide();
9743         }
9744         this.field.show().focus(false, true);
9745         this.fireEvent("startedit", this.boundEl, this.startValue);
9746     },
9747
9748     /**
9749      * Cancels the editing process and hides the editor without persisting any changes.  The field value will be
9750      * reverted to the original starting value.
9751      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
9752      * cancel (defaults to false)
9753      */
9754     cancelEdit : function(remainVisible){
9755         if(this.editing){
9756             var v = this.getValue();
9757             this.setValue(this.startValue);
9758             this.hideEdit(remainVisible);
9759             this.fireEvent("canceledit", this, v, this.startValue);
9760         }
9761     },
9762     
9763     // private
9764     hideEdit: function(remainVisible){
9765         if(remainVisible !== true){
9766             this.editing = false;
9767             this.hide();
9768         }
9769     },
9770
9771     // private
9772     onBlur : function(){
9773         if(this.allowBlur !== true && this.editing){
9774             this.completeEdit();
9775         }
9776     },
9777
9778     // private
9779     onHide : function(){
9780         if(this.editing){
9781             this.completeEdit();
9782             return;
9783         }
9784         this.field.blur();
9785         if(this.field.collapse){
9786             this.field.collapse();
9787         }
9788         this.el.hide();
9789         if(this.hideEl !== false){
9790             this.boundEl.show();
9791         }
9792     },
9793
9794     /**
9795      * Sets the data value of the editor
9796      * @param {Mixed} value Any valid value supported by the underlying field
9797      */
9798     setValue : function(v){
9799         this.field.setValue(v);
9800     },
9801
9802     /**
9803      * Gets the data value of the editor
9804      * @return {Mixed} The data value
9805      */
9806     getValue : function(){
9807         return this.field.getValue();
9808     },
9809
9810     beforeDestroy : function(){
9811         Ext.destroy(this.field);
9812         this.field = null;
9813     }
9814 });
9815 Ext.reg('editor', Ext.Editor);/**
9816  * @class Ext.ColorPalette
9817  * @extends Ext.Component
9818  * Simple color palette class for choosing colors.  The palette can be rendered to any container.<br />
9819  * Here's an example of typical usage:
9820  * <pre><code>
9821 var cp = new Ext.ColorPalette({value:'993300'});  // initial selected color
9822 cp.render('my-div');
9823
9824 cp.on('select', function(palette, selColor){
9825     // do something with selColor
9826 });
9827 </code></pre>
9828  * @constructor
9829  * Create a new ColorPalette
9830  * @param {Object} config The config object
9831  * @xtype colorpalette
9832  */
9833 Ext.ColorPalette = function(config){
9834     Ext.ColorPalette.superclass.constructor.call(this, config);
9835     this.addEvents(
9836         /**
9837              * @event select
9838              * Fires when a color is selected
9839              * @param {ColorPalette} this
9840              * @param {String} color The 6-digit color hex code (without the # symbol)
9841              */
9842         'select'
9843     );
9844
9845     if(this.handler){
9846         this.on('select', this.handler, this.scope, true);
9847     }
9848 };
9849 Ext.extend(Ext.ColorPalette, Ext.Component, {
9850         /**
9851          * @cfg {String} tpl An existing XTemplate instance to be used in place of the default template for rendering the component.
9852          */
9853     /**
9854      * @cfg {String} itemCls
9855      * The CSS class to apply to the containing element (defaults to 'x-color-palette')
9856      */
9857     itemCls : 'x-color-palette',
9858     /**
9859      * @cfg {String} value
9860      * The initial color to highlight (should be a valid 6-digit color hex code without the # symbol).  Note that
9861      * the hex codes are case-sensitive.
9862      */
9863     value : null,
9864     clickEvent :'click',
9865     // private
9866     ctype : 'Ext.ColorPalette',
9867
9868     /**
9869      * @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the {@link #select} event
9870      */
9871     allowReselect : false,
9872
9873     /**
9874      * <p>An array of 6-digit color hex code strings (without the # symbol).  This array can contain any number
9875      * of colors, and each hex code should be unique.  The width of the palette is controlled via CSS by adjusting
9876      * the width property of the 'x-color-palette' class (or assigning a custom class), so you can balance the number
9877      * of colors with the width setting until the box is symmetrical.</p>
9878      * <p>You can override individual colors if needed:</p>
9879      * <pre><code>
9880 var cp = new Ext.ColorPalette();
9881 cp.colors[0] = 'FF0000';  // change the first box to red
9882 </code></pre>
9883
9884 Or you can provide a custom array of your own for complete control:
9885 <pre><code>
9886 var cp = new Ext.ColorPalette();
9887 cp.colors = ['000000', '993300', '333300'];
9888 </code></pre>
9889      * @type Array
9890      */
9891     colors : [
9892         '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
9893         '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
9894         'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
9895         'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
9896         'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
9897     ],
9898
9899     /**
9900      * @cfg {Function} handler
9901      * Optional. A function that will handle the select event of this palette.
9902      * The handler is passed the following parameters:<div class="mdetail-params"><ul>
9903      * <li><code>palette</code> : ColorPalette<div class="sub-desc">The {@link #palette Ext.ColorPalette}.</div></li>
9904      * <li><code>color</code> : String<div class="sub-desc">The 6-digit color hex code (without the # symbol).</div></li>
9905      * </ul></div>
9906      */
9907     /**
9908      * @cfg {Object} scope
9909      * The scope (<tt><b>this</b></tt> reference) in which the <code>{@link #handler}</code>
9910      * function will be called.  Defaults to this ColorPalette instance.
9911      */
9912
9913     // private
9914     onRender : function(container, position){
9915         var t = this.tpl || new Ext.XTemplate(
9916             '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
9917         );
9918         var el = document.createElement('div');
9919         el.id = this.getId();
9920         el.className = this.itemCls;
9921         t.overwrite(el, this.colors);
9922         container.dom.insertBefore(el, position);
9923         this.el = Ext.get(el);
9924         this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
9925         if(this.clickEvent != 'click'){
9926                 this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
9927         }
9928     },
9929
9930     // private
9931     afterRender : function(){
9932         Ext.ColorPalette.superclass.afterRender.call(this);
9933         if(this.value){
9934             var s = this.value;
9935             this.value = null;
9936             this.select(s);
9937         }
9938     },
9939
9940     // private
9941     handleClick : function(e, t){
9942         e.preventDefault();
9943         if(!this.disabled){
9944             var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
9945             this.select(c.toUpperCase());
9946         }
9947     },
9948
9949     /**
9950      * Selects the specified color in the palette (fires the {@link #select} event)
9951      * @param {String} color A valid 6-digit color hex code (# will be stripped if included)
9952      */
9953     select : function(color){
9954         color = color.replace('#', '');
9955         if(color != this.value || this.allowReselect){
9956             var el = this.el;
9957             if(this.value){
9958                 el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
9959             }
9960             el.child('a.color-'+color).addClass('x-color-palette-sel');
9961             this.value = color;
9962             this.fireEvent('select', this, color);
9963         }
9964     }
9965
9966     /**
9967      * @cfg {String} autoEl @hide
9968      */
9969 });
9970 Ext.reg('colorpalette', Ext.ColorPalette);
9971 /**\r
9972  * @class Ext.DatePicker\r
9973  * @extends Ext.Component\r
9974  * Simple date picker class.\r
9975  * @constructor\r
9976  * Create a new DatePicker\r
9977  * @param {Object} config The config object\r
9978  * @xtype datepicker\r
9979  */\r
9980 Ext.DatePicker = Ext.extend(Ext.BoxComponent, {\r
9981     /**\r
9982      * @cfg {String} todayText\r
9983      * The text to display on the button that selects the current date (defaults to <tt>'Today'</tt>)\r
9984      */\r
9985     todayText : 'Today',\r
9986     /**\r
9987      * @cfg {String} okText\r
9988      * The text to display on the ok button (defaults to <tt>'&#160;OK&#160;'</tt> to give the user extra clicking room)\r
9989      */\r
9990     okText : '&#160;OK&#160;',\r
9991     /**\r
9992      * @cfg {String} cancelText\r
9993      * The text to display on the cancel button (defaults to <tt>'Cancel'</tt>)\r
9994      */\r
9995     cancelText : 'Cancel',\r
9996     /**\r
9997      * @cfg {Function} handler\r
9998      * Optional. A function that will handle the select event of this picker.\r
9999      * The handler is passed the following parameters:<div class="mdetail-params"><ul>\r
10000      * <li><code>picker</code> : DatePicker<div class="sub-desc">The Ext.DatePicker.</div></li>\r
10001      * <li><code>date</code> : Date<div class="sub-desc">The selected date.</div></li>\r
10002      * </ul></div>\r
10003      */\r
10004     /**\r
10005      * @cfg {Object} scope\r
10006      * The scope (<tt><b>this</b></tt> reference) in which the <code>{@link #handler}</code>\r
10007      * function will be called.  Defaults to this DatePicker instance.\r
10008      */ \r
10009     /**\r
10010      * @cfg {String} todayTip\r
10011      * The tooltip to display for the button that selects the current date (defaults to <tt>'{current date} (Spacebar)'</tt>)\r
10012      */\r
10013     todayTip : '{0} (Spacebar)',\r
10014     /**\r
10015      * @cfg {String} minText\r
10016      * The error text to display if the minDate validation fails (defaults to <tt>'This date is before the minimum date'</tt>)\r
10017      */\r
10018     minText : 'This date is before the minimum date',\r
10019     /**\r
10020      * @cfg {String} maxText\r
10021      * The error text to display if the maxDate validation fails (defaults to <tt>'This date is after the maximum date'</tt>)\r
10022      */\r
10023     maxText : 'This date is after the maximum date',\r
10024     /**\r
10025      * @cfg {String} format\r
10026      * The default date format string which can be overriden for localization support.  The format must be\r
10027      * valid according to {@link Date#parseDate} (defaults to <tt>'m/d/y'</tt>).\r
10028      */\r
10029     format : 'm/d/y',\r
10030     /**\r
10031      * @cfg {String} disabledDaysText\r
10032      * The tooltip to display when the date falls on a disabled day (defaults to <tt>'Disabled'</tt>)\r
10033      */\r
10034     disabledDaysText : 'Disabled',\r
10035     /**\r
10036      * @cfg {String} disabledDatesText\r
10037      * The tooltip text to display when the date falls on a disabled date (defaults to <tt>'Disabled'</tt>)\r
10038      */\r
10039     disabledDatesText : 'Disabled',\r
10040     /**\r
10041      * @cfg {Array} monthNames\r
10042      * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)\r
10043      */\r
10044     monthNames : Date.monthNames,\r
10045     /**\r
10046      * @cfg {Array} dayNames\r
10047      * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)\r
10048      */\r
10049     dayNames : Date.dayNames,\r
10050     /**\r
10051      * @cfg {String} nextText\r
10052      * The next month navigation button tooltip (defaults to <tt>'Next Month (Control+Right)'</tt>)\r
10053      */\r
10054     nextText : 'Next Month (Control+Right)',\r
10055     /**\r
10056      * @cfg {String} prevText\r
10057      * The previous month navigation button tooltip (defaults to <tt>'Previous Month (Control+Left)'</tt>)\r
10058      */\r
10059     prevText : 'Previous Month (Control+Left)',\r
10060     /**\r
10061      * @cfg {String} monthYearText\r
10062      * The header month selector tooltip (defaults to <tt>'Choose a month (Control+Up/Down to move years)'</tt>)\r
10063      */\r
10064     monthYearText : 'Choose a month (Control+Up/Down to move years)',\r
10065     /**\r
10066      * @cfg {Number} startDay\r
10067      * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)\r
10068      */\r
10069     startDay : 0,\r
10070     /**\r
10071      * @cfg {Boolean} showToday\r
10072      * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar\r
10073      * that selects the current date (defaults to <tt>true</tt>).\r
10074      */\r
10075     showToday : true,\r
10076     /**\r
10077      * @cfg {Date} minDate\r
10078      * Minimum allowable date (JavaScript date object, defaults to null)\r
10079      */\r
10080     /**\r
10081      * @cfg {Date} maxDate\r
10082      * Maximum allowable date (JavaScript date object, defaults to null)\r
10083      */\r
10084     /**\r
10085      * @cfg {Array} disabledDays\r
10086      * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).\r
10087      */\r
10088     /**\r
10089      * @cfg {RegExp} disabledDatesRE\r
10090      * JavaScript regular expression used to disable a pattern of dates (defaults to null).  The {@link #disabledDates}\r
10091      * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the\r
10092      * disabledDates value.\r
10093      */\r
10094     /**\r
10095      * @cfg {Array} disabledDates\r
10096      * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular\r
10097      * expression so they are very powerful. Some examples:\r
10098      * <ul>\r
10099      * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>\r
10100      * <li>['03/08', '09/16'] would disable those days for every year</li>\r
10101      * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>\r
10102      * <li>['03/../2006'] would disable every day in March 2006</li>\r
10103      * <li>['^03'] would disable every day in every March</li>\r
10104      * </ul>\r
10105      * Note that the format of the dates included in the array should exactly match the {@link #format} config.\r
10106      * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to\r
10107      * escape the dot when restricting dates. For example: ['03\\.08\\.03'].\r
10108      */\r
10109 \r
10110     // private\r
10111     initComponent : function(){\r
10112         Ext.DatePicker.superclass.initComponent.call(this);\r
10113 \r
10114         this.value = this.value ?\r
10115                  this.value.clearTime(true) : new Date().clearTime();\r
10116 \r
10117         this.addEvents(\r
10118             /**\r
10119              * @event select\r
10120              * Fires when a date is selected\r
10121              * @param {DatePicker} this\r
10122              * @param {Date} date The selected date\r
10123              */\r
10124             'select'\r
10125         );\r
10126 \r
10127         if(this.handler){\r
10128             this.on('select', this.handler,  this.scope || this);\r
10129         }\r
10130 \r
10131         this.initDisabledDays();\r
10132     },\r
10133 \r
10134     // private\r
10135     initDisabledDays : function(){\r
10136         if(!this.disabledDatesRE && this.disabledDates){\r
10137             var dd = this.disabledDates,\r
10138                 len = dd.length - 1,\r
10139                 re = '(?:';\r
10140                 \r
10141             Ext.each(dd, function(d, i){\r
10142                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];\r
10143                 if(i != len){\r
10144                     re += '|';\r
10145                 }\r
10146             }, this);\r
10147             this.disabledDatesRE = new RegExp(re + ')');\r
10148         }\r
10149     },\r
10150 \r
10151     /**\r
10152      * Replaces any existing disabled dates with new values and refreshes the DatePicker.\r
10153      * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config\r
10154      * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.\r
10155      */\r
10156     setDisabledDates : function(dd){\r
10157         if(Ext.isArray(dd)){\r
10158             this.disabledDates = dd;\r
10159             this.disabledDatesRE = null;\r
10160         }else{\r
10161             this.disabledDatesRE = dd;\r
10162         }\r
10163         this.initDisabledDays();\r
10164         this.update(this.value, true);\r
10165     },\r
10166 \r
10167     /**\r
10168      * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.\r
10169      * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config\r
10170      * for details on supported values.\r
10171      */\r
10172     setDisabledDays : function(dd){\r
10173         this.disabledDays = dd;\r
10174         this.update(this.value, true);\r
10175     },\r
10176 \r
10177     /**\r
10178      * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.\r
10179      * @param {Date} value The minimum date that can be selected\r
10180      */\r
10181     setMinDate : function(dt){\r
10182         this.minDate = dt;\r
10183         this.update(this.value, true);\r
10184     },\r
10185 \r
10186     /**\r
10187      * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.\r
10188      * @param {Date} value The maximum date that can be selected\r
10189      */\r
10190     setMaxDate : function(dt){\r
10191         this.maxDate = dt;\r
10192         this.update(this.value, true);\r
10193     },\r
10194 \r
10195     /**\r
10196      * Sets the value of the date field\r
10197      * @param {Date} value The date to set\r
10198      */\r
10199     setValue : function(value){\r
10200         this.value = value.clearTime(true);\r
10201         this.update(this.value);\r
10202     },\r
10203 \r
10204     /**\r
10205      * Gets the current selected value of the date field\r
10206      * @return {Date} The selected date\r
10207      */\r
10208     getValue : function(){\r
10209         return this.value;\r
10210     },\r
10211 \r
10212     // private\r
10213     focus : function(){\r
10214         this.update(this.activeDate);\r
10215     },\r
10216     \r
10217     // private\r
10218     onEnable: function(initial){\r
10219         Ext.DatePicker.superclass.onEnable.call(this);    \r
10220         this.doDisabled(false);\r
10221         this.update(initial ? this.value : this.activeDate);\r
10222         if(Ext.isIE){\r
10223             this.el.repaint();\r
10224         }\r
10225         \r
10226     },\r
10227     \r
10228     // private\r
10229     onDisable : function(){\r
10230         Ext.DatePicker.superclass.onDisable.call(this);   \r
10231         this.doDisabled(true);\r
10232         if(Ext.isIE && !Ext.isIE8){\r
10233             /* Really strange problem in IE6/7, when disabled, have to explicitly\r
10234              * repaint each of the nodes to get them to display correctly, simply\r
10235              * calling repaint on the main element doesn't appear to be enough.\r
10236              */\r
10237              Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){\r
10238                  Ext.fly(el).repaint();\r
10239              });\r
10240         }\r
10241     },\r
10242     \r
10243     // private\r
10244     doDisabled : function(disabled){\r
10245         this.keyNav.setDisabled(disabled);\r
10246         this.prevRepeater.setDisabled(disabled);\r
10247         this.nextRepeater.setDisabled(disabled);\r
10248         if(this.showToday){\r
10249             this.todayKeyListener.setDisabled(disabled);\r
10250             this.todayBtn.setDisabled(disabled);\r
10251         }\r
10252     },\r
10253 \r
10254     // private\r
10255     onRender : function(container, position){\r
10256         var m = [\r
10257              '<table cellspacing="0">',\r
10258                 '<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>',\r
10259                 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],\r
10260                 dn = this.dayNames,\r
10261                 i;\r
10262         for(i = 0; i < 7; i++){\r
10263             var d = this.startDay+i;\r
10264             if(d > 6){\r
10265                 d = d-7;\r
10266             }\r
10267             m.push('<th><span>', dn[d].substr(0,1), '</span></th>');\r
10268         }\r
10269         m[m.length] = '</tr></thead><tbody><tr>';\r
10270         for(i = 0; i < 42; i++) {\r
10271             if(i % 7 === 0 && i !== 0){\r
10272                 m[m.length] = '</tr><tr>';\r
10273             }\r
10274             m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';\r
10275         }\r
10276         m.push('</tr></tbody></table></td></tr>',\r
10277                 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',\r
10278                 '</table><div class="x-date-mp"></div>');\r
10279 \r
10280         var el = document.createElement('div');\r
10281         el.className = 'x-date-picker';\r
10282         el.innerHTML = m.join('');\r
10283 \r
10284         container.dom.insertBefore(el, position);\r
10285 \r
10286         this.el = Ext.get(el);\r
10287         this.eventEl = Ext.get(el.firstChild);\r
10288 \r
10289         this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {\r
10290             handler: this.showPrevMonth,\r
10291             scope: this,\r
10292             preventDefault:true,\r
10293             stopDefault:true\r
10294         });\r
10295 \r
10296         this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {\r
10297             handler: this.showNextMonth,\r
10298             scope: this,\r
10299             preventDefault:true,\r
10300             stopDefault:true\r
10301         });\r
10302 \r
10303         this.monthPicker = this.el.down('div.x-date-mp');\r
10304         this.monthPicker.enableDisplayMode('block');\r
10305 \r
10306         this.keyNav = new Ext.KeyNav(this.eventEl, {\r
10307             'left' : function(e){\r
10308                 if(e.ctrlKey){\r
10309                     this.showPrevMonth();\r
10310                 }else{\r
10311                     this.update(this.activeDate.add('d', -1));    \r
10312                 }\r
10313             },\r
10314 \r
10315             'right' : function(e){\r
10316                 if(e.ctrlKey){\r
10317                     this.showNextMonth();\r
10318                 }else{\r
10319                     this.update(this.activeDate.add('d', 1));    \r
10320                 }\r
10321             },\r
10322 \r
10323             'up' : function(e){\r
10324                 if(e.ctrlKey){\r
10325                     this.showNextYear();\r
10326                 }else{\r
10327                     this.update(this.activeDate.add('d', -7));\r
10328                 }\r
10329             },\r
10330 \r
10331             'down' : function(e){\r
10332                 if(e.ctrlKey){\r
10333                     this.showPrevYear();\r
10334                 }else{\r
10335                     this.update(this.activeDate.add('d', 7));\r
10336                 }\r
10337             },\r
10338 \r
10339             'pageUp' : function(e){\r
10340                 this.showNextMonth();\r
10341             },\r
10342 \r
10343             'pageDown' : function(e){\r
10344                 this.showPrevMonth();\r
10345             },\r
10346 \r
10347             'enter' : function(e){\r
10348                 e.stopPropagation();\r
10349                 return true;\r
10350             },\r
10351 \r
10352             scope : this\r
10353         });\r
10354 \r
10355         this.el.unselectable();\r
10356 \r
10357         this.cells = this.el.select('table.x-date-inner tbody td');\r
10358         this.textNodes = this.el.query('table.x-date-inner tbody span');\r
10359 \r
10360         this.mbtn = new Ext.Button({\r
10361             text: '&#160;',\r
10362             tooltip: this.monthYearText,\r
10363             renderTo: this.el.child('td.x-date-middle', true)\r
10364         });\r
10365         this.mbtn.el.child('em').addClass('x-btn-arrow');\r
10366 \r
10367         if(this.showToday){\r
10368             this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);\r
10369             var today = (new Date()).dateFormat(this.format);\r
10370             this.todayBtn = new Ext.Button({\r
10371                 renderTo: this.el.child('td.x-date-bottom', true),\r
10372                 text: String.format(this.todayText, today),\r
10373                 tooltip: String.format(this.todayTip, today),\r
10374                 handler: this.selectToday,\r
10375                 scope: this\r
10376             });\r
10377         }\r
10378         this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);\r
10379         this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});\r
10380         this.mon(this.mbtn, 'click', this.showMonthPicker, this);\r
10381         this.onEnable(true);\r
10382     },\r
10383 \r
10384     // private\r
10385     createMonthPicker : function(){\r
10386         if(!this.monthPicker.dom.firstChild){\r
10387             var buf = ['<table border="0" cellspacing="0">'];\r
10388             for(var i = 0; i < 6; i++){\r
10389                 buf.push(\r
10390                     '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',\r
10391                     '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',\r
10392                     i === 0 ?\r
10393                     '<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>' :\r
10394                     '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'\r
10395                 );\r
10396             }\r
10397             buf.push(\r
10398                 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',\r
10399                     this.okText,\r
10400                     '</button><button type="button" class="x-date-mp-cancel">',\r
10401                     this.cancelText,\r
10402                     '</button></td></tr>',\r
10403                 '</table>'\r
10404             );\r
10405             this.monthPicker.update(buf.join(''));\r
10406 \r
10407             this.mon(this.monthPicker, 'click', this.onMonthClick, this);\r
10408             this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);\r
10409 \r
10410             this.mpMonths = this.monthPicker.select('td.x-date-mp-month');\r
10411             this.mpYears = this.monthPicker.select('td.x-date-mp-year');\r
10412 \r
10413             this.mpMonths.each(function(m, a, i){\r
10414                 i += 1;\r
10415                 if((i%2) === 0){\r
10416                     m.dom.xmonth = 5 + Math.round(i * 0.5);\r
10417                 }else{\r
10418                     m.dom.xmonth = Math.round((i-1) * 0.5);\r
10419                 }\r
10420             });\r
10421         }\r
10422     },\r
10423 \r
10424     // private\r
10425     showMonthPicker : function(){\r
10426         if(!this.disabled){\r
10427             this.createMonthPicker();\r
10428             var size = this.el.getSize();\r
10429             this.monthPicker.setSize(size);\r
10430             this.monthPicker.child('table').setSize(size);\r
10431 \r
10432             this.mpSelMonth = (this.activeDate || this.value).getMonth();\r
10433             this.updateMPMonth(this.mpSelMonth);\r
10434             this.mpSelYear = (this.activeDate || this.value).getFullYear();\r
10435             this.updateMPYear(this.mpSelYear);\r
10436 \r
10437             this.monthPicker.slideIn('t', {duration:0.2});\r
10438         }\r
10439     },\r
10440 \r
10441     // private\r
10442     updateMPYear : function(y){\r
10443         this.mpyear = y;\r
10444         var ys = this.mpYears.elements;\r
10445         for(var i = 1; i <= 10; i++){\r
10446             var td = ys[i-1], y2;\r
10447             if((i%2) === 0){\r
10448                 y2 = y + Math.round(i * 0.5);\r
10449                 td.firstChild.innerHTML = y2;\r
10450                 td.xyear = y2;\r
10451             }else{\r
10452                 y2 = y - (5-Math.round(i * 0.5));\r
10453                 td.firstChild.innerHTML = y2;\r
10454                 td.xyear = y2;\r
10455             }\r
10456             this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');\r
10457         }\r
10458     },\r
10459 \r
10460     // private\r
10461     updateMPMonth : function(sm){\r
10462         this.mpMonths.each(function(m, a, i){\r
10463             m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');\r
10464         });\r
10465     },\r
10466 \r
10467     // private\r
10468     selectMPMonth : function(m){\r
10469 \r
10470     },\r
10471 \r
10472     // private\r
10473     onMonthClick : function(e, t){\r
10474         e.stopEvent();\r
10475         var el = new Ext.Element(t), pn;\r
10476         if(el.is('button.x-date-mp-cancel')){\r
10477             this.hideMonthPicker();\r
10478         }\r
10479         else if(el.is('button.x-date-mp-ok')){\r
10480             var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());\r
10481             if(d.getMonth() != this.mpSelMonth){\r
10482                 // 'fix' the JS rolling date conversion if needed\r
10483                 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();\r
10484             }\r
10485             this.update(d);\r
10486             this.hideMonthPicker();\r
10487         }\r
10488         else if((pn = el.up('td.x-date-mp-month', 2))){\r
10489             this.mpMonths.removeClass('x-date-mp-sel');\r
10490             pn.addClass('x-date-mp-sel');\r
10491             this.mpSelMonth = pn.dom.xmonth;\r
10492         }\r
10493         else if((pn = el.up('td.x-date-mp-year', 2))){\r
10494             this.mpYears.removeClass('x-date-mp-sel');\r
10495             pn.addClass('x-date-mp-sel');\r
10496             this.mpSelYear = pn.dom.xyear;\r
10497         }\r
10498         else if(el.is('a.x-date-mp-prev')){\r
10499             this.updateMPYear(this.mpyear-10);\r
10500         }\r
10501         else if(el.is('a.x-date-mp-next')){\r
10502             this.updateMPYear(this.mpyear+10);\r
10503         }\r
10504     },\r
10505 \r
10506     // private\r
10507     onMonthDblClick : function(e, t){\r
10508         e.stopEvent();\r
10509         var el = new Ext.Element(t), pn;\r
10510         if((pn = el.up('td.x-date-mp-month', 2))){\r
10511             this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));\r
10512             this.hideMonthPicker();\r
10513         }\r
10514         else if((pn = el.up('td.x-date-mp-year', 2))){\r
10515             this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));\r
10516             this.hideMonthPicker();\r
10517         }\r
10518     },\r
10519 \r
10520     // private\r
10521     hideMonthPicker : function(disableAnim){\r
10522         if(this.monthPicker){\r
10523             if(disableAnim === true){\r
10524                 this.monthPicker.hide();\r
10525             }else{\r
10526                 this.monthPicker.slideOut('t', {duration:0.2});\r
10527             }\r
10528         }\r
10529     },\r
10530 \r
10531     // private\r
10532     showPrevMonth : function(e){\r
10533         this.update(this.activeDate.add('mo', -1));\r
10534     },\r
10535 \r
10536     // private\r
10537     showNextMonth : function(e){\r
10538         this.update(this.activeDate.add('mo', 1));\r
10539     },\r
10540 \r
10541     // private\r
10542     showPrevYear : function(){\r
10543         this.update(this.activeDate.add('y', -1));\r
10544     },\r
10545 \r
10546     // private\r
10547     showNextYear : function(){\r
10548         this.update(this.activeDate.add('y', 1));\r
10549     },\r
10550 \r
10551     // private\r
10552     handleMouseWheel : function(e){\r
10553         e.stopEvent();\r
10554         if(!this.disabled){\r
10555             var delta = e.getWheelDelta();\r
10556             if(delta > 0){\r
10557                 this.showPrevMonth();\r
10558             } else if(delta < 0){\r
10559                 this.showNextMonth();\r
10560             }\r
10561         }\r
10562     },\r
10563 \r
10564     // private\r
10565     handleDateClick : function(e, t){\r
10566         e.stopEvent();\r
10567         if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){\r
10568             this.setValue(new Date(t.dateValue));\r
10569             this.fireEvent('select', this, this.value);\r
10570         }\r
10571     },\r
10572 \r
10573     // private\r
10574     selectToday : function(){\r
10575         if(this.todayBtn && !this.todayBtn.disabled){\r
10576             this.setValue(new Date().clearTime());\r
10577             this.fireEvent('select', this, this.value);\r
10578         }\r
10579     },\r
10580 \r
10581     // private\r
10582     update : function(date, forceRefresh){\r
10583         if(this.rendered){\r
10584                 var vd = this.activeDate, vis = this.isVisible();\r
10585                 this.activeDate = date;\r
10586                 if(!forceRefresh && vd && this.el){\r
10587                     var t = date.getTime();\r
10588                     if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){\r
10589                         this.cells.removeClass('x-date-selected');\r
10590                         this.cells.each(function(c){\r
10591                            if(c.dom.firstChild.dateValue == t){\r
10592                                c.addClass('x-date-selected');\r
10593                                if(vis){\r
10594                                    Ext.fly(c.dom.firstChild).focus(50);\r
10595                                }\r
10596                                return false;\r
10597                            }\r
10598                         });\r
10599                         return;\r
10600                     }\r
10601                 }\r
10602                 var days = date.getDaysInMonth(),\r
10603                     firstOfMonth = date.getFirstDateOfMonth(),\r
10604                     startingPos = firstOfMonth.getDay()-this.startDay;\r
10605         \r
10606                 if(startingPos < 0){\r
10607                     startingPos += 7;\r
10608                 }\r
10609                 days += startingPos;\r
10610         \r
10611                 var pm = date.add('mo', -1),\r
10612                     prevStart = pm.getDaysInMonth()-startingPos,\r
10613                     cells = this.cells.elements,\r
10614                     textEls = this.textNodes,\r
10615                     // convert everything to numbers so it's fast\r
10616                     day = 86400000,\r
10617                     d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime(),\r
10618                     today = new Date().clearTime().getTime(),\r
10619                     sel = date.clearTime(true).getTime(),\r
10620                     min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,\r
10621                     max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,\r
10622                     ddMatch = this.disabledDatesRE,\r
10623                     ddText = this.disabledDatesText,\r
10624                     ddays = this.disabledDays ? this.disabledDays.join('') : false,\r
10625                     ddaysText = this.disabledDaysText,\r
10626                     format = this.format;\r
10627         \r
10628                 if(this.showToday){\r
10629                     var td = new Date().clearTime(),\r
10630                         disable = (td < min || td > max ||\r
10631                         (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||\r
10632                         (ddays && ddays.indexOf(td.getDay()) != -1));\r
10633         \r
10634                     if(!this.disabled){\r
10635                         this.todayBtn.setDisabled(disable);\r
10636                         this.todayKeyListener[disable ? 'disable' : 'enable']();\r
10637                     }\r
10638                 }\r
10639         \r
10640                 var setCellClass = function(cal, cell){\r
10641                     cell.title = '';\r
10642                     var t = d.getTime();\r
10643                     cell.firstChild.dateValue = t;\r
10644                     if(t == today){\r
10645                         cell.className += ' x-date-today';\r
10646                         cell.title = cal.todayText;\r
10647                     }\r
10648                     if(t == sel){\r
10649                         cell.className += ' x-date-selected';\r
10650                         if(vis){\r
10651                             Ext.fly(cell.firstChild).focus(50);\r
10652                         }\r
10653                     }\r
10654                     // disabling\r
10655                     if(t < min) {\r
10656                         cell.className = ' x-date-disabled';\r
10657                         cell.title = cal.minText;\r
10658                         return;\r
10659                     }\r
10660                     if(t > max) {\r
10661                         cell.className = ' x-date-disabled';\r
10662                         cell.title = cal.maxText;\r
10663                         return;\r
10664                     }\r
10665                     if(ddays){\r
10666                         if(ddays.indexOf(d.getDay()) != -1){\r
10667                             cell.title = ddaysText;\r
10668                             cell.className = ' x-date-disabled';\r
10669                         }\r
10670                     }\r
10671                     if(ddMatch && format){\r
10672                         var fvalue = d.dateFormat(format);\r
10673                         if(ddMatch.test(fvalue)){\r
10674                             cell.title = ddText.replace('%0', fvalue);\r
10675                             cell.className = ' x-date-disabled';\r
10676                         }\r
10677                     }\r
10678                 };\r
10679         \r
10680                 var i = 0;\r
10681                 for(; i < startingPos; i++) {\r
10682                     textEls[i].innerHTML = (++prevStart);\r
10683                     d.setDate(d.getDate()+1);\r
10684                     cells[i].className = 'x-date-prevday';\r
10685                     setCellClass(this, cells[i]);\r
10686                 }\r
10687                 for(; i < days; i++){\r
10688                     var intDay = i - startingPos + 1;\r
10689                     textEls[i].innerHTML = (intDay);\r
10690                     d.setDate(d.getDate()+1);\r
10691                     cells[i].className = 'x-date-active';\r
10692                     setCellClass(this, cells[i]);\r
10693                 }\r
10694                 var extraDays = 0;\r
10695                 for(; i < 42; i++) {\r
10696                      textEls[i].innerHTML = (++extraDays);\r
10697                      d.setDate(d.getDate()+1);\r
10698                      cells[i].className = 'x-date-nextday';\r
10699                      setCellClass(this, cells[i]);\r
10700                 }\r
10701         \r
10702                 this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());\r
10703         \r
10704                 if(!this.internalRender){\r
10705                     var main = this.el.dom.firstChild,\r
10706                         w = main.offsetWidth;\r
10707                     this.el.setWidth(w + this.el.getBorderWidth('lr'));\r
10708                     Ext.fly(main).setWidth(w);\r
10709                     this.internalRender = true;\r
10710                     // opera does not respect the auto grow header center column\r
10711                     // then, after it gets a width opera refuses to recalculate\r
10712                     // without a second pass\r
10713                     if(Ext.isOpera && !this.secondPass){\r
10714                         main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';\r
10715                         this.secondPass = true;\r
10716                         this.update.defer(10, this, [date]);\r
10717                     }\r
10718                 }\r
10719         }\r
10720     },\r
10721 \r
10722     // private\r
10723     beforeDestroy : function() {\r
10724         if(this.rendered){\r
10725             this.keyNav.disable();\r
10726             this.keyNav = null;\r
10727             Ext.destroy(\r
10728                 this.leftClickRpt,\r
10729                 this.rightClickRpt,\r
10730                 this.monthPicker,\r
10731                 this.eventEl,\r
10732                 this.mbtn,\r
10733                 this.todayBtn\r
10734             );\r
10735         }\r
10736     }\r
10737 \r
10738     /**\r
10739      * @cfg {String} autoEl @hide\r
10740      */\r
10741 });\r
10742 \r
10743 Ext.reg('datepicker', Ext.DatePicker);\r
10744 /**
10745  * @class Ext.LoadMask
10746  * A simple utility class for generically masking elements while loading data.  If the {@link #store}
10747  * config option is specified, the masking will be automatically synchronized with the store's loading
10748  * process and the mask element will be cached for reuse.  For all other elements, this mask will replace the
10749  * element's Updater load indicator and will be destroyed after the initial load.
10750  * <p>Example usage:</p>
10751  *<pre><code>
10752 // Basic mask:
10753 var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
10754 myMask.show();
10755 </code></pre>
10756  * @constructor
10757  * Create a new LoadMask
10758  * @param {Mixed} el The element or DOM node, or its id
10759  * @param {Object} config The config object
10760  */
10761 Ext.LoadMask = function(el, config){
10762     this.el = Ext.get(el);
10763     Ext.apply(this, config);
10764     if(this.store){
10765         this.store.on('beforeload', this.onBeforeLoad, this);
10766         this.store.on('load', this.onLoad, this);
10767         this.store.on('exception', this.onLoad, this);
10768         this.removeMask = Ext.value(this.removeMask, false);
10769     }else{
10770         var um = this.el.getUpdater();
10771         um.showLoadIndicator = false; // disable the default indicator
10772         um.on('beforeupdate', this.onBeforeLoad, this);
10773         um.on('update', this.onLoad, this);
10774         um.on('failure', this.onLoad, this);
10775         this.removeMask = Ext.value(this.removeMask, true);
10776     }
10777 };
10778
10779 Ext.LoadMask.prototype = {
10780     /**
10781      * @cfg {Ext.data.Store} store
10782      * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and
10783      * hidden on either load sucess, or load fail.
10784      */
10785     /**
10786      * @cfg {Boolean} removeMask
10787      * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
10788      * False to persist the mask element reference for multiple uses (e.g., for paged data widgets).  Defaults to false.
10789      */
10790     /**
10791      * @cfg {String} msg
10792      * The text to display in a centered loading message box (defaults to 'Loading...')
10793      */
10794     msg : 'Loading...',
10795     /**
10796      * @cfg {String} msgCls
10797      * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
10798      */
10799     msgCls : 'x-mask-loading',
10800
10801     /**
10802      * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
10803      * @type Boolean
10804      */
10805     disabled: false,
10806
10807     /**
10808      * Disables the mask to prevent it from being displayed
10809      */
10810     disable : function(){
10811        this.disabled = true;
10812     },
10813
10814     /**
10815      * Enables the mask so that it can be displayed
10816      */
10817     enable : function(){
10818         this.disabled = false;
10819     },
10820
10821     // private
10822     onLoad : function(){
10823         this.el.unmask(this.removeMask);
10824     },
10825
10826     // private
10827     onBeforeLoad : function(){
10828         if(!this.disabled){
10829             this.el.mask(this.msg, this.msgCls);
10830         }
10831     },
10832
10833     /**
10834      * Show this LoadMask over the configured Element.
10835      */
10836     show: function(){
10837         this.onBeforeLoad();
10838     },
10839
10840     /**
10841      * Hide this LoadMask.
10842      */
10843     hide: function(){
10844         this.onLoad();
10845     },
10846
10847     // private
10848     destroy : function(){
10849         if(this.store){
10850             this.store.un('beforeload', this.onBeforeLoad, this);
10851             this.store.un('load', this.onLoad, this);
10852             this.store.un('exception', this.onLoad, this);
10853         }else{
10854             var um = this.el.getUpdater();
10855             um.un('beforeupdate', this.onBeforeLoad, this);
10856             um.un('update', this.onLoad, this);
10857             um.un('failure', this.onLoad, this);
10858         }
10859     }
10860 };/**\r
10861  * @class Ext.Slider\r
10862  * @extends Ext.BoxComponent\r
10863  * Slider which supports vertical or horizontal orientation, keyboard adjustments,\r
10864  * configurable snapping, axis clicking and animation. Can be added as an item to\r
10865  * any container. Example usage:\r
10866 <pre><code>\r
10867 new Ext.Slider({\r
10868     renderTo: Ext.getBody(),\r
10869     width: 200,\r
10870     value: 50,\r
10871     increment: 10,\r
10872     minValue: 0,\r
10873     maxValue: 100\r
10874 });\r
10875 </code></pre>\r
10876  */\r
10877 Ext.Slider = Ext.extend(Ext.BoxComponent, {\r
10878         /**\r
10879          * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.\r
10880          */\r
10881         /**\r
10882          * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.\r
10883          */\r
10884     vertical: false,\r
10885         /**\r
10886          * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.\r
10887          */\r
10888     minValue: 0,\r
10889         /**\r
10890          * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.\r
10891          */\r
10892     maxValue: 100,\r
10893     /**\r
10894      * @cfg {Number/Boolean} decimalPrecision.\r
10895      * <p>The number of decimal places to which to round the Slider's value. Defaults to 0.</p>\r
10896      * <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>\r
10897      */\r
10898     decimalPrecision: 0,\r
10899         /**\r
10900          * @cfg {Number} keyIncrement How many units to change the Slider when adjusting with keyboard navigation. Defaults to 1. If the increment config is larger, it will be used instead.\r
10901          */\r
10902     keyIncrement: 1,\r
10903         /**\r
10904          * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.\r
10905          */\r
10906     increment: 0,\r
10907         // private\r
10908     clickRange: [5,15],\r
10909         /**\r
10910          * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true\r
10911          */\r
10912     clickToChange : true,\r
10913         /**\r
10914          * @cfg {Boolean} animate Turn on or off animation. Defaults to true\r
10915          */\r
10916     animate: true,\r
10917 \r
10918     /**\r
10919      * True while the thumb is in a drag operation\r
10920      * @type boolean\r
10921      */\r
10922     dragging: false,\r
10923 \r
10924     // private override\r
10925     initComponent : function(){\r
10926         if(!Ext.isDefined(this.value)){\r
10927             this.value = this.minValue;\r
10928         }\r
10929         Ext.Slider.superclass.initComponent.call(this);\r
10930         this.keyIncrement = Math.max(this.increment, this.keyIncrement);\r
10931         this.addEvents(\r
10932             /**\r
10933              * @event beforechange\r
10934              * Fires before the slider value is changed. By returning false from an event handler,\r
10935              * you can cancel the event and prevent the slider from changing.\r
10936                          * @param {Ext.Slider} slider The slider\r
10937                          * @param {Number} newValue The new value which the slider is being changed to.\r
10938                          * @param {Number} oldValue The old value which the slider was previously.\r
10939              */\r
10940                         'beforechange',\r
10941                         /**\r
10942                          * @event change\r
10943                          * Fires when the slider value is changed.\r
10944                          * @param {Ext.Slider} slider The slider\r
10945                          * @param {Number} newValue The new value which the slider has been changed to.\r
10946                          */\r
10947                         'change',\r
10948                         /**\r
10949                          * @event changecomplete\r
10950                          * Fires when the slider value is changed by the user and any drag operations have completed.\r
10951                          * @param {Ext.Slider} slider The slider\r
10952                          * @param {Number} newValue The new value which the slider has been changed to.\r
10953                          */\r
10954                         'changecomplete',\r
10955                         /**\r
10956                          * @event dragstart\r
10957              * Fires after a drag operation has started.\r
10958                          * @param {Ext.Slider} slider The slider\r
10959                          * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
10960                          */\r
10961                         'dragstart',\r
10962                         /**\r
10963                          * @event drag\r
10964              * Fires continuously during the drag operation while the mouse is moving.\r
10965                          * @param {Ext.Slider} slider The slider\r
10966                          * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
10967                          */\r
10968                         'drag',\r
10969                         /**\r
10970                          * @event dragend\r
10971              * Fires after the drag operation has completed.\r
10972                          * @param {Ext.Slider} slider The slider\r
10973                          * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
10974                          */\r
10975                         'dragend'\r
10976                 );\r
10977 \r
10978         if(this.vertical){\r
10979             Ext.apply(this, Ext.Slider.Vertical);\r
10980         }\r
10981     },\r
10982 \r
10983         // private override\r
10984     onRender : function(){\r
10985         this.autoEl = {\r
10986             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),\r
10987             cn:{cls:'x-slider-end',cn:{cls:'x-slider-inner',cn:[{cls:'x-slider-thumb'},{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]}}\r
10988         };\r
10989         Ext.Slider.superclass.onRender.apply(this, arguments);\r
10990         this.endEl = this.el.first();\r
10991         this.innerEl = this.endEl.first();\r
10992         this.thumb = this.innerEl.first();\r
10993         this.halfThumb = (this.vertical ? this.thumb.getHeight() : this.thumb.getWidth())/2;\r
10994         this.focusEl = this.thumb.next();\r
10995         this.initEvents();\r
10996     },\r
10997 \r
10998         // private override\r
10999     initEvents : function(){\r
11000         this.thumb.addClassOnOver('x-slider-thumb-over');\r
11001         this.mon(this.el, {\r
11002             scope: this,\r
11003             mousedown: this.onMouseDown,\r
11004             keydown: this.onKeyDown\r
11005         });\r
11006 \r
11007         this.focusEl.swallowEvent("click", true);\r
11008 \r
11009         this.tracker = new Ext.dd.DragTracker({\r
11010             onBeforeStart: this.onBeforeDragStart.createDelegate(this),\r
11011             onStart: this.onDragStart.createDelegate(this),\r
11012             onDrag: this.onDrag.createDelegate(this),\r
11013             onEnd: this.onDragEnd.createDelegate(this),\r
11014             tolerance: 3,\r
11015             autoStart: 300\r
11016         });\r
11017         this.tracker.initEl(this.thumb);\r
11018         this.on('beforedestroy', this.tracker.destroy, this.tracker);\r
11019     },\r
11020 \r
11021         // private override\r
11022     onMouseDown : function(e){\r
11023         if(this.disabled) {return;}\r
11024         if(this.clickToChange && e.target != this.thumb.dom){\r
11025             var local = this.innerEl.translatePoints(e.getXY());\r
11026             this.onClickChange(local);\r
11027         }\r
11028         this.focus();\r
11029     },\r
11030 \r
11031         // private\r
11032     onClickChange : function(local){\r
11033         if(local.top > this.clickRange[0] && local.top < this.clickRange[1]){\r
11034             this.setValue(Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);\r
11035         }\r
11036     },\r
11037 \r
11038         // private\r
11039     onKeyDown : function(e){\r
11040         if(this.disabled){e.preventDefault();return;}\r
11041         var k = e.getKey();\r
11042         switch(k){\r
11043             case e.UP:\r
11044             case e.RIGHT:\r
11045                 e.stopEvent();\r
11046                 if(e.ctrlKey){\r
11047                     this.setValue(this.maxValue, undefined, true);\r
11048                 }else{\r
11049                     this.setValue(this.value+this.keyIncrement, undefined, true);\r
11050                 }\r
11051             break;\r
11052             case e.DOWN:\r
11053             case e.LEFT:\r
11054                 e.stopEvent();\r
11055                 if(e.ctrlKey){\r
11056                     this.setValue(this.minValue, undefined, true);\r
11057                 }else{\r
11058                     this.setValue(this.value-this.keyIncrement, undefined, true);\r
11059                 }\r
11060             break;\r
11061             default:\r
11062                 e.preventDefault();\r
11063         }\r
11064     },\r
11065 \r
11066         // private\r
11067     doSnap : function(value){\r
11068         if(!this.increment || this.increment == 1 || !value) {\r
11069             return value;\r
11070         }\r
11071         var newValue = value, inc = this.increment;\r
11072         var m = value % inc;\r
11073         if(m != 0){\r
11074             newValue -= m;\r
11075             if(m * 2 > inc){\r
11076                 newValue += inc;\r
11077             }else if(m * 2 < -inc){\r
11078                 newValue -= inc;\r
11079             }\r
11080         }\r
11081         return newValue.constrain(this.minValue,  this.maxValue);\r
11082     },\r
11083 \r
11084         // private\r
11085     afterRender : function(){\r
11086         Ext.Slider.superclass.afterRender.apply(this, arguments);\r
11087         if(this.value !== undefined){\r
11088             var v = this.normalizeValue(this.value);\r
11089             if(v !== this.value){\r
11090                 delete this.value;\r
11091                 this.setValue(v, false);\r
11092             }else{\r
11093                 this.moveThumb(this.translateValue(v), false);\r
11094             }\r
11095         }\r
11096     },\r
11097 \r
11098         // private\r
11099     getRatio : function(){\r
11100         var w = this.innerEl.getWidth();\r
11101         var v = this.maxValue - this.minValue;\r
11102         return v == 0 ? w : (w/v);\r
11103     },\r
11104 \r
11105         // private\r
11106     normalizeValue : function(v){\r
11107         v = this.doSnap(v);\r
11108         v = Ext.util.Format.round(v, this.decimalPrecision);\r
11109         v = v.constrain(this.minValue, this.maxValue);\r
11110         return v;\r
11111     },\r
11112 \r
11113         /**\r
11114          * Programmatically sets the value of the Slider. Ensures that the value is constrained within\r
11115          * the minValue and maxValue.\r
11116          * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)\r
11117          * @param {Boolean} animate Turn on or off animation, defaults to true\r
11118          */\r
11119     setValue : function(v, animate, changeComplete){\r
11120         v = this.normalizeValue(v);\r
11121         if(v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false){\r
11122             this.value = v;\r
11123             this.moveThumb(this.translateValue(v), animate !== false);\r
11124             this.fireEvent('change', this, v);\r
11125             if(changeComplete){\r
11126                 this.fireEvent('changecomplete', this, v);\r
11127             }\r
11128         }\r
11129     },\r
11130 \r
11131         // private\r
11132     translateValue : function(v){\r
11133         var ratio = this.getRatio();\r
11134         return (v * ratio)-(this.minValue * ratio)-this.halfThumb;\r
11135     },\r
11136 \r
11137         reverseValue : function(pos){\r
11138         var ratio = this.getRatio();\r
11139         return (pos+this.halfThumb+(this.minValue * ratio))/ratio;\r
11140     },\r
11141 \r
11142         // private\r
11143     moveThumb: function(v, animate){\r
11144         if(!animate || this.animate === false){\r
11145             this.thumb.setLeft(v);\r
11146         }else{\r
11147             this.thumb.shift({left: v, stopFx: true, duration:.35});\r
11148         }\r
11149     },\r
11150 \r
11151         // private\r
11152     focus : function(){\r
11153         this.focusEl.focus(10);\r
11154     },\r
11155 \r
11156         // private\r
11157     onBeforeDragStart : function(e){\r
11158         return !this.disabled;\r
11159     },\r
11160 \r
11161         // private\r
11162     onDragStart: function(e){\r
11163         this.thumb.addClass('x-slider-thumb-drag');\r
11164         this.dragging = true;\r
11165         this.dragStartValue = this.value;\r
11166         this.fireEvent('dragstart', this, e);\r
11167     },\r
11168 \r
11169         // private\r
11170     onDrag: function(e){\r
11171         var pos = this.innerEl.translatePoints(this.tracker.getXY());\r
11172         this.setValue(Ext.util.Format.round(this.reverseValue(pos.left), this.decimalPrecision), false);\r
11173         this.fireEvent('drag', this, e);\r
11174     },\r
11175 \r
11176         // private\r
11177     onDragEnd: function(e){\r
11178         this.thumb.removeClass('x-slider-thumb-drag');\r
11179         this.dragging = false;\r
11180         this.fireEvent('dragend', this, e);\r
11181         if(this.dragStartValue != this.value){\r
11182             this.fireEvent('changecomplete', this, this.value);\r
11183         }\r
11184     },\r
11185 \r
11186         // private\r
11187     onResize : function(w, h){\r
11188         this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));\r
11189         this.syncThumb();\r
11190     },\r
11191     \r
11192     //private\r
11193     onDisable: function(){\r
11194         Ext.Slider.superclass.onDisable.call(this);\r
11195         this.thumb.addClass(this.disabledClass);\r
11196         if(Ext.isIE){\r
11197             //IE breaks when using overflow visible and opacity other than 1.\r
11198             //Create a place holder for the thumb and display it.\r
11199             var xy = this.thumb.getXY();\r
11200             this.thumb.hide();\r
11201             this.innerEl.addClass(this.disabledClass).dom.disabled = true;\r
11202             if (!this.thumbHolder){\r
11203                 this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});    \r
11204             }\r
11205             this.thumbHolder.show().setXY(xy);\r
11206         }\r
11207     },\r
11208     \r
11209     //private\r
11210     onEnable: function(){\r
11211         Ext.Slider.superclass.onEnable.call(this);\r
11212         this.thumb.removeClass(this.disabledClass);\r
11213         if(Ext.isIE){\r
11214             this.innerEl.removeClass(this.disabledClass).dom.disabled = false;\r
11215             if (this.thumbHolder){\r
11216                 this.thumbHolder.hide();\r
11217             }\r
11218             this.thumb.show();\r
11219             this.syncThumb();\r
11220         }\r
11221     },\r
11222     \r
11223     /**\r
11224      * Synchronizes the thumb position to the proper proportion of the total component width based\r
11225      * on the current slider {@link #value}.  This will be called automatically when the Slider\r
11226      * is resized by a layout, but if it is rendered auto width, this method can be called from\r
11227      * another resize handler to sync the Slider if necessary.\r
11228      */\r
11229     syncThumb : function(){\r
11230         if(this.rendered){\r
11231             this.moveThumb(this.translateValue(this.value));\r
11232         }\r
11233     },\r
11234 \r
11235         /**\r
11236          * Returns the current value of the slider\r
11237          * @return {Number} The current value of the slider\r
11238          */\r
11239     getValue : function(){\r
11240         return this.value;\r
11241     }\r
11242 });\r
11243 Ext.reg('slider', Ext.Slider);\r
11244 \r
11245 // private class to support vertical sliders\r
11246 Ext.Slider.Vertical = {\r
11247     onResize : function(w, h){\r
11248         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));\r
11249         this.syncThumb();\r
11250     },\r
11251 \r
11252     getRatio : function(){\r
11253         var h = this.innerEl.getHeight();\r
11254         var v = this.maxValue - this.minValue;\r
11255         return h/v;\r
11256     },\r
11257 \r
11258     moveThumb: function(v, animate){\r
11259         if(!animate || this.animate === false){\r
11260             this.thumb.setBottom(v);\r
11261         }else{\r
11262             this.thumb.shift({bottom: v, stopFx: true, duration:.35});\r
11263         }\r
11264     },\r
11265 \r
11266     onDrag: function(e){\r
11267         var pos = this.innerEl.translatePoints(this.tracker.getXY());\r
11268         var bottom = this.innerEl.getHeight()-pos.top;\r
11269         this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), false);\r
11270         this.fireEvent('drag', this, e);\r
11271     },\r
11272 \r
11273     onClickChange : function(local){\r
11274         if(local.left > this.clickRange[0] && local.left < this.clickRange[1]){\r
11275             var bottom = this.innerEl.getHeight()-local.top;\r
11276             this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), undefined, true);\r
11277         }\r
11278     }\r
11279 };/**\r
11280  * @class Ext.ProgressBar\r
11281  * @extends Ext.BoxComponent\r
11282  * <p>An updateable progress bar component.  The progress bar supports two different modes: manual and automatic.</p>\r
11283  * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the\r
11284  * progress bar as needed from your own code.  This method is most appropriate when you want to show progress\r
11285  * throughout an operation that has predictable points of interest at which you can update the control.</p>\r
11286  * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it\r
11287  * once the operation is complete.  You can optionally have the progress bar wait for a specific amount of time\r
11288  * and then clear itself.  Automatic mode is most appropriate for timed operations or asynchronous operations in\r
11289  * which you have no need for indicating intermediate progress.</p>\r
11290  * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0)\r
11291  * @cfg {String} text The progress bar text (defaults to '')\r
11292  * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress\r
11293  * bar's internal text element)\r
11294  * @cfg {String} id The progress bar element's id (defaults to an auto-generated id)\r
11295  * @xtype progress\r
11296  */\r
11297 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {\r
11298    /**\r
11299     * @cfg {String} baseCls\r
11300     * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress')\r
11301     */\r
11302     baseCls : 'x-progress',\r
11303     \r
11304     /**\r
11305     * @cfg {Boolean} animate\r
11306     * True to animate the progress bar during transitions (defaults to false)\r
11307     */\r
11308     animate : false,\r
11309 \r
11310     // private\r
11311     waitTimer : null,\r
11312 \r
11313     // private\r
11314     initComponent : function(){\r
11315         Ext.ProgressBar.superclass.initComponent.call(this);\r
11316         this.addEvents(\r
11317             /**\r
11318              * @event update\r
11319              * Fires after each update interval\r
11320              * @param {Ext.ProgressBar} this\r
11321              * @param {Number} The current progress value\r
11322              * @param {String} The current progress text\r
11323              */\r
11324             "update"\r
11325         );\r
11326     },\r
11327 \r
11328     // private\r
11329     onRender : function(ct, position){\r
11330         var tpl = new Ext.Template(\r
11331             '<div class="{cls}-wrap">',\r
11332                 '<div class="{cls}-inner">',\r
11333                     '<div class="{cls}-bar">',\r
11334                         '<div class="{cls}-text">',\r
11335                             '<div>&#160;</div>',\r
11336                         '</div>',\r
11337                     '</div>',\r
11338                     '<div class="{cls}-text {cls}-text-back">',\r
11339                         '<div>&#160;</div>',\r
11340                     '</div>',\r
11341                 '</div>',\r
11342             '</div>'\r
11343         );\r
11344 \r
11345         this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)\r
11346                 : tpl.append(ct, {cls: this.baseCls}, true);\r
11347                         \r
11348         if(this.id){\r
11349             this.el.dom.id = this.id;\r
11350         }\r
11351         var inner = this.el.dom.firstChild;\r
11352         this.progressBar = Ext.get(inner.firstChild);\r
11353 \r
11354         if(this.textEl){\r
11355             //use an external text el\r
11356             this.textEl = Ext.get(this.textEl);\r
11357             delete this.textTopEl;\r
11358         }else{\r
11359             //setup our internal layered text els\r
11360             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);\r
11361             var textBackEl = Ext.get(inner.childNodes[1]);\r
11362             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');\r
11363             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);\r
11364             this.textEl.setWidth(inner.offsetWidth);\r
11365         }\r
11366         this.progressBar.setHeight(inner.offsetHeight);\r
11367     },\r
11368     \r
11369     // private\r
11370     afterRender : function(){\r
11371         Ext.ProgressBar.superclass.afterRender.call(this);\r
11372         if(this.value){\r
11373             this.updateProgress(this.value, this.text);\r
11374         }else{\r
11375             this.updateText(this.text);\r
11376         }\r
11377     },\r
11378 \r
11379     /**\r
11380      * Updates the progress bar value, and optionally its text.  If the text argument is not specified,\r
11381      * any existing text value will be unchanged.  To blank out existing text, pass ''.  Note that even\r
11382      * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for\r
11383      * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control.\r
11384      * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0)\r
11385      * @param {String} text (optional) The string to display in the progress text element (defaults to '')\r
11386      * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is\r
11387      * not specified, the default for the class is used (default to false)\r
11388      * @return {Ext.ProgressBar} this\r
11389      */\r
11390     updateProgress : function(value, text, animate){\r
11391         this.value = value || 0;\r
11392         if(text){\r
11393             this.updateText(text);\r
11394         }\r
11395         if(this.rendered){\r
11396             var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);\r
11397             this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));\r
11398             if(this.textTopEl){\r
11399                 //textTopEl should be the same width as the bar so overflow will clip as the bar moves\r
11400                 this.textTopEl.removeClass('x-hidden').setWidth(w);\r
11401             }\r
11402         }\r
11403         this.fireEvent('update', this, value, text);\r
11404         return this;\r
11405     },\r
11406 \r
11407     /**\r
11408      * Initiates an auto-updating progress bar.  A duration can be specified, in which case the progress\r
11409      * bar will automatically reset after a fixed amount of time and optionally call a callback function\r
11410      * if specified.  If no duration is passed in, then the progress bar will run indefinitely and must\r
11411      * be manually cleared by calling {@link #reset}.  The wait method accepts a config object with\r
11412      * the following properties:\r
11413      * <pre>\r
11414 Property   Type          Description\r
11415 ---------- ------------  ----------------------------------------------------------------------\r
11416 duration   Number        The length of time in milliseconds that the progress bar should\r
11417                          run before resetting itself (defaults to undefined, in which case it\r
11418                          will run indefinitely until reset is called)\r
11419 interval   Number        The length of time in milliseconds between each progress update\r
11420                          (defaults to 1000 ms)\r
11421 animate    Boolean       Whether to animate the transition of the progress bar. If this value is\r
11422                          not specified, the default for the class is used.                                                   \r
11423 increment  Number        The number of progress update segments to display within the progress\r
11424                          bar (defaults to 10).  If the bar reaches the end and is still\r
11425                          updating, it will automatically wrap back to the beginning.\r
11426 text       String        Optional text to display in the progress bar element (defaults to '').\r
11427 fn         Function      A callback function to execute after the progress bar finishes auto-\r
11428                          updating.  The function will be called with no arguments.  This function\r
11429                          will be ignored if duration is not specified since in that case the\r
11430                          progress bar can only be stopped programmatically, so any required function\r
11431                          should be called by the same code after it resets the progress bar.\r
11432 scope      Object        The scope that is passed to the callback function (only applies when\r
11433                          duration and fn are both passed).\r
11434 </pre>\r
11435          *\r
11436          * Example usage:\r
11437          * <pre><code>\r
11438 var p = new Ext.ProgressBar({\r
11439    renderTo: 'my-el'\r
11440 });\r
11441 \r
11442 //Wait for 5 seconds, then update the status el (progress bar will auto-reset)\r
11443 p.wait({\r
11444    interval: 100, //bar will move fast!\r
11445    duration: 5000,\r
11446    increment: 15,\r
11447    text: 'Updating...',\r
11448    scope: this,\r
11449    fn: function(){\r
11450       Ext.fly('status').update('Done!');\r
11451    }\r
11452 });\r
11453 \r
11454 //Or update indefinitely until some async action completes, then reset manually\r
11455 p.wait();\r
11456 myAction.on('complete', function(){\r
11457     p.reset();\r
11458     Ext.fly('status').update('Done!');\r
11459 });\r
11460 </code></pre>\r
11461      * @param {Object} config (optional) Configuration options\r
11462      * @return {Ext.ProgressBar} this\r
11463      */\r
11464     wait : function(o){\r
11465         if(!this.waitTimer){\r
11466             var scope = this;\r
11467             o = o || {};\r
11468             this.updateText(o.text);\r
11469             this.waitTimer = Ext.TaskMgr.start({\r
11470                 run: function(i){\r
11471                     var inc = o.increment || 10;\r
11472                     i -= 1;\r
11473                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);\r
11474                 },\r
11475                 interval: o.interval || 1000,\r
11476                 duration: o.duration,\r
11477                 onStop: function(){\r
11478                     if(o.fn){\r
11479                         o.fn.apply(o.scope || this);\r
11480                     }\r
11481                     this.reset();\r
11482                 },\r
11483                 scope: scope\r
11484             });\r
11485         }\r
11486         return this;\r
11487     },\r
11488 \r
11489     /**\r
11490      * Returns true if the progress bar is currently in a {@link #wait} operation\r
11491      * @return {Boolean} True if waiting, else false\r
11492      */\r
11493     isWaiting : function(){\r
11494         return this.waitTimer !== null;\r
11495     },\r
11496 \r
11497     /**\r
11498      * Updates the progress bar text.  If specified, textEl will be updated, otherwise the progress\r
11499      * bar itself will display the updated text.\r
11500      * @param {String} text (optional) The string to display in the progress text element (defaults to '')\r
11501      * @return {Ext.ProgressBar} this\r
11502      */\r
11503     updateText : function(text){\r
11504         this.text = text || '&#160;';\r
11505         if(this.rendered){\r
11506             this.textEl.update(this.text);\r
11507         }\r
11508         return this;\r
11509     },\r
11510     \r
11511     /**\r
11512      * Synchronizes the inner bar width to the proper proportion of the total componet width based\r
11513      * on the current progress {@link #value}.  This will be called automatically when the ProgressBar\r
11514      * is resized by a layout, but if it is rendered auto width, this method can be called from\r
11515      * another resize handler to sync the ProgressBar if necessary.\r
11516      */\r
11517     syncProgressBar : function(){\r
11518         if(this.value){\r
11519             this.updateProgress(this.value, this.text);\r
11520         }\r
11521         return this;\r
11522     },\r
11523 \r
11524     /**\r
11525      * Sets the size of the progress bar.\r
11526      * @param {Number} width The new width in pixels\r
11527      * @param {Number} height The new height in pixels\r
11528      * @return {Ext.ProgressBar} this\r
11529      */\r
11530     setSize : function(w, h){\r
11531         Ext.ProgressBar.superclass.setSize.call(this, w, h);\r
11532         if(this.textTopEl){\r
11533             var inner = this.el.dom.firstChild;\r
11534             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);\r
11535         }\r
11536         this.syncProgressBar();\r
11537         return this;\r
11538     },\r
11539 \r
11540     /**\r
11541      * Resets the progress bar value to 0 and text to empty string.  If hide = true, the progress\r
11542      * bar will also be hidden (using the {@link #hideMode} property internally).\r
11543      * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false)\r
11544      * @return {Ext.ProgressBar} this\r
11545      */\r
11546     reset : function(hide){\r
11547         this.updateProgress(0);\r
11548         if(this.textTopEl){\r
11549             this.textTopEl.addClass('x-hidden');\r
11550         }\r
11551         if(this.waitTimer){\r
11552             this.waitTimer.onStop = null; //prevent recursion\r
11553             Ext.TaskMgr.stop(this.waitTimer);\r
11554             this.waitTimer = null;\r
11555         }\r
11556         if(hide === true){\r
11557             this.hide();\r
11558         }\r
11559         return this;\r
11560     }\r
11561 });\r
11562 Ext.reg('progress', Ext.ProgressBar);