Upgrade to ExtJS 3.0.0 - Released 07/06/2009
[extjs.git] / pkgs / cmp-foundation-debug.js
1 /*!
2  * Ext JS Library 3.0.0
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 <tt>{@link Ext.Component#xtype xtype}</tt> 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 <tt>{@link Ext.Component#xtype xtype}</tt> 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 <tt>{@link Ext.Component#xtype xtypes}</tt>, 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, <tt>undefined</tt> if not found, or <tt>null</tt> 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 <tt>xtype</tt>. (Optional if the config contains a <tt>xtype</tt>).
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 <tt>ptype</tt>. (Optional if the config contains a <tt>ptype</tt>).
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 Ext.create = Ext.ComponentMgr.create;
160 /**
161  * @class Ext.Component
162  * @extends Ext.util.Observable
163  * <p>Base class for all Ext components.  All subclasses of Component may participate in the automated
164  * Ext component lifecycle of creation, rendering and destruction which is provided by the {@link Ext.Container Container} class.
165  * Components may be added to a Container through the {@link Ext.Container#items items} config option at the time the Container is created,
166  * or they may be added dynamically via the {@link Ext.Container#add add} method.</p>
167  * <p>The Component base class has built-in support for basic hide/show and enable/disable behavior.</p>
168  * <p>All Components are registered with the {@link Ext.ComponentMgr} on construction so that they can be referenced at any time via
169  * {@link Ext#getCmp}, passing the {@link #id}.</p>
170  * <p>All user-developed visual widgets that are required to participate in automated lifecycle and size management should subclass Component (or
171  * {@link Ext.BoxComponent} if managed box model handling is required, ie height and width management).</p>
172  * <p>See the <a href="http://extjs.com/learn/Tutorial:Creating_new_UI_controls">Creating new UI controls</a> tutorial for details on how
173  * and to either extend or augment ExtJs base classes to create custom Components.</p>
174  * <p>Every component has a specific xtype, which is its Ext-specific type name, along with methods for checking the
175  * xtype like {@link #getXType} and {@link #isXType}. This is the list of all valid xtypes:</p>
176  * <pre>
177 xtype            Class
178 -------------    ------------------
179 box              {@link Ext.BoxComponent}
180 button           {@link Ext.Button}
181 buttongroup      {@link Ext.ButtonGroup}
182 colorpalette     {@link Ext.ColorPalette}
183 component        {@link Ext.Component}
184 container        {@link Ext.Container}
185 cycle            {@link Ext.CycleButton}
186 dataview         {@link Ext.DataView}
187 datepicker       {@link Ext.DatePicker}
188 editor           {@link Ext.Editor}
189 editorgrid       {@link Ext.grid.EditorGridPanel}
190 flash            {@link Ext.FlashComponent}
191 grid             {@link Ext.grid.GridPanel}
192 listview         {@link Ext.ListView}
193 panel            {@link Ext.Panel}
194 progress         {@link Ext.ProgressBar}
195 propertygrid     {@link Ext.grid.PropertyGrid}
196 slider           {@link Ext.Slider}
197 spacer           {@link Ext.Spacer}
198 splitbutton      {@link Ext.SplitButton}
199 tabpanel         {@link Ext.TabPanel}
200 treepanel        {@link Ext.tree.TreePanel}
201 viewport         {@link Ext.ViewPort}
202 window           {@link Ext.Window}
203
204 Toolbar components
205 ---------------------------------------
206 paging           {@link Ext.PagingToolbar}
207 toolbar          {@link Ext.Toolbar}
208 tbbutton         {@link Ext.Toolbar.Button}        (deprecated; use button)
209 tbfill           {@link Ext.Toolbar.Fill}
210 tbitem           {@link Ext.Toolbar.Item}
211 tbseparator      {@link Ext.Toolbar.Separator}
212 tbspacer         {@link Ext.Toolbar.Spacer}
213 tbsplit          {@link Ext.Toolbar.SplitButton}   (deprecated; use splitbutton)
214 tbtext           {@link Ext.Toolbar.TextItem}
215
216 Menu components
217 ---------------------------------------
218 menu             {@link Ext.menu.Menu}
219 colormenu        {@link Ext.menu.ColorMenu}
220 datemenu         {@link Ext.menu.DateMenu}
221 menubaseitem     {@link Ext.menu.BaseItem}
222 menucheckitem    {@link Ext.menu.CheckItem}
223 menuitem         {@link Ext.menu.Item}
224 menuseparator    {@link Ext.menu.Separator}
225 menutextitem     {@link Ext.menu.TextItem}
226
227 Form components
228 ---------------------------------------
229 form             {@link Ext.FormPanel}
230 checkbox         {@link Ext.form.Checkbox}
231 checkboxgroup    {@link Ext.form.CheckboxGroup}
232 combo            {@link Ext.form.ComboBox}
233 datefield        {@link Ext.form.DateField}
234 displayfield     {@link Ext.form.DisplayField}
235 field            {@link Ext.form.Field}
236 fieldset         {@link Ext.form.FieldSet}
237 hidden           {@link Ext.form.Hidden}
238 htmleditor       {@link Ext.form.HtmlEditor}
239 label            {@link Ext.form.Label}
240 numberfield      {@link Ext.form.NumberField}
241 radio            {@link Ext.form.Radio}
242 radiogroup       {@link Ext.form.RadioGroup}
243 textarea         {@link Ext.form.TextArea}
244 textfield        {@link Ext.form.TextField}
245 timefield        {@link Ext.form.TimeField}
246 trigger          {@link Ext.form.TriggerField}
247
248 Chart components
249 ---------------------------------------
250 chart            {@link Ext.chart.Chart}
251 barchart         {@link Ext.chart.BarChart}
252 cartesianchart   {@link Ext.chart.CartesianChart}
253 columnchart      {@link Ext.chart.ColumnChart}
254 linechart        {@link Ext.chart.LineChart}
255 piechart         {@link Ext.chart.PieChart}
256
257 Store xtypes
258 ---------------------------------------
259 arraystore       {@link Ext.data.ArrayStore}
260 directstore      {@link Ext.data.DirectStore}
261 groupingstore    {@link Ext.data.GroupingStore}
262 jsonstore        {@link Ext.data.JsonStore}
263 simplestore      {@link Ext.data.SimpleStore}      (deprecated; use arraystore)
264 store            {@link Ext.data.Store}
265 xmlstore         {@link Ext.data.XmlStore}
266 </pre>
267  * @constructor
268  * @param {Ext.Element/String/Object} config The configuration options may be specified as either:
269  * <div class="mdetail-params"><ul>
270  * <li><b>an element</b> :
271  * <p class="sub-desc">it is set as the internal element and its id used as the component id</p></li>
272  * <li><b>a string</b> :
273  * <p class="sub-desc">it is assumed to be the id of an existing element and is used as the component id</p></li>
274  * <li><b>anything else</b> :
275  * <p class="sub-desc">it is assumed to be a standard config object and is applied to the component</p></li>
276  * </ul></div>
277  */
278 Ext.Component = function(config){
279     config = config || {};
280     if(config.initialConfig){
281         if(config.isAction){           // actions
282             this.baseAction = config;
283         }
284         config = config.initialConfig; // component cloning / action set up
285     }else if(config.tagName || config.dom || Ext.isString(config)){ // element object
286         config = {applyTo: config, id: config.id || config};
287     }
288
289     /**
290      * This Component's initial configuration specification. Read-only.
291      * @type Object
292      * @property initialConfig
293      */
294     this.initialConfig = config;
295
296     Ext.apply(this, config);
297     this.addEvents(
298         /**
299          * @event disable
300          * Fires after the component is disabled.
301          * @param {Ext.Component} this
302          */
303         'disable',
304         /**
305          * @event enable
306          * Fires after the component is enabled.
307          * @param {Ext.Component} this
308          */
309         'enable',
310         /**
311          * @event beforeshow
312          * Fires before the component is shown by calling the {@link #show} method.
313          * Return false from an event handler to stop the show.
314          * @param {Ext.Component} this
315          */
316         'beforeshow',
317         /**
318          * @event show
319          * Fires after the component is shown when calling the {@link #show} method.
320          * @param {Ext.Component} this
321          */
322         'show',
323         /**
324          * @event beforehide
325          * Fires before the component is hidden by calling the {@link #hide} method.
326          * Return false from an event handler to stop the hide.
327          * @param {Ext.Component} this
328          */
329         'beforehide',
330         /**
331          * @event hide
332          * Fires after the component is hidden.
333          * Fires after the component is hidden when calling the {@link #hide} method.
334          * @param {Ext.Component} this
335          */
336         'hide',
337         /**
338          * @event beforerender
339          * Fires before the component is {@link #rendered}. Return false from an
340          * event handler to stop the {@link #render}.
341          * @param {Ext.Component} this
342          */
343         'beforerender',
344         /**
345          * @event render
346          * Fires after the component markup is {@link #rendered}.
347          * @param {Ext.Component} this
348          */
349         'render',
350         /**
351          * @event afterrender
352          * <p>Fires after the component rendering is finished.</p>
353          * <p>The afterrender event is fired after this Component has been {@link #rendered}, been postprocesed
354          * by any afterRender method defined for the Component, and, if {@link #stateful}, after state
355          * has been restored.</p>
356          * @param {Ext.Component} this
357          */
358         'afterrender',
359         /**
360          * @event beforedestroy
361          * Fires before the component is {@link #destroy}ed. Return false from an event handler to stop the {@link #destroy}.
362          * @param {Ext.Component} this
363          */
364         'beforedestroy',
365         /**
366          * @event destroy
367          * Fires after the component is {@link #destroy}ed.
368          * @param {Ext.Component} this
369          */
370         'destroy',
371         /**
372          * @event beforestaterestore
373          * Fires before the state of the component is restored. Return false from an event handler to stop the restore.
374          * @param {Ext.Component} this
375          * @param {Object} state The hash of state values returned from the StateProvider. If this
376          * event is not vetoed, then the state object is passed to <b><tt>applyState</tt></b>. By default,
377          * that simply copies property values into this Component. The method maybe overriden to
378          * provide custom state restoration.
379          */
380         'beforestaterestore',
381         /**
382          * @event staterestore
383          * Fires after the state of the component is restored.
384          * @param {Ext.Component} this
385          * @param {Object} state The hash of state values returned from the StateProvider. This is passed
386          * to <b><tt>applyState</tt></b>. By default, that simply copies property values into this
387          * Component. The method maybe overriden to provide custom state restoration.
388          */
389         'staterestore',
390         /**
391          * @event beforestatesave
392          * Fires before the state of the component is saved to the configured state provider. Return false to stop the save.
393          * @param {Ext.Component} this
394          * @param {Object} state The hash of state values. This is determined by calling
395          * <b><tt>getState()</tt></b> on the Component. This method must be provided by the
396          * developer to return whetever representation of state is required, by default, Ext.Component
397          * has a null implementation.
398          */
399         'beforestatesave',
400         /**
401          * @event statesave
402          * Fires after the state of the component is saved to the configured state provider.
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         'statesave'
410     );
411     this.getId();
412     Ext.ComponentMgr.register(this);
413     Ext.Component.superclass.constructor.call(this);
414
415     if(this.baseAction){
416         this.baseAction.addComponent(this);
417     }
418
419     this.initComponent();
420
421     if(this.plugins){
422         if(Ext.isArray(this.plugins)){
423             for(var i = 0, len = this.plugins.length; i < len; i++){
424                 this.plugins[i] = this.initPlugin(this.plugins[i]);
425             }
426         }else{
427             this.plugins = this.initPlugin(this.plugins);
428         }
429     }
430
431     if(this.stateful !== false){
432         this.initState(config);
433     }
434
435     if(this.applyTo){
436         this.applyToMarkup(this.applyTo);
437         delete this.applyTo;
438     }else if(this.renderTo){
439         this.render(this.renderTo);
440         delete this.renderTo;
441     }
442 };
443
444 // private
445 Ext.Component.AUTO_ID = 1000;
446
447 Ext.extend(Ext.Component, Ext.util.Observable, {
448         // Configs below are used for all Components when rendered by FormLayout.
449     /**
450      * @cfg {String} fieldLabel <p>The label text to display next to this Component (defaults to '').</p>
451      * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container which
452      * has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout manager (e.g.
453      * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>).</p><br>
454      * <p>Also see <tt>{@link #hideLabel}</tt> and
455      * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</p>
456      * Example use:<pre><code>
457 new Ext.FormPanel({
458     height: 100,
459     renderTo: Ext.getBody(),
460     items: [{
461         xtype: 'textfield',
462         fieldLabel: 'Name'
463     }]
464 });
465 </code></pre>
466      */
467     /**
468      * @cfg {String} labelStyle <p>A CSS style specification string to apply directly to this field's
469      * label.  Defaults to the container's labelStyle value if set (e.g.,
470      * <tt>{@link Ext.layout.FormLayout#labelStyle}</tt> , or '').</p>
471      * <br><p><b>Note</b>: see the note for <code>{@link #clearCls}</code>.</p><br>
472      * <p>Also see <code>{@link #hideLabel}</code> and
473      * <code>{@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</code></p>
474      * Example use:<pre><code>
475 new Ext.FormPanel({
476     height: 100,
477     renderTo: Ext.getBody(),
478     items: [{
479         xtype: 'textfield',
480         fieldLabel: 'Name',
481         labelStyle: 'font-weight:bold;'
482     }]
483 });
484 </code></pre>
485      */
486     /**
487      * @cfg {String} labelSeparator <p>The separator to display after the text of each
488      * <tt>{@link #fieldLabel}</tt>.  This property may be configured at various levels.
489      * The order of precedence is:
490      * <div class="mdetail-params"><ul>
491      * <li>field / component level</li>
492      * <li>container level</li>
493      * <li>{@link Ext.layout.FormLayout#labelSeparator layout level} (defaults to colon <tt>':'</tt>)</li>
494      * </ul></div>
495      * To display no separator for this field's label specify empty string ''.</p>
496      * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</tt>.</p><br>
497      * <p>Also see <tt>{@link #hideLabel}</tt> and
498      * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</p>
499      * Example use:<pre><code>
500 new Ext.FormPanel({
501     height: 100,
502     renderTo: Ext.getBody(),
503     layoutConfig: {
504         labelSeparator: '~'   // layout config has lowest priority (defaults to ':')
505     },
506     {@link Ext.layout.FormLayout#labelSeparator labelSeparator}: '>>',     // config at container level
507     items: [{
508         xtype: 'textfield',
509         fieldLabel: 'Field 1',
510         labelSeparator: '...' // field/component level config supersedes others
511     },{
512         xtype: 'textfield',
513         fieldLabel: 'Field 2' // labelSeparator will be '='
514     }]
515 });
516 </code></pre>
517      */
518     /**
519      * @cfg {Boolean} hideLabel <p><tt>true</tt> to completely hide the label element
520      * ({@link #fieldLabel label} and {@link #labelSeparator separator}). Defaults to <tt>false</tt>.
521      * By default, even if you do not specify a <tt>{@link #fieldLabel}</tt> the space will still be
522      * reserved so that the field will line up with other fields that do have labels.
523      * Setting this to <tt>true</tt> will cause the field to not reserve that space.</p>
524      * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</tt>.</p><br>
525      * Example use:<pre><code>
526 new Ext.FormPanel({
527     height: 100,
528     renderTo: Ext.getBody(),
529     items: [{
530         xtype: 'textfield'
531         hideLabel: true
532     }]
533 });
534 </code></pre>
535      */
536     /**
537      * @cfg {String} clearCls <p>The CSS class used to to apply to the special clearing div rendered
538      * directly after each form field wrapper to provide field clearing (defaults to
539      * <tt>'x-form-clear-left'</tt>).</p>
540      * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container
541      * which has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout
542      * manager (e.g. {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) and either a
543      * <tt>{@link #fieldLabel}</tt> is specified or <tt>isFormField=true</tt> is specified.</p><br>
544      * <p>See {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl} also.</p>
545      */
546     /**
547      * @cfg {String} itemCls <p>An additional CSS class to apply to the div wrapping the form item
548      * element of this field.  If supplied, <tt>itemCls</tt> at the <b>field</b> level will override
549      * the default <tt>itemCls</tt> supplied at the <b>container</b> level. The value specified for
550      * <tt>itemCls</tt> will be added to the default class (<tt>'x-form-item'</tt>).</p>
551      * <p>Since it is applied to the item wrapper (see
552      * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}), it allows
553      * you to write standard CSS rules that can apply to the field, the label (if specified), or
554      * any other element within the markup for the field.</p>
555      * <br><p><b>Note</b>: see the note for <tt>{@link #fieldLabel}</tt>.</p><br>
556      * Example use:<pre><code>
557 // Apply a style to the field's label:
558 &lt;style>
559     .required .x-form-item-label {font-weight:bold;color:red;}
560 &lt;/style>
561
562 new Ext.FormPanel({
563         height: 100,
564         renderTo: Ext.getBody(),
565         items: [{
566                 xtype: 'textfield',
567                 fieldLabel: 'Name',
568                 itemCls: 'required' //this label will be styled
569         },{
570                 xtype: 'textfield',
571                 fieldLabel: 'Favorite Color'
572         }]
573 });
574 </code></pre>
575      */
576
577         // Configs below are used for all Components when rendered by AnchorLayout.
578     /**
579      * @cfg {String} anchor <p><b>Note</b>: this config is only used when this Component is rendered
580      * by a Container which has been configured to use an <b>{@link Ext.layout.AnchorLayout AnchorLayout}</b>
581      * based layout manager, for example:<div class="mdetail-params"><ul>
582      * <li>{@link Ext.form.FormPanel}</li>
583      * <li>specifying <code>layout: 'anchor' // or 'form', or 'absolute'</code></li>
584      * </ul></div></p>
585      * <p>See {@link Ext.layout.AnchorLayout}.{@link Ext.layout.AnchorLayout#anchor anchor} also.</p>
586      */
587
588     /**
589      * @cfg {String} id
590      * <p>The <b>unique</b> id of this component (defaults to an {@link #getId auto-assigned id}).
591      * You should assign an id if you need to be able to access the component later and you do
592      * not have an object reference available (e.g., using {@link Ext}.{@link Ext#getCmp getCmp}).</p>
593      * <p>Note that this id will also be used as the element id for the containing HTML element
594      * that is rendered to the page for this component. This allows you to write id-based CSS
595      * rules to style the specific instance of this component uniquely, and also to select
596      * sub-elements using this component's id as the parent.</p>
597      * <p><b>Note</b>: to avoid complications imposed by a unique <tt>id</tt> also see
598      * <code>{@link #itemId}</code> and <code>{@link #ref}</code>.</p>
599      * <p><b>Note</b>: to access the container of an item see <code>{@link #ownerCt}</code>.</p>
600      */
601     /**
602      * @cfg {String} itemId
603      * <p>An <tt>itemId</tt> can be used as an alternative way to get a reference to a component
604      * when no object reference is available.  Instead of using an <code>{@link #id}</code> with
605      * {@link Ext}.{@link Ext#getCmp getCmp}, use <code>itemId</code> with
606      * {@link Ext.Container}.{@link Ext.Container#getComponent getComponent} which will retrieve
607      * <code>itemId</code>'s or <tt>{@link #id}</tt>'s. Since <code>itemId</code>'s are an index to the
608      * container's internal MixedCollection, the <code>itemId</code> is scoped locally to the container --
609      * avoiding potential conflicts with {@link Ext.ComponentMgr} which requires a <b>unique</b>
610      * <code>{@link #id}</code>.</p>
611      * <pre><code>
612 var c = new Ext.Panel({ //
613     {@link Ext.BoxComponent#height height}: 300,
614     {@link #renderTo}: document.body,
615     {@link Ext.Container#layout layout}: 'auto',
616     {@link Ext.Container#items items}: [
617         {
618             itemId: 'p1',
619             {@link Ext.Panel#title title}: 'Panel 1',
620             {@link Ext.BoxComponent#height height}: 150
621         },
622         {
623             itemId: 'p2',
624             {@link Ext.Panel#title title}: 'Panel 2',
625             {@link Ext.BoxComponent#height height}: 150
626         }
627     ]
628 })
629 p1 = c.{@link Ext.Container#getComponent getComponent}('p1'); // not the same as {@link Ext#getCmp Ext.getCmp()}
630 p2 = p1.{@link #ownerCt}.{@link Ext.Container#getComponent getComponent}('p2'); // reference via a sibling
631      * </code></pre>
632      * <p>Also see <tt>{@link #id}</tt> and <code>{@link #ref}</code>.</p>
633      * <p><b>Note</b>: to access the container of an item see <tt>{@link #ownerCt}</tt>.</p>
634      */
635     /**
636      * @cfg {String} xtype
637      * The registered <tt>xtype</tt> to create. This config option is not used when passing
638      * a config object into a constructor. This config option is used only when
639      * lazy instantiation is being used, and a child item of a Container is being
640      * specified not as a fully instantiated Component, but as a <i>Component config
641      * object</i>. The <tt>xtype</tt> will be looked up at render time up to determine what
642      * type of child Component to create.<br><br>
643      * The predefined xtypes are listed {@link Ext.Component here}.
644      * <br><br>
645      * If you subclass Components to create your own Components, you may register
646      * them using {@link Ext.ComponentMgr#registerType} in order to be able to
647      * take advantage of lazy instantiation and rendering.
648      */
649     /**
650      * @cfg {String} ptype
651      * The registered <tt>ptype</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 Plugin is being
654      * specified not as a fully instantiated Component, but as a <i>Component config
655      * object</i>. The <tt>ptype</tt> will be looked up at render time up to determine what
656      * type of Plugin to create.<br><br>
657      * If you create your own Plugins, you may register them using
658      * {@link Ext.ComponentMgr#registerPlugin} in order to be able to
659      * take advantage of lazy instantiation and rendering.
660      */
661     /**
662      * @cfg {String} cls
663      * An optional extra CSS class that will be added to this component's Element (defaults to '').  This can be
664      * useful for adding customized styles to the component or any of its children using standard CSS rules.
665      */
666     /**
667      * @cfg {String} overCls
668      * An optional extra CSS class that will be added to this component's Element when the mouse moves
669      * over the Element, and removed when the mouse moves out. (defaults to '').  This can be
670      * useful for adding customized 'active' or 'hover' styles to the component or any of its children using standard CSS rules.
671      */
672     /**
673      * @cfg {String} style
674      * A custom style specification to be applied to this component's Element.  Should be a valid argument to
675      * {@link Ext.Element#applyStyles}.
676      * <pre><code>
677 new Ext.Panel({
678     title: 'Some Title',
679     renderTo: Ext.getBody(),
680     width: 400, height: 300,
681     layout: 'form',
682     items: [{
683         xtype: 'textarea',
684         style: {
685             width: '95%',
686             marginBottom: '10px'
687         }
688     },
689         new Ext.Button({
690             text: 'Send',
691             minWidth: '100',
692             style: {
693                 marginBottom: '10px'
694             }
695         })
696     ]
697 });
698      * </code></pre>
699      */
700     /**
701      * @cfg {String} ctCls
702      * <p>An optional extra CSS class that will be added to this component's container. This can be useful for
703      * adding customized styles to the container or any of its children using standard CSS rules.  See
704      * {@link Ext.layout.ContainerLayout}.{@link Ext.layout.ContainerLayout#extraCls extraCls} also.</p>
705      * <p><b>Note</b>: <tt>ctCls</tt> defaults to <tt>''</tt> except for the following class
706      * which assigns a value by default:
707      * <div class="mdetail-params"><ul>
708      * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-layout-ct'</tt></li>
709      * </ul></div>
710      * To configure the above Class with an extra CSS class append to the default.  For example,
711      * for BoxLayout (Hbox and Vbox):<pre><code>
712      * ctCls: 'x-box-layout-ct custom-class'
713      * </code></pre>
714      * </p>
715      */
716     /**
717      * @cfg {Boolean} disabled
718      * Render this component disabled (default is false).
719      */
720     disabled : false,
721     /**
722      * @cfg {Boolean} hidden
723      * Render this component hidden (default is false). If <tt>true</tt>, the
724      * {@link #hide} method will be called internally.
725      */
726     hidden : false,
727     /**
728      * @cfg {Object/Array} plugins
729      * An object or array of objects that will provide custom functionality for this component.  The only
730      * requirement for a valid plugin is that it contain an init method that accepts a reference of type Ext.Component.
731      * When a component is created, if any plugins are available, the component will call the init method on each
732      * plugin, passing a reference to itself.  Each plugin can then call methods or respond to events on the
733      * component as needed to provide its functionality.
734      */
735     /**
736      * @cfg {Mixed} applyTo
737      * <p>Specify the id of the element, a DOM element or an existing Element corresponding to a DIV
738      * that is already present in the document that specifies some structural markup for this
739      * component.</p><div><ul>
740      * <li><b>Description</b> : <ul>
741      * <div class="sub-desc">When <tt>applyTo</tt> is used, constituent parts of the component can also be specified
742      * by id or CSS class name within the main element, and the component being created may attempt
743      * to create its subcomponents from that markup if applicable.</div>
744      * </ul></li>
745      * <li><b>Notes</b> : <ul>
746      * <div class="sub-desc">When using this config, a call to render() is not required.</div>
747      * <div class="sub-desc">If applyTo is specified, any value passed for {@link #renderTo} will be ignored and the target
748      * element's parent node will automatically be used as the component's container.</div>
749      * </ul></li>
750      * </ul></div>
751      */
752     /**
753      * @cfg {Mixed} renderTo
754      * <p>Specify the id of the element, a DOM element or an existing Element that this component
755      * will be rendered into.</p><div><ul>
756      * <li><b>Notes</b> : <ul>
757      * <div class="sub-desc">Do <u>not</u> use this option if the Component is to be a child item of
758      * a {@link Ext.Container Container}. It is the responsibility of the
759      * {@link Ext.Container Container}'s {@link Ext.Container#layout layout manager}
760      * to render and manage its child items.</div>
761      * <div class="sub-desc">When using this config, a call to render() is not required.</div>
762      * </ul></li>
763      * </ul></div>
764      * <p>See <tt>{@link #render}</tt> also.</p>
765      */
766     /**
767      * @cfg {Boolean} stateful
768      * <p>A flag which causes the Component to attempt to restore the state of
769      * internal properties from a saved state on startup. The component must have
770      * either a <code>{@link #stateId}</code> or <code>{@link #id}</code> assigned
771      * for state to be managed. Auto-generated ids are not guaranteed to be stable
772      * across page loads and cannot be relied upon to save and restore the same
773      * state for a component.<p>
774      * <p>For state saving to work, the state manager's provider must have been
775      * set to an implementation of {@link Ext.state.Provider} which overrides the
776      * {@link Ext.state.Provider#set set} and {@link Ext.state.Provider#get get}
777      * methods to save and recall name/value pairs. A built-in implementation,
778      * {@link Ext.state.CookieProvider} is available.</p>
779      * <p>To set the state provider for the current page:</p>
780      * <pre><code>
781 Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
782     expires: new Date(new Date().getTime()+(1000*60*60*24*7)), //7 days from now
783 }));
784      * </code></pre>
785      * <p>A stateful Component attempts to save state when one of the events
786      * listed in the <code>{@link #stateEvents}</code> configuration fires.</p>
787      * <p>To save state, a stateful Component first serializes its state by
788      * calling <b><code>getState</code></b>. By default, this function does
789      * nothing. The developer must provide an implementation which returns an
790      * object hash which represents the Component's restorable state.</p>
791      * <p>The value yielded by getState is passed to {@link Ext.state.Manager#set}
792      * which uses the configured {@link Ext.state.Provider} to save the object
793      * keyed by the Component's <code>{@link stateId}</code>, or, if that is not
794      * specified, its <code>{@link #id}</code>.</p>
795      * <p>During construction, a stateful Component attempts to <i>restore</i>
796      * its state by calling {@link Ext.state.Manager#get} passing the
797      * <code>{@link #stateId}</code>, or, if that is not specified, the
798      * <code>{@link #id}</code>.</p>
799      * <p>The resulting object is passed to <b><code>applyState</code></b>.
800      * The default implementation of <code>applyState</code> simply copies
801      * properties into the object, but a developer may override this to support
802      * more behaviour.</p>
803      * <p>You can perform extra processing on state save and restore by attaching
804      * handlers to the {@link #beforestaterestore}, {@link #staterestore},
805      * {@link #beforestatesave} and {@link #statesave} events.</p>
806      */
807     /**
808      * @cfg {String} stateId
809      * The unique id for this component to use for state management purposes
810      * (defaults to the component id if one was set, otherwise null if the
811      * component is using a generated id).
812      * <p>See <code>{@link #stateful}</code> for an explanation of saving and
813      * restoring Component state.</p>
814      */
815     /**
816      * @cfg {Array} stateEvents
817      * <p>An array of events that, when fired, should trigger this component to
818      * save its state (defaults to none). <code>stateEvents</code> may be any type
819      * of event supported by this component, including browser or custom events
820      * (e.g., <tt>['click', 'customerchange']</tt>).</p>
821      * <p>See <code>{@link #stateful}</code> for an explanation of saving and
822      * restoring Component state.</p>
823      */
824     /**
825      * @cfg {Mixed} autoEl
826      * <p>A tag name or {@link Ext.DomHelper DomHelper} spec used to create the {@link #getEl Element} which will
827      * encapsulate this Component.</p>
828      * <p>You do not normally need to specify this. For the base classes {@link Ext.Component}, {@link Ext.BoxComponent},
829      * and {@link Ext.Container}, this defaults to <b><tt>'div'</tt></b>. The more complex Ext classes use a more complex
830      * DOM structure created by their own onRender methods.</p>
831      * <p>This is intended to allow the developer to create application-specific utility Components encapsulated by
832      * different DOM elements. Example usage:</p><pre><code>
833 {
834     xtype: 'box',
835     autoEl: {
836         tag: 'img',
837         src: 'http://www.example.com/example.jpg'
838     }
839 }, {
840     xtype: 'box',
841     autoEl: {
842         tag: 'blockquote',
843         html: 'autoEl is cool!'
844     }
845 }, {
846     xtype: 'container',
847     autoEl: 'ul',
848     cls: 'ux-unordered-list',
849     items: {
850         xtype: 'box',
851         autoEl: 'li',
852         html: 'First list item'
853     }
854 }
855 </code></pre>
856      */
857     autoEl : 'div',
858
859     /**
860      * @cfg {String} disabledClass
861      * CSS class added to the component when it is disabled (defaults to 'x-item-disabled').
862      */
863     disabledClass : 'x-item-disabled',
864     /**
865      * @cfg {Boolean} allowDomMove
866      * Whether the component can move the Dom node when rendering (defaults to true).
867      */
868     allowDomMove : true,
869     /**
870      * @cfg {Boolean} autoShow
871      * True if the component should check for hidden classes (e.g. 'x-hidden' or 'x-hide-display') and remove
872      * them on render (defaults to false).
873      */
874     autoShow : false,
875     /**
876      * @cfg {String} hideMode
877      * <p>How this component should be hidden. Supported values are <tt>'visibility'</tt>
878      * (css visibility), <tt>'offsets'</tt> (negative offset position) and <tt>'display'</tt>
879      * (css display).</p>
880      * <br><p><b>Note</b>: the default of <tt>'display'</tt> is generally preferred
881      * since items are automatically laid out when they are first shown (no sizing
882      * is done while hidden).</p>
883      */
884     hideMode : 'display',
885     /**
886      * @cfg {Boolean} hideParent
887      * True to hide and show the component's container when hide/show is called on the component, false to hide
888      * and show the component itself (defaults to false).  For example, this can be used as a shortcut for a hide
889      * button on a window by setting hide:true on the button when adding it to its parent container.
890      */
891     hideParent : false,
892     /**
893      * <p>The {@link Ext.Element} which encapsulates this Component. Read-only.</p>
894      * <p>This will <i>usually</i> be a &lt;DIV> element created by the class's onRender method, but
895      * that may be overridden using the <code>{@link #autoEl}</code> config.</p>
896      * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br>
897      * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners
898      * for this Component's own Observable events), see the {@link Ext.util.Observable#listeners listeners}
899      * config for a suggestion, or use a render listener directly:</p><pre><code>
900 new Ext.Panel({
901     title: 'The Clickable Panel',
902     listeners: {
903         render: function(p) {
904             // Append the Panel to the click handler&#39;s argument list.
905             p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));
906         },
907         single: true  // Remove the listener after first invocation
908     }
909 });
910 </code></pre>
911      * <p>See also <tt>{@link #getEl getEl}</p>
912      * @type Ext.Element
913      * @property el
914      */
915     /**
916      * The component's owner {@link Ext.Container} (defaults to undefined, and is set automatically when
917      * the component is added to a container).  Read-only.
918      * <p><b>Note</b>: to access items within the container see <tt>{@link #itemId}</tt>.</p>
919      * @type Ext.Container
920      * @property ownerCt
921      */
922     /**
923      * True if this component is hidden. Read-only.
924      * @type Boolean
925      * @property
926      */
927     /**
928      * True if this component is disabled. Read-only.
929      * @type Boolean
930      * @property
931      */
932     /**
933      * True if this component has been rendered. Read-only.
934      * @type Boolean
935      * @property
936      */
937     rendered : false,
938
939     // private
940     ctype : 'Ext.Component',
941
942     // private
943     actionMode : 'el',
944
945     // private
946     getActionEl : function(){
947         return this[this.actionMode];
948     },
949
950     initPlugin : function(p){
951         if(p.ptype && !Ext.isFunction(p.init)){
952             p = Ext.ComponentMgr.createPlugin(p);
953         }else if(Ext.isString(p)){
954             p = Ext.ComponentMgr.createPlugin({
955                 ptype: p
956             });
957         }
958         p.init(this);
959         return p;
960     },
961
962     /* // protected
963      * Function to be implemented by Component subclasses to be part of standard component initialization flow (it is empty by default).
964      * <pre><code>
965 // Traditional constructor:
966 Ext.Foo = function(config){
967     // call superclass constructor:
968     Ext.Foo.superclass.constructor.call(this, config);
969
970     this.addEvents({
971         // add events
972     });
973 };
974 Ext.extend(Ext.Foo, Ext.Bar, {
975    // class body
976 }
977
978 // initComponent replaces the constructor:
979 Ext.Foo = Ext.extend(Ext.Bar, {
980     initComponent : function(){
981         // call superclass initComponent
982         Ext.Container.superclass.initComponent.call(this);
983
984         this.addEvents({
985             // add events
986         });
987     }
988 }
989 </code></pre>
990      */
991     initComponent : Ext.emptyFn,
992
993     /**
994      * <p>Render this Component into the passed HTML element.</p>
995      * <p><b>If you are using a {@link Ext.Container Container} object to house this Component, then
996      * do not use the render method.</b></p>
997      * <p>A Container's child Components are rendered by that Container's
998      * {@link Ext.Container#layout layout} manager when the Container is first rendered.</p>
999      * <p>Certain layout managers allow dynamic addition of child components. Those that do
1000      * include {@link Ext.layout.CardLayout}, {@link Ext.layout.AnchorLayout},
1001      * {@link Ext.layout.FormLayout}, {@link Ext.layout.TableLayout}.</p>
1002      * <p>If the Container is already rendered when a new child Component is added, you may need to call
1003      * the Container's {@link Ext.Container#doLayout doLayout} to refresh the view which causes any
1004      * unrendered child Components to be rendered. This is required so that you can add multiple
1005      * child components if needed while only refreshing the layout once.</p>
1006      * <p>When creating complex UIs, it is important to remember that sizing and positioning
1007      * of child items is the responsibility of the Container's {@link Ext.Container#layout layout} manager.
1008      * If you expect child items to be sized in response to user interactions, you must
1009      * configure the Container with a layout manager which creates and manages the type of layout you
1010      * have in mind.</p>
1011      * <p><b>Omitting the Container's {@link Ext.Container#layout layout} config means that a basic
1012      * layout manager is used which does nothing but render child components sequentially into the
1013      * Container. No sizing or positioning will be performed in this situation.</b></p>
1014      * @param {Element/HTMLElement/String} container (optional) The element this Component should be
1015      * rendered into. If it is being created from existing markup, this should be omitted.
1016      * @param {String/Number} position (optional) The element ID or DOM node index within the container <b>before</b>
1017      * which this component will be inserted (defaults to appending to the end of the container)
1018      */
1019     render : function(container, position){
1020         if(!this.rendered && this.fireEvent('beforerender', this) !== false){
1021             if(!container && this.el){
1022                 this.el = Ext.get(this.el);
1023                 container = this.el.dom.parentNode;
1024                 this.allowDomMove = false;
1025             }
1026             this.container = Ext.get(container);
1027             if(this.ctCls){
1028                 this.container.addClass(this.ctCls);
1029             }
1030             this.rendered = true;
1031             if(position !== undefined){
1032                 if(Ext.isNumber(position)){
1033                     position = this.container.dom.childNodes[position];
1034                 }else{
1035                     position = Ext.getDom(position);
1036                 }
1037             }
1038             this.onRender(this.container, position || null);
1039             if(this.autoShow){
1040                 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
1041             }
1042             if(this.cls){
1043                 this.el.addClass(this.cls);
1044                 delete this.cls;
1045             }
1046             if(this.style){
1047                 this.el.applyStyles(this.style);
1048                 delete this.style;
1049             }
1050             if(this.overCls){
1051                 this.el.addClassOnOver(this.overCls);
1052             }
1053             this.fireEvent('render', this);
1054             this.afterRender(this.container);
1055             if(this.hidden){
1056                 // call this so we don't fire initial hide events.
1057                 this.doHide();
1058             }
1059             if(this.disabled){
1060                 // pass silent so the event doesn't fire the first time.
1061                 this.disable(true);
1062             }
1063
1064             if(this.stateful !== false){
1065                 this.initStateEvents();
1066             }
1067             this.initRef();
1068             this.fireEvent('afterrender', this);
1069         }
1070         return this;
1071     },
1072
1073     initRef : function(){
1074         /**
1075          * @cfg {String} ref
1076          * <p>A path specification, relative to the Component's {@link #ownerCt} specifying into which
1077          * ancestor Container to place a named reference to this Component.</p>
1078          * <p>The ancestor axis can be traversed by using '/' characters in the path.
1079          * For example, to put a reference to a Toolbar Button into <i>the Panel which owns the Toolbar</i>:</p><pre><code>
1080 var myGrid = new Ext.grid.EditorGridPanel({
1081     title: 'My EditorGridPanel',
1082     store: myStore,
1083     colModel: myColModel,
1084     tbar: [{
1085         text: 'Save',
1086         handler: saveChanges,
1087         disabled: true,
1088         ref: '../saveButton'
1089     }],
1090     listeners: {
1091         afteredit: function() {
1092 //          The button reference is in the GridPanel
1093             myGrid.saveButton.enable();
1094         }
1095     }
1096 });
1097 </code></pre>
1098          * <p>In the code above, if the ref had been <code>'saveButton'</code> the reference would
1099          * have been placed into the Toolbar. Each '/' in the ref moves up one level from the
1100          * Component's {@link #ownerCt}.</p>
1101          */
1102         if(this.ref){
1103             var levels = this.ref.split('/');
1104             var last = levels.length, i = 0;
1105             var t = this;
1106             while(i < last){
1107                 if(t.ownerCt){
1108                     t = t.ownerCt;
1109                 }
1110                 i++;
1111             }
1112             t[levels[--i]] = this;
1113         }
1114     },
1115
1116     // private
1117     initState : function(config){
1118         if(Ext.state.Manager){
1119             var id = this.getStateId();
1120             if(id){
1121                 var state = Ext.state.Manager.get(id);
1122                 if(state){
1123                     if(this.fireEvent('beforestaterestore', this, state) !== false){
1124                         this.applyState(state);
1125                         this.fireEvent('staterestore', this, state);
1126                     }
1127                 }
1128             }
1129         }
1130     },
1131
1132     // private
1133     getStateId : function(){
1134         return this.stateId || ((this.id.indexOf('ext-comp-') == 0 || this.id.indexOf('ext-gen') == 0) ? null : this.id);
1135     },
1136
1137     // private
1138     initStateEvents : function(){
1139         if(this.stateEvents){
1140             for(var i = 0, e; e = this.stateEvents[i]; i++){
1141                 this.on(e, this.saveState, this, {delay:100});
1142             }
1143         }
1144     },
1145
1146     // private
1147     applyState : function(state, config){
1148         if(state){
1149             Ext.apply(this, state);
1150         }
1151     },
1152
1153     // private
1154     getState : function(){
1155         return null;
1156     },
1157
1158     // private
1159     saveState : function(){
1160         if(Ext.state.Manager && this.stateful !== false){
1161             var id = this.getStateId();
1162             if(id){
1163                 var state = this.getState();
1164                 if(this.fireEvent('beforestatesave', this, state) !== false){
1165                     Ext.state.Manager.set(id, state);
1166                     this.fireEvent('statesave', this, state);
1167                 }
1168             }
1169         }
1170     },
1171
1172     /**
1173      * Apply this component to existing markup that is valid. With this function, no call to render() is required.
1174      * @param {String/HTMLElement} el
1175      */
1176     applyToMarkup : function(el){
1177         this.allowDomMove = false;
1178         this.el = Ext.get(el);
1179         this.render(this.el.dom.parentNode);
1180     },
1181
1182     /**
1183      * Adds a CSS class to the component's underlying element.
1184      * @param {string} cls The CSS class name to add
1185      * @return {Ext.Component} this
1186      */
1187     addClass : function(cls){
1188         if(this.el){
1189             this.el.addClass(cls);
1190         }else{
1191             this.cls = this.cls ? this.cls + ' ' + cls : cls;
1192         }
1193         return this;
1194     },
1195
1196     /**
1197      * Removes a CSS class from the component's underlying element.
1198      * @param {string} cls The CSS class name to remove
1199      * @return {Ext.Component} this
1200      */
1201     removeClass : function(cls){
1202         if(this.el){
1203             this.el.removeClass(cls);
1204         }else if(this.cls){
1205             this.cls = this.cls.split(' ').remove(cls).join(' ');
1206         }
1207         return this;
1208     },
1209
1210     // private
1211     // default function is not really useful
1212     onRender : function(ct, position){
1213         if(!this.el && this.autoEl){
1214             if(Ext.isString(this.autoEl)){
1215                 this.el = document.createElement(this.autoEl);
1216             }else{
1217                 var div = document.createElement('div');
1218                 Ext.DomHelper.overwrite(div, this.autoEl);
1219                 this.el = div.firstChild;
1220             }
1221             if (!this.el.id) {
1222                 this.el.id = this.getId();
1223             }
1224         }
1225         if(this.el){
1226             this.el = Ext.get(this.el);
1227             if(this.allowDomMove !== false){
1228                 ct.dom.insertBefore(this.el.dom, position);
1229             }
1230         }
1231     },
1232
1233     // private
1234     getAutoCreate : function(){
1235         var cfg = Ext.isObject(this.autoCreate) ?
1236                       this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
1237         if(this.id && !cfg.id){
1238             cfg.id = this.id;
1239         }
1240         return cfg;
1241     },
1242
1243     // private
1244     afterRender : Ext.emptyFn,
1245
1246     /**
1247      * Destroys this component by purging any event listeners, removing the component's element from the DOM,
1248      * removing the component from its {@link Ext.Container} (if applicable) and unregistering it from
1249      * {@link Ext.ComponentMgr}.  Destruction is generally handled automatically by the framework and this method
1250      * should usually not need to be called directly.
1251      *
1252      */
1253     destroy : function(){
1254         if(this.fireEvent('beforedestroy', this) !== false){
1255             this.beforeDestroy();
1256             if(this.rendered){
1257                 this.el.removeAllListeners();
1258                 this.el.remove();
1259                 if(this.actionMode == 'container' || this.removeMode == 'container'){
1260                     this.container.remove();
1261                 }
1262             }
1263             this.onDestroy();
1264             Ext.ComponentMgr.unregister(this);
1265             this.fireEvent('destroy', this);
1266             this.purgeListeners();
1267         }
1268     },
1269
1270     // private
1271     beforeDestroy : Ext.emptyFn,
1272
1273     // private
1274     onDestroy  : Ext.emptyFn,
1275
1276     /**
1277      * <p>Returns the {@link Ext.Element} which encapsulates this Component.</p>
1278      * <p>This will <i>usually</i> be a &lt;DIV> element created by the class's onRender method, but
1279      * that may be overridden using the {@link #autoEl} config.</p>
1280      * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br>
1281      * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners
1282      * for this Component's own Observable events), see the {@link #listeners} config for a suggestion,
1283      * or use a render listener directly:</p><pre><code>
1284 new Ext.Panel({
1285     title: 'The Clickable Panel',
1286     listeners: {
1287         render: function(p) {
1288             // Append the Panel to the click handler&#39;s argument list.
1289             p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));
1290         },
1291         single: true  // Remove the listener after first invocation
1292     }
1293 });
1294 </code></pre>
1295      * @return {Ext.Element} The Element which encapsulates this Component.
1296      */
1297     getEl : function(){
1298         return this.el;
1299     },
1300
1301     /**
1302      * Returns the <code>id</code> of this component or automatically generates and
1303      * returns an <code>id</code> if an <code>id</code> is not defined yet:<pre><code>
1304      * 'ext-comp-' + (++Ext.Component.AUTO_ID)
1305      * </code></pre>
1306      * @return {String} id
1307      */
1308     getId : function(){
1309         return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
1310     },
1311
1312     /**
1313      * Returns the <code>{@link #itemId}</code> of this component.  If an
1314      * <code>{@link #itemId}</code> was not assigned through configuration the
1315      * <code>id</code> is returned using <code>{@link #getId}</code>.
1316      * @return {String}
1317      */
1318     getItemId : function(){
1319         return this.itemId || this.getId();
1320     },
1321
1322     /**
1323      * Try to focus this component.
1324      * @param {Boolean} selectText (optional) If applicable, true to also select the text in this component
1325      * @param {Boolean/Number} delay (optional) Delay the focus this number of milliseconds (true for 10 milliseconds)
1326      * @return {Ext.Component} this
1327      */
1328     focus : function(selectText, delay){
1329         if(delay){
1330             this.focus.defer(Ext.isNumber(delay) ? delay : 10, this, [selectText, false]);
1331             return;
1332         }
1333         if(this.rendered){
1334             this.el.focus();
1335             if(selectText === true){
1336                 this.el.dom.select();
1337             }
1338         }
1339         return this;
1340     },
1341
1342     // private
1343     blur : function(){
1344         if(this.rendered){
1345             this.el.blur();
1346         }
1347         return this;
1348     },
1349
1350     /**
1351      * Disable this component and fire the 'disable' event.
1352      * @return {Ext.Component} this
1353      */
1354     disable : function(/* private */ silent){
1355         if(this.rendered){
1356             this.onDisable();
1357         }
1358         this.disabled = true;
1359         if(silent !== true){
1360             this.fireEvent('disable', this);
1361         }
1362         return this;
1363     },
1364
1365     // private
1366     onDisable : function(){
1367         this.getActionEl().addClass(this.disabledClass);
1368         this.el.dom.disabled = true;
1369     },
1370
1371     /**
1372      * Enable this component and fire the 'enable' event.
1373      * @return {Ext.Component} this
1374      */
1375     enable : function(){
1376         if(this.rendered){
1377             this.onEnable();
1378         }
1379         this.disabled = false;
1380         this.fireEvent('enable', this);
1381         return this;
1382     },
1383
1384     // private
1385     onEnable : function(){
1386         this.getActionEl().removeClass(this.disabledClass);
1387         this.el.dom.disabled = false;
1388     },
1389
1390     /**
1391      * Convenience function for setting disabled/enabled by boolean.
1392      * @param {Boolean} disabled
1393      * @return {Ext.Component} this
1394      */
1395     setDisabled : function(disabled){
1396         return this[disabled ? 'disable' : 'enable']();
1397     },
1398
1399     /**
1400      * Show this component.  Listen to the '{@link #beforeshow}' event and return
1401      * <tt>false</tt> to cancel showing the component.  Fires the '{@link #show}'
1402      * event after showing the component.
1403      * @return {Ext.Component} this
1404      */
1405     show : function(){
1406         if(this.fireEvent('beforeshow', this) !== false){
1407             this.hidden = false;
1408             if(this.autoRender){
1409                 this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
1410             }
1411             if(this.rendered){
1412                 this.onShow();
1413             }
1414             this.fireEvent('show', this);
1415         }
1416         return this;
1417     },
1418
1419     // private
1420     onShow : function(){
1421         this.getVisibiltyEl().removeClass('x-hide-' + this.hideMode);
1422     },
1423
1424     /**
1425      * Hide this component.  Listen to the '{@link #beforehide}' event and return
1426      * <tt>false</tt> to cancel hiding the component.  Fires the '{@link #hide}'
1427      * event after hiding the component. Note this method is called internally if
1428      * the component is configured to be <code>{@link #hidden}</code>.
1429      * @return {Ext.Component} this
1430      */
1431     hide : function(){
1432         if(this.fireEvent('beforehide', this) !== false){
1433             this.doHide();
1434             this.fireEvent('hide', this);
1435         }
1436         return this;
1437     },
1438
1439     // private
1440     doHide: function(){
1441         this.hidden = true;
1442         if(this.rendered){
1443             this.onHide();
1444         }
1445     },
1446
1447     // private
1448     onHide : function(){
1449         this.getVisibiltyEl().addClass('x-hide-' + this.hideMode);
1450     },
1451
1452     // private
1453     getVisibiltyEl : function(){
1454         return this.hideParent ? this.container : this.getActionEl();
1455     },
1456
1457     /**
1458      * Convenience function to hide or show this component by boolean.
1459      * @param {Boolean} visible True to show, false to hide
1460      * @return {Ext.Component} this
1461      */
1462     setVisible : function(visible){
1463         return this[visible ? 'show' : 'hide']();
1464     },
1465
1466     /**
1467      * Returns true if this component is visible.
1468      * @return {Boolean} True if this component is visible, false otherwise.
1469      */
1470     isVisible : function(){
1471         return this.rendered && this.getVisibiltyEl().isVisible();
1472     },
1473
1474     /**
1475      * Clone the current component using the original config values passed into this instance by default.
1476      * @param {Object} overrides A new config containing any properties to override in the cloned version.
1477      * An id property can be passed on this object, otherwise one will be generated to avoid duplicates.
1478      * @return {Ext.Component} clone The cloned copy of this component
1479      */
1480     cloneConfig : function(overrides){
1481         overrides = overrides || {};
1482         var id = overrides.id || Ext.id();
1483         var cfg = Ext.applyIf(overrides, this.initialConfig);
1484         cfg.id = id; // prevent dup id
1485         return new this.constructor(cfg);
1486     },
1487
1488     /**
1489      * Gets the xtype for this component as registered with {@link Ext.ComponentMgr}. For a list of all
1490      * available xtypes, see the {@link Ext.Component} header. Example usage:
1491      * <pre><code>
1492 var t = new Ext.form.TextField();
1493 alert(t.getXType());  // alerts 'textfield'
1494 </code></pre>
1495      * @return {String} The xtype
1496      */
1497     getXType : function(){
1498         return this.constructor.xtype;
1499     },
1500
1501     /**
1502      * <p>Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended
1503      * from the xtype (default) or whether it is directly of the xtype specified (shallow = true).</p>
1504      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1505      * to participate in determination of inherited xtypes.</b></p>
1506      * <p>For a list of all available xtypes, see the {@link Ext.Component} header.</p>
1507      * <p>Example usage:</p>
1508      * <pre><code>
1509 var t = new Ext.form.TextField();
1510 var isText = t.isXType('textfield');        // true
1511 var isBoxSubclass = t.isXType('box');       // true, descended from BoxComponent
1512 var isBoxInstance = t.isXType('box', true); // false, not a direct BoxComponent instance
1513 </code></pre>
1514      * @param {String} xtype The xtype to check for this Component
1515      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
1516      * the default), or true to check whether this Component is directly of the specified xtype.
1517      * @return {Boolean} True if this component descends from the specified xtype, false otherwise.
1518      */
1519     isXType : function(xtype, shallow){
1520         //assume a string by default
1521         if (Ext.isFunction(xtype)){
1522             xtype = xtype.xtype; //handle being passed the class, e.g. Ext.Component
1523         }else if (Ext.isObject(xtype)){
1524             xtype = xtype.constructor.xtype; //handle being passed an instance
1525         }
1526
1527         return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
1528     },
1529
1530     /**
1531      * <p>Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all
1532      * available xtypes, see the {@link Ext.Component} header.</p>
1533      * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1534      * to participate in determination of inherited xtypes.</b></p>
1535      * <p>Example usage:</p>
1536      * <pre><code>
1537 var t = new Ext.form.TextField();
1538 alert(t.getXTypes());  // alerts 'component/box/field/textfield'
1539 </code></pre>
1540      * @return {String} The xtype hierarchy string
1541      */
1542     getXTypes : function(){
1543         var tc = this.constructor;
1544         if(!tc.xtypes){
1545             var c = [], sc = this;
1546             while(sc && sc.constructor.xtype){
1547                 c.unshift(sc.constructor.xtype);
1548                 sc = sc.constructor.superclass;
1549             }
1550             tc.xtypeChain = c;
1551             tc.xtypes = c.join('/');
1552         }
1553         return tc.xtypes;
1554     },
1555
1556     /**
1557      * Find a container above this component at any level by a custom function. If the passed function returns
1558      * true, the container will be returned.
1559      * @param {Function} fn The custom function to call with the arguments (container, this component).
1560      * @return {Ext.Container} The first Container for which the custom function returns true
1561      */
1562     findParentBy : function(fn) {
1563         for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
1564         return p || null;
1565     },
1566
1567     /**
1568      * Find a container above this component at any level by xtype or class
1569      * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
1570      * @return {Ext.Container} The first Container which matches the given xtype or class
1571      */
1572     findParentByType : function(xtype) {
1573         return Ext.isFunction(xtype) ?
1574             this.findParentBy(function(p){
1575                 return p.constructor === xtype;
1576             }) :
1577             this.findParentBy(function(p){
1578                 return p.constructor.xtype === xtype;
1579             });
1580     },
1581
1582     getDomPositionEl : function(){
1583         return this.getPositionEl ? this.getPositionEl() : this.getEl();
1584     },
1585
1586     // private
1587     purgeListeners : function(){
1588         Ext.Component.superclass.purgeListeners.call(this);
1589         if(this.mons){
1590             this.on('beforedestroy', this.clearMons, this, {single: true});
1591         }
1592     },
1593
1594     // private
1595     clearMons : function(){
1596         Ext.each(this.mons, function(m){
1597             m.item.un(m.ename, m.fn, m.scope);
1598         }, this);
1599         this.mons = [];
1600     },
1601
1602     // internal function for auto removal of assigned event handlers on destruction
1603     mon : function(item, ename, fn, scope, opt){
1604         if(!this.mons){
1605             this.mons = [];
1606             this.on('beforedestroy', this.clearMons, this, {single: true});
1607         }
1608
1609         if(Ext.isObject(ename)){
1610                 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
1611
1612             var o = ename;
1613             for(var e in o){
1614                 if(propRe.test(e)){
1615                     continue;
1616                 }
1617                 if(Ext.isFunction(o[e])){
1618                     // shared options
1619                                 this.mons.push({
1620                                     item: item, ename: e, fn: o[e], scope: o.scope
1621                                 });
1622                                 item.on(e, o[e], o.scope, o);
1623                 }else{
1624                     // individual options
1625                                 this.mons.push({
1626                                     item: item, ename: e, fn: o[e], scope: o.scope
1627                                 });
1628                                 item.on(e, o[e]);
1629                 }
1630             }
1631             return;
1632         }
1633
1634
1635         this.mons.push({
1636             item: item, ename: ename, fn: fn, scope: scope
1637         });
1638         item.on(ename, fn, scope, opt);
1639     },
1640
1641     // protected, opposite of mon
1642     mun : function(item, ename, fn, scope){
1643         var found, mon;
1644         for(var i = 0, len = this.mons.length; i < len; ++i){
1645             mon = this.mons[i];
1646             if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){
1647                 this.mons.splice(i, 1);
1648                 item.un(ename, fn, scope);
1649                 found = true;
1650                 break;
1651             }
1652         }
1653         return found;
1654     },
1655
1656     /**
1657      * Returns the next component in the owning container
1658      * @return Ext.Component
1659      */
1660     nextSibling : function(){
1661         if(this.ownerCt){
1662             var index = this.ownerCt.items.indexOf(this);
1663             if(index != -1 && index+1 < this.ownerCt.items.getCount()){
1664                 return this.ownerCt.items.itemAt(index+1);
1665             }
1666         }
1667         return null;
1668     },
1669
1670     /**
1671      * Returns the previous component in the owning container
1672      * @return Ext.Component
1673      */
1674     previousSibling : function(){
1675         if(this.ownerCt){
1676             var index = this.ownerCt.items.indexOf(this);
1677             if(index > 0){
1678                 return this.ownerCt.items.itemAt(index-1);
1679             }
1680         }
1681         return null;
1682     },
1683
1684     /**
1685      * Provides the link for Observable's fireEvent method to bubble up the ownership hierarchy.
1686      * @return {Ext.Container} the Container which owns this Component.
1687      */
1688     getBubbleTarget : function(){
1689         return this.ownerCt;
1690     }
1691 });
1692
1693 Ext.reg('component', Ext.Component);
1694 /**\r
1695  * @class Ext.Action\r
1696  * <p>An Action is a piece of reusable functionality that can be abstracted out of any particular component so that it\r
1697  * can be usefully shared among multiple components.  Actions let you share handlers, configuration options and UI\r
1698  * updates across any components that support the Action interface (primarily {@link Ext.Toolbar}, {@link Ext.Button}\r
1699  * and {@link Ext.menu.Menu} components).</p>\r
1700  * <p>Aside from supporting the config object interface, any component that needs to use Actions must also support\r
1701  * the following method list, as these will be called as needed by the Action class: setText(string), setIconCls(string),\r
1702  * setDisabled(boolean), setVisible(boolean) and setHandler(function).</p>\r
1703  * Example usage:<br>\r
1704  * <pre><code>\r
1705 // Define the shared action.  Each component below will have the same\r
1706 // display text and icon, and will display the same message on click.\r
1707 var action = new Ext.Action({\r
1708     {@link #text}: 'Do something',\r
1709     {@link #handler}: function(){\r
1710         Ext.Msg.alert('Click', 'You did something.');\r
1711     },\r
1712     {@link #iconCls}: 'do-something',\r
1713     {@link #itemId}: 'myAction'\r
1714 });\r
1715 \r
1716 var panel = new Ext.Panel({\r
1717     title: 'Actions',\r
1718     width: 500,\r
1719     height: 300,\r
1720     tbar: [\r
1721         // Add the action directly to a toolbar as a menu button\r
1722         action,\r
1723         {\r
1724             text: 'Action Menu',\r
1725             // Add the action to a menu as a text item\r
1726             menu: [action]\r
1727         }\r
1728     ],\r
1729     items: [\r
1730         // Add the action to the panel body as a standard button\r
1731         new Ext.Button(action)\r
1732     ],\r
1733     renderTo: Ext.getBody()\r
1734 });\r
1735 \r
1736 // Change the text for all components using the action\r
1737 action.setText('Something else');\r
1738 \r
1739 // Reference an action through a container using the itemId\r
1740 var btn = panel.getComponent('myAction');\r
1741 var aRef = btn.baseAction;\r
1742 aRef.setText('New text');\r
1743 </code></pre>\r
1744  * @constructor\r
1745  * @param {Object} config The configuration options\r
1746  */\r
1747 Ext.Action = function(config){\r
1748     this.initialConfig = config;\r
1749     this.itemId = config.itemId = (config.itemId || config.id || Ext.id());\r
1750     this.items = [];\r
1751 }\r
1752 \r
1753 Ext.Action.prototype = {\r
1754     /**\r
1755      * @cfg {String} text The text to set for all components using this action (defaults to '').\r
1756      */\r
1757     /**\r
1758      * @cfg {String} iconCls\r
1759      * The CSS class selector that specifies a background image to be used as the header icon for\r
1760      * all components using this action (defaults to '').\r
1761      * <p>An example of specifying a custom icon class would be something like:\r
1762      * </p><pre><code>\r
1763 // specify the property in the config for the class:\r
1764      ...\r
1765      iconCls: 'do-something'\r
1766 \r
1767 // css class that specifies background image to be used as the icon image:\r
1768 .do-something { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }\r
1769 </code></pre>\r
1770      */\r
1771     /**\r
1772      * @cfg {Boolean} disabled True to disable all components using this action, false to enable them (defaults to false).\r
1773      */\r
1774     /**\r
1775      * @cfg {Boolean} hidden True to hide all components using this action, false to show them (defaults to false).\r
1776      */\r
1777     /**\r
1778      * @cfg {Function} handler The function that will be invoked by each component tied to this action\r
1779      * when the component's primary event is triggered (defaults to undefined).\r
1780      */\r
1781     /**\r
1782      * @cfg {String} itemId\r
1783      * See {@link Ext.Component}.{@link Ext.Component#itemId itemId}.\r
1784      */\r
1785     /**\r
1786      * @cfg {Object} scope The scope in which the {@link #handler} function will execute.\r
1787      */\r
1788 \r
1789     // private\r
1790     isAction : true,\r
1791 \r
1792     /**\r
1793      * Sets the text to be displayed by all components using this action.\r
1794      * @param {String} text The text to display\r
1795      */\r
1796     setText : function(text){\r
1797         this.initialConfig.text = text;\r
1798         this.callEach('setText', [text]);\r
1799     },\r
1800 \r
1801     /**\r
1802      * Gets the text currently displayed by all components using this action.\r
1803      */\r
1804     getText : function(){\r
1805         return this.initialConfig.text;\r
1806     },\r
1807 \r
1808     /**\r
1809      * Sets the icon CSS class for all components using this action.  The class should supply\r
1810      * a background image that will be used as the icon image.\r
1811      * @param {String} cls The CSS class supplying the icon image\r
1812      */\r
1813     setIconClass : function(cls){\r
1814         this.initialConfig.iconCls = cls;\r
1815         this.callEach('setIconClass', [cls]);\r
1816     },\r
1817 \r
1818     /**\r
1819      * Gets the icon CSS class currently used by all components using this action.\r
1820      */\r
1821     getIconClass : function(){\r
1822         return this.initialConfig.iconCls;\r
1823     },\r
1824 \r
1825     /**\r
1826      * Sets the disabled state of all components using this action.  Shortcut method\r
1827      * for {@link #enable} and {@link #disable}.\r
1828      * @param {Boolean} disabled True to disable the component, false to enable it\r
1829      */\r
1830     setDisabled : function(v){\r
1831         this.initialConfig.disabled = v;\r
1832         this.callEach('setDisabled', [v]);\r
1833     },\r
1834 \r
1835     /**\r
1836      * Enables all components using this action.\r
1837      */\r
1838     enable : function(){\r
1839         this.setDisabled(false);\r
1840     },\r
1841 \r
1842     /**\r
1843      * Disables all components using this action.\r
1844      */\r
1845     disable : function(){\r
1846         this.setDisabled(true);\r
1847     },\r
1848 \r
1849     /**\r
1850      * Returns true if the components using this action are currently disabled, else returns false.  \r
1851      */\r
1852     isDisabled : function(){\r
1853         return this.initialConfig.disabled;\r
1854     },\r
1855 \r
1856     /**\r
1857      * Sets the hidden state of all components using this action.  Shortcut method\r
1858      * for <code>{@link #hide}</code> and <code>{@link #show}</code>.\r
1859      * @param {Boolean} hidden True to hide the component, false to show it\r
1860      */\r
1861     setHidden : function(v){\r
1862         this.initialConfig.hidden = v;\r
1863         this.callEach('setVisible', [!v]);\r
1864     },\r
1865 \r
1866     /**\r
1867      * Shows all components using this action.\r
1868      */\r
1869     show : function(){\r
1870         this.setHidden(false);\r
1871     },\r
1872 \r
1873     /**\r
1874      * Hides all components using this action.\r
1875      */\r
1876     hide : function(){\r
1877         this.setHidden(true);\r
1878     },\r
1879 \r
1880     /**\r
1881      * Returns true if the components using this action are currently hidden, else returns false.  \r
1882      */\r
1883     isHidden : function(){\r
1884         return this.initialConfig.hidden;\r
1885     },\r
1886 \r
1887     /**\r
1888      * Sets the function that will be called by each component using this action when its primary event is triggered.\r
1889      * @param {Function} fn The function that will be invoked by the action's components.  The function\r
1890      * will be called with no arguments.\r
1891      * @param {Object} scope The scope in which the function will execute\r
1892      */\r
1893     setHandler : function(fn, scope){\r
1894         this.initialConfig.handler = fn;\r
1895         this.initialConfig.scope = scope;\r
1896         this.callEach('setHandler', [fn, scope]);\r
1897     },\r
1898 \r
1899     /**\r
1900      * Executes the specified function once for each component currently tied to this action.  The function passed\r
1901      * in should accept a single argument that will be an object that supports the basic Action config/method interface.\r
1902      * @param {Function} fn The function to execute for each component\r
1903      * @param {Object} scope The scope in which the function will execute\r
1904      */\r
1905     each : function(fn, scope){\r
1906         Ext.each(this.items, fn, scope);\r
1907     },\r
1908 \r
1909     // private\r
1910     callEach : function(fnName, args){\r
1911         var cs = this.items;\r
1912         for(var i = 0, len = cs.length; i < len; i++){\r
1913             cs[i][fnName].apply(cs[i], args);\r
1914         }\r
1915     },\r
1916 \r
1917     // private\r
1918     addComponent : function(comp){\r
1919         this.items.push(comp);\r
1920         comp.on('destroy', this.removeComponent, this);\r
1921     },\r
1922 \r
1923     // private\r
1924     removeComponent : function(comp){\r
1925         this.items.remove(comp);\r
1926     },\r
1927 \r
1928     /**\r
1929      * Executes this action manually using the handler function specified in the original config object\r
1930      * or the handler function set with <code>{@link #setHandler}</code>.  Any arguments passed to this\r
1931      * function will be passed on to the handler function.\r
1932      * @param {Mixed} arg1 (optional) Variable number of arguments passed to the handler function\r
1933      * @param {Mixed} arg2 (optional)\r
1934      * @param {Mixed} etc... (optional)\r
1935      */\r
1936     execute : function(){\r
1937         this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);\r
1938     }\r
1939 };
1940 /**
1941  * @class Ext.Layer
1942  * @extends Ext.Element
1943  * An extended {@link Ext.Element} object that supports a shadow and shim, constrain to viewport and
1944  * automatic maintaining of shadow/shim positions.
1945  * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true)
1946  * @cfg {String/Boolean} shadow True to automatically create an {@link Ext.Shadow}, or a string indicating the
1947  * shadow's display {@link Ext.Shadow#mode}. False to disable the shadow. (defaults to false)
1948  * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: 'div', cls: 'x-layer'}).
1949  * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true)
1950  * @cfg {String} cls CSS class to add to the element
1951  * @cfg {Number} zindex Starting z-index (defaults to 11000)
1952  * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 4)
1953  * @cfg {Boolean} useDisplay
1954  * Defaults to use css offsets to hide the Layer. Specify <tt>true</tt>
1955  * to use css style <tt>'display:none;'</tt> to hide the Layer.
1956  * @constructor
1957  * @param {Object} config An object with config options.
1958  * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element. If the element is not found it creates it.
1959  */
1960 (function(){
1961 Ext.Layer = function(config, existingEl){
1962     config = config || {};
1963     var dh = Ext.DomHelper;
1964     var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
1965     if(existingEl){
1966         this.dom = Ext.getDom(existingEl);
1967     }
1968     if(!this.dom){
1969         var o = config.dh || {tag: 'div', cls: 'x-layer'};
1970         this.dom = dh.append(pel, o);
1971     }
1972     if(config.cls){
1973         this.addClass(config.cls);
1974     }
1975     this.constrain = config.constrain !== false;
1976     this.setVisibilityMode(Ext.Element.VISIBILITY);
1977     if(config.id){
1978         this.id = this.dom.id = config.id;
1979     }else{
1980         this.id = Ext.id(this.dom);
1981     }
1982     this.zindex = config.zindex || this.getZIndex();
1983     this.position('absolute', this.zindex);
1984     if(config.shadow){
1985         this.shadowOffset = config.shadowOffset || 4;
1986         this.shadow = new Ext.Shadow({
1987             offset : this.shadowOffset,
1988             mode : config.shadow
1989         });
1990     }else{
1991         this.shadowOffset = 0;
1992     }
1993     this.useShim = config.shim !== false && Ext.useShims;
1994     this.useDisplay = config.useDisplay;
1995     this.hide();
1996 };
1997
1998 var supr = Ext.Element.prototype;
1999
2000 // shims are shared among layer to keep from having 100 iframes
2001 var shims = [];
2002
2003 Ext.extend(Ext.Layer, Ext.Element, {
2004
2005     getZIndex : function(){
2006         return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
2007     },
2008
2009     getShim : function(){
2010         if(!this.useShim){
2011             return null;
2012         }
2013         if(this.shim){
2014             return this.shim;
2015         }
2016         var shim = shims.shift();
2017         if(!shim){
2018             shim = this.createShim();
2019             shim.enableDisplayMode('block');
2020             shim.dom.style.display = 'none';
2021             shim.dom.style.visibility = 'visible';
2022         }
2023         var pn = this.dom.parentNode;
2024         if(shim.dom.parentNode != pn){
2025             pn.insertBefore(shim.dom, this.dom);
2026         }
2027         shim.setStyle('z-index', this.getZIndex()-2);
2028         this.shim = shim;
2029         return shim;
2030     },
2031
2032     hideShim : function(){
2033         if(this.shim){
2034             this.shim.setDisplayed(false);
2035             shims.push(this.shim);
2036             delete this.shim;
2037         }
2038     },
2039
2040     disableShadow : function(){
2041         if(this.shadow){
2042             this.shadowDisabled = true;
2043             this.shadow.hide();
2044             this.lastShadowOffset = this.shadowOffset;
2045             this.shadowOffset = 0;
2046         }
2047     },
2048
2049     enableShadow : function(show){
2050         if(this.shadow){
2051             this.shadowDisabled = false;
2052             this.shadowOffset = this.lastShadowOffset;
2053             delete this.lastShadowOffset;
2054             if(show){
2055                 this.sync(true);
2056             }
2057         }
2058     },
2059
2060     // private
2061     // this code can execute repeatedly in milliseconds (i.e. during a drag) so
2062     // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
2063     sync : function(doShow){
2064         var sw = this.shadow;
2065         if(!this.updating && this.isVisible() && (sw || this.useShim)){
2066             var sh = this.getShim();
2067
2068             var w = this.getWidth(),
2069                 h = this.getHeight();
2070
2071             var l = this.getLeft(true),
2072                 t = this.getTop(true);
2073
2074             if(sw && !this.shadowDisabled){
2075                 if(doShow && !sw.isVisible()){
2076                     sw.show(this);
2077                 }else{
2078                     sw.realign(l, t, w, h);
2079                 }
2080                 if(sh){
2081                     if(doShow){
2082                        sh.show();
2083                     }
2084                     // fit the shim behind the shadow, so it is shimmed too
2085                     var a = sw.adjusts, s = sh.dom.style;
2086                     s.left = (Math.min(l, l+a.l))+'px';
2087                     s.top = (Math.min(t, t+a.t))+'px';
2088                     s.width = (w+a.w)+'px';
2089                     s.height = (h+a.h)+'px';
2090                 }
2091             }else if(sh){
2092                 if(doShow){
2093                    sh.show();
2094                 }
2095                 sh.setSize(w, h);
2096                 sh.setLeftTop(l, t);
2097             }
2098
2099         }
2100     },
2101
2102     // private
2103     destroy : function(){
2104         this.hideShim();
2105         if(this.shadow){
2106             this.shadow.hide();
2107         }
2108         this.removeAllListeners();
2109         Ext.removeNode(this.dom);
2110         Ext.Element.uncache(this.id);
2111     },
2112
2113     remove : function(){
2114         this.destroy();
2115     },
2116
2117     // private
2118     beginUpdate : function(){
2119         this.updating = true;
2120     },
2121
2122     // private
2123     endUpdate : function(){
2124         this.updating = false;
2125         this.sync(true);
2126     },
2127
2128     // private
2129     hideUnders : function(negOffset){
2130         if(this.shadow){
2131             this.shadow.hide();
2132         }
2133         this.hideShim();
2134     },
2135
2136     // private
2137     constrainXY : function(){
2138         if(this.constrain){
2139             var vw = Ext.lib.Dom.getViewWidth(),
2140                 vh = Ext.lib.Dom.getViewHeight();
2141             var s = Ext.getDoc().getScroll();
2142
2143             var xy = this.getXY();
2144             var x = xy[0], y = xy[1];
2145             var so = this.shadowOffset;
2146             var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so;
2147             // only move it if it needs it
2148             var moved = false;
2149             // first validate right/bottom
2150             if((x + w) > vw+s.left){
2151                 x = vw - w - so;
2152                 moved = true;
2153             }
2154             if((y + h) > vh+s.top){
2155                 y = vh - h - so;
2156                 moved = true;
2157             }
2158             // then make sure top/left isn't negative
2159             if(x < s.left){
2160                 x = s.left;
2161                 moved = true;
2162             }
2163             if(y < s.top){
2164                 y = s.top;
2165                 moved = true;
2166             }
2167             if(moved){
2168                 if(this.avoidY){
2169                     var ay = this.avoidY;
2170                     if(y <= ay && (y+h) >= ay){
2171                         y = ay-h-5;
2172                     }
2173                 }
2174                 xy = [x, y];
2175                 this.storeXY(xy);
2176                 supr.setXY.call(this, xy);
2177                 this.sync();
2178             }
2179         }
2180         return this;
2181     },
2182
2183     isVisible : function(){
2184         return this.visible;
2185     },
2186
2187     // private
2188     showAction : function(){
2189         this.visible = true; // track visibility to prevent getStyle calls
2190         if(this.useDisplay === true){
2191             this.setDisplayed('');
2192         }else if(this.lastXY){
2193             supr.setXY.call(this, this.lastXY);
2194         }else if(this.lastLT){
2195             supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
2196         }
2197     },
2198
2199     // private
2200     hideAction : function(){
2201         this.visible = false;
2202         if(this.useDisplay === true){
2203             this.setDisplayed(false);
2204         }else{
2205             this.setLeftTop(-10000,-10000);
2206         }
2207     },
2208
2209     // overridden Element method
2210     setVisible : function(v, a, d, c, e){
2211         if(v){
2212             this.showAction();
2213         }
2214         if(a && v){
2215             var cb = function(){
2216                 this.sync(true);
2217                 if(c){
2218                     c();
2219                 }
2220             }.createDelegate(this);
2221             supr.setVisible.call(this, true, true, d, cb, e);
2222         }else{
2223             if(!v){
2224                 this.hideUnders(true);
2225             }
2226             var cb = c;
2227             if(a){
2228                 cb = function(){
2229                     this.hideAction();
2230                     if(c){
2231                         c();
2232                     }
2233                 }.createDelegate(this);
2234             }
2235             supr.setVisible.call(this, v, a, d, cb, e);
2236             if(v){
2237                 this.sync(true);
2238             }else if(!a){
2239                 this.hideAction();
2240             }
2241         }
2242         return this;
2243     },
2244
2245     storeXY : function(xy){
2246         delete this.lastLT;
2247         this.lastXY = xy;
2248     },
2249
2250     storeLeftTop : function(left, top){
2251         delete this.lastXY;
2252         this.lastLT = [left, top];
2253     },
2254
2255     // private
2256     beforeFx : function(){
2257         this.beforeAction();
2258         return Ext.Layer.superclass.beforeFx.apply(this, arguments);
2259     },
2260
2261     // private
2262     afterFx : function(){
2263         Ext.Layer.superclass.afterFx.apply(this, arguments);
2264         this.sync(this.isVisible());
2265     },
2266
2267     // private
2268     beforeAction : function(){
2269         if(!this.updating && this.shadow){
2270             this.shadow.hide();
2271         }
2272     },
2273
2274     // overridden Element method
2275     setLeft : function(left){
2276         this.storeLeftTop(left, this.getTop(true));
2277         supr.setLeft.apply(this, arguments);
2278         this.sync();
2279         return this;
2280     },
2281
2282     setTop : function(top){
2283         this.storeLeftTop(this.getLeft(true), top);
2284         supr.setTop.apply(this, arguments);
2285         this.sync();
2286         return this;
2287     },
2288
2289     setLeftTop : function(left, top){
2290         this.storeLeftTop(left, top);
2291         supr.setLeftTop.apply(this, arguments);
2292         this.sync();
2293         return this;
2294     },
2295
2296     setXY : function(xy, a, d, c, e){
2297         this.fixDisplay();
2298         this.beforeAction();
2299         this.storeXY(xy);
2300         var cb = this.createCB(c);
2301         supr.setXY.call(this, xy, a, d, cb, e);
2302         if(!a){
2303             cb();
2304         }
2305         return this;
2306     },
2307
2308     // private
2309     createCB : function(c){
2310         var el = this;
2311         return function(){
2312             el.constrainXY();
2313             el.sync(true);
2314             if(c){
2315                 c();
2316             }
2317         };
2318     },
2319
2320     // overridden Element method
2321     setX : function(x, a, d, c, e){
2322         this.setXY([x, this.getY()], a, d, c, e);
2323         return this;
2324     },
2325
2326     // overridden Element method
2327     setY : function(y, a, d, c, e){
2328         this.setXY([this.getX(), y], a, d, c, e);
2329         return this;
2330     },
2331
2332     // overridden Element method
2333     setSize : function(w, h, a, d, c, e){
2334         this.beforeAction();
2335         var cb = this.createCB(c);
2336         supr.setSize.call(this, w, h, a, d, cb, e);
2337         if(!a){
2338             cb();
2339         }
2340         return this;
2341     },
2342
2343     // overridden Element method
2344     setWidth : function(w, a, d, c, e){
2345         this.beforeAction();
2346         var cb = this.createCB(c);
2347         supr.setWidth.call(this, w, a, d, cb, e);
2348         if(!a){
2349             cb();
2350         }
2351         return this;
2352     },
2353
2354     // overridden Element method
2355     setHeight : function(h, a, d, c, e){
2356         this.beforeAction();
2357         var cb = this.createCB(c);
2358         supr.setHeight.call(this, h, a, d, cb, e);
2359         if(!a){
2360             cb();
2361         }
2362         return this;
2363     },
2364
2365     // overridden Element method
2366     setBounds : function(x, y, w, h, a, d, c, e){
2367         this.beforeAction();
2368         var cb = this.createCB(c);
2369         if(!a){
2370             this.storeXY([x, y]);
2371             supr.setXY.call(this, [x, y]);
2372             supr.setSize.call(this, w, h, a, d, cb, e);
2373             cb();
2374         }else{
2375             supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
2376         }
2377         return this;
2378     },
2379
2380     /**
2381      * Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
2382      * incremented by two more than the value passed in so that it always shows above any shadow or shim (the shadow
2383      * element, if any, will be assigned z-index + 1, and the shim element, if any, will be assigned the unmodified z-index).
2384      * @param {Number} zindex The new z-index to set
2385      * @return {this} The Layer
2386      */
2387     setZIndex : function(zindex){
2388         this.zindex = zindex;
2389         this.setStyle('z-index', zindex + 2);
2390         if(this.shadow){
2391             this.shadow.setZIndex(zindex + 1);
2392         }
2393         if(this.shim){
2394             this.shim.setStyle('z-index', zindex);
2395         }
2396         return this;
2397     }
2398 });
2399 })();/**
2400  * @class Ext.Shadow
2401  * Simple class that can provide a shadow effect for any element.  Note that the element MUST be absolutely positioned,
2402  * and the shadow does not provide any shimming.  This should be used only in simple cases -- for more advanced
2403  * functionality that can also provide the same shadow effect, see the {@link Ext.Layer} class.
2404  * @constructor
2405  * Create a new Shadow
2406  * @param {Object} config The config object
2407  */
2408 Ext.Shadow = function(config){
2409     Ext.apply(this, config);
2410     if(typeof this.mode != "string"){
2411         this.mode = this.defaultMode;
2412     }
2413     var o = this.offset, a = {h: 0};
2414     var rad = Math.floor(this.offset/2);
2415     switch(this.mode.toLowerCase()){ // all this hideous nonsense calculates the various offsets for shadows
2416         case "drop":
2417             a.w = 0;
2418             a.l = a.t = o;
2419             a.t -= 1;
2420             if(Ext.isIE){
2421                 a.l -= this.offset + rad;
2422                 a.t -= this.offset + rad;
2423                 a.w -= rad;
2424                 a.h -= rad;
2425                 a.t += 1;
2426             }
2427         break;
2428         case "sides":
2429             a.w = (o*2);
2430             a.l = -o;
2431             a.t = o-1;
2432             if(Ext.isIE){
2433                 a.l -= (this.offset - rad);
2434                 a.t -= this.offset + rad;
2435                 a.l += 1;
2436                 a.w -= (this.offset - rad)*2;
2437                 a.w -= rad + 1;
2438                 a.h -= 1;
2439             }
2440         break;
2441         case "frame":
2442             a.w = a.h = (o*2);
2443             a.l = a.t = -o;
2444             a.t += 1;
2445             a.h -= 2;
2446             if(Ext.isIE){
2447                 a.l -= (this.offset - rad);
2448                 a.t -= (this.offset - rad);
2449                 a.l += 1;
2450                 a.w -= (this.offset + rad + 1);
2451                 a.h -= (this.offset + rad);
2452                 a.h += 1;
2453             }
2454         break;
2455     };
2456
2457     this.adjusts = a;
2458 };
2459
2460 Ext.Shadow.prototype = {
2461     /**
2462      * @cfg {String} mode
2463      * The shadow display mode.  Supports the following options:<div class="mdetail-params"><ul>
2464      * <li><b><tt>sides</tt></b> : Shadow displays on both sides and bottom only</li>
2465      * <li><b><tt>frame</tt></b> : Shadow displays equally on all four sides</li>
2466      * <li><b><tt>drop</tt></b> : Traditional bottom-right drop shadow</li>
2467      * </ul></div>
2468      */
2469     /**
2470      * @cfg {String} offset
2471      * The number of pixels to offset the shadow from the element (defaults to <tt>4</tt>)
2472      */
2473     offset: 4,
2474
2475     // private
2476     defaultMode: "drop",
2477
2478     /**
2479      * Displays the shadow under the target element
2480      * @param {Mixed} targetEl The id or element under which the shadow should display
2481      */
2482     show : function(target){
2483         target = Ext.get(target);
2484         if(!this.el){
2485             this.el = Ext.Shadow.Pool.pull();
2486             if(this.el.dom.nextSibling != target.dom){
2487                 this.el.insertBefore(target);
2488             }
2489         }
2490         this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
2491         if(Ext.isIE){
2492             this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
2493         }
2494         this.realign(
2495             target.getLeft(true),
2496             target.getTop(true),
2497             target.getWidth(),
2498             target.getHeight()
2499         );
2500         this.el.dom.style.display = "block";
2501     },
2502
2503     /**
2504      * Returns true if the shadow is visible, else false
2505      */
2506     isVisible : function(){
2507         return this.el ? true : false;  
2508     },
2509
2510     /**
2511      * Direct alignment when values are already available. Show must be called at least once before
2512      * calling this method to ensure it is initialized.
2513      * @param {Number} left The target element left position
2514      * @param {Number} top The target element top position
2515      * @param {Number} width The target element width
2516      * @param {Number} height The target element height
2517      */
2518     realign : function(l, t, w, h){
2519         if(!this.el){
2520             return;
2521         }
2522         var a = this.adjusts, d = this.el.dom, s = d.style;
2523         var iea = 0;
2524         s.left = (l+a.l)+"px";
2525         s.top = (t+a.t)+"px";
2526         var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
2527         if(s.width != sws || s.height != shs){
2528             s.width = sws;
2529             s.height = shs;
2530             if(!Ext.isIE){
2531                 var cn = d.childNodes;
2532                 var sww = Math.max(0, (sw-12))+"px";
2533                 cn[0].childNodes[1].style.width = sww;
2534                 cn[1].childNodes[1].style.width = sww;
2535                 cn[2].childNodes[1].style.width = sww;
2536                 cn[1].style.height = Math.max(0, (sh-12))+"px";
2537             }
2538         }
2539     },
2540
2541     /**
2542      * Hides this shadow
2543      */
2544     hide : function(){
2545         if(this.el){
2546             this.el.dom.style.display = "none";
2547             Ext.Shadow.Pool.push(this.el);
2548             delete this.el;
2549         }
2550     },
2551
2552     /**
2553      * Adjust the z-index of this shadow
2554      * @param {Number} zindex The new z-index
2555      */
2556     setZIndex : function(z){
2557         this.zIndex = z;
2558         if(this.el){
2559             this.el.setStyle("z-index", z);
2560         }
2561     }
2562 };
2563
2564 // Private utility class that manages the internal Shadow cache
2565 Ext.Shadow.Pool = function(){
2566     var p = [];
2567     var markup = Ext.isIE ?
2568                  '<div class="x-ie-shadow"></div>' :
2569                  '<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>';
2570     return {
2571         pull : function(){
2572             var sh = p.shift();
2573             if(!sh){
2574                 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
2575                 sh.autoBoxAdjust = false;
2576             }
2577             return sh;
2578         },
2579
2580         push : function(sh){
2581             p.push(sh);
2582         }
2583     };
2584 }();/**
2585  * @class Ext.BoxComponent
2586  * @extends Ext.Component
2587  * <p>Base class for any {@link Ext.Component Component} that is to be sized as a box, using width and height.</p>
2588  * <p>BoxComponent provides automatic box model adjustments for sizing and positioning and will work correctly
2589  * within the Component rendering model.</p>
2590  * <p>A BoxComponent may be created as a custom Component which encapsulates any HTML element, either a pre-existing
2591  * element, or one that is created to your specifications at render time. Usually, to participate in layouts,
2592  * a Component will need to be a <b>Box</b>Component in order to have its width and height managed.</p>
2593  * <p>To use a pre-existing element as a BoxComponent, configure it so that you preset the <b>el</b> property to the
2594  * element to reference:<pre><code>
2595 var pageHeader = new Ext.BoxComponent({
2596     el: 'my-header-div'
2597 });</code></pre>
2598  * This may then be {@link Ext.Container#add added} to a {@link Ext.Container Container} as a child item.</p>
2599  * <p>To create a BoxComponent based around a HTML element to be created at render time, use the
2600  * {@link Ext.Component#autoEl autoEl} config option which takes the form of a
2601  * {@link Ext.DomHelper DomHelper} specification:<pre><code>
2602 var myImage = new Ext.BoxComponent({
2603     autoEl: {
2604         tag: 'img',
2605         src: '/images/my-image.jpg'
2606     }
2607 });</code></pre></p>
2608  * @constructor
2609  * @param {Ext.Element/String/Object} config The configuration options.
2610  * @xtype box
2611  */
2612 Ext.BoxComponent = Ext.extend(Ext.Component, {
2613
2614     // Configs below are used for all Components when rendered by BorderLayout.
2615     /**
2616      * @cfg {String} region <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2617      * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2618      * layout manager (e.g. specifying <tt>layout:'border'</tt>).</p><br>
2619      * <p>See {@link Ext.layout.BorderLayout} also.</p>
2620      */
2621     // margins config is used when a BoxComponent is rendered by BorderLayout or BoxLayout.
2622     /**
2623      * @cfg {Object} margins <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2624      * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2625      * or one of the two <b>{@link Ext.layout.BoxLayout BoxLayout} subclasses.</b></p>
2626      * <p>An object containing margins to apply to this BoxComponent in the
2627      * format:</p><pre><code>
2628 {
2629     top: (top margin),
2630     right: (right margin),
2631     bottom: (bottom margin),
2632     left: (left margin)
2633 }</code></pre>
2634      * <p>May also be a string containing space-separated, numeric margin values. The order of the
2635      * sides associated with each value matches the way CSS processes margin values:</p>
2636      * <p><div class="mdetail-params"><ul>
2637      * <li>If there is only one value, it applies to all sides.</li>
2638      * <li>If there are two values, the top and bottom borders are set to the first value and the
2639      * right and left are set to the second.</li>
2640      * <li>If there are three values, the top is set to the first value, the left and right are set
2641      * to the second, and the bottom is set to the third.</li>
2642      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
2643      * </ul></div></p>
2644      * <p>Defaults to:</p><pre><code>
2645      * {top:0, right:0, bottom:0, left:0}
2646      * </code></pre>
2647      */
2648     /**
2649      * @cfg {Number} x
2650      * The local x (left) coordinate for this component if contained within a positioning container.
2651      */
2652     /**
2653      * @cfg {Number} y
2654      * The local y (top) coordinate for this component if contained within a positioning container.
2655      */
2656     /**
2657      * @cfg {Number} pageX
2658      * The page level x coordinate for this component if contained within a positioning container.
2659      */
2660     /**
2661      * @cfg {Number} pageY
2662      * The page level y coordinate for this component if contained within a positioning container.
2663      */
2664     /**
2665      * @cfg {Number} height
2666      * The height of this component in pixels (defaults to auto).
2667      * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
2668      */
2669     /**
2670      * @cfg {Number} width
2671      * The width of this component in pixels (defaults to auto).
2672      * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
2673      */
2674     /**
2675      * @cfg {Boolean} autoHeight
2676      * <p>True to use height:'auto', false to use fixed height (or allow it to be managed by its parent
2677      * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
2678      * <p><b>Note</b>: Although many components inherit this config option, not all will
2679      * function as expected with a height of 'auto'. Setting autoHeight:true means that the
2680      * browser will manage height based on the element's contents, and that Ext will not manage it at all.</p>
2681      * <p>If the <i>browser</i> is managing the height, be aware that resizes performed by the browser in response
2682      * to changes within the structure of the Component cannot be detected. Therefore changes to the height might
2683      * result in elements needing to be synchronized with the new height. Example:</p><pre><code>
2684 var w = new Ext.Window({
2685     title: 'Window',
2686     width: 600,
2687     autoHeight: true,
2688     items: {
2689         title: 'Collapse Me',
2690         height: 400,
2691         collapsible: true,
2692         border: false,
2693         listeners: {
2694             beforecollapse: function() {
2695                 w.el.shadow.hide();
2696             },
2697             beforeexpand: function() {
2698                 w.el.shadow.hide();
2699             },
2700             collapse: function() {
2701                 w.syncShadow();
2702             },
2703             expand: function() {
2704                 w.syncShadow();
2705             }
2706         }
2707     }
2708 }).show();
2709 </code></pre>
2710      */
2711     /**
2712      * @cfg {Boolean} autoWidth
2713      * <p>True to use width:'auto', false to use fixed width (or allow it to be managed by its parent
2714      * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
2715      * <p><b>Note</b>: Although many components  inherit this config option, not all will
2716      * function as expected with a width of 'auto'. Setting autoWidth:true means that the
2717      * browser will manage width based on the element's contents, and that Ext will not manage it at all.</p>
2718      * <p>If the <i>browser</i> is managing the width, be aware that resizes performed by the browser in response
2719      * to changes within the structure of the Component cannot be detected. Therefore changes to the width might
2720      * result in elements needing to be synchronized with the new width. For example, where the target element is:</p><pre><code>
2721 &lt;div id='grid-container' style='margin-left:25%;width:50%'>&lt;/div>
2722 </code></pre>
2723      * A Panel rendered into that target element must listen for browser window resize in order to relay its
2724       * child items when the browser changes its width:<pre><code>
2725 var myPanel = new Ext.Panel({
2726     renderTo: 'grid-container',
2727     monitorResize: true, // relay on browser resize
2728     title: 'Panel',
2729     height: 400,
2730     autoWidth: true,
2731     layout: 'hbox',
2732     layoutConfig: {
2733         align: 'stretch'
2734     },
2735     defaults: {
2736         flex: 1
2737     },
2738     items: [{
2739         title: 'Box 1',
2740     }, {
2741         title: 'Box 2'
2742     }, {
2743         title: 'Box 3'
2744     }],
2745 });
2746 </code></pre>
2747      */
2748
2749     /* // private internal config
2750      * {Boolean} deferHeight
2751      * True to defer height calculations to an external component, false to allow this component to set its own
2752      * height (defaults to false).
2753      */
2754
2755     // private
2756     initComponent : function(){
2757         Ext.BoxComponent.superclass.initComponent.call(this);
2758         this.addEvents(
2759             /**
2760              * @event resize
2761              * Fires after the component is resized.
2762              * @param {Ext.Component} this
2763              * @param {Number} adjWidth The box-adjusted width that was set
2764              * @param {Number} adjHeight The box-adjusted height that was set
2765              * @param {Number} rawWidth The width that was originally specified
2766              * @param {Number} rawHeight The height that was originally specified
2767              */
2768             'resize',
2769             /**
2770              * @event move
2771              * Fires after the component is moved.
2772              * @param {Ext.Component} this
2773              * @param {Number} x The new x position
2774              * @param {Number} y The new y position
2775              */
2776             'move'
2777         );
2778     },
2779
2780     // private, set in afterRender to signify that the component has been rendered
2781     boxReady : false,
2782     // private, used to defer height settings to subclasses
2783     deferHeight: false,
2784
2785     /**
2786      * Sets the width and height of this BoxComponent. This method fires the {@link #resize} event. This method can accept
2787      * either width and height as separate arguments, or you can pass a size object like <code>{width:10, height:20}</code>.
2788      * @param {Mixed} width The new width to set. This may be one of:<div class="mdetail-params"><ul>
2789      * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
2790      * <li>A String used to set the CSS width style.</li>
2791      * <li>A size object in the format <code>{width: widthValue, height: heightValue}</code>.</li>
2792      * <li><code>undefined</code> to leave the width unchanged.</li>
2793      * </ul></div>
2794      * @param {Mixed} height The new height to set (not required if a size object is passed as the first arg).
2795      * This may be one of:<div class="mdetail-params"><ul>
2796      * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
2797      * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
2798      * <li><code>undefined</code> to leave the height unchanged.</li>
2799      * </ul></div>
2800      * @return {Ext.BoxComponent} this
2801      */
2802     setSize : function(w, h){
2803         // support for standard size objects
2804         if(typeof w == 'object'){
2805             h = w.height;
2806             w = w.width;
2807         }
2808         // not rendered
2809         if(!this.boxReady){
2810             this.width = w;
2811             this.height = h;
2812             return this;
2813         }
2814
2815         // prevent recalcs when not needed
2816         if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
2817             return this;
2818         }
2819         this.lastSize = {width: w, height: h};
2820         var adj = this.adjustSize(w, h);
2821         var aw = adj.width, ah = adj.height;
2822         if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
2823             var rz = this.getResizeEl();
2824             if(!this.deferHeight && aw !== undefined && ah !== undefined){
2825                 rz.setSize(aw, ah);
2826             }else if(!this.deferHeight && ah !== undefined){
2827                 rz.setHeight(ah);
2828             }else if(aw !== undefined){
2829                 rz.setWidth(aw);
2830             }
2831             this.onResize(aw, ah, w, h);
2832             this.fireEvent('resize', this, aw, ah, w, h);
2833         }
2834         return this;
2835     },
2836
2837     /**
2838      * Sets the width of the component.  This method fires the {@link #resize} event.
2839      * @param {Number} width The new width to setThis may be one of:<div class="mdetail-params"><ul>
2840      * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
2841      * <li>A String used to set the CSS width style.</li>
2842      * </ul></div>
2843      * @return {Ext.BoxComponent} this
2844      */
2845     setWidth : function(width){
2846         return this.setSize(width);
2847     },
2848
2849     /**
2850      * Sets the height of the component.  This method fires the {@link #resize} event.
2851      * @param {Number} height The new height to set. This may be one of:<div class="mdetail-params"><ul>
2852      * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
2853      * <li>A String used to set the CSS height style.</li>
2854      * <li><i>undefined</i> to leave the height unchanged.</li>
2855      * </ul></div>
2856      * @return {Ext.BoxComponent} this
2857      */
2858     setHeight : function(height){
2859         return this.setSize(undefined, height);
2860     },
2861
2862     /**
2863      * Gets the current size of the component's underlying element.
2864      * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
2865      */
2866     getSize : function(){
2867         return this.getResizeEl().getSize();
2868     },
2869
2870     /**
2871      * Gets the current width of the component's underlying element.
2872      * @return {Number}
2873      */
2874     getWidth : function(){
2875         return this.getResizeEl().getWidth();
2876     },
2877
2878     /**
2879      * Gets the current height of the component's underlying element.
2880      * @return {Number}
2881      */
2882     getHeight : function(){
2883         return this.getResizeEl().getHeight();
2884     },
2885
2886     /**
2887      * Gets the current size of the component's underlying element, including space taken by its margins.
2888      * @return {Object} An object containing the element's size {width: (element width + left/right margins), height: (element height + top/bottom margins)}
2889      */
2890     getOuterSize : function(){
2891         var el = this.getResizeEl();
2892         return {width: el.getWidth() + el.getMargins('lr'),
2893                 height: el.getHeight() + el.getMargins('tb')};
2894     },
2895
2896     /**
2897      * Gets the current XY position of the component's underlying element.
2898      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
2899      * @return {Array} The XY position of the element (e.g., [100, 200])
2900      */
2901     getPosition : function(local){
2902         var el = this.getPositionEl();
2903         if(local === true){
2904             return [el.getLeft(true), el.getTop(true)];
2905         }
2906         return this.xy || el.getXY();
2907     },
2908
2909     /**
2910      * Gets the current box measurements of the component's underlying element.
2911      * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
2912      * @return {Object} box An object in the format {x, y, width, height}
2913      */
2914     getBox : function(local){
2915         var pos = this.getPosition(local);
2916         var s = this.getSize();
2917         s.x = pos[0];
2918         s.y = pos[1];
2919         return s;
2920     },
2921
2922     /**
2923      * Sets the current box measurements of the component's underlying element.
2924      * @param {Object} box An object in the format {x, y, width, height}
2925      * @return {Ext.BoxComponent} this
2926      */
2927     updateBox : function(box){
2928         this.setSize(box.width, box.height);
2929         this.setPagePosition(box.x, box.y);
2930         return this;
2931     },
2932
2933     /**
2934      * <p>Returns the outermost Element of this Component which defines the Components overall size.</p>
2935      * <p><i>Usually</i> this will return the same Element as <code>{@link #getEl}</code>,
2936      * but in some cases, a Component may have some more wrapping Elements around its main
2937      * active Element.</p>
2938      * <p>An example is a ComboBox. It is encased in a <i>wrapping</i> Element which
2939      * contains both the <code>&lt;input></code> Element (which is what would be returned
2940      * by its <code>{@link #getEl}</code> method, <i>and</i> the trigger button Element.
2941      * This Element is returned as the <code>resizeEl</code>.
2942      */
2943     getResizeEl : function(){
2944         return this.resizeEl || this.el;
2945     },
2946
2947     // protected
2948     getPositionEl : function(){
2949         return this.positionEl || this.el;
2950     },
2951
2952     /**
2953      * Sets the left and top of the component.  To set the page XY position instead, use {@link #setPagePosition}.
2954      * This method fires the {@link #move} event.
2955      * @param {Number} left The new left
2956      * @param {Number} top The new top
2957      * @return {Ext.BoxComponent} this
2958      */
2959     setPosition : function(x, y){
2960         if(x && typeof x[1] == 'number'){
2961             y = x[1];
2962             x = x[0];
2963         }
2964         this.x = x;
2965         this.y = y;
2966         if(!this.boxReady){
2967             return this;
2968         }
2969         var adj = this.adjustPosition(x, y);
2970         var ax = adj.x, ay = adj.y;
2971
2972         var el = this.getPositionEl();
2973         if(ax !== undefined || ay !== undefined){
2974             if(ax !== undefined && ay !== undefined){
2975                 el.setLeftTop(ax, ay);
2976             }else if(ax !== undefined){
2977                 el.setLeft(ax);
2978             }else if(ay !== undefined){
2979                 el.setTop(ay);
2980             }
2981             this.onPosition(ax, ay);
2982             this.fireEvent('move', this, ax, ay);
2983         }
2984         return this;
2985     },
2986
2987     /**
2988      * Sets the page XY position of the component.  To set the left and top instead, use {@link #setPosition}.
2989      * This method fires the {@link #move} event.
2990      * @param {Number} x The new x position
2991      * @param {Number} y The new y position
2992      * @return {Ext.BoxComponent} this
2993      */
2994     setPagePosition : function(x, y){
2995         if(x && typeof x[1] == 'number'){
2996             y = x[1];
2997             x = x[0];
2998         }
2999         this.pageX = x;
3000         this.pageY = y;
3001         if(!this.boxReady){
3002             return;
3003         }
3004         if(x === undefined || y === undefined){ // cannot translate undefined points
3005             return;
3006         }
3007         var p = this.getPositionEl().translatePoints(x, y);
3008         this.setPosition(p.left, p.top);
3009         return this;
3010     },
3011
3012     // private
3013     onRender : function(ct, position){
3014         Ext.BoxComponent.superclass.onRender.call(this, ct, position);
3015         if(this.resizeEl){
3016             this.resizeEl = Ext.get(this.resizeEl);
3017         }
3018         if(this.positionEl){
3019             this.positionEl = Ext.get(this.positionEl);
3020         }
3021     },
3022
3023     // private
3024     afterRender : function(){
3025         Ext.BoxComponent.superclass.afterRender.call(this);
3026         this.boxReady = true;
3027         this.setSize(this.width, this.height);
3028         if(this.x || this.y){
3029             this.setPosition(this.x, this.y);
3030         }else if(this.pageX || this.pageY){
3031             this.setPagePosition(this.pageX, this.pageY);
3032         }
3033     },
3034
3035     /**
3036      * Force the component's size to recalculate based on the underlying element's current height and width.
3037      * @return {Ext.BoxComponent} this
3038      */
3039     syncSize : function(){
3040         delete this.lastSize;
3041         this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
3042         return this;
3043     },
3044
3045     /* // protected
3046      * Called after the component is resized, this method is empty by default but can be implemented by any
3047      * subclass that needs to perform custom logic after a resize occurs.
3048      * @param {Number} adjWidth The box-adjusted width that was set
3049      * @param {Number} adjHeight The box-adjusted height that was set
3050      * @param {Number} rawWidth The width that was originally specified
3051      * @param {Number} rawHeight The height that was originally specified
3052      */
3053     onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
3054
3055     },
3056
3057     /* // protected
3058      * Called after the component is moved, this method is empty by default but can be implemented by any
3059      * subclass that needs to perform custom logic after a move occurs.
3060      * @param {Number} x The new x position
3061      * @param {Number} y The new y position
3062      */
3063     onPosition : function(x, y){
3064
3065     },
3066
3067     // private
3068     adjustSize : function(w, h){
3069         if(this.autoWidth){
3070             w = 'auto';
3071         }
3072         if(this.autoHeight){
3073             h = 'auto';
3074         }
3075         return {width : w, height: h};
3076     },
3077
3078     // private
3079     adjustPosition : function(x, y){
3080         return {x : x, y: y};
3081     }
3082 });
3083 Ext.reg('box', Ext.BoxComponent);
3084
3085
3086 /**
3087  * @class Ext.Spacer
3088  * @extends Ext.BoxComponent
3089  * <p>Used to provide a sizable space in a layout.</p>
3090  * @constructor
3091  * @param {Object} config
3092  */
3093 Ext.Spacer = Ext.extend(Ext.BoxComponent, {
3094     autoEl:'div'
3095 });
3096 Ext.reg('spacer', Ext.Spacer);/**\r
3097  * @class Ext.SplitBar\r
3098  * @extends Ext.util.Observable\r
3099  * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).\r
3100  * <br><br>\r
3101  * Usage:\r
3102  * <pre><code>\r
3103 var split = new Ext.SplitBar("elementToDrag", "elementToSize",\r
3104                    Ext.SplitBar.HORIZONTAL, Ext.SplitBar.LEFT);\r
3105 split.setAdapter(new Ext.SplitBar.AbsoluteLayoutAdapter("container"));\r
3106 split.minSize = 100;\r
3107 split.maxSize = 600;\r
3108 split.animate = true;\r
3109 split.on('moved', splitterMoved);\r
3110 </code></pre>\r
3111  * @constructor\r
3112  * Create a new SplitBar\r
3113  * @param {Mixed} dragElement The element to be dragged and act as the SplitBar.\r
3114  * @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged\r
3115  * @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)\r
3116  * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or  \r
3117                         Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial\r
3118                         position of the SplitBar).\r
3119  */\r
3120 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){\r
3121     \r
3122     /** @private */\r
3123     this.el = Ext.get(dragElement, true);\r
3124     this.el.dom.unselectable = "on";\r
3125     /** @private */\r
3126     this.resizingEl = Ext.get(resizingElement, true);\r
3127 \r
3128     /**\r
3129      * @private\r
3130      * The orientation of the split. Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)\r
3131      * Note: If this is changed after creating the SplitBar, the placement property must be manually updated\r
3132      * @type Number\r
3133      */\r
3134     this.orientation = orientation || Ext.SplitBar.HORIZONTAL;\r
3135     \r
3136     /**\r
3137      * The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.\r
3138      * @type Number\r
3139      * @property tickSize\r
3140      */\r
3141     /**\r
3142      * The minimum size of the resizing element. (Defaults to 0)\r
3143      * @type Number\r
3144      */\r
3145     this.minSize = 0;\r
3146     \r
3147     /**\r
3148      * The maximum size of the resizing element. (Defaults to 2000)\r
3149      * @type Number\r
3150      */\r
3151     this.maxSize = 2000;\r
3152     \r
3153     /**\r
3154      * Whether to animate the transition to the new size\r
3155      * @type Boolean\r
3156      */\r
3157     this.animate = false;\r
3158     \r
3159     /**\r
3160      * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.\r
3161      * @type Boolean\r
3162      */\r
3163     this.useShim = false;\r
3164     \r
3165     /** @private */\r
3166     this.shim = null;\r
3167     \r
3168     if(!existingProxy){\r
3169         /** @private */\r
3170         this.proxy = Ext.SplitBar.createProxy(this.orientation);\r
3171     }else{\r
3172         this.proxy = Ext.get(existingProxy).dom;\r
3173     }\r
3174     /** @private */\r
3175     this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});\r
3176     \r
3177     /** @private */\r
3178     this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);\r
3179     \r
3180     /** @private */\r
3181     this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);\r
3182     \r
3183     /** @private */\r
3184     this.dragSpecs = {};\r
3185     \r
3186     /**\r
3187      * @private The adapter to use to positon and resize elements\r
3188      */\r
3189     this.adapter = new Ext.SplitBar.BasicLayoutAdapter();\r
3190     this.adapter.init(this);\r
3191     \r
3192     if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
3193         /** @private */\r
3194         this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);\r
3195         this.el.addClass("x-splitbar-h");\r
3196     }else{\r
3197         /** @private */\r
3198         this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);\r
3199         this.el.addClass("x-splitbar-v");\r
3200     }\r
3201     \r
3202     this.addEvents(\r
3203         /**\r
3204          * @event resize\r
3205          * Fires when the splitter is moved (alias for {@link #moved})\r
3206          * @param {Ext.SplitBar} this\r
3207          * @param {Number} newSize the new width or height\r
3208          */\r
3209         "resize",\r
3210         /**\r
3211          * @event moved\r
3212          * Fires when the splitter is moved\r
3213          * @param {Ext.SplitBar} this\r
3214          * @param {Number} newSize the new width or height\r
3215          */\r
3216         "moved",\r
3217         /**\r
3218          * @event beforeresize\r
3219          * Fires before the splitter is dragged\r
3220          * @param {Ext.SplitBar} this\r
3221          */\r
3222         "beforeresize",\r
3223 \r
3224         "beforeapply"\r
3225     );\r
3226 \r
3227     Ext.SplitBar.superclass.constructor.call(this);\r
3228 };\r
3229 \r
3230 Ext.extend(Ext.SplitBar, Ext.util.Observable, {\r
3231     onStartProxyDrag : function(x, y){\r
3232         this.fireEvent("beforeresize", this);\r
3233         this.overlay =  Ext.DomHelper.append(document.body,  {cls: "x-drag-overlay", html: "&#160;"}, true);\r
3234         this.overlay.unselectable();\r
3235         this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));\r
3236         this.overlay.show();\r
3237         Ext.get(this.proxy).setDisplayed("block");\r
3238         var size = this.adapter.getElementSize(this);\r
3239         this.activeMinSize = this.getMinimumSize();\r
3240         this.activeMaxSize = this.getMaximumSize();\r
3241         var c1 = size - this.activeMinSize;\r
3242         var c2 = Math.max(this.activeMaxSize - size, 0);\r
3243         if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
3244             this.dd.resetConstraints();\r
3245             this.dd.setXConstraint(\r
3246                 this.placement == Ext.SplitBar.LEFT ? c1 : c2, \r
3247                 this.placement == Ext.SplitBar.LEFT ? c2 : c1,\r
3248                 this.tickSize\r
3249             );\r
3250             this.dd.setYConstraint(0, 0);\r
3251         }else{\r
3252             this.dd.resetConstraints();\r
3253             this.dd.setXConstraint(0, 0);\r
3254             this.dd.setYConstraint(\r
3255                 this.placement == Ext.SplitBar.TOP ? c1 : c2, \r
3256                 this.placement == Ext.SplitBar.TOP ? c2 : c1,\r
3257                 this.tickSize\r
3258             );\r
3259          }\r
3260         this.dragSpecs.startSize = size;\r
3261         this.dragSpecs.startPoint = [x, y];\r
3262         Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);\r
3263     },\r
3264     \r
3265     /** \r
3266      * @private Called after the drag operation by the DDProxy\r
3267      */\r
3268     onEndProxyDrag : function(e){\r
3269         Ext.get(this.proxy).setDisplayed(false);\r
3270         var endPoint = Ext.lib.Event.getXY(e);\r
3271         if(this.overlay){\r
3272             Ext.destroy(this.overlay);\r
3273             delete this.overlay;\r
3274         }\r
3275         var newSize;\r
3276         if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
3277             newSize = this.dragSpecs.startSize + \r
3278                 (this.placement == Ext.SplitBar.LEFT ?\r
3279                     endPoint[0] - this.dragSpecs.startPoint[0] :\r
3280                     this.dragSpecs.startPoint[0] - endPoint[0]\r
3281                 );\r
3282         }else{\r
3283             newSize = this.dragSpecs.startSize + \r
3284                 (this.placement == Ext.SplitBar.TOP ?\r
3285                     endPoint[1] - this.dragSpecs.startPoint[1] :\r
3286                     this.dragSpecs.startPoint[1] - endPoint[1]\r
3287                 );\r
3288         }\r
3289         newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);\r
3290         if(newSize != this.dragSpecs.startSize){\r
3291             if(this.fireEvent('beforeapply', this, newSize) !== false){\r
3292                 this.adapter.setElementSize(this, newSize);\r
3293                 this.fireEvent("moved", this, newSize);\r
3294                 this.fireEvent("resize", this, newSize);\r
3295             }\r
3296         }\r
3297     },\r
3298     \r
3299     /**\r
3300      * Get the adapter this SplitBar uses\r
3301      * @return The adapter object\r
3302      */\r
3303     getAdapter : function(){\r
3304         return this.adapter;\r
3305     },\r
3306     \r
3307     /**\r
3308      * Set the adapter this SplitBar uses\r
3309      * @param {Object} adapter A SplitBar adapter object\r
3310      */\r
3311     setAdapter : function(adapter){\r
3312         this.adapter = adapter;\r
3313         this.adapter.init(this);\r
3314     },\r
3315     \r
3316     /**\r
3317      * Gets the minimum size for the resizing element\r
3318      * @return {Number} The minimum size\r
3319      */\r
3320     getMinimumSize : function(){\r
3321         return this.minSize;\r
3322     },\r
3323     \r
3324     /**\r
3325      * Sets the minimum size for the resizing element\r
3326      * @param {Number} minSize The minimum size\r
3327      */\r
3328     setMinimumSize : function(minSize){\r
3329         this.minSize = minSize;\r
3330     },\r
3331     \r
3332     /**\r
3333      * Gets the maximum size for the resizing element\r
3334      * @return {Number} The maximum size\r
3335      */\r
3336     getMaximumSize : function(){\r
3337         return this.maxSize;\r
3338     },\r
3339     \r
3340     /**\r
3341      * Sets the maximum size for the resizing element\r
3342      * @param {Number} maxSize The maximum size\r
3343      */\r
3344     setMaximumSize : function(maxSize){\r
3345         this.maxSize = maxSize;\r
3346     },\r
3347     \r
3348     /**\r
3349      * Sets the initialize size for the resizing element\r
3350      * @param {Number} size The initial size\r
3351      */\r
3352     setCurrentSize : function(size){\r
3353         var oldAnimate = this.animate;\r
3354         this.animate = false;\r
3355         this.adapter.setElementSize(this, size);\r
3356         this.animate = oldAnimate;\r
3357     },\r
3358     \r
3359     /**\r
3360      * Destroy this splitbar. \r
3361      * @param {Boolean} removeEl True to remove the element\r
3362      */\r
3363     destroy : function(removeEl){\r
3364                 Ext.destroy(this.shim, Ext.get(this.proxy));\r
3365         this.dd.unreg();\r
3366         if(removeEl){\r
3367             this.el.remove();\r
3368         }\r
3369                 this.purgeListeners();\r
3370     }\r
3371 });\r
3372 \r
3373 /**\r
3374  * @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
3375  */\r
3376 Ext.SplitBar.createProxy = function(dir){\r
3377     var proxy = new Ext.Element(document.createElement("div"));\r
3378     proxy.unselectable();\r
3379     var cls = 'x-splitbar-proxy';\r
3380     proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));\r
3381     document.body.appendChild(proxy.dom);\r
3382     return proxy.dom;\r
3383 };\r
3384 \r
3385 /** \r
3386  * @class Ext.SplitBar.BasicLayoutAdapter\r
3387  * Default Adapter. It assumes the splitter and resizing element are not positioned\r
3388  * elements and only gets/sets the width of the element. Generally used for table based layouts.\r
3389  */\r
3390 Ext.SplitBar.BasicLayoutAdapter = function(){\r
3391 };\r
3392 \r
3393 Ext.SplitBar.BasicLayoutAdapter.prototype = {\r
3394     // do nothing for now\r
3395     init : function(s){\r
3396     \r
3397     },\r
3398     /**\r
3399      * Called before drag operations to get the current size of the resizing element. \r
3400      * @param {Ext.SplitBar} s The SplitBar using this adapter\r
3401      */\r
3402      getElementSize : function(s){\r
3403         if(s.orientation == Ext.SplitBar.HORIZONTAL){\r
3404             return s.resizingEl.getWidth();\r
3405         }else{\r
3406             return s.resizingEl.getHeight();\r
3407         }\r
3408     },\r
3409     \r
3410     /**\r
3411      * Called after drag operations to set the size of the resizing element.\r
3412      * @param {Ext.SplitBar} s The SplitBar using this adapter\r
3413      * @param {Number} newSize The new size to set\r
3414      * @param {Function} onComplete A function to be invoked when resizing is complete\r
3415      */\r
3416     setElementSize : function(s, newSize, onComplete){\r
3417         if(s.orientation == Ext.SplitBar.HORIZONTAL){\r
3418             if(!s.animate){\r
3419                 s.resizingEl.setWidth(newSize);\r
3420                 if(onComplete){\r
3421                     onComplete(s, newSize);\r
3422                 }\r
3423             }else{\r
3424                 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');\r
3425             }\r
3426         }else{\r
3427             \r
3428             if(!s.animate){\r
3429                 s.resizingEl.setHeight(newSize);\r
3430                 if(onComplete){\r
3431                     onComplete(s, newSize);\r
3432                 }\r
3433             }else{\r
3434                 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');\r
3435             }\r
3436         }\r
3437     }\r
3438 };\r
3439 \r
3440 /** \r
3441  *@class Ext.SplitBar.AbsoluteLayoutAdapter\r
3442  * @extends Ext.SplitBar.BasicLayoutAdapter\r
3443  * Adapter that  moves the splitter element to align with the resized sizing element. \r
3444  * Used with an absolute positioned SplitBar.\r
3445  * @param {Mixed} container The container that wraps around the absolute positioned content. If it's\r
3446  * document.body, make sure you assign an id to the body element.\r
3447  */\r
3448 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){\r
3449     this.basic = new Ext.SplitBar.BasicLayoutAdapter();\r
3450     this.container = Ext.get(container);\r
3451 };\r
3452 \r
3453 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {\r
3454     init : function(s){\r
3455         this.basic.init(s);\r
3456     },\r
3457     \r
3458     getElementSize : function(s){\r
3459         return this.basic.getElementSize(s);\r
3460     },\r
3461     \r
3462     setElementSize : function(s, newSize, onComplete){\r
3463         this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));\r
3464     },\r
3465     \r
3466     moveSplitter : function(s){\r
3467         var yes = Ext.SplitBar;\r
3468         switch(s.placement){\r
3469             case yes.LEFT:\r
3470                 s.el.setX(s.resizingEl.getRight());\r
3471                 break;\r
3472             case yes.RIGHT:\r
3473                 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");\r
3474                 break;\r
3475             case yes.TOP:\r
3476                 s.el.setY(s.resizingEl.getBottom());\r
3477                 break;\r
3478             case yes.BOTTOM:\r
3479                 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());\r
3480                 break;\r
3481         }\r
3482     }\r
3483 };\r
3484 \r
3485 /**\r
3486  * Orientation constant - Create a vertical SplitBar\r
3487  * @static\r
3488  * @type Number\r
3489  */\r
3490 Ext.SplitBar.VERTICAL = 1;\r
3491 \r
3492 /**\r
3493  * Orientation constant - Create a horizontal SplitBar\r
3494  * @static\r
3495  * @type Number\r
3496  */\r
3497 Ext.SplitBar.HORIZONTAL = 2;\r
3498 \r
3499 /**\r
3500  * Placement constant - The resizing element is to the left of the splitter element\r
3501  * @static\r
3502  * @type Number\r
3503  */\r
3504 Ext.SplitBar.LEFT = 1;\r
3505 \r
3506 /**\r
3507  * Placement constant - The resizing element is to the right of the splitter element\r
3508  * @static\r
3509  * @type Number\r
3510  */\r
3511 Ext.SplitBar.RIGHT = 2;\r
3512 \r
3513 /**\r
3514  * Placement constant - The resizing element is positioned above the splitter element\r
3515  * @static\r
3516  * @type Number\r
3517  */\r
3518 Ext.SplitBar.TOP = 3;\r
3519 \r
3520 /**\r
3521  * Placement constant - The resizing element is positioned under splitter element\r
3522  * @static\r
3523  * @type Number\r
3524  */\r
3525 Ext.SplitBar.BOTTOM = 4;\r
3526 /**
3527  * @class Ext.Container
3528  * @extends Ext.BoxComponent
3529  * <p>Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the
3530  * basic behavior of containing items, namely adding, inserting and removing items.</p>
3531  *
3532  * <p>The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}.
3533  * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight
3534  * Container to be encapsulated by an HTML element to your specifications by using the
3535  * <tt><b>{@link Ext.Component#autoEl autoEl}</b></tt> config option. This is a useful technique when creating
3536  * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels}
3537  * for example.</p>
3538  *
3539  * <p>The code below illustrates both how to explicitly create a Container, and how to implicitly
3540  * create one using the <b><tt>'container'</tt></b> xtype:<pre><code>
3541 // explicitly create a Container
3542 var embeddedColumns = new Ext.Container({
3543     autoEl: 'div',  // This is the default
3544     layout: 'column',
3545     defaults: {
3546         // implicitly create Container by specifying xtype
3547         xtype: 'container',
3548         autoEl: 'div', // This is the default.
3549         layout: 'form',
3550         columnWidth: 0.5,
3551         style: {
3552             padding: '10px'
3553         }
3554     },
3555 //  The two items below will be Ext.Containers, each encapsulated by a &lt;DIV> element.
3556     items: [{
3557         items: {
3558             xtype: 'datefield',
3559             name: 'startDate',
3560             fieldLabel: 'Start date'
3561         }
3562     }, {
3563         items: {
3564             xtype: 'datefield',
3565             name: 'endDate',
3566             fieldLabel: 'End date'
3567         }
3568     }]
3569 });</code></pre></p>
3570  *
3571  * <p><u><b>Layout</b></u></p>
3572  * <p>Container classes delegate the rendering of child Components to a layout
3573  * manager class which must be configured into the Container using the
3574  * <code><b>{@link #layout}</b></code> configuration property.</p>
3575  * <p>When either specifying child <code>{@link #items}</code> of a Container,
3576  * or dynamically {@link #add adding} Components to a Container, remember to
3577  * consider how you wish the Container to arrange those child elements, and
3578  * whether those child elements need to be sized using one of Ext's built-in
3579  * <b><code>{@link #layout}</code></b> schemes. By default, Containers use the
3580  * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only
3581  * renders child components, appending them one after the other inside the
3582  * Container, and <b>does not apply any sizing</b> at all.</p>
3583  * <p>A common mistake is when a developer neglects to specify a
3584  * <b><code>{@link #layout}</code></b> (e.g. widgets like GridPanels or
3585  * TreePanels are added to Containers for which no <tt><b>{@link #layout}</b></tt>
3586  * has been specified). If a Container is left to use the default
3587  * {@link Ext.layout.ContainerLayout ContainerLayout} scheme, none of its
3588  * child components will be resized, or changed in any way when the Container
3589  * is resized.</p>
3590  * <p>Certain layout managers allow dynamic addition of child components.
3591  * Those that do include {@link Ext.layout.CardLayout},
3592  * {@link Ext.layout.AnchorLayout}, {@link Ext.layout.FormLayout}, and
3593  * {@link Ext.layout.TableLayout}. For example:<pre><code>
3594 //  Create the GridPanel.
3595 var myNewGrid = new Ext.grid.GridPanel({
3596     store: myStore,
3597     columns: myColumnModel,
3598     title: 'Results', // the title becomes the title of the tab
3599 });
3600
3601 myTabPanel.add(myNewGrid); // {@link Ext.TabPanel} implicitly uses {@link Ext.layout.CardLayout CardLayout}
3602 myTabPanel.{@link Ext.TabPanel#setActiveTab setActiveTab}(myNewGrid);
3603  * </code></pre></p>
3604  * <p>The example above adds a newly created GridPanel to a TabPanel. Note that
3605  * a TabPanel uses {@link Ext.layout.CardLayout} as its layout manager which
3606  * means all its child items are sized to {@link Ext.layout.FitLayout fit}
3607  * exactly into its client area.
3608  * <p><b><u>Overnesting is a common problem</u></b>.
3609  * An example of overnesting occurs when a GridPanel is added to a TabPanel
3610  * by wrapping the GridPanel <i>inside</i> a wrapping Panel (that has no
3611  * <tt><b>{@link #layout}</b></tt> specified) and then add that wrapping Panel
3612  * to the TabPanel. The point to realize is that a GridPanel <b>is</b> a
3613  * Component which can be added directly to a Container. If the wrapping Panel
3614  * has no <tt><b>{@link #layout}</b></tt> configuration, then the overnested
3615  * GridPanel will not be sized as expected.<p>
3616 </code></pre>
3617  *
3618  * <p><u><b>Adding via remote configuration</b></u></p>
3619  *
3620  * <p>A server side script can be used to add Components which are generated dynamically on the server.
3621  * An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server
3622  * based on certain parameters:
3623  * </p><pre><code>
3624 // execute an Ajax request to invoke server side script:
3625 Ext.Ajax.request({
3626     url: 'gen-invoice-grid.php',
3627     // send additional parameters to instruct server script
3628     params: {
3629         startDate: Ext.getCmp('start-date').getValue(),
3630         endDate: Ext.getCmp('end-date').getValue()
3631     },
3632     // process the response object to add it to the TabPanel:
3633     success: function(xhr) {
3634         var newComponent = eval(xhr.responseText); // see discussion below
3635         myTabPanel.add(newComponent); // add the component to the TabPanel
3636         myTabPanel.setActiveTab(newComponent);
3637     },
3638     failure: function() {
3639         Ext.Msg.alert("Grid create failed", "Server communication failure");
3640     }
3641 });
3642 </code></pre>
3643  * <p>The server script needs to return an executable Javascript statement which, when processed
3644  * using <tt>eval()</tt>, will return either a config object with an {@link Ext.Component#xtype xtype},
3645  * or an instantiated Component. The server might return this for example:</p><pre><code>
3646 (function() {
3647     function formatDate(value){
3648         return value ? value.dateFormat('M d, Y') : '';
3649     };
3650
3651     var store = new Ext.data.Store({
3652         url: 'get-invoice-data.php',
3653         baseParams: {
3654             startDate: '01/01/2008',
3655             endDate: '01/31/2008'
3656         },
3657         reader: new Ext.data.JsonReader({
3658             record: 'transaction',
3659             idProperty: 'id',
3660             totalRecords: 'total'
3661         }, [
3662            'customer',
3663            'invNo',
3664            {name: 'date', type: 'date', dateFormat: 'm/d/Y'},
3665            {name: 'value', type: 'float'}
3666         ])
3667     });
3668
3669     var grid = new Ext.grid.GridPanel({
3670         title: 'Invoice Report',
3671         bbar: new Ext.PagingToolbar(store),
3672         store: store,
3673         columns: [
3674             {header: "Customer", width: 250, dataIndex: 'customer', sortable: true},
3675             {header: "Invoice Number", width: 120, dataIndex: 'invNo', sortable: true},
3676             {header: "Invoice Date", width: 100, dataIndex: 'date', renderer: formatDate, sortable: true},
3677             {header: "Value", width: 120, dataIndex: 'value', renderer: 'usMoney', sortable: true}
3678         ],
3679     });
3680     store.load();
3681     return grid;  // return instantiated component
3682 })();
3683 </code></pre>
3684  * <p>When the above code fragment is passed through the <tt>eval</tt> function in the success handler
3685  * of the Ajax request, the code is executed by the Javascript processor, and the anonymous function
3686  * runs, and returns the instantiated grid component.</p>
3687  * <p>Note: since the code above is <i>generated</i> by a server script, the <tt>baseParams</tt> for
3688  * the Store, the metadata to allow generation of the Record layout, and the ColumnModel
3689  * can all be generated into the code since these are all known on the server.</p>
3690  *
3691  * @xtype container
3692  */
3693 Ext.Container = Ext.extend(Ext.BoxComponent, {
3694     /**
3695      * @cfg {Boolean} monitorResize
3696      * True to automatically monitor window resize events to handle anything that is sensitive to the current size
3697      * of the viewport.  This value is typically managed by the chosen <code>{@link #layout}</code> and should not need
3698      * to be set manually.
3699      */
3700     /**
3701      * @cfg {String/Object} layout
3702      * When creating complex UIs, it is important to remember that sizing and
3703      * positioning of child items is the responsibility of the Container's
3704      * layout manager. If you expect child items to be sized in response to
3705      * user interactions, <b>you must specify a layout manager</b> which
3706      * creates and manages the type of layout you have in mind.  For example:<pre><code>
3707 new Ext.Window({
3708     width:300, height: 300,
3709     layout: 'fit', // explicitly set layout manager: override the default (layout:'auto')
3710     items: [{
3711         title: 'Panel inside a Window'
3712     }]
3713 }).show();
3714      * </code></pre>
3715      * <p>Omitting the {@link #layout} config means that the
3716      * {@link Ext.layout.ContainerLayout default layout manager} will be used which does
3717      * nothing but render child components sequentially into the Container (no sizing or
3718      * positioning will be performed in this situation).</p>
3719      * <p>The layout manager class for this container may be specified as either as an
3720      * Object or as a String:</p>
3721      * <div><ul class="mdetail-params">
3722      *
3723      * <li><u>Specify as an Object</u></li>
3724      * <div><ul class="mdetail-params">
3725      * <li>Example usage:</li>
3726 <pre><code>
3727 layout: {
3728     type: 'vbox',
3729     padding: '5',
3730     align: 'left'
3731 }
3732 </code></pre>
3733      *
3734      * <li><tt><b>type</b></tt></li>
3735      * <br/><p>The layout type to be used for this container.  If not specified,
3736      * a default {@link Ext.layout.ContainerLayout} will be created and used.</p>
3737      * <br/><p>Valid layout <tt>type</tt> values are:</p>
3738      * <div class="sub-desc"><ul class="mdetail-params">
3739      * <li><tt><b>{@link Ext.layout.AbsoluteLayout absolute}</b></tt></li>
3740      * <li><tt><b>{@link Ext.layout.AccordionLayout accordion}</b></tt></li>
3741      * <li><tt><b>{@link Ext.layout.AnchorLayout anchor}</b></tt></li>
3742      * <li><tt><b>{@link Ext.layout.ContainerLayout auto}</b></tt> &nbsp;&nbsp;&nbsp; <b>Default</b></li>
3743      * <li><tt><b>{@link Ext.layout.BorderLayout border}</b></tt></li>
3744      * <li><tt><b>{@link Ext.layout.CardLayout card}</b></tt></li>
3745      * <li><tt><b>{@link Ext.layout.ColumnLayout column}</b></tt></li>
3746      * <li><tt><b>{@link Ext.layout.FitLayout fit}</b></tt></li>
3747      * <li><tt><b>{@link Ext.layout.FormLayout form}</b></tt></li>
3748      * <li><tt><b>{@link Ext.layout.HBoxLayout hbox}</b></tt></li>
3749      * <li><tt><b>{@link Ext.layout.MenuLayout menu}</b></tt></li>
3750      * <li><tt><b>{@link Ext.layout.TableLayout table}</b></tt></li>
3751      * <li><tt><b>{@link Ext.layout.ToolbarLayout toolbar}</b></tt></li>
3752      * <li><tt><b>{@link Ext.layout.VBoxLayout vbox}</b></tt></li>
3753      * </ul></div>
3754      *
3755      * <li>Layout specific configuration properties</li>
3756      * <br/><p>Additional layout specific configuration properties may also be
3757      * specified. For complete details regarding the valid config options for
3758      * each layout type, see the layout class corresponding to the <tt>type</tt>
3759      * specified.</p>
3760      *
3761      * </ul></div>
3762      *
3763      * <li><u>Specify as a String</u></li>
3764      * <div><ul class="mdetail-params">
3765      * <li>Example usage:</li>
3766 <pre><code>
3767 layout: 'vbox',
3768 layoutConfig: {
3769     padding: '5',
3770     align: 'left'
3771 }
3772 </code></pre>
3773      * <li><tt><b>layout</b></tt></li>
3774      * <br/><p>The layout <tt>type</tt> to be used for this container (see list
3775      * of valid layout type values above).</p><br/>
3776      * <li><tt><b>{@link #layoutConfig}</b></tt></li>
3777      * <br/><p>Additional layout specific configuration properties. For complete
3778      * details regarding the valid config options for each layout type, see the
3779      * layout class corresponding to the <tt>layout</tt> specified.</p>
3780      * </ul></div></ul></div>
3781      */
3782     /**
3783      * @cfg {Object} layoutConfig
3784      * This is a config object containing properties specific to the chosen
3785      * <b><code>{@link #layout}</code></b> if <b><code>{@link #layout}</code></b>
3786      * has been specified as a <i>string</i>.</p>
3787      */
3788     /**
3789      * @cfg {Boolean/Number} bufferResize
3790      * When set to true (100 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer
3791      * the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers
3792      * with a large quantity of sub-components for which frequent layout calls would be expensive.
3793      */
3794     bufferResize: 100,
3795     
3796     /**
3797      * @cfg {String/Number} activeItem
3798      * A string component id or the numeric index of the component that should be initially activated within the
3799      * container's layout on render.  For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first
3800      * item in the container's collection).  activeItem only applies to layout styles that can display
3801      * items one at a time (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout} and
3802      * {@link Ext.layout.FitLayout}).  Related to {@link Ext.layout.ContainerLayout#activeItem}.
3803      */
3804     /**
3805      * @cfg {Object/Array} items
3806      * <pre><b>** IMPORTANT</b>: be sure to specify a <b><code>{@link #layout}</code> ! **</b></pre>
3807      * <p>A single item, or an array of child Components to be added to this container,
3808      * for example:</p>
3809      * <pre><code>
3810 // specifying a single item
3811 items: {...},
3812 layout: 'fit',    // specify a layout!
3813
3814 // specifying multiple items
3815 items: [{...}, {...}],
3816 layout: 'anchor', // specify a layout!
3817      * </code></pre>
3818      * <p>Each item may be:</p>
3819      * <div><ul class="mdetail-params">
3820      * <li>any type of object based on {@link Ext.Component}</li>
3821      * <li>a fully instanciated object or</li>
3822      * <li>an object literal that:</li>
3823      * <div><ul class="mdetail-params">
3824      * <li>has a specified <code>{@link Ext.Component#xtype xtype}</code></li>
3825      * <li>the {@link Ext.Component#xtype} specified is associated with the Component
3826      * desired and should be chosen from one of the available xtypes as listed
3827      * in {@link Ext.Component}.</li>
3828      * <li>If an <code>{@link Ext.Component#xtype xtype}</code> is not explicitly
3829      * specified, the {@link #defaultType} for that Container is used.</li>
3830      * <li>will be "lazily instanciated", avoiding the overhead of constructing a fully
3831      * instanciated Component object</li>
3832      * </ul></div></ul></div>
3833      * <p><b>Notes</b>:</p>
3834      * <div><ul class="mdetail-params">
3835      * <li>Ext uses lazy rendering. Child Components will only be rendered
3836      * should it become necessary. Items are automatically laid out when they are first
3837      * shown (no sizing is done while hidden), or in response to a {@link #doLayout} call.</li>
3838      * <li>Do not specify <code>{@link Ext.Panel#contentEl contentEl}</code>/
3839      * <code>{@link Ext.Panel#html html}</code> with <code>items</code>.</li>
3840      * </ul></div>
3841      */
3842     /**
3843      * @cfg {Object} defaults
3844      * <p>A config object that will be applied to all components added to this container either via the {@link #items}
3845      * config or via the {@link #add} or {@link #insert} methods.  The <tt>defaults</tt> config can contain any
3846      * number of name/value property pairs to be added to each item, and should be valid for the types of items
3847      * being added to the container.  For example, to automatically apply padding to the body of each of a set of
3848      * contained {@link Ext.Panel} items, you could pass: <tt>defaults: {bodyStyle:'padding:15px'}</tt>.</p><br/>
3849      * <p><b>Note</b>: <tt>defaults</tt> will not be applied to config objects if the option is already specified.
3850      * For example:</p><pre><code>
3851 defaults: {               // defaults are applied to items, not the container
3852     autoScroll:true
3853 },
3854 items: [
3855     {
3856         xtype: 'panel',   // defaults <b>do not</b> have precedence over
3857         id: 'panel1',     // options in config objects, so the defaults
3858         autoScroll: false // will not be applied here, panel1 will be autoScroll:false
3859     },
3860     new Ext.Panel({       // defaults <b>do</b> have precedence over options
3861         id: 'panel2',     // options in components, so the defaults
3862         autoScroll: false // will be applied here, panel2 will be autoScroll:true.
3863     })
3864 ]
3865      * </code></pre>
3866      */
3867
3868
3869     /** @cfg {Boolean} autoDestroy
3870      * If true the container will automatically destroy any contained component that is removed from it, else
3871      * destruction must be handled manually (defaults to true).
3872      */
3873     autoDestroy : true,
3874
3875     /** @cfg {Boolean} forceLayout
3876      * If true the container will force a layout initially even if hidden or collapsed. This option
3877      * is useful for forcing forms to render in collapsed or hidden containers. (defaults to false).
3878      */
3879     forceLayout: false,
3880
3881     /** @cfg {Boolean} hideBorders
3882      * True to hide the borders of each contained component, false to defer to the component's existing
3883      * border settings (defaults to false).
3884      */
3885     /** @cfg {String} defaultType
3886      * <p>The default {@link Ext.Component xtype} of child Components to create in this Container when
3887      * a child item is specified as a raw configuration object, rather than as an instantiated Component.</p>
3888      * <p>Defaults to <tt>'panel'</tt>, except {@link Ext.menu.Menu} which defaults to <tt>'menuitem'</tt>,
3889      * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to <tt>'button'</tt>.</p>
3890      */
3891     defaultType : 'panel',
3892
3893     // private
3894     initComponent : function(){
3895         Ext.Container.superclass.initComponent.call(this);
3896
3897         this.addEvents(
3898             /**
3899              * @event afterlayout
3900              * Fires when the components in this container are arranged by the associated layout manager.
3901              * @param {Ext.Container} this
3902              * @param {ContainerLayout} layout The ContainerLayout implementation for this container
3903              */
3904             'afterlayout',
3905             /**
3906              * @event beforeadd
3907              * Fires before any {@link Ext.Component} is added or inserted into the container.
3908              * A handler can return false to cancel the add.
3909              * @param {Ext.Container} this
3910              * @param {Ext.Component} component The component being added
3911              * @param {Number} index The index at which the component will be added to the container's items collection
3912              */
3913             'beforeadd',
3914             /**
3915              * @event beforeremove
3916              * Fires before any {@link Ext.Component} is removed from the container.  A handler can return
3917              * false to cancel the remove.
3918              * @param {Ext.Container} this
3919              * @param {Ext.Component} component The component being removed
3920              */
3921             'beforeremove',
3922             /**
3923              * @event add
3924              * @bubbles
3925              * Fires after any {@link Ext.Component} is added or inserted into the container.
3926              * @param {Ext.Container} this
3927              * @param {Ext.Component} component The component that was added
3928              * @param {Number} index The index at which the component was added to the container's items collection
3929              */
3930             'add',
3931             /**
3932              * @event remove
3933              * @bubbles
3934              * Fires after any {@link Ext.Component} is removed from the container.
3935              * @param {Ext.Container} this
3936              * @param {Ext.Component} component The component that was removed
3937              */
3938             'remove'
3939         );
3940
3941                 this.enableBubble('add', 'remove');
3942
3943         /**
3944          * The collection of components in this container as a {@link Ext.util.MixedCollection}
3945          * @type MixedCollection
3946          * @property items
3947          */
3948         var items = this.items;
3949         if(items){
3950             delete this.items;
3951             if(Ext.isArray(items) && items.length > 0){
3952                 this.add.apply(this, items);
3953             }else{
3954                 this.add(items);
3955             }
3956         }
3957     },
3958
3959     // private
3960     initItems : function(){
3961         if(!this.items){
3962             this.items = new Ext.util.MixedCollection(false, this.getComponentId);
3963             this.getLayout(); // initialize the layout
3964         }
3965     },
3966
3967     // private
3968     setLayout : function(layout){
3969         if(this.layout && this.layout != layout){
3970             this.layout.setContainer(null);
3971         }
3972         this.initItems();
3973         this.layout = layout;
3974         layout.setContainer(this);
3975     },
3976
3977     // private
3978     render : function(){
3979         Ext.Container.superclass.render.apply(this, arguments);
3980         if(this.layout){
3981             if(Ext.isObject(this.layout) && !this.layout.layout){
3982                 this.layoutConfig = this.layout;
3983                 this.layout = this.layoutConfig.type;
3984             }
3985             if(typeof this.layout == 'string'){
3986                 this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
3987             }
3988             this.setLayout(this.layout);
3989
3990             if(this.activeItem !== undefined){
3991                 var item = this.activeItem;
3992                 delete this.activeItem;
3993                 this.layout.setActiveItem(item);
3994             }
3995         }
3996         if(!this.ownerCt){
3997             // force a layout if no ownerCt is set
3998             this.doLayout(false, true);
3999         }
4000         if(this.monitorResize === true){
4001             Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
4002         }
4003     },
4004
4005     /**
4006      * <p>Returns the Element to be used to contain the child Components of this Container.</p>
4007      * <p>An implementation is provided which returns the Container's {@link #getEl Element}, but
4008      * if there is a more complex structure to a Container, this may be overridden to return
4009      * the element into which the {@link #layout layout} renders child Components.</p>
4010      * @return {Ext.Element} The Element to render child Components into.
4011      */
4012     getLayoutTarget : function(){
4013         return this.el;
4014     },
4015
4016     // private - used as the key lookup function for the items collection
4017     getComponentId : function(comp){
4018         return comp.getItemId();
4019     },
4020
4021     /**
4022      * <p>Adds {@link Ext.Component Component}(s) to this Container.</p>
4023      * <br><p><b>Description</b></u> :
4024      * <div><ul class="mdetail-params">
4025      * <li>Fires the {@link #beforeadd} event before adding</li>
4026      * <li>The Container's {@link #defaults default config values} will be applied
4027      * accordingly (see <code>{@link #defaults}</code> for details).</li>
4028      * <li>Fires the {@link #add} event after the component has been added.</li>
4029      * </ul></div>
4030      * <br><p><b>Notes</b></u> :
4031      * <div><ul class="mdetail-params">
4032      * <li>If the Container is <i>already rendered</i> when <tt>add</tt>
4033      * is called, you may need to call {@link #doLayout} to refresh the view which causes
4034      * any unrendered child Components to be rendered. This is required so that you can
4035      * <tt>add</tt> multiple child components if needed while only refreshing the layout
4036      * once. For example:<pre><code>
4037 var tb = new {@link Ext.Toolbar}();
4038 tb.render(document.body);  // toolbar is rendered
4039 tb.add({text:'Button 1'}); // add multiple items ({@link #defaultType} for {@link Ext.Toolbar Toolbar} is 'button')
4040 tb.add({text:'Button 2'});
4041 tb.{@link #doLayout}();             // refresh the layout
4042      * </code></pre></li>
4043      * <li><i>Warning:</i> Containers directly managed by the BorderLayout layout manager
4044      * may not be removed or added.  See the Notes for {@link Ext.layout.BorderLayout BorderLayout}
4045      * for more details.</li>
4046      * </ul></div>
4047      * @param {Object/Array} component
4048      * <p>Either a single component or an Array of components to add.  See
4049      * <code>{@link #items}</code> for additional information.</p>
4050      * @param {Object} (Optional) component_2
4051      * @param {Object} (Optional) component_n
4052      * @return {Ext.Component} component The Component (or config object) that was added.
4053      */
4054     add : function(comp){
4055         this.initItems();
4056         var args = arguments.length > 1;
4057         if(args || Ext.isArray(comp)){
4058             Ext.each(args ? arguments : comp, function(c){
4059                 this.add(c);
4060             }, this);
4061             return;
4062         }
4063         var c = this.lookupComponent(this.applyDefaults(comp));
4064         var pos = this.items.length;
4065         if(this.fireEvent('beforeadd', this, c, pos) !== false && this.onBeforeAdd(c) !== false){
4066             this.items.add(c);
4067             c.ownerCt = this;
4068             this.fireEvent('add', this, c, pos);
4069         }
4070         return c;
4071     },
4072
4073     /**
4074      * Inserts a Component into this Container at a specified index. Fires the
4075      * {@link #beforeadd} event before inserting, then fires the {@link #add} event after the
4076      * Component has been inserted.
4077      * @param {Number} index The index at which the Component will be inserted
4078      * into the Container's items collection
4079      * @param {Ext.Component} component The child Component to insert.<br><br>
4080      * Ext uses lazy rendering, and will only render the inserted Component should
4081      * it become necessary.<br><br>
4082      * A Component config object may be passed in order to avoid the overhead of
4083      * constructing a real Component object if lazy rendering might mean that the
4084      * inserted Component will not be rendered immediately. To take advantage of
4085      * this 'lazy instantiation', set the {@link Ext.Component#xtype} config
4086      * property to the registered type of the Component wanted.<br><br>
4087      * For a list of all available xtypes, see {@link Ext.Component}.
4088      * @return {Ext.Component} component The Component (or config object) that was
4089      * inserted with the Container's default config values applied.
4090      */
4091     insert : function(index, comp){
4092         this.initItems();
4093         var a = arguments, len = a.length;
4094         if(len > 2){
4095             for(var i = len-1; i >= 1; --i) {
4096                 this.insert(index, a[i]);
4097             }
4098             return;
4099         }
4100         var c = this.lookupComponent(this.applyDefaults(comp));
4101
4102         if(c.ownerCt == this && this.items.indexOf(c) < index){
4103             --index;
4104         }
4105
4106         if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
4107             this.items.insert(index, c);
4108             c.ownerCt = this;
4109             this.fireEvent('add', this, c, index);
4110         }
4111         return c;
4112     },
4113
4114     // private
4115     applyDefaults : function(c){
4116         if(this.defaults){
4117             if(typeof c == 'string'){
4118                 c = Ext.ComponentMgr.get(c);
4119                 Ext.apply(c, this.defaults);
4120             }else if(!c.events){
4121                 Ext.applyIf(c, this.defaults);
4122             }else{
4123                 Ext.apply(c, this.defaults);
4124             }
4125         }
4126         return c;
4127     },
4128
4129     // private
4130     onBeforeAdd : function(item){
4131         if(item.ownerCt){
4132             item.ownerCt.remove(item, false);
4133         }
4134         if(this.hideBorders === true){
4135             item.border = (item.border === true);
4136         }
4137     },
4138
4139     /**
4140      * Removes a component from this container.  Fires the {@link #beforeremove} event before removing, then fires
4141      * the {@link #remove} event after the component has been removed.
4142      * @param {Component/String} component The component reference or id to remove.
4143      * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
4144      * Defaults to the value of this Container's {@link #autoDestroy} config.
4145      * @return {Ext.Component} component The Component that was removed.
4146      */
4147     remove : function(comp, autoDestroy){
4148         this.initItems();
4149         var c = this.getComponent(comp);
4150         if(c && this.fireEvent('beforeremove', this, c) !== false){
4151             this.items.remove(c);
4152             delete c.ownerCt;
4153             if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
4154                 c.destroy();
4155             }
4156             if(this.layout && this.layout.activeItem == c){
4157                 delete this.layout.activeItem;
4158             }
4159             this.fireEvent('remove', this, c);
4160         }
4161         return c;
4162     },
4163
4164     /**
4165      * Removes all components from this container.
4166      * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
4167      * Defaults to the value of this Container's {@link #autoDestroy} config.
4168      * @return {Array} Array of the destroyed components
4169      */
4170     removeAll: function(autoDestroy){
4171         this.initItems();
4172         var item, rem = [], items = [];
4173         this.items.each(function(i){
4174             rem.push(i);
4175         });
4176         for (var i = 0, len = rem.length; i < len; ++i){
4177             item = rem[i];
4178             this.remove(item, autoDestroy);
4179             if(item.ownerCt !== this){
4180                 items.push(item);
4181             }
4182         }
4183         return items;
4184     },
4185
4186     /**
4187      * Examines this container's <code>{@link #items}</code> <b>property</b>
4188      * and gets a direct child component of this container.
4189      * @param {String/Number} comp This parameter may be any of the following:
4190      * <div><ul class="mdetail-params">
4191      * <li>a <b><tt>String</tt></b> : representing the <code>{@link Ext.Component#itemId itemId}</code>
4192      * or <code>{@link Ext.Component#id id}</code> of the child component </li>
4193      * <li>a <b><tt>Number</tt></b> : representing the position of the child component
4194      * within the <code>{@link #items}</code> <b>property</b></li>
4195      * </ul></div>
4196      * <p>For additional information see {@link Ext.util.MixedCollection#get}.
4197      * @return Ext.Component The component (if found).
4198      */
4199     getComponent : function(comp){
4200         if(Ext.isObject(comp)){
4201             return comp;
4202         }
4203         return this.items.get(comp);
4204     },
4205
4206     // private
4207     lookupComponent : function(comp){
4208         if(typeof comp == 'string'){
4209             return Ext.ComponentMgr.get(comp);
4210         }else if(!comp.events){
4211             return this.createComponent(comp);
4212         }
4213         return comp;
4214     },
4215
4216     // private
4217     createComponent : function(config){
4218         return Ext.create(config, this.defaultType);
4219     },
4220
4221     /**
4222      * Force this container's layout to be recalculated. A call to this function is required after adding a new component
4223      * to an already rendered container, or possibly after changing sizing/position properties of child components.
4224      * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto
4225      * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer)
4226      * @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden.
4227      * @return {Ext.Container} this
4228      */
4229     doLayout: function(shallow, force){
4230         var rendered = this.rendered,
4231             forceLayout = this.forceLayout;
4232
4233         if(!this.isVisible() || this.collapsed){
4234             this.deferLayout = this.deferLayout || !shallow;
4235             if(!(force || forceLayout)){
4236                 return;
4237             }
4238             shallow = shallow && !this.deferLayout;
4239         } else {
4240             delete this.deferLayout;
4241         }
4242         if(rendered && this.layout){
4243             this.layout.layout();
4244         }
4245         if(shallow !== true && this.items){
4246             var cs = this.items.items;
4247             for(var i = 0, len = cs.length; i < len; i++){
4248                 var c = cs[i];
4249                 if(c.doLayout){
4250                     c.forceLayout = forceLayout;
4251                     c.doLayout();
4252                 }
4253             }
4254         }
4255         if(rendered){
4256             this.onLayout(shallow, force);
4257         }
4258         delete this.forceLayout;
4259     },
4260
4261     //private
4262     onLayout : Ext.emptyFn,
4263
4264     onShow : function(){
4265         Ext.Container.superclass.onShow.call(this);
4266         if(this.deferLayout !== undefined){
4267             this.doLayout(true);
4268         }
4269     },
4270
4271     /**
4272      * Returns the layout currently in use by the container.  If the container does not currently have a layout
4273      * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout.
4274      * @return {ContainerLayout} layout The container's layout
4275      */
4276     getLayout : function(){
4277         if(!this.layout){
4278             var layout = new Ext.layout.ContainerLayout(this.layoutConfig);
4279             this.setLayout(layout);
4280         }
4281         return this.layout;
4282     },
4283
4284     // private
4285     beforeDestroy : function(){
4286         if(this.items){
4287             Ext.destroy.apply(Ext, this.items.items);
4288         }
4289         if(this.monitorResize){
4290             Ext.EventManager.removeResizeListener(this.doLayout, this);
4291         }
4292         Ext.destroy(this.layout);
4293         Ext.Container.superclass.beforeDestroy.call(this);
4294     },
4295
4296     /**
4297      * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of
4298      * function call will be the scope provided or the current component. The arguments to the function
4299      * will be the args provided or the current component. If the function returns false at any point,
4300      * the bubble is stopped.
4301      * @param {Function} fn The function to call
4302      * @param {Object} scope (optional) The scope of the function (defaults to current node)
4303      * @param {Array} args (optional) The args to call the function with (default to passing the current component)
4304      * @return {Ext.Container} this
4305      */
4306     bubble : function(fn, scope, args){
4307         var p = this;
4308         while(p){
4309             if(fn.apply(scope || p, args || [p]) === false){
4310                 break;
4311             }
4312             p = p.ownerCt;
4313         }
4314         return this;
4315     },
4316
4317     /**
4318      * Cascades down the component/container heirarchy from this component (called first), calling the specified function with
4319      * each component. The scope (<i>this</i>) of
4320      * function call will be the scope provided or the current component. The arguments to the function
4321      * will be the args provided or the current component. If the function returns false at any point,
4322      * the cascade is stopped on that branch.
4323      * @param {Function} fn The function to call
4324      * @param {Object} scope (optional) The scope of the function (defaults to current component)
4325      * @param {Array} args (optional) The args to call the function with (defaults to passing the current component)
4326      * @return {Ext.Container} this
4327      */
4328     cascade : function(fn, scope, args){
4329         if(fn.apply(scope || this, args || [this]) !== false){
4330             if(this.items){
4331                 var cs = this.items.items;
4332                 for(var i = 0, len = cs.length; i < len; i++){
4333                     if(cs[i].cascade){
4334                         cs[i].cascade(fn, scope, args);
4335                     }else{
4336                         fn.apply(scope || cs[i], args || [cs[i]]);
4337                     }
4338                 }
4339             }
4340         }
4341         return this;
4342     },
4343
4344     /**
4345      * Find a component under this container at any level by id
4346      * @param {String} id
4347      * @return Ext.Component
4348      */
4349     findById : function(id){
4350         var m, ct = this;
4351         this.cascade(function(c){
4352             if(ct != c && c.id === id){
4353                 m = c;
4354                 return false;
4355             }
4356         });
4357         return m || null;
4358     },
4359
4360     /**
4361      * Find a component under this container at any level by xtype or class
4362      * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
4363      * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
4364      * the default), or true to check whether this Component is directly of the specified xtype.
4365      * @return {Array} Array of Ext.Components
4366      */
4367     findByType : function(xtype, shallow){
4368         return this.findBy(function(c){
4369             return c.isXType(xtype, shallow);
4370         });
4371     },
4372
4373     /**
4374      * Find a component under this container at any level by property
4375      * @param {String} prop
4376      * @param {String} value
4377      * @return {Array} Array of Ext.Components
4378      */
4379     find : function(prop, value){
4380         return this.findBy(function(c){
4381             return c[prop] === value;
4382         });
4383     },
4384
4385     /**
4386      * Find a component under this container at any level by a custom function. If the passed function returns
4387      * true, the component will be included in the results. The passed function is called with the arguments (component, this container).
4388      * @param {Function} fn The function to call
4389      * @param {Object} scope (optional)
4390      * @return {Array} Array of Ext.Components
4391      */
4392     findBy : function(fn, scope){
4393         var m = [], ct = this;
4394         this.cascade(function(c){
4395             if(ct != c && fn.call(scope || c, c, ct) === true){
4396                 m.push(c);
4397             }
4398         });
4399         return m;
4400     },
4401
4402     /**
4403      * Get a component contained by this container (alias for items.get(key))
4404      * @param {String/Number} key The index or id of the component
4405      * @return {Ext.Component} Ext.Component
4406      */
4407     get : function(key){
4408         return this.items.get(key);
4409     }
4410 });
4411
4412 Ext.Container.LAYOUTS = {};
4413 Ext.reg('container', Ext.Container);
4414 /**
4415  * @class Ext.layout.ContainerLayout
4416  * <p>The ContainerLayout class is the default layout manager delegated by {@link Ext.Container} to
4417  * render any child Components when no <tt>{@link Ext.Container#layout layout}</tt> is configured into
4418  * a {@link Ext.Container Container}. ContainerLayout provides the basic foundation for all other layout
4419  * classes in Ext. It simply renders all child Components into the Container, performing no sizing or
4420  * positioning services. To utilize a layout that provides sizing and positioning of child Components,
4421  * specify an appropriate <tt>{@link Ext.Container#layout layout}</tt>.</p>
4422  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
4423  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
4424  */
4425 Ext.layout.ContainerLayout = function(config){
4426     Ext.apply(this, config);
4427 };
4428
4429 Ext.layout.ContainerLayout.prototype = {
4430     /**
4431      * @cfg {String} extraCls
4432      * <p>An optional extra CSS class that will be added to the container. This can be useful for adding
4433      * customized styles to the container or any of its children using standard CSS rules. See
4434      * {@link Ext.Component}.{@link Ext.Component#ctCls ctCls} also.</p>
4435      * <p><b>Note</b>: <tt>extraCls</tt> defaults to <tt>''</tt> except for the following classes
4436      * which assign a value by default:
4437      * <div class="mdetail-params"><ul>
4438      * <li>{@link Ext.layout.AbsoluteLayout Absolute Layout} : <tt>'x-abs-layout-item'</tt></li>
4439      * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-item'</tt></li>
4440      * <li>{@link Ext.layout.ColumnLayout Column Layout} : <tt>'x-column'</tt></li>
4441      * </ul></div>
4442      * To configure the above Classes with an extra CSS class append to the default.  For example,
4443      * for ColumnLayout:<pre><code>
4444      * extraCls: 'x-column custom-class'
4445      * </code></pre>
4446      * </p>
4447      */
4448     /**
4449      * @cfg {Boolean} renderHidden
4450      * True to hide each contained item on render (defaults to false).
4451      */
4452
4453     /**
4454      * A reference to the {@link Ext.Component} that is active.  For example, <pre><code>
4455      * if(myPanel.layout.activeItem.id == 'item-1') { ... }
4456      * </code></pre>
4457      * <tt>activeItem</tt> only applies to layout styles that can display items one at a time
4458      * (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout}
4459      * and {@link Ext.layout.FitLayout}).  Read-only.  Related to {@link Ext.Container#activeItem}.
4460      * @type {Ext.Component}
4461      * @property activeItem
4462      */
4463
4464     // private
4465     monitorResize:false,
4466     // private
4467     activeItem : null,
4468
4469     // private
4470     layout : function(){
4471         var target = this.container.getLayoutTarget();
4472         this.onLayout(this.container, target);
4473         this.container.fireEvent('afterlayout', this.container, this);
4474     },
4475
4476     // private
4477     onLayout : function(ct, target){
4478         this.renderAll(ct, target);
4479     },
4480
4481     // private
4482     isValidParent : function(c, target){
4483                 return target && c.getDomPositionEl().dom.parentNode == (target.dom || target);
4484     },
4485
4486     // private
4487     renderAll : function(ct, target){
4488         var items = ct.items.items;
4489         for(var i = 0, len = items.length; i < len; i++) {
4490             var c = items[i];
4491             if(c && (!c.rendered || !this.isValidParent(c, target))){
4492                 this.renderItem(c, i, target);
4493             }
4494         }
4495     },
4496
4497     // private
4498     renderItem : function(c, position, target){
4499         if(c && !c.rendered){
4500             c.render(target, position);
4501             this.configureItem(c, position);
4502         }else if(c && !this.isValidParent(c, target)){
4503             if(typeof position == 'number'){
4504                 position = target.dom.childNodes[position];
4505             }
4506             target.dom.insertBefore(c.getDomPositionEl().dom, position || null);
4507             c.container = target;
4508             this.configureItem(c, position);
4509         }
4510     },
4511     
4512     // private
4513     configureItem: function(c, position){
4514         if(this.extraCls){
4515             var t = c.getPositionEl ? c.getPositionEl() : c;
4516             t.addClass(this.extraCls);
4517         }
4518         if (this.renderHidden && c != this.activeItem) {
4519             c.hide();
4520         }
4521         if(c.doLayout){
4522             c.doLayout(false, this.forceLayout);
4523         }
4524     },
4525
4526     // private
4527     onResize: function(){
4528         if(this.container.collapsed){
4529             return;
4530         }
4531         var b = this.container.bufferResize;
4532         if(b){
4533             if(!this.resizeTask){
4534                 this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
4535                 this.resizeBuffer = typeof b == 'number' ? b : 100;
4536             }
4537             this.resizeTask.delay(this.resizeBuffer);
4538         }else{
4539             this.runLayout();
4540         }
4541     },
4542     
4543     // private
4544     runLayout: function(){
4545         this.layout();
4546         this.container.onLayout();
4547     },
4548
4549     // private
4550     setContainer : function(ct){
4551         if(this.monitorResize && ct != this.container){
4552             if(this.container){
4553                 this.container.un('resize', this.onResize, this);
4554                 this.container.un('bodyresize', this.onResize, this);
4555             }
4556             if(ct){
4557                 ct.on({
4558                     scope: this,
4559                     resize: this.onResize,
4560                     bodyresize: this.onResize
4561                 });
4562             }
4563         }
4564         this.container = ct;
4565     },
4566
4567     // private
4568     parseMargins : function(v){
4569         if(typeof v == 'number'){
4570             v = v.toString();
4571         }
4572         var ms = v.split(' ');
4573         var len = ms.length;
4574         if(len == 1){
4575             ms[1] = ms[0];
4576             ms[2] = ms[0];
4577             ms[3] = ms[0];
4578         }
4579         if(len == 2){
4580             ms[2] = ms[0];
4581             ms[3] = ms[1];
4582         }
4583         if(len == 3){
4584             ms[3] = ms[1];
4585         }
4586         return {
4587             top:parseInt(ms[0], 10) || 0,
4588             right:parseInt(ms[1], 10) || 0,
4589             bottom:parseInt(ms[2], 10) || 0,
4590             left:parseInt(ms[3], 10) || 0
4591         };
4592     },
4593
4594     /**
4595      * The {@link Template Ext.Template} used by Field rendering layout classes (such as
4596      * {@link Ext.layout.FormLayout}) to create the DOM structure of a fully wrapped,
4597      * labeled and styled form Field. A default Template is supplied, but this may be
4598      * overriden to create custom field structures. The template processes values returned from
4599      * {@link Ext.layout.FormLayout#getTemplateArgs}.
4600      * @property fieldTpl
4601      * @type Ext.Template
4602      */
4603     fieldTpl: (function() {
4604         var t = new Ext.Template(
4605             '<div class="x-form-item {itemCls}" tabIndex="-1">',
4606                 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
4607                 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
4608                 '</div><div class="{clearCls}"></div>',
4609             '</div>'
4610         );
4611         t.disableFormats = true;
4612         return t.compile();
4613     })(),
4614         
4615     /*
4616      * Destroys this layout. This is a template method that is empty by default, but should be implemented
4617      * by subclasses that require explicit destruction to purge event handlers or remove DOM nodes.
4618      * @protected
4619      */
4620     destroy : Ext.emptyFn
4621 };
4622 Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout;/**\r
4623  * @class Ext.layout.FitLayout\r
4624  * @extends Ext.layout.ContainerLayout\r
4625  * <p>This is a base class for layouts that contain <b>a single item</b> that automatically expands to fill the layout's\r
4626  * container.  This class is intended to be extended or created via the <tt>layout:'fit'</tt> {@link Ext.Container#layout}\r
4627  * config, and should generally not need to be created directly via the new keyword.</p>\r
4628  * <p>FitLayout does not have any direct config options (other than inherited ones).  To fit a panel to a container\r
4629  * using FitLayout, simply set layout:'fit' on the container and add a single panel to it.  If the container has\r
4630  * multiple panels, only the first one will be displayed.  Example usage:</p>\r
4631  * <pre><code>\r
4632 var p = new Ext.Panel({\r
4633     title: 'Fit Layout',\r
4634     layout:'fit',\r
4635     items: {\r
4636         title: 'Inner Panel',\r
4637         html: '&lt;p&gt;This is the inner panel content&lt;/p&gt;',\r
4638         border: false\r
4639     }\r
4640 });\r
4641 </code></pre>\r
4642  */\r
4643 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
4644     // private\r
4645     monitorResize:true,\r
4646 \r
4647     // private\r
4648     onLayout : function(ct, target){\r
4649         Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);\r
4650         if(!this.container.collapsed){\r
4651             var sz = (Ext.isIE6 && Ext.isStrict && target.dom == document.body) ? target.getViewSize() : target.getStyleSize();\r
4652             this.setItemSize(this.activeItem || ct.items.itemAt(0), sz);\r
4653         }\r
4654     },\r
4655 \r
4656     // private\r
4657     setItemSize : function(item, size){\r
4658         if(item && size.height > 0){ // display none?\r
4659             item.setSize(size);\r
4660         }\r
4661     }\r
4662 });\r
4663 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;/**\r
4664  * @class Ext.layout.CardLayout\r
4665  * @extends Ext.layout.FitLayout\r
4666  * <p>This layout manages multiple child Components, each fitted to the Container, where only a single child Component can be\r
4667  * visible at any given time.  This layout style is most commonly used for wizards, tab implementations, etc.\r
4668  * This class is intended to be extended or created via the layout:'card' {@link Ext.Container#layout} config,\r
4669  * and should generally not need to be created directly via the new keyword.</p>\r
4670  * <p>The CardLayout's focal method is {@link #setActiveItem}.  Since only one panel is displayed at a time,\r
4671  * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of\r
4672  * the next panel to display.  The layout itself does not provide a user interface for handling this navigation,\r
4673  * so that functionality must be provided by the developer.</p>\r
4674  * <p>In the following example, a simplistic wizard setup is demonstrated.  A button bar is added\r
4675  * to the footer of the containing panel to provide navigation buttons.  The buttons will be handled by a\r
4676  * common navigation routine -- for this example, the implementation of that routine has been ommitted since\r
4677  * it can be any type of custom logic.  Note that other uses of a CardLayout (like a tab control) would require a\r
4678  * completely different implementation.  For serious implementations, a better approach would be to extend\r
4679  * CardLayout to provide the custom functionality needed.  Example usage:</p>\r
4680  * <pre><code>\r
4681 var navHandler = function(direction){\r
4682     // This routine could contain business logic required to manage the navigation steps.\r
4683     // It would call setActiveItem as needed, manage navigation button state, handle any\r
4684     // branching logic that might be required, handle alternate actions like cancellation\r
4685     // or finalization, etc.  A complete wizard implementation could get pretty\r
4686     // sophisticated depending on the complexity required, and should probably be\r
4687     // done as a subclass of CardLayout in a real-world implementation.\r
4688 };\r
4689 \r
4690 var card = new Ext.Panel({\r
4691     title: 'Example Wizard',\r
4692     layout:'card',\r
4693     activeItem: 0, // make sure the active item is set on the container config!\r
4694     bodyStyle: 'padding:15px',\r
4695     defaults: {\r
4696         // applied to each contained panel\r
4697         border:false\r
4698     },\r
4699     // just an example of one possible navigation scheme, using buttons\r
4700     bbar: [\r
4701         {\r
4702             id: 'move-prev',\r
4703             text: 'Back',\r
4704             handler: navHandler.createDelegate(this, [-1]),\r
4705             disabled: true\r
4706         },\r
4707         '->', // greedy spacer so that the buttons are aligned to each side\r
4708         {\r
4709             id: 'move-next',\r
4710             text: 'Next',\r
4711             handler: navHandler.createDelegate(this, [1])\r
4712         }\r
4713     ],\r
4714     // the panels (or "cards") within the layout\r
4715     items: [{\r
4716         id: 'card-0',\r
4717         html: '&lt;h1&gt;Welcome to the Wizard!&lt;/h1&gt;&lt;p&gt;Step 1 of 3&lt;/p&gt;'\r
4718     },{\r
4719         id: 'card-1',\r
4720         html: '&lt;p&gt;Step 2 of 3&lt;/p&gt;'\r
4721     },{\r
4722         id: 'card-2',\r
4723         html: '&lt;h1&gt;Congratulations!&lt;/h1&gt;&lt;p&gt;Step 3 of 3 - Complete&lt;/p&gt;'\r
4724     }]\r
4725 });\r
4726 </code></pre>\r
4727  */\r
4728 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {\r
4729     /**\r
4730      * @cfg {Boolean} deferredRender\r
4731      * True to render each contained item at the time it becomes active, false to render all contained items\r
4732      * as soon as the layout is rendered (defaults to false).  If there is a significant amount of content or\r
4733      * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to\r
4734      * true might improve performance.\r
4735      */\r
4736     deferredRender : false,\r
4737     \r
4738     /**\r
4739      * @cfg {Boolean} layoutOnCardChange\r
4740      * True to force a layout of the active item when the active card is changed. Defaults to false.\r
4741      */\r
4742     layoutOnCardChange : false,\r
4743 \r
4744     /**\r
4745      * @cfg {Boolean} renderHidden @hide\r
4746      */\r
4747     // private\r
4748     renderHidden : true,\r
4749     \r
4750     constructor: function(config){\r
4751         Ext.layout.CardLayout.superclass.constructor.call(this, config);\r
4752         this.forceLayout = (this.deferredRender === false);\r
4753     },\r
4754 \r
4755     /**\r
4756      * Sets the active (visible) item in the layout.\r
4757      * @param {String/Number} item The string component id or numeric index of the item to activate\r
4758      */\r
4759     setActiveItem : function(item){\r
4760         item = this.container.getComponent(item);\r
4761         if(this.activeItem != item){\r
4762             if(this.activeItem){\r
4763                 this.activeItem.hide();\r
4764             }\r
4765             this.activeItem = item;\r
4766             item.show();\r
4767             this.container.doLayout();\r
4768             if(this.layoutOnCardChange && item.doLayout){\r
4769                 item.doLayout();\r
4770             }\r
4771         }\r
4772     },\r
4773 \r
4774     // private\r
4775     renderAll : function(ct, target){\r
4776         if(this.deferredRender){\r
4777             this.renderItem(this.activeItem, undefined, target);\r
4778         }else{\r
4779             Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);\r
4780         }\r
4781     }\r
4782 });\r
4783 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;/**\r
4784  * @class Ext.layout.AnchorLayout\r
4785  * @extends Ext.layout.ContainerLayout\r
4786  * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.\r
4787  * If the container is resized, all anchored items are automatically rerendered according to their\r
4788  * <b><tt>{@link #anchor}</tt></b> rules.</p>\r
4789  * <p>This class is intended to be extended or created via the layout:'anchor' {@link Ext.Container#layout}\r
4790  * config, and should generally not need to be created directly via the new keyword.</p>\r
4791  * <p>AnchorLayout does not have any direct config options (other than inherited ones). By default,\r
4792  * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the\r
4793  * container using the AnchorLayout can supply an anchoring-specific config property of <b>anchorSize</b>.\r
4794  * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating\r
4795  * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring\r
4796  * logic if necessary.  For example:</p>\r
4797  * <pre><code>\r
4798 var viewport = new Ext.Viewport({\r
4799     layout:'anchor',\r
4800     anchorSize: {width:800, height:600},\r
4801     items:[{\r
4802         title:'Item 1',\r
4803         html:'Content 1',\r
4804         width:800,\r
4805         anchor:'right 20%'\r
4806     },{\r
4807         title:'Item 2',\r
4808         html:'Content 2',\r
4809         width:300,\r
4810         anchor:'50% 30%'\r
4811     },{\r
4812         title:'Item 3',\r
4813         html:'Content 3',\r
4814         width:600,\r
4815         anchor:'-100 50%'\r
4816     }]\r
4817 });\r
4818  * </code></pre>\r
4819  */\r
4820 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
4821     /**\r
4822      * @cfg {String} anchor\r
4823      * <p>This configuation option is to be applied to <b>child <tt>items</tt></b> of a container managed by\r
4824      * this layout (ie. configured with <tt>layout:'anchor'</tt>).</p><br/>\r
4825      * \r
4826      * <p>This value is what tells the layout how an item should be anchored to the container. <tt>items</tt>\r
4827      * added to an AnchorLayout accept an anchoring-specific config property of <b>anchor</b> which is a string\r
4828      * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').\r
4829      * The following types of anchor values are supported:<div class="mdetail-params"><ul>\r
4830      * \r
4831      * <li><b>Percentage</b> : Any value between 1 and 100, expressed as a percentage.<div class="sub-desc">\r
4832      * The first anchor is the percentage width that the item should take up within the container, and the\r
4833      * second is the percentage height.  For example:<pre><code>\r
4834 // two values specified\r
4835 anchor: '100% 50%' // render item complete width of the container and\r
4836                    // 1/2 height of the container\r
4837 // one value specified\r
4838 anchor: '100%'     // the width value; the height will default to auto\r
4839      * </code></pre></div></li>\r
4840      * \r
4841      * <li><b>Offsets</b> : Any positive or negative integer value.<div class="sub-desc">\r
4842      * This is a raw adjustment where the first anchor is the offset from the right edge of the container,\r
4843      * and the second is the offset from the bottom edge. For example:<pre><code>\r
4844 // two values specified\r
4845 anchor: '-50 -100' // render item the complete width of the container\r
4846                    // minus 50 pixels and\r
4847                    // the complete height minus 100 pixels.\r
4848 // one value specified\r
4849 anchor: '-50'      // anchor value is assumed to be the right offset value\r
4850                    // bottom offset will default to 0\r
4851      * </code></pre></div></li>\r
4852      * \r
4853      * <li><b>Sides</b> : Valid values are <tt>'right'</tt> (or <tt>'r'</tt>) and <tt>'bottom'</tt>\r
4854      * (or <tt>'b'</tt>).<div class="sub-desc">\r
4855      * Either the container must have a fixed size or an anchorSize config value defined at render time in\r
4856      * order for these to have any effect.</div></li>\r
4857      *\r
4858      * <li><b>Mixed</b> : <div class="sub-desc">\r
4859      * Anchor values can also be mixed as needed.  For example, to render the width offset from the container\r
4860      * right edge by 50 pixels and 75% of the container's height use:\r
4861      * <pre><code>\r
4862 anchor: '-50 75%' \r
4863      * </code></pre></div></li>\r
4864      * \r
4865      * \r
4866      * </ul></div>\r
4867      */\r
4868     \r
4869     // private\r
4870     monitorResize:true,\r
4871 \r
4872     // private\r
4873     getAnchorViewSize : function(ct, target){\r
4874         return target.dom == document.body ?\r
4875                    target.getViewSize() : target.getStyleSize();\r
4876     },\r
4877 \r
4878     // private\r
4879     onLayout : function(ct, target){\r
4880         Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);\r
4881 \r
4882         var size = this.getAnchorViewSize(ct, target);\r
4883 \r
4884         var w = size.width, h = size.height;\r
4885 \r
4886         if(w < 20 && h < 20){\r
4887             return;\r
4888         }\r
4889 \r
4890         // find the container anchoring size\r
4891         var aw, ah;\r
4892         if(ct.anchorSize){\r
4893             if(typeof ct.anchorSize == 'number'){\r
4894                 aw = ct.anchorSize;\r
4895             }else{\r
4896                 aw = ct.anchorSize.width;\r
4897                 ah = ct.anchorSize.height;\r
4898             }\r
4899         }else{\r
4900             aw = ct.initialConfig.width;\r
4901             ah = ct.initialConfig.height;\r
4902         }\r
4903 \r
4904         var cs = ct.items.items, len = cs.length, i, c, a, cw, ch;\r
4905         for(i = 0; i < len; i++){\r
4906             c = cs[i];\r
4907             if(c.anchor){\r
4908                 a = c.anchorSpec;\r
4909                 if(!a){ // cache all anchor values\r
4910                     var vs = c.anchor.split(' ');\r
4911                     c.anchorSpec = a = {\r
4912                         right: this.parseAnchor(vs[0], c.initialConfig.width, aw),\r
4913                         bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)\r
4914                     };\r
4915                 }\r
4916                 cw = a.right ? this.adjustWidthAnchor(a.right(w), c) : undefined;\r
4917                 ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h), c) : undefined;\r
4918 \r
4919                 if(cw || ch){\r
4920                     c.setSize(cw || undefined, ch || undefined);\r
4921                 }\r
4922             }\r
4923         }\r
4924     },\r
4925 \r
4926     // private\r
4927     parseAnchor : function(a, start, cstart){\r
4928         if(a && a != 'none'){\r
4929             var last;\r
4930             if(/^(r|right|b|bottom)$/i.test(a)){   // standard anchor\r
4931                 var diff = cstart - start;\r
4932                 return function(v){\r
4933                     if(v !== last){\r
4934                         last = v;\r
4935                         return v - diff;\r
4936                     }\r
4937                 }\r
4938             }else if(a.indexOf('%') != -1){\r
4939                 var ratio = parseFloat(a.replace('%', ''))*.01;   // percentage\r
4940                 return function(v){\r
4941                     if(v !== last){\r
4942                         last = v;\r
4943                         return Math.floor(v*ratio);\r
4944                     }\r
4945                 }\r
4946             }else{\r
4947                 a = parseInt(a, 10);\r
4948                 if(!isNaN(a)){                            // simple offset adjustment\r
4949                     return function(v){\r
4950                         if(v !== last){\r
4951                             last = v;\r
4952                             return v + a;\r
4953                         }\r
4954                     }\r
4955                 }\r
4956             }\r
4957         }\r
4958         return false;\r
4959     },\r
4960 \r
4961     // private\r
4962     adjustWidthAnchor : function(value, comp){\r
4963         return value;\r
4964     },\r
4965 \r
4966     // private\r
4967     adjustHeightAnchor : function(value, comp){\r
4968         return value;\r
4969     }\r
4970     \r
4971     /**\r
4972      * @property activeItem\r
4973      * @hide\r
4974      */\r
4975 });\r
4976 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;/**\r
4977  * @class Ext.layout.ColumnLayout\r
4978  * @extends Ext.layout.ContainerLayout\r
4979  * <p>This is the layout style of choice for creating structural layouts in a multi-column format where the width of\r
4980  * each column can be specified as a percentage or fixed width, but the height is allowed to vary based on the content.\r
4981  * This class is intended to be extended or created via the layout:'column' {@link Ext.Container#layout} config,\r
4982  * and should generally not need to be created directly via the new keyword.</p>\r
4983  * <p>ColumnLayout does not have any direct config options (other than inherited ones), but it does support a\r
4984  * specific config property of <b><tt>columnWidth</tt></b> that can be included in the config of any panel added to it.  The\r
4985  * layout will use the columnWidth (if present) or width of each panel during layout to determine how to size each panel.\r
4986  * If width or columnWidth is not specified for a given panel, its width will default to the panel's width (or auto).</p>\r
4987  * <p>The width property is always evaluated as pixels, and must be a number greater than or equal to 1.\r
4988  * The columnWidth property is always evaluated as a percentage, and must be a decimal value greater than 0 and\r
4989  * less than 1 (e.g., .25).</p>\r
4990  * <p>The basic rules for specifying column widths are pretty simple.  The logic makes two passes through the\r
4991  * set of contained panels.  During the first layout pass, all panels that either have a fixed width or none\r
4992  * specified (auto) are skipped, but their widths are subtracted from the overall container width.  During the second\r
4993  * pass, all panels with columnWidths are assigned pixel widths in proportion to their percentages based on\r
4994  * the total <b>remaining</b> container width.  In other words, percentage width panels are designed to fill the space\r
4995  * left over by all the fixed-width and/or auto-width panels.  Because of this, while you can specify any number of columns\r
4996  * with different percentages, the columnWidths must always add up to 1 (or 100%) when added together, otherwise your\r
4997  * layout may not render as expected.  Example usage:</p>\r
4998  * <pre><code>\r
4999 // All columns are percentages -- they must add up to 1\r
5000 var p = new Ext.Panel({\r
5001     title: 'Column Layout - Percentage Only',\r
5002     layout:'column',\r
5003     items: [{\r
5004         title: 'Column 1',\r
5005         columnWidth: .25 \r
5006     },{\r
5007         title: 'Column 2',\r
5008         columnWidth: .6\r
5009     },{\r
5010         title: 'Column 3',\r
5011         columnWidth: .15\r
5012     }]\r
5013 });\r
5014 \r
5015 // Mix of width and columnWidth -- all columnWidth values must add up\r
5016 // to 1. The first column will take up exactly 120px, and the last two\r
5017 // columns will fill the remaining container width.\r
5018 var p = new Ext.Panel({\r
5019     title: 'Column Layout - Mixed',\r
5020     layout:'column',\r
5021     items: [{\r
5022         title: 'Column 1',\r
5023         width: 120\r
5024     },{\r
5025         title: 'Column 2',\r
5026         columnWidth: .8\r
5027     },{\r
5028         title: 'Column 3',\r
5029         columnWidth: .2\r
5030     }]\r
5031 });\r
5032 </code></pre>\r
5033  */\r
5034 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
5035     // private\r
5036     monitorResize:true,\r
5037     \r
5038     extraCls: 'x-column',\r
5039 \r
5040     scrollOffset : 0,\r
5041 \r
5042     // private\r
5043     isValidParent : function(c, target){\r
5044         return (c.getPositionEl ? c.getPositionEl() : c.getEl()).dom.parentNode == this.innerCt.dom;\r
5045     },\r
5046 \r
5047     // private\r
5048     onLayout : function(ct, target){\r
5049         var cs = ct.items.items, len = cs.length, c, i;\r
5050 \r
5051         if(!this.innerCt){\r
5052             target.addClass('x-column-layout-ct');\r
5053 \r
5054             // the innerCt prevents wrapping and shuffling while\r
5055             // the container is resizing\r
5056             this.innerCt = target.createChild({cls:'x-column-inner'});\r
5057             this.innerCt.createChild({cls:'x-clear'});\r
5058         }\r
5059         this.renderAll(ct, this.innerCt);\r
5060 \r
5061         var size = Ext.isIE && target.dom != Ext.getBody().dom ? target.getStyleSize() : target.getViewSize();\r
5062 \r
5063         if(size.width < 1 && size.height < 1){ // display none?\r
5064             return;\r
5065         }\r
5066 \r
5067         var w = size.width - target.getPadding('lr') - this.scrollOffset,\r
5068             h = size.height - target.getPadding('tb'),\r
5069             pw = w;\r
5070 \r
5071         this.innerCt.setWidth(w);\r
5072         \r
5073         // some columns can be percentages while others are fixed\r
5074         // so we need to make 2 passes\r
5075 \r
5076         for(i = 0; i < len; i++){\r
5077             c = cs[i];\r
5078             if(!c.columnWidth){\r
5079                 pw -= (c.getSize().width + c.getEl().getMargins('lr'));\r
5080             }\r
5081         }\r
5082 \r
5083         pw = pw < 0 ? 0 : pw;\r
5084 \r
5085         for(i = 0; i < len; i++){\r
5086             c = cs[i];\r
5087             if(c.columnWidth){\r
5088                 c.setSize(Math.floor(c.columnWidth*pw) - c.getEl().getMargins('lr'));\r
5089             }\r
5090         }\r
5091     }\r
5092     \r
5093     /**\r
5094      * @property activeItem\r
5095      * @hide\r
5096      */\r
5097 });\r
5098 \r
5099 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;/**
5100  * @class Ext.layout.BorderLayout
5101  * @extends Ext.layout.ContainerLayout
5102  * <p>This is a multi-pane, application-oriented UI layout style that supports multiple
5103  * nested panels, automatic {@link Ext.layout.BorderLayout.Region#split split} bars between
5104  * {@link Ext.layout.BorderLayout.Region#BorderLayout.Region regions} and built-in
5105  * {@link Ext.layout.BorderLayout.Region#collapsible expanding and collapsing} of regions.</p>
5106  * <p>This class is intended to be extended or created via the <tt>layout:'border'</tt>
5107  * {@link Ext.Container#layout} config, and should generally not need to be created directly
5108  * via the new keyword.</p>
5109  * <p>BorderLayout does not have any direct config options (other than inherited ones).
5110  * All configuration options available for customizing the BorderLayout are at the
5111  * {@link Ext.layout.BorderLayout.Region} and {@link Ext.layout.BorderLayout.SplitRegion}
5112  * levels.</p>
5113  * <p>Example usage:</p>
5114  * <pre><code>
5115 var myBorderPanel = new Ext.Panel({
5116     {@link Ext.Component#renderTo renderTo}: document.body,
5117     {@link Ext.BoxComponent#width width}: 700,
5118     {@link Ext.BoxComponent#height height}: 500,
5119     {@link Ext.Panel#title title}: 'Border Layout',
5120     {@link Ext.Container#layout layout}: 'border',
5121     {@link Ext.Container#items items}: [{
5122         {@link Ext.Panel#title title}: 'South Region is resizable',
5123         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south',     // position for region
5124         {@link Ext.BoxComponent#height height}: 100,
5125         {@link Ext.layout.BorderLayout.Region#split split}: true,         // enable resizing
5126         {@link Ext.SplitBar#minSize minSize}: 75,         // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50} 
5127         {@link Ext.SplitBar#maxSize maxSize}: 150,
5128         {@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5'
5129     },{
5130         // xtype: 'panel' implied by default
5131         {@link Ext.Panel#title title}: 'West Region is collapsible',
5132         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}:'west',
5133         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 0 0 5',
5134         {@link Ext.BoxComponent#width width}: 200,
5135         {@link Ext.layout.BorderLayout.Region#collapsible collapsible}: true,   // make collapsible
5136         {@link Ext.layout.BorderLayout.Region#cmargins cmargins}: '5 5 0 5', // adjust top margin when collapsed
5137         {@link Ext.Component#id id}: 'west-region-container',
5138         {@link Ext.Container#layout layout}: 'fit',
5139         {@link Ext.Panel#unstyled unstyled}: true
5140     },{
5141         {@link Ext.Panel#title title}: 'Center Region',
5142         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'center',     // center region is required, no width/height specified
5143         {@link Ext.Component#xtype xtype}: 'container',
5144         {@link Ext.Container#layout layout}: 'fit',
5145         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 5 0 0'
5146     }]
5147 });
5148 </code></pre>
5149  * <p><b><u>Notes</u></b>:</p><div class="mdetail-params"><ul>
5150  * <li>Any container using the BorderLayout <b>must</b> have a child item with <tt>region:'center'</tt>.
5151  * The child item in the center region will always be resized to fill the remaining space not used by
5152  * the other regions in the layout.</li>
5153  * <li>Any child items with a region of <tt>west</tt> or <tt>east</tt> must have <tt>width</tt> defined
5154  * (an integer representing the number of pixels that the region should take up).</li>
5155  * <li>Any child items with a region of <tt>north</tt> or <tt>south</tt> must have <tt>height</tt> defined.</li>
5156  * <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
5157  * Components within a BorderLayout, have them wrapped by an additional Container which is directly
5158  * managed by the BorderLayout.  If the region is to be collapsible, the Container used directly
5159  * by the BorderLayout manager should be a Panel.  In the following example a Container (an Ext.Panel)
5160  * is added to the west region:
5161  * <div style="margin-left:16px"><pre><code>
5162 wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container');
5163 wrc.{@link Ext.Panel#removeAll removeAll}();
5164 wrc.{@link Ext.Container#add add}({
5165     title: 'Added Panel',
5166     html: 'Some content'
5167 });
5168 wrc.{@link Ext.Container#doLayout doLayout}();
5169  * </code></pre></div>
5170  * </li>
5171  * <li> To reference a {@link Ext.layout.BorderLayout.Region Region}:
5172  * <div style="margin-left:16px"><pre><code>
5173 wr = myBorderPanel.layout.west;
5174  * </code></pre></div>
5175  * </li>
5176  * </ul></div>
5177  */
5178 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
5179     // private
5180     monitorResize:true,
5181     // private
5182     rendered : false,
5183
5184     // private
5185     onLayout : function(ct, target){
5186         var collapsed;
5187         if(!this.rendered){
5188             target.addClass('x-border-layout-ct');
5189             var items = ct.items.items;
5190             collapsed = [];
5191             for(var i = 0, len = items.length; i < len; i++) {
5192                 var c = items[i];
5193                 var pos = c.region;
5194                 if(c.collapsed){
5195                     collapsed.push(c);
5196                 }
5197                 c.collapsed = false;
5198                 if(!c.rendered){
5199                     c.cls = c.cls ? c.cls +' x-border-panel' : 'x-border-panel';
5200                     c.render(target, i);
5201                 }
5202                 this[pos] = pos != 'center' && c.split ?
5203                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
5204                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
5205                 this[pos].render(target, c);
5206             }
5207             this.rendered = true;
5208         }
5209
5210         var size = target.getViewSize();
5211         if(size.width < 20 || size.height < 20){ // display none?
5212             if(collapsed){
5213                 this.restoreCollapsed = collapsed;
5214             }
5215             return;
5216         }else if(this.restoreCollapsed){
5217             collapsed = this.restoreCollapsed;
5218             delete this.restoreCollapsed;
5219         }
5220
5221         var w = size.width, h = size.height;
5222         var centerW = w, centerH = h, centerY = 0, centerX = 0;
5223
5224         var n = this.north, s = this.south, west = this.west, e = this.east, c = this.center;
5225         if(!c && Ext.layout.BorderLayout.WARN !== false){
5226             throw 'No center region defined in BorderLayout ' + ct.id;
5227         }
5228
5229         if(n && n.isVisible()){
5230             var b = n.getSize();
5231             var m = n.getMargins();
5232             b.width = w - (m.left+m.right);
5233             b.x = m.left;
5234             b.y = m.top;
5235             centerY = b.height + b.y + m.bottom;
5236             centerH -= centerY;
5237             n.applyLayout(b);
5238         }
5239         if(s && s.isVisible()){
5240             var b = s.getSize();
5241             var m = s.getMargins();
5242             b.width = w - (m.left+m.right);
5243             b.x = m.left;
5244             var totalHeight = (b.height + m.top + m.bottom);
5245             b.y = h - totalHeight + m.top;
5246             centerH -= totalHeight;
5247             s.applyLayout(b);
5248         }
5249         if(west && west.isVisible()){
5250             var b = west.getSize();
5251             var m = west.getMargins();
5252             b.height = centerH - (m.top+m.bottom);
5253             b.x = m.left;
5254             b.y = centerY + m.top;
5255             var totalWidth = (b.width + m.left + m.right);
5256             centerX += totalWidth;
5257             centerW -= totalWidth;
5258             west.applyLayout(b);
5259         }
5260         if(e && e.isVisible()){
5261             var b = e.getSize();
5262             var m = e.getMargins();
5263             b.height = centerH - (m.top+m.bottom);
5264             var totalWidth = (b.width + m.left + m.right);
5265             b.x = w - totalWidth + m.left;
5266             b.y = centerY + m.top;
5267             centerW -= totalWidth;
5268             e.applyLayout(b);
5269         }
5270         if(c){
5271             var m = c.getMargins();
5272             var centerBox = {
5273                 x: centerX + m.left,
5274                 y: centerY + m.top,
5275                 width: centerW - (m.left+m.right),
5276                 height: centerH - (m.top+m.bottom)
5277             };
5278             c.applyLayout(centerBox);
5279         }
5280         if(collapsed){
5281             for(var i = 0, len = collapsed.length; i < len; i++){
5282                 collapsed[i].collapse(false);
5283             }
5284         }
5285         if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue
5286             target.repaint();
5287         }
5288     },
5289
5290     destroy: function() {
5291         var r = ['north', 'south', 'east', 'west'];
5292         for (var i = 0; i < r.length; i++) {
5293             var region = this[r[i]];
5294             if(region){
5295                 if(region.destroy){
5296                     region.destroy();
5297                 }else if (region.split){
5298                     region.split.destroy(true);
5299                 }
5300             }
5301         }
5302         Ext.layout.BorderLayout.superclass.destroy.call(this);
5303     }
5304
5305     /**
5306      * @property activeItem
5307      * @hide
5308      */
5309 });
5310
5311 /**
5312  * @class Ext.layout.BorderLayout.Region
5313  * <p>This is a region of a {@link Ext.layout.BorderLayout BorderLayout} that acts as a subcontainer
5314  * within the layout.  Each region has its own {@link Ext.layout.ContainerLayout layout} that is
5315  * independent of other regions and the containing BorderLayout, and can be any of the
5316  * {@link Ext.layout.ContainerLayout valid Ext layout types}.</p>
5317  * <p>Region size is managed automatically and cannot be changed by the user -- for
5318  * {@link #split resizable regions}, see {@link Ext.layout.BorderLayout.SplitRegion}.</p>
5319  * @constructor
5320  * Create a new Region.
5321  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
5322  * @param {Object} config The configuration options
5323  * @param {String} position The region position.  Valid values are: <tt>north</tt>, <tt>south</tt>,
5324  * <tt>east</tt>, <tt>west</tt> and <tt>center</tt>.  Every {@link Ext.layout.BorderLayout BorderLayout}
5325  * <b>must have a center region</b> for the primary content -- all other regions are optional.
5326  */
5327 Ext.layout.BorderLayout.Region = function(layout, config, pos){
5328     Ext.apply(this, config);
5329     this.layout = layout;
5330     this.position = pos;
5331     this.state = {};
5332     if(typeof this.margins == 'string'){
5333         this.margins = this.layout.parseMargins(this.margins);
5334     }
5335     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
5336     if(this.collapsible){
5337         if(typeof this.cmargins == 'string'){
5338             this.cmargins = this.layout.parseMargins(this.cmargins);
5339         }
5340         if(this.collapseMode == 'mini' && !this.cmargins){
5341             this.cmargins = {left:0,top:0,right:0,bottom:0};
5342         }else{
5343             this.cmargins = Ext.applyIf(this.cmargins || {},
5344                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
5345         }
5346     }
5347 };
5348
5349 Ext.layout.BorderLayout.Region.prototype = {
5350     /**
5351      * @cfg {Boolean} animFloat
5352      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
5353      * panel that will close again once the user mouses out of that panel (or clicks out if
5354      * <tt>{@link #autoHide} = false</tt>).  Setting <tt>{@link #animFloat} = false</tt> will
5355      * prevent the open and close of these floated panels from being animated (defaults to <tt>true</tt>).
5356      */
5357     /**
5358      * @cfg {Boolean} autoHide
5359      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
5360      * panel.  If <tt>autoHide = true</tt>, the panel will automatically hide after the user mouses
5361      * out of the panel.  If <tt>autoHide = false</tt>, the panel will continue to display until the
5362      * user clicks outside of the panel (defaults to <tt>true</tt>).
5363      */
5364     /**
5365      * @cfg {String} collapseMode
5366      * <tt>collapseMode</tt> supports two configuration values:<div class="mdetail-params"><ul>
5367      * <li><b><tt>undefined</tt></b> (default)<div class="sub-desc">By default, {@link #collapsible}
5368      * regions are collapsed by clicking the expand/collapse tool button that renders into the region's
5369      * title bar.</div></li>
5370      * <li><b><tt>'mini'</tt></b><div class="sub-desc">Optionally, when <tt>collapseMode</tt> is set to
5371      * <tt>'mini'</tt> the region's split bar will also display a small collapse button in the center of
5372      * the bar. In <tt>'mini'</tt> mode the region will collapse to a thinner bar than in normal mode.
5373      * </div></li>
5374      * </ul></div></p>
5375      * <p><b>Note</b>: if a collapsible region does not have a title bar, then set <tt>collapseMode =
5376      * 'mini'</tt> and <tt>{@link #split} = true</tt> in order for the region to be {@link #collapsible}
5377      * by the user as the expand/collapse tool button (that would go in the title bar) will not be rendered.</p>
5378      * <p>See also <tt>{@link #cmargins}</tt>.</p>
5379      */
5380     /**
5381      * @cfg {Object} margins
5382      * An object containing margins to apply to the region when in the expanded state in the
5383      * format:<pre><code>
5384 {
5385     top: (top margin),
5386     right: (right margin),
5387     bottom: (bottom margin),
5388     left: (left margin)
5389 }</code></pre>
5390      * <p>May also be a string containing space-separated, numeric margin values. The order of the
5391      * sides associated with each value matches the way CSS processes margin values:</p>
5392      * <p><div class="mdetail-params"><ul>
5393      * <li>If there is only one value, it applies to all sides.</li>
5394      * <li>If there are two values, the top and bottom borders are set to the first value and the
5395      * right and left are set to the second.</li>
5396      * <li>If there are three values, the top is set to the first value, the left and right are set
5397      * to the second, and the bottom is set to the third.</li>
5398      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
5399      * </ul></div></p>
5400      * <p>Defaults to:</p><pre><code>
5401      * {top:0, right:0, bottom:0, left:0}
5402      * </code></pre>
5403      */
5404     /**
5405      * @cfg {Object} cmargins
5406      * An object containing margins to apply to the region when in the collapsed state in the
5407      * format:<pre><code>
5408 {
5409     top: (top margin),
5410     right: (right margin),
5411     bottom: (bottom margin),
5412     left: (left margin)
5413 }</code></pre>
5414      * <p>May also be a string containing space-separated, numeric margin values. The order of the
5415      * sides associated with each value matches the way CSS processes margin values.</p>
5416      * <p><ul>
5417      * <li>If there is only one value, it applies to all sides.</li>
5418      * <li>If there are two values, the top and bottom borders are set to the first value and the
5419      * right and left are set to the second.</li>
5420      * <li>If there are three values, the top is set to the first value, the left and right are set
5421      * to the second, and the bottom is set to the third.</li>
5422      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
5423      * </ul></p>
5424      */
5425     /**
5426      * @cfg {Boolean} collapsible
5427      * <p><tt>true</tt> to allow the user to collapse this region (defaults to <tt>false</tt>).  If
5428      * <tt>true</tt>, an expand/collapse tool button will automatically be rendered into the title
5429      * bar of the region, otherwise the button will not be shown.</p>
5430      * <p><b>Note</b>: that a title bar is required to display the collapse/expand toggle button -- if
5431      * no <tt>title</tt> is specified for the region's panel, the region will only be collapsible if
5432      * <tt>{@link #collapseMode} = 'mini'</tt> and <tt>{@link #split} = true</tt>.
5433      */
5434     collapsible : false,
5435     /**
5436      * @cfg {Boolean} split
5437      * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and 
5438      * display a 5px wide {@link Ext.SplitBar} between this region and its neighbor, allowing the user to
5439      * resize the regions dynamically.  Defaults to <tt>false</tt> creating a
5440      * {@link Ext.layout.BorderLayout.Region Region}.</p><br>
5441      * <p><b>Notes</b>:</p><div class="mdetail-params"><ul>
5442      * <li>this configuration option is ignored if <tt>region='center'</tt></li> 
5443      * <li>when <tt>split == true</tt>, it is common to specify a
5444      * <tt>{@link Ext.SplitBar#minSize minSize}</tt> and <tt>{@link Ext.SplitBar#maxSize maxSize}</tt>
5445      * for the {@link Ext.BoxComponent BoxComponent} representing the region. These are not native
5446      * configs of {@link Ext.BoxComponent BoxComponent}, and are used only by this class.</li>
5447      * <li>if <tt>{@link #collapseMode} = 'mini'</tt> requires <tt>split = true</tt> to reserve space
5448      * for the collapse tool</tt></li> 
5449      * </ul></div> 
5450      */
5451     split:false,
5452     /**
5453      * @cfg {Boolean} floatable
5454      * <tt>true</tt> to allow clicking a collapsed region's bar to display the region's panel floated
5455      * above the layout, <tt>false</tt> to force the user to fully expand a collapsed region by
5456      * clicking the expand button to see it again (defaults to <tt>true</tt>).
5457      */
5458     floatable: true,
5459     /**
5460      * @cfg {Number} minWidth
5461      * <p>The minimum allowable width in pixels for this region (defaults to <tt>50</tt>).
5462      * <tt>maxWidth</tt> may also be specified.</p><br>
5463      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> / 
5464      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified 
5465      * <tt>minWidth</tt> / <tt>maxWidth</tt>.</p>
5466      */
5467     minWidth:50,
5468     /**
5469      * @cfg {Number} minHeight
5470      * The minimum allowable height in pixels for this region (defaults to <tt>50</tt>)
5471      * <tt>maxHeight</tt> may also be specified.</p><br>
5472      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> / 
5473      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified 
5474      * <tt>minHeight</tt> / <tt>maxHeight</tt>.</p>
5475      */
5476     minHeight:50,
5477
5478     // private
5479     defaultMargins : {left:0,top:0,right:0,bottom:0},
5480     // private
5481     defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
5482     // private
5483     defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
5484     floatingZIndex: 100,
5485
5486     /**
5487      * True if this region is collapsed. Read-only.
5488      * @type Boolean
5489      * @property
5490      */
5491     isCollapsed : false,
5492
5493     /**
5494      * This region's panel.  Read-only.
5495      * @type Ext.Panel
5496      * @property panel
5497      */
5498     /**
5499      * This region's layout.  Read-only.
5500      * @type Layout
5501      * @property layout
5502      */
5503     /**
5504      * This region's layout position (north, south, east, west or center).  Read-only.
5505      * @type String
5506      * @property position
5507      */
5508
5509     // private
5510     render : function(ct, p){
5511         this.panel = p;
5512         p.el.enableDisplayMode();
5513         this.targetEl = ct;
5514         this.el = p.el;
5515
5516         var gs = p.getState, ps = this.position;
5517         p.getState = function(){
5518             return Ext.apply(gs.call(p) || {}, this.state);
5519         }.createDelegate(this);
5520
5521         if(ps != 'center'){
5522             p.allowQueuedExpand = false;
5523             p.on({
5524                 beforecollapse: this.beforeCollapse,
5525                 collapse: this.onCollapse,
5526                 beforeexpand: this.beforeExpand,
5527                 expand: this.onExpand,
5528                 hide: this.onHide,
5529                 show: this.onShow,
5530                 scope: this
5531             });
5532             if(this.collapsible || this.floatable){
5533                 p.collapseEl = 'el';
5534                 p.slideAnchor = this.getSlideAnchor();
5535             }
5536             if(p.tools && p.tools.toggle){
5537                 p.tools.toggle.addClass('x-tool-collapse-'+ps);
5538                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
5539             }
5540         }
5541     },
5542
5543     // private
5544     getCollapsedEl : function(){
5545         if(!this.collapsedEl){
5546             if(!this.toolTemplate){
5547                 var tt = new Ext.Template(
5548                      '<div class="x-tool x-tool-{id}">&#160;</div>'
5549                 );
5550                 tt.disableFormats = true;
5551                 tt.compile();
5552                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
5553             }
5554             this.collapsedEl = this.targetEl.createChild({
5555                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
5556                 id: this.panel.id + '-xcollapsed'
5557             });
5558             this.collapsedEl.enableDisplayMode('block');
5559
5560             if(this.collapseMode == 'mini'){
5561                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
5562                 this.miniCollapsedEl = this.collapsedEl.createChild({
5563                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
5564                 });
5565                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
5566                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
5567                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
5568             }else {
5569                 if(this.collapsible !== false && !this.hideCollapseTool) {
5570                     var t = this.toolTemplate.append(
5571                             this.collapsedEl.dom,
5572                             {id:'expand-'+this.position}, true);
5573                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
5574                     t.on('click', this.onExpandClick, this, {stopEvent:true});
5575                 }
5576                 if(this.floatable !== false || this.titleCollapse){
5577                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
5578                    this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
5579                 }
5580             }
5581         }
5582         return this.collapsedEl;
5583     },
5584
5585     // private
5586     onExpandClick : function(e){
5587         if(this.isSlid){
5588             this.afterSlideIn();
5589             this.panel.expand(false);
5590         }else{
5591             this.panel.expand();
5592         }
5593     },
5594
5595     // private
5596     onCollapseClick : function(e){
5597         this.panel.collapse();
5598     },
5599
5600     // private
5601     beforeCollapse : function(p, animate){
5602         this.lastAnim = animate;
5603         if(this.splitEl){
5604             this.splitEl.hide();
5605         }
5606         this.getCollapsedEl().show();
5607         this.panel.el.setStyle('z-index', 100);
5608         this.isCollapsed = true;
5609         this.layout.layout();
5610     },
5611
5612     // private
5613     onCollapse : function(animate){
5614         this.panel.el.setStyle('z-index', 1);
5615         if(this.lastAnim === false || this.panel.animCollapse === false){
5616             this.getCollapsedEl().dom.style.visibility = 'visible';
5617         }else{
5618             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
5619         }
5620         this.state.collapsed = true;
5621         this.panel.saveState();
5622     },
5623
5624     // private
5625     beforeExpand : function(animate){
5626         var c = this.getCollapsedEl();
5627         this.el.show();
5628         if(this.position == 'east' || this.position == 'west'){
5629             this.panel.setSize(undefined, c.getHeight());
5630         }else{
5631             this.panel.setSize(c.getWidth(), undefined);
5632         }
5633         c.hide();
5634         c.dom.style.visibility = 'hidden';
5635         this.panel.el.setStyle('z-index', this.floatingZIndex);
5636     },
5637
5638     // private
5639     onExpand : function(){
5640         this.isCollapsed = false;
5641         if(this.splitEl){
5642             this.splitEl.show();
5643         }
5644         this.layout.layout();
5645         this.panel.el.setStyle('z-index', 1);
5646         this.state.collapsed = false;
5647         this.panel.saveState();
5648     },
5649
5650     // private
5651     collapseClick : function(e){
5652         if(this.isSlid){
5653            e.stopPropagation();
5654            this.slideIn();
5655         }else{
5656            e.stopPropagation();
5657            this.slideOut();
5658         }
5659     },
5660
5661     // private
5662     onHide : function(){
5663         if(this.isCollapsed){
5664             this.getCollapsedEl().hide();
5665         }else if(this.splitEl){
5666             this.splitEl.hide();
5667         }
5668     },
5669
5670     // private
5671     onShow : function(){
5672         if(this.isCollapsed){
5673             this.getCollapsedEl().show();
5674         }else if(this.splitEl){
5675             this.splitEl.show();
5676         }
5677     },
5678
5679     /**
5680      * True if this region is currently visible, else false.
5681      * @return {Boolean}
5682      */
5683     isVisible : function(){
5684         return !this.panel.hidden;
5685     },
5686
5687     /**
5688      * Returns the current margins for this region.  If the region is collapsed, the
5689      * {@link #cmargins} (collapsed margins) value will be returned, otherwise the
5690      * {@link #margins} value will be returned.
5691      * @return {Object} An object containing the element's margins: <tt>{left: (left
5692      * margin), top: (top margin), right: (right margin), bottom: (bottom margin)}</tt>
5693      */
5694     getMargins : function(){
5695         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
5696     },
5697
5698     /**
5699      * Returns the current size of this region.  If the region is collapsed, the size of the
5700      * collapsedEl will be returned, otherwise the size of the region's panel will be returned.
5701      * @return {Object} An object containing the element's size: <tt>{width: (element width),
5702      * height: (element height)}</tt>
5703      */
5704     getSize : function(){
5705         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
5706     },
5707
5708     /**
5709      * Sets the specified panel as the container element for this region.
5710      * @param {Ext.Panel} panel The new panel
5711      */
5712     setPanel : function(panel){
5713         this.panel = panel;
5714     },
5715
5716     /**
5717      * Returns the minimum allowable width for this region.
5718      * @return {Number} The minimum width
5719      */
5720     getMinWidth: function(){
5721         return this.minWidth;
5722     },
5723
5724     /**
5725      * Returns the minimum allowable height for this region.
5726      * @return {Number} The minimum height
5727      */
5728     getMinHeight: function(){
5729         return this.minHeight;
5730     },
5731
5732     // private
5733     applyLayoutCollapsed : function(box){
5734         var ce = this.getCollapsedEl();
5735         ce.setLeftTop(box.x, box.y);
5736         ce.setSize(box.width, box.height);
5737     },
5738
5739     // private
5740     applyLayout : function(box){
5741         if(this.isCollapsed){
5742             this.applyLayoutCollapsed(box);
5743         }else{
5744             this.panel.setPosition(box.x, box.y);
5745             this.panel.setSize(box.width, box.height);
5746         }
5747     },
5748
5749     // private
5750     beforeSlide: function(){
5751         this.panel.beforeEffect();
5752     },
5753
5754     // private
5755     afterSlide : function(){
5756         this.panel.afterEffect();
5757     },
5758
5759     // private
5760     initAutoHide : function(){
5761         if(this.autoHide !== false){
5762             if(!this.autoHideHd){
5763                 var st = new Ext.util.DelayedTask(this.slideIn, this);
5764                 this.autoHideHd = {
5765                     "mouseout": function(e){
5766                         if(!e.within(this.el, true)){
5767                             st.delay(500);
5768                         }
5769                     },
5770                     "mouseover" : function(e){
5771                         st.cancel();
5772                     },
5773                     scope : this
5774                 };
5775             }
5776             this.el.on(this.autoHideHd);
5777         }
5778     },
5779
5780     // private
5781     clearAutoHide : function(){
5782         if(this.autoHide !== false){
5783             this.el.un("mouseout", this.autoHideHd.mouseout);
5784             this.el.un("mouseover", this.autoHideHd.mouseover);
5785         }
5786     },
5787
5788     // private
5789     clearMonitor : function(){
5790         Ext.getDoc().un("click", this.slideInIf, this);
5791     },
5792
5793     /**
5794      * If this Region is {@link #floatable}, this method slides this Region into full visibility <i>over the top
5795      * of the center Region</i> where it floats until either {@link #slideIn} is called, or other regions of the layout
5796      * are clicked, or the mouse exits the Region.
5797      */
5798     slideOut : function(){
5799         if(this.isSlid || this.el.hasActiveFx()){
5800             return;
5801         }
5802         this.isSlid = true;
5803         var ts = this.panel.tools;
5804         if(ts && ts.toggle){
5805             ts.toggle.hide();
5806         }
5807         this.el.show();
5808         if(this.position == 'east' || this.position == 'west'){
5809             this.panel.setSize(undefined, this.collapsedEl.getHeight());
5810         }else{
5811             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
5812         }
5813         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
5814         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
5815         this.el.setStyle("z-index", this.floatingZIndex+2);
5816         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
5817         if(this.animFloat !== false){
5818             this.beforeSlide();
5819             this.el.slideIn(this.getSlideAnchor(), {
5820                 callback: function(){
5821                     this.afterSlide();
5822                     this.initAutoHide();
5823                     Ext.getDoc().on("click", this.slideInIf, this);
5824                 },
5825                 scope: this,
5826                 block: true
5827             });
5828         }else{
5829             this.initAutoHide();
5830              Ext.getDoc().on("click", this.slideInIf, this);
5831         }
5832     },
5833
5834     // private
5835     afterSlideIn : function(){
5836         this.clearAutoHide();
5837         this.isSlid = false;
5838         this.clearMonitor();
5839         this.el.setStyle("z-index", "");
5840         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
5841         this.el.dom.style.left = this.restoreLT[0];
5842         this.el.dom.style.top = this.restoreLT[1];
5843
5844         var ts = this.panel.tools;
5845         if(ts && ts.toggle){
5846             ts.toggle.show();
5847         }
5848     },
5849
5850     /**
5851      * If this Region is {@link #floatable}, and this Region has been slid into floating visibility, then this method slides
5852      * this region back into its collapsed state.
5853      */
5854     slideIn : function(cb){
5855         if(!this.isSlid || this.el.hasActiveFx()){
5856             Ext.callback(cb);
5857             return;
5858         }
5859         this.isSlid = false;
5860         if(this.animFloat !== false){
5861             this.beforeSlide();
5862             this.el.slideOut(this.getSlideAnchor(), {
5863                 callback: function(){
5864                     this.el.hide();
5865                     this.afterSlide();
5866                     this.afterSlideIn();
5867                     Ext.callback(cb);
5868                 },
5869                 scope: this,
5870                 block: true
5871             });
5872         }else{
5873             this.el.hide();
5874             this.afterSlideIn();
5875         }
5876     },
5877
5878     // private
5879     slideInIf : function(e){
5880         if(!e.within(this.el)){
5881             this.slideIn();
5882         }
5883     },
5884
5885     // private
5886     anchors : {
5887         "west" : "left",
5888         "east" : "right",
5889         "north" : "top",
5890         "south" : "bottom"
5891     },
5892
5893     // private
5894     sanchors : {
5895         "west" : "l",
5896         "east" : "r",
5897         "north" : "t",
5898         "south" : "b"
5899     },
5900
5901     // private
5902     canchors : {
5903         "west" : "tl-tr",
5904         "east" : "tr-tl",
5905         "north" : "tl-bl",
5906         "south" : "bl-tl"
5907     },
5908
5909     // private
5910     getAnchor : function(){
5911         return this.anchors[this.position];
5912     },
5913
5914     // private
5915     getCollapseAnchor : function(){
5916         return this.canchors[this.position];
5917     },
5918
5919     // private
5920     getSlideAnchor : function(){
5921         return this.sanchors[this.position];
5922     },
5923
5924     // private
5925     getAlignAdj : function(){
5926         var cm = this.cmargins;
5927         switch(this.position){
5928             case "west":
5929                 return [0, 0];
5930             break;
5931             case "east":
5932                 return [0, 0];
5933             break;
5934             case "north":
5935                 return [0, 0];
5936             break;
5937             case "south":
5938                 return [0, 0];
5939             break;
5940         }
5941     },
5942
5943     // private
5944     getExpandAdj : function(){
5945         var c = this.collapsedEl, cm = this.cmargins;
5946         switch(this.position){
5947             case "west":
5948                 return [-(cm.right+c.getWidth()+cm.left), 0];
5949             break;
5950             case "east":
5951                 return [cm.right+c.getWidth()+cm.left, 0];
5952             break;
5953             case "north":
5954                 return [0, -(cm.top+cm.bottom+c.getHeight())];
5955             break;
5956             case "south":
5957                 return [0, cm.top+cm.bottom+c.getHeight()];
5958             break;
5959         }
5960     }
5961 };
5962
5963 /**
5964  * @class Ext.layout.BorderLayout.SplitRegion
5965  * @extends Ext.layout.BorderLayout.Region
5966  * <p>This is a specialized type of {@link Ext.layout.BorderLayout.Region BorderLayout region} that
5967  * has a built-in {@link Ext.SplitBar} for user resizing of regions.  The movement of the split bar
5968  * is configurable to move either {@link #tickSize smooth or incrementally}.</p>
5969  * @constructor
5970  * Create a new SplitRegion.
5971  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
5972  * @param {Object} config The configuration options
5973  * @param {String} position The region position.  Valid values are: north, south, east, west and center.  Every
5974  * BorderLayout must have a center region for the primary content -- all other regions are optional.
5975  */
5976 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
5977     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
5978     // prevent switch
5979     this.applyLayout = this.applyFns[pos];
5980 };
5981
5982 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
5983     /**
5984      * @cfg {Number} tickSize
5985      * The increment, in pixels by which to move this Region's {@link Ext.SplitBar SplitBar}.
5986      * By default, the {@link Ext.SplitBar SplitBar} moves smoothly.
5987      */
5988     /**
5989      * @cfg {String} splitTip
5990      * The tooltip to display when the user hovers over a
5991      * {@link Ext.layout.BorderLayout.Region#collapsible non-collapsible} region's split bar
5992      * (defaults to <tt>"Drag to resize."</tt>).  Only applies if
5993      * <tt>{@link #useSplitTips} = true</tt>.
5994      */
5995     splitTip : "Drag to resize.",
5996     /**
5997      * @cfg {String} collapsibleSplitTip
5998      * The tooltip to display when the user hovers over a
5999      * {@link Ext.layout.BorderLayout.Region#collapsible collapsible} region's split bar
6000      * (defaults to "Drag to resize. Double click to hide."). Only applies if
6001      * <tt>{@link #useSplitTips} = true</tt>.
6002      */
6003     collapsibleSplitTip : "Drag to resize. Double click to hide.",
6004     /**
6005      * @cfg {Boolean} useSplitTips
6006      * <tt>true</tt> to display a tooltip when the user hovers over a region's split bar
6007      * (defaults to <tt>false</tt>).  The tooltip text will be the value of either
6008      * <tt>{@link #splitTip}</tt> or <tt>{@link #collapsibleSplitTip}</tt> as appropriate.
6009      */
6010     useSplitTips : false,
6011
6012     // private
6013     splitSettings : {
6014         north : {
6015             orientation: Ext.SplitBar.VERTICAL,
6016             placement: Ext.SplitBar.TOP,
6017             maxFn : 'getVMaxSize',
6018             minProp: 'minHeight',
6019             maxProp: 'maxHeight'
6020         },
6021         south : {
6022             orientation: Ext.SplitBar.VERTICAL,
6023             placement: Ext.SplitBar.BOTTOM,
6024             maxFn : 'getVMaxSize',
6025             minProp: 'minHeight',
6026             maxProp: 'maxHeight'
6027         },
6028         east : {
6029             orientation: Ext.SplitBar.HORIZONTAL,
6030             placement: Ext.SplitBar.RIGHT,
6031             maxFn : 'getHMaxSize',
6032             minProp: 'minWidth',
6033             maxProp: 'maxWidth'
6034         },
6035         west : {
6036             orientation: Ext.SplitBar.HORIZONTAL,
6037             placement: Ext.SplitBar.LEFT,
6038             maxFn : 'getHMaxSize',
6039             minProp: 'minWidth',
6040             maxProp: 'maxWidth'
6041         }
6042     },
6043
6044     // private
6045     applyFns : {
6046         west : function(box){
6047             if(this.isCollapsed){
6048                 return this.applyLayoutCollapsed(box);
6049             }
6050             var sd = this.splitEl.dom, s = sd.style;
6051             this.panel.setPosition(box.x, box.y);
6052             var sw = sd.offsetWidth;
6053             s.left = (box.x+box.width-sw)+'px';
6054             s.top = (box.y)+'px';
6055             s.height = Math.max(0, box.height)+'px';
6056             this.panel.setSize(box.width-sw, box.height);
6057         },
6058         east : function(box){
6059             if(this.isCollapsed){
6060                 return this.applyLayoutCollapsed(box);
6061             }
6062             var sd = this.splitEl.dom, s = sd.style;
6063             var sw = sd.offsetWidth;
6064             this.panel.setPosition(box.x+sw, box.y);
6065             s.left = (box.x)+'px';
6066             s.top = (box.y)+'px';
6067             s.height = Math.max(0, box.height)+'px';
6068             this.panel.setSize(box.width-sw, box.height);
6069         },
6070         north : function(box){
6071             if(this.isCollapsed){
6072                 return this.applyLayoutCollapsed(box);
6073             }
6074             var sd = this.splitEl.dom, s = sd.style;
6075             var sh = sd.offsetHeight;
6076             this.panel.setPosition(box.x, box.y);
6077             s.left = (box.x)+'px';
6078             s.top = (box.y+box.height-sh)+'px';
6079             s.width = Math.max(0, box.width)+'px';
6080             this.panel.setSize(box.width, box.height-sh);
6081         },
6082         south : function(box){
6083             if(this.isCollapsed){
6084                 return this.applyLayoutCollapsed(box);
6085             }
6086             var sd = this.splitEl.dom, s = sd.style;
6087             var sh = sd.offsetHeight;
6088             this.panel.setPosition(box.x, box.y+sh);
6089             s.left = (box.x)+'px';
6090             s.top = (box.y)+'px';
6091             s.width = Math.max(0, box.width)+'px';
6092             this.panel.setSize(box.width, box.height-sh);
6093         }
6094     },
6095
6096     // private
6097     render : function(ct, p){
6098         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
6099
6100         var ps = this.position;
6101
6102         this.splitEl = ct.createChild({
6103             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
6104             id: this.panel.id + '-xsplit'
6105         });
6106
6107         if(this.collapseMode == 'mini'){
6108             this.miniSplitEl = this.splitEl.createChild({
6109                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
6110             });
6111             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
6112             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
6113         }
6114
6115         var s = this.splitSettings[ps];
6116
6117         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
6118         this.split.tickSize = this.tickSize;
6119         this.split.placement = s.placement;
6120         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
6121         this.split.minSize = this.minSize || this[s.minProp];
6122         this.split.on("beforeapply", this.onSplitMove, this);
6123         this.split.useShim = this.useShim === true;
6124         this.maxSize = this.maxSize || this[s.maxProp];
6125
6126         if(p.hidden){
6127             this.splitEl.hide();
6128         }
6129
6130         if(this.useSplitTips){
6131             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
6132         }
6133         if(this.collapsible){
6134             this.splitEl.on("dblclick", this.onCollapseClick,  this);
6135         }
6136     },
6137
6138     //docs inherit from superclass
6139     getSize : function(){
6140         if(this.isCollapsed){
6141             return this.collapsedEl.getSize();
6142         }
6143         var s = this.panel.getSize();
6144         if(this.position == 'north' || this.position == 'south'){
6145             s.height += this.splitEl.dom.offsetHeight;
6146         }else{
6147             s.width += this.splitEl.dom.offsetWidth;
6148         }
6149         return s;
6150     },
6151
6152     // private
6153     getHMaxSize : function(){
6154          var cmax = this.maxSize || 10000;
6155          var center = this.layout.center;
6156          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
6157     },
6158
6159     // private
6160     getVMaxSize : function(){
6161         var cmax = this.maxSize || 10000;
6162         var center = this.layout.center;
6163         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
6164     },
6165
6166     // private
6167     onSplitMove : function(split, newSize){
6168         var s = this.panel.getSize();
6169         this.lastSplitSize = newSize;
6170         if(this.position == 'north' || this.position == 'south'){
6171             this.panel.setSize(s.width, newSize);
6172             this.state.height = newSize;
6173         }else{
6174             this.panel.setSize(newSize, s.height);
6175             this.state.width = newSize;
6176         }
6177         this.layout.layout();
6178         this.panel.saveState();
6179         return false;
6180     },
6181
6182     /**
6183      * Returns a reference to the split bar in use by this region.
6184      * @return {Ext.SplitBar} The split bar
6185      */
6186     getSplitBar : function(){
6187         return this.split;
6188     },
6189
6190     // inherit docs
6191     destroy : function() {
6192         Ext.destroy(
6193             this.miniSplitEl,
6194             this.split,
6195             this.splitEl
6196         );
6197     }
6198 });
6199
6200 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;/**
6201  * @class Ext.layout.FormLayout
6202  * @extends Ext.layout.AnchorLayout
6203  * <p>This layout manager is specifically designed for rendering and managing child Components of
6204  * {@link Ext.form.FormPanel forms}. It is responsible for rendering the labels of
6205  * {@link Ext.form.Field Field}s.</p>
6206  *
6207  * <p>This layout manager is used when a Container is configured with the <tt>layout:'form'</tt>
6208  * {@link Ext.Container#layout layout} config option, and should generally not need to be created directly
6209  * via the new keyword. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
6210  *
6211  * <p>In an application, it will usually be preferrable to use a {@link Ext.form.FormPanel FormPanel}
6212  * (which is configured with FormLayout as its layout class by default) since it also provides built-in
6213  * functionality for {@link Ext.form.BasicForm#doAction loading, validating and submitting} the form.</p>
6214  *
6215  * <p>A {@link Ext.Container Container} <i>using</i> the FormLayout layout manager (e.g.
6216  * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) can also accept the following
6217  * layout-specific config properties:<div class="mdetail-params"><ul>
6218  * <li><b><tt>{@link Ext.form.FormPanel#hideLabels hideLabels}</tt></b></li>
6219  * <li><b><tt>{@link Ext.form.FormPanel#labelAlign labelAlign}</tt></b></li>
6220  * <li><b><tt>{@link Ext.form.FormPanel#labelPad labelPad}</tt></b></li>
6221  * <li><b><tt>{@link Ext.form.FormPanel#labelSeparator labelSeparator}</tt></b></li>
6222  * <li><b><tt>{@link Ext.form.FormPanel#labelWidth labelWidth}</tt></b></li>
6223  * </ul></div></p>
6224  *
6225  * <p>Any Component (including Fields) managed by FormLayout accepts the following as a config option:
6226  * <div class="mdetail-params"><ul>
6227  * <li><b><tt>{@link Ext.Component#anchor anchor}</tt></b></li>
6228  * </ul></div></p>
6229  *
6230  * <p>Any Component managed by FormLayout may be rendered as a form field (with an associated label) by
6231  * configuring it with a non-null <b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b>. Components configured
6232  * in this way may be configured with the following options which affect the way the FormLayout renders them:
6233  * <div class="mdetail-params"><ul>
6234  * <li><b><tt>{@link Ext.Component#clearCls clearCls}</tt></b></li>
6235  * <li><b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b></li>
6236  * <li><b><tt>{@link Ext.Component#hideLabel hideLabel}</tt></b></li>
6237  * <li><b><tt>{@link Ext.Component#itemCls itemCls}</tt></b></li>
6238  * <li><b><tt>{@link Ext.Component#labelSeparator labelSeparator}</tt></b></li>
6239  * <li><b><tt>{@link Ext.Component#labelStyle labelStyle}</tt></b></li>
6240  * </ul></div></p>
6241  *
6242  * <p>Example usage:</p>
6243  * <pre><code>
6244 // Required if showing validation messages
6245 Ext.QuickTips.init();
6246
6247 // While you can create a basic Panel with layout:'form', practically
6248 // you should usually use a FormPanel to also get its form functionality
6249 // since it already creates a FormLayout internally.
6250 var form = new Ext.form.FormPanel({
6251     title: 'Form Layout',
6252     bodyStyle: 'padding:15px',
6253     width: 350,
6254     defaultType: 'textfield',
6255     defaults: {
6256         // applied to each contained item
6257         width: 230,
6258         msgTarget: 'side'
6259     },
6260     items: [{
6261             fieldLabel: 'First Name',
6262             name: 'first',
6263             allowBlank: false,
6264             {@link Ext.Component#labelSeparator labelSeparator}: ':' // override labelSeparator layout config
6265         },{
6266             fieldLabel: 'Last Name',
6267             name: 'last'
6268         },{
6269             fieldLabel: 'Email',
6270             name: 'email',
6271             vtype:'email'
6272         }, {
6273             xtype: 'textarea',
6274             hideLabel: true,     // override hideLabels layout config
6275             name: 'msg',
6276             anchor: '100% -53'
6277         }
6278     ],
6279     buttons: [
6280         {text: 'Save'},
6281         {text: 'Cancel'}
6282     ],
6283     layoutConfig: {
6284         {@link #labelSeparator}: '~' // superseded by assignment below
6285     },
6286     // config options applicable to container when layout='form':
6287     hideLabels: false,
6288     labelAlign: 'left',   // or 'right' or 'top'
6289     {@link Ext.form.FormPanel#labelSeparator labelSeparator}: '>>', // takes precedence over layoutConfig value
6290     labelWidth: 65,       // defaults to 100
6291     labelPad: 8           // defaults to 5, must specify labelWidth to be honored
6292 });
6293 </code></pre>
6294  */
6295 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
6296
6297     /**
6298      * @cfg {String} labelSeparator
6299      * See {@link Ext.form.FormPanel}.{@link Ext.form.FormPanel#labelSeparator labelSeparator}.  Configuration
6300      * of this property at the <b>container</b> level takes precedence.
6301      */
6302     labelSeparator : ':',
6303
6304     /**
6305      * Read only. The CSS style specification string added to field labels in this layout if not
6306      * otherwise {@link Ext.Component#labelStyle specified by each contained field}.
6307      * @type String
6308      * @property labelStyle
6309      */
6310
6311     // private
6312     setContainer : function(ct){
6313         Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
6314         if(ct.labelAlign){
6315             ct.addClass('x-form-label-'+ct.labelAlign);
6316         }
6317
6318         if(ct.hideLabels){
6319             this.labelStyle = "display:none";
6320             this.elementStyle = "padding-left:0;";
6321             this.labelAdjust = 0;
6322         }else{
6323             this.labelSeparator = ct.labelSeparator || this.labelSeparator;
6324             ct.labelWidth = ct.labelWidth || 100;
6325             if(typeof ct.labelWidth == 'number'){
6326                 var pad = (typeof ct.labelPad == 'number' ? ct.labelPad : 5);
6327                 this.labelAdjust = ct.labelWidth+pad;
6328                 this.labelStyle = "width:"+ct.labelWidth+"px;";
6329                 this.elementStyle = "padding-left:"+(ct.labelWidth+pad)+'px';
6330             }
6331             if(ct.labelAlign == 'top'){
6332                 this.labelStyle = "width:auto;";
6333                 this.labelAdjust = 0;
6334                 this.elementStyle = "padding-left:0;";
6335             }
6336         }
6337     },
6338
6339     //private
6340     getLabelStyle: function(s){
6341         var ls = '', items = [this.labelStyle, s];
6342         for (var i = 0, len = items.length; i < len; ++i){
6343             if (items[i]){
6344                 ls += items[i];
6345                 if (ls.substr(-1, 1) != ';'){
6346                     ls += ';'
6347                 }
6348             }
6349         }
6350         return ls;
6351     },
6352
6353     /**
6354      * @cfg {Ext.Template} fieldTpl
6355      * A {@link Ext.Template#compile compile}d {@link Ext.Template} for rendering
6356      * the fully wrapped, labeled and styled form Field. Defaults to:</p><pre><code>
6357 new Ext.Template(
6358     &#39;&lt;div class="x-form-item {itemCls}" tabIndex="-1">&#39;,
6359         &#39;&lt;&#108;abel for="{id}" style="{labelStyle}" class="x-form-item-&#108;abel">{&#108;abel}{labelSeparator}&lt;/&#108;abel>&#39;,
6360         &#39;&lt;div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">&#39;,
6361         &#39;&lt;/div>&lt;div class="{clearCls}">&lt;/div>&#39;,
6362     '&lt;/div>'
6363 );
6364 </code></pre>
6365      * <p>This may be specified to produce a different DOM structure when rendering form Fields.</p>
6366      * <p>A description of the properties within the template follows:</p><div class="mdetail-params"><ul>
6367      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
6368      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
6369      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
6370      * supplied at the container level.</div></li>
6371      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
6372      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
6373      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
6374      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
6375      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
6376      * field (defaults to <tt>''</tt>)</div></li>
6377      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
6378      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
6379      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
6380      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
6381      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
6382      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
6383      * </ul></div>
6384      * <p>Also see <tt>{@link #getTemplateArgs}</tt></p>
6385      */
6386
6387     // private
6388     renderItem : function(c, position, target){
6389         if(c && !c.rendered && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
6390             var args = this.getTemplateArgs(c);
6391             if(typeof position == 'number'){
6392                 position = target.dom.childNodes[position] || null;
6393             }
6394             if(position){
6395                 this.fieldTpl.insertBefore(position, args);
6396             }else{
6397                 this.fieldTpl.append(target, args);
6398             }
6399             c.render('x-form-el-'+c.id);
6400         }else {
6401             Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
6402         }
6403     },
6404
6405     /**
6406      * <p>Provides template arguments for rendering the fully wrapped, labeled and styled form Field.</p>
6407      * <p>This method returns an object hash containing properties used by the layout's {@link #fieldTpl}
6408      * to create a correctly wrapped, labeled and styled form Field. This may be overriden to
6409      * create custom layouts. The properties which must be returned are:</p><div class="mdetail-params"><ul>
6410      * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
6411      * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
6412      * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
6413      * supplied at the container level.</div></li>
6414      * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
6415      * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
6416      * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
6417      * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
6418      * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
6419      * field (defaults to <tt>''</tt>)</div></li>
6420      * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
6421      * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
6422      * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
6423      * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
6424      * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
6425      * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
6426      * </ul></div>
6427      * @param field The {@link Field Ext.form.Field} being rendered.
6428      * @return An object hash containing the properties required to render the Field.
6429      */
6430     getTemplateArgs: function(field) {
6431         var noLabelSep = !field.fieldLabel || field.hideLabel;
6432         return {
6433             id: field.id,
6434             label: field.fieldLabel,
6435             labelStyle: field.labelStyle||this.labelStyle||'',
6436             elementStyle: this.elementStyle||'',
6437             labelSeparator: noLabelSep ? '' : (typeof field.labelSeparator == 'undefined' ? this.labelSeparator : field.labelSeparator),
6438             itemCls: (field.itemCls||this.container.itemCls||'') + (field.hideLabel ? ' x-hide-label' : ''),
6439             clearCls: field.clearCls || 'x-form-clear-left'
6440         };
6441     },
6442
6443     // private
6444     adjustWidthAnchor : function(value, comp){
6445         return value - (comp.isFormField || comp.fieldLabel  ? (comp.hideLabel ? 0 : this.labelAdjust) : 0);
6446     },
6447
6448     // private
6449     isValidParent : function(c, target){
6450         return true;
6451     }
6452
6453     /**
6454      * @property activeItem
6455      * @hide
6456      */
6457 });
6458
6459 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;/**\r
6460  * @class Ext.layout.AccordionLayout\r
6461  * @extends Ext.layout.FitLayout\r
6462  * <p>This is a layout that contains multiple panels in an expandable accordion style such that only\r
6463  * <b>one panel can be open at any given time</b>.  Each panel has built-in support for expanding and collapsing.\r
6464  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>\r
6465  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>\r
6466  * <p>Example usage:</p>\r
6467  * <pre><code>\r
6468 var accordion = new Ext.Panel({\r
6469     title: 'Accordion Layout',\r
6470     layout:'accordion',\r
6471     defaults: {\r
6472         // applied to each contained panel\r
6473         bodyStyle: 'padding:15px'\r
6474     },\r
6475     layoutConfig: {\r
6476         // layout-specific configs go here\r
6477         titleCollapse: false,\r
6478         animate: true,\r
6479         activeOnTop: true\r
6480     },\r
6481     items: [{\r
6482         title: 'Panel 1',\r
6483         html: '&lt;p&gt;Panel content!&lt;/p&gt;'\r
6484     },{\r
6485         title: 'Panel 2',\r
6486         html: '&lt;p&gt;Panel content!&lt;/p&gt;'\r
6487     },{\r
6488         title: 'Panel 3',\r
6489         html: '&lt;p&gt;Panel content!&lt;/p&gt;'\r
6490     }]\r
6491 });\r
6492 </code></pre>\r
6493  */\r
6494 Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {\r
6495     /**\r
6496      * @cfg {Boolean} fill\r
6497      * True to adjust the active item's height to fill the available space in the container, false to use the\r
6498      * item's current height, or auto height if not explicitly set (defaults to true).\r
6499      */\r
6500     fill : true,\r
6501     /**\r
6502      * @cfg {Boolean} autoWidth\r
6503      * True to set each contained item's width to 'auto', false to use the item's current width (defaults to true).\r
6504      * Note that some components, in particular the {@link Ext.grid.GridPanel grid}, will not function properly within\r
6505      * layouts if they have auto width, so in such cases this config should be set to false.\r
6506      */\r
6507     autoWidth : true,\r
6508     /**\r
6509      * @cfg {Boolean} titleCollapse\r
6510      * True to allow expand/collapse of each contained panel by clicking anywhere on the title bar, false to allow\r
6511      * expand/collapse only when the toggle tool button is clicked (defaults to true).  When set to false,\r
6512      * {@link #hideCollapseTool} should be false also.\r
6513      */\r
6514     titleCollapse : true,\r
6515     /**\r
6516      * @cfg {Boolean} hideCollapseTool\r
6517      * True to hide the contained panels' collapse/expand toggle buttons, false to display them (defaults to false).\r
6518      * When set to true, {@link #titleCollapse} should be true also.\r
6519      */\r
6520     hideCollapseTool : false,\r
6521     /**\r
6522      * @cfg {Boolean} collapseFirst\r
6523      * True to make sure the collapse/expand toggle button always renders first (to the left of) any other tools\r
6524      * in the contained panels' title bars, false to render it last (defaults to false).\r
6525      */\r
6526     collapseFirst : false,\r
6527     /**\r
6528      * @cfg {Boolean} animate\r
6529      * True to slide the contained panels open and closed during expand/collapse using animation, false to open and\r
6530      * close directly with no animation (defaults to false).  Note: to defer to the specific config setting of each\r
6531      * contained panel for this property, set this to undefined at the layout level.\r
6532      */\r
6533     animate : false,\r
6534     /**\r
6535      * @cfg {Boolean} sequence\r
6536      * <b>Experimental</b>. If animate is set to true, this will result in each animation running in sequence.\r
6537      */\r
6538     sequence : false,\r
6539     /**\r
6540      * @cfg {Boolean} activeOnTop\r
6541      * True to swap the position of each panel as it is expanded so that it becomes the first item in the container,\r
6542      * false to keep the panels in the rendered order. <b>This is NOT compatible with "animate:true"</b> (defaults to false).\r
6543      */\r
6544     activeOnTop : false,\r
6545 \r
6546     renderItem : function(c){\r
6547         if(this.animate === false){\r
6548             c.animCollapse = false;\r
6549         }\r
6550         c.collapsible = true;\r
6551         if(this.autoWidth){\r
6552             c.autoWidth = true;\r
6553         }\r
6554         if(this.titleCollapse){\r
6555             c.titleCollapse = true;\r
6556         }\r
6557         if(this.hideCollapseTool){\r
6558             c.hideCollapseTool = true;\r
6559         }\r
6560         if(this.collapseFirst !== undefined){\r
6561             c.collapseFirst = this.collapseFirst;\r
6562         }\r
6563         if(!this.activeItem && !c.collapsed){\r
6564             this.activeItem = c;\r
6565         }else if(this.activeItem && this.activeItem != c){\r
6566             c.collapsed = true;\r
6567         }\r
6568         Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);\r
6569         c.header.addClass('x-accordion-hd');\r
6570         c.on('beforeexpand', this.beforeExpand, this);\r
6571     },\r
6572 \r
6573     // private\r
6574     beforeExpand : function(p, anim){\r
6575         var ai = this.activeItem;\r
6576         if(ai){\r
6577             if(this.sequence){\r
6578                 delete this.activeItem;\r
6579                 if (!ai.collapsed){\r
6580                     ai.collapse({callback:function(){\r
6581                         p.expand(anim || true);\r
6582                     }, scope: this});\r
6583                     return false;\r
6584                 }\r
6585             }else{\r
6586                 ai.collapse(this.animate);\r
6587             }\r
6588         }\r
6589         this.activeItem = p;\r
6590         if(this.activeOnTop){\r
6591             p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);\r
6592         }\r
6593         this.layout();\r
6594     },\r
6595 \r
6596     // private\r
6597     setItemSize : function(item, size){\r
6598         if(this.fill && item){\r
6599             var hh = 0;\r
6600             this.container.items.each(function(p){\r
6601                 if(p != item){\r
6602                     hh += p.header.getHeight();\r
6603                 }    \r
6604             });\r
6605             size.height -= hh;\r
6606             item.setSize(size);\r
6607         }\r
6608     },\r
6609 \r
6610     /**\r
6611      * Sets the active (expanded) item in the layout.\r
6612      * @param {String/Number} item The string component id or numeric index of the item to activate\r
6613      */\r
6614     setActiveItem : function(item){\r
6615         item = this.container.getComponent(item);\r
6616         if(this.activeItem != item){\r
6617             if(item.rendered && item.collapsed){\r
6618                 item.expand();\r
6619             }else{\r
6620                 this.activeItem = item;\r
6621             }\r
6622         }\r
6623 \r
6624     }\r
6625 });\r
6626 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;\r
6627 \r
6628 //backwards compat\r
6629 Ext.layout.Accordion = Ext.layout.AccordionLayout;/**\r
6630  * @class Ext.layout.TableLayout\r
6631  * @extends Ext.layout.ContainerLayout\r
6632  * <p>This layout allows you to easily render content into an HTML table.  The total number of columns can be\r
6633  * specified, and rowspan and colspan can be used to create complex layouts within the table.\r
6634  * This class is intended to be extended or created via the layout:'table' {@link Ext.Container#layout} config,\r
6635  * and should generally not need to be created directly via the new keyword.</p>\r
6636  * <p>Note that when creating a layout via config, the layout-specific config properties must be passed in via\r
6637  * the {@link Ext.Container#layoutConfig} object which will then be applied internally to the layout.  In the\r
6638  * case of TableLayout, the only valid layout config property is {@link #columns}.  However, the items added to a\r
6639  * TableLayout can supply the following table-specific config properties:</p>\r
6640  * <ul>\r
6641  * <li><b>rowspan</b> Applied to the table cell containing the item.</li>\r
6642  * <li><b>colspan</b> Applied to the table cell containing the item.</li>\r
6643  * <li><b>cellId</b> An id applied to the table cell containing the item.</li>\r
6644  * <li><b>cellCls</b> A CSS class name added to the table cell containing the item.</li>\r
6645  * </ul>\r
6646  * <p>The basic concept of building up a TableLayout is conceptually very similar to building up a standard\r
6647  * HTML table.  You simply add each panel (or "cell") that you want to include along with any span attributes\r
6648  * specified as the special config properties of rowspan and colspan which work exactly like their HTML counterparts.\r
6649  * Rather than explicitly creating and nesting rows and columns as you would in HTML, you simply specify the\r
6650  * total column count in the layoutConfig and start adding panels in their natural order from left to right,\r
6651  * top to bottom.  The layout will automatically figure out, based on the column count, rowspans and colspans,\r
6652  * how to position each panel within the table.  Just like with HTML tables, your rowspans and colspans must add\r
6653  * up correctly in your overall layout or you'll end up with missing and/or extra cells!  Example usage:</p>\r
6654  * <pre><code>\r
6655 // This code will generate a layout table that is 3 columns by 2 rows\r
6656 // with some spanning included.  The basic layout will be:\r
6657 // +--------+-----------------+\r
6658 // |   A    |   B             |\r
6659 // |        |--------+--------|\r
6660 // |        |   C    |   D    |\r
6661 // +--------+--------+--------+\r
6662 var table = new Ext.Panel({\r
6663     title: 'Table Layout',\r
6664     layout:'table',\r
6665     defaults: {\r
6666         // applied to each contained panel\r
6667         bodyStyle:'padding:20px'\r
6668     },\r
6669     layoutConfig: {\r
6670         // The total column count must be specified here\r
6671         columns: 3\r
6672     },\r
6673     items: [{\r
6674         html: '&lt;p&gt;Cell A content&lt;/p&gt;',\r
6675         rowspan: 2\r
6676     },{\r
6677         html: '&lt;p&gt;Cell B content&lt;/p&gt;',\r
6678         colspan: 2\r
6679     },{\r
6680         html: '&lt;p&gt;Cell C content&lt;/p&gt;',\r
6681         cellCls: 'highlight'\r
6682     },{\r
6683         html: '&lt;p&gt;Cell D content&lt;/p&gt;'\r
6684     }]\r
6685 });\r
6686 </code></pre>\r
6687  */\r
6688 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
6689     /**\r
6690      * @cfg {Number} columns\r
6691      * The total number of columns to create in the table for this layout.  If not specified, all Components added to\r
6692      * this layout will be rendered into a single row using one column per Component.\r
6693      */\r
6694 \r
6695     // private\r
6696     monitorResize:false,\r
6697 \r
6698     /**\r
6699      * @cfg {Object} tableAttrs\r
6700      * <p>An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification\r
6701      * used to create the layout's <tt>&lt;table&gt;</tt> element. Example:</p><pre><code>\r
6702 {\r
6703     xtype: 'panel',\r
6704     layout: 'table',\r
6705     layoutConfig: {\r
6706         tableAttrs: {\r
6707                 style: {\r
6708                         width: '100%'\r
6709                 }\r
6710         },\r
6711         columns: 3\r
6712     }\r
6713 }</code></pre>\r
6714      */\r
6715     tableAttrs:null,\r
6716     \r
6717     // private\r
6718     setContainer : function(ct){\r
6719         Ext.layout.TableLayout.superclass.setContainer.call(this, ct);\r
6720 \r
6721         this.currentRow = 0;\r
6722         this.currentColumn = 0;\r
6723         this.cells = [];\r
6724     },\r
6725 \r
6726     // private\r
6727     onLayout : function(ct, target){\r
6728         var cs = ct.items.items, len = cs.length, c, i;\r
6729 \r
6730         if(!this.table){\r
6731             target.addClass('x-table-layout-ct');\r
6732 \r
6733             this.table = target.createChild(\r
6734                 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);\r
6735         }\r
6736         this.renderAll(ct, target);\r
6737     },\r
6738 \r
6739     // private\r
6740     getRow : function(index){\r
6741         var row = this.table.tBodies[0].childNodes[index];\r
6742         if(!row){\r
6743             row = document.createElement('tr');\r
6744             this.table.tBodies[0].appendChild(row);\r
6745         }\r
6746         return row;\r
6747     },\r
6748 \r
6749     // private\r
6750     getNextCell : function(c){\r
6751         var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);\r
6752         var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];\r
6753         for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){\r
6754             if(!this.cells[rowIndex]){\r
6755                 this.cells[rowIndex] = [];\r
6756             }\r
6757             for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){\r
6758                 this.cells[rowIndex][colIndex] = true;\r
6759             }\r
6760         }\r
6761         var td = document.createElement('td');\r
6762         if(c.cellId){\r
6763             td.id = c.cellId;\r
6764         }\r
6765         var cls = 'x-table-layout-cell';\r
6766         if(c.cellCls){\r
6767             cls += ' ' + c.cellCls;\r
6768         }\r
6769         td.className = cls;\r
6770         if(c.colspan){\r
6771             td.colSpan = c.colspan;\r
6772         }\r
6773         if(c.rowspan){\r
6774             td.rowSpan = c.rowspan;\r
6775         }\r
6776         this.getRow(curRow).appendChild(td);\r
6777         return td;\r
6778     },\r
6779     \r
6780     // private\r
6781     getNextNonSpan: function(colIndex, rowIndex){\r
6782         var cols = this.columns;\r
6783         while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {\r
6784             if(cols && colIndex >= cols){\r
6785                 rowIndex++;\r
6786                 colIndex = 0;\r
6787             }else{\r
6788                 colIndex++;\r
6789             }\r
6790         }\r
6791         return [colIndex, rowIndex];\r
6792     },\r
6793 \r
6794     // private\r
6795     renderItem : function(c, position, target){\r
6796         if(c && !c.rendered){\r
6797             c.render(this.getNextCell(c));\r
6798             if(this.extraCls){\r
6799                 var t = c.getPositionEl ? c.getPositionEl() : c;\r
6800                 t.addClass(this.extraCls);\r
6801             }\r
6802         }\r
6803     },\r
6804 \r
6805     // private\r
6806     isValidParent : function(c, target){\r
6807         return true;\r
6808     }\r
6809 \r
6810     /**\r
6811      * @property activeItem\r
6812      * @hide\r
6813      */\r
6814 });\r
6815 \r
6816 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;/**\r
6817  * @class Ext.layout.AbsoluteLayout\r
6818  * @extends Ext.layout.AnchorLayout\r
6819  * <p>This is a layout that inherits the anchoring of <b>{@link Ext.layout.AnchorLayout}</b> and adds the\r
6820  * ability for x/y positioning using the standard x and y component config options.</p>\r
6821  * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>\r
6822  * configuration property.  See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>\r
6823  * <p>Example usage:</p>\r
6824  * <pre><code>\r
6825 var form = new Ext.form.FormPanel({\r
6826     title: 'Absolute Layout',\r
6827     layout:'absolute',\r
6828     layoutConfig: {\r
6829         // layout-specific configs go here\r
6830         extraCls: 'x-abs-layout-item',\r
6831     },\r
6832     baseCls: 'x-plain',\r
6833     url:'save-form.php',\r
6834     defaultType: 'textfield',\r
6835     items: [{\r
6836         x: 0,\r
6837         y: 5,\r
6838         xtype:'label',\r
6839         text: 'Send To:'\r
6840     },{\r
6841         x: 60,\r
6842         y: 0,\r
6843         name: 'to',\r
6844         anchor:'100%'  // anchor width by percentage\r
6845     },{\r
6846         x: 0,\r
6847         y: 35,\r
6848         xtype:'label',\r
6849         text: 'Subject:'\r
6850     },{\r
6851         x: 60,\r
6852         y: 30,\r
6853         name: 'subject',\r
6854         anchor: '100%'  // anchor width by percentage\r
6855     },{\r
6856         x:0,\r
6857         y: 60,\r
6858         xtype: 'textarea',\r
6859         name: 'msg',\r
6860         anchor: '100% 100%'  // anchor width and height\r
6861     }]\r
6862 });\r
6863 </code></pre>\r
6864  */\r
6865 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {\r
6866 \r
6867     extraCls: 'x-abs-layout-item',\r
6868 \r
6869     onLayout : function(ct, target){\r
6870         target.position();\r
6871         this.paddingLeft = target.getPadding('l');\r
6872         this.paddingTop = target.getPadding('t');\r
6873 \r
6874         Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);\r
6875     },\r
6876 \r
6877     // private\r
6878     adjustWidthAnchor : function(value, comp){\r
6879         return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;\r
6880     },\r
6881 \r
6882     // private\r
6883     adjustHeightAnchor : function(value, comp){\r
6884         return  value ? value - comp.getPosition(true)[1] + this.paddingTop : value;\r
6885     }\r
6886     /**\r
6887      * @property activeItem\r
6888      * @hide\r
6889      */\r
6890 });\r
6891 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
6892 /**\r
6893  * @class Ext.layout.BoxLayout\r
6894  * @extends Ext.layout.ContainerLayout\r
6895  * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>\r
6896  */\r
6897 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
6898     /**\r
6899      * @cfg {Object} defaultMargins\r
6900      * <p>If the individual contained items do not have a <tt>margins</tt>\r
6901      * property specified, the default margins from this property will be\r
6902      * applied to each item.</p>\r
6903      * <br><p>This property may be specified as an object containing margins\r
6904      * to apply in the format:</p><pre><code>\r
6905 {\r
6906     top: (top margin),\r
6907     right: (right margin),\r
6908     bottom: (bottom margin),\r
6909     left: (left margin)\r
6910 }</code></pre>\r
6911      * <p>This property may also be specified as a string containing\r
6912      * space-separated, numeric margin values. The order of the sides associated\r
6913      * with each value matches the way CSS processes margin values:</p>\r
6914      * <div class="mdetail-params"><ul>\r
6915      * <li>If there is only one value, it applies to all sides.</li>\r
6916      * <li>If there are two values, the top and bottom borders are set to the\r
6917      * first value and the right and left are set to the second.</li>\r
6918      * <li>If there are three values, the top is set to the first value, the left\r
6919      * and right are set to the second, and the bottom is set to the third.</li>\r
6920      * <li>If there are four values, they apply to the top, right, bottom, and\r
6921      * left, respectively.</li>\r
6922      * </ul></div>\r
6923      * <p>Defaults to:</p><pre><code>\r
6924      * {top:0, right:0, bottom:0, left:0}\r
6925      * </code></pre>\r
6926      */\r
6927     defaultMargins : {left:0,top:0,right:0,bottom:0},\r
6928     /**\r
6929      * @cfg {String} padding\r
6930      * Defaults to <tt>'0'</tt>. Sets the padding to be applied to all child items managed by this\r
6931      * container's layout. \r
6932      */\r
6933     padding : '0',\r
6934     // documented in subclasses\r
6935     pack : 'start',\r
6936 \r
6937     // private\r
6938     monitorResize : true,\r
6939     scrollOffset : 0,\r
6940     extraCls : 'x-box-item',\r
6941     ctCls : 'x-box-layout-ct',\r
6942     innerCls : 'x-box-inner',\r
6943 \r
6944     // private\r
6945     isValidParent : function(c, target){\r
6946         return c.getEl().dom.parentNode == this.innerCt.dom;\r
6947     },\r
6948 \r
6949     // private\r
6950     onLayout : function(ct, target){\r
6951         var cs = ct.items.items, len = cs.length, c, i, last = len-1, cm;\r
6952 \r
6953         if(!this.innerCt){\r
6954             target.addClass(this.ctCls);\r
6955 \r
6956             // the innerCt prevents wrapping and shuffling while\r
6957             // the container is resizing\r
6958             this.innerCt = target.createChild({cls:this.innerCls});\r
6959             this.padding = this.parseMargins(this.padding); \r
6960         }\r
6961         this.renderAll(ct, this.innerCt);\r
6962     },\r
6963 \r
6964     // private\r
6965     renderItem : function(c){\r
6966         if(typeof c.margins == 'string'){\r
6967             c.margins = this.parseMargins(c.margins);\r
6968         }else if(!c.margins){\r
6969             c.margins = this.defaultMargins;\r
6970         }\r
6971         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);\r
6972     },\r
6973 \r
6974     getTargetSize : function(target){
6975         return (Ext.isIE6 && Ext.isStrict && target.dom == document.body) ? target.getStyleSize() : target.getViewSize();\r
6976     },\r
6977     \r
6978     getItems: function(ct){\r
6979         var items = [];\r
6980         ct.items.each(function(c){\r
6981             if(c.isVisible()){\r
6982                 items.push(c);\r
6983             }\r
6984         });\r
6985         return items;\r
6986     }\r
6987 \r
6988     /**\r
6989      * @property activeItem\r
6990      * @hide\r
6991      */\r
6992 });\r
6993 \r
6994 /**\r
6995  * @class Ext.layout.VBoxLayout\r
6996  * @extends Ext.layout.BoxLayout\r
6997  * A layout that arranges items vertically\r
6998  */\r
6999 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {\r
7000     /**\r
7001      * @cfg {String} align\r
7002      * Controls how the child items of the container are aligned. Acceptable configuration values for this\r
7003      * property are:\r
7004      * <div class="mdetail-params"><ul>\r
7005      * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally\r
7006      * at the <b>left</b> side of the container</div></li>\r
7007      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the\r
7008      * <b>mid-width</b> of the container</div></li>\r
7009      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill\r
7010      * the width of the container</div></li>\r
7011      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to\r
7012      * the size of the largest item.</div></li>\r
7013      * </ul></div>\r
7014      */\r
7015     align : 'left', // left, center, stretch, strechmax\r
7016     /**\r
7017      * @cfg {String} pack\r
7018      * Controls how the child items of the container are packed together. Acceptable configuration values\r
7019      * for this property are:\r
7020      * <div class="mdetail-params"><ul>\r
7021      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at\r
7022      * <b>top</b> side of container</div></li>\r
7023      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at\r
7024      * <b>mid-height</b> of container</div></li>\r
7025      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>\r
7026      * side of container</div></li>\r
7027      * </ul></div>\r
7028      */\r
7029     /**\r
7030      * @cfg {Number} flex\r
7031      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed\r
7032      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>\r
7033      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with\r
7034      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or\r
7035      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).\r
7036      */\r
7037 \r
7038     // private\r
7039     onLayout : function(ct, target){\r
7040         Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);\r
7041                     \r
7042         \r
7043         var cs = this.getItems(ct), cm, ch, margin,\r
7044             size = this.getTargetSize(target),\r
7045             w = size.width - target.getPadding('lr') - this.scrollOffset,\r
7046             h = size.height - target.getPadding('tb'),\r
7047             l = this.padding.left, t = this.padding.top,\r
7048             isStart = this.pack == 'start',\r
7049             isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,\r
7050             stretchWidth = w - (this.padding.left + this.padding.right),\r
7051             extraHeight = 0,\r
7052             maxWidth = 0,\r
7053             totalFlex = 0,\r
7054             flexHeight = 0,\r
7055             usedHeight = 0;\r
7056             \r
7057         Ext.each(cs, function(c){\r
7058             cm = c.margins;\r
7059             totalFlex += c.flex || 0;\r
7060             ch = c.getHeight();\r
7061             margin = cm.top + cm.bottom;\r
7062             extraHeight += ch + margin;\r
7063             flexHeight += margin + (c.flex ? 0 : ch);\r
7064             maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);\r
7065         });\r
7066         extraHeight = h - extraHeight - this.padding.top - this.padding.bottom;\r
7067         \r
7068         var innerCtWidth = maxWidth + this.padding.left + this.padding.right;\r
7069         switch(this.align){\r
7070             case 'stretch':\r
7071                 this.innerCt.setSize(w, h);\r
7072                 break;\r
7073             case 'stretchmax':\r
7074             case 'left':\r
7075                 this.innerCt.setSize(innerCtWidth, h);\r
7076                 break;\r
7077             case 'center':\r
7078                 this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);\r
7079                 break;\r
7080         }\r
7081 \r
7082         var availHeight = Math.max(0, h - this.padding.top - this.padding.bottom - flexHeight),\r
7083             leftOver = availHeight,\r
7084             heights = [],\r
7085             restore = [],\r
7086             idx = 0,\r
7087             availableWidth = Math.max(0, w - this.padding.left - this.padding.right);\r
7088             \r
7089 \r
7090         Ext.each(cs, function(c){\r
7091             if(isStart && c.flex){\r
7092                 ch = Math.floor(availHeight * (c.flex / totalFlex));\r
7093                 leftOver -= ch;\r
7094                 heights.push(ch);\r
7095             }\r
7096         }); \r
7097         \r
7098         if(this.pack == 'center'){\r
7099             t += extraHeight ? extraHeight / 2 : 0;\r
7100         }else if(this.pack == 'end'){\r
7101             t += extraHeight;\r
7102         }\r
7103         Ext.each(cs, function(c){\r
7104             cm = c.margins;\r
7105             t += cm.top;\r
7106             c.setPosition(l + cm.left, t);\r
7107             if(isStart && c.flex){\r
7108                 ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));\r
7109                 if(isRestore){\r
7110                     restore.push(c.getWidth());\r
7111                 }\r
7112                 c.setSize(availableWidth, ch);\r
7113             }else{\r
7114                 ch = c.getHeight();\r
7115             }\r
7116             t += ch + cm.bottom;\r
7117         });\r
7118         \r
7119         idx = 0;\r
7120         Ext.each(cs, function(c){\r
7121             cm = c.margins;\r
7122             if(this.align == 'stretch'){\r
7123                 c.setWidth((stretchWidth - (cm.left + cm.right)).constrain(\r
7124                     c.minWidth || 0, c.maxWidth || 1000000));\r
7125             }else if(this.align == 'stretchmax'){\r
7126                 c.setWidth((maxWidth - (cm.left + cm.right)).constrain(\r
7127                     c.minWidth || 0, c.maxWidth || 1000000));\r
7128             }else{\r
7129                 if(this.align == 'center'){\r
7130                     var diff = availableWidth - (c.getWidth() + cm.left + cm.right);\r
7131                     if(diff > 0){\r
7132                         c.setPosition(l + cm.left + (diff/2), c.y);\r
7133                     }\r
7134                 }\r
7135                 if(isStart && c.flex){\r
7136                     c.setWidth(restore[idx++]);\r
7137                 }\r
7138             }\r
7139         }, this);\r
7140     }\r
7141     /**\r
7142      * @property activeItem\r
7143      * @hide\r
7144      */\r
7145 });\r
7146 \r
7147 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;\r
7148 \r
7149 /**\r
7150  * @class Ext.layout.HBoxLayout\r
7151  * @extends Ext.layout.BoxLayout\r
7152  * A layout that arranges items horizontally\r
7153  */\r
7154 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {\r
7155     /**\r
7156      * @cfg {String} align\r
7157      * Controls how the child items of the container are aligned. Acceptable configuration values for this\r
7158      * property are:\r
7159      * <div class="mdetail-params"><ul>\r
7160      * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically\r
7161      * at the <b>left</b> side of the container</div></li>\r
7162      * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically at the\r
7163      * <b>mid-height</b> of the container</div></li>\r
7164      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill\r
7165      * the height of the container</div></li>\r
7166      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to\r
7167      * the size of the largest item.</div></li>\r
7168      */\r
7169     align : 'top', // top, middle, stretch, strechmax\r
7170     /**\r
7171      * @cfg {String} pack\r
7172      * Controls how the child items of the container are packed together. Acceptable configuration values\r
7173      * for this property are:\r
7174      * <div class="mdetail-params"><ul>\r
7175      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at\r
7176      * <b>left</b> side of container</div></li>\r
7177      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at\r
7178      * <b>mid-width</b> of container</div></li>\r
7179      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>\r
7180      * side of container</div></li>\r
7181      * </ul></div>\r
7182      */\r
7183     /**\r
7184      * @cfg {Number} flex\r
7185      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed\r
7186      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>\r
7187      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with\r
7188      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or\r
7189      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).\r
7190      */\r
7191 \r
7192     // private\r
7193     onLayout : function(ct, target){\r
7194         Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);\r
7195         \r
7196         var cs = this.getItems(ct), cm, cw, margin,\r
7197             size = this.getTargetSize(target),\r
7198             w = size.width - target.getPadding('lr') - this.scrollOffset,\r
7199             h = size.height - target.getPadding('tb'),\r
7200             l = this.padding.left, t = this.padding.top,\r
7201             isStart = this.pack == 'start',\r
7202             isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,\r
7203             stretchHeight = h - (this.padding.top + this.padding.bottom),\r
7204             extraWidth = 0,\r
7205             maxHeight = 0,\r
7206             totalFlex = 0,\r
7207             flexWidth = 0,\r
7208             usedWidth = 0;\r
7209         \r
7210         Ext.each(cs, function(c){\r
7211             cm = c.margins;\r
7212             totalFlex += c.flex || 0;\r
7213             cw = c.getWidth();\r
7214             margin = cm.left + cm.right;\r
7215             extraWidth += cw + margin;\r
7216             flexWidth += margin + (c.flex ? 0 : cw);\r
7217             maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom);\r
7218         });\r
7219         extraWidth = w - extraWidth - this.padding.left - this.padding.right;\r
7220         \r
7221         var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom;\r
7222         switch(this.align){\r
7223             case 'stretch':\r
7224                 this.innerCt.setSize(w, h);\r
7225                 break;\r
7226             case 'stretchmax':\r
7227             case 'top':\r
7228                 this.innerCt.setSize(w, innerCtHeight);\r
7229                 break;\r
7230             case 'middle':\r
7231                 this.innerCt.setSize(w, h = Math.max(h, innerCtHeight));\r
7232                 break;\r
7233         }\r
7234         \r
7235 \r
7236         var availWidth = Math.max(0, w - this.padding.left - this.padding.right - flexWidth),\r
7237             leftOver = availWidth,\r
7238             widths = [],\r
7239             restore = [],\r
7240             idx = 0,\r
7241             availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom);\r
7242             \r
7243 \r
7244         Ext.each(cs, function(c){\r
7245             if(isStart && c.flex){\r
7246                 cw = Math.floor(availWidth * (c.flex / totalFlex));\r
7247                 leftOver -= cw;\r
7248                 widths.push(cw);\r
7249             }\r
7250         }); \r
7251         \r
7252         if(this.pack == 'center'){\r
7253             l += extraWidth ? extraWidth / 2 : 0;\r
7254         }else if(this.pack == 'end'){\r
7255             l += extraWidth;\r
7256         }\r
7257         Ext.each(cs, function(c){\r
7258             cm = c.margins;\r
7259             l += cm.left;\r
7260             c.setPosition(l, t + cm.top);\r
7261             if(isStart && c.flex){\r
7262                 cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0));\r
7263                 if(isRestore){\r
7264                     restore.push(c.getHeight());\r
7265                 }\r
7266                 c.setSize(cw, availableHeight);\r
7267             }else{\r
7268                 cw = c.getWidth();\r
7269             }\r
7270             l += cw + cm.right;\r
7271         });\r
7272         \r
7273         idx = 0;\r
7274         Ext.each(cs, function(c){\r
7275             var cm = c.margins;\r
7276             if(this.align == 'stretch'){\r
7277                 c.setHeight((stretchHeight - (cm.top + cm.bottom)).constrain(\r
7278                     c.minHeight || 0, c.maxHeight || 1000000));\r
7279             }else if(this.align == 'stretchmax'){\r
7280                 c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain(\r
7281                     c.minHeight || 0, c.maxHeight || 1000000));\r
7282             }else{\r
7283                 if(this.align == 'middle'){\r
7284                     var diff = availableHeight - (c.getHeight() + cm.top + cm.bottom);\r
7285                     if(diff > 0){\r
7286                         c.setPosition(c.x, t + cm.top + (diff/2));\r
7287                     }\r
7288                 }\r
7289                 if(isStart && c.flex){\r
7290                     c.setHeight(restore[idx++]);\r
7291                 }\r
7292             }\r
7293         }, this);\r
7294     }\r
7295 \r
7296     /**\r
7297      * @property activeItem\r
7298      * @hide\r
7299      */\r
7300 });\r
7301 \r
7302 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
7303 /**\r
7304  * @class Ext.Viewport\r
7305  * @extends Ext.Container\r
7306  * <p>A specialized container representing the viewable application area (the browser viewport).</p>\r
7307  * <p>The Viewport renders itself to the document body, and automatically sizes itself to the size of\r
7308  * the browser viewport and manages window resizing. There may only be one Viewport created\r
7309  * in a page. Inner layouts are available by virtue of the fact that all {@link Ext.Panel Panel}s\r
7310  * added to the Viewport, either through its {@link #items}, or through the items, or the {@link #add}\r
7311  * method of any of its child Panels may themselves have a layout.</p>\r
7312  * <p>The Viewport does not provide scrolling, so child Panels within the Viewport should provide\r
7313  * for scrolling if needed using the {@link #autoScroll} config.</p>\r
7314  * <p>An example showing a classic application border layout:</p><pre><code>\r
7315 new Ext.Viewport({\r
7316     layout: 'border',\r
7317     items: [{\r
7318         region: 'north',\r
7319         html: '&lt;h1 class="x-panel-header">Page Title&lt;/h1>',\r
7320         autoHeight: true,\r
7321         border: false,\r
7322         margins: '0 0 5 0'\r
7323     }, {\r
7324         region: 'west',\r
7325         collapsible: true,\r
7326         title: 'Navigation',\r
7327         width: 200\r
7328         // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout} \r
7329     }, {\r
7330         region: 'south',\r
7331         title: 'Title for Panel',\r
7332         collapsible: true,\r
7333         html: 'Information goes here',\r
7334         split: true,\r
7335         height: 100,\r
7336         minHeight: 100\r
7337     }, {\r
7338         region: 'east',\r
7339         title: 'Title for the Grid Panel',\r
7340         collapsible: true,\r
7341         split: true,\r
7342         width: 200,\r
7343         xtype: 'grid',\r
7344         // remaining grid configuration not shown ...\r
7345         // notice that the GridPanel is added directly as the region\r
7346         // it is not "overnested" inside another Panel\r
7347     }, {\r
7348         region: 'center',\r
7349         xtype: 'tabpanel', // TabPanel itself has no title\r
7350         items: {\r
7351             title: 'Default Tab',\r
7352             html: 'The first tab\'s content. Others may be added dynamically'\r
7353         }\r
7354     }]\r
7355 });\r
7356 </code></pre>\r
7357  * @constructor\r
7358  * Create a new Viewport\r
7359  * @param {Object} config The config object\r
7360  * @xtype viewport\r
7361  */\r
7362 Ext.Viewport = Ext.extend(Ext.Container, {\r
7363         /*\r
7364          * Privatize config options which, if used, would interfere with the\r
7365          * correct operation of the Viewport as the sole manager of the\r
7366          * layout of the document body.\r
7367          */\r
7368     /**\r
7369      * @cfg {Mixed} applyTo @hide\r
7370          */\r
7371     /**\r
7372      * @cfg {Boolean} allowDomMove @hide\r
7373          */\r
7374     /**\r
7375      * @cfg {Boolean} hideParent @hide\r
7376          */\r
7377     /**\r
7378      * @cfg {Mixed} renderTo @hide\r
7379          */\r
7380     /**\r
7381      * @cfg {Boolean} hideParent @hide\r
7382          */\r
7383     /**\r
7384      * @cfg {Number} height @hide\r
7385          */\r
7386     /**\r
7387      * @cfg {Number} width @hide\r
7388          */\r
7389     /**\r
7390      * @cfg {Boolean} autoHeight @hide\r
7391          */\r
7392     /**\r
7393      * @cfg {Boolean} autoWidth @hide\r
7394          */\r
7395     /**\r
7396      * @cfg {Boolean} deferHeight @hide\r
7397          */\r
7398     /**\r
7399      * @cfg {Boolean} monitorResize @hide\r
7400          */\r
7401     initComponent : function() {\r
7402         Ext.Viewport.superclass.initComponent.call(this);\r
7403         document.getElementsByTagName('html')[0].className += ' x-viewport';\r
7404         this.el = Ext.getBody();\r
7405         this.el.setHeight = Ext.emptyFn;\r
7406         this.el.setWidth = Ext.emptyFn;\r
7407         this.el.setSize = Ext.emptyFn;\r
7408         this.el.dom.scroll = 'no';\r
7409         this.allowDomMove = false;\r
7410         this.autoWidth = true;\r
7411         this.autoHeight = true;\r
7412         Ext.EventManager.onWindowResize(this.fireResize, this);\r
7413         this.renderTo = this.el;\r
7414     },\r
7415 \r
7416     fireResize : function(w, h){\r
7417         this.fireEvent('resize', this, w, h, w, h);\r
7418     }\r
7419 });\r
7420 Ext.reg('viewport', Ext.Viewport);/**
7421  * @class Ext.Panel
7422  * @extends Ext.Container
7423  * <p>Panel is a container that has specific functionality and structural components that make
7424  * it the perfect building block for application-oriented user interfaces.</p>
7425  * <p>Panels are, by virtue of their inheritance from {@link Ext.Container}, capable
7426  * of being configured with a {@link Ext.Container#layout layout}, and containing child Components.</p>
7427  * <p>When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.Container#add adding} Components
7428  * to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether
7429  * those child elements need to be sized using one of Ext's built-in <tt><b>{@link Ext.Container#layout layout}</b></tt> schemes. By
7430  * default, Panels use the {@link Ext.layout.ContainerLayout ContainerLayout} scheme. This simply renders
7431  * child components, appending them one after the other inside the Container, and <b>does not apply any sizing</b>
7432  * at all.</p>
7433  * <p>A Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate
7434  * {@link #header}, {@link #footer} and {@link #body} sections (see {@link #frame} for additional
7435  * information).</p>
7436  * <p>Panel also provides built-in {@link #collapsible expandable and collapsible behavior}, along with
7437  * a variety of {@link #tools prebuilt tool buttons} that can be wired up to provide other customized
7438  * behavior.  Panels can be easily dropped into any {@link Ext.Container Container} or layout, and the
7439  * layout and rendering pipeline is {@link Ext.Container#add completely managed by the framework}.</p>
7440  * @constructor
7441  * @param {Object} config The config object
7442  * @xtype panel
7443  */
7444 Ext.Panel = Ext.extend(Ext.Container, {
7445     /**
7446      * The Panel's header {@link Ext.Element Element}. Read-only.
7447      * <p>This Element is used to house the {@link #title} and {@link #tools}</p>
7448      * <br><p><b>Note</b>: see the Note for <tt>{@link Ext.Component#el el} also.</p>
7449      * @type Ext.Element
7450      * @property header
7451      */
7452     /**
7453      * The Panel's body {@link Ext.Element Element} which may be used to contain HTML content.
7454      * The content may be specified in the {@link #html} config, or it may be loaded using the
7455      * {@link autoLoad} config, or through the Panel's {@link #getUpdater Updater}. Read-only.
7456      * <p>If this is used to load visible HTML elements in either way, then
7457      * the Panel may not be used as a Layout for hosting nested Panels.</p>
7458      * <p>If this Panel is intended to be used as the host of a Layout (See {@link #layout}
7459      * then the body Element must not be loaded or changed - it is under the control
7460      * of the Panel's Layout.
7461      * <br><p><b>Note</b>: see the Note for <tt>{@link Ext.Component#el el} also.</p>
7462      * @type Ext.Element
7463      * @property body
7464      */
7465     /**
7466      * The Panel's bwrap {@link Ext.Element Element} used to contain other Panel elements
7467      * (tbar, body, bbar, footer). See {@link #bodyCfg}. Read-only.
7468      * @type Ext.Element
7469      * @property bwrap
7470      */
7471     /**
7472      * True if this panel is collapsed. Read-only.
7473      * @type Boolean
7474      * @property collapsed
7475      */
7476     /**
7477      * @cfg {Object} bodyCfg
7478      * <p>A {@link Ext.DomHelper DomHelper} element specification object may be specified for any
7479      * Panel Element.</p>
7480      * <p>By default, the Default element in the table below will be used for the html markup to
7481      * create a child element with the commensurate Default class name (<tt>baseCls</tt> will be
7482      * replaced by <tt>{@link #baseCls}</tt>):</p>
7483      * <pre>
7484      * Panel      Default  Default             Custom      Additional       Additional
7485      * Element    element  class               element     class            style
7486      * ========   ==========================   =========   ==============   ===========
7487      * {@link #header}     div      {@link #baseCls}+'-header'   {@link #headerCfg}   headerCssClass   headerStyle
7488      * {@link #bwrap}      div      {@link #baseCls}+'-bwrap'     {@link #bwrapCfg}    bwrapCssClass    bwrapStyle
7489      * + tbar     div      {@link #baseCls}+'-tbar'       {@link #tbarCfg}     tbarCssClass     tbarStyle
7490      * + {@link #body}     div      {@link #baseCls}+'-body'       {@link #bodyCfg}     {@link #bodyCssClass}     {@link #bodyStyle}
7491      * + bbar     div      {@link #baseCls}+'-bbar'       {@link #bbarCfg}     bbarCssClass     bbarStyle
7492      * + {@link #footer}   div      {@link #baseCls}+'-footer'   {@link #footerCfg}   footerCssClass   footerStyle
7493      * </pre>
7494      * <p>Configuring a Custom element may be used, for example, to force the {@link #body} Element
7495      * to use a different form of markup than is created by default. An example of this might be
7496      * to {@link Ext.Element#createChild create a child} Panel containing a custom content, such as
7497      * a header, or forcing centering of all Panel content by having the body be a &lt;center&gt;
7498      * element:</p>
7499      * <pre><code>
7500 new Ext.Panel({
7501     title: 'Message Title',
7502     renderTo: Ext.getBody(),
7503     width: 200, height: 130,
7504     <b>bodyCfg</b>: {
7505         tag: 'center',
7506         cls: 'x-panel-body',  // Default class not applied if Custom element specified
7507         html: 'Message'
7508     },
7509     footerCfg: {
7510         tag: 'h2',
7511         cls: 'x-panel-footer'        // same as the Default class
7512         html: 'footer html'
7513     },
7514     footerCssClass: 'custom-footer', // additional css class, see {@link Ext.element#addClass addClass}
7515     footerStyle:    'background-color:red' // see {@link #bodyStyle}
7516 });
7517      * </code></pre>
7518      * <p>The example above also explicitly creates a <tt>{@link #footer}</tt> with custom markup and
7519      * styling applied.</p>
7520      */
7521     /**
7522      * @cfg {Object} headerCfg
7523      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
7524      * of this Panel's {@link #header} Element.  See <tt>{@link #bodyCfg}</tt> also.</p>
7525      */
7526     /**
7527      * @cfg {Object} bwrapCfg
7528      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
7529      * of this Panel's {@link #bwrap} Element.  See <tt>{@link #bodyCfg}</tt> also.</p>
7530      */
7531     /**
7532      * @cfg {Object} tbarCfg
7533      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
7534      * of this Panel's {@link #tbar} Element.  See <tt>{@link #bodyCfg}</tt> also.</p>
7535      */
7536     /**
7537      * @cfg {Object} bbarCfg
7538      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
7539      * of this Panel's {@link #bbar} Element.  See <tt>{@link #bodyCfg}</tt> also.</p>
7540      */
7541     /**
7542      * @cfg {Object} footerCfg
7543      * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
7544      * of this Panel's {@link #footer} Element.  See <tt>{@link #bodyCfg}</tt> also.</p>
7545      */
7546     /**
7547      * @cfg {Boolean} closable
7548      * Panels themselves do not directly support being closed, but some Panel subclasses do (like
7549      * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}.  Specify <tt>true</tt>
7550      * to enable closing in such situations. Defaults to <tt>false</tt>.
7551      */
7552     /**
7553      * The Panel's footer {@link Ext.Element Element}. Read-only.
7554      * <p>This Element is used to house the Panel's <tt>{@link #buttons}</tt> or <tt>{@link #fbar}</tt>.</p>
7555      * <br><p><b>Note</b>: see the Note for <tt>{@link Ext.Component#el el} also.</p>
7556      * @type Ext.Element
7557      * @property footer
7558      */
7559     /**
7560      * @cfg {Mixed} applyTo
7561      * <p>The id of the node, a DOM node or an existing Element corresponding to a DIV that is already present in
7562      * the document that specifies some panel-specific structural markup.  When <tt>applyTo</tt> is used,
7563      * constituent parts of the panel can be specified by CSS class name within the main element, and the panel
7564      * will automatically create those components from that markup. Any required components not specified in the
7565      * markup will be autogenerated if necessary.</p>
7566      * <p>The following class names are supported (baseCls will be replaced by {@link #baseCls}):</p>
7567      * <ul><li>baseCls + '-header'</li>
7568      * <li>baseCls + '-header-text'</li>
7569      * <li>baseCls + '-bwrap'</li>
7570      * <li>baseCls + '-tbar'</li>
7571      * <li>baseCls + '-body'</li>
7572      * <li>baseCls + '-bbar'</li>
7573      * <li>baseCls + '-footer'</li></ul>
7574      * <p>Using this config, a call to render() is not required.  If applyTo is specified, any value passed for
7575      * {@link #renderTo} will be ignored and the target element's parent node will automatically be used as the
7576      * panel's container.</p>
7577      */
7578     /**
7579      * @cfg {Object/Array} tbar
7580      * <p>The top toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
7581      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
7582      * To access the top toolbar after render, use {@link #getTopToolbar}.</p>
7583      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
7584      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
7585      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
7586      * submission parameters are collected from the DOM tree.</p>
7587      */
7588     /**
7589      * @cfg {Object/Array} bbar
7590      * <p>The bottom toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
7591      * buttons/button configs to be added to the toolbar.  Note that this is not available as a property after render.
7592      * To access the bottom toolbar after render, use {@link #getBottomToolbar}.</p>
7593      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not<b> be updated by a load
7594      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
7595      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
7596      * submission parameters are collected from the DOM tree.</p>
7597      */
7598     /** @cfg {Object/Array} fbar
7599      * <p>A {@link Ext.Toolbar Toolbar} object, a Toolbar config, or an array of
7600      * {@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>
7601      * <p>After render, the <code>fbar</code> property will be an {@link Ext.Toolbar Toolbar} instance.</p>
7602      * <p>If <tt>{@link #buttons}</tt> are specified, they will supersede the <tt>fbar</tt> configuration property.</p>
7603      * The Panel's <tt>{@link #buttonAlign}</tt> configuration affects the layout of these items, for example:
7604      * <pre><code>
7605 var w = new Ext.Window({
7606     height: 250,
7607     width: 500,
7608     bbar: new Ext.Toolbar({
7609         items: [{
7610             text: 'bbar Left'
7611         },'->',{
7612             text: 'bbar Right'
7613         }]
7614     }),
7615     {@link #buttonAlign}: 'left', // anything but 'center' or 'right' and you can use "-", and "->"
7616                                   // to control the alignment of fbar items
7617     fbar: [{
7618         text: 'fbar Left'
7619     },'->',{
7620         text: 'fbar Right'
7621     }]
7622 }).show();
7623      * </code></pre>
7624      * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not<b> be updated by a load
7625      * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
7626      * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
7627      * submission parameters are collected from the DOM tree.</p>
7628      */
7629     /**
7630      * @cfg {Boolean} header
7631      * <tt>true</tt> to create the Panel's header element explicitly, <tt>false</tt> to skip creating
7632      * it.  If a <tt>{@link #title}</tt> is set the header will be created automatically, otherwise it will not.
7633      * If a <tt>{@link #title}</tt> is set but <tt>header</tt> is explicitly set to <tt>false</tt>, the header
7634      * will not be rendered.
7635      */
7636     /**
7637      * @cfg {Boolean} footer
7638      * <tt>true</tt> to create the footer element explicitly, false to skip creating it. The footer
7639      * will be created automatically if <tt>{@link #buttons}</tt> or a <tt>{@link #fbar}</tt> have
7640      * been configured.  See <tt>{@link #bodyCfg}</tt> for an example.
7641      */
7642     /**
7643      * @cfg {String} title
7644      * The title text to be used as innerHTML (html tags are accepted) to display in the panel
7645      * <tt>{@link #header}</tt> (defaults to ''). When a <tt>title</tt> is specified the
7646      * <tt>{@link #header}</tt> element will automatically be created and displayed unless
7647      * {@link #header} is explicitly set to <tt>false</tt>.  If you do not want to specify a
7648      * <tt>title</tt> at config time, but you may want one later, you must either specify a non-empty
7649      * <tt>title</tt> (a blank space ' ' will do) or <tt>header:true</tt> so that the container
7650      * element will get created.
7651      */
7652     /**
7653      * @cfg {Array} buttons
7654      * <tt>buttons</tt> will be used as <tt>{@link Ext.Container#items items}</tt> for the toolbar in
7655      * the footer (<tt>{@link #fbar}</tt>). Typically the value of this configuration property will be
7656      * an array of {@link Ext.Button}s or {@link Ext.Button} configuration objects.
7657      * If an item is configured with <tt>minWidth</tt> or the Panel is configured with <tt>minButtonWidth</tt>,
7658      * that width will be applied to the item.
7659      */
7660     /**
7661      * @cfg {Object/String/Function} autoLoad
7662      * A valid url spec according to the Updater {@link Ext.Updater#update} method.
7663      * If autoLoad is not null, the panel will attempt to load its contents
7664      * immediately upon render.<p>
7665      * The URL will become the default URL for this panel's {@link #body} element,
7666      * so it may be {@link Ext.Element#refresh refresh}ed at any time.</p>
7667      */
7668     /**
7669      * @cfg {Boolean} frame
7670      * <tt>false</tt> by default to render with plain 1px square borders. <tt>true</tt> to render with
7671      * 9 elements, complete with custom rounded corners (also see {@link Ext.Element#boxWrap}).
7672      * <p>The template generated for each condition is depicted below:</p><pre><code>
7673      *
7674 // frame = false
7675 &lt;div id="developer-specified-id-goes-here" class="x-panel">
7676
7677     &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:false)&lt;/span>&lt;/div>
7678
7679     &lt;div class="x-panel-bwrap">
7680         &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
7681     &lt;/div>
7682 &lt;/div>
7683
7684 // frame = true (create 9 elements)
7685 &lt;div id="developer-specified-id-goes-here" class="x-panel">
7686     &lt;div class="x-panel-tl">&lt;div class="x-panel-tr">&lt;div class="x-panel-tc">
7687         &lt;div class="x-panel-header">&lt;span class="x-panel-header-text">Title: (frame:true)&lt;/span>&lt;/div>
7688     &lt;/div>&lt;/div>&lt;/div>
7689
7690     &lt;div class="x-panel-bwrap">
7691         &lt;div class="x-panel-ml">&lt;div class="x-panel-mr">&lt;div class="x-panel-mc">
7692             &lt;div class="x-panel-body">&lt;p>html value goes here&lt;/p>&lt;/div>
7693         &lt;/div>&lt;/div>&lt;/div>
7694
7695         &lt;div class="x-panel-bl">&lt;div class="x-panel-br">&lt;div class="x-panel-bc"/>
7696         &lt;/div>&lt;/div>&lt;/div>
7697 &lt;/div>
7698      * </code></pre>
7699      */
7700     /**
7701      * @cfg {Boolean} border
7702      * True to display the borders of the panel's body element, false to hide them (defaults to true).  By default,
7703      * the border is a 2px wide inset border, but this can be further altered by setting {@link #bodyBorder} to false.
7704      */
7705     /**
7706      * @cfg {Boolean} bodyBorder
7707      * True to display an interior border on the body element of the panel, false to hide it (defaults to true).
7708      * This only applies when {@link #border} == true.  If border == true and bodyBorder == false, the border will display
7709      * as a 1px wide inset border, giving the entire body element an inset appearance.
7710      */
7711     /**
7712      * @cfg {String/Object/Function} bodyCssClass
7713      * Additional css class selector to be applied to the {@link #body} element in the format expected by
7714      * {@link Ext.Element#addClass} (defaults to null). See {@link #bodyCfg}.
7715      */
7716     /**
7717      * @cfg {String/Object/Function} bodyStyle
7718      * Custom CSS styles to be applied to the {@link #body} element in the format expected by
7719      * {@link Ext.Element#applyStyles} (defaults to null). See {@link #bodyCfg}.
7720      */
7721     /**
7722      * @cfg {String} iconCls
7723      * The CSS class selector that specifies a background image to be used as the header icon (defaults to '').
7724      * <p>An example of specifying a custom icon class would be something like:
7725      * </p><pre><code>
7726 // specify the property in the config for the class:
7727      ...
7728      iconCls: 'my-icon'
7729
7730 // css class that specifies background image to be used as the icon image:
7731 .my-icon { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
7732 </code></pre>
7733      */
7734     /**
7735      * @cfg {Boolean} collapsible
7736      * True to make the panel collapsible and have the expand/collapse toggle button automatically rendered into
7737      * the header tool button area, false to keep the panel statically sized with no button (defaults to false).
7738      */
7739     /**
7740      * @cfg {Array} tools
7741      * An array of tool button configs to be added to the header tool area. When rendered, each tool is
7742      * stored as an {@link Ext.Element Element} referenced by a public property called <tt><b></b>tools.<i>&lt;tool-type&gt;</i></tt>
7743      * <p>Each tool config may contain the following properties:
7744      * <div class="mdetail-params"><ul>
7745      * <li><b>id</b> : String<div class="sub-desc"><b>Required.</b> The type
7746      * of tool to create. By default, this assigns a CSS class of the form <tt>x-tool-<i>&lt;tool-type&gt;</i></tt> to the
7747      * resulting tool Element. Ext provides CSS rules, and an icon sprite containing images for the tool types listed below.
7748      * The developer may implement custom tools by supplying alternate CSS rules and background images:
7749      * <ul>
7750      * <div class="x-tool x-tool-toggle" style="float:left; margin-right:5;"> </div><div><tt> toggle</tt> (Created by default when {@link #collapsible} is <tt>true</tt>)</div>
7751      * <div class="x-tool x-tool-close" style="float:left; margin-right:5;"> </div><div><tt> close</tt></div>
7752      * <div class="x-tool x-tool-minimize" style="float:left; margin-right:5;"> </div><div><tt> minimize</tt></div>
7753      * <div class="x-tool x-tool-maximize" style="float:left; margin-right:5;"> </div><div><tt> maximize</tt></div>
7754      * <div class="x-tool x-tool-restore" style="float:left; margin-right:5;"> </div><div><tt> restore</tt></div>
7755      * <div class="x-tool x-tool-gear" style="float:left; margin-right:5;"> </div><div><tt> gear</tt></div>
7756      * <div class="x-tool x-tool-pin" style="float:left; margin-right:5;"> </div><div><tt> pin</tt></div>
7757      * <div class="x-tool x-tool-unpin" style="float:left; margin-right:5;"> </div><div><tt> unpin</tt></div>
7758      * <div class="x-tool x-tool-right" style="float:left; margin-right:5;"> </div><div><tt> right</tt></div>
7759      * <div class="x-tool x-tool-left" style="float:left; margin-right:5;"> </div><div><tt> left</tt></div>
7760      * <div class="x-tool x-tool-up" style="float:left; margin-right:5;"> </div><div><tt> up</tt></div>
7761      * <div class="x-tool x-tool-down" style="float:left; margin-right:5;"> </div><div><tt> down</tt></div>
7762      * <div class="x-tool x-tool-refresh" style="float:left; margin-right:5;"> </div><div><tt> refresh</tt></div>
7763      * <div class="x-tool x-tool-minus" style="float:left; margin-right:5;"> </div><div><tt> minus</tt></div>
7764      * <div class="x-tool x-tool-plus" style="float:left; margin-right:5;"> </div><div><tt> plus</tt></div>
7765      * <div class="x-tool x-tool-help" style="float:left; margin-right:5;"> </div><div><tt> help</tt></div>
7766      * <div class="x-tool x-tool-search" style="float:left; margin-right:5;"> </div><div><tt> search</tt></div>
7767      * <div class="x-tool x-tool-save" style="float:left; margin-right:5;"> </div><div><tt> save</tt></div>
7768      * <div class="x-tool x-tool-print" style="float:left; margin-right:5;"> </div><div><tt> print</tt></div>
7769      * </ul></div></li>
7770      * <li><b>handler</b> : Function<div class="sub-desc"><b>Required.</b> The function to
7771      * call when clicked. Arguments passed are:<ul>
7772      * <li><b>event</b> : Ext.EventObject<div class="sub-desc">The click event.</div></li>
7773      * <li><b>toolEl</b> : Ext.Element<div class="sub-desc">The tool Element.</div></li>
7774      * <li><b>panel</b> : Ext.Panel<div class="sub-desc">The host Panel</div></li>
7775      * <li><b>tc</b> : Ext.Panel<div class="sub-desc">The tool configuration object</div></li>
7776      * </ul></div></li>
7777      * <li><b>stopEvent</b> : Boolean<div class="sub-desc">Defaults to true. Specify as false to allow click event to propagate.</div></li>
7778      * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the handler.</div></li>
7779      * <li><b>qtip</b> : String/Object<div class="sub-desc">A tip string, or
7780      * a config argument to {@link Ext.QuickTip#register}</div></li>
7781      * <li><b>hidden</b> : Boolean<div class="sub-desc">True to initially render hidden.</div></li>
7782      * <li><b>on</b> : Object<div class="sub-desc">A listener config object specifiying
7783      * event listeners in the format of an argument to {@link #addListener}</div></li>
7784      * </ul></div>
7785      * <p>Note that, apart from the toggle tool which is provided when a panel is collapsible, these
7786      * tools only provide the visual button. Any required functionality must be provided by adding
7787      * handlers that implement the necessary behavior.</p>
7788      * <p>Example usage:</p>
7789      * <pre><code>
7790 tools:[{
7791     id:'refresh',
7792     qtip: 'Refresh form Data',
7793     // hidden:true,
7794     handler: function(event, toolEl, panel){
7795         // refresh logic
7796     }
7797 },
7798 {
7799     id:'help',
7800     qtip: 'Get Help',
7801     handler: function(event, toolEl, panel){
7802         // whatever
7803     }
7804 }]
7805 </code></pre>
7806      * <p>For the custom id of <tt>'help'</tt> define two relevant css classes with a link to
7807      * a 15x15 image:</p>
7808      * <pre><code>
7809 .x-tool-help {background-image: url(images/help.png);}
7810 .x-tool-help-over {background-image: url(images/help_over.png);}
7811 // if using an image sprite:
7812 .x-tool-help {background-image: url(images/help.png) no-repeat 0 0;}
7813 .x-tool-help-over {background-position:-15px 0;}
7814 </code></pre>
7815      */
7816     /**
7817      * @cfg {Ext.Template/Ext.XTemplate} toolTemplate
7818      * <p>A Template used to create {@link #tools} in the {@link #header} Element. Defaults to:</p><pre><code>
7819 new Ext.Template('&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>')</code></pre>
7820      * <p>This may may be overridden to provide a custom DOM structure for tools based upon a more
7821      * complex XTemplate. The template's data is a single tool configuration object (Not the entire Array)
7822      * as specified in {@link #tools}.  In the following example an &lt;a> tag is used to provide a
7823      * visual indication when hovering over the tool:</p><pre><code>
7824 var win = new Ext.Window({
7825     tools: [{
7826         id: 'download',
7827         href: '/MyPdfDoc.pdf'
7828     }],
7829     toolTemplate: new Ext.XTemplate(
7830         '&lt;tpl if="id==\'download\'">',
7831             '&lt;a class="x-tool x-tool-pdf" href="{href}">&lt;/a>',
7832         '&lt;/tpl>',
7833         '&lt;tpl if="id!=\'download\'">',
7834             '&lt;div class="x-tool x-tool-{id}">&amp;#160;&lt;/div>',
7835         '&lt;/tpl>'
7836     ),
7837     width:500,
7838     height:300,
7839     closeAction:'hide'
7840 });</code></pre>
7841      * <p>Note that the CSS class "x-tool-pdf" should have an associated style rule which provides an
7842      * appropriate background image, something like:</p>
7843     <pre><code>
7844     a.x-tool-pdf {background-image: url(../shared/extjs/images/pdf.gif)!important;}
7845     </code></pre>
7846      */
7847     /**
7848      * @cfg {Boolean} hideCollapseTool
7849      * <tt>true</tt> to hide the expand/collapse toggle button when <code>{@link #collapsible} == true</code>,
7850      * <tt>false</tt> to display it (defaults to <tt>false</tt>).
7851      */
7852     /**
7853      * @cfg {Boolean} titleCollapse
7854      * <tt>true</tt> to allow expanding and collapsing the panel (when <tt>{@link #collapsible} = true</tt>)
7855      * by clicking anywhere in the header bar, <tt>false</tt>) to allow it only by clicking to tool button
7856      * (defaults to <tt>false</tt>)). If this panel is a child item of a border layout also see the
7857      * {@link Ext.layout.BorderLayout.Region BorderLayout.Region}
7858      * <tt>{@link Ext.layout.BorderLayout.Region#floatable floatable}</tt> config option.
7859      */
7860     /**
7861      * @cfg {Boolean} autoScroll
7862      * <tt>true</tt> to use overflow:'auto' on the panel's body element and show scroll bars automatically when
7863      * necessary, <tt>false</tt> to clip any overflowing content (defaults to <tt>false</tt>).
7864      */
7865     /**
7866      * @cfg {Mixed} floating
7867      * <p>This property is used to configure the underlying {@link Ext.Layer}. Acceptable values for this
7868      * configuration property are:</p><div class="mdetail-params"><ul>
7869      * <li><b><tt>false</tt></b> : <b>Default.</b><div class="sub-desc">Display the panel inline where it is
7870      * rendered.</div></li>
7871      * <li><b><tt>true</tt></b> : <div class="sub-desc">Float the panel (absolute position it with automatic
7872      * shimming and shadow).<ul>
7873      * <div class="sub-desc">Setting floating to true will create an Ext.Layer for this panel and display the
7874      * panel at negative offsets so that it is hidden.</div>
7875      * <div class="sub-desc">Since the panel will be absolute positioned, the position must be set explicitly
7876      * <i>after</i> render (e.g., <tt>myPanel.setPosition(100,100);</tt>).</div>
7877      * <div class="sub-desc"><b>Note</b>: when floating a panel you should always assign a fixed width,
7878      * otherwise it will be auto width and will expand to fill to the right edge of the viewport.</div>
7879      * </ul></div></li>
7880      * <li><b><tt>{@link Ext.Layer object}</tt></b> : <div class="sub-desc">The specified object will be used
7881      * as the configuration object for the {@link Ext.Layer} that will be created.</div></li>
7882      * </ul></div>
7883      */
7884     /**
7885      * @cfg {Boolean/String} shadow
7886      * <tt>true</tt> (or a valid Ext.Shadow {@link Ext.Shadow#mode} value) to display a shadow behind the
7887      * panel, <tt>false</tt> to display no shadow (defaults to <tt>'sides'</tt>).  Note that this option
7888      * only applies when <tt>{@link #floating} = true</tt>.
7889      */
7890     /**
7891      * @cfg {Number} shadowOffset
7892      * The number of pixels to offset the shadow if displayed (defaults to <tt>4</tt>). Note that this
7893      * option only applies when <tt>{@link #floating} = true</tt>.
7894      */
7895     /**
7896      * @cfg {Boolean} shim
7897      * <tt>false</tt> to disable the iframe shim in browsers which need one (defaults to <tt>true</tt>).
7898      * Note that this option only applies when <tt>{@link #floating} = true</tt>.
7899      */
7900     /**
7901      * @cfg {String/Object} html
7902      * An HTML fragment, or a {@link Ext.DomHelper DomHelper} specification to use as the panel's body
7903      * content (defaults to ''). The HTML content is added by the Panel's {@link #afterRender} method,
7904      * and so the document will not contain this HTML at the time the {@link #render} event is fired.
7905      * This content is inserted into the body <i>before</i> any configured {@link #contentEl} is appended.
7906      */
7907     /**
7908      * @cfg {String} contentEl
7909      * <p>Specify the <tt>id</tt> of an existing HTML node to use as the panel's body content
7910      * (defaults to '').</p><div><ul>
7911      * <li><b>Description</b> : <ul>
7912      * <div class="sub-desc">This config option is used to take an existing HTML element and place it in the body
7913      * of a new panel (it simply moves the specified DOM element into the body element of the Panel
7914      * <i>when the Panel is rendered</i> to use as the content (it is not going to be the
7915      * actual panel itself).</div>
7916      * </ul></li>
7917      * <li><b>Notes</b> : <ul>
7918      * <div class="sub-desc">The specified HTML Element is appended to the Panel's {@link #body} Element by the
7919      * Panel's {@link #afterRender} method <i>after any configured {@link #html HTML} has
7920      * been inserted</i>, and so the document will not contain this HTML at the time the
7921      * {@link #render} event is fired.</div>
7922      * <div class="sub-desc">The specified HTML element used will not participate in any layout scheme that the
7923      * Panel may use. It's just HTML. Layouts operate on child items.</div>
7924      * <div class="sub-desc">Add either the <tt>x-hidden</tt> or the <tt>x-hide-display</tt> CSS class to
7925      * prevent a brief flicker of the content before it is rendered to the panel.</div>
7926      * </ul></li>
7927      * </ul></div>
7928      */
7929     /**
7930      * @cfg {Object/Array} keys
7931      * A {@link Ext.KeyMap} config object (in the format expected by {@link Ext.KeyMap#addBinding}
7932      * used to assign custom key handling to this panel (defaults to <tt>null</tt>).
7933      */
7934     /**
7935      * @cfg {Boolean/Object} draggable
7936      * <p><tt>true</tt> to enable dragging of this Panel (defaults to <tt>false</tt>).</p>
7937      * <p>For custom drag/drop implementations, an <b>Ext.Panel.DD</b> config could also be passed
7938      * in this config instead of <tt>true</tt>. Ext.Panel.DD is an internal, undocumented class which
7939      * moves a proxy Element around in place of the Panel's element, but provides no other behaviour
7940      * during dragging or on drop. It is a subclass of {@link Ext.dd.DragSource}, so behaviour may be
7941      * added by implementing the interface methods of {@link Ext.dd.DragDrop} e.g.:
7942      * <pre><code>
7943 new Ext.Panel({
7944     title: 'Drag me',
7945     x: 100,
7946     y: 100,
7947     renderTo: Ext.getBody(),
7948     floating: true,
7949     frame: true,
7950     width: 400,
7951     height: 200,
7952     draggable: {
7953 //      Config option of Ext.Panel.DD class.
7954 //      It&#39;s a floating Panel, so do not show a placeholder proxy in the original position.
7955         insertProxy: false,
7956
7957 //      Called for each mousemove event while dragging the DD object.
7958         onDrag : function(e){
7959 //          Record the x,y position of the drag proxy so that we can
7960 //          position the Panel at end of drag.
7961             var pel = this.proxy.getEl();
7962             this.x = pel.getLeft(true);
7963             this.y = pel.getTop(true);
7964
7965 //          Keep the Shadow aligned if there is one.
7966             var s = this.panel.getEl().shadow;
7967             if (s) {
7968                 s.realign(this.x, this.y, pel.getWidth(), pel.getHeight());
7969             }
7970         },
7971
7972 //      Called on the mouseup event.
7973         endDrag : function(e){
7974             this.panel.setPosition(this.x, this.y);
7975         }
7976     }
7977 }).show();
7978 </code></pre>
7979      */
7980     /**
7981      * @cfg {String} tabTip
7982      * A string to be used as innerHTML (html tags are accepted) to show in a tooltip when mousing over
7983      * the tab of a Ext.Panel which is an item of a {@link Ext.TabPanel}. {@link Ext.QuickTips}.init()
7984      * must be called in order for the tips to render.
7985      */
7986     /**
7987      * @cfg {Boolean} disabled
7988      * Render this panel disabled (default is <tt>false</tt>). An important note when using the disabled
7989      * config on panels is that IE will often fail to initialize the disabled mask element correectly if
7990      * the panel's layout has not yet completed by the time the Panel is disabled during the render process.
7991      * If you experience this issue, you may need to instead use the {@link #afterlayout} event to initialize
7992      * the disabled state:
7993      * <pre><code>
7994 new Ext.Panel({
7995     ...
7996     listeners: {
7997         'afterlayout': {
7998             fn: function(p){
7999                 p.disable();
8000             },
8001             single: true // important, as many layouts can occur
8002         }
8003     }
8004 });
8005 </code></pre>
8006      */
8007     /**
8008      * @cfg {Boolean} autoHeight
8009      * <tt>true</tt> to use height:'auto', <tt>false</tt> to use fixed height (defaults to <tt>false</tt>).
8010      * <b>Note</b>: Setting <tt>autoHeight:true</tt> means that the browser will manage the panel's height
8011      * based on its contents, and that Ext will not manage it at all. If the panel is within a layout that
8012      * manages dimensions (<tt>fit</tt>, <tt>border</tt>, etc.) then setting <tt>autoHeight:true</tt>
8013      * can cause issues with scrolling and will not generally work as expected since the panel will take
8014      * on the height of its contents rather than the height required by the Ext layout.
8015      */
8016
8017
8018     /**
8019      * @cfg {String} baseCls
8020      * The base CSS class to apply to this panel's element (defaults to <tt>'x-panel'</tt>).
8021      * <p>Another option available by default is to specify <tt>'x-plain'</tt> which strips all styling
8022      * except for required attributes for Ext layouts to function (e.g. overflow:hidden).
8023      * See <tt>{@link #unstyled}</tt> also.</p>
8024      */
8025     baseCls : 'x-panel',
8026     /**
8027      * @cfg {String} collapsedCls
8028      * A CSS class to add to the panel's element after it has been collapsed (defaults to
8029      * <tt>'x-panel-collapsed'</tt>).
8030      */
8031     collapsedCls : 'x-panel-collapsed',
8032     /**
8033      * @cfg {Boolean} maskDisabled
8034      * <tt>true</tt> to mask the panel when it is {@link #disabled}, <tt>false</tt> to not mask it (defaults
8035      * to <tt>true</tt>).  Either way, the panel will always tell its contained elements to disable themselves
8036      * when it is disabled, but masking the panel can provide an additional visual cue that the panel is
8037      * disabled.
8038      */
8039     maskDisabled : true,
8040     /**
8041      * @cfg {Boolean} animCollapse
8042      * <tt>true</tt> to animate the transition when the panel is collapsed, <tt>false</tt> to skip the
8043      * animation (defaults to <tt>true</tt> if the {@link Ext.Fx} class is available, otherwise <tt>false</tt>).
8044      */
8045     animCollapse : Ext.enableFx,
8046     /**
8047      * @cfg {Boolean} headerAsText
8048      * <tt>true</tt> to display the panel <tt>{@link #title}</tt> in the <tt>{@link #header}</tt>,
8049      * <tt>false</tt> to hide it (defaults to <tt>true</tt>).
8050      */
8051     headerAsText : true,
8052     /**
8053      * @cfg {String} buttonAlign
8054      * The alignment of any {@link #buttons} added to this panel.  Valid values are <tt>'right'</tt>,
8055      * <tt>'left'</tt> and <tt>'center'</tt> (defaults to <tt>'right'</tt>).
8056      */
8057     buttonAlign : 'right',
8058     /**
8059      * @cfg {Boolean} collapsed
8060      * <tt>true</tt> to render the panel collapsed, <tt>false</tt> to render it expanded (defaults to
8061      * <tt>false</tt>).
8062      */
8063     collapsed : false,
8064     /**
8065      * @cfg {Boolean} collapseFirst
8066      * <tt>true</tt> to make sure the collapse/expand toggle button always renders first (to the left of)
8067      * any other tools in the panel's title bar, <tt>false</tt> to render it last (defaults to <tt>true</tt>).
8068      */
8069     collapseFirst : true,
8070     /**
8071      * @cfg {Number} minButtonWidth
8072      * Minimum width in pixels of all {@link #buttons} in this panel (defaults to <tt>75</tt>)
8073      */
8074     minButtonWidth : 75,
8075     /**
8076      * @cfg {Boolean} unstyled
8077      * Overrides the <tt>{@link #baseCls}</tt> setting to <tt>{@link #baseCls} = 'x-plain'</tt> which renders
8078      * the panel unstyled except for required attributes for Ext layouts to function (e.g. overflow:hidden).
8079      */
8080     /**
8081      * @cfg {String} elements
8082      * A comma-delimited list of panel elements to initialize when the panel is rendered.  Normally, this list will be
8083      * generated automatically based on the items added to the panel at config time, but sometimes it might be useful to
8084      * make sure a structural element is rendered even if not specified at config time (for example, you may want
8085      * to add a button or toolbar dynamically after the panel has been rendered).  Adding those elements to this
8086      * list will allocate the required placeholders in the panel when it is rendered.  Valid values are<div class="mdetail-params"><ul>
8087      * <li><tt>header</tt></li>
8088      * <li><tt>tbar</tt> (top bar)</li>
8089      * <li><tt>body</tt></li>
8090      * <li><tt>bbar</tt> (bottom bar)</li>
8091      * <li><tt>footer</tt></li>
8092      * </ul></div>
8093      * Defaults to '<tt>body</tt>'.
8094      */
8095     elements : 'body',
8096     /**
8097      * @cfg {Boolean} preventBodyReset
8098      * Defaults to <tt>false</tt>.  When set to <tt>true</tt>, an extra css class <tt>'x-panel-normal'</tt>
8099      * will be added to the panel's element, effectively applying css styles suggested by the W3C
8100      * (see http://www.w3.org/TR/CSS21/sample.html) to the Panel's <b>body</b> element (not the header,
8101      * footer, etc.).
8102      */
8103     preventBodyReset : false,
8104
8105     // protected - these could be used to customize the behavior of the window,
8106     // but changing them would not be useful without further mofifications and
8107     // could lead to unexpected or undesirable results.
8108     toolTarget : 'header',
8109     collapseEl : 'bwrap',
8110     slideAnchor : 't',
8111     disabledClass : '',
8112
8113     // private, notify box this class will handle heights
8114     deferHeight : true,
8115     // private
8116     expandDefaults: {
8117         duration : 0.25
8118     },
8119     // private
8120     collapseDefaults : {
8121         duration : 0.25
8122     },
8123
8124     // private
8125     initComponent : function(){
8126         Ext.Panel.superclass.initComponent.call(this);
8127
8128         this.addEvents(
8129             /**
8130              * @event bodyresize
8131              * Fires after the Panel has been resized.
8132              * @param {Ext.Panel} p the Panel which has been resized.
8133              * @param {Number} width The Panel's new width.
8134              * @param {Number} height The Panel's new height.
8135              */
8136             'bodyresize',
8137             /**
8138              * @event titlechange
8139              * Fires after the Panel title has been {@link #title set} or {@link #setTitle changed}.
8140              * @param {Ext.Panel} p the Panel which has had its title changed.
8141              * @param {String} The new title.
8142              */
8143             'titlechange',
8144             /**
8145              * @event iconchange
8146              * Fires after the Panel icon class has been {@link #iconCls set} or {@link #setIconClass changed}.
8147              * @param {Ext.Panel} p the Panel which has had its {@link #iconCls icon class} changed.
8148              * @param {String} The new icon class.
8149              * @param {String} The old icon class.
8150              */
8151             'iconchange',
8152             /**
8153              * @event collapse
8154              * Fires after the Panel has been collapsed.
8155              * @param {Ext.Panel} p the Panel that has been collapsed.
8156              */
8157             'collapse',
8158             /**
8159              * @event expand
8160              * Fires after the Panel has been expanded.
8161              * @param {Ext.Panel} p The Panel that has been expanded.
8162              */
8163             'expand',
8164             /**
8165              * @event beforecollapse
8166              * Fires before the Panel is collapsed.  A handler can return false to cancel the collapse.
8167              * @param {Ext.Panel} p the Panel being collapsed.
8168              * @param {Boolean} animate True if the collapse is animated, else false.
8169              */
8170             'beforecollapse',
8171             /**
8172              * @event beforeexpand
8173              * Fires before the Panel is expanded.  A handler can return false to cancel the expand.
8174              * @param {Ext.Panel} p The Panel being expanded.
8175              * @param {Boolean} animate True if the expand is animated, else false.
8176              */
8177             'beforeexpand',
8178             /**
8179              * @event beforeclose
8180              * Fires before the Panel is closed.  Note that Panels do not directly support being closed, but some
8181              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.  This event only
8182              * applies to such subclasses.
8183              * A handler can return false to cancel the close.
8184              * @param {Ext.Panel} p The Panel being closed.
8185              */
8186             'beforeclose',
8187             /**
8188              * @event close
8189              * Fires after the Panel is closed.  Note that Panels do not directly support being closed, but some
8190              * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.
8191              * @param {Ext.Panel} p The Panel that has been closed.
8192              */
8193             'close',
8194             /**
8195              * @event activate
8196              * Fires after the Panel has been visually activated.
8197              * Note that Panels do not directly support being activated, but some Panel subclasses
8198              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
8199              * activate and deactivate events under the control of the TabPanel.
8200              * @param {Ext.Panel} p The Panel that has been activated.
8201              */
8202             'activate',
8203             /**
8204              * @event deactivate
8205              * Fires after the Panel has been visually deactivated.
8206              * Note that Panels do not directly support being deactivated, but some Panel subclasses
8207              * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
8208              * activate and deactivate events under the control of the TabPanel.
8209              * @param {Ext.Panel} p The Panel that has been deactivated.
8210              */
8211             'deactivate'
8212         );
8213
8214         if(this.unstyled){
8215             this.baseCls = 'x-plain';
8216         }
8217
8218         // shortcuts
8219         if(this.tbar){
8220             this.elements += ',tbar';
8221             if(Ext.isObject(this.tbar)){
8222                 this.topToolbar = this.tbar;
8223             }
8224             delete this.tbar;
8225         }
8226         if(this.bbar){
8227             this.elements += ',bbar';
8228             if(Ext.isObject(this.bbar)){
8229                 this.bottomToolbar = this.bbar;
8230             }
8231             delete this.bbar;
8232         }
8233
8234         if(this.header === true){
8235             this.elements += ',header';
8236             delete this.header;
8237         }else if(this.headerCfg || (this.title && this.header !== false)){
8238             this.elements += ',header';
8239         }
8240
8241         if(this.footerCfg || this.footer === true){
8242             this.elements += ',footer';
8243             delete this.footer;
8244         }
8245
8246         if(this.buttons){
8247             this.elements += ',footer';
8248             var btns = this.buttons;
8249             /**
8250              * This Panel's Array of buttons as created from the <tt>{@link #buttons}</tt>
8251              * config property. Read only.
8252              * @type Array
8253              * @property buttons
8254              */
8255             this.buttons = [];
8256             for(var i = 0, len = btns.length; i < len; i++) {
8257                 if(btns[i].render){ // button instance
8258                     this.buttons.push(btns[i]);
8259                 }else if(btns[i].xtype){
8260                     this.buttons.push(Ext.create(btns[i], 'button'));
8261                 }else{
8262                     this.addButton(btns[i]);
8263                 }
8264             }
8265         }
8266         if(this.fbar){
8267             this.elements += ',footer';
8268         }
8269         if(this.autoLoad){
8270             this.on('render', this.doAutoLoad, this, {delay:10});
8271         }
8272     },
8273
8274     // private
8275     createElement : function(name, pnode){
8276         if(this[name]){
8277             pnode.appendChild(this[name].dom);
8278             return;
8279         }
8280
8281         if(name === 'bwrap' || this.elements.indexOf(name) != -1){
8282             if(this[name+'Cfg']){
8283                 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
8284             }else{
8285                 var el = document.createElement('div');
8286                 el.className = this[name+'Cls'];
8287                 this[name] = Ext.get(pnode.appendChild(el));
8288             }
8289             if(this[name+'CssClass']){
8290                 this[name].addClass(this[name+'CssClass']);
8291             }
8292             if(this[name+'Style']){
8293                 this[name].applyStyles(this[name+'Style']);
8294             }
8295         }
8296     },
8297
8298     // private
8299     onRender : function(ct, position){
8300         Ext.Panel.superclass.onRender.call(this, ct, position);
8301         this.createClasses();
8302
8303         var el = this.el,
8304             d = el.dom,
8305             bw;
8306         el.addClass(this.baseCls);
8307         if(d.firstChild){ // existing markup
8308             this.header = el.down('.'+this.headerCls);
8309             this.bwrap = el.down('.'+this.bwrapCls);
8310             var cp = this.bwrap ? this.bwrap : el;
8311             this.tbar = cp.down('.'+this.tbarCls);
8312             this.body = cp.down('.'+this.bodyCls);
8313             this.bbar = cp.down('.'+this.bbarCls);
8314             this.footer = cp.down('.'+this.footerCls);
8315             this.fromMarkup = true;
8316         }
8317         if (this.preventBodyReset === true) {
8318             el.addClass('x-panel-reset');
8319         }
8320         if(this.cls){
8321             el.addClass(this.cls);
8322         }
8323
8324         if(this.buttons){
8325             this.elements += ',footer';
8326         }
8327
8328         // This block allows for maximum flexibility and performance when using existing markup
8329
8330         // framing requires special markup
8331         if(this.frame){
8332             el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
8333
8334             this.createElement('header', d.firstChild.firstChild.firstChild);
8335             this.createElement('bwrap', d);
8336
8337             // append the mid and bottom frame to the bwrap
8338             bw = this.bwrap.dom;
8339             var ml = d.childNodes[1], bl = d.childNodes[2];
8340             bw.appendChild(ml);
8341             bw.appendChild(bl);
8342
8343             var mc = bw.firstChild.firstChild.firstChild;
8344             this.createElement('tbar', mc);
8345             this.createElement('body', mc);
8346             this.createElement('bbar', mc);
8347             this.createElement('footer', bw.lastChild.firstChild.firstChild);
8348
8349             if(!this.footer){
8350                 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
8351             }
8352         }else{
8353             this.createElement('header', d);
8354             this.createElement('bwrap', d);
8355
8356             // append the mid and bottom frame to the bwrap
8357             bw = this.bwrap.dom;
8358             this.createElement('tbar', bw);
8359             this.createElement('body', bw);
8360             this.createElement('bbar', bw);
8361             this.createElement('footer', bw);
8362
8363             if(!this.header){
8364                 this.body.addClass(this.bodyCls + '-noheader');
8365                 if(this.tbar){
8366                     this.tbar.addClass(this.tbarCls + '-noheader');
8367                 }
8368             }
8369         }
8370
8371         if(this.padding !== undefined) {
8372             this.body.setStyle('padding', this.body.addUnits(this.padding));
8373         }
8374
8375         if(this.border === false){
8376             this.el.addClass(this.baseCls + '-noborder');
8377             this.body.addClass(this.bodyCls + '-noborder');
8378             if(this.header){
8379                 this.header.addClass(this.headerCls + '-noborder');
8380             }
8381             if(this.footer){
8382                 this.footer.addClass(this.footerCls + '-noborder');
8383             }
8384             if(this.tbar){
8385                 this.tbar.addClass(this.tbarCls + '-noborder');
8386             }
8387             if(this.bbar){
8388                 this.bbar.addClass(this.bbarCls + '-noborder');
8389             }
8390         }
8391
8392         if(this.bodyBorder === false){
8393            this.body.addClass(this.bodyCls + '-noborder');
8394         }
8395
8396         this.bwrap.enableDisplayMode('block');
8397
8398         if(this.header){
8399             this.header.unselectable();
8400
8401             // for tools, we need to wrap any existing header markup
8402             if(this.headerAsText){
8403                 this.header.dom.innerHTML =
8404                     '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
8405
8406                 if(this.iconCls){
8407                     this.setIconClass(this.iconCls);
8408                 }
8409             }
8410         }
8411
8412         if(this.floating){
8413             this.makeFloating(this.floating);
8414         }
8415
8416         if(this.collapsible){
8417             this.tools = this.tools ? this.tools.slice(0) : [];
8418             if(!this.hideCollapseTool){
8419                 this.tools[this.collapseFirst?'unshift':'push']({
8420                     id: 'toggle',
8421                     handler : this.toggleCollapse,
8422                     scope: this
8423                 });
8424             }
8425             if(this.titleCollapse && this.header){
8426                 this.mon(this.header, 'click', this.toggleCollapse, this);
8427                 this.header.setStyle('cursor', 'pointer');
8428             }
8429         }
8430         if(this.tools){
8431             var ts = this.tools;
8432             this.tools = {};
8433             this.addTool.apply(this, ts);
8434         }else{
8435             this.tools = {};
8436         }
8437
8438         if(this.buttons && this.buttons.length > 0){
8439             this.fbar = new Ext.Toolbar({
8440                 items: this.buttons,
8441                 toolbarCls: 'x-panel-fbar'
8442             });
8443         }
8444         this.toolbars = [];
8445         if(this.fbar){
8446             this.fbar = Ext.create(this.fbar, 'toolbar');
8447             this.fbar.enableOverflow = false;
8448             if(this.fbar.items){
8449                 this.fbar.items.each(function(c){
8450                     c.minWidth = c.minWidth || this.minButtonWidth;
8451                 }, this);
8452             }
8453             this.fbar.toolbarCls = 'x-panel-fbar';
8454
8455             var bct = this.footer.createChild({cls: 'x-panel-btns x-panel-btns-'+this.buttonAlign});
8456             this.fbar.ownerCt = this;
8457             this.fbar.render(bct);
8458             bct.createChild({cls:'x-clear'});
8459             this.toolbars.push(this.fbar);
8460         }
8461
8462         if(this.tbar && this.topToolbar){
8463             if(Ext.isArray(this.topToolbar)){
8464                 this.topToolbar = new Ext.Toolbar(this.topToolbar);
8465             }else if(!this.topToolbar.events){
8466                 this.topToolbar = Ext.create(this.topToolbar, 'toolbar');
8467             }
8468             this.topToolbar.ownerCt = this;
8469             this.topToolbar.render(this.tbar);
8470             this.toolbars.push(this.topToolbar);
8471         }
8472         if(this.bbar && this.bottomToolbar){
8473             if(Ext.isArray(this.bottomToolbar)){
8474                 this.bottomToolbar = new Ext.Toolbar(this.bottomToolbar);
8475             }else if(!this.bottomToolbar.events){
8476                 this.bottomToolbar = Ext.create(this.bottomToolbar, 'toolbar');
8477             }
8478             this.bottomToolbar.ownerCt = this;
8479             this.bottomToolbar.render(this.bbar);
8480             this.toolbars.push(this.bottomToolbar);
8481         }
8482         Ext.each(this.toolbars, function(tb){
8483             tb.on({
8484                 scope: this,
8485                 afterlayout: this.syncHeight,
8486                 remove: this.syncHeight
8487             });
8488         }, this);
8489     },
8490
8491     /**
8492      * Sets the CSS class that provides the icon image for this panel.  This method will replace any existing
8493      * icon class if one has already been set and fire the {@link #iconchange} event after completion.
8494      * @param {String} cls The new CSS class name
8495      */
8496     setIconClass : function(cls){
8497         var old = this.iconCls;
8498         this.iconCls = cls;
8499         if(this.rendered && this.header){
8500             if(this.frame){
8501                 this.header.addClass('x-panel-icon');
8502                 this.header.replaceClass(old, this.iconCls);
8503             }else{
8504                 var hd = this.header.dom;
8505                 var img = hd.firstChild && String(hd.firstChild.tagName).toLowerCase() == 'img' ? hd.firstChild : null;
8506                 if(img){
8507                     Ext.fly(img).replaceClass(old, this.iconCls);
8508                 }else{
8509                     Ext.DomHelper.insertBefore(hd.firstChild, {
8510                         tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
8511                     });
8512                  }
8513             }
8514         }
8515         this.fireEvent('iconchange', this, cls, old);
8516     },
8517
8518     // private
8519     makeFloating : function(cfg){
8520         this.floating = true;
8521         this.el = new Ext.Layer(
8522             Ext.isObject(cfg) ? cfg : {
8523                 shadow: this.shadow !== undefined ? this.shadow : 'sides',
8524                 shadowOffset: this.shadowOffset,
8525                 constrain:false,
8526                 shim: this.shim === false ? false : undefined
8527             }, this.el
8528         );
8529     },
8530
8531     /**
8532      * Returns the {@link Ext.Toolbar toolbar} from the top (<tt>{@link #tbar}</tt>) section of the panel.
8533      * @return {Ext.Toolbar} The toolbar
8534      */
8535     getTopToolbar : function(){
8536         return this.topToolbar;
8537     },
8538
8539     /**
8540      * Returns the {@link Ext.Toolbar toolbar} from the bottom (<tt>{@link #bbar}</tt>) section of the panel.
8541      * @return {Ext.Toolbar} The toolbar
8542      */
8543     getBottomToolbar : function(){
8544         return this.bottomToolbar;
8545     },
8546
8547     /**
8548      * Adds a button to this panel.  Note that this method must be called prior to rendering.  The preferred
8549      * approach is to add buttons via the {@link #buttons} config.
8550      * @param {String/Object} config A valid {@link Ext.Button} config.  A string will become the text for a default
8551      * button config, an object will be treated as a button config object.
8552      * @param {Function} handler The function to be called on button {@link Ext.Button#click}
8553      * @param {Object} scope The scope to use for the button handler function
8554      * @return {Ext.Button} The button that was added
8555      */
8556     addButton : function(config, handler, scope){
8557         var bc = {
8558             handler: handler,
8559             scope: scope,
8560             minWidth: this.minButtonWidth,
8561             hideParent:true
8562         };
8563         if(typeof config == "string"){
8564             bc.text = config;
8565         }else{
8566             Ext.apply(bc, config);
8567         }
8568         var btn = new Ext.Button(bc);
8569         if(!this.buttons){
8570             this.buttons = [];
8571         }
8572         this.buttons.push(btn);
8573         return btn;
8574     },
8575
8576     // private
8577     addTool : function(){
8578         if(!this[this.toolTarget]) { // no where to render tools!
8579             return;
8580         }
8581         if(!this.toolTemplate){
8582             // initialize the global tool template on first use
8583             var tt = new Ext.Template(
8584                  '<div class="x-tool x-tool-{id}">&#160;</div>'
8585             );
8586             tt.disableFormats = true;
8587             tt.compile();
8588             Ext.Panel.prototype.toolTemplate = tt;
8589         }
8590         for(var i = 0, a = arguments, len = a.length; i < len; i++) {
8591             var tc = a[i];
8592             if(!this.tools[tc.id]){
8593                 var overCls = 'x-tool-'+tc.id+'-over';
8594                 var t = this.toolTemplate.insertFirst((tc.align !== 'left') ? this[this.toolTarget] : this[this.toolTarget].child('span'), tc, true);
8595                 this.tools[tc.id] = t;
8596                 t.enableDisplayMode('block');
8597                 this.mon(t, 'click',  this.createToolHandler(t, tc, overCls, this));
8598                 if(tc.on){
8599                     this.mon(t, tc.on);
8600                 }
8601                 if(tc.hidden){
8602                     t.hide();
8603                 }
8604                 if(tc.qtip){
8605                     if(Ext.isObject(tc.qtip)){
8606                         Ext.QuickTips.register(Ext.apply({
8607                               target: t.id
8608                         }, tc.qtip));
8609                     } else {
8610                         t.dom.qtip = tc.qtip;
8611                     }
8612                 }
8613                 t.addClassOnOver(overCls);
8614             }
8615         }
8616     },
8617
8618     onLayout : function(){
8619         if(this.toolbars.length > 0){
8620             this.duringLayout = true;
8621             Ext.each(this.toolbars, function(tb){
8622                 tb.doLayout();
8623             });
8624             delete this.duringLayout;
8625             this.syncHeight();
8626         }
8627     },
8628
8629     syncHeight : function(){
8630         if(!(this.autoHeight || this.duringLayout)){
8631             var last = this.lastSize;
8632             if(last && !Ext.isEmpty(last.height)){
8633                 var old = last.height, h = this.el.getHeight();
8634                 if(old != 'auto' && old != h){
8635                     var bd = this.body, bdh = bd.getHeight();
8636                     h = Math.max(bdh + old - h, 0);
8637                     if(bdh > 0 && bdh != h){
8638                         bd.setHeight(h);
8639                         if(Ext.isIE && h <= 0){
8640                             return;
8641                         }
8642                         var sz = bd.getSize();
8643                         this.fireEvent('bodyresize', sz.width, sz.height);
8644                     }
8645                 }
8646             }
8647         }
8648     },
8649
8650     // private
8651     onShow : function(){
8652         if(this.floating){
8653             return this.el.show();
8654         }
8655         Ext.Panel.superclass.onShow.call(this);
8656     },
8657
8658     // private
8659     onHide : function(){
8660         if(this.floating){
8661             return this.el.hide();
8662         }
8663         Ext.Panel.superclass.onHide.call(this);
8664     },
8665
8666     // private
8667     createToolHandler : function(t, tc, overCls, panel){
8668         return function(e){
8669             t.removeClass(overCls);
8670             if(tc.stopEvent !== false){
8671                 e.stopEvent();
8672             }
8673             if(tc.handler){
8674                 tc.handler.call(tc.scope || t, e, t, panel, tc);
8675             }
8676         };
8677     },
8678
8679     // private
8680     afterRender : function(){
8681         if(this.floating && !this.hidden){
8682             this.el.show();
8683         }
8684         if(this.title){
8685             this.setTitle(this.title);
8686         }
8687         this.setAutoScroll();
8688         if(this.html){
8689             this.body.update(Ext.isObject(this.html) ?
8690                              Ext.DomHelper.markup(this.html) :
8691                              this.html);
8692             delete this.html;
8693         }
8694         if(this.contentEl){
8695             var ce = Ext.getDom(this.contentEl);
8696             Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
8697             this.body.dom.appendChild(ce);
8698         }
8699         if(this.collapsed){
8700             this.collapsed = false;
8701             this.collapse(false);
8702         }
8703         Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
8704         this.initEvents();
8705     },
8706
8707     // private
8708     setAutoScroll : function(){
8709         if(this.rendered && this.autoScroll){
8710             var el = this.body || this.el;
8711             if(el){
8712                 el.setOverflow('auto');
8713             }
8714         }
8715     },
8716
8717     // private
8718     getKeyMap : function(){
8719         if(!this.keyMap){
8720             this.keyMap = new Ext.KeyMap(this.el, this.keys);
8721         }
8722         return this.keyMap;
8723     },
8724
8725     // private
8726     initEvents : function(){
8727         if(this.keys){
8728             this.getKeyMap();
8729         }
8730         if(this.draggable){
8731             this.initDraggable();
8732         }
8733     },
8734
8735     // private
8736     initDraggable : function(){
8737         /**
8738          * <p>If this Panel is configured {@link #draggable}, this property will contain
8739          * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.</p>
8740          * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource}
8741          * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
8742          * @type Ext.dd.DragSource.
8743          * @property dd
8744          */
8745         this.dd = new Ext.Panel.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
8746     },
8747
8748     // private
8749     beforeEffect : function(){
8750         if(this.floating){
8751             this.el.beforeAction();
8752         }
8753         this.el.addClass('x-panel-animated');
8754     },
8755
8756     // private
8757     afterEffect : function(){
8758         this.syncShadow();
8759         this.el.removeClass('x-panel-animated');
8760     },
8761
8762     // private - wraps up an animation param with internal callbacks
8763     createEffect : function(a, cb, scope){
8764         var o = {
8765             scope:scope,
8766             block:true
8767         };
8768         if(a === true){
8769             o.callback = cb;
8770             return o;
8771         }else if(!a.callback){
8772             o.callback = cb;
8773         }else { // wrap it up
8774             o.callback = function(){
8775                 cb.call(scope);
8776                 Ext.callback(a.callback, a.scope);
8777             };
8778         }
8779         return Ext.applyIf(o, a);
8780     },
8781
8782     /**
8783      * Collapses the panel body so that it becomes hidden.  Fires the {@link #beforecollapse} event which will
8784      * cancel the collapse action if it returns false.
8785      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
8786      * {@link #animCollapse} panel config)
8787      * @return {Ext.Panel} this
8788      */
8789     collapse : function(animate){
8790         if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
8791             return;
8792         }
8793         var doAnim = animate === true || (animate !== false && this.animCollapse);
8794         this.beforeEffect();
8795         this.onCollapse(doAnim, animate);
8796         return this;
8797     },
8798
8799     // private
8800     onCollapse : function(doAnim, animArg){
8801         if(doAnim){
8802             this[this.collapseEl].slideOut(this.slideAnchor,
8803                     Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
8804                         this.collapseDefaults));
8805         }else{
8806             this[this.collapseEl].hide();
8807             this.afterCollapse();
8808         }
8809     },
8810
8811     // private
8812     afterCollapse : function(){
8813         this.collapsed = true;
8814         this.el.addClass(this.collapsedCls);
8815         this.afterEffect();
8816         this.fireEvent('collapse', this);
8817     },
8818
8819     /**
8820      * Expands the panel body so that it becomes visible.  Fires the {@link #beforeexpand} event which will
8821      * cancel the expand action if it returns false.
8822      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
8823      * {@link #animCollapse} panel config)
8824      * @return {Ext.Panel} this
8825      */
8826     expand : function(animate){
8827         if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
8828             return;
8829         }
8830         var doAnim = animate === true || (animate !== false && this.animCollapse);
8831         this.el.removeClass(this.collapsedCls);
8832         this.beforeEffect();
8833         this.onExpand(doAnim, animate);
8834         return this;
8835     },
8836
8837     // private
8838     onExpand : function(doAnim, animArg){
8839         if(doAnim){
8840             this[this.collapseEl].slideIn(this.slideAnchor,
8841                     Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
8842                         this.expandDefaults));
8843         }else{
8844             this[this.collapseEl].show();
8845             this.afterExpand();
8846         }
8847     },
8848
8849     // private
8850     afterExpand : function(){
8851         this.collapsed = false;
8852         this.afterEffect();
8853         if(this.deferLayout !== undefined){
8854             this.doLayout(true);
8855         }
8856         this.fireEvent('expand', this);
8857     },
8858
8859     /**
8860      * Shortcut for performing an {@link #expand} or {@link #collapse} based on the current state of the panel.
8861      * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
8862      * {@link #animCollapse} panel config)
8863      * @return {Ext.Panel} this
8864      */
8865     toggleCollapse : function(animate){
8866         this[this.collapsed ? 'expand' : 'collapse'](animate);
8867         return this;
8868     },
8869
8870     // private
8871     onDisable : function(){
8872         if(this.rendered && this.maskDisabled){
8873             this.el.mask();
8874         }
8875         Ext.Panel.superclass.onDisable.call(this);
8876     },
8877
8878     // private
8879     onEnable : function(){
8880         if(this.rendered && this.maskDisabled){
8881             this.el.unmask();
8882         }
8883         Ext.Panel.superclass.onEnable.call(this);
8884     },
8885
8886     // private
8887     onResize : function(w, h){
8888         if(w !== undefined || h !== undefined){
8889             if(!this.collapsed){
8890                 if(typeof w == 'number'){
8891                     w = this.adjustBodyWidth(w - this.getFrameWidth());
8892                     if(this.tbar){
8893                         this.tbar.setWidth(w);
8894                         if(this.topToolbar){
8895                             this.topToolbar.setSize(w);
8896                         }
8897                     }
8898                     if(this.bbar){
8899                         this.bbar.setWidth(w);
8900                         if(this.bottomToolbar){
8901                             this.bottomToolbar.setSize(w);
8902                         }
8903                     }
8904                     if(this.fbar){
8905                         var f = this.fbar,
8906                             fWidth = 1,
8907                             strict = Ext.isStrict;
8908                         if(this.buttonAlign == 'left'){
8909                            fWidth = w - f.container.getFrameWidth('lr');
8910                         }else{
8911                             //center/right alignment off in webkit
8912                             if(Ext.isIE || Ext.isWebKit){
8913                                 //center alignment ok on webkit.
8914                                 //right broken in both, center on IE
8915                                 if(!(this.buttonAlign == 'center' && Ext.isWebKit) && (!strict || (!Ext.isIE8 && strict))){
8916                                     (function(){
8917                                         f.setWidth(f.getEl().child('.x-toolbar-ct').getWidth());
8918                                     }).defer(1);
8919                                 }else{
8920                                     fWidth = 'auto';
8921                                 }
8922                             }else{
8923                                 fWidth = 'auto';
8924                             }
8925                         }
8926                         f.setWidth(fWidth);
8927                     }
8928                     this.body.setWidth(w);
8929                 }else if(w == 'auto'){
8930                     this.body.setWidth(w);
8931                 }
8932
8933                 if(typeof h == 'number'){
8934                     h = Math.max(0, this.adjustBodyHeight(h - this.getFrameHeight()));
8935                     this.body.setHeight(h);
8936                 }else if(h == 'auto'){
8937                     this.body.setHeight(h);
8938                 }
8939
8940                 if(this.disabled && this.el._mask){
8941                     this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
8942                 }
8943             }else{
8944                 this.queuedBodySize = {width: w, height: h};
8945                 if(!this.queuedExpand && this.allowQueuedExpand !== false){
8946                     this.queuedExpand = true;
8947                     this.on('expand', function(){
8948                         delete this.queuedExpand;
8949                         this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
8950                         this.doLayout();
8951                     }, this, {single:true});
8952                 }
8953             }
8954             this.fireEvent('bodyresize', this, w, h);
8955         }
8956         this.syncShadow();
8957     },
8958
8959     // private
8960     adjustBodyHeight : function(h){
8961         return h;
8962     },
8963
8964     // private
8965     adjustBodyWidth : function(w){
8966         return w;
8967     },
8968
8969     // private
8970     onPosition : function(){
8971         this.syncShadow();
8972     },
8973
8974     /**
8975      * Returns the width in pixels of the framing elements of this panel (not including the body width).  To
8976      * retrieve the body width see {@link #getInnerWidth}.
8977      * @return {Number} The frame width
8978      */
8979     getFrameWidth : function(){
8980         var w = this.el.getFrameWidth('lr')+this.bwrap.getFrameWidth('lr');
8981
8982         if(this.frame){
8983             var l = this.bwrap.dom.firstChild;
8984             w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
8985             var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
8986             w += Ext.fly(mc).getFrameWidth('lr');
8987         }
8988         return w;
8989     },
8990
8991     /**
8992      * Returns the height in pixels of the framing elements of this panel (including any top and bottom bars and
8993      * header and footer elements, but not including the body height).  To retrieve the body height see {@link #getInnerHeight}.
8994      * @return {Number} The frame height
8995      */
8996     getFrameHeight : function(){
8997         var h  = this.el.getFrameWidth('tb')+this.bwrap.getFrameWidth('tb');
8998         h += (this.tbar ? this.tbar.getHeight() : 0) +
8999              (this.bbar ? this.bbar.getHeight() : 0);
9000
9001         if(this.frame){
9002             var hd = this.el.dom.firstChild;
9003             var ft = this.bwrap.dom.lastChild;
9004             h += (hd.offsetHeight + ft.offsetHeight);
9005             var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
9006             h += Ext.fly(mc).getFrameWidth('tb');
9007         }else{
9008             h += (this.header ? this.header.getHeight() : 0) +
9009                 (this.footer ? this.footer.getHeight() : 0);
9010         }
9011         return h;
9012     },
9013
9014     /**
9015      * Returns the width in pixels of the body element (not including the width of any framing elements).
9016      * For the frame width see {@link #getFrameWidth}.
9017      * @return {Number} The body width
9018      */
9019     getInnerWidth : function(){
9020         return this.getSize().width - this.getFrameWidth();
9021     },
9022
9023     /**
9024      * Returns the height in pixels of the body element (not including the height of any framing elements).
9025      * For the frame height see {@link #getFrameHeight}.
9026      * @return {Number} The body height
9027      */
9028     getInnerHeight : function(){
9029         return this.getSize().height - this.getFrameHeight();
9030     },
9031
9032     // private
9033     syncShadow : function(){
9034         if(this.floating){
9035             this.el.sync(true);
9036         }
9037     },
9038
9039     // private
9040     getLayoutTarget : function(){
9041         return this.body;
9042     },
9043
9044     /**
9045      * <p>Sets the title text for the panel and optionally the {@link #iconCls icon class}.</p>
9046      * <p>In order to be able to set the title, a header element must have been created
9047      * for the Panel. This is triggered either by configuring the Panel with a non-blank <tt>{@link #title}</tt>,
9048      * or configuring it with <tt><b>{@link #header}: true</b></tt>.</p>
9049      * @param {String} title The title text to set
9050      * @param {String} iconCls (optional) {@link #iconCls iconCls} A user-defined CSS class that provides the icon image for this panel
9051      */
9052     setTitle : function(title, iconCls){
9053         this.title = title;
9054         if(this.header && this.headerAsText){
9055             this.header.child('span').update(title);
9056         }
9057         if(iconCls){
9058             this.setIconClass(iconCls);
9059         }
9060         this.fireEvent('titlechange', this, title);
9061         return this;
9062     },
9063
9064     /**
9065      * Get the {@link Ext.Updater} for this panel. Enables you to perform Ajax updates of this panel's body.
9066      * @return {Ext.Updater} The Updater
9067      */
9068     getUpdater : function(){
9069         return this.body.getUpdater();
9070     },
9071
9072      /**
9073      * Loads this content panel immediately with content returned from an XHR call.
9074      * @param {Object/String/Function} config A config object containing any of the following options:
9075 <pre><code>
9076 panel.load({
9077     url: "your-url.php",
9078     params: {param1: "foo", param2: "bar"}, // or a URL encoded string
9079     callback: yourFunction,
9080     scope: yourObject, // optional scope for the callback
9081     discardUrl: false,
9082     nocache: false,
9083     text: "Loading...",
9084     timeout: 30,
9085     scripts: false
9086 });
9087 </code></pre>
9088      * The only required property is url. The optional properties nocache, text and scripts
9089      * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their
9090      * associated property on this panel Updater instance.
9091      * @return {Ext.Panel} this
9092      */
9093     load : function(){
9094         var um = this.body.getUpdater();
9095         um.update.apply(um, arguments);
9096         return this;
9097     },
9098
9099     // private
9100     beforeDestroy : function(){
9101         if(this.header){
9102             this.header.removeAllListeners();
9103             if(this.headerAsText){
9104                 Ext.Element.uncache(this.header.child('span'));
9105             }
9106         }
9107         Ext.Element.uncache(
9108             this.header,
9109             this.tbar,
9110             this.bbar,
9111             this.footer,
9112             this.body,
9113             this.bwrap
9114         );
9115         if(this.tools){
9116             for(var k in this.tools){
9117                 Ext.destroy(this.tools[k]);
9118             }
9119         }
9120         if(this.buttons){
9121             for(var b in this.buttons){
9122                 Ext.destroy(this.buttons[b]);
9123             }
9124         }
9125         Ext.destroy(this.toolbars);
9126         Ext.Panel.superclass.beforeDestroy.call(this);
9127     },
9128
9129     // private
9130     createClasses : function(){
9131         this.headerCls = this.baseCls + '-header';
9132         this.headerTextCls = this.baseCls + '-header-text';
9133         this.bwrapCls = this.baseCls + '-bwrap';
9134         this.tbarCls = this.baseCls + '-tbar';
9135         this.bodyCls = this.baseCls + '-body';
9136         this.bbarCls = this.baseCls + '-bbar';
9137         this.footerCls = this.baseCls + '-footer';
9138     },
9139
9140     // private
9141     createGhost : function(cls, useShim, appendTo){
9142         var el = document.createElement('div');
9143         el.className = 'x-panel-ghost ' + (cls ? cls : '');
9144         if(this.header){
9145             el.appendChild(this.el.dom.firstChild.cloneNode(true));
9146         }
9147         Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
9148         el.style.width = this.el.dom.offsetWidth + 'px';;
9149         if(!appendTo){
9150             this.container.dom.appendChild(el);
9151         }else{
9152             Ext.getDom(appendTo).appendChild(el);
9153         }
9154         if(useShim !== false && this.el.useShim !== false){
9155             var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
9156             layer.show();
9157             return layer;
9158         }else{
9159             return new Ext.Element(el);
9160         }
9161     },
9162
9163     // private
9164     doAutoLoad : function(){
9165         var u = this.body.getUpdater();
9166         if(this.renderer){
9167             u.setRenderer(this.renderer);
9168         }
9169         u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
9170     },
9171
9172     /**
9173      * Retrieve a tool by id.
9174      * @param {String} id
9175      * @return {Object} tool
9176      */
9177     getTool : function(id) {
9178         return this.tools[id];
9179     }
9180
9181 /**
9182  * @cfg {String} autoEl @hide
9183  */
9184 });
9185 Ext.reg('panel', Ext.Panel);
9186 /**
9187  * @class Ext.Editor
9188  * @extends Ext.Component
9189  * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
9190  * @constructor
9191  * Create a new Editor
9192  * @param {Object} config The config object
9193  * @xtype editor
9194  */
9195 Ext.Editor = function(field, config){
9196     if(field.field){
9197         this.field = Ext.create(field.field, 'textfield');
9198         config = Ext.apply({}, field); // copy so we don't disturb original config
9199         delete config.field;
9200     }else{
9201         this.field = field;
9202     }
9203     Ext.Editor.superclass.constructor.call(this, config);
9204 };
9205
9206 Ext.extend(Ext.Editor, Ext.Component, {
9207     /**
9208     * @cfg {Ext.form.Field} field
9209     * The Field object (or descendant) or config object for field
9210     */
9211     /**
9212      * @cfg {Boolean} allowBlur
9213      * True to {@link #completeEdit complete the editing process} if in edit mode when the
9214      * field is blurred. Defaults to <tt>false</tt>.
9215      */
9216     /**
9217      * @cfg {Boolean/String} autoSize
9218      * True for the editor to automatically adopt the size of the element being edited, "width" to adopt the width only,
9219      * or "height" to adopt the height only (defaults to false)
9220      */
9221     /**
9222      * @cfg {Boolean} revertInvalid
9223      * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
9224      * validation fails (defaults to true)
9225      */
9226     /**
9227      * @cfg {Boolean} ignoreNoChange
9228      * True to skip the edit completion process (no save, no events fired) if the user completes an edit and
9229      * the value has not changed (defaults to false).  Applies only to string values - edits for other data types
9230      * will never be ignored.
9231      */
9232     /**
9233      * @cfg {Boolean} hideEl
9234      * False to keep the bound element visible while the editor is displayed (defaults to true)
9235      */
9236     /**
9237      * @cfg {Mixed} value
9238      * The data value of the underlying field (defaults to "")
9239      */
9240     value : "",
9241     /**
9242      * @cfg {String} alignment
9243      * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?").
9244      */
9245     alignment: "c-c?",
9246     /**
9247      * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
9248      * for bottom-right shadow (defaults to "frame")
9249      */
9250     shadow : "frame",
9251     /**
9252      * @cfg {Boolean} constrain True to constrain the editor to the viewport
9253      */
9254     constrain : false,
9255     /**
9256      * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true)
9257      */
9258     swallowKeys : true,
9259     /**
9260      * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed (defaults to false)
9261      */
9262     completeOnEnter : false,
9263     /**
9264      * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed (defaults to false)
9265      */
9266     cancelOnEsc : false,
9267     /**
9268      * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
9269      */
9270     updateEl : false,
9271
9272     initComponent : function(){
9273         Ext.Editor.superclass.initComponent.call(this);
9274         this.addEvents(
9275             /**
9276              * @event beforestartedit
9277              * Fires when editing is initiated, but before the value changes.  Editing can be canceled by returning
9278              * false from the handler of this event.
9279              * @param {Editor} this
9280              * @param {Ext.Element} boundEl The underlying element bound to this editor
9281              * @param {Mixed} value The field value being set
9282              */
9283             "beforestartedit",
9284             /**
9285              * @event startedit
9286              * Fires when this editor is displayed
9287              * @param {Ext.Element} boundEl The underlying element bound to this editor
9288              * @param {Mixed} value The starting field value
9289              */
9290             "startedit",
9291             /**
9292              * @event beforecomplete
9293              * Fires after a change has been made to the field, but before the change is reflected in the underlying
9294              * field.  Saving the change to the field can be canceled by returning false from the handler of this event.
9295              * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
9296              * event will not fire since no edit actually occurred.
9297              * @param {Editor} this
9298              * @param {Mixed} value The current field value
9299              * @param {Mixed} startValue The original field value
9300              */
9301             "beforecomplete",
9302             /**
9303              * @event complete
9304              * Fires after editing is complete and any changed value has been written to the underlying field.
9305              * @param {Editor} this
9306              * @param {Mixed} value The current field value
9307              * @param {Mixed} startValue The original field value
9308              */
9309             "complete",
9310             /**
9311              * @event canceledit
9312              * Fires after editing has been canceled and the editor's value has been reset.
9313              * @param {Editor} this
9314              * @param {Mixed} value The user-entered field value that was discarded
9315              * @param {Mixed} startValue The original field value that was set back into the editor after cancel
9316              */
9317             "canceledit",
9318             /**
9319              * @event specialkey
9320              * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed.  You can check
9321              * {@link Ext.EventObject#getKey} to determine which key was pressed.
9322              * @param {Ext.form.Field} this
9323              * @param {Ext.EventObject} e The event object
9324              */
9325             "specialkey"
9326         );
9327     },
9328
9329     // private
9330     onRender : function(ct, position){
9331         this.el = new Ext.Layer({
9332             shadow: this.shadow,
9333             cls: "x-editor",
9334             parentEl : ct,
9335             shim : this.shim,
9336             shadowOffset: this.shadowOffset || 4,
9337             id: this.id,
9338             constrain: this.constrain
9339         });
9340         if(this.zIndex){
9341             this.el.setZIndex(this.zIndex);
9342         }
9343         this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
9344         if(this.field.msgTarget != 'title'){
9345             this.field.msgTarget = 'qtip';
9346         }
9347         this.field.inEditor = true;
9348         this.field.render(this.el);
9349         if(Ext.isGecko){
9350             this.field.el.dom.setAttribute('autocomplete', 'off');
9351         }
9352         this.mon(this.field, "specialkey", this.onSpecialKey, this);
9353         if(this.swallowKeys){
9354             this.field.el.swallowEvent(['keydown','keypress']);
9355         }
9356         this.field.show();
9357         this.mon(this.field, "blur", this.onBlur, this);
9358         if(this.field.grow){
9359                 this.mon(this.field, "autosize", this.el.sync,  this.el, {delay:1});
9360         }
9361     },
9362
9363     // private
9364     onSpecialKey : function(field, e){
9365         var key = e.getKey();
9366         if(this.completeOnEnter && key == e.ENTER){
9367             e.stopEvent();
9368             this.completeEdit();
9369         }else if(this.cancelOnEsc && key == e.ESC){
9370             this.cancelEdit();
9371         }else{
9372             this.fireEvent('specialkey', field, e);
9373         }
9374         if(this.field.triggerBlur && (key == e.ENTER || key == e.ESC || key == e.TAB)){
9375             this.field.triggerBlur();
9376         }
9377     },
9378
9379     /**
9380      * Starts the editing process and shows the editor.
9381      * @param {Mixed} el The element to edit
9382      * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
9383       * to the innerHTML of el.
9384      */
9385     startEdit : function(el, value){
9386         if(this.editing){
9387             this.completeEdit();
9388         }
9389         this.boundEl = Ext.get(el);
9390         var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
9391         if(!this.rendered){
9392             this.render(this.parentEl || document.body);
9393         }
9394         if(this.fireEvent("beforestartedit", this, this.boundEl, v) === false){
9395             return;
9396         }
9397         this.startValue = v;
9398         this.field.setValue(v);
9399         this.doAutoSize();
9400         this.el.alignTo(this.boundEl, this.alignment);
9401         this.editing = true;
9402         this.show();
9403     },
9404
9405     // private
9406     doAutoSize : function(){
9407         if(this.autoSize){
9408             var sz = this.boundEl.getSize();
9409             switch(this.autoSize){
9410                 case "width":
9411                     this.setSize(sz.width,  "");
9412                 break;
9413                 case "height":
9414                     this.setSize("",  sz.height);
9415                 break;
9416                 default:
9417                     this.setSize(sz.width,  sz.height);
9418             }
9419         }
9420     },
9421
9422     /**
9423      * Sets the height and width of this editor.
9424      * @param {Number} width The new width
9425      * @param {Number} height The new height
9426      */
9427     setSize : function(w, h){
9428         delete this.field.lastSize;
9429         this.field.setSize(w, h);
9430         if(this.el){
9431             if(Ext.isGecko2 || Ext.isOpera){
9432                 // prevent layer scrollbars
9433                 this.el.setSize(w, h);
9434             }
9435             this.el.sync();
9436         }
9437     },
9438
9439     /**
9440      * Realigns the editor to the bound field based on the current alignment config value.
9441      */
9442     realign : function(){
9443         this.el.alignTo(this.boundEl, this.alignment);
9444     },
9445
9446     /**
9447      * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
9448      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
9449      */
9450     completeEdit : function(remainVisible){
9451         if(!this.editing){
9452             return;
9453         }
9454         var v = this.getValue();
9455         if(!this.field.isValid()){
9456             if(this.revertInvalid !== false){
9457                 this.cancelEdit(remainVisible);
9458             }
9459             return;
9460         }
9461         if(String(v) === String(this.startValue) && this.ignoreNoChange){
9462             this.hideEdit(remainVisible);
9463             return;
9464         }
9465         if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
9466             v = this.getValue();
9467             if(this.updateEl && this.boundEl){
9468                 this.boundEl.update(v);
9469             }
9470             this.hideEdit(remainVisible);
9471             this.fireEvent("complete", this, v, this.startValue);
9472         }
9473     },
9474
9475     // private
9476     onShow : function(){
9477         this.el.show();
9478         if(this.hideEl !== false){
9479             this.boundEl.hide();
9480         }
9481         this.field.show();
9482         if(Ext.isIE && !this.fixIEFocus){ // IE has problems with focusing the first time
9483             this.fixIEFocus = true;
9484             this.deferredFocus.defer(50, this);
9485         }else{
9486             this.field.focus();
9487         }
9488         this.fireEvent("startedit", this.boundEl, this.startValue);
9489     },
9490
9491     deferredFocus : function(){
9492         if(this.editing){
9493             this.field.focus();
9494         }
9495     },
9496
9497     /**
9498      * Cancels the editing process and hides the editor without persisting any changes.  The field value will be
9499      * reverted to the original starting value.
9500      * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
9501      * cancel (defaults to false)
9502      */
9503     cancelEdit : function(remainVisible){
9504         if(this.editing){
9505             var v = this.getValue();
9506             this.setValue(this.startValue);
9507             this.hideEdit(remainVisible);
9508             this.fireEvent("canceledit", this, v, this.startValue);
9509         }
9510     },
9511     
9512     // private
9513     hideEdit: function(remainVisible){
9514         if(remainVisible !== true){
9515             this.editing = false;
9516             this.hide();
9517         }
9518     },
9519
9520     // private
9521     onBlur : function(){
9522         if(this.allowBlur !== true && this.editing){
9523             this.completeEdit();
9524         }
9525     },
9526
9527     // private
9528     onHide : function(){
9529         if(this.editing){
9530             this.completeEdit();
9531             return;
9532         }
9533         this.field.blur();
9534         if(this.field.collapse){
9535             this.field.collapse();
9536         }
9537         this.el.hide();
9538         if(this.hideEl !== false){
9539             this.boundEl.show();
9540         }
9541     },
9542
9543     /**
9544      * Sets the data value of the editor
9545      * @param {Mixed} value Any valid value supported by the underlying field
9546      */
9547     setValue : function(v){
9548         this.field.setValue(v);
9549     },
9550
9551     /**
9552      * Gets the data value of the editor
9553      * @return {Mixed} The data value
9554      */
9555     getValue : function(){
9556         return this.field.getValue();
9557     },
9558
9559     beforeDestroy : function(){
9560         Ext.destroy(this.field);
9561         this.field = null;
9562     }
9563 });
9564 Ext.reg('editor', Ext.Editor);/**
9565  * @class Ext.ColorPalette
9566  * @extends Ext.Component
9567  * Simple color palette class for choosing colors.  The palette can be rendered to any container.<br />
9568  * Here's an example of typical usage:
9569  * <pre><code>
9570 var cp = new Ext.ColorPalette({value:'993300'});  // initial selected color
9571 cp.render('my-div');
9572
9573 cp.on('select', function(palette, selColor){
9574     // do something with selColor
9575 });
9576 </code></pre>
9577  * @constructor
9578  * Create a new ColorPalette
9579  * @param {Object} config The config object
9580  * @xtype colorpalette
9581  */
9582 Ext.ColorPalette = function(config){
9583     Ext.ColorPalette.superclass.constructor.call(this, config);
9584     this.addEvents(
9585         /**
9586              * @event select
9587              * Fires when a color is selected
9588              * @param {ColorPalette} this
9589              * @param {String} color The 6-digit color hex code (without the # symbol)
9590              */
9591         'select'
9592     );
9593
9594     if(this.handler){
9595         this.on("select", this.handler, this.scope, true);
9596     }
9597 };
9598 Ext.extend(Ext.ColorPalette, Ext.Component, {
9599         /**
9600          * @cfg {String} tpl An existing XTemplate instance to be used in place of the default template for rendering the component.
9601          */
9602     /**
9603      * @cfg {String} itemCls
9604      * The CSS class to apply to the containing element (defaults to "x-color-palette")
9605      */
9606     itemCls : "x-color-palette",
9607     /**
9608      * @cfg {String} value
9609      * The initial color to highlight (should be a valid 6-digit color hex code without the # symbol).  Note that
9610      * the hex codes are case-sensitive.
9611      */
9612     value : null,
9613     clickEvent:'click',
9614     // private
9615     ctype: "Ext.ColorPalette",
9616
9617     /**
9618      * @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the {@link #select} event
9619      */
9620     allowReselect : false,
9621
9622     /**
9623      * <p>An array of 6-digit color hex code strings (without the # symbol).  This array can contain any number
9624      * of colors, and each hex code should be unique.  The width of the palette is controlled via CSS by adjusting
9625      * the width property of the 'x-color-palette' class (or assigning a custom class), so you can balance the number
9626      * of colors with the width setting until the box is symmetrical.</p>
9627      * <p>You can override individual colors if needed:</p>
9628      * <pre><code>
9629 var cp = new Ext.ColorPalette();
9630 cp.colors[0] = "FF0000";  // change the first box to red
9631 </code></pre>
9632
9633 Or you can provide a custom array of your own for complete control:
9634 <pre><code>
9635 var cp = new Ext.ColorPalette();
9636 cp.colors = ["000000", "993300", "333300"];
9637 </code></pre>
9638      * @type Array
9639      */
9640     colors : [
9641         "000000", "993300", "333300", "003300", "003366", "000080", "333399", "333333",
9642         "800000", "FF6600", "808000", "008000", "008080", "0000FF", "666699", "808080",
9643         "FF0000", "FF9900", "99CC00", "339966", "33CCCC", "3366FF", "800080", "969696",
9644         "FF00FF", "FFCC00", "FFFF00", "00FF00", "00FFFF", "00CCFF", "993366", "C0C0C0",
9645         "FF99CC", "FFCC99", "FFFF99", "CCFFCC", "CCFFFF", "99CCFF", "CC99FF", "FFFFFF"
9646     ],
9647
9648     // private
9649     onRender : function(container, position){
9650         var t = this.tpl || new Ext.XTemplate(
9651             '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>'
9652         );
9653         var el = document.createElement("div");
9654         el.id = this.getId();
9655         el.className = this.itemCls;
9656         t.overwrite(el, this.colors);
9657         container.dom.insertBefore(el, position);
9658         this.el = Ext.get(el);
9659         this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
9660         if(this.clickEvent != 'click'){
9661                 this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
9662         }
9663     },
9664
9665     // private
9666     afterRender : function(){
9667         Ext.ColorPalette.superclass.afterRender.call(this);
9668         if(this.value){
9669             var s = this.value;
9670             this.value = null;
9671             this.select(s);
9672         }
9673     },
9674
9675     // private
9676     handleClick : function(e, t){
9677         e.preventDefault();
9678         if(!this.disabled){
9679             var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
9680             this.select(c.toUpperCase());
9681         }
9682     },
9683
9684     /**
9685      * Selects the specified color in the palette (fires the {@link #select} event)
9686      * @param {String} color A valid 6-digit color hex code (# will be stripped if included)
9687      */
9688     select : function(color){
9689         color = color.replace("#", "");
9690         if(color != this.value || this.allowReselect){
9691             var el = this.el;
9692             if(this.value){
9693                 el.child("a.color-"+this.value).removeClass("x-color-palette-sel");
9694             }
9695             el.child("a.color-"+color).addClass("x-color-palette-sel");
9696             this.value = color;
9697             this.fireEvent("select", this, color);
9698         }
9699     }
9700
9701     /**
9702      * @cfg {String} autoEl @hide
9703      */
9704 });
9705 Ext.reg('colorpalette', Ext.ColorPalette);/**\r
9706  * @class Ext.DatePicker\r
9707  * @extends Ext.Component\r
9708  * Simple date picker class.\r
9709  * @constructor\r
9710  * Create a new DatePicker\r
9711  * @param {Object} config The config object\r
9712  * @xtype datepicker\r
9713  */\r
9714 Ext.DatePicker = Ext.extend(Ext.BoxComponent, {\r
9715     /**\r
9716      * @cfg {String} todayText\r
9717      * The text to display on the button that selects the current date (defaults to <tt>'Today'</tt>)\r
9718      */\r
9719     todayText : 'Today',\r
9720     /**\r
9721      * @cfg {String} okText\r
9722      * The text to display on the ok button (defaults to <tt>'&#160;OK&#160;'</tt> to give the user extra clicking room)\r
9723      */\r
9724     okText : '&#160;OK&#160;',\r
9725     /**\r
9726      * @cfg {String} cancelText\r
9727      * The text to display on the cancel button (defaults to <tt>'Cancel'</tt>)\r
9728      */\r
9729     cancelText : 'Cancel',\r
9730     /**\r
9731      * @cfg {String} todayTip\r
9732      * The tooltip to display for the button that selects the current date (defaults to <tt>'{current date} (Spacebar)'</tt>)\r
9733      */\r
9734     todayTip : '{0} (Spacebar)',\r
9735     /**\r
9736      * @cfg {String} minText\r
9737      * The error text to display if the minDate validation fails (defaults to <tt>'This date is before the minimum date'</tt>)\r
9738      */\r
9739     minText : 'This date is before the minimum date',\r
9740     /**\r
9741      * @cfg {String} maxText\r
9742      * The error text to display if the maxDate validation fails (defaults to <tt>'This date is after the maximum date'</tt>)\r
9743      */\r
9744     maxText : 'This date is after the maximum date',\r
9745     /**\r
9746      * @cfg {String} format\r
9747      * The default date format string which can be overriden for localization support.  The format must be\r
9748      * valid according to {@link Date#parseDate} (defaults to <tt>'m/d/y'</tt>).\r
9749      */\r
9750     format : 'm/d/y',\r
9751     /**\r
9752      * @cfg {String} disabledDaysText\r
9753      * The tooltip to display when the date falls on a disabled day (defaults to <tt>'Disabled'</tt>)\r
9754      */\r
9755     disabledDaysText : 'Disabled',\r
9756     /**\r
9757      * @cfg {String} disabledDatesText\r
9758      * The tooltip text to display when the date falls on a disabled date (defaults to <tt>'Disabled'</tt>)\r
9759      */\r
9760     disabledDatesText : 'Disabled',\r
9761     /**\r
9762      * @cfg {Array} monthNames\r
9763      * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)\r
9764      */\r
9765     monthNames : Date.monthNames,\r
9766     /**\r
9767      * @cfg {Array} dayNames\r
9768      * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)\r
9769      */\r
9770     dayNames : Date.dayNames,\r
9771     /**\r
9772      * @cfg {String} nextText\r
9773      * The next month navigation button tooltip (defaults to <tt>'Next Month (Control+Right)'</tt>)\r
9774      */\r
9775     nextText : 'Next Month (Control+Right)',\r
9776     /**\r
9777      * @cfg {String} prevText\r
9778      * The previous month navigation button tooltip (defaults to <tt>'Previous Month (Control+Left)'</tt>)\r
9779      */\r
9780     prevText : 'Previous Month (Control+Left)',\r
9781     /**\r
9782      * @cfg {String} monthYearText\r
9783      * The header month selector tooltip (defaults to <tt>'Choose a month (Control+Up/Down to move years)'</tt>)\r
9784      */\r
9785     monthYearText : 'Choose a month (Control+Up/Down to move years)',\r
9786     /**\r
9787      * @cfg {Number} startDay\r
9788      * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)\r
9789      */\r
9790     startDay : 0,\r
9791     /**\r
9792      * @cfg {Boolean} showToday\r
9793      * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar\r
9794      * that selects the current date (defaults to <tt>true</tt>).\r
9795      */\r
9796     showToday : true,\r
9797     /**\r
9798      * @cfg {Date} minDate\r
9799      * Minimum allowable date (JavaScript date object, defaults to null)\r
9800      */\r
9801     /**\r
9802      * @cfg {Date} maxDate\r
9803      * Maximum allowable date (JavaScript date object, defaults to null)\r
9804      */\r
9805     /**\r
9806      * @cfg {Array} disabledDays\r
9807      * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).\r
9808      */\r
9809     /**\r
9810      * @cfg {RegExp} disabledDatesRE\r
9811      * JavaScript regular expression used to disable a pattern of dates (defaults to null).  The {@link #disabledDates}\r
9812      * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the\r
9813      * disabledDates value.\r
9814      */\r
9815     /**\r
9816      * @cfg {Array} disabledDates\r
9817      * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular\r
9818      * expression so they are very powerful. Some examples:\r
9819      * <ul>\r
9820      * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>\r
9821      * <li>['03/08', '09/16'] would disable those days for every year</li>\r
9822      * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>\r
9823      * <li>['03/../2006'] would disable every day in March 2006</li>\r
9824      * <li>['^03'] would disable every day in every March</li>\r
9825      * </ul>\r
9826      * Note that the format of the dates included in the array should exactly match the {@link #format} config.\r
9827      * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to\r
9828      * escape the dot when restricting dates. For example: ['03\\.08\\.03'].\r
9829      */\r
9830 \r
9831     // private\r
9832     initComponent : function(){\r
9833         Ext.DatePicker.superclass.initComponent.call(this);\r
9834 \r
9835         this.value = this.value ?\r
9836                  this.value.clearTime() : new Date().clearTime();\r
9837 \r
9838         this.addEvents(\r
9839             /**\r
9840              * @event select\r
9841              * Fires when a date is selected\r
9842              * @param {DatePicker} this\r
9843              * @param {Date} date The selected date\r
9844              */\r
9845             'select'\r
9846         );\r
9847 \r
9848         if(this.handler){\r
9849             this.on('select', this.handler,  this.scope || this);\r
9850         }\r
9851 \r
9852         this.initDisabledDays();\r
9853     },\r
9854 \r
9855     // private\r
9856     initDisabledDays : function(){\r
9857         if(!this.disabledDatesRE && this.disabledDates){\r
9858             var dd = this.disabledDates,\r
9859                 len = dd.length - 1,\r
9860                 re = '(?:';\r
9861                 \r
9862             Ext.each(dd, function(d, i){\r
9863                 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];\r
9864                 if(i != len){\r
9865                     re += '|';\r
9866                 }\r
9867             }, this);\r
9868             this.disabledDatesRE = new RegExp(re + ')');\r
9869         }\r
9870     },\r
9871 \r
9872     /**\r
9873      * Replaces any existing disabled dates with new values and refreshes the DatePicker.\r
9874      * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config\r
9875      * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.\r
9876      */\r
9877     setDisabledDates : function(dd){\r
9878         if(Ext.isArray(dd)){\r
9879             this.disabledDates = dd;\r
9880             this.disabledDatesRE = null;\r
9881         }else{\r
9882             this.disabledDatesRE = dd;\r
9883         }\r
9884         this.initDisabledDays();\r
9885         this.update(this.value, true);\r
9886     },\r
9887 \r
9888     /**\r
9889      * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.\r
9890      * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config\r
9891      * for details on supported values.\r
9892      */\r
9893     setDisabledDays : function(dd){\r
9894         this.disabledDays = dd;\r
9895         this.update(this.value, true);\r
9896     },\r
9897 \r
9898     /**\r
9899      * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.\r
9900      * @param {Date} value The minimum date that can be selected\r
9901      */\r
9902     setMinDate : function(dt){\r
9903         this.minDate = dt;\r
9904         this.update(this.value, true);\r
9905     },\r
9906 \r
9907     /**\r
9908      * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.\r
9909      * @param {Date} value The maximum date that can be selected\r
9910      */\r
9911     setMaxDate : function(dt){\r
9912         this.maxDate = dt;\r
9913         this.update(this.value, true);\r
9914     },\r
9915 \r
9916     /**\r
9917      * Sets the value of the date field\r
9918      * @param {Date} value The date to set\r
9919      */\r
9920     setValue : function(value){\r
9921         var old = this.value;\r
9922         this.value = value.clearTime(true);\r
9923         if(this.el){\r
9924             this.update(this.value);\r
9925         }\r
9926     },\r
9927 \r
9928     /**\r
9929      * Gets the current selected value of the date field\r
9930      * @return {Date} The selected date\r
9931      */\r
9932     getValue : function(){\r
9933         return this.value;\r
9934     },\r
9935 \r
9936     // private\r
9937     focus : function(){\r
9938         if(this.el){\r
9939             this.update(this.activeDate);\r
9940         }\r
9941     },\r
9942     \r
9943     // private\r
9944     onEnable: function(initial){\r
9945         Ext.DatePicker.superclass.onEnable.call(this);    \r
9946         this.doDisabled(false);\r
9947         this.update(initial ? this.value : this.activeDate);\r
9948         if(Ext.isIE){\r
9949             this.el.repaint();\r
9950         }\r
9951         \r
9952     },\r
9953     \r
9954     // private\r
9955     onDisable: function(){\r
9956         Ext.DatePicker.superclass.onDisable.call(this);   \r
9957         this.doDisabled(true);\r
9958         if(Ext.isIE && !Ext.isIE8){\r
9959             /* Really strange problem in IE6/7, when disabled, have to explicitly\r
9960              * repaint each of the nodes to get them to display correctly, simply\r
9961              * calling repaint on the main element doesn't appear to be enough.\r
9962              */\r
9963              Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){\r
9964                  Ext.fly(el).repaint();\r
9965              });\r
9966         }\r
9967     },\r
9968     \r
9969     // private\r
9970     doDisabled: function(disabled){\r
9971         this.keyNav.setDisabled(disabled);\r
9972         this.prevRepeater.setDisabled(disabled);\r
9973         this.nextRepeater.setDisabled(disabled);\r
9974         if(this.showToday){\r
9975             this.todayKeyListener.setDisabled(disabled);\r
9976             this.todayBtn.setDisabled(disabled);\r
9977         }\r
9978     },\r
9979 \r
9980     // private\r
9981     onRender : function(container, position){\r
9982         var m = [\r
9983              '<table cellspacing="0">',\r
9984                 '<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
9985                 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],\r
9986                 dn = this.dayNames,\r
9987                 i;\r
9988         for(i = 0; i < 7; i++){\r
9989             var d = this.startDay+i;\r
9990             if(d > 6){\r
9991                 d = d-7;\r
9992             }\r
9993             m.push('<th><span>', dn[d].substr(0,1), '</span></th>');\r
9994         }\r
9995         m[m.length] = '</tr></thead><tbody><tr>';\r
9996         for(i = 0; i < 42; i++) {\r
9997             if(i % 7 === 0 && i !== 0){\r
9998                 m[m.length] = '</tr><tr>';\r
9999             }\r
10000             m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';\r
10001         }\r
10002         m.push('</tr></tbody></table></td></tr>',\r
10003                 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',\r
10004                 '</table><div class="x-date-mp"></div>');\r
10005 \r
10006         var el = document.createElement('div');\r
10007         el.className = 'x-date-picker';\r
10008         el.innerHTML = m.join('');\r
10009 \r
10010         container.dom.insertBefore(el, position);\r
10011 \r
10012         this.el = Ext.get(el);\r
10013         this.eventEl = Ext.get(el.firstChild);\r
10014 \r
10015         this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {\r
10016             handler: this.showPrevMonth,\r
10017             scope: this,\r
10018             preventDefault:true,\r
10019             stopDefault:true\r
10020         });\r
10021 \r
10022         this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {\r
10023             handler: this.showNextMonth,\r
10024             scope: this,\r
10025             preventDefault:true,\r
10026             stopDefault:true\r
10027         });\r
10028 \r
10029         this.monthPicker = this.el.down('div.x-date-mp');\r
10030         this.monthPicker.enableDisplayMode('block');\r
10031 \r
10032         this.keyNav = new Ext.KeyNav(this.eventEl, {\r
10033             'left' : function(e){\r
10034                 if(e.ctrlKey){\r
10035                     this.showPrevMonth();\r
10036                 }else{\r
10037                     this.update(this.activeDate.add('d', -1));    \r
10038                 }\r
10039             },\r
10040 \r
10041             'right' : function(e){\r
10042                 if(e.ctrlKey){\r
10043                     this.showNextMonth();\r
10044                 }else{\r
10045                     this.update(this.activeDate.add('d', 1));    \r
10046                 }\r
10047             },\r
10048 \r
10049             'up' : function(e){\r
10050                 if(e.ctrlKey){\r
10051                     this.showNextYear();\r
10052                 }else{\r
10053                     this.update(this.activeDate.add('d', -7));\r
10054                 }\r
10055             },\r
10056 \r
10057             'down' : function(e){\r
10058                 if(e.ctrlKey){\r
10059                     this.showPrevYear();\r
10060                 }else{\r
10061                     this.update(this.activeDate.add('d', 7));\r
10062                 }\r
10063             },\r
10064 \r
10065             'pageUp' : function(e){\r
10066                 this.showNextMonth();\r
10067             },\r
10068 \r
10069             'pageDown' : function(e){\r
10070                 this.showPrevMonth();\r
10071             },\r
10072 \r
10073             'enter' : function(e){\r
10074                 e.stopPropagation();\r
10075                 return true;\r
10076             },\r
10077 \r
10078             scope : this\r
10079         });\r
10080 \r
10081         this.el.unselectable();\r
10082 \r
10083         this.cells = this.el.select('table.x-date-inner tbody td');\r
10084         this.textNodes = this.el.query('table.x-date-inner tbody span');\r
10085 \r
10086         this.mbtn = new Ext.Button({\r
10087             text: '&#160;',\r
10088             tooltip: this.monthYearText,\r
10089             renderTo: this.el.child('td.x-date-middle', true)\r
10090         });\r
10091         this.mbtn.el.child('em').addClass('x-btn-arrow');\r
10092 \r
10093         if(this.showToday){\r
10094             this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday,  this);\r
10095             var today = (new Date()).dateFormat(this.format);\r
10096             this.todayBtn = new Ext.Button({\r
10097                 renderTo: this.el.child('td.x-date-bottom', true),\r
10098                 text: String.format(this.todayText, today),\r
10099                 tooltip: String.format(this.todayTip, today),\r
10100                 handler: this.selectToday,\r
10101                 scope: this\r
10102             });\r
10103         }\r
10104         this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);\r
10105         this.mon(this.eventEl, 'click', this.handleDateClick,  this, {delegate: 'a.x-date-date'});\r
10106         this.mon(this.mbtn, 'click', this.showMonthPicker, this);\r
10107         this.onEnable(true);\r
10108     },\r
10109 \r
10110     // private\r
10111     createMonthPicker : function(){\r
10112         if(!this.monthPicker.dom.firstChild){\r
10113             var buf = ['<table border="0" cellspacing="0">'];\r
10114             for(var i = 0; i < 6; i++){\r
10115                 buf.push(\r
10116                     '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',\r
10117                     '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',\r
10118                     i === 0 ?\r
10119                     '<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
10120                     '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'\r
10121                 );\r
10122             }\r
10123             buf.push(\r
10124                 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',\r
10125                     this.okText,\r
10126                     '</button><button type="button" class="x-date-mp-cancel">',\r
10127                     this.cancelText,\r
10128                     '</button></td></tr>',\r
10129                 '</table>'\r
10130             );\r
10131             this.monthPicker.update(buf.join(''));\r
10132 \r
10133             this.mon(this.monthPicker, 'click', this.onMonthClick, this);\r
10134             this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);\r
10135 \r
10136             this.mpMonths = this.monthPicker.select('td.x-date-mp-month');\r
10137             this.mpYears = this.monthPicker.select('td.x-date-mp-year');\r
10138 \r
10139             this.mpMonths.each(function(m, a, i){\r
10140                 i += 1;\r
10141                 if((i%2) === 0){\r
10142                     m.dom.xmonth = 5 + Math.round(i * 0.5);\r
10143                 }else{\r
10144                     m.dom.xmonth = Math.round((i-1) * 0.5);\r
10145                 }\r
10146             });\r
10147         }\r
10148     },\r
10149 \r
10150     // private\r
10151     showMonthPicker : function(){\r
10152         if(!this.disabled){\r
10153             this.createMonthPicker();\r
10154             var size = this.el.getSize();\r
10155             this.monthPicker.setSize(size);\r
10156             this.monthPicker.child('table').setSize(size);\r
10157 \r
10158             this.mpSelMonth = (this.activeDate || this.value).getMonth();\r
10159             this.updateMPMonth(this.mpSelMonth);\r
10160             this.mpSelYear = (this.activeDate || this.value).getFullYear();\r
10161             this.updateMPYear(this.mpSelYear);\r
10162 \r
10163             this.monthPicker.slideIn('t', {duration:0.2});\r
10164         }\r
10165     },\r
10166 \r
10167     // private\r
10168     updateMPYear : function(y){\r
10169         this.mpyear = y;\r
10170         var ys = this.mpYears.elements;\r
10171         for(var i = 1; i <= 10; i++){\r
10172             var td = ys[i-1], y2;\r
10173             if((i%2) === 0){\r
10174                 y2 = y + Math.round(i * 0.5);\r
10175                 td.firstChild.innerHTML = y2;\r
10176                 td.xyear = y2;\r
10177             }else{\r
10178                 y2 = y - (5-Math.round(i * 0.5));\r
10179                 td.firstChild.innerHTML = y2;\r
10180                 td.xyear = y2;\r
10181             }\r
10182             this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');\r
10183         }\r
10184     },\r
10185 \r
10186     // private\r
10187     updateMPMonth : function(sm){\r
10188         this.mpMonths.each(function(m, a, i){\r
10189             m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');\r
10190         });\r
10191     },\r
10192 \r
10193     // private\r
10194     selectMPMonth : function(m){\r
10195 \r
10196     },\r
10197 \r
10198     // private\r
10199     onMonthClick : function(e, t){\r
10200         e.stopEvent();\r
10201         var el = new Ext.Element(t), pn;\r
10202         if(el.is('button.x-date-mp-cancel')){\r
10203             this.hideMonthPicker();\r
10204         }\r
10205         else if(el.is('button.x-date-mp-ok')){\r
10206             var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());\r
10207             if(d.getMonth() != this.mpSelMonth){\r
10208                 // 'fix' the JS rolling date conversion if needed\r
10209                 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();\r
10210             }\r
10211             this.update(d);\r
10212             this.hideMonthPicker();\r
10213         }\r
10214         else if((pn = el.up('td.x-date-mp-month', 2))){\r
10215             this.mpMonths.removeClass('x-date-mp-sel');\r
10216             pn.addClass('x-date-mp-sel');\r
10217             this.mpSelMonth = pn.dom.xmonth;\r
10218         }\r
10219         else if((pn = el.up('td.x-date-mp-year', 2))){\r
10220             this.mpYears.removeClass('x-date-mp-sel');\r
10221             pn.addClass('x-date-mp-sel');\r
10222             this.mpSelYear = pn.dom.xyear;\r
10223         }\r
10224         else if(el.is('a.x-date-mp-prev')){\r
10225             this.updateMPYear(this.mpyear-10);\r
10226         }\r
10227         else if(el.is('a.x-date-mp-next')){\r
10228             this.updateMPYear(this.mpyear+10);\r
10229         }\r
10230     },\r
10231 \r
10232     // private\r
10233     onMonthDblClick : function(e, t){\r
10234         e.stopEvent();\r
10235         var el = new Ext.Element(t), pn;\r
10236         if((pn = el.up('td.x-date-mp-month', 2))){\r
10237             this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));\r
10238             this.hideMonthPicker();\r
10239         }\r
10240         else if((pn = el.up('td.x-date-mp-year', 2))){\r
10241             this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));\r
10242             this.hideMonthPicker();\r
10243         }\r
10244     },\r
10245 \r
10246     // private\r
10247     hideMonthPicker : function(disableAnim){\r
10248         if(this.monthPicker){\r
10249             if(disableAnim === true){\r
10250                 this.monthPicker.hide();\r
10251             }else{\r
10252                 this.monthPicker.slideOut('t', {duration:0.2});\r
10253             }\r
10254         }\r
10255     },\r
10256 \r
10257     // private\r
10258     showPrevMonth : function(e){\r
10259         this.update(this.activeDate.add('mo', -1));\r
10260     },\r
10261 \r
10262     // private\r
10263     showNextMonth : function(e){\r
10264         this.update(this.activeDate.add('mo', 1));\r
10265     },\r
10266 \r
10267     // private\r
10268     showPrevYear : function(){\r
10269         this.update(this.activeDate.add('y', -1));\r
10270     },\r
10271 \r
10272     // private\r
10273     showNextYear : function(){\r
10274         this.update(this.activeDate.add('y', 1));\r
10275     },\r
10276 \r
10277     // private\r
10278     handleMouseWheel : function(e){\r
10279         e.stopEvent();\r
10280         if(!this.disabled){\r
10281             var delta = e.getWheelDelta();\r
10282             if(delta > 0){\r
10283                 this.showPrevMonth();\r
10284             } else if(delta < 0){\r
10285                 this.showNextMonth();\r
10286             }\r
10287         }\r
10288     },\r
10289 \r
10290     // private\r
10291     handleDateClick : function(e, t){\r
10292         e.stopEvent();\r
10293         if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){\r
10294             this.setValue(new Date(t.dateValue));\r
10295             this.fireEvent('select', this, this.value);\r
10296         }\r
10297     },\r
10298 \r
10299     // private\r
10300     selectToday : function(){\r
10301         if(this.todayBtn && !this.todayBtn.disabled){\r
10302             this.setValue(new Date().clearTime());\r
10303             this.fireEvent('select', this, this.value);\r
10304         }\r
10305     },\r
10306 \r
10307     // private\r
10308     update : function(date, forceRefresh){\r
10309         var vd = this.activeDate, vis = this.isVisible();\r
10310         this.activeDate = date;\r
10311         if(!forceRefresh && vd && this.el){\r
10312             var t = date.getTime();\r
10313             if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){\r
10314                 this.cells.removeClass('x-date-selected');\r
10315                 this.cells.each(function(c){\r
10316                    if(c.dom.firstChild.dateValue == t){\r
10317                        c.addClass('x-date-selected');\r
10318                        if(vis){\r
10319                            Ext.fly(c.dom.firstChild).focus(50);\r
10320                        }\r
10321                        return false;\r
10322                    }\r
10323                 });\r
10324                 return;\r
10325             }\r
10326         }\r
10327         var days = date.getDaysInMonth();\r
10328         var firstOfMonth = date.getFirstDateOfMonth();\r
10329         var startingPos = firstOfMonth.getDay()-this.startDay;\r
10330 \r
10331         if(startingPos <= this.startDay){\r
10332             startingPos += 7;\r
10333         }\r
10334 \r
10335         var pm = date.add('mo', -1);\r
10336         var prevStart = pm.getDaysInMonth()-startingPos;\r
10337 \r
10338         var cells = this.cells.elements;\r
10339         var textEls = this.textNodes;\r
10340         days += startingPos;\r
10341 \r
10342         // convert everything to numbers so it's fast\r
10343         var day = 86400000;\r
10344         var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();\r
10345         var today = new Date().clearTime().getTime();\r
10346         var sel = date.clearTime().getTime();\r
10347         var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;\r
10348         var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;\r
10349         var ddMatch = this.disabledDatesRE;\r
10350         var ddText = this.disabledDatesText;\r
10351         var ddays = this.disabledDays ? this.disabledDays.join('') : false;\r
10352         var ddaysText = this.disabledDaysText;\r
10353         var format = this.format;\r
10354 \r
10355         if(this.showToday){\r
10356             var td = new Date().clearTime();\r
10357             var disable = (td < min || td > max ||\r
10358                 (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||\r
10359                 (ddays && ddays.indexOf(td.getDay()) != -1));\r
10360 \r
10361             if(!this.disabled){\r
10362                 this.todayBtn.setDisabled(disable);\r
10363                 this.todayKeyListener[disable ? 'disable' : 'enable']();\r
10364             }\r
10365         }\r
10366 \r
10367         var setCellClass = function(cal, cell){\r
10368             cell.title = '';\r
10369             var t = d.getTime();\r
10370             cell.firstChild.dateValue = t;\r
10371             if(t == today){\r
10372                 cell.className += ' x-date-today';\r
10373                 cell.title = cal.todayText;\r
10374             }\r
10375             if(t == sel){\r
10376                 cell.className += ' x-date-selected';\r
10377                 if(vis){\r
10378                     Ext.fly(cell.firstChild).focus(50);\r
10379                 }\r
10380             }\r
10381             // disabling\r
10382             if(t < min) {\r
10383                 cell.className = ' x-date-disabled';\r
10384                 cell.title = cal.minText;\r
10385                 return;\r
10386             }\r
10387             if(t > max) {\r
10388                 cell.className = ' x-date-disabled';\r
10389                 cell.title = cal.maxText;\r
10390                 return;\r
10391             }\r
10392             if(ddays){\r
10393                 if(ddays.indexOf(d.getDay()) != -1){\r
10394                     cell.title = ddaysText;\r
10395                     cell.className = ' x-date-disabled';\r
10396                 }\r
10397             }\r
10398             if(ddMatch && format){\r
10399                 var fvalue = d.dateFormat(format);\r
10400                 if(ddMatch.test(fvalue)){\r
10401                     cell.title = ddText.replace('%0', fvalue);\r
10402                     cell.className = ' x-date-disabled';\r
10403                 }\r
10404             }\r
10405         };\r
10406 \r
10407         var i = 0;\r
10408         for(; i < startingPos; i++) {\r
10409             textEls[i].innerHTML = (++prevStart);\r
10410             d.setDate(d.getDate()+1);\r
10411             cells[i].className = 'x-date-prevday';\r
10412             setCellClass(this, cells[i]);\r
10413         }\r
10414         for(; i < days; i++){\r
10415             var intDay = i - startingPos + 1;\r
10416             textEls[i].innerHTML = (intDay);\r
10417             d.setDate(d.getDate()+1);\r
10418             cells[i].className = 'x-date-active';\r
10419             setCellClass(this, cells[i]);\r
10420         }\r
10421         var extraDays = 0;\r
10422         for(; i < 42; i++) {\r
10423              textEls[i].innerHTML = (++extraDays);\r
10424              d.setDate(d.getDate()+1);\r
10425              cells[i].className = 'x-date-nextday';\r
10426              setCellClass(this, cells[i]);\r
10427         }\r
10428 \r
10429         this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());\r
10430 \r
10431         if(!this.internalRender){\r
10432             var main = this.el.dom.firstChild;\r
10433             var w = main.offsetWidth;\r
10434             this.el.setWidth(w + this.el.getBorderWidth('lr'));\r
10435             Ext.fly(main).setWidth(w);\r
10436             this.internalRender = true;\r
10437             // opera does not respect the auto grow header center column\r
10438             // then, after it gets a width opera refuses to recalculate\r
10439             // without a second pass\r
10440             if(Ext.isOpera && !this.secondPass){\r
10441                 main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';\r
10442                 this.secondPass = true;\r
10443                 this.update.defer(10, this, [date]);\r
10444             }\r
10445         }\r
10446     },\r
10447 \r
10448     // private\r
10449     beforeDestroy : function() {\r
10450         if(this.rendered){\r
10451             this.keyNav.disable();\r
10452             this.keyNav = null;\r
10453             Ext.destroy(\r
10454                 this.leftClickRpt,\r
10455                 this.rightClickRpt,\r
10456                 this.monthPicker,\r
10457                 this.eventEl,\r
10458                 this.mbtn,\r
10459                 this.todayBtn\r
10460             );\r
10461         }\r
10462     }\r
10463 \r
10464     /**\r
10465      * @cfg {String} autoEl @hide\r
10466      */\r
10467 });\r
10468 \r
10469 Ext.reg('datepicker', Ext.DatePicker);\r
10470 /**
10471  * @class Ext.LoadMask
10472  * A simple utility class for generically masking elements while loading data.  If the {@link #store}
10473  * config option is specified, the masking will be automatically synchronized with the store's loading
10474  * process and the mask element will be cached for reuse.  For all other elements, this mask will replace the
10475  * element's Updater load indicator and will be destroyed after the initial load.
10476  * <p>Example usage:</p>
10477  *<pre><code>
10478 // Basic mask:
10479 var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
10480 myMask.show();
10481 </code></pre>
10482  * @constructor
10483  * Create a new LoadMask
10484  * @param {Mixed} el The element or DOM node, or its id
10485  * @param {Object} config The config object
10486  */
10487 Ext.LoadMask = function(el, config){
10488     this.el = Ext.get(el);
10489     Ext.apply(this, config);
10490     if(this.store){
10491         this.store.on('beforeload', this.onBeforeLoad, this);
10492         this.store.on('load', this.onLoad, this);
10493         this.store.on('exception', this.onLoad, this);
10494         this.removeMask = Ext.value(this.removeMask, false);
10495     }else{
10496         var um = this.el.getUpdater();
10497         um.showLoadIndicator = false; // disable the default indicator
10498         um.on('beforeupdate', this.onBeforeLoad, this);
10499         um.on('update', this.onLoad, this);
10500         um.on('failure', this.onLoad, this);
10501         this.removeMask = Ext.value(this.removeMask, true);
10502     }
10503 };
10504
10505 Ext.LoadMask.prototype = {
10506     /**
10507      * @cfg {Ext.data.Store} store
10508      * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and
10509      * hidden on either load sucess, or load fail.
10510      */
10511     /**
10512      * @cfg {Boolean} removeMask
10513      * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
10514      * False to persist the mask element reference for multiple uses (e.g., for paged data widgets).  Defaults to false.
10515      */
10516     /**
10517      * @cfg {String} msg
10518      * The text to display in a centered loading message box (defaults to 'Loading...')
10519      */
10520     msg : 'Loading...',
10521     /**
10522      * @cfg {String} msgCls
10523      * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
10524      */
10525     msgCls : 'x-mask-loading',
10526
10527     /**
10528      * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
10529      * @type Boolean
10530      */
10531     disabled: false,
10532
10533     /**
10534      * Disables the mask to prevent it from being displayed
10535      */
10536     disable : function(){
10537        this.disabled = true;
10538     },
10539
10540     /**
10541      * Enables the mask so that it can be displayed
10542      */
10543     enable : function(){
10544         this.disabled = false;
10545     },
10546
10547     // private
10548     onLoad : function(){
10549         this.el.unmask(this.removeMask);
10550     },
10551
10552     // private
10553     onBeforeLoad : function(){
10554         if(!this.disabled){
10555             this.el.mask(this.msg, this.msgCls);
10556         }
10557     },
10558
10559     /**
10560      * Show this LoadMask over the configured Element.
10561      */
10562     show: function(){
10563         this.onBeforeLoad();
10564     },
10565
10566     /**
10567      * Hide this LoadMask.
10568      */
10569     hide: function(){
10570         this.onLoad();
10571     },
10572
10573     // private
10574     destroy : function(){
10575         if(this.store){
10576             this.store.un('beforeload', this.onBeforeLoad, this);
10577             this.store.un('load', this.onLoad, this);
10578             this.store.un('exception', this.onLoad, this);
10579         }else{
10580             var um = this.el.getUpdater();
10581             um.un('beforeupdate', this.onBeforeLoad, this);
10582             um.un('update', this.onLoad, this);
10583             um.un('failure', this.onLoad, this);
10584         }
10585     }
10586 };/**\r
10587  * @class Ext.Slider\r
10588  * @extends Ext.BoxComponent\r
10589  * Slider which supports vertical or horizontal orientation, keyboard adjustments,\r
10590  * configurable snapping, axis clicking and animation. Can be added as an item to\r
10591  * any container. Example usage:\r
10592 <pre><code>\r
10593 new Ext.Slider({\r
10594     renderTo: Ext.getBody(),\r
10595     width: 200,\r
10596     value: 50,\r
10597     increment: 10,\r
10598     minValue: 0,\r
10599     maxValue: 100\r
10600 });\r
10601 </code></pre>\r
10602  */\r
10603 Ext.Slider = Ext.extend(Ext.BoxComponent, {\r
10604         /**\r
10605          * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.\r
10606          */\r
10607         /**\r
10608          * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.\r
10609          */\r
10610     vertical: false,\r
10611         /**\r
10612          * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.\r
10613          */\r
10614     minValue: 0,\r
10615         /**\r
10616          * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.\r
10617          */\r
10618     maxValue: 100,\r
10619     /**\r
10620      * @cfg {Number/Boolean} decimalPrecision.\r
10621      * <p>The number of decimal places to which to round the Slider's value. Defaults to 0.</p>\r
10622      * <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>\r
10623      */\r
10624     decimalPrecision: 0,\r
10625         /**\r
10626          * @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
10627          */\r
10628     keyIncrement: 1,\r
10629         /**\r
10630          * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.\r
10631          */\r
10632     increment: 0,\r
10633         // private\r
10634     clickRange: [5,15],\r
10635         /**\r
10636          * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true\r
10637          */\r
10638     clickToChange : true,\r
10639         /**\r
10640          * @cfg {Boolean} animate Turn on or off animation. Defaults to true\r
10641          */\r
10642     animate: true,\r
10643 \r
10644     /**\r
10645      * True while the thumb is in a drag operation\r
10646      * @type boolean\r
10647      */\r
10648     dragging: false,\r
10649 \r
10650     // private override\r
10651     initComponent : function(){\r
10652         if(!Ext.isDefined(this.value)){\r
10653             this.value = this.minValue;\r
10654         }\r
10655         Ext.Slider.superclass.initComponent.call(this);\r
10656         this.keyIncrement = Math.max(this.increment, this.keyIncrement);\r
10657         this.addEvents(\r
10658             /**\r
10659              * @event beforechange\r
10660              * Fires before the slider value is changed. By returning false from an event handler,\r
10661              * you can cancel the event and prevent the slider from changing.\r
10662                          * @param {Ext.Slider} slider The slider\r
10663                          * @param {Number} newValue The new value which the slider is being changed to.\r
10664                          * @param {Number} oldValue The old value which the slider was previously.\r
10665              */\r
10666                         'beforechange',\r
10667                         /**\r
10668                          * @event change\r
10669                          * Fires when the slider value is changed.\r
10670                          * @param {Ext.Slider} slider The slider\r
10671                          * @param {Number} newValue The new value which the slider has been changed to.\r
10672                          */\r
10673                         'change',\r
10674                         /**\r
10675                          * @event changecomplete\r
10676                          * Fires when the slider value is changed by the user and any drag operations have completed.\r
10677                          * @param {Ext.Slider} slider The slider\r
10678                          * @param {Number} newValue The new value which the slider has been changed to.\r
10679                          */\r
10680                         'changecomplete',\r
10681                         /**\r
10682                          * @event dragstart\r
10683              * Fires after a drag operation has started.\r
10684                          * @param {Ext.Slider} slider The slider\r
10685                          * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
10686                          */\r
10687                         'dragstart',\r
10688                         /**\r
10689                          * @event drag\r
10690              * Fires continuously during the drag operation while the mouse is moving.\r
10691                          * @param {Ext.Slider} slider The slider\r
10692                          * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
10693                          */\r
10694                         'drag',\r
10695                         /**\r
10696                          * @event dragend\r
10697              * Fires after the drag operation has completed.\r
10698                          * @param {Ext.Slider} slider The slider\r
10699                          * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker\r
10700                          */\r
10701                         'dragend'\r
10702                 );\r
10703 \r
10704         if(this.vertical){\r
10705             Ext.apply(this, Ext.Slider.Vertical);\r
10706         }\r
10707     },\r
10708 \r
10709         // private override\r
10710     onRender : function(){\r
10711         this.autoEl = {\r
10712             cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),\r
10713             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
10714         };\r
10715         Ext.Slider.superclass.onRender.apply(this, arguments);\r
10716         this.endEl = this.el.first();\r
10717         this.innerEl = this.endEl.first();\r
10718         this.thumb = this.innerEl.first();\r
10719         this.halfThumb = (this.vertical ? this.thumb.getHeight() : this.thumb.getWidth())/2;\r
10720         this.focusEl = this.thumb.next();\r
10721         this.initEvents();\r
10722     },\r
10723 \r
10724         // private override\r
10725     initEvents : function(){\r
10726         this.thumb.addClassOnOver('x-slider-thumb-over');\r
10727         this.mon(this.el, {\r
10728             scope: this,\r
10729             mousedown: this.onMouseDown,\r
10730             keydown: this.onKeyDown\r
10731         });\r
10732 \r
10733         this.focusEl.swallowEvent("click", true);\r
10734 \r
10735         this.tracker = new Ext.dd.DragTracker({\r
10736             onBeforeStart: this.onBeforeDragStart.createDelegate(this),\r
10737             onStart: this.onDragStart.createDelegate(this),\r
10738             onDrag: this.onDrag.createDelegate(this),\r
10739             onEnd: this.onDragEnd.createDelegate(this),\r
10740             tolerance: 3,\r
10741             autoStart: 300\r
10742         });\r
10743         this.tracker.initEl(this.thumb);\r
10744         this.on('beforedestroy', this.tracker.destroy, this.tracker);\r
10745     },\r
10746 \r
10747         // private override\r
10748     onMouseDown : function(e){\r
10749         if(this.disabled) {return;}\r
10750         if(this.clickToChange && e.target != this.thumb.dom){\r
10751             var local = this.innerEl.translatePoints(e.getXY());\r
10752             this.onClickChange(local);\r
10753         }\r
10754         this.focus();\r
10755     },\r
10756 \r
10757         // private\r
10758     onClickChange : function(local){\r
10759         if(local.top > this.clickRange[0] && local.top < this.clickRange[1]){\r
10760             this.setValue(Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);\r
10761         }\r
10762     },\r
10763 \r
10764         // private\r
10765     onKeyDown : function(e){\r
10766         if(this.disabled){e.preventDefault();return;}\r
10767         var k = e.getKey();\r
10768         switch(k){\r
10769             case e.UP:\r
10770             case e.RIGHT:\r
10771                 e.stopEvent();\r
10772                 if(e.ctrlKey){\r
10773                     this.setValue(this.maxValue, undefined, true);\r
10774                 }else{\r
10775                     this.setValue(this.value+this.keyIncrement, undefined, true);\r
10776                 }\r
10777             break;\r
10778             case e.DOWN:\r
10779             case e.LEFT:\r
10780                 e.stopEvent();\r
10781                 if(e.ctrlKey){\r
10782                     this.setValue(this.minValue, undefined, true);\r
10783                 }else{\r
10784                     this.setValue(this.value-this.keyIncrement, undefined, true);\r
10785                 }\r
10786             break;\r
10787             default:\r
10788                 e.preventDefault();\r
10789         }\r
10790     },\r
10791 \r
10792         // private\r
10793     doSnap : function(value){\r
10794         if(!this.increment || this.increment == 1 || !value) {\r
10795             return value;\r
10796         }\r
10797         var newValue = value, inc = this.increment;\r
10798         var m = value % inc;\r
10799         if(m != 0){\r
10800             newValue -= m;\r
10801             if(m * 2 > inc){\r
10802                 newValue += inc;\r
10803             }else if(m * 2 < -inc){\r
10804                 newValue -= inc;\r
10805             }\r
10806         }\r
10807         return newValue.constrain(this.minValue,  this.maxValue);\r
10808     },\r
10809 \r
10810         // private\r
10811     afterRender : function(){\r
10812         Ext.Slider.superclass.afterRender.apply(this, arguments);\r
10813         if(this.value !== undefined){\r
10814             var v = this.normalizeValue(this.value);\r
10815             if(v !== this.value){\r
10816                 delete this.value;\r
10817                 this.setValue(v, false);\r
10818             }else{\r
10819                 this.moveThumb(this.translateValue(v), false);\r
10820             }\r
10821         }\r
10822     },\r
10823 \r
10824         // private\r
10825     getRatio : function(){\r
10826         var w = this.innerEl.getWidth();\r
10827         var v = this.maxValue - this.minValue;\r
10828         return v == 0 ? w : (w/v);\r
10829     },\r
10830 \r
10831         // private\r
10832     normalizeValue : function(v){\r
10833         v = this.doSnap(v);\r
10834         v = Ext.util.Format.round(v, this.decimalPrecision);\r
10835         v = v.constrain(this.minValue, this.maxValue);\r
10836         return v;\r
10837     },\r
10838 \r
10839         /**\r
10840          * Programmatically sets the value of the Slider. Ensures that the value is constrained within\r
10841          * the minValue and maxValue.\r
10842          * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)\r
10843          * @param {Boolean} animate Turn on or off animation, defaults to true\r
10844          */\r
10845     setValue : function(v, animate, changeComplete){\r
10846         v = this.normalizeValue(v);\r
10847         if(v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false){\r
10848             this.value = v;\r
10849             this.moveThumb(this.translateValue(v), animate !== false);\r
10850             this.fireEvent('change', this, v);\r
10851             if(changeComplete){\r
10852                 this.fireEvent('changecomplete', this, v);\r
10853             }\r
10854         }\r
10855     },\r
10856 \r
10857         // private\r
10858     translateValue : function(v){\r
10859         var ratio = this.getRatio();\r
10860         return (v * ratio)-(this.minValue * ratio)-this.halfThumb;\r
10861     },\r
10862 \r
10863         reverseValue : function(pos){\r
10864         var ratio = this.getRatio();\r
10865         return (pos+this.halfThumb+(this.minValue * ratio))/ratio;\r
10866     },\r
10867 \r
10868         // private\r
10869     moveThumb: function(v, animate){\r
10870         if(!animate || this.animate === false){\r
10871             this.thumb.setLeft(v);\r
10872         }else{\r
10873             this.thumb.shift({left: v, stopFx: true, duration:.35});\r
10874         }\r
10875     },\r
10876 \r
10877         // private\r
10878     focus : function(){\r
10879         this.focusEl.focus(10);\r
10880     },\r
10881 \r
10882         // private\r
10883     onBeforeDragStart : function(e){\r
10884         return !this.disabled;\r
10885     },\r
10886 \r
10887         // private\r
10888     onDragStart: function(e){\r
10889         this.thumb.addClass('x-slider-thumb-drag');\r
10890         this.dragging = true;\r
10891         this.dragStartValue = this.value;\r
10892         this.fireEvent('dragstart', this, e);\r
10893     },\r
10894 \r
10895         // private\r
10896     onDrag: function(e){\r
10897         var pos = this.innerEl.translatePoints(this.tracker.getXY());\r
10898         this.setValue(Ext.util.Format.round(this.reverseValue(pos.left), this.decimalPrecision), false);\r
10899         this.fireEvent('drag', this, e);\r
10900     },\r
10901 \r
10902         // private\r
10903     onDragEnd: function(e){\r
10904         this.thumb.removeClass('x-slider-thumb-drag');\r
10905         this.dragging = false;\r
10906         this.fireEvent('dragend', this, e);\r
10907         if(this.dragStartValue != this.value){\r
10908             this.fireEvent('changecomplete', this, this.value);\r
10909         }\r
10910     },\r
10911 \r
10912         // private\r
10913     onResize : function(w, h){\r
10914         this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));\r
10915         this.syncThumb();\r
10916     },\r
10917     \r
10918     //private\r
10919     onDisable: function(){\r
10920         Ext.Slider.superclass.onDisable.call(this);\r
10921         this.thumb.addClass(this.disabledClass);\r
10922         if(Ext.isIE){\r
10923             //IE breaks when using overflow visible and opacity other than 1.\r
10924             //Create a place holder for the thumb and display it.\r
10925             var xy = this.thumb.getXY();\r
10926             this.thumb.hide();\r
10927             this.innerEl.addClass(this.disabledClass).dom.disabled = true;\r
10928             if (!this.thumbHolder){\r
10929                 this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});    \r
10930             }\r
10931             this.thumbHolder.show().setXY(xy);\r
10932         }\r
10933     },\r
10934     \r
10935     //private\r
10936     onEnable: function(){\r
10937         Ext.Slider.superclass.onEnable.call(this);\r
10938         this.thumb.removeClass(this.disabledClass);\r
10939         if(Ext.isIE){\r
10940             this.innerEl.removeClass(this.disabledClass).dom.disabled = false;\r
10941             if (this.thumbHolder){\r
10942                 this.thumbHolder.hide();\r
10943             }\r
10944             this.thumb.show();\r
10945             this.syncThumb();\r
10946         }\r
10947     },\r
10948     \r
10949     /**\r
10950      * Synchronizes the thumb position to the proper proportion of the total component width based\r
10951      * on the current slider {@link #value}.  This will be called automatically when the Slider\r
10952      * is resized by a layout, but if it is rendered auto width, this method can be called from\r
10953      * another resize handler to sync the Slider if necessary.\r
10954      */\r
10955     syncThumb : function(){\r
10956         if(this.rendered){\r
10957             this.moveThumb(this.translateValue(this.value));\r
10958         }\r
10959     },\r
10960 \r
10961         /**\r
10962          * Returns the current value of the slider\r
10963          * @return {Number} The current value of the slider\r
10964          */\r
10965     getValue : function(){\r
10966         return this.value;\r
10967     }\r
10968 });\r
10969 Ext.reg('slider', Ext.Slider);\r
10970 \r
10971 // private class to support vertical sliders\r
10972 Ext.Slider.Vertical = {\r
10973     onResize : function(w, h){\r
10974         this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));\r
10975         this.syncThumb();\r
10976     },\r
10977 \r
10978     getRatio : function(){\r
10979         var h = this.innerEl.getHeight();\r
10980         var v = this.maxValue - this.minValue;\r
10981         return h/v;\r
10982     },\r
10983 \r
10984     moveThumb: function(v, animate){\r
10985         if(!animate || this.animate === false){\r
10986             this.thumb.setBottom(v);\r
10987         }else{\r
10988             this.thumb.shift({bottom: v, stopFx: true, duration:.35});\r
10989         }\r
10990     },\r
10991 \r
10992     onDrag: function(e){\r
10993         var pos = this.innerEl.translatePoints(this.tracker.getXY());\r
10994         var bottom = this.innerEl.getHeight()-pos.top;\r
10995         this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), false);\r
10996         this.fireEvent('drag', this, e);\r
10997     },\r
10998 \r
10999     onClickChange : function(local){\r
11000         if(local.left > this.clickRange[0] && local.left < this.clickRange[1]){\r
11001             var bottom = this.innerEl.getHeight()-local.top;\r
11002             this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), undefined, true);\r
11003         }\r
11004     }\r
11005 };/**\r
11006  * @class Ext.ProgressBar\r
11007  * @extends Ext.BoxComponent\r
11008  * <p>An updateable progress bar component.  The progress bar supports two different modes: manual and automatic.</p>\r
11009  * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the\r
11010  * progress bar as needed from your own code.  This method is most appropriate when you want to show progress\r
11011  * throughout an operation that has predictable points of interest at which you can update the control.</p>\r
11012  * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it\r
11013  * once the operation is complete.  You can optionally have the progress bar wait for a specific amount of time\r
11014  * and then clear itself.  Automatic mode is most appropriate for timed operations or asynchronous operations in\r
11015  * which you have no need for indicating intermediate progress.</p>\r
11016  * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0)\r
11017  * @cfg {String} text The progress bar text (defaults to '')\r
11018  * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress\r
11019  * bar's internal text element)\r
11020  * @cfg {String} id The progress bar element's id (defaults to an auto-generated id)\r
11021  * @xtype progress\r
11022  */\r
11023 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {\r
11024    /**\r
11025     * @cfg {String} baseCls\r
11026     * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress')\r
11027     */\r
11028     baseCls : 'x-progress',\r
11029     \r
11030     /**\r
11031     * @cfg {Boolean} animate\r
11032     * True to animate the progress bar during transitions (defaults to false)\r
11033     */\r
11034     animate : false,\r
11035 \r
11036     // private\r
11037     waitTimer : null,\r
11038 \r
11039     // private\r
11040     initComponent : function(){\r
11041         Ext.ProgressBar.superclass.initComponent.call(this);\r
11042         this.addEvents(\r
11043             /**\r
11044              * @event update\r
11045              * Fires after each update interval\r
11046              * @param {Ext.ProgressBar} this\r
11047              * @param {Number} The current progress value\r
11048              * @param {String} The current progress text\r
11049              */\r
11050             "update"\r
11051         );\r
11052     },\r
11053 \r
11054     // private\r
11055     onRender : function(ct, position){\r
11056         var tpl = new Ext.Template(\r
11057             '<div class="{cls}-wrap">',\r
11058                 '<div class="{cls}-inner">',\r
11059                     '<div class="{cls}-bar">',\r
11060                         '<div class="{cls}-text">',\r
11061                             '<div>&#160;</div>',\r
11062                         '</div>',\r
11063                     '</div>',\r
11064                     '<div class="{cls}-text {cls}-text-back">',\r
11065                         '<div>&#160;</div>',\r
11066                     '</div>',\r
11067                 '</div>',\r
11068             '</div>'\r
11069         );\r
11070 \r
11071         this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)\r
11072                 : tpl.append(ct, {cls: this.baseCls}, true);\r
11073                         \r
11074         if(this.id){\r
11075             this.el.dom.id = this.id;\r
11076         }\r
11077         var inner = this.el.dom.firstChild;\r
11078         this.progressBar = Ext.get(inner.firstChild);\r
11079 \r
11080         if(this.textEl){\r
11081             //use an external text el\r
11082             this.textEl = Ext.get(this.textEl);\r
11083             delete this.textTopEl;\r
11084         }else{\r
11085             //setup our internal layered text els\r
11086             this.textTopEl = Ext.get(this.progressBar.dom.firstChild);\r
11087             var textBackEl = Ext.get(inner.childNodes[1]);\r
11088             this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');\r
11089             this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);\r
11090             this.textEl.setWidth(inner.offsetWidth);\r
11091         }\r
11092         this.progressBar.setHeight(inner.offsetHeight);\r
11093     },\r
11094     \r
11095     // private\r
11096     afterRender : function(){\r
11097         Ext.ProgressBar.superclass.afterRender.call(this);\r
11098         if(this.value){\r
11099             this.updateProgress(this.value, this.text);\r
11100         }else{\r
11101             this.updateText(this.text);\r
11102         }\r
11103     },\r
11104 \r
11105     /**\r
11106      * Updates the progress bar value, and optionally its text.  If the text argument is not specified,\r
11107      * any existing text value will be unchanged.  To blank out existing text, pass ''.  Note that even\r
11108      * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for\r
11109      * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control.\r
11110      * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0)\r
11111      * @param {String} text (optional) The string to display in the progress text element (defaults to '')\r
11112      * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is\r
11113      * not specified, the default for the class is used (default to false)\r
11114      * @return {Ext.ProgressBar} this\r
11115      */\r
11116     updateProgress : function(value, text, animate){\r
11117         this.value = value || 0;\r
11118         if(text){\r
11119             this.updateText(text);\r
11120         }\r
11121         if(this.rendered){\r
11122             var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);\r
11123             this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));\r
11124             if(this.textTopEl){\r
11125                 //textTopEl should be the same width as the bar so overflow will clip as the bar moves\r
11126                 this.textTopEl.removeClass('x-hidden').setWidth(w);\r
11127             }\r
11128         }\r
11129         this.fireEvent('update', this, value, text);\r
11130         return this;\r
11131     },\r
11132 \r
11133     /**\r
11134      * Initiates an auto-updating progress bar.  A duration can be specified, in which case the progress\r
11135      * bar will automatically reset after a fixed amount of time and optionally call a callback function\r
11136      * if specified.  If no duration is passed in, then the progress bar will run indefinitely and must\r
11137      * be manually cleared by calling {@link #reset}.  The wait method accepts a config object with\r
11138      * the following properties:\r
11139      * <pre>\r
11140 Property   Type          Description\r
11141 ---------- ------------  ----------------------------------------------------------------------\r
11142 duration   Number        The length of time in milliseconds that the progress bar should\r
11143                          run before resetting itself (defaults to undefined, in which case it\r
11144                          will run indefinitely until reset is called)\r
11145 interval   Number        The length of time in milliseconds between each progress update\r
11146                          (defaults to 1000 ms)\r
11147 animate    Boolean       Whether to animate the transition of the progress bar. If this value is\r
11148                          not specified, the default for the class is used.                                                   \r
11149 increment  Number        The number of progress update segments to display within the progress\r
11150                          bar (defaults to 10).  If the bar reaches the end and is still\r
11151                          updating, it will automatically wrap back to the beginning.\r
11152 text       String        Optional text to display in the progress bar element (defaults to '').\r
11153 fn         Function      A callback function to execute after the progress bar finishes auto-\r
11154                          updating.  The function will be called with no arguments.  This function\r
11155                          will be ignored if duration is not specified since in that case the\r
11156                          progress bar can only be stopped programmatically, so any required function\r
11157                          should be called by the same code after it resets the progress bar.\r
11158 scope      Object        The scope that is passed to the callback function (only applies when\r
11159                          duration and fn are both passed).\r
11160 </pre>\r
11161          *\r
11162          * Example usage:\r
11163          * <pre><code>\r
11164 var p = new Ext.ProgressBar({\r
11165    renderTo: 'my-el'\r
11166 });\r
11167 \r
11168 //Wait for 5 seconds, then update the status el (progress bar will auto-reset)\r
11169 p.wait({\r
11170    interval: 100, //bar will move fast!\r
11171    duration: 5000,\r
11172    increment: 15,\r
11173    text: 'Updating...',\r
11174    scope: this,\r
11175    fn: function(){\r
11176       Ext.fly('status').update('Done!');\r
11177    }\r
11178 });\r
11179 \r
11180 //Or update indefinitely until some async action completes, then reset manually\r
11181 p.wait();\r
11182 myAction.on('complete', function(){\r
11183     p.reset();\r
11184     Ext.fly('status').update('Done!');\r
11185 });\r
11186 </code></pre>\r
11187      * @param {Object} config (optional) Configuration options\r
11188      * @return {Ext.ProgressBar} this\r
11189      */\r
11190     wait : function(o){\r
11191         if(!this.waitTimer){\r
11192             var scope = this;\r
11193             o = o || {};\r
11194             this.updateText(o.text);\r
11195             this.waitTimer = Ext.TaskMgr.start({\r
11196                 run: function(i){\r
11197                     var inc = o.increment || 10;\r
11198                     this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);\r
11199                 },\r
11200                 interval: o.interval || 1000,\r
11201                 duration: o.duration,\r
11202                 onStop: function(){\r
11203                     if(o.fn){\r
11204                         o.fn.apply(o.scope || this);\r
11205                     }\r
11206                     this.reset();\r
11207                 },\r
11208                 scope: scope\r
11209             });\r
11210         }\r
11211         return this;\r
11212     },\r
11213 \r
11214     /**\r
11215      * Returns true if the progress bar is currently in a {@link #wait} operation\r
11216      * @return {Boolean} True if waiting, else false\r
11217      */\r
11218     isWaiting : function(){\r
11219         return this.waitTimer !== null;\r
11220     },\r
11221 \r
11222     /**\r
11223      * Updates the progress bar text.  If specified, textEl will be updated, otherwise the progress\r
11224      * bar itself will display the updated text.\r
11225      * @param {String} text (optional) The string to display in the progress text element (defaults to '')\r
11226      * @return {Ext.ProgressBar} this\r
11227      */\r
11228     updateText : function(text){\r
11229         this.text = text || '&#160;';\r
11230         if(this.rendered){\r
11231             this.textEl.update(this.text);\r
11232         }\r
11233         return this;\r
11234     },\r
11235     \r
11236     /**\r
11237      * Synchronizes the inner bar width to the proper proportion of the total componet width based\r
11238      * on the current progress {@link #value}.  This will be called automatically when the ProgressBar\r
11239      * is resized by a layout, but if it is rendered auto width, this method can be called from\r
11240      * another resize handler to sync the ProgressBar if necessary.\r
11241      */\r
11242     syncProgressBar : function(){\r
11243         if(this.value){\r
11244             this.updateProgress(this.value, this.text);\r
11245         }\r
11246         return this;\r
11247     },\r
11248 \r
11249     /**\r
11250      * Sets the size of the progress bar.\r
11251      * @param {Number} width The new width in pixels\r
11252      * @param {Number} height The new height in pixels\r
11253      * @return {Ext.ProgressBar} this\r
11254      */\r
11255     setSize : function(w, h){\r
11256         Ext.ProgressBar.superclass.setSize.call(this, w, h);\r
11257         if(this.textTopEl){\r
11258             var inner = this.el.dom.firstChild;\r
11259             this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);\r
11260         }\r
11261         this.syncProgressBar();\r
11262         return this;\r
11263     },\r
11264 \r
11265     /**\r
11266      * Resets the progress bar value to 0 and text to empty string.  If hide = true, the progress\r
11267      * bar will also be hidden (using the {@link #hideMode} property internally).\r
11268      * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false)\r
11269      * @return {Ext.ProgressBar} this\r
11270      */\r
11271     reset : function(hide){\r
11272         this.updateProgress(0);\r
11273         if(this.textTopEl){\r
11274             this.textTopEl.addClass('x-hidden');\r
11275         }\r
11276         if(this.waitTimer){\r
11277             this.waitTimer.onStop = null; //prevent recursion\r
11278             Ext.TaskMgr.stop(this.waitTimer);\r
11279             this.waitTimer = null;\r
11280         }\r
11281         if(hide === true){\r
11282             this.hide();\r
11283         }\r
11284         return this;\r
11285     }\r
11286 });\r
11287 Ext.reg('progress', Ext.ProgressBar);