3 * Copyright(c) 2006-2010 Ext JS, LLC
5 * http://www.extjs.com/license
8 * @class Ext.ComponentMgr
9 * <p>Provides a registry of all Components (instances of {@link Ext.Component} or any subclass
10 * thereof) on a page so that they can be easily accessed by {@link Ext.Component component}
11 * {@link Ext.Component#id id} (see {@link #get}, or the convenience method {@link Ext#getCmp Ext.getCmp}).</p>
12 * <p>This object also provides a registry of available Component <i>classes</i>
13 * indexed by a mnemonic code known as the Component's {@link Ext.Component#xtype xtype}.
14 * The <code>{@link Ext.Component#xtype xtype}</code> provides a way to avoid instantiating child Components
15 * when creating a full, nested config object for a complete Ext page.</p>
16 * <p>A child Component may be specified simply as a <i>config object</i>
17 * as long as the correct <code>{@link Ext.Component#xtype xtype}</code> is specified so that if and when the Component
18 * needs rendering, the correct type can be looked up for lazy instantiation.</p>
19 * <p>For a list of all available <code>{@link Ext.Component#xtype xtypes}</code>, see {@link Ext.Component}.</p>
22 Ext.ComponentMgr = function(){
23 var all = new Ext.util.MixedCollection();
29 * Registers a component.
30 * @param {Ext.Component} c The component
32 register : function(c){
37 * Unregisters a component.
38 * @param {Ext.Component} c The component
40 unregister : function(c){
45 * Returns a component by {@link Ext.Component#id id}.
46 * For additional details see {@link Ext.util.MixedCollection#get}.
47 * @param {String} id The component {@link Ext.Component#id id}
48 * @return Ext.Component The Component, <code>undefined</code> if not found, or <code>null</code> if a
56 * Registers a function that will be called when a Component with the specified id is added to ComponentMgr. This will happen on instantiation.
57 * @param {String} id The component {@link Ext.Component#id id}
58 * @param {Function} fn The callback function
59 * @param {Object} scope The scope (<code>this</code> reference) in which the callback is executed. Defaults to the Component.
61 onAvailable : function(id, fn, scope){
62 all.on("add", function(index, o){
64 fn.call(scope || o, o);
65 all.un("add", fn, scope);
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}
78 * The xtypes that have been registered with the component manager.
84 * The ptypes that have been registered with the component manager.
90 * Checks if a Component type is registered.
91 * @param {Ext.Component} xtype The mnemonic string by which the Component class may be looked up
92 * @return {Boolean} Whether the type is registered.
94 isRegistered : function(xtype){
95 return types[xtype] !== undefined;
99 * Checks if a Plugin type is registered.
100 * @param {Ext.Component} ptype The mnemonic string by which the Plugin class may be looked up
101 * @return {Boolean} Whether the type is registered.
103 isPluginRegistered : function(ptype){
104 return ptypes[ptype] !== undefined;
108 * <p>Registers a new Component constructor, keyed by a new
109 * {@link Ext.Component#xtype}.</p>
110 * <p>Use this method (or its alias {@link Ext#reg Ext.reg}) to register new
111 * subclasses of {@link Ext.Component} so that lazy instantiation may be used when specifying
113 * see {@link Ext.Container#items}</p>
114 * @param {String} xtype The mnemonic string by which the Component class may be looked up.
115 * @param {Constructor} cls The new Component class.
117 registerType : function(xtype, cls){
123 * Creates a new Component from the specified config object using the
124 * config object's {@link Ext.component#xtype xtype} to determine the class to instantiate.
125 * @param {Object} config A configuration object for the Component you wish to create.
126 * @param {Constructor} defaultType The constructor to provide the default Component type if
127 * the config object does not contain a <code>xtype</code>. (Optional if the config contains a <code>xtype</code>).
128 * @return {Ext.Component} The newly instantiated Component.
130 create : function(config, defaultType){
131 return config.render ? config : new types[config.xtype || defaultType](config);
135 * <p>Registers a new Plugin constructor, keyed by a new
136 * {@link Ext.Component#ptype}.</p>
137 * <p>Use this method (or its alias {@link Ext#preg Ext.preg}) to register new
138 * plugins for {@link Ext.Component}s so that lazy instantiation may be used when specifying
140 * @param {String} ptype The mnemonic string by which the Plugin class may be looked up.
141 * @param {Constructor} cls The new Plugin class.
143 registerPlugin : function(ptype, cls){
149 * Creates a new Plugin from the specified config object using the
150 * config object's {@link Ext.component#ptype ptype} to determine the class to instantiate.
151 * @param {Object} config A configuration object for the Plugin you wish to create.
152 * @param {Constructor} defaultType The constructor to provide the default Plugin type if
153 * the config object does not contain a <code>ptype</code>. (Optional if the config contains a <code>ptype</code>).
154 * @return {Ext.Component} The newly instantiated Plugin.
156 createPlugin : function(config, defaultType){
157 var PluginCls = ptypes[config.ptype || defaultType];
158 if (PluginCls.init) {
161 return new PluginCls(config);
168 * Shorthand for {@link Ext.ComponentMgr#registerType}
169 * @param {String} xtype The {@link Ext.component#xtype mnemonic string} by which the Component class
171 * @param {Constructor} cls The new Component class.
175 Ext.reg = Ext.ComponentMgr.registerType; // this will be called a lot internally, shorthand to keep the bytes down
177 * Shorthand for {@link Ext.ComponentMgr#registerPlugin}
178 * @param {String} ptype The {@link Ext.component#ptype mnemonic string} by which the Plugin class
180 * @param {Constructor} cls The new Plugin class.
184 Ext.preg = Ext.ComponentMgr.registerPlugin;
186 * Shorthand for {@link Ext.ComponentMgr#create}
187 * Creates a new Component from the specified config object using the
188 * config object's {@link Ext.component#xtype xtype} to determine the class to instantiate.
189 * @param {Object} config A configuration object for the Component you wish to create.
190 * @param {Constructor} defaultType The constructor to provide the default Component type if
191 * the config object does not contain a <code>xtype</code>. (Optional if the config contains a <code>xtype</code>).
192 * @return {Ext.Component} The newly instantiated Component.
196 Ext.create = Ext.ComponentMgr.create;/**
197 * @class Ext.Component
198 * @extends Ext.util.Observable
199 * <p>Base class for all Ext components. All subclasses of Component may participate in the automated
200 * Ext component lifecycle of creation, rendering and destruction which is provided by the {@link Ext.Container Container} class.
201 * Components may be added to a Container through the {@link Ext.Container#items items} config option at the time the Container is created,
202 * or they may be added dynamically via the {@link Ext.Container#add add} method.</p>
203 * <p>The Component base class has built-in support for basic hide/show and enable/disable behavior.</p>
204 * <p>All Components are registered with the {@link Ext.ComponentMgr} on construction so that they can be referenced at any time via
205 * {@link Ext#getCmp}, passing the {@link #id}.</p>
206 * <p>All user-developed visual widgets that are required to participate in automated lifecycle and size management should subclass Component (or
207 * {@link Ext.BoxComponent} if managed box model handling is required, ie height and width management).</p>
208 * <p>See the <a href="http://extjs.com/learn/Tutorial:Creating_new_UI_controls">Creating new UI controls</a> tutorial for details on how
209 * and to either extend or augment ExtJs base classes to create custom Components.</p>
210 * <p>Every component has a specific xtype, which is its Ext-specific type name, along with methods for checking the
211 * xtype like {@link #getXType} and {@link #isXType}. This is the list of all valid xtypes:</p>
214 ------------- ------------------
215 box {@link Ext.BoxComponent}
216 button {@link Ext.Button}
217 buttongroup {@link Ext.ButtonGroup}
218 colorpalette {@link Ext.ColorPalette}
219 component {@link Ext.Component}
220 container {@link Ext.Container}
221 cycle {@link Ext.CycleButton}
222 dataview {@link Ext.DataView}
223 datepicker {@link Ext.DatePicker}
224 editor {@link Ext.Editor}
225 editorgrid {@link Ext.grid.EditorGridPanel}
226 flash {@link Ext.FlashComponent}
227 grid {@link Ext.grid.GridPanel}
228 listview {@link Ext.ListView}
229 panel {@link Ext.Panel}
230 progress {@link Ext.ProgressBar}
231 propertygrid {@link Ext.grid.PropertyGrid}
232 slider {@link Ext.Slider}
233 spacer {@link Ext.Spacer}
234 splitbutton {@link Ext.SplitButton}
235 tabpanel {@link Ext.TabPanel}
236 treepanel {@link Ext.tree.TreePanel}
237 viewport {@link Ext.ViewPort}
238 window {@link Ext.Window}
241 ---------------------------------------
242 paging {@link Ext.PagingToolbar}
243 toolbar {@link Ext.Toolbar}
244 tbbutton {@link Ext.Toolbar.Button} (deprecated; use button)
245 tbfill {@link Ext.Toolbar.Fill}
246 tbitem {@link Ext.Toolbar.Item}
247 tbseparator {@link Ext.Toolbar.Separator}
248 tbspacer {@link Ext.Toolbar.Spacer}
249 tbsplit {@link Ext.Toolbar.SplitButton} (deprecated; use splitbutton)
250 tbtext {@link Ext.Toolbar.TextItem}
253 ---------------------------------------
254 menu {@link Ext.menu.Menu}
255 colormenu {@link Ext.menu.ColorMenu}
256 datemenu {@link Ext.menu.DateMenu}
257 menubaseitem {@link Ext.menu.BaseItem}
258 menucheckitem {@link Ext.menu.CheckItem}
259 menuitem {@link Ext.menu.Item}
260 menuseparator {@link Ext.menu.Separator}
261 menutextitem {@link Ext.menu.TextItem}
264 ---------------------------------------
265 form {@link Ext.form.FormPanel}
266 checkbox {@link Ext.form.Checkbox}
267 checkboxgroup {@link Ext.form.CheckboxGroup}
268 combo {@link Ext.form.ComboBox}
269 datefield {@link Ext.form.DateField}
270 displayfield {@link Ext.form.DisplayField}
271 field {@link Ext.form.Field}
272 fieldset {@link Ext.form.FieldSet}
273 hidden {@link Ext.form.Hidden}
274 htmleditor {@link Ext.form.HtmlEditor}
275 label {@link Ext.form.Label}
276 numberfield {@link Ext.form.NumberField}
277 radio {@link Ext.form.Radio}
278 radiogroup {@link Ext.form.RadioGroup}
279 textarea {@link Ext.form.TextArea}
280 textfield {@link Ext.form.TextField}
281 timefield {@link Ext.form.TimeField}
282 trigger {@link Ext.form.TriggerField}
285 ---------------------------------------
286 chart {@link Ext.chart.Chart}
287 barchart {@link Ext.chart.BarChart}
288 cartesianchart {@link Ext.chart.CartesianChart}
289 columnchart {@link Ext.chart.ColumnChart}
290 linechart {@link Ext.chart.LineChart}
291 piechart {@link Ext.chart.PieChart}
294 ---------------------------------------
295 arraystore {@link Ext.data.ArrayStore}
296 directstore {@link Ext.data.DirectStore}
297 groupingstore {@link Ext.data.GroupingStore}
298 jsonstore {@link Ext.data.JsonStore}
299 simplestore {@link Ext.data.SimpleStore} (deprecated; use arraystore)
300 store {@link Ext.data.Store}
301 xmlstore {@link Ext.data.XmlStore}
304 * @param {Ext.Element/String/Object} config The configuration options may be specified as either:
305 * <div class="mdetail-params"><ul>
306 * <li><b>an element</b> :
307 * <p class="sub-desc">it is set as the internal element and its id used as the component id</p></li>
308 * <li><b>a string</b> :
309 * <p class="sub-desc">it is assumed to be the id of an existing element and is used as the component id</p></li>
310 * <li><b>anything else</b> :
311 * <p class="sub-desc">it is assumed to be a standard config object and is applied to the component</p></li>
314 Ext.Component = function(config){
315 config = config || {};
316 if(config.initialConfig){
317 if(config.isAction){ // actions
318 this.baseAction = config;
320 config = config.initialConfig; // component cloning / action set up
321 }else if(config.tagName || config.dom || Ext.isString(config)){ // element object
322 config = {applyTo: config, id: config.id || config};
326 * This Component's initial configuration specification. Read-only.
328 * @property initialConfig
330 this.initialConfig = config;
332 Ext.apply(this, config);
336 * Fires when a component is added to an Ext.Container
337 * @param {Ext.Component} this
338 * @param {Ext.Container} ownerCt Container which holds the component
339 * @param {number} index Position at which the component was added
344 * Fires after the component is disabled.
345 * @param {Ext.Component} this
350 * Fires after the component is enabled.
351 * @param {Ext.Component} this
356 * Fires before the component is shown by calling the {@link #show} method.
357 * Return false from an event handler to stop the show.
358 * @param {Ext.Component} this
363 * Fires after the component is shown when calling the {@link #show} method.
364 * @param {Ext.Component} this
369 * Fires before the component is hidden by calling the {@link #hide} method.
370 * Return false from an event handler to stop the hide.
371 * @param {Ext.Component} this
376 * Fires after the component is hidden.
377 * Fires after the component is hidden when calling the {@link #hide} method.
378 * @param {Ext.Component} this
383 * Fires when a component is removed from an Ext.Container
384 * @param {Ext.Component} this
385 * @param {Ext.Container} ownerCt Container which holds the component
389 * @event beforerender
390 * Fires before the component is {@link #rendered}. Return false from an
391 * event handler to stop the {@link #render}.
392 * @param {Ext.Component} this
397 * Fires after the component markup is {@link #rendered}.
398 * @param {Ext.Component} this
403 * <p>Fires after the component rendering is finished.</p>
404 * <p>The afterrender event is fired after this Component has been {@link #rendered}, been postprocesed
405 * by any afterRender method defined for the Component, and, if {@link #stateful}, after state
406 * has been restored.</p>
407 * @param {Ext.Component} this
411 * @event beforedestroy
412 * Fires before the component is {@link #destroy}ed. Return false from an event handler to stop the {@link #destroy}.
413 * @param {Ext.Component} this
418 * Fires after the component is {@link #destroy}ed.
419 * @param {Ext.Component} this
423 * @event beforestaterestore
424 * Fires before the state of the component is restored. Return false from an event handler to stop the restore.
425 * @param {Ext.Component} this
426 * @param {Object} state The hash of state values returned from the StateProvider. If this
427 * event is not vetoed, then the state object is passed to <b><tt>applyState</tt></b>. By default,
428 * that simply copies property values into this Component. The method maybe overriden to
429 * provide custom state restoration.
431 'beforestaterestore',
433 * @event staterestore
434 * Fires after the state of the component is restored.
435 * @param {Ext.Component} this
436 * @param {Object} state The hash of state values returned from the StateProvider. This is passed
437 * to <b><tt>applyState</tt></b>. By default, that simply copies property values into this
438 * Component. The method maybe overriden to provide custom state restoration.
442 * @event beforestatesave
443 * Fires before the state of the component is saved to the configured state provider. Return false to stop the save.
444 * @param {Ext.Component} this
445 * @param {Object} state The hash of state values. This is determined by calling
446 * <b><tt>getState()</tt></b> on the Component. This method must be provided by the
447 * developer to return whetever representation of state is required, by default, Ext.Component
448 * has a null implementation.
453 * Fires after the state of the component is saved to the configured state provider.
454 * @param {Ext.Component} this
455 * @param {Object} state The hash of state values. This is determined by calling
456 * <b><tt>getState()</tt></b> on the Component. This method must be provided by the
457 * developer to return whetever representation of state is required, by default, Ext.Component
458 * has a null implementation.
463 Ext.ComponentMgr.register(this);
464 Ext.Component.superclass.constructor.call(this);
467 this.baseAction.addComponent(this);
470 this.initComponent();
473 if(Ext.isArray(this.plugins)){
474 for(var i = 0, len = this.plugins.length; i < len; i++){
475 this.plugins[i] = this.initPlugin(this.plugins[i]);
478 this.plugins = this.initPlugin(this.plugins);
482 if(this.stateful !== false){
487 this.applyToMarkup(this.applyTo);
489 }else if(this.renderTo){
490 this.render(this.renderTo);
491 delete this.renderTo;
496 Ext.Component.AUTO_ID = 1000;
498 Ext.extend(Ext.Component, Ext.util.Observable, {
499 // Configs below are used for all Components when rendered by FormLayout.
501 * @cfg {String} fieldLabel <p>The label text to display next to this Component (defaults to '').</p>
502 * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container which
503 * has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout manager (e.g.
504 * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>).</p><br>
505 * <p>Also see <tt>{@link #hideLabel}</tt> and
506 * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</p>
507 * Example use:<pre><code>
510 renderTo: Ext.getBody(),
519 * @cfg {String} labelStyle <p>A CSS style specification string to apply directly to this field's
520 * label. Defaults to the container's labelStyle value if set (e.g.,
521 * <tt>{@link Ext.layout.FormLayout#labelStyle}</tt> , or '').</p>
522 * <br><p><b>Note</b>: see the note for <code>{@link #clearCls}</code>.</p><br>
523 * <p>Also see <code>{@link #hideLabel}</code> and
524 * <code>{@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</code></p>
525 * Example use:<pre><code>
528 renderTo: Ext.getBody(),
532 labelStyle: 'font-weight:bold;'
538 * @cfg {String} labelSeparator <p>The separator to display after the text of each
539 * <tt>{@link #fieldLabel}</tt>. This property may be configured at various levels.
540 * The order of precedence is:
541 * <div class="mdetail-params"><ul>
542 * <li>field / component level</li>
543 * <li>container level</li>
544 * <li>{@link Ext.layout.FormLayout#labelSeparator layout level} (defaults to colon <tt>':'</tt>)</li>
546 * To display no separator for this field's label specify empty string ''.</p>
547 * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</tt>.</p><br>
548 * <p>Also see <tt>{@link #hideLabel}</tt> and
549 * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</p>
550 * Example use:<pre><code>
553 renderTo: Ext.getBody(),
555 labelSeparator: '~' // layout config has lowest priority (defaults to ':')
557 {@link Ext.layout.FormLayout#labelSeparator labelSeparator}: '>>', // config at container level
560 fieldLabel: 'Field 1',
561 labelSeparator: '...' // field/component level config supersedes others
564 fieldLabel: 'Field 2' // labelSeparator will be '='
570 * @cfg {Boolean} hideLabel <p><tt>true</tt> to completely hide the label element
571 * ({@link #fieldLabel label} and {@link #labelSeparator separator}). Defaults to <tt>false</tt>.
572 * By default, even if you do not specify a <tt>{@link #fieldLabel}</tt> the space will still be
573 * reserved so that the field will line up with other fields that do have labels.
574 * Setting this to <tt>true</tt> will cause the field to not reserve that space.</p>
575 * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</tt>.</p><br>
576 * Example use:<pre><code>
579 renderTo: Ext.getBody(),
588 * @cfg {String} clearCls <p>The CSS class used to to apply to the special clearing div rendered
589 * directly after each form field wrapper to provide field clearing (defaults to
590 * <tt>'x-form-clear-left'</tt>).</p>
591 * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container
592 * which has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout
593 * manager (e.g. {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) and either a
594 * <tt>{@link #fieldLabel}</tt> is specified or <tt>isFormField=true</tt> is specified.</p><br>
595 * <p>See {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl} also.</p>
598 * @cfg {String} itemCls
599 * <p><b>Note</b>: this config is only used when this Component is rendered by a Container which
600 * has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout manager (e.g.
601 * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>).</p><br>
602 * <p>An additional CSS class to apply to the div wrapping the form item
603 * element of this field. If supplied, <tt>itemCls</tt> at the <b>field</b> level will override
604 * the default <tt>itemCls</tt> supplied at the <b>container</b> level. The value specified for
605 * <tt>itemCls</tt> will be added to the default class (<tt>'x-form-item'</tt>).</p>
606 * <p>Since it is applied to the item wrapper (see
607 * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}), it allows
608 * you to write standard CSS rules that can apply to the field, the label (if specified), or
609 * any other element within the markup for the field.</p>
610 * <br><p><b>Note</b>: see the note for <tt>{@link #fieldLabel}</tt>.</p><br>
611 * Example use:<pre><code>
612 // Apply a style to the field's label:
614 .required .x-form-item-label {font-weight:bold;color:red;}
619 renderTo: Ext.getBody(),
623 itemCls: 'required' //this label will be styled
626 fieldLabel: 'Favorite Color'
634 * <p>The <b>unique</b> id of this component (defaults to an {@link #getId auto-assigned id}).
635 * You should assign an id if you need to be able to access the component later and you do
636 * not have an object reference available (e.g., using {@link Ext}.{@link Ext#getCmp getCmp}).</p>
637 * <p>Note that this id will also be used as the element id for the containing HTML element
638 * that is rendered to the page for this component. This allows you to write id-based CSS
639 * rules to style the specific instance of this component uniquely, and also to select
640 * sub-elements using this component's id as the parent.</p>
641 * <p><b>Note</b>: to avoid complications imposed by a unique <tt>id</tt> also see
642 * <code>{@link #itemId}</code> and <code>{@link #ref}</code>.</p>
643 * <p><b>Note</b>: to access the container of an item see <code>{@link #ownerCt}</code>.</p>
646 * @cfg {String} itemId
647 * <p>An <tt>itemId</tt> can be used as an alternative way to get a reference to a component
648 * when no object reference is available. Instead of using an <code>{@link #id}</code> with
649 * {@link Ext}.{@link Ext#getCmp getCmp}, use <code>itemId</code> with
650 * {@link Ext.Container}.{@link Ext.Container#getComponent getComponent} which will retrieve
651 * <code>itemId</code>'s or <tt>{@link #id}</tt>'s. Since <code>itemId</code>'s are an index to the
652 * container's internal MixedCollection, the <code>itemId</code> is scoped locally to the container --
653 * avoiding potential conflicts with {@link Ext.ComponentMgr} which requires a <b>unique</b>
654 * <code>{@link #id}</code>.</p>
656 var c = new Ext.Panel({ //
657 {@link Ext.BoxComponent#height height}: 300,
658 {@link #renderTo}: document.body,
659 {@link Ext.Container#layout layout}: 'auto',
660 {@link Ext.Container#items items}: [
663 {@link Ext.Panel#title title}: 'Panel 1',
664 {@link Ext.BoxComponent#height height}: 150
668 {@link Ext.Panel#title title}: 'Panel 2',
669 {@link Ext.BoxComponent#height height}: 150
673 p1 = c.{@link Ext.Container#getComponent getComponent}('p1'); // not the same as {@link Ext#getCmp Ext.getCmp()}
674 p2 = p1.{@link #ownerCt}.{@link Ext.Container#getComponent getComponent}('p2'); // reference via a sibling
676 * <p>Also see <tt>{@link #id}</tt> and <code>{@link #ref}</code>.</p>
677 * <p><b>Note</b>: to access the container of an item see <tt>{@link #ownerCt}</tt>.</p>
680 * @cfg {String} xtype
681 * The registered <tt>xtype</tt> to create. This config option is not used when passing
682 * a config object into a constructor. This config option is used only when
683 * lazy instantiation is being used, and a child item of a Container is being
684 * specified not as a fully instantiated Component, but as a <i>Component config
685 * object</i>. The <tt>xtype</tt> will be looked up at render time up to determine what
686 * type of child Component to create.<br><br>
687 * The predefined xtypes are listed {@link Ext.Component here}.
689 * If you subclass Components to create your own Components, you may register
690 * them using {@link Ext.ComponentMgr#registerType} in order to be able to
691 * take advantage of lazy instantiation and rendering.
694 * @cfg {String} ptype
695 * The registered <tt>ptype</tt> to create. This config option is not used when passing
696 * a config object into a constructor. This config option is used only when
697 * lazy instantiation is being used, and a Plugin is being
698 * specified not as a fully instantiated Component, but as a <i>Component config
699 * object</i>. The <tt>ptype</tt> will be looked up at render time up to determine what
700 * type of Plugin to create.<br><br>
701 * If you create your own Plugins, you may register them using
702 * {@link Ext.ComponentMgr#registerPlugin} in order to be able to
703 * take advantage of lazy instantiation and rendering.
707 * An optional extra CSS class that will be added to this component's Element (defaults to ''). This can be
708 * useful for adding customized styles to the component or any of its children using standard CSS rules.
711 * @cfg {String} overCls
712 * An optional extra CSS class that will be added to this component's Element when the mouse moves
713 * over the Element, and removed when the mouse moves out. (defaults to ''). This can be
714 * useful for adding customized 'active' or 'hover' styles to the component or any of its children using standard CSS rules.
717 * @cfg {String} style
718 * A custom style specification to be applied to this component's Element. Should be a valid argument to
719 * {@link Ext.Element#applyStyles}.
723 renderTo: Ext.getBody(),
724 width: 400, height: 300,
745 * @cfg {String} ctCls
746 * <p>An optional extra CSS class that will be added to this component's container. This can be useful for
747 * adding customized styles to the container or any of its children using standard CSS rules. See
748 * {@link Ext.layout.ContainerLayout}.{@link Ext.layout.ContainerLayout#extraCls extraCls} also.</p>
749 * <p><b>Note</b>: <tt>ctCls</tt> defaults to <tt>''</tt> except for the following class
750 * which assigns a value by default:
751 * <div class="mdetail-params"><ul>
752 * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-layout-ct'</tt></li>
754 * To configure the above Class with an extra CSS class append to the default. For example,
755 * for BoxLayout (Hbox and Vbox):<pre><code>
756 * ctCls: 'x-box-layout-ct custom-class'
761 * @cfg {Boolean} disabled
762 * Render this component disabled (default is false).
766 * @cfg {Boolean} hidden
767 * Render this component hidden (default is false). If <tt>true</tt>, the
768 * {@link #hide} method will be called internally.
772 * @cfg {Object/Array} plugins
773 * An object or array of objects that will provide custom functionality for this component. The only
774 * requirement for a valid plugin is that it contain an init method that accepts a reference of type Ext.Component.
775 * When a component is created, if any plugins are available, the component will call the init method on each
776 * plugin, passing a reference to itself. Each plugin can then call methods or respond to events on the
777 * component as needed to provide its functionality.
780 * @cfg {Mixed} applyTo
781 * <p>Specify the id of the element, a DOM element or an existing Element corresponding to a DIV
782 * that is already present in the document that specifies some structural markup for this
783 * component.</p><div><ul>
784 * <li><b>Description</b> : <ul>
785 * <div class="sub-desc">When <tt>applyTo</tt> is used, constituent parts of the component can also be specified
786 * by id or CSS class name within the main element, and the component being created may attempt
787 * to create its subcomponents from that markup if applicable.</div>
789 * <li><b>Notes</b> : <ul>
790 * <div class="sub-desc">When using this config, a call to render() is not required.</div>
791 * <div class="sub-desc">If applyTo is specified, any value passed for {@link #renderTo} will be ignored and the target
792 * element's parent node will automatically be used as the component's container.</div>
797 * @cfg {Mixed} renderTo
798 * <p>Specify the id of the element, a DOM element or an existing Element that this component
799 * will be rendered into.</p><div><ul>
800 * <li><b>Notes</b> : <ul>
801 * <div class="sub-desc">Do <u>not</u> use this option if the Component is to be a child item of
802 * a {@link Ext.Container Container}. It is the responsibility of the
803 * {@link Ext.Container Container}'s {@link Ext.Container#layout layout manager}
804 * to render and manage its child items.</div>
805 * <div class="sub-desc">When using this config, a call to render() is not required.</div>
808 * <p>See <tt>{@link #render}</tt> also.</p>
811 * @cfg {Boolean} stateful
812 * <p>A flag which causes the Component to attempt to restore the state of
813 * internal properties from a saved state on startup. The component must have
814 * either a <code>{@link #stateId}</code> or <code>{@link #id}</code> assigned
815 * for state to be managed. Auto-generated ids are not guaranteed to be stable
816 * across page loads and cannot be relied upon to save and restore the same
817 * state for a component.<p>
818 * <p>For state saving to work, the state manager's provider must have been
819 * set to an implementation of {@link Ext.state.Provider} which overrides the
820 * {@link Ext.state.Provider#set set} and {@link Ext.state.Provider#get get}
821 * methods to save and recall name/value pairs. A built-in implementation,
822 * {@link Ext.state.CookieProvider} is available.</p>
823 * <p>To set the state provider for the current page:</p>
825 Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
826 expires: new Date(new Date().getTime()+(1000*60*60*24*7)), //7 days from now
829 * <p>A stateful Component attempts to save state when one of the events
830 * listed in the <code>{@link #stateEvents}</code> configuration fires.</p>
831 * <p>To save state, a stateful Component first serializes its state by
832 * calling <b><code>getState</code></b>. By default, this function does
833 * nothing. The developer must provide an implementation which returns an
834 * object hash which represents the Component's restorable state.</p>
835 * <p>The value yielded by getState is passed to {@link Ext.state.Manager#set}
836 * which uses the configured {@link Ext.state.Provider} to save the object
837 * keyed by the Component's <code>{@link stateId}</code>, or, if that is not
838 * specified, its <code>{@link #id}</code>.</p>
839 * <p>During construction, a stateful Component attempts to <i>restore</i>
840 * its state by calling {@link Ext.state.Manager#get} passing the
841 * <code>{@link #stateId}</code>, or, if that is not specified, the
842 * <code>{@link #id}</code>.</p>
843 * <p>The resulting object is passed to <b><code>applyState</code></b>.
844 * The default implementation of <code>applyState</code> simply copies
845 * properties into the object, but a developer may override this to support
846 * more behaviour.</p>
847 * <p>You can perform extra processing on state save and restore by attaching
848 * handlers to the {@link #beforestaterestore}, {@link #staterestore},
849 * {@link #beforestatesave} and {@link #statesave} events.</p>
852 * @cfg {String} stateId
853 * The unique id for this component to use for state management purposes
854 * (defaults to the component id if one was set, otherwise null if the
855 * component is using a generated id).
856 * <p>See <code>{@link #stateful}</code> for an explanation of saving and
857 * restoring Component state.</p>
860 * @cfg {Array} stateEvents
861 * <p>An array of events that, when fired, should trigger this component to
862 * save its state (defaults to none). <code>stateEvents</code> may be any type
863 * of event supported by this component, including browser or custom events
864 * (e.g., <tt>['click', 'customerchange']</tt>).</p>
865 * <p>See <code>{@link #stateful}</code> for an explanation of saving and
866 * restoring Component state.</p>
869 * @cfg {Mixed} autoEl
870 * <p>A tag name or {@link Ext.DomHelper DomHelper} spec used to create the {@link #getEl Element} which will
871 * encapsulate this Component.</p>
872 * <p>You do not normally need to specify this. For the base classes {@link Ext.Component}, {@link Ext.BoxComponent},
873 * and {@link Ext.Container}, this defaults to <b><tt>'div'</tt></b>. The more complex Ext classes use a more complex
874 * DOM structure created by their own onRender methods.</p>
875 * <p>This is intended to allow the developer to create application-specific utility Components encapsulated by
876 * different DOM elements. Example usage:</p><pre><code>
881 src: 'http://www.example.com/example.jpg'
887 html: 'autoEl is cool!'
892 cls: 'ux-unordered-list',
896 html: 'First list item'
904 * @cfg {String} disabledClass
905 * CSS class added to the component when it is disabled (defaults to 'x-item-disabled').
907 disabledClass : 'x-item-disabled',
909 * @cfg {Boolean} allowDomMove
910 * Whether the component can move the Dom node when rendering (defaults to true).
914 * @cfg {Boolean} autoShow
915 * True if the component should check for hidden classes (e.g. 'x-hidden' or 'x-hide-display') and remove
916 * them on render (defaults to false).
920 * @cfg {String} hideMode
921 * <p>How this component should be hidden. Supported values are <tt>'visibility'</tt>
922 * (css visibility), <tt>'offsets'</tt> (negative offset position) and <tt>'display'</tt>
924 * <br><p><b>Note</b>: the default of <tt>'display'</tt> is generally preferred
925 * since items are automatically laid out when they are first shown (no sizing
926 * is done while hidden).</p>
928 hideMode : 'display',
930 * @cfg {Boolean} hideParent
931 * True to hide and show the component's container when hide/show is called on the component, false to hide
932 * and show the component itself (defaults to false). For example, this can be used as a shortcut for a hide
933 * button on a window by setting hide:true on the button when adding it to its parent container.
937 * <p>The {@link Ext.Element} which encapsulates this Component. Read-only.</p>
938 * <p>This will <i>usually</i> be a <DIV> element created by the class's onRender method, but
939 * that may be overridden using the <code>{@link #autoEl}</code> config.</p>
940 * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br>
941 * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners
942 * for this Component's own Observable events), see the {@link Ext.util.Observable#listeners listeners}
943 * config for a suggestion, or use a render listener directly:</p><pre><code>
945 title: 'The Clickable Panel',
947 render: function(p) {
948 // Append the Panel to the click handler's argument list.
949 p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));
951 single: true // Remove the listener after first invocation
955 * <p>See also <tt>{@link #getEl getEl}</p>
960 * This Component's owner {@link Ext.Container Container} (defaults to undefined, and is set automatically when
961 * this Component is added to a Container). Read-only.
962 * <p><b>Note</b>: to access items within the Container see <tt>{@link #itemId}</tt>.</p>
963 * @type Ext.Container
967 * True if this component is hidden. Read-only.
972 * True if this component is disabled. Read-only.
977 * True if this component has been rendered. Read-only.
984 * @cfg {String} contentEl
985 * <p>Optional. Specify an existing HTML element, or the <code>id</code> of an existing HTML element to use as the content
986 * for this component.</p>
988 * <li><b>Description</b> :
989 * <div class="sub-desc">This config option is used to take an existing HTML element and place it in the layout element
990 * of a new component (it simply moves the specified DOM element <i>after the Component is rendered</i> to use as the content.</div></li>
992 * <div class="sub-desc">The specified HTML element is appended to the layout element of the component <i>after any configured
993 * {@link #html HTML} has been inserted</i>, and so the document will not contain this element at the time the {@link #render} event is fired.</div>
994 * <div class="sub-desc">The specified HTML element used will not participate in any <code><b>{@link Ext.Container#layout layout}</b></code>
995 * scheme that the Component may use. It is just HTML. Layouts operate on child <code><b>{@link Ext.Container#items items}</b></code>.</div>
996 * <div class="sub-desc">Add either the <code>x-hidden</code> or the <code>x-hide-display</code> CSS class to
997 * prevent a brief flicker of the content before it is rendered to the panel.</div></li>
1001 * @cfg {String/Object} html
1002 * An HTML fragment, or a {@link Ext.DomHelper DomHelper} specification to use as the layout element
1003 * content (defaults to ''). The HTML content is added after the component is rendered,
1004 * so the document will not contain this HTML at the time the {@link #render} event is fired.
1005 * This content is inserted into the body <i>before</i> any configured {@link #contentEl} is appended.
1010 * An <bold>{@link Ext.Template}</bold>, <bold>{@link Ext.XTemplate}</bold>
1011 * or an array of strings to form an Ext.XTemplate.
1012 * Used in conjunction with the <code>{@link #data}</code> and
1013 * <code>{@link #tplWriteMode}</code> configurations.
1017 * @cfg {String} tplWriteMode The Ext.(X)Template method to use when
1018 * updating the content area of the Component. Defaults to <tt>'overwrite'</tt>
1019 * (see <code>{@link Ext.XTemplate#overwrite}</code>).
1021 tplWriteMode : 'overwrite',
1025 * The initial set of data to apply to the <code>{@link #tpl}</code> to
1026 * update the content area of the Component.
1031 ctype : 'Ext.Component',
1037 getActionEl : function(){
1038 return this[this.actionMode];
1041 initPlugin : function(p){
1042 if(p.ptype && !Ext.isFunction(p.init)){
1043 p = Ext.ComponentMgr.createPlugin(p);
1044 }else if(Ext.isString(p)){
1045 p = Ext.ComponentMgr.createPlugin({
1054 * Function to be implemented by Component subclasses to be part of standard component initialization flow (it is empty by default).
1056 // Traditional constructor:
1057 Ext.Foo = function(config){
1058 // call superclass constructor:
1059 Ext.Foo.superclass.constructor.call(this, config);
1065 Ext.extend(Ext.Foo, Ext.Bar, {
1069 // initComponent replaces the constructor:
1070 Ext.Foo = Ext.extend(Ext.Bar, {
1071 initComponent : function(){
1072 // call superclass initComponent
1073 Ext.Container.superclass.initComponent.call(this);
1082 initComponent : Ext.emptyFn,
1085 * <p>Render this Component into the passed HTML element.</p>
1086 * <p><b>If you are using a {@link Ext.Container Container} object to house this Component, then
1087 * do not use the render method.</b></p>
1088 * <p>A Container's child Components are rendered by that Container's
1089 * {@link Ext.Container#layout layout} manager when the Container is first rendered.</p>
1090 * <p>Certain layout managers allow dynamic addition of child components. Those that do
1091 * include {@link Ext.layout.CardLayout}, {@link Ext.layout.AnchorLayout},
1092 * {@link Ext.layout.FormLayout}, {@link Ext.layout.TableLayout}.</p>
1093 * <p>If the Container is already rendered when a new child Component is added, you may need to call
1094 * the Container's {@link Ext.Container#doLayout doLayout} to refresh the view which causes any
1095 * unrendered child Components to be rendered. This is required so that you can add multiple
1096 * child components if needed while only refreshing the layout once.</p>
1097 * <p>When creating complex UIs, it is important to remember that sizing and positioning
1098 * of child items is the responsibility of the Container's {@link Ext.Container#layout layout} manager.
1099 * If you expect child items to be sized in response to user interactions, you must
1100 * configure the Container with a layout manager which creates and manages the type of layout you
1102 * <p><b>Omitting the Container's {@link Ext.Container#layout layout} config means that a basic
1103 * layout manager is used which does nothing but render child components sequentially into the
1104 * Container. No sizing or positioning will be performed in this situation.</b></p>
1105 * @param {Element/HTMLElement/String} container (optional) The element this Component should be
1106 * rendered into. If it is being created from existing markup, this should be omitted.
1107 * @param {String/Number} position (optional) The element ID or DOM node index within the container <b>before</b>
1108 * which this component will be inserted (defaults to appending to the end of the container)
1110 render : function(container, position){
1111 if(!this.rendered && this.fireEvent('beforerender', this) !== false){
1112 if(!container && this.el){
1113 this.el = Ext.get(this.el);
1114 container = this.el.dom.parentNode;
1115 this.allowDomMove = false;
1117 this.container = Ext.get(container);
1119 this.container.addClass(this.ctCls);
1121 this.rendered = true;
1122 if(position !== undefined){
1123 if(Ext.isNumber(position)){
1124 position = this.container.dom.childNodes[position];
1126 position = Ext.getDom(position);
1129 this.onRender(this.container, position || null);
1131 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
1134 this.el.addClass(this.cls);
1138 this.el.applyStyles(this.style);
1142 this.el.addClassOnOver(this.overCls);
1144 this.fireEvent('render', this);
1147 // Populate content of the component with html, contentEl or
1149 var contentTarget = this.getContentTarget();
1151 contentTarget.update(Ext.DomHelper.markup(this.html));
1154 if (this.contentEl){
1155 var ce = Ext.getDom(this.contentEl);
1156 Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
1157 contentTarget.appendChild(ce);
1160 if (!this.tpl.compile) {
1161 this.tpl = new Ext.XTemplate(this.tpl);
1164 this.tpl[this.tplWriteMode](contentTarget, this.data);
1168 this.afterRender(this.container);
1172 // call this so we don't fire initial hide events.
1176 // pass silent so the event doesn't fire the first time.
1180 if(this.stateful !== false){
1181 this.initStateEvents();
1183 this.fireEvent('afterrender', this);
1190 * Update the content area of a component.
1191 * @param {Mixed} htmlOrData
1192 * If this component has been configured with a template via the tpl config
1193 * then it will use this argument as data to populate the template.
1194 * If this component was not configured with a template, the components
1195 * content area will be updated via Ext.Element update
1196 * @param {Boolean} loadScripts
1197 * (optional) Only legitimate when using the html configuration. Defaults to false
1198 * @param {Function} callback
1199 * (optional) Only legitimate when using the html configuration. Callback to execute when scripts have finished loading
1201 update: function(htmlOrData, loadScripts, cb) {
1202 var contentTarget = this.getContentTarget();
1203 if (this.tpl && typeof htmlOrData !== "string") {
1204 this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
1206 var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
1207 contentTarget.update(html, loadScripts, cb);
1214 * Method to manage awareness of when components are added to their
1215 * respective Container, firing an added event.
1216 * References are established at add time rather than at render time.
1217 * @param {Ext.Container} container Container which holds the component
1218 * @param {number} pos Position at which the component was added
1220 onAdded : function(container, pos) {
1221 this.ownerCt = container;
1223 this.fireEvent('added', this, container, pos);
1228 * Method to manage awareness of when components are removed from their
1229 * respective Container, firing an removed event. References are properly
1230 * cleaned up after removing a component from its owning container.
1232 onRemoved : function() {
1234 this.fireEvent('removed', this, this.ownerCt);
1235 delete this.ownerCt;
1240 * Method to establish a reference to a component.
1242 initRef : function() {
1245 * <p>A path specification, relative to the Component's <code>{@link #ownerCt}</code>
1246 * specifying into which ancestor Container to place a named reference to this Component.</p>
1247 * <p>The ancestor axis can be traversed by using '/' characters in the path.
1248 * For example, to put a reference to a Toolbar Button into <i>the Panel which owns the Toolbar</i>:</p><pre><code>
1249 var myGrid = new Ext.grid.EditorGridPanel({
1250 title: 'My EditorGridPanel',
1252 colModel: myColModel,
1255 handler: saveChanges,
1257 ref: '../saveButton'
1260 afteredit: function() {
1261 // The button reference is in the GridPanel
1262 myGrid.saveButton.enable();
1267 * <p>In the code above, if the <code>ref</code> had been <code>'saveButton'</code>
1268 * the reference would have been placed into the Toolbar. Each '/' in the <code>ref</code>
1269 * moves up one level from the Component's <code>{@link #ownerCt}</code>.</p>
1270 * <p>Also see the <code>{@link #added}</code> and <code>{@link #removed}</code> events.</p>
1272 if(this.ref && !this.refOwner){
1273 var levels = this.ref.split('/'),
1274 last = levels.length,
1278 while(t && i < last){
1283 t[this.refName = levels[--i]] = this;
1285 * @type Ext.Container
1286 * @property refOwner
1287 * The ancestor Container into which the {@link #ref} reference was inserted if this Component
1288 * is a child of a Container, and has been configured with a <code>ref</code>.
1295 removeRef : function() {
1296 if (this.refOwner && this.refName) {
1297 delete this.refOwner[this.refName];
1298 delete this.refOwner;
1303 initState : function(){
1304 if(Ext.state.Manager){
1305 var id = this.getStateId();
1307 var state = Ext.state.Manager.get(id);
1309 if(this.fireEvent('beforestaterestore', this, state) !== false){
1310 this.applyState(Ext.apply({}, state));
1311 this.fireEvent('staterestore', this, state);
1319 getStateId : function(){
1320 return this.stateId || ((/^(ext-comp-|ext-gen)/).test(String(this.id)) ? null : this.id);
1324 initStateEvents : function(){
1325 if(this.stateEvents){
1326 for(var i = 0, e; e = this.stateEvents[i]; i++){
1327 this.on(e, this.saveState, this, {delay:100});
1333 applyState : function(state){
1335 Ext.apply(this, state);
1340 getState : function(){
1345 saveState : function(){
1346 if(Ext.state.Manager && this.stateful !== false){
1347 var id = this.getStateId();
1349 var state = this.getState();
1350 if(this.fireEvent('beforestatesave', this, state) !== false){
1351 Ext.state.Manager.set(id, state);
1352 this.fireEvent('statesave', this, state);
1359 * Apply this component to existing markup that is valid. With this function, no call to render() is required.
1360 * @param {String/HTMLElement} el
1362 applyToMarkup : function(el){
1363 this.allowDomMove = false;
1364 this.el = Ext.get(el);
1365 this.render(this.el.dom.parentNode);
1369 * Adds a CSS class to the component's underlying element.
1370 * @param {string} cls The CSS class name to add
1371 * @return {Ext.Component} this
1373 addClass : function(cls){
1375 this.el.addClass(cls);
1377 this.cls = this.cls ? this.cls + ' ' + cls : cls;
1383 * Removes a CSS class from the component's underlying element.
1384 * @param {string} cls The CSS class name to remove
1385 * @return {Ext.Component} this
1387 removeClass : function(cls){
1389 this.el.removeClass(cls);
1391 this.cls = this.cls.split(' ').remove(cls).join(' ');
1397 // default function is not really useful
1398 onRender : function(ct, position){
1399 if(!this.el && this.autoEl){
1400 if(Ext.isString(this.autoEl)){
1401 this.el = document.createElement(this.autoEl);
1403 var div = document.createElement('div');
1404 Ext.DomHelper.overwrite(div, this.autoEl);
1405 this.el = div.firstChild;
1408 this.el.id = this.getId();
1412 this.el = Ext.get(this.el);
1413 if(this.allowDomMove !== false){
1414 ct.dom.insertBefore(this.el.dom, position);
1416 Ext.removeNode(div);
1424 getAutoCreate : function(){
1425 var cfg = Ext.isObject(this.autoCreate) ?
1426 this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
1427 if(this.id && !cfg.id){
1434 afterRender : Ext.emptyFn,
1437 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
1438 * removing the component from its {@link Ext.Container} (if applicable) and unregistering it from
1439 * {@link Ext.ComponentMgr}. Destruction is generally handled automatically by the framework and this method
1440 * should usually not need to be called directly.
1443 destroy : function(){
1444 if(!this.isDestroyed){
1445 if(this.fireEvent('beforedestroy', this) !== false){
1446 this.destroying = true;
1447 this.beforeDestroy();
1448 if(this.ownerCt && this.ownerCt.remove){
1449 this.ownerCt.remove(this, false);
1453 if(this.actionMode == 'container' || this.removeMode == 'container'){
1454 this.container.remove();
1458 Ext.ComponentMgr.unregister(this);
1459 this.fireEvent('destroy', this);
1460 this.purgeListeners();
1461 this.destroying = false;
1462 this.isDestroyed = true;
1467 deleteMembers : function(){
1468 var args = arguments;
1469 for(var i = 0, len = args.length; i < len; ++i){
1470 delete this[args[i]];
1475 beforeDestroy : Ext.emptyFn,
1478 onDestroy : Ext.emptyFn,
1481 * <p>Returns the {@link Ext.Element} which encapsulates this Component.</p>
1482 * <p>This will <i>usually</i> be a <DIV> element created by the class's onRender method, but
1483 * that may be overridden using the {@link #autoEl} config.</p>
1484 * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br>
1485 * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners
1486 * for this Component's own Observable events), see the {@link #listeners} config for a suggestion,
1487 * or use a render listener directly:</p><pre><code>
1489 title: 'The Clickable Panel',
1491 render: function(p) {
1492 // Append the Panel to the click handler's argument list.
1493 p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));
1495 single: true // Remove the listener after first invocation
1499 * @return {Ext.Element} The Element which encapsulates this Component.
1506 getContentTarget : function(){
1511 * Returns the <code>id</code> of this component or automatically generates and
1512 * returns an <code>id</code> if an <code>id</code> is not defined yet:<pre><code>
1513 * 'ext-comp-' + (++Ext.Component.AUTO_ID)
1515 * @return {String} id
1518 return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
1522 * Returns the <code>{@link #itemId}</code> of this component. If an
1523 * <code>{@link #itemId}</code> was not assigned through configuration the
1524 * <code>id</code> is returned using <code>{@link #getId}</code>.
1527 getItemId : function(){
1528 return this.itemId || this.getId();
1532 * Try to focus this component.
1533 * @param {Boolean} selectText (optional) If applicable, true to also select the text in this component
1534 * @param {Boolean/Number} delay (optional) Delay the focus this number of milliseconds (true for 10 milliseconds)
1535 * @return {Ext.Component} this
1537 focus : function(selectText, delay){
1539 this.focus.defer(Ext.isNumber(delay) ? delay : 10, this, [selectText, false]);
1544 if(selectText === true){
1545 this.el.dom.select();
1560 * Disable this component and fire the 'disable' event.
1561 * @return {Ext.Component} this
1563 disable : function(/* private */ silent){
1567 this.disabled = true;
1568 if(silent !== true){
1569 this.fireEvent('disable', this);
1575 onDisable : function(){
1576 this.getActionEl().addClass(this.disabledClass);
1577 this.el.dom.disabled = true;
1581 * Enable this component and fire the 'enable' event.
1582 * @return {Ext.Component} this
1584 enable : function(){
1588 this.disabled = false;
1589 this.fireEvent('enable', this);
1594 onEnable : function(){
1595 this.getActionEl().removeClass(this.disabledClass);
1596 this.el.dom.disabled = false;
1600 * Convenience function for setting disabled/enabled by boolean.
1601 * @param {Boolean} disabled
1602 * @return {Ext.Component} this
1604 setDisabled : function(disabled){
1605 return this[disabled ? 'disable' : 'enable']();
1609 * Show this component. Listen to the '{@link #beforeshow}' event and return
1610 * <tt>false</tt> to cancel showing the component. Fires the '{@link #show}'
1611 * event after showing the component.
1612 * @return {Ext.Component} this
1615 if(this.fireEvent('beforeshow', this) !== false){
1616 this.hidden = false;
1617 if(this.autoRender){
1618 this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
1623 this.fireEvent('show', this);
1629 onShow : function(){
1630 this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);
1634 * Hide this component. Listen to the '{@link #beforehide}' event and return
1635 * <tt>false</tt> to cancel hiding the component. Fires the '{@link #hide}'
1636 * event after hiding the component. Note this method is called internally if
1637 * the component is configured to be <code>{@link #hidden}</code>.
1638 * @return {Ext.Component} this
1641 if(this.fireEvent('beforehide', this) !== false){
1643 this.fireEvent('hide', this);
1657 onHide : function(){
1658 this.getVisibilityEl().addClass('x-hide-' + this.hideMode);
1662 getVisibilityEl : function(){
1663 return this.hideParent ? this.container : this.getActionEl();
1667 * Convenience function to hide or show this component by boolean.
1668 * @param {Boolean} visible True to show, false to hide
1669 * @return {Ext.Component} this
1671 setVisible : function(visible){
1672 return this[visible ? 'show' : 'hide']();
1676 * Returns true if this component is visible.
1677 * @return {Boolean} True if this component is visible, false otherwise.
1679 isVisible : function(){
1680 return this.rendered && this.getVisibilityEl().isVisible();
1684 * Clone the current component using the original config values passed into this instance by default.
1685 * @param {Object} overrides A new config containing any properties to override in the cloned version.
1686 * An id property can be passed on this object, otherwise one will be generated to avoid duplicates.
1687 * @return {Ext.Component} clone The cloned copy of this component
1689 cloneConfig : function(overrides){
1690 overrides = overrides || {};
1691 var id = overrides.id || Ext.id();
1692 var cfg = Ext.applyIf(overrides, this.initialConfig);
1693 cfg.id = id; // prevent dup id
1694 return new this.constructor(cfg);
1698 * Gets the xtype for this component as registered with {@link Ext.ComponentMgr}. For a list of all
1699 * available xtypes, see the {@link Ext.Component} header. Example usage:
1701 var t = new Ext.form.TextField();
1702 alert(t.getXType()); // alerts 'textfield'
1704 * @return {String} The xtype
1706 getXType : function(){
1707 return this.constructor.xtype;
1711 * <p>Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended
1712 * from the xtype (default) or whether it is directly of the xtype specified (shallow = true).</p>
1713 * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1714 * to participate in determination of inherited xtypes.</b></p>
1715 * <p>For a list of all available xtypes, see the {@link Ext.Component} header.</p>
1716 * <p>Example usage:</p>
1718 var t = new Ext.form.TextField();
1719 var isText = t.isXType('textfield'); // true
1720 var isBoxSubclass = t.isXType('box'); // true, descended from BoxComponent
1721 var isBoxInstance = t.isXType('box', true); // false, not a direct BoxComponent instance
1723 * @param {String} xtype The xtype to check for this Component
1724 * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
1725 * the default), or true to check whether this Component is directly of the specified xtype.
1726 * @return {Boolean} True if this component descends from the specified xtype, false otherwise.
1728 isXType : function(xtype, shallow){
1729 //assume a string by default
1730 if (Ext.isFunction(xtype)){
1731 xtype = xtype.xtype; //handle being passed the class, e.g. Ext.Component
1732 }else if (Ext.isObject(xtype)){
1733 xtype = xtype.constructor.xtype; //handle being passed an instance
1736 return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
1740 * <p>Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all
1741 * available xtypes, see the {@link Ext.Component} header.</p>
1742 * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1743 * to participate in determination of inherited xtypes.</b></p>
1744 * <p>Example usage:</p>
1746 var t = new Ext.form.TextField();
1747 alert(t.getXTypes()); // alerts 'component/box/field/textfield'
1749 * @return {String} The xtype hierarchy string
1751 getXTypes : function(){
1752 var tc = this.constructor;
1754 var c = [], sc = this;
1755 while(sc && sc.constructor.xtype){
1756 c.unshift(sc.constructor.xtype);
1757 sc = sc.constructor.superclass;
1760 tc.xtypes = c.join('/');
1766 * Find a container above this component at any level by a custom function. If the passed function returns
1767 * true, the container will be returned.
1768 * @param {Function} fn The custom function to call with the arguments (container, this component).
1769 * @return {Ext.Container} The first Container for which the custom function returns true
1771 findParentBy : function(fn) {
1772 for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
1777 * Find a container above this component at any level by xtype or class
1778 * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
1779 * @return {Ext.Container} The first Container which matches the given xtype or class
1781 findParentByType : function(xtype) {
1782 return Ext.isFunction(xtype) ?
1783 this.findParentBy(function(p){
1784 return p.constructor === xtype;
1786 this.findParentBy(function(p){
1787 return p.constructor.xtype === xtype;
1792 getPositionEl : function(){
1793 return this.positionEl || this.el;
1797 purgeListeners : function(){
1798 Ext.Component.superclass.purgeListeners.call(this);
1800 this.on('beforedestroy', this.clearMons, this, {single: true});
1805 clearMons : function(){
1806 Ext.each(this.mons, function(m){
1807 m.item.un(m.ename, m.fn, m.scope);
1813 createMons: function(){
1816 this.on('beforedestroy', this.clearMons, this, {single: true});
1821 * <p>Adds listeners to any Observable object (or Elements) which are automatically removed when this Component
1822 * is destroyed. Usage:</p><code><pre>
1823 myGridPanel.mon(myGridPanel.getSelectionModel(), 'selectionchange', handleSelectionChange, null, {buffer: 50});
1825 * <p>or:</p><code><pre>
1826 myGridPanel.mon(myGridPanel.getSelectionModel(), {
1827 selectionchange: handleSelectionChange,
1831 * @param {Observable|Element} item The item to which to add a listener/listeners.
1832 * @param {Object|String} ename The event name, or an object containing event name properties.
1833 * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this
1834 * is the handler function.
1835 * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this
1836 * is the scope (<code>this</code> reference) in which the handler function is executed.
1837 * @param {Object} opt Optional. If the <code>ename</code> parameter was an event name, this
1838 * is the {@link Ext.util.Observable#addListener addListener} options.
1840 mon : function(item, ename, fn, scope, opt){
1842 if(Ext.isObject(ename)){
1843 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
1850 if(Ext.isFunction(o[e])){
1853 item: item, ename: e, fn: o[e], scope: o.scope
1855 item.on(e, o[e], o.scope, o);
1857 // individual options
1859 item: item, ename: e, fn: o[e], scope: o.scope
1868 item: item, ename: ename, fn: fn, scope: scope
1870 item.on(ename, fn, scope, opt);
1874 * Removes listeners that were added by the {@link #mon} method.
1875 * @param {Observable|Element} item The item from which to remove a listener/listeners.
1876 * @param {Object|String} ename The event name, or an object containing event name properties.
1877 * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this
1878 * is the handler function.
1879 * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this
1880 * is the scope (<code>this</code> reference) in which the handler function is executed.
1882 mun : function(item, ename, fn, scope){
1885 for(var i = 0, len = this.mons.length; i < len; ++i){
1887 if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){
1888 this.mons.splice(i, 1);
1889 item.un(ename, fn, scope);
1898 * Returns the next component in the owning container
1899 * @return Ext.Component
1901 nextSibling : function(){
1903 var index = this.ownerCt.items.indexOf(this);
1904 if(index != -1 && index+1 < this.ownerCt.items.getCount()){
1905 return this.ownerCt.items.itemAt(index+1);
1912 * Returns the previous component in the owning container
1913 * @return Ext.Component
1915 previousSibling : function(){
1917 var index = this.ownerCt.items.indexOf(this);
1919 return this.ownerCt.items.itemAt(index-1);
1926 * Provides the link for Observable's fireEvent method to bubble up the ownership hierarchy.
1927 * @return {Ext.Container} the Container which owns this Component.
1929 getBubbleTarget : function(){
1930 return this.ownerCt;
1934 Ext.reg('component', Ext.Component);/**
\r
1935 * @class Ext.Action
\r
1936 * <p>An Action is a piece of reusable functionality that can be abstracted out of any particular component so that it
\r
1937 * can be usefully shared among multiple components. Actions let you share handlers, configuration options and UI
\r
1938 * updates across any components that support the Action interface (primarily {@link Ext.Toolbar}, {@link Ext.Button}
\r
1939 * and {@link Ext.menu.Menu} components).</p>
\r
1940 * <p>Aside from supporting the config object interface, any component that needs to use Actions must also support
\r
1941 * the following method list, as these will be called as needed by the Action class: setText(string), setIconCls(string),
\r
1942 * setDisabled(boolean), setVisible(boolean) and setHandler(function).</p>
\r
1943 * Example usage:<br>
\r
1945 // Define the shared action. Each component below will have the same
\r
1946 // display text and icon, and will display the same message on click.
\r
1947 var action = new Ext.Action({
\r
1948 {@link #text}: 'Do something',
\r
1949 {@link #handler}: function(){
\r
1950 Ext.Msg.alert('Click', 'You did something.');
\r
1952 {@link #iconCls}: 'do-something',
\r
1953 {@link #itemId}: 'myAction'
\r
1956 var panel = new Ext.Panel({
\r
1961 // Add the action directly to a toolbar as a menu button
\r
1964 text: 'Action Menu',
\r
1965 // Add the action to a menu as a text item
\r
1970 // Add the action to the panel body as a standard button
\r
1971 new Ext.Button(action)
\r
1973 renderTo: Ext.getBody()
\r
1976 // Change the text for all components using the action
\r
1977 action.setText('Something else');
\r
1979 // Reference an action through a container using the itemId
\r
1980 var btn = panel.getComponent('myAction');
\r
1981 var aRef = btn.baseAction;
\r
1982 aRef.setText('New text');
\r
1985 * @param {Object} config The configuration options
\r
1987 Ext.Action = Ext.extend(Object, {
\r
1989 * @cfg {String} text The text to set for all components using this action (defaults to '').
\r
1992 * @cfg {String} iconCls
\r
1993 * The CSS class selector that specifies a background image to be used as the header icon for
\r
1994 * all components using this action (defaults to '').
\r
1995 * <p>An example of specifying a custom icon class would be something like:
\r
1997 // specify the property in the config for the class:
\r
1999 iconCls: 'do-something'
\r
2001 // css class that specifies background image to be used as the icon image:
\r
2002 .do-something { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
\r
2006 * @cfg {Boolean} disabled True to disable all components using this action, false to enable them (defaults to false).
\r
2009 * @cfg {Boolean} hidden True to hide all components using this action, false to show them (defaults to false).
\r
2012 * @cfg {Function} handler The function that will be invoked by each component tied to this action
\r
2013 * when the component's primary event is triggered (defaults to undefined).
\r
2016 * @cfg {String} itemId
\r
2017 * See {@link Ext.Component}.{@link Ext.Component#itemId itemId}.
\r
2020 * @cfg {Object} scope The scope (<tt><b>this</b></tt> reference) in which the
\r
2021 * <code>{@link #handler}</code> is executed. Defaults to this Button.
\r
2024 constructor : function(config){
\r
2025 this.initialConfig = config;
\r
2026 this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
\r
2034 * Sets the text to be displayed by all components using this action.
\r
2035 * @param {String} text The text to display
\r
2037 setText : function(text){
\r
2038 this.initialConfig.text = text;
\r
2039 this.callEach('setText', [text]);
\r
2043 * Gets the text currently displayed by all components using this action.
\r
2045 getText : function(){
\r
2046 return this.initialConfig.text;
\r
2050 * Sets the icon CSS class for all components using this action. The class should supply
\r
2051 * a background image that will be used as the icon image.
\r
2052 * @param {String} cls The CSS class supplying the icon image
\r
2054 setIconClass : function(cls){
\r
2055 this.initialConfig.iconCls = cls;
\r
2056 this.callEach('setIconClass', [cls]);
\r
2060 * Gets the icon CSS class currently used by all components using this action.
\r
2062 getIconClass : function(){
\r
2063 return this.initialConfig.iconCls;
\r
2067 * Sets the disabled state of all components using this action. Shortcut method
\r
2068 * for {@link #enable} and {@link #disable}.
\r
2069 * @param {Boolean} disabled True to disable the component, false to enable it
\r
2071 setDisabled : function(v){
\r
2072 this.initialConfig.disabled = v;
\r
2073 this.callEach('setDisabled', [v]);
\r
2077 * Enables all components using this action.
\r
2079 enable : function(){
\r
2080 this.setDisabled(false);
\r
2084 * Disables all components using this action.
\r
2086 disable : function(){
\r
2087 this.setDisabled(true);
\r
2091 * Returns true if the components using this action are currently disabled, else returns false.
\r
2093 isDisabled : function(){
\r
2094 return this.initialConfig.disabled;
\r
2098 * Sets the hidden state of all components using this action. Shortcut method
\r
2099 * for <code>{@link #hide}</code> and <code>{@link #show}</code>.
\r
2100 * @param {Boolean} hidden True to hide the component, false to show it
\r
2102 setHidden : function(v){
\r
2103 this.initialConfig.hidden = v;
\r
2104 this.callEach('setVisible', [!v]);
\r
2108 * Shows all components using this action.
\r
2110 show : function(){
\r
2111 this.setHidden(false);
\r
2115 * Hides all components using this action.
\r
2117 hide : function(){
\r
2118 this.setHidden(true);
\r
2122 * Returns true if the components using this action are currently hidden, else returns false.
\r
2124 isHidden : function(){
\r
2125 return this.initialConfig.hidden;
\r
2129 * Sets the function that will be called by each Component using this action when its primary event is triggered.
\r
2130 * @param {Function} fn The function that will be invoked by the action's components. The function
\r
2131 * will be called with no arguments.
\r
2132 * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed. Defaults to the Component firing the event.
\r
2134 setHandler : function(fn, scope){
\r
2135 this.initialConfig.handler = fn;
\r
2136 this.initialConfig.scope = scope;
\r
2137 this.callEach('setHandler', [fn, scope]);
\r
2141 * Executes the specified function once for each Component currently tied to this action. The function passed
\r
2142 * in should accept a single argument that will be an object that supports the basic Action config/method interface.
\r
2143 * @param {Function} fn The function to execute for each component
\r
2144 * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed. Defaults to the Component.
\r
2146 each : function(fn, scope){
\r
2147 Ext.each(this.items, fn, scope);
\r
2151 callEach : function(fnName, args){
\r
2152 var cs = this.items;
\r
2153 for(var i = 0, len = cs.length; i < len; i++){
\r
2154 cs[i][fnName].apply(cs[i], args);
\r
2159 addComponent : function(comp){
\r
2160 this.items.push(comp);
\r
2161 comp.on('destroy', this.removeComponent, this);
\r
2165 removeComponent : function(comp){
\r
2166 this.items.remove(comp);
\r
2170 * Executes this action manually using the handler function specified in the original config object
\r
2171 * or the handler function set with <code>{@link #setHandler}</code>. Any arguments passed to this
\r
2172 * function will be passed on to the handler function.
\r
2173 * @param {Mixed} arg1 (optional) Variable number of arguments passed to the handler function
\r
2174 * @param {Mixed} arg2 (optional)
\r
2175 * @param {Mixed} etc... (optional)
\r
2177 execute : function(){
\r
2178 this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
\r
2183 * @extends Ext.Element
2184 * An extended {@link Ext.Element} object that supports a shadow and shim, constrain to viewport and
2185 * automatic maintaining of shadow/shim positions.
2186 * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true)
2187 * @cfg {String/Boolean} shadow True to automatically create an {@link Ext.Shadow}, or a string indicating the
2188 * shadow's display {@link Ext.Shadow#mode}. False to disable the shadow. (defaults to false)
2189 * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: 'div', cls: 'x-layer'}).
2190 * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true)
2191 * @cfg {String} cls CSS class to add to the element
2192 * @cfg {Number} zindex Starting z-index (defaults to 11000)
2193 * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 4)
2194 * @cfg {Boolean} useDisplay
2195 * Defaults to use css offsets to hide the Layer. Specify <tt>true</tt>
2196 * to use css style <tt>'display:none;'</tt> to hide the Layer.
2198 * @param {Object} config An object with config options.
2199 * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element. If the element is not found it creates it.
2202 Ext.Layer = function(config, existingEl){
2203 config = config || {};
2204 var dh = Ext.DomHelper;
2205 var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
2207 this.dom = Ext.getDom(existingEl);
2210 var o = config.dh || {tag: 'div', cls: 'x-layer'};
2211 this.dom = dh.append(pel, o);
2214 this.addClass(config.cls);
2216 this.constrain = config.constrain !== false;
2217 this.setVisibilityMode(Ext.Element.VISIBILITY);
2219 this.id = this.dom.id = config.id;
2221 this.id = Ext.id(this.dom);
2223 this.zindex = config.zindex || this.getZIndex();
2224 this.position('absolute', this.zindex);
2226 this.shadowOffset = config.shadowOffset || 4;
2227 this.shadow = new Ext.Shadow({
2228 offset : this.shadowOffset,
2229 mode : config.shadow
2232 this.shadowOffset = 0;
2234 this.useShim = config.shim !== false && Ext.useShims;
2235 this.useDisplay = config.useDisplay;
2239 var supr = Ext.Element.prototype;
2241 // shims are shared among layer to keep from having 100 iframes
2244 Ext.extend(Ext.Layer, Ext.Element, {
2246 getZIndex : function(){
2247 return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
2250 getShim : function(){
2257 var shim = shims.shift();
2259 shim = this.createShim();
2260 shim.enableDisplayMode('block');
2261 shim.dom.style.display = 'none';
2262 shim.dom.style.visibility = 'visible';
2264 var pn = this.dom.parentNode;
2265 if(shim.dom.parentNode != pn){
2266 pn.insertBefore(shim.dom, this.dom);
2268 shim.setStyle('z-index', this.getZIndex()-2);
2273 hideShim : function(){
2275 this.shim.setDisplayed(false);
2276 shims.push(this.shim);
2281 disableShadow : function(){
2283 this.shadowDisabled = true;
2285 this.lastShadowOffset = this.shadowOffset;
2286 this.shadowOffset = 0;
2290 enableShadow : function(show){
2292 this.shadowDisabled = false;
2293 this.shadowOffset = this.lastShadowOffset;
2294 delete this.lastShadowOffset;
2302 // this code can execute repeatedly in milliseconds (i.e. during a drag) so
2303 // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
2304 sync : function(doShow){
2305 var sw = this.shadow;
2306 if(!this.updating && this.isVisible() && (sw || this.useShim)){
2307 var sh = this.getShim();
2309 var w = this.getWidth(),
2310 h = this.getHeight();
2312 var l = this.getLeft(true),
2313 t = this.getTop(true);
2315 if(sw && !this.shadowDisabled){
2316 if(doShow && !sw.isVisible()){
2319 sw.realign(l, t, w, h);
2325 // fit the shim behind the shadow, so it is shimmed too
2326 var a = sw.adjusts, s = sh.dom.style;
2327 s.left = (Math.min(l, l+a.l))+'px';
2328 s.top = (Math.min(t, t+a.t))+'px';
2329 s.width = (w+a.w)+'px';
2330 s.height = (h+a.h)+'px';
2337 sh.setLeftTop(l, t);
2344 destroy : function(){
2349 this.removeAllListeners();
2350 Ext.removeNode(this.dom);
2354 remove : function(){
2359 beginUpdate : function(){
2360 this.updating = true;
2364 endUpdate : function(){
2365 this.updating = false;
2370 hideUnders : function(negOffset){
2378 constrainXY : function(){
2380 var vw = Ext.lib.Dom.getViewWidth(),
2381 vh = Ext.lib.Dom.getViewHeight();
2382 var s = Ext.getDoc().getScroll();
2384 var xy = this.getXY();
2385 var x = xy[0], y = xy[1];
2386 var so = this.shadowOffset;
2387 var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so;
2388 // only move it if it needs it
2390 // first validate right/bottom
2391 if((x + w) > vw+s.left){
2395 if((y + h) > vh+s.top){
2399 // then make sure top/left isn't negative
2410 var ay = this.avoidY;
2411 if(y <= ay && (y+h) >= ay){
2417 supr.setXY.call(this, xy);
2424 isVisible : function(){
2425 return this.visible;
2429 showAction : function(){
2430 this.visible = true; // track visibility to prevent getStyle calls
2431 if(this.useDisplay === true){
2432 this.setDisplayed('');
2433 }else if(this.lastXY){
2434 supr.setXY.call(this, this.lastXY);
2435 }else if(this.lastLT){
2436 supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
2441 hideAction : function(){
2442 this.visible = false;
2443 if(this.useDisplay === true){
2444 this.setDisplayed(false);
2446 this.setLeftTop(-10000,-10000);
2450 // overridden Element method
2451 setVisible : function(v, a, d, c, e){
2456 var cb = function(){
2461 }.createDelegate(this);
2462 supr.setVisible.call(this, true, true, d, cb, e);
2465 this.hideUnders(true);
2474 }.createDelegate(this);
2476 supr.setVisible.call(this, v, a, d, cb, e);
2486 storeXY : function(xy){
2491 storeLeftTop : function(left, top){
2493 this.lastLT = [left, top];
2497 beforeFx : function(){
2498 this.beforeAction();
2499 return Ext.Layer.superclass.beforeFx.apply(this, arguments);
2503 afterFx : function(){
2504 Ext.Layer.superclass.afterFx.apply(this, arguments);
2505 this.sync(this.isVisible());
2509 beforeAction : function(){
2510 if(!this.updating && this.shadow){
2515 // overridden Element method
2516 setLeft : function(left){
2517 this.storeLeftTop(left, this.getTop(true));
2518 supr.setLeft.apply(this, arguments);
2523 setTop : function(top){
2524 this.storeLeftTop(this.getLeft(true), top);
2525 supr.setTop.apply(this, arguments);
2530 setLeftTop : function(left, top){
2531 this.storeLeftTop(left, top);
2532 supr.setLeftTop.apply(this, arguments);
2537 setXY : function(xy, a, d, c, e){
2539 this.beforeAction();
2541 var cb = this.createCB(c);
2542 supr.setXY.call(this, xy, a, d, cb, e);
2550 createCB : function(c){
2561 // overridden Element method
2562 setX : function(x, a, d, c, e){
2563 this.setXY([x, this.getY()], a, d, c, e);
2567 // overridden Element method
2568 setY : function(y, a, d, c, e){
2569 this.setXY([this.getX(), y], a, d, c, e);
2573 // overridden Element method
2574 setSize : function(w, h, a, d, c, e){
2575 this.beforeAction();
2576 var cb = this.createCB(c);
2577 supr.setSize.call(this, w, h, a, d, cb, e);
2584 // overridden Element method
2585 setWidth : function(w, a, d, c, e){
2586 this.beforeAction();
2587 var cb = this.createCB(c);
2588 supr.setWidth.call(this, w, a, d, cb, e);
2595 // overridden Element method
2596 setHeight : function(h, a, d, c, e){
2597 this.beforeAction();
2598 var cb = this.createCB(c);
2599 supr.setHeight.call(this, h, a, d, cb, e);
2606 // overridden Element method
2607 setBounds : function(x, y, w, h, a, d, c, e){
2608 this.beforeAction();
2609 var cb = this.createCB(c);
2611 this.storeXY([x, y]);
2612 supr.setXY.call(this, [x, y]);
2613 supr.setSize.call(this, w, h, a, d, cb, e);
2616 supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
2622 * Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
2623 * incremented by two more than the value passed in so that it always shows above any shadow or shim (the shadow
2624 * element, if any, will be assigned z-index + 1, and the shim element, if any, will be assigned the unmodified z-index).
2625 * @param {Number} zindex The new z-index to set
2626 * @return {this} The Layer
2628 setZIndex : function(zindex){
2629 this.zindex = zindex;
2630 this.setStyle('z-index', zindex + 2);
2632 this.shadow.setZIndex(zindex + 1);
2635 this.shim.setStyle('z-index', zindex);
2643 * Simple class that can provide a shadow effect for any element. Note that the element MUST be absolutely positioned,
2644 * and the shadow does not provide any shimming. This should be used only in simple cases -- for more advanced
2645 * functionality that can also provide the same shadow effect, see the {@link Ext.Layer} class.
2647 * Create a new Shadow
2648 * @param {Object} config The config object
2650 Ext.Shadow = function(config){
2651 Ext.apply(this, config);
2652 if(typeof this.mode != "string"){
2653 this.mode = this.defaultMode;
2655 var o = this.offset, a = {h: 0};
2656 var rad = Math.floor(this.offset/2);
2657 switch(this.mode.toLowerCase()){ // all this hideous nonsense calculates the various offsets for shadows
2663 a.l -= this.offset + rad;
2664 a.t -= this.offset + rad;
2675 a.l -= (this.offset - rad);
2676 a.t -= this.offset + rad;
2678 a.w -= (this.offset - rad)*2;
2689 a.l -= (this.offset - rad);
2690 a.t -= (this.offset - rad);
2692 a.w -= (this.offset + rad + 1);
2693 a.h -= (this.offset + rad);
2702 Ext.Shadow.prototype = {
2704 * @cfg {String} mode
2705 * The shadow display mode. Supports the following options:<div class="mdetail-params"><ul>
2706 * <li><b><tt>sides</tt></b> : Shadow displays on both sides and bottom only</li>
2707 * <li><b><tt>frame</tt></b> : Shadow displays equally on all four sides</li>
2708 * <li><b><tt>drop</tt></b> : Traditional bottom-right drop shadow</li>
2712 * @cfg {String} offset
2713 * The number of pixels to offset the shadow from the element (defaults to <tt>4</tt>)
2718 defaultMode: "drop",
2721 * Displays the shadow under the target element
2722 * @param {Mixed} targetEl The id or element under which the shadow should display
2724 show : function(target){
2725 target = Ext.get(target);
2727 this.el = Ext.Shadow.Pool.pull();
2728 if(this.el.dom.nextSibling != target.dom){
2729 this.el.insertBefore(target);
2732 this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
2734 this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
2737 target.getLeft(true),
2738 target.getTop(true),
2742 this.el.dom.style.display = "block";
2746 * Returns true if the shadow is visible, else false
2748 isVisible : function(){
2749 return this.el ? true : false;
2753 * Direct alignment when values are already available. Show must be called at least once before
2754 * calling this method to ensure it is initialized.
2755 * @param {Number} left The target element left position
2756 * @param {Number} top The target element top position
2757 * @param {Number} width The target element width
2758 * @param {Number} height The target element height
2760 realign : function(l, t, w, h){
2764 var a = this.adjusts, d = this.el.dom, s = d.style;
2766 s.left = (l+a.l)+"px";
2767 s.top = (t+a.t)+"px";
2768 var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
2769 if(s.width != sws || s.height != shs){
2773 var cn = d.childNodes;
2774 var sww = Math.max(0, (sw-12))+"px";
2775 cn[0].childNodes[1].style.width = sww;
2776 cn[1].childNodes[1].style.width = sww;
2777 cn[2].childNodes[1].style.width = sww;
2778 cn[1].style.height = Math.max(0, (sh-12))+"px";
2788 this.el.dom.style.display = "none";
2789 Ext.Shadow.Pool.push(this.el);
2795 * Adjust the z-index of this shadow
2796 * @param {Number} zindex The new z-index
2798 setZIndex : function(z){
2801 this.el.setStyle("z-index", z);
2806 // Private utility class that manages the internal Shadow cache
2807 Ext.Shadow.Pool = function(){
2809 var markup = Ext.isIE ?
2810 '<div class="x-ie-shadow"></div>' :
2811 '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';
2816 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
2817 sh.autoBoxAdjust = false;
2822 push : function(sh){
2827 * @class Ext.BoxComponent
2828 * @extends Ext.Component
2829 * <p>Base class for any {@link Ext.Component Component} that is to be sized as a box, using width and height.</p>
2830 * <p>BoxComponent provides automatic box model adjustments for sizing and positioning and will work correctly
2831 * within the Component rendering model.</p>
2832 * <p>A BoxComponent may be created as a custom Component which encapsulates any HTML element, either a pre-existing
2833 * element, or one that is created to your specifications at render time. Usually, to participate in layouts,
2834 * a Component will need to be a <b>Box</b>Component in order to have its width and height managed.</p>
2835 * <p>To use a pre-existing element as a BoxComponent, configure it so that you preset the <b>el</b> property to the
2836 * element to reference:<pre><code>
2837 var pageHeader = new Ext.BoxComponent({
2840 * This may then be {@link Ext.Container#add added} to a {@link Ext.Container Container} as a child item.</p>
2841 * <p>To create a BoxComponent based around a HTML element to be created at render time, use the
2842 * {@link Ext.Component#autoEl autoEl} config option which takes the form of a
2843 * {@link Ext.DomHelper DomHelper} specification:<pre><code>
2844 var myImage = new Ext.BoxComponent({
2847 src: '/images/my-image.jpg'
2849 });</code></pre></p>
2851 * @param {Ext.Element/String/Object} config The configuration options.
2854 Ext.BoxComponent = Ext.extend(Ext.Component, {
2856 // Configs below are used for all Components when rendered by BoxLayout.
2858 * @cfg {Number} flex
2859 * <p><b>Note</b>: this config is only used when this Component is rendered
2860 * by a Container which has been configured to use a <b>{@link Ext.layout.BoxLayout BoxLayout}.</b>
2861 * Each child Component with a <code>flex</code> property will be flexed either vertically (by a VBoxLayout)
2862 * or horizontally (by an HBoxLayout) according to the item's <b>relative</b> <code>flex</code> value
2863 * compared to the sum of all Components with <code>flex</flex> value specified. Any child items that have
2864 * either a <code>flex = 0</code> or <code>flex = undefined</code> will not be 'flexed' (the initial size will not be changed).
2866 // Configs below are used for all Components when rendered by AnchorLayout.
2868 * @cfg {String} anchor <p><b>Note</b>: this config is only used when this Component is rendered
2869 * by a Container which has been configured to use an <b>{@link Ext.layout.AnchorLayout AnchorLayout} (or subclass thereof).</b>
2870 * based layout manager, for example:<div class="mdetail-params"><ul>
2871 * <li>{@link Ext.form.FormPanel}</li>
2872 * <li>specifying <code>layout: 'anchor' // or 'form', or 'absolute'</code></li>
2874 * <p>See {@link Ext.layout.AnchorLayout}.{@link Ext.layout.AnchorLayout#anchor anchor} also.</p>
2876 // tabTip config is used when a BoxComponent is a child of a TabPanel
2878 * @cfg {String} tabTip
2879 * <p><b>Note</b>: this config is only used when this BoxComponent is a child item of a TabPanel.</p>
2880 * A string to be used as innerHTML (html tags are accepted) to show in a tooltip when mousing over
2881 * the associated tab selector element. {@link Ext.QuickTips}.init()
2882 * must be called in order for the tips to render.
2884 // Configs below are used for all Components when rendered by BorderLayout.
2886 * @cfg {String} region <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2887 * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2888 * layout manager (e.g. specifying <tt>layout:'border'</tt>).</p><br>
2889 * <p>See {@link Ext.layout.BorderLayout} also.</p>
2891 // margins config is used when a BoxComponent is rendered by BorderLayout or BoxLayout.
2893 * @cfg {Object} margins <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2894 * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2895 * or one of the two <b>{@link Ext.layout.BoxLayout BoxLayout} subclasses.</b></p>
2896 * <p>An object containing margins to apply to this BoxComponent in the
2897 * format:</p><pre><code>
2900 right: (right margin),
2901 bottom: (bottom margin),
2904 * <p>May also be a string containing space-separated, numeric margin values. The order of the
2905 * sides associated with each value matches the way CSS processes margin values:</p>
2906 * <p><div class="mdetail-params"><ul>
2907 * <li>If there is only one value, it applies to all sides.</li>
2908 * <li>If there are two values, the top and bottom borders are set to the first value and the
2909 * right and left are set to the second.</li>
2910 * <li>If there are three values, the top is set to the first value, the left and right are set
2911 * to the second, and the bottom is set to the third.</li>
2912 * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
2914 * <p>Defaults to:</p><pre><code>
2915 * {top:0, right:0, bottom:0, left:0}
2920 * The local x (left) coordinate for this component if contained within a positioning container.
2924 * The local y (top) coordinate for this component if contained within a positioning container.
2927 * @cfg {Number} pageX
2928 * The page level x coordinate for this component if contained within a positioning container.
2931 * @cfg {Number} pageY
2932 * The page level y coordinate for this component if contained within a positioning container.
2935 * @cfg {Number} height
2936 * The height of this component in pixels (defaults to auto).
2937 * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
2940 * @cfg {Number} width
2941 * The width of this component in pixels (defaults to auto).
2942 * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
2945 * @cfg {Number} boxMinHeight
2946 * <p>The minimum value in pixels which this BoxComponent will set its height to.</p>
2947 * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2950 * @cfg {Number} boxMinWidth
2951 * <p>The minimum value in pixels which this BoxComponent will set its width to.</p>
2952 * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2955 * @cfg {Number} boxMaxHeight
2956 * <p>The maximum value in pixels which this BoxComponent will set its height to.</p>
2957 * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2960 * @cfg {Number} boxMaxWidth
2961 * <p>The maximum value in pixels which this BoxComponent will set its width to.</p>
2962 * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
2965 * @cfg {Boolean} autoHeight
2966 * <p>True to use height:'auto', false to use fixed height (or allow it to be managed by its parent
2967 * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
2968 * <p><b>Note</b>: Although many components inherit this config option, not all will
2969 * function as expected with a height of 'auto'. Setting autoHeight:true means that the
2970 * browser will manage height based on the element's contents, and that Ext will not manage it at all.</p>
2971 * <p>If the <i>browser</i> is managing the height, be aware that resizes performed by the browser in response
2972 * to changes within the structure of the Component cannot be detected. Therefore changes to the height might
2973 * result in elements needing to be synchronized with the new height. Example:</p><pre><code>
2974 var w = new Ext.Window({
2979 title: 'Collapse Me',
2984 beforecollapse: function() {
2987 beforeexpand: function() {
2990 collapse: function() {
2993 expand: function() {
3002 * @cfg {Boolean} autoWidth
3003 * <p>True to use width:'auto', false to use fixed width (or allow it to be managed by its parent
3004 * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
3005 * <p><b>Note</b>: Although many components inherit this config option, not all will
3006 * function as expected with a width of 'auto'. Setting autoWidth:true means that the
3007 * browser will manage width based on the element's contents, and that Ext will not manage it at all.</p>
3008 * <p>If the <i>browser</i> is managing the width, be aware that resizes performed by the browser in response
3009 * to changes within the structure of the Component cannot be detected. Therefore changes to the width might
3010 * result in elements needing to be synchronized with the new width. For example, where the target element is:</p><pre><code>
3011 <div id='grid-container' style='margin-left:25%;width:50%'></div>
3013 * A Panel rendered into that target element must listen for browser window resize in order to relay its
3014 * child items when the browser changes its width:<pre><code>
3015 var myPanel = new Ext.Panel({
3016 renderTo: 'grid-container',
3017 monitorResize: true, // relay on browser resize
3039 * @cfg {Boolean} autoScroll
3040 * <code>true</code> to use overflow:'auto' on the components layout element and show scroll bars automatically when
3041 * necessary, <code>false</code> to clip any overflowing content (defaults to <code>false</code>).
3044 /* // private internal config
3045 * {Boolean} deferHeight
3046 * True to defer height calculations to an external component, false to allow this component to set its own
3047 * height (defaults to false).
3051 initComponent : function(){
3052 Ext.BoxComponent.superclass.initComponent.call(this);
3056 * Fires after the component is resized.
3057 * @param {Ext.Component} this
3058 * @param {Number} adjWidth The box-adjusted width that was set
3059 * @param {Number} adjHeight The box-adjusted height that was set
3060 * @param {Number} rawWidth The width that was originally specified
3061 * @param {Number} rawHeight The height that was originally specified
3066 * Fires after the component is moved.
3067 * @param {Ext.Component} this
3068 * @param {Number} x The new x position
3069 * @param {Number} y The new y position
3075 // private, set in afterRender to signify that the component has been rendered
3077 // private, used to defer height settings to subclasses
3081 * Sets the width and height of this BoxComponent. This method fires the {@link #resize} event. This method can accept
3082 * either width and height as separate arguments, or you can pass a size object like <code>{width:10, height:20}</code>.
3083 * @param {Mixed} width The new width to set. This may be one of:<div class="mdetail-params"><ul>
3084 * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3085 * <li>A String used to set the CSS width style.</li>
3086 * <li>A size object in the format <code>{width: widthValue, height: heightValue}</code>.</li>
3087 * <li><code>undefined</code> to leave the width unchanged.</li>
3089 * @param {Mixed} height The new height to set (not required if a size object is passed as the first arg).
3090 * This may be one of:<div class="mdetail-params"><ul>
3091 * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3092 * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
3093 * <li><code>undefined</code> to leave the height unchanged.</li>
3095 * @return {Ext.BoxComponent} this
3097 setSize : function(w, h){
3099 // support for standard size objects
3100 if(typeof w == 'object'){
3101 h = w.height, w = w.width;
3103 if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
3104 w = this.boxMinWidth;
3106 if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) {
3107 h = this.boxMinHeight;
3109 if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) {
3110 w = this.boxMaxWidth;
3112 if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) {
3113 h = this.boxMaxHeight;
3117 this.width = w, this.height = h;
3121 // prevent recalcs when not needed
3122 if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
3125 this.lastSize = {width: w, height: h};
3126 var adj = this.adjustSize(w, h),
3130 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
3131 rz = this.getResizeEl();
3132 if(!this.deferHeight && aw !== undefined && ah !== undefined){
3134 }else if(!this.deferHeight && ah !== undefined){
3136 }else if(aw !== undefined){
3139 this.onResize(aw, ah, w, h);
3140 this.fireEvent('resize', this, aw, ah, w, h);
3146 * Sets the width of the component. This method fires the {@link #resize} event.
3147 * @param {Number} width The new width to setThis may be one of:<div class="mdetail-params"><ul>
3148 * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3149 * <li>A String used to set the CSS width style.</li>
3151 * @return {Ext.BoxComponent} this
3153 setWidth : function(width){
3154 return this.setSize(width);
3158 * Sets the height of the component. This method fires the {@link #resize} event.
3159 * @param {Number} height The new height to set. This may be one of:<div class="mdetail-params"><ul>
3160 * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
3161 * <li>A String used to set the CSS height style.</li>
3162 * <li><i>undefined</i> to leave the height unchanged.</li>
3164 * @return {Ext.BoxComponent} this
3166 setHeight : function(height){
3167 return this.setSize(undefined, height);
3171 * Gets the current size of the component's underlying element.
3172 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
3174 getSize : function(){
3175 return this.getResizeEl().getSize();
3179 * Gets the current width of the component's underlying element.
3182 getWidth : function(){
3183 return this.getResizeEl().getWidth();
3187 * Gets the current height of the component's underlying element.
3190 getHeight : function(){
3191 return this.getResizeEl().getHeight();
3195 * Gets the current size of the component's underlying element, including space taken by its margins.
3196 * @return {Object} An object containing the element's size {width: (element width + left/right margins), height: (element height + top/bottom margins)}
3198 getOuterSize : function(){
3199 var el = this.getResizeEl();
3200 return {width: el.getWidth() + el.getMargins('lr'),
3201 height: el.getHeight() + el.getMargins('tb')};
3205 * Gets the current XY position of the component's underlying element.
3206 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
3207 * @return {Array} The XY position of the element (e.g., [100, 200])
3209 getPosition : function(local){
3210 var el = this.getPositionEl();
3212 return [el.getLeft(true), el.getTop(true)];
3214 return this.xy || el.getXY();
3218 * Gets the current box measurements of the component's underlying element.
3219 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
3220 * @return {Object} box An object in the format {x, y, width, height}
3222 getBox : function(local){
3223 var pos = this.getPosition(local);
3224 var s = this.getSize();
3231 * Sets the current box measurements of the component's underlying element.
3232 * @param {Object} box An object in the format {x, y, width, height}
3233 * @return {Ext.BoxComponent} this
3235 updateBox : function(box){
3236 this.setSize(box.width, box.height);
3237 this.setPagePosition(box.x, box.y);
3242 * <p>Returns the outermost Element of this Component which defines the Components overall size.</p>
3243 * <p><i>Usually</i> this will return the same Element as <code>{@link #getEl}</code>,
3244 * but in some cases, a Component may have some more wrapping Elements around its main
3245 * active Element.</p>
3246 * <p>An example is a ComboBox. It is encased in a <i>wrapping</i> Element which
3247 * contains both the <code><input></code> Element (which is what would be returned
3248 * by its <code>{@link #getEl}</code> method, <i>and</i> the trigger button Element.
3249 * This Element is returned as the <code>resizeEl</code>.
3250 * @return {Ext.Element} The Element which is to be resized by size managing layouts.
3252 getResizeEl : function(){
3253 return this.resizeEl || this.el;
3257 * Sets the overflow on the content element of the component.
3258 * @param {Boolean} scroll True to allow the Component to auto scroll.
3259 * @return {Ext.BoxComponent} this
3261 setAutoScroll : function(scroll){
3263 this.getContentTarget().setOverflow(scroll ? 'auto' : '');
3265 this.autoScroll = scroll;
3270 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
3271 * This method fires the {@link #move} event.
3272 * @param {Number} left The new left
3273 * @param {Number} top The new top
3274 * @return {Ext.BoxComponent} this
3276 setPosition : function(x, y){
3277 if(x && typeof x[1] == 'number'){
3286 var adj = this.adjustPosition(x, y);
3287 var ax = adj.x, ay = adj.y;
3289 var el = this.getPositionEl();
3290 if(ax !== undefined || ay !== undefined){
3291 if(ax !== undefined && ay !== undefined){
3292 el.setLeftTop(ax, ay);
3293 }else if(ax !== undefined){
3295 }else if(ay !== undefined){
3298 this.onPosition(ax, ay);
3299 this.fireEvent('move', this, ax, ay);
3305 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
3306 * This method fires the {@link #move} event.
3307 * @param {Number} x The new x position
3308 * @param {Number} y The new y position
3309 * @return {Ext.BoxComponent} this
3311 setPagePosition : function(x, y){
3312 if(x && typeof x[1] == 'number'){
3321 if(x === undefined || y === undefined){ // cannot translate undefined points
3324 var p = this.getPositionEl().translatePoints(x, y);
3325 this.setPosition(p.left, p.top);
3330 afterRender : function(){
3331 Ext.BoxComponent.superclass.afterRender.call(this);
3333 this.resizeEl = Ext.get(this.resizeEl);
3335 if(this.positionEl){
3336 this.positionEl = Ext.get(this.positionEl);
3338 this.boxReady = true;
3339 Ext.isDefined(this.autoScroll) && this.setAutoScroll(this.autoScroll);
3340 this.setSize(this.width, this.height);
3341 if(this.x || this.y){
3342 this.setPosition(this.x, this.y);
3343 }else if(this.pageX || this.pageY){
3344 this.setPagePosition(this.pageX, this.pageY);
3349 * Force the component's size to recalculate based on the underlying element's current height and width.
3350 * @return {Ext.BoxComponent} this
3352 syncSize : function(){
3353 delete this.lastSize;
3354 this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
3359 * Called after the component is resized, this method is empty by default but can be implemented by any
3360 * subclass that needs to perform custom logic after a resize occurs.
3361 * @param {Number} adjWidth The box-adjusted width that was set
3362 * @param {Number} adjHeight The box-adjusted height that was set
3363 * @param {Number} rawWidth The width that was originally specified
3364 * @param {Number} rawHeight The height that was originally specified
3366 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
3370 * Called after the component is moved, this method is empty by default but can be implemented by any
3371 * subclass that needs to perform custom logic after a move occurs.
3372 * @param {Number} x The new x position
3373 * @param {Number} y The new y position
3375 onPosition : function(x, y){
3380 adjustSize : function(w, h){
3384 if(this.autoHeight){
3387 return {width : w, height: h};
3391 adjustPosition : function(x, y){
3392 return {x : x, y: y};
3395 Ext.reg('box', Ext.BoxComponent);
3400 * @extends Ext.BoxComponent
3401 * <p>Used to provide a sizable space in a layout.</p>
3403 * @param {Object} config
3405 Ext.Spacer = Ext.extend(Ext.BoxComponent, {
3408 Ext.reg('spacer', Ext.Spacer);/**
\r
3409 * @class Ext.SplitBar
\r
3410 * @extends Ext.util.Observable
\r
3411 * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).
\r
3415 var split = new Ext.SplitBar("elementToDrag", "elementToSize",
\r
3416 Ext.SplitBar.HORIZONTAL, Ext.SplitBar.LEFT);
\r
3417 split.setAdapter(new Ext.SplitBar.AbsoluteLayoutAdapter("container"));
\r
3418 split.minSize = 100;
\r
3419 split.maxSize = 600;
\r
3420 split.animate = true;
\r
3421 split.on('moved', splitterMoved);
\r
3424 * Create a new SplitBar
\r
3425 * @param {Mixed} dragElement The element to be dragged and act as the SplitBar.
\r
3426 * @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged
\r
3427 * @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
\r
3428 * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or
\r
3429 Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial
\r
3430 position of the SplitBar).
\r
3432 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
\r
3435 this.el = Ext.get(dragElement, true);
\r
3436 this.el.dom.unselectable = "on";
\r
3438 this.resizingEl = Ext.get(resizingElement, true);
\r
3442 * The orientation of the split. Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
\r
3443 * Note: If this is changed after creating the SplitBar, the placement property must be manually updated
\r
3446 this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
\r
3449 * The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.
\r
3451 * @property tickSize
\r
3454 * The minimum size of the resizing element. (Defaults to 0)
\r
3460 * The maximum size of the resizing element. (Defaults to 2000)
\r
3463 this.maxSize = 2000;
\r
3466 * Whether to animate the transition to the new size
\r
3469 this.animate = false;
\r
3472 * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.
\r
3475 this.useShim = false;
\r
3480 if(!existingProxy){
\r
3482 this.proxy = Ext.SplitBar.createProxy(this.orientation);
\r
3484 this.proxy = Ext.get(existingProxy).dom;
\r
3487 this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
\r
3490 this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
\r
3493 this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
\r
3496 this.dragSpecs = {};
\r
3499 * @private The adapter to use to positon and resize elements
\r
3501 this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
\r
3502 this.adapter.init(this);
\r
3504 if(this.orientation == Ext.SplitBar.HORIZONTAL){
\r
3506 this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
\r
3507 this.el.addClass("x-splitbar-h");
\r
3510 this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
\r
3511 this.el.addClass("x-splitbar-v");
\r
3517 * Fires when the splitter is moved (alias for {@link #moved})
\r
3518 * @param {Ext.SplitBar} this
\r
3519 * @param {Number} newSize the new width or height
\r
3524 * Fires when the splitter is moved
\r
3525 * @param {Ext.SplitBar} this
\r
3526 * @param {Number} newSize the new width or height
\r
3530 * @event beforeresize
\r
3531 * Fires before the splitter is dragged
\r
3532 * @param {Ext.SplitBar} this
\r
3539 Ext.SplitBar.superclass.constructor.call(this);
\r
3542 Ext.extend(Ext.SplitBar, Ext.util.Observable, {
\r
3543 onStartProxyDrag : function(x, y){
\r
3544 this.fireEvent("beforeresize", this);
\r
3545 this.overlay = Ext.DomHelper.append(document.body, {cls: "x-drag-overlay", html: " "}, true);
\r
3546 this.overlay.unselectable();
\r
3547 this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
\r
3548 this.overlay.show();
\r
3549 Ext.get(this.proxy).setDisplayed("block");
\r
3550 var size = this.adapter.getElementSize(this);
\r
3551 this.activeMinSize = this.getMinimumSize();
\r
3552 this.activeMaxSize = this.getMaximumSize();
\r
3553 var c1 = size - this.activeMinSize;
\r
3554 var c2 = Math.max(this.activeMaxSize - size, 0);
\r
3555 if(this.orientation == Ext.SplitBar.HORIZONTAL){
\r
3556 this.dd.resetConstraints();
\r
3557 this.dd.setXConstraint(
\r
3558 this.placement == Ext.SplitBar.LEFT ? c1 : c2,
\r
3559 this.placement == Ext.SplitBar.LEFT ? c2 : c1,
\r
3562 this.dd.setYConstraint(0, 0);
\r
3564 this.dd.resetConstraints();
\r
3565 this.dd.setXConstraint(0, 0);
\r
3566 this.dd.setYConstraint(
\r
3567 this.placement == Ext.SplitBar.TOP ? c1 : c2,
\r
3568 this.placement == Ext.SplitBar.TOP ? c2 : c1,
\r
3572 this.dragSpecs.startSize = size;
\r
3573 this.dragSpecs.startPoint = [x, y];
\r
3574 Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
\r
3578 * @private Called after the drag operation by the DDProxy
\r
3580 onEndProxyDrag : function(e){
\r
3581 Ext.get(this.proxy).setDisplayed(false);
\r
3582 var endPoint = Ext.lib.Event.getXY(e);
\r
3584 Ext.destroy(this.overlay);
\r
3585 delete this.overlay;
\r
3588 if(this.orientation == Ext.SplitBar.HORIZONTAL){
\r
3589 newSize = this.dragSpecs.startSize +
\r
3590 (this.placement == Ext.SplitBar.LEFT ?
\r
3591 endPoint[0] - this.dragSpecs.startPoint[0] :
\r
3592 this.dragSpecs.startPoint[0] - endPoint[0]
\r
3595 newSize = this.dragSpecs.startSize +
\r
3596 (this.placement == Ext.SplitBar.TOP ?
\r
3597 endPoint[1] - this.dragSpecs.startPoint[1] :
\r
3598 this.dragSpecs.startPoint[1] - endPoint[1]
\r
3601 newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
\r
3602 if(newSize != this.dragSpecs.startSize){
\r
3603 if(this.fireEvent('beforeapply', this, newSize) !== false){
\r
3604 this.adapter.setElementSize(this, newSize);
\r
3605 this.fireEvent("moved", this, newSize);
\r
3606 this.fireEvent("resize", this, newSize);
\r
3612 * Get the adapter this SplitBar uses
\r
3613 * @return The adapter object
\r
3615 getAdapter : function(){
\r
3616 return this.adapter;
\r
3620 * Set the adapter this SplitBar uses
\r
3621 * @param {Object} adapter A SplitBar adapter object
\r
3623 setAdapter : function(adapter){
\r
3624 this.adapter = adapter;
\r
3625 this.adapter.init(this);
\r
3629 * Gets the minimum size for the resizing element
\r
3630 * @return {Number} The minimum size
\r
3632 getMinimumSize : function(){
\r
3633 return this.minSize;
\r
3637 * Sets the minimum size for the resizing element
\r
3638 * @param {Number} minSize The minimum size
\r
3640 setMinimumSize : function(minSize){
\r
3641 this.minSize = minSize;
\r
3645 * Gets the maximum size for the resizing element
\r
3646 * @return {Number} The maximum size
\r
3648 getMaximumSize : function(){
\r
3649 return this.maxSize;
\r
3653 * Sets the maximum size for the resizing element
\r
3654 * @param {Number} maxSize The maximum size
\r
3656 setMaximumSize : function(maxSize){
\r
3657 this.maxSize = maxSize;
\r
3661 * Sets the initialize size for the resizing element
\r
3662 * @param {Number} size The initial size
\r
3664 setCurrentSize : function(size){
\r
3665 var oldAnimate = this.animate;
\r
3666 this.animate = false;
\r
3667 this.adapter.setElementSize(this, size);
\r
3668 this.animate = oldAnimate;
\r
3672 * Destroy this splitbar.
\r
3673 * @param {Boolean} removeEl True to remove the element
\r
3675 destroy : function(removeEl){
\r
3676 Ext.destroy(this.shim, Ext.get(this.proxy));
\r
3681 this.purgeListeners();
\r
3686 * @private static Create our own proxy element element. So it will be the same same size on all browsers, we won't use borders. Instead we use a background color.
\r
3688 Ext.SplitBar.createProxy = function(dir){
\r
3689 var proxy = new Ext.Element(document.createElement("div"));
\r
3690 document.body.appendChild(proxy.dom);
\r
3691 proxy.unselectable();
\r
3692 var cls = 'x-splitbar-proxy';
\r
3693 proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
\r
3698 * @class Ext.SplitBar.BasicLayoutAdapter
\r
3699 * Default Adapter. It assumes the splitter and resizing element are not positioned
\r
3700 * elements and only gets/sets the width of the element. Generally used for table based layouts.
\r
3702 Ext.SplitBar.BasicLayoutAdapter = function(){
\r
3705 Ext.SplitBar.BasicLayoutAdapter.prototype = {
\r
3706 // do nothing for now
\r
3707 init : function(s){
\r
3711 * Called before drag operations to get the current size of the resizing element.
\r
3712 * @param {Ext.SplitBar} s The SplitBar using this adapter
\r
3714 getElementSize : function(s){
\r
3715 if(s.orientation == Ext.SplitBar.HORIZONTAL){
\r
3716 return s.resizingEl.getWidth();
\r
3718 return s.resizingEl.getHeight();
\r
3723 * Called after drag operations to set the size of the resizing element.
\r
3724 * @param {Ext.SplitBar} s The SplitBar using this adapter
\r
3725 * @param {Number} newSize The new size to set
\r
3726 * @param {Function} onComplete A function to be invoked when resizing is complete
\r
3728 setElementSize : function(s, newSize, onComplete){
\r
3729 if(s.orientation == Ext.SplitBar.HORIZONTAL){
\r
3731 s.resizingEl.setWidth(newSize);
\r
3733 onComplete(s, newSize);
\r
3736 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
\r
3741 s.resizingEl.setHeight(newSize);
\r
3743 onComplete(s, newSize);
\r
3746 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
\r
3753 *@class Ext.SplitBar.AbsoluteLayoutAdapter
\r
3754 * @extends Ext.SplitBar.BasicLayoutAdapter
\r
3755 * Adapter that moves the splitter element to align with the resized sizing element.
\r
3756 * Used with an absolute positioned SplitBar.
\r
3757 * @param {Mixed} container The container that wraps around the absolute positioned content. If it's
\r
3758 * document.body, make sure you assign an id to the body element.
\r
3760 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
\r
3761 this.basic = new Ext.SplitBar.BasicLayoutAdapter();
\r
3762 this.container = Ext.get(container);
\r
3765 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
\r
3766 init : function(s){
\r
3767 this.basic.init(s);
\r
3770 getElementSize : function(s){
\r
3771 return this.basic.getElementSize(s);
\r
3774 setElementSize : function(s, newSize, onComplete){
\r
3775 this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
\r
3778 moveSplitter : function(s){
\r
3779 var yes = Ext.SplitBar;
\r
3780 switch(s.placement){
\r
3782 s.el.setX(s.resizingEl.getRight());
\r
3785 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
\r
3788 s.el.setY(s.resizingEl.getBottom());
\r
3791 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
\r
3798 * Orientation constant - Create a vertical SplitBar
\r
3802 Ext.SplitBar.VERTICAL = 1;
\r
3805 * Orientation constant - Create a horizontal SplitBar
\r
3809 Ext.SplitBar.HORIZONTAL = 2;
\r
3812 * Placement constant - The resizing element is to the left of the splitter element
\r
3816 Ext.SplitBar.LEFT = 1;
\r
3819 * Placement constant - The resizing element is to the right of the splitter element
\r
3823 Ext.SplitBar.RIGHT = 2;
\r
3826 * Placement constant - The resizing element is positioned above the splitter element
\r
3830 Ext.SplitBar.TOP = 3;
\r
3833 * Placement constant - The resizing element is positioned under splitter element
\r
3837 Ext.SplitBar.BOTTOM = 4;
\r
3839 * @class Ext.Container
3840 * @extends Ext.BoxComponent
3841 * <p>Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the
3842 * basic behavior of containing items, namely adding, inserting and removing items.</p>
3844 * <p>The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}.
3845 * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight
3846 * Container to be encapsulated by an HTML element to your specifications by using the
3847 * <code><b>{@link Ext.Component#autoEl autoEl}</b></code> config option. This is a useful technique when creating
3848 * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels}
3851 * <p>The code below illustrates both how to explicitly create a Container, and how to implicitly
3852 * create one using the <b><code>'container'</code></b> xtype:<pre><code>
3853 // explicitly create a Container
3854 var embeddedColumns = new Ext.Container({
3855 autoEl: 'div', // This is the default
3858 // implicitly create Container by specifying xtype
3860 autoEl: 'div', // This is the default.
3867 // The two items below will be Ext.Containers, each encapsulated by a <DIV> element.
3872 fieldLabel: 'Start date'
3878 fieldLabel: 'End date'
3881 });</code></pre></p>
3883 * <p><u><b>Layout</b></u></p>
3884 * <p>Container classes delegate the rendering of child Components to a layout
3885 * manager class which must be configured into the Container using the
3886 * <code><b>{@link #layout}</b></code> configuration property.</p>
3887 * <p>When either specifying child <code>{@link #items}</code> of a Container,
3888 * or dynamically {@link #add adding} Components to a Container, remember to
3889 * consider how you wish the Container to arrange those child elements, and
3890 * whether those child elements need to be sized using one of Ext's built-in
3891 * <b><code>{@link #layout}</code></b> schemes. By default, Containers use the
3892 * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only
3893 * renders child components, appending them one after the other inside the
3894 * Container, and <b>does not apply any sizing</b> at all.</p>
3895 * <p>A common mistake is when a developer neglects to specify a
3896 * <b><code>{@link #layout}</code></b> (e.g. widgets like GridPanels or
3897 * TreePanels are added to Containers for which no <code><b>{@link #layout}</b></code>
3898 * has been specified). If a Container is left to use the default
3899 * {@link Ext.layout.ContainerLayout ContainerLayout} scheme, none of its
3900 * child components will be resized, or changed in any way when the Container
3902 * <p>Certain layout managers allow dynamic addition of child components.
3903 * Those that do include {@link Ext.layout.CardLayout},
3904 * {@link Ext.layout.AnchorLayout}, {@link Ext.layout.FormLayout}, and
3905 * {@link Ext.layout.TableLayout}. For example:<pre><code>
3906 // Create the GridPanel.
3907 var myNewGrid = new Ext.grid.GridPanel({
3909 columns: myColumnModel,
3910 title: 'Results', // the title becomes the title of the tab
3913 myTabPanel.add(myNewGrid); // {@link Ext.TabPanel} implicitly uses {@link Ext.layout.CardLayout CardLayout}
3914 myTabPanel.{@link Ext.TabPanel#setActiveTab setActiveTab}(myNewGrid);
3916 * <p>The example above adds a newly created GridPanel to a TabPanel. Note that
3917 * a TabPanel uses {@link Ext.layout.CardLayout} as its layout manager which
3918 * means all its child items are sized to {@link Ext.layout.FitLayout fit}
3919 * exactly into its client area.
3920 * <p><b><u>Overnesting is a common problem</u></b>.
3921 * An example of overnesting occurs when a GridPanel is added to a TabPanel
3922 * by wrapping the GridPanel <i>inside</i> a wrapping Panel (that has no
3923 * <code><b>{@link #layout}</b></code> specified) and then add that wrapping Panel
3924 * to the TabPanel. The point to realize is that a GridPanel <b>is</b> a
3925 * Component which can be added directly to a Container. If the wrapping Panel
3926 * has no <code><b>{@link #layout}</b></code> configuration, then the overnested
3927 * GridPanel will not be sized as expected.<p>
3929 * <p><u><b>Adding via remote configuration</b></u></p>
3931 * <p>A server side script can be used to add Components which are generated dynamically on the server.
3932 * An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server
3933 * based on certain parameters:
3935 // execute an Ajax request to invoke server side script:
3937 url: 'gen-invoice-grid.php',
3938 // send additional parameters to instruct server script
3940 startDate: Ext.getCmp('start-date').getValue(),
3941 endDate: Ext.getCmp('end-date').getValue()
3943 // process the response object to add it to the TabPanel:
3944 success: function(xhr) {
3945 var newComponent = eval(xhr.responseText); // see discussion below
3946 myTabPanel.add(newComponent); // add the component to the TabPanel
3947 myTabPanel.setActiveTab(newComponent);
3949 failure: function() {
3950 Ext.Msg.alert("Grid create failed", "Server communication failure");
3954 * <p>The server script needs to return an executable Javascript statement which, when processed
3955 * using <code>eval()</code>, will return either a config object with an {@link Ext.Component#xtype xtype},
3956 * or an instantiated Component. The server might return this for example:</p><pre><code>
3958 function formatDate(value){
3959 return value ? value.dateFormat('M d, Y') : '';
3962 var store = new Ext.data.Store({
3963 url: 'get-invoice-data.php',
3965 startDate: '01/01/2008',
3966 endDate: '01/31/2008'
3968 reader: new Ext.data.JsonReader({
3969 record: 'transaction',
3971 totalRecords: 'total'
3975 {name: 'date', type: 'date', dateFormat: 'm/d/Y'},
3976 {name: 'value', type: 'float'}
3980 var grid = new Ext.grid.GridPanel({
3981 title: 'Invoice Report',
3982 bbar: new Ext.PagingToolbar(store),
3985 {header: "Customer", width: 250, dataIndex: 'customer', sortable: true},
3986 {header: "Invoice Number", width: 120, dataIndex: 'invNo', sortable: true},
3987 {header: "Invoice Date", width: 100, dataIndex: 'date', renderer: formatDate, sortable: true},
3988 {header: "Value", width: 120, dataIndex: 'value', renderer: 'usMoney', sortable: true}
3992 return grid; // return instantiated component
3995 * <p>When the above code fragment is passed through the <code>eval</code> function in the success handler
3996 * of the Ajax request, the code is executed by the Javascript processor, and the anonymous function
3997 * runs, and returns the instantiated grid component.</p>
3998 * <p>Note: since the code above is <i>generated</i> by a server script, the <code>baseParams</code> for
3999 * the Store, the metadata to allow generation of the Record layout, and the ColumnModel
4000 * can all be generated into the code since these are all known on the server.</p>
4004 Ext.Container = Ext.extend(Ext.BoxComponent, {
4006 * @cfg {Boolean} monitorResize
4007 * True to automatically monitor window resize events to handle anything that is sensitive to the current size
4008 * of the viewport. This value is typically managed by the chosen <code>{@link #layout}</code> and should not need
4009 * to be set manually.
4012 * @cfg {String/Object} layout
4013 * <p><b>*Important</b>: In order for child items to be correctly sized and
4014 * positioned, typically a layout manager <b>must</b> be specified through
4015 * the <code>layout</code> configuration option.</p>
4016 * <br><p>The sizing and positioning of child {@link items} is the responsibility of
4017 * the Container's layout manager which creates and manages the type of layout
4018 * you have in mind. For example:</p><pre><code>
4020 width:300, height: 300,
4021 layout: 'fit', // explicitly set layout manager: override the default (layout:'auto')
4023 title: 'Panel inside a Window'
4027 * <p>If the {@link #layout} configuration is not explicitly specified for
4028 * a general purpose container (e.g. Container or Panel) the
4029 * {@link Ext.layout.ContainerLayout default layout manager} will be used
4030 * which does nothing but render child components sequentially into the
4031 * Container (no sizing or positioning will be performed in this situation).
4032 * Some container classes implicitly specify a default layout
4033 * (e.g. FormPanel specifies <code>layout:'form'</code>). Other specific
4034 * purpose classes internally specify/manage their internal layout (e.g.
4035 * GridPanel, TabPanel, TreePanel, Toolbar, Menu, etc.).</p>
4036 * <br><p><b><code>layout</code></b> may be specified as either as an Object or
4037 * as a String:</p><div><ul class="mdetail-params">
4039 * <li><u>Specify as an Object</u></li>
4040 * <div><ul class="mdetail-params">
4041 * <li>Example usage:</li>
4050 * <li><code><b>type</b></code></li>
4051 * <br/><p>The layout type to be used for this container. If not specified,
4052 * a default {@link Ext.layout.ContainerLayout} will be created and used.</p>
4053 * <br/><p>Valid layout <code>type</code> values are:</p>
4054 * <div class="sub-desc"><ul class="mdetail-params">
4055 * <li><code><b>{@link Ext.layout.AbsoluteLayout absolute}</b></code></li>
4056 * <li><code><b>{@link Ext.layout.AccordionLayout accordion}</b></code></li>
4057 * <li><code><b>{@link Ext.layout.AnchorLayout anchor}</b></code></li>
4058 * <li><code><b>{@link Ext.layout.ContainerLayout auto}</b></code> <b>Default</b></li>
4059 * <li><code><b>{@link Ext.layout.BorderLayout border}</b></code></li>
4060 * <li><code><b>{@link Ext.layout.CardLayout card}</b></code></li>
4061 * <li><code><b>{@link Ext.layout.ColumnLayout column}</b></code></li>
4062 * <li><code><b>{@link Ext.layout.FitLayout fit}</b></code></li>
4063 * <li><code><b>{@link Ext.layout.FormLayout form}</b></code></li>
4064 * <li><code><b>{@link Ext.layout.HBoxLayout hbox}</b></code></li>
4065 * <li><code><b>{@link Ext.layout.MenuLayout menu}</b></code></li>
4066 * <li><code><b>{@link Ext.layout.TableLayout table}</b></code></li>
4067 * <li><code><b>{@link Ext.layout.ToolbarLayout toolbar}</b></code></li>
4068 * <li><code><b>{@link Ext.layout.VBoxLayout vbox}</b></code></li>
4071 * <li>Layout specific configuration properties</li>
4072 * <br/><p>Additional layout specific configuration properties may also be
4073 * specified. For complete details regarding the valid config options for
4074 * each layout type, see the layout class corresponding to the <code>type</code>
4079 * <li><u>Specify as a String</u></li>
4080 * <div><ul class="mdetail-params">
4081 * <li>Example usage:</li>
4089 * <li><code><b>layout</b></code></li>
4090 * <br/><p>The layout <code>type</code> to be used for this container (see list
4091 * of valid layout type values above).</p><br/>
4092 * <li><code><b>{@link #layoutConfig}</b></code></li>
4093 * <br/><p>Additional layout specific configuration properties. For complete
4094 * details regarding the valid config options for each layout type, see the
4095 * layout class corresponding to the <code>layout</code> specified.</p>
4096 * </ul></div></ul></div>
4099 * @cfg {Object} layoutConfig
4100 * This is a config object containing properties specific to the chosen
4101 * <b><code>{@link #layout}</code></b> if <b><code>{@link #layout}</code></b>
4102 * has been specified as a <i>string</i>.</p>
4105 * @cfg {Boolean/Number} bufferResize
4106 * When set to true (50 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer
4107 * the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers
4108 * with a large quantity of sub-components for which frequent layout calls would be expensive. Defaults to <code>50</code>.
4110 // Deprecated - will be removed in 3.2.x
4114 * @cfg {String/Number} activeItem
4115 * A string component id or the numeric index of the component that should be initially activated within the
4116 * container's layout on render. For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first
4117 * item in the container's collection). activeItem only applies to layout styles that can display
4118 * items one at a time (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout} and
4119 * {@link Ext.layout.FitLayout}). Related to {@link Ext.layout.ContainerLayout#activeItem}.
4122 * @cfg {Object/Array} items
4123 * <pre><b>** IMPORTANT</b>: be sure to <b>{@link #layout specify a <code>layout</code>} if needed ! **</b></pre>
4124 * <p>A single item, or an array of child Components to be added to this container,
4127 // specifying a single item
4129 layout: 'fit', // specify a layout!
4131 // specifying multiple items
4132 items: [{...}, {...}],
4133 layout: 'anchor', // specify a layout!
4135 * <p>Each item may be:</p>
4136 * <div><ul class="mdetail-params">
4137 * <li>any type of object based on {@link Ext.Component}</li>
4138 * <li>a fully instanciated object or</li>
4139 * <li>an object literal that:</li>
4140 * <div><ul class="mdetail-params">
4141 * <li>has a specified <code>{@link Ext.Component#xtype xtype}</code></li>
4142 * <li>the {@link Ext.Component#xtype} specified is associated with the Component
4143 * desired and should be chosen from one of the available xtypes as listed
4144 * in {@link Ext.Component}.</li>
4145 * <li>If an <code>{@link Ext.Component#xtype xtype}</code> is not explicitly
4146 * specified, the {@link #defaultType} for that Container is used.</li>
4147 * <li>will be "lazily instanciated", avoiding the overhead of constructing a fully
4148 * instanciated Component object</li>
4149 * </ul></div></ul></div>
4150 * <p><b>Notes</b>:</p>
4151 * <div><ul class="mdetail-params">
4152 * <li>Ext uses lazy rendering. Child Components will only be rendered
4153 * should it become necessary. Items are automatically laid out when they are first
4154 * shown (no sizing is done while hidden), or in response to a {@link #doLayout} call.</li>
4155 * <li>Do not specify <code>{@link Ext.Panel#contentEl contentEl}</code>/
4156 * <code>{@link Ext.Panel#html html}</code> with <code>items</code>.</li>
4160 * @cfg {Object|Function} defaults
4161 * <p>This option is a means of applying default settings to all added items whether added through the {@link #items}
4162 * config or via the {@link #add} or {@link #insert} methods.</p>
4163 * <p>If an added item is a config object, and <b>not</b> an instantiated Component, then the default properties are
4164 * unconditionally applied. If the added item <b>is</b> an instantiated Component, then the default properties are
4165 * applied conditionally so as not to override existing properties in the item.</p>
4166 * <p>If the defaults option is specified as a function, then the function will be called using this Container as the
4167 * scope (<code>this</code> reference) and passing the added item as the first parameter. Any resulting object
4168 * from that call is then applied to the item as default properties.</p>
4169 * <p>For example, to automatically apply padding to the body of each of a set of
4170 * contained {@link Ext.Panel} items, you could pass: <code>defaults: {bodyStyle:'padding:15px'}</code>.</p>
4171 * <p>Usage:</p><pre><code>
4172 defaults: { // defaults are applied to items, not the container
4177 xtype: 'panel', // defaults <b>do not</b> have precedence over
4178 id: 'panel1', // options in config objects, so the defaults
4179 autoScroll: false // will not be applied here, panel1 will be autoScroll:false
4181 new Ext.Panel({ // defaults <b>do</b> have precedence over options
4182 id: 'panel2', // options in components, so the defaults
4183 autoScroll: false // will be applied here, panel2 will be autoScroll:true.
4190 /** @cfg {Boolean} autoDestroy
4191 * If true the container will automatically destroy any contained component that is removed from it, else
4192 * destruction must be handled manually (defaults to true).
4196 /** @cfg {Boolean} forceLayout
4197 * If true the container will force a layout initially even if hidden or collapsed. This option
4198 * is useful for forcing forms to render in collapsed or hidden containers. (defaults to false).
4202 /** @cfg {Boolean} hideBorders
4203 * True to hide the borders of each contained component, false to defer to the component's existing
4204 * border settings (defaults to false).
4206 /** @cfg {String} defaultType
4207 * <p>The default {@link Ext.Component xtype} of child Components to create in this Container when
4208 * a child item is specified as a raw configuration object, rather than as an instantiated Component.</p>
4209 * <p>Defaults to <code>'panel'</code>, except {@link Ext.menu.Menu} which defaults to <code>'menuitem'</code>,
4210 * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to <code>'button'</code>.</p>
4212 defaultType : 'panel',
4214 /** @cfg {String} resizeEvent
4215 * The event to listen to for resizing in layouts. Defaults to <code>'resize'</code>.
4217 resizeEvent: 'resize',
4220 * @cfg {Array} bubbleEvents
4221 * <p>An array of events that, when fired, should be bubbled to any parent container.
4222 * See {@link Ext.util.Observable#enableBubble}.
4223 * Defaults to <code>['add', 'remove']</code>.
4225 bubbleEvents: ['add', 'remove'],
4228 initComponent : function(){
4229 Ext.Container.superclass.initComponent.call(this);
4233 * @event afterlayout
4234 * Fires when the components in this container are arranged by the associated layout manager.
4235 * @param {Ext.Container} this
4236 * @param {ContainerLayout} layout The ContainerLayout implementation for this container
4241 * Fires before any {@link Ext.Component} is added or inserted into the container.
4242 * A handler can return false to cancel the add.
4243 * @param {Ext.Container} this
4244 * @param {Ext.Component} component The component being added
4245 * @param {Number} index The index at which the component will be added to the container's items collection
4249 * @event beforeremove
4250 * Fires before any {@link Ext.Component} is removed from the container. A handler can return
4251 * false to cancel the remove.
4252 * @param {Ext.Container} this
4253 * @param {Ext.Component} component The component being removed
4259 * Fires after any {@link Ext.Component} is added or inserted into the container.
4260 * @param {Ext.Container} this
4261 * @param {Ext.Component} component The component that was added
4262 * @param {Number} index The index at which the component was added to the container's items collection
4268 * Fires after any {@link Ext.Component} is removed from the container.
4269 * @param {Ext.Container} this
4270 * @param {Ext.Component} component The component that was removed
4275 this.enableBubble(this.bubbleEvents);
4278 * The collection of components in this container as a {@link Ext.util.MixedCollection}
4279 * @type MixedCollection
4282 var items = this.items;
4290 initItems : function(){
4292 this.items = new Ext.util.MixedCollection(false, this.getComponentId);
4293 this.getLayout(); // initialize the layout
4298 setLayout : function(layout){
4299 if(this.layout && this.layout != layout){
4300 this.layout.setContainer(null);
4303 this.layout = layout;
4304 layout.setContainer(this);
4307 afterRender: function(){
4308 // Render this Container, this should be done before setLayout is called which
4309 // will hook onResize
4310 Ext.Container.superclass.afterRender.call(this);
4312 this.layout = 'auto';
4314 if(Ext.isObject(this.layout) && !this.layout.layout){
4315 this.layoutConfig = this.layout;
4316 this.layout = this.layoutConfig.type;
4318 if(Ext.isString(this.layout)){
4319 this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
4321 this.setLayout(this.layout);
4323 // If a CardLayout, the active item set
4324 if(this.activeItem !== undefined){
4325 var item = this.activeItem;
4326 delete this.activeItem;
4327 this.layout.setActiveItem(item);
4330 // If we have no ownerCt, render and size all children
4332 this.doLayout(false, true);
4335 // This is a manually configured flag set by users in conjunction with renderTo.
4336 // Not to be confused with the flag by the same name used in Layouts.
4337 if(this.monitorResize === true){
4338 Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
4343 * <p>Returns the Element to be used to contain the child Components of this Container.</p>
4344 * <p>An implementation is provided which returns the Container's {@link #getEl Element}, but
4345 * if there is a more complex structure to a Container, this may be overridden to return
4346 * the element into which the {@link #layout layout} renders child Components.</p>
4347 * @return {Ext.Element} The Element to render child Components into.
4349 getLayoutTarget : function(){
4353 // private - used as the key lookup function for the items collection
4354 getComponentId : function(comp){
4355 return comp.getItemId();
4359 * <p>Adds {@link Ext.Component Component}(s) to this Container.</p>
4360 * <br><p><b>Description</b></u> :
4361 * <div><ul class="mdetail-params">
4362 * <li>Fires the {@link #beforeadd} event before adding</li>
4363 * <li>The Container's {@link #defaults default config values} will be applied
4364 * accordingly (see <code>{@link #defaults}</code> for details).</li>
4365 * <li>Fires the {@link #add} event after the component has been added.</li>
4367 * <br><p><b>Notes</b></u> :
4368 * <div><ul class="mdetail-params">
4369 * <li>If the Container is <i>already rendered</i> when <code>add</code>
4370 * is called, you may need to call {@link #doLayout} to refresh the view which causes
4371 * any unrendered child Components to be rendered. This is required so that you can
4372 * <code>add</code> multiple child components if needed while only refreshing the layout
4373 * once. For example:<pre><code>
4374 var tb = new {@link Ext.Toolbar}();
4375 tb.render(document.body); // toolbar is rendered
4376 tb.add({text:'Button 1'}); // add multiple items ({@link #defaultType} for {@link Ext.Toolbar Toolbar} is 'button')
4377 tb.add({text:'Button 2'});
4378 tb.{@link #doLayout}(); // refresh the layout
4379 * </code></pre></li>
4380 * <li><i>Warning:</i> Containers directly managed by the BorderLayout layout manager
4381 * may not be removed or added. See the Notes for {@link Ext.layout.BorderLayout BorderLayout}
4382 * for more details.</li>
4384 * @param {Object/Array} component
4385 * <p>Either a single component or an Array of components to add. See
4386 * <code>{@link #items}</code> for additional information.</p>
4387 * @param {Object} (Optional) component_2
4388 * @param {Object} (Optional) component_n
4389 * @return {Ext.Component} component The Component (or config object) that was added.
4391 add : function(comp){
4393 var args = arguments.length > 1;
4394 if(args || Ext.isArray(comp)){
4396 Ext.each(args ? arguments : comp, function(c){
4397 result.push(this.add(c));
4401 var c = this.lookupComponent(this.applyDefaults(comp));
4402 var index = this.items.length;
4403 if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
4406 c.onAdded(this, index);
4408 this.fireEvent('add', this, c, index);
4413 onAdd : function(c){
4414 // Empty template method
4418 onAdded : function(container, pos) {
4419 //overridden here so we can cascade down, not worth creating a template method.
4420 this.ownerCt = container;
4422 //initialize references for child items
4423 this.cascade(function(c){
4426 this.fireEvent('added', this, container, pos);
4430 * Inserts a Component into this Container at a specified index. Fires the
4431 * {@link #beforeadd} event before inserting, then fires the {@link #add} event after the
4432 * Component has been inserted.
4433 * @param {Number} index The index at which the Component will be inserted
4434 * into the Container's items collection
4435 * @param {Ext.Component} component The child Component to insert.<br><br>
4436 * Ext uses lazy rendering, and will only render the inserted Component should
4437 * it become necessary.<br><br>
4438 * A Component config object may be passed in order to avoid the overhead of
4439 * constructing a real Component object if lazy rendering might mean that the
4440 * inserted Component will not be rendered immediately. To take advantage of
4441 * this 'lazy instantiation', set the {@link Ext.Component#xtype} config
4442 * property to the registered type of the Component wanted.<br><br>
4443 * For a list of all available xtypes, see {@link Ext.Component}.
4444 * @return {Ext.Component} component The Component (or config object) that was
4445 * inserted with the Container's default config values applied.
4447 insert : function(index, comp){
4449 var a = arguments, len = a.length;
4452 for(var i = len-1; i >= 1; --i) {
4453 result.push(this.insert(index, a[i]));
4457 var c = this.lookupComponent(this.applyDefaults(comp));
4458 index = Math.min(index, this.items.length);
4459 if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
4460 if(c.ownerCt == this){
4461 this.items.remove(c);
4463 this.items.insert(index, c);
4464 c.onAdded(this, index);
4466 this.fireEvent('add', this, c, index);
4472 applyDefaults : function(c){
4473 var d = this.defaults;
4475 if(Ext.isFunction(d)){
4476 d = d.call(this, c);
4478 if(Ext.isString(c)){
4479 c = Ext.ComponentMgr.get(c);
4481 }else if(!c.events){
4491 onBeforeAdd : function(item){
4493 item.ownerCt.remove(item, false);
4495 if(this.hideBorders === true){
4496 item.border = (item.border === true);
4501 * Removes a component from this container. Fires the {@link #beforeremove} event before removing, then fires
4502 * the {@link #remove} event after the component has been removed.
4503 * @param {Component/String} component The component reference or id to remove.
4504 * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
4505 * Defaults to the value of this Container's {@link #autoDestroy} config.
4506 * @return {Ext.Component} component The Component that was removed.
4508 remove : function(comp, autoDestroy){
4510 var c = this.getComponent(comp);
4511 if(c && this.fireEvent('beforeremove', this, c) !== false){
4512 this.doRemove(c, autoDestroy);
4513 this.fireEvent('remove', this, c);
4518 onRemove: function(c){
4519 // Empty template method
4523 doRemove: function(c, autoDestroy){
4524 var l = this.layout,
4525 hasLayout = l && this.rendered;
4530 this.items.remove(c);
4533 if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
4542 * Removes all components from this container.
4543 * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
4544 * Defaults to the value of this Container's {@link #autoDestroy} config.
4545 * @return {Array} Array of the destroyed components
4547 removeAll: function(autoDestroy){
4549 var item, rem = [], items = [];
4550 this.items.each(function(i){
4553 for (var i = 0, len = rem.length; i < len; ++i){
4555 this.remove(item, autoDestroy);
4556 if(item.ownerCt !== this){
4564 * Examines this container's <code>{@link #items}</code> <b>property</b>
4565 * and gets a direct child component of this container.
4566 * @param {String/Number} comp This parameter may be any of the following:
4567 * <div><ul class="mdetail-params">
4568 * <li>a <b><code>String</code></b> : representing the <code>{@link Ext.Component#itemId itemId}</code>
4569 * or <code>{@link Ext.Component#id id}</code> of the child component </li>
4570 * <li>a <b><code>Number</code></b> : representing the position of the child component
4571 * within the <code>{@link #items}</code> <b>property</b></li>
4573 * <p>For additional information see {@link Ext.util.MixedCollection#get}.
4574 * @return Ext.Component The component (if found).
4576 getComponent : function(comp){
4577 if(Ext.isObject(comp)){
4578 comp = comp.getItemId();
4580 return this.items.get(comp);
4584 lookupComponent : function(comp){
4585 if(Ext.isString(comp)){
4586 return Ext.ComponentMgr.get(comp);
4587 }else if(!comp.events){
4588 return this.createComponent(comp);
4594 createComponent : function(config, defaultType){
4595 // add in ownerCt at creation time but then immediately
4596 // remove so that onBeforeAdd can handle it
4597 var c = config.render ? config : Ext.create(Ext.apply({
4599 }, config), defaultType || this.defaultType);
4605 * We can only lay out if there is a view area in which to layout.
4606 * display:none on the layout target, *or any of its parent elements* will mean it has no view area.
4610 canLayout : function() {
4611 var el = this.getVisibilityEl();
4612 return el && el.dom && !el.isStyle("display", "none");
4616 * Force this container's layout to be recalculated. A call to this function is required after adding a new component
4617 * to an already rendered container, or possibly after changing sizing/position properties of child components.
4618 * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto
4619 * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer)
4620 * @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden.
4621 * @return {Ext.Container} this
4624 doLayout : function(shallow, force){
4625 var rendered = this.rendered,
4626 forceLayout = force || this.forceLayout;
4628 if(this.collapsed || !this.canLayout()){
4629 this.deferLayout = this.deferLayout || !shallow;
4633 shallow = shallow && !this.deferLayout;
4635 delete this.deferLayout;
4637 if(rendered && this.layout){
4638 this.layout.layout();
4640 if(shallow !== true && this.items){
4641 var cs = this.items.items;
4642 for(var i = 0, len = cs.length; i < len; i++){
4645 c.doLayout(false, forceLayout);
4650 this.onLayout(shallow, forceLayout);
4652 // Initial layout completed
4653 this.hasLayout = true;
4654 delete this.forceLayout;
4657 onLayout : Ext.emptyFn,
4660 shouldBufferLayout: function(){
4662 * Returns true if the container should buffer a layout.
4663 * This is true only if the container has previously been laid out
4664 * and has a parent container that is pending a layout.
4666 var hl = this.hasLayout;
4668 // Only ever buffer if we've laid out the first time and we have one pending.
4669 return hl ? !this.hasLayoutPending() : false;
4671 // Never buffer initial layout
4676 hasLayoutPending: function(){
4677 // Traverse hierarchy to see if any parent container has a pending layout.
4678 var pending = false;
4679 this.ownerCt.bubble(function(c){
4680 if(c.layoutPending){
4688 onShow : function(){
4689 // removes css classes that were added to hide
4690 Ext.Container.superclass.onShow.call(this);
4691 // If we were sized during the time we were hidden, layout.
4692 if(Ext.isDefined(this.deferLayout)){
4693 delete this.deferLayout;
4694 this.doLayout(true);
4699 * Returns the layout currently in use by the container. If the container does not currently have a layout
4700 * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout.
4701 * @return {ContainerLayout} layout The container's layout
4703 getLayout : function(){
4705 var layout = new Ext.layout.ContainerLayout(this.layoutConfig);
4706 this.setLayout(layout);
4712 beforeDestroy : function(){
4715 while(c = this.items.first()){
4716 this.doRemove(c, true);
4719 if(this.monitorResize){
4720 Ext.EventManager.removeResizeListener(this.doLayout, this);
4722 Ext.destroy(this.layout);
4723 Ext.Container.superclass.beforeDestroy.call(this);
4727 * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of
4728 * function call will be the scope provided or the current component. The arguments to the function
4729 * will be the args provided or the current component. If the function returns false at any point,
4730 * the bubble is stopped.
4731 * @param {Function} fn The function to call
4732 * @param {Object} scope (optional) The scope of the function (defaults to current node)
4733 * @param {Array} args (optional) The args to call the function with (default to passing the current component)
4734 * @return {Ext.Container} this
4736 bubble : function(fn, scope, args){
4739 if(fn.apply(scope || p, args || [p]) === false){
4748 * Cascades down the component/container heirarchy from this component (called first), calling the specified function with
4749 * each component. The scope (<i>this</i>) of
4750 * function call will be the scope provided or the current component. The arguments to the function
4751 * will be the args provided or the current component. If the function returns false at any point,
4752 * the cascade is stopped on that branch.
4753 * @param {Function} fn The function to call
4754 * @param {Object} scope (optional) The scope of the function (defaults to current component)
4755 * @param {Array} args (optional) The args to call the function with (defaults to passing the current component)
4756 * @return {Ext.Container} this
4758 cascade : function(fn, scope, args){
4759 if(fn.apply(scope || this, args || [this]) !== false){
4761 var cs = this.items.items;
4762 for(var i = 0, len = cs.length; i < len; i++){
4764 cs[i].cascade(fn, scope, args);
4766 fn.apply(scope || cs[i], args || [cs[i]]);
4775 * Find a component under this container at any level by id
4776 * @param {String} id
4777 * @return Ext.Component
4779 findById : function(id){
4781 this.cascade(function(c){
4782 if(ct != c && c.id === id){
4791 * Find a component under this container at any level by xtype or class
4792 * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
4793 * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
4794 * the default), or true to check whether this Component is directly of the specified xtype.
4795 * @return {Array} Array of Ext.Components
4797 findByType : function(xtype, shallow){
4798 return this.findBy(function(c){
4799 return c.isXType(xtype, shallow);
4804 * Find a component under this container at any level by property
4805 * @param {String} prop
4806 * @param {String} value
4807 * @return {Array} Array of Ext.Components
4809 find : function(prop, value){
4810 return this.findBy(function(c){
4811 return c[prop] === value;
4816 * Find a component under this container at any level by a custom function. If the passed function returns
4817 * true, the component will be included in the results. The passed function is called with the arguments (component, this container).
4818 * @param {Function} fn The function to call
4819 * @param {Object} scope (optional)
4820 * @return {Array} Array of Ext.Components
4822 findBy : function(fn, scope){
4823 var m = [], ct = this;
4824 this.cascade(function(c){
4825 if(ct != c && fn.call(scope || c, c, ct) === true){
4833 * Get a component contained by this container (alias for items.get(key))
4834 * @param {String/Number} key The index or id of the component
4835 * @return {Ext.Component} Ext.Component
4837 get : function(key){
4838 return this.items.get(key);
4842 Ext.Container.LAYOUTS = {};
4843 Ext.reg('container', Ext.Container);
4845 * @class Ext.layout.ContainerLayout
4846 * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
4847 * configuration property. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
4849 Ext.layout.ContainerLayout = Ext.extend(Object, {
4851 * @cfg {String} extraCls
4852 * <p>An optional extra CSS class that will be added to the container. This can be useful for adding
4853 * customized styles to the container or any of its children using standard CSS rules. See
4854 * {@link Ext.Component}.{@link Ext.Component#ctCls ctCls} also.</p>
4855 * <p><b>Note</b>: <tt>extraCls</tt> defaults to <tt>''</tt> except for the following classes
4856 * which assign a value by default:
4857 * <div class="mdetail-params"><ul>
4858 * <li>{@link Ext.layout.AbsoluteLayout Absolute Layout} : <tt>'x-abs-layout-item'</tt></li>
4859 * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-item'</tt></li>
4860 * <li>{@link Ext.layout.ColumnLayout Column Layout} : <tt>'x-column'</tt></li>
4862 * To configure the above Classes with an extra CSS class append to the default. For example,
4863 * for ColumnLayout:<pre><code>
4864 * extraCls: 'x-column custom-class'
4869 * @cfg {Boolean} renderHidden
4870 * True to hide each contained item on render (defaults to false).
4874 * A reference to the {@link Ext.Component} that is active. For example, <pre><code>
4875 * if(myPanel.layout.activeItem.id == 'item-1') { ... }
4877 * <tt>activeItem</tt> only applies to layout styles that can display items one at a time
4878 * (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout}
4879 * and {@link Ext.layout.FitLayout}). Read-only. Related to {@link Ext.Container#activeItem}.
4880 * @type {Ext.Component}
4881 * @property activeItem
4885 monitorResize:false,
4889 constructor : function(config){
4890 this.id = Ext.id(null, 'ext-layout-');
4891 Ext.apply(this, config);
4896 /* Workaround for how IE measures autoWidth elements. It prefers bottom-up measurements
4897 whereas other browser prefer top-down. We will hide all target child elements before we measure and
4898 put them back to get an accurate measurement.
4900 IEMeasureHack : function(target, viewFlag) {
4901 var tChildren = target.dom.childNodes, tLen = tChildren.length, c, d = [], e, i, ret;
4902 for (i = 0 ; i < tLen ; i++) {
4906 d[i] = e.getStyle('display');
4907 e.setStyle({display: 'none'});
4910 ret = target ? target.getViewSize(viewFlag) : {};
4911 for (i = 0 ; i < tLen ; i++) {
4915 e.setStyle({display: d[i]});
4921 // Placeholder for the derived layouts
4922 getLayoutTargetSize : Ext.EmptyFn,
4925 layout : function(){
4926 var ct = this.container, target = ct.getLayoutTarget();
4927 if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
4928 target.addClass(this.targetCls);
4930 this.onLayout(ct, target);
4931 ct.fireEvent('afterlayout', ct, this);
4935 onLayout : function(ct, target){
4936 this.renderAll(ct, target);
4940 isValidParent : function(c, target){
4941 return target && c.getPositionEl().dom.parentNode == (target.dom || target);
4945 renderAll : function(ct, target){
4946 var items = ct.items.items, i, c, len = items.length;
4947 for(i = 0; i < len; i++) {
4949 if(c && (!c.rendered || !this.isValidParent(c, target))){
4950 this.renderItem(c, i, target);
4956 renderItem : function(c, position, target){
4959 c.render(target, position);
4960 this.configureItem(c, position);
4961 }else if(!this.isValidParent(c, target)){
4962 if(Ext.isNumber(position)){
4963 position = target.dom.childNodes[position];
4965 target.dom.insertBefore(c.getPositionEl().dom, position || null);
4966 c.container = target;
4967 this.configureItem(c, position);
4973 // Get all rendered items to lay out.
4974 getRenderedItems: function(ct){
4975 var t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = [];
4976 for (i = 0; i < len; i++) {
4977 if((c = cti[i]).rendered && this.isValidParent(c, t)){
4985 configureItem: function(c, position){
4987 var t = c.getPositionEl ? c.getPositionEl() : c;
4988 t.addClass(this.extraCls);
4990 // If we are forcing a layout, do so *before* we hide so elements have height/width
4991 if(c.doLayout && this.forceLayout){
4994 if (this.renderHidden && c != this.activeItem) {
4999 onRemove: function(c){
5000 if(this.activeItem == c){
5001 delete this.activeItem;
5003 if(c.rendered && this.extraCls){
5004 var t = c.getPositionEl ? c.getPositionEl() : c;
5005 t.removeClass(this.extraCls);
5009 afterRemove: function(c){
5010 if(c.removeRestore){
5011 c.removeMode = 'container';
5012 delete c.removeRestore;
5017 onResize: function(){
5018 var ct = this.container,
5023 if(b = ct.bufferResize){
5024 // Only allow if we should buffer the layout
5025 if(ct.shouldBufferLayout()){
5026 if(!this.resizeTask){
5027 this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
5028 this.resizeBuffer = Ext.isNumber(b) ? b : 50;
5030 ct.layoutPending = true;
5031 this.resizeTask.delay(this.resizeBuffer);
5038 runLayout: function(){
5039 var ct = this.container;
5040 // AutoLayout is known to require the recursive doLayout call, others need this currently (BorderLayout for example)
5041 // but shouldn't. A more extensive review will take place for 3.2 which requires a ContainerMgr with hierarchy lookups.
5045 delete ct.layoutPending;
5049 setContainer : function(ct){
5050 if (!Ext.LayoutManager) {
5051 Ext.LayoutManager = {};
5054 /* This monitorResize flag will be renamed soon as to avoid confusion
5055 * with the Container version which hooks onWindowResize to doLayout
5057 * monitorResize flag in this context attaches the resize event between
5058 * a container and it's layout
5061 if(this.monitorResize && ct != this.container){
5062 var old = this.container;
5064 old.un(old.resizeEvent, this.onResize, this);
5067 ct.on(ct.resizeEvent, this.onResize, this);
5070 this.container = ct;
5074 parseMargins : function(v){
5075 if(Ext.isNumber(v)){
5078 var ms = v.split(' ');
5079 var len = ms.length;
5081 ms[1] = ms[2] = ms[3] = ms[0];
5082 } else if(len == 2){
5085 } else if(len == 3){
5089 top:parseInt(ms[0], 10) || 0,
5090 right:parseInt(ms[1], 10) || 0,
5091 bottom:parseInt(ms[2], 10) || 0,
5092 left:parseInt(ms[3], 10) || 0
5097 * The {@link Ext.Template Ext.Template} used by Field rendering layout classes (such as
5098 * {@link Ext.layout.FormLayout}) to create the DOM structure of a fully wrapped,
5099 * labeled and styled form Field. A default Template is supplied, but this may be
5100 * overriden to create custom field structures. The template processes values returned from
5101 * {@link Ext.layout.FormLayout#getTemplateArgs}.
5102 * @property fieldTpl
5103 * @type Ext.Template
5105 fieldTpl: (function() {
5106 var t = new Ext.Template(
5107 '<div class="x-form-item {itemCls}" tabIndex="-1">',
5108 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
5109 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
5110 '</div><div class="{clearCls}"></div>',
5113 t.disableFormats = true;
5118 * Destroys this layout. This is a template method that is empty by default, but should be implemented
5119 * by subclasses that require explicit destruction to purge event handlers or remove DOM nodes.
5122 destroy : function(){
5123 if(!Ext.isEmpty(this.targetCls)){
5124 var target = this.container.getLayoutTarget();
5126 target.removeClass(this.targetCls);
5131 * @class Ext.layout.AutoLayout
5132 * <p>The AutoLayout is the default layout manager delegated by {@link Ext.Container} to
5133 * render any child Components when no <tt>{@link Ext.Container#layout layout}</tt> is configured into
5134 * a {@link Ext.Container Container}. ContainerLayout provides the basic foundation for all other layout
5135 * classes in Ext. It simply renders all child Components into the Container, performing no sizing or
5136 * positioning services. To utilize a layout that provides sizing and positioning of child Components,
5137 * specify an appropriate <tt>{@link Ext.Container#layout layout}</tt>.</p>
5139 Ext.layout.AutoLayout = Ext.extend(Ext.layout.ContainerLayout, {
5140 runLayout: function(){
5141 var ct = this.container;
5143 delete ct.layoutPending;
5147 Ext.Container.LAYOUTS['auto'] = Ext.layout.AutoLayout;
5149 * @class Ext.layout.FitLayout
\r
5150 * @extends Ext.layout.ContainerLayout
\r
5151 * <p>This is a base class for layouts that contain <b>a single item</b> that automatically expands to fill the layout's
\r
5152 * container. This class is intended to be extended or created via the <tt>layout:'fit'</tt> {@link Ext.Container#layout}
\r
5153 * config, and should generally not need to be created directly via the new keyword.</p>
\r
5154 * <p>FitLayout does not have any direct config options (other than inherited ones). To fit a panel to a container
\r
5155 * using FitLayout, simply set layout:'fit' on the container and add a single panel to it. If the container has
\r
5156 * multiple panels, only the first one will be displayed. Example usage:</p>
\r
5158 var p = new Ext.Panel({
\r
5159 title: 'Fit Layout',
\r
5162 title: 'Inner Panel',
\r
5163 html: '<p>This is the inner panel content</p>',
\r
5169 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
\r
5171 monitorResize:true,
\r
5175 getLayoutTargetSize : function() {
\r
5176 var target = this.container.getLayoutTarget();
\r
5180 // Style Sized (scrollbars not included)
\r
5181 return target.getStyleSize();
\r
5185 onLayout : function(ct, target){
\r
5186 Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
\r
5187 if(!ct.collapsed){
\r
5188 this.setItemSize(this.activeItem || ct.items.itemAt(0), this.getLayoutTargetSize());
\r
5193 setItemSize : function(item, size){
\r
5194 if(item && size.height > 0){ // display none?
\r
5195 item.setSize(size);
\r
5199 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;/**
\r
5200 * @class Ext.layout.CardLayout
\r
5201 * @extends Ext.layout.FitLayout
\r
5202 * <p>This layout manages multiple child Components, each fitted to the Container, where only a single child Component can be
\r
5203 * visible at any given time. This layout style is most commonly used for wizards, tab implementations, etc.
\r
5204 * This class is intended to be extended or created via the layout:'card' {@link Ext.Container#layout} config,
\r
5205 * and should generally not need to be created directly via the new keyword.</p>
\r
5206 * <p>The CardLayout's focal method is {@link #setActiveItem}. Since only one panel is displayed at a time,
\r
5207 * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of
\r
5208 * the next panel to display. The layout itself does not provide a user interface for handling this navigation,
\r
5209 * so that functionality must be provided by the developer.</p>
\r
5210 * <p>In the following example, a simplistic wizard setup is demonstrated. A button bar is added
\r
5211 * to the footer of the containing panel to provide navigation buttons. The buttons will be handled by a
\r
5212 * common navigation routine -- for this example, the implementation of that routine has been ommitted since
\r
5213 * it can be any type of custom logic. Note that other uses of a CardLayout (like a tab control) would require a
\r
5214 * completely different implementation. For serious implementations, a better approach would be to extend
\r
5215 * CardLayout to provide the custom functionality needed. Example usage:</p>
\r
5217 var navHandler = function(direction){
\r
5218 // This routine could contain business logic required to manage the navigation steps.
\r
5219 // It would call setActiveItem as needed, manage navigation button state, handle any
\r
5220 // branching logic that might be required, handle alternate actions like cancellation
\r
5221 // or finalization, etc. A complete wizard implementation could get pretty
\r
5222 // sophisticated depending on the complexity required, and should probably be
\r
5223 // done as a subclass of CardLayout in a real-world implementation.
\r
5226 var card = new Ext.Panel({
\r
5227 title: 'Example Wizard',
\r
5229 activeItem: 0, // make sure the active item is set on the container config!
\r
5230 bodyStyle: 'padding:15px',
\r
5232 // applied to each contained panel
\r
5235 // just an example of one possible navigation scheme, using buttons
\r
5240 handler: navHandler.createDelegate(this, [-1]),
\r
5243 '->', // greedy spacer so that the buttons are aligned to each side
\r
5247 handler: navHandler.createDelegate(this, [1])
\r
5250 // the panels (or "cards") within the layout
\r
5253 html: '<h1>Welcome to the Wizard!</h1><p>Step 1 of 3</p>'
\r
5256 html: '<p>Step 2 of 3</p>'
\r
5259 html: '<h1>Congratulations!</h1><p>Step 3 of 3 - Complete</p>'
\r
5264 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
\r
5266 * @cfg {Boolean} deferredRender
\r
5267 * True to render each contained item at the time it becomes active, false to render all contained items
\r
5268 * as soon as the layout is rendered (defaults to false). If there is a significant amount of content or
\r
5269 * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to
\r
5270 * true might improve performance.
\r
5272 deferredRender : false,
\r
5275 * @cfg {Boolean} layoutOnCardChange
\r
5276 * True to force a layout of the active item when the active card is changed. Defaults to false.
\r
5278 layoutOnCardChange : false,
\r
5281 * @cfg {Boolean} renderHidden @hide
\r
5284 renderHidden : true,
\r
5288 constructor: function(config){
\r
5289 Ext.layout.CardLayout.superclass.constructor.call(this, config);
\r
5293 * Sets the active (visible) item in the layout.
\r
5294 * @param {String/Number} item The string component id or numeric index of the item to activate
\r
5296 setActiveItem : function(item){
\r
5297 var ai = this.activeItem,
\r
5298 ct = this.container;
\r
5299 item = ct.getComponent(item);
\r
5301 // Is this a valid, different card?
\r
5302 if(item && ai != item){
\r
5304 // Changing cards, hide the current one
\r
5307 if (ai.hidden !== true) {
\r
5310 ai.fireEvent('deactivate', ai);
\r
5312 // Change activeItem reference
\r
5313 this.activeItem = item;
\r
5315 // The container is about to get a recursive layout, remove any deferLayout reference
\r
5316 // because it will trigger a redundant layout.
\r
5317 delete item.deferLayout;
\r
5319 // Show the new component
\r
5324 if(item.doLayout){
\r
5327 item.fireEvent('activate', item);
\r
5332 renderAll : function(ct, target){
\r
5333 if(this.deferredRender){
\r
5334 this.renderItem(this.activeItem, undefined, target);
\r
5336 Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
\r
5340 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;/**
5341 * @class Ext.layout.AnchorLayout
5342 * @extends Ext.layout.ContainerLayout
5343 * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.
5344 * If the container is resized, all anchored items are automatically rerendered according to their
5345 * <b><tt>{@link #anchor}</tt></b> rules.</p>
5346 * <p>This class is intended to be extended or created via the layout:'anchor' {@link Ext.Container#layout}
5347 * config, and should generally not need to be created directly via the new keyword.</p>
5348 * <p>AnchorLayout does not have any direct config options (other than inherited ones). By default,
5349 * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the
5350 * container using the AnchorLayout can supply an anchoring-specific config property of <b>anchorSize</b>.
5351 * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating
5352 * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring
5353 * logic if necessary. For example:</p>
5355 var viewport = new Ext.Viewport({
5357 anchorSize: {width:800, height:600},
5377 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
5379 * @cfg {String} anchor
5380 * <p>This configuation option is to be applied to <b>child <tt>items</tt></b> of a container managed by
5381 * this layout (ie. configured with <tt>layout:'anchor'</tt>).</p><br/>
5383 * <p>This value is what tells the layout how an item should be anchored to the container. <tt>items</tt>
5384 * added to an AnchorLayout accept an anchoring-specific config property of <b>anchor</b> which is a string
5385 * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').
5386 * The following types of anchor values are supported:<div class="mdetail-params"><ul>
5388 * <li><b>Percentage</b> : Any value between 1 and 100, expressed as a percentage.<div class="sub-desc">
5389 * The first anchor is the percentage width that the item should take up within the container, and the
5390 * second is the percentage height. For example:<pre><code>
5391 // two values specified
5392 anchor: '100% 50%' // render item complete width of the container and
5393 // 1/2 height of the container
5394 // one value specified
5395 anchor: '100%' // the width value; the height will default to auto
5396 * </code></pre></div></li>
5398 * <li><b>Offsets</b> : Any positive or negative integer value.<div class="sub-desc">
5399 * This is a raw adjustment where the first anchor is the offset from the right edge of the container,
5400 * and the second is the offset from the bottom edge. For example:<pre><code>
5401 // two values specified
5402 anchor: '-50 -100' // render item the complete width of the container
5403 // minus 50 pixels and
5404 // the complete height minus 100 pixels.
5405 // one value specified
5406 anchor: '-50' // anchor value is assumed to be the right offset value
5407 // bottom offset will default to 0
5408 * </code></pre></div></li>
5410 * <li><b>Sides</b> : Valid values are <tt>'right'</tt> (or <tt>'r'</tt>) and <tt>'bottom'</tt>
5411 * (or <tt>'b'</tt>).<div class="sub-desc">
5412 * Either the container must have a fixed size or an anchorSize config value defined at render time in
5413 * order for these to have any effect.</div></li>
5415 * <li><b>Mixed</b> : <div class="sub-desc">
5416 * Anchor values can also be mixed as needed. For example, to render the width offset from the container
5417 * right edge by 50 pixels and 75% of the container's height use:
5420 * </code></pre></div></li>
5430 getLayoutTargetSize : function() {
5431 var target = this.container.getLayoutTarget();
5435 // Style Sized (scrollbars not included)
5436 return target.getStyleSize();
5440 onLayout : function(ct, target){
5441 Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
5442 var size = this.getLayoutTargetSize();
5444 var w = size.width, h = size.height;
5446 if(w < 20 && h < 20){
5450 // find the container anchoring size
5453 if(typeof ct.anchorSize == 'number'){
5456 aw = ct.anchorSize.width;
5457 ah = ct.anchorSize.height;
5460 aw = ct.initialConfig.width;
5461 ah = ct.initialConfig.height;
5464 var cs = this.getRenderedItems(ct), len = cs.length, i, c, a, cw, ch, el, vs;
5465 for(i = 0; i < len; i++){
5467 el = c.getPositionEl();
5470 if(!a){ // cache all anchor values
5471 vs = c.anchor.split(' ');
5472 c.anchorSpec = a = {
5473 right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
5474 bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
5477 cw = a.right ? this.adjustWidthAnchor(a.right(w) - el.getMargins('lr'), c) : undefined;
5478 ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h) - el.getMargins('tb'), c) : undefined;
5481 c.setSize(cw || undefined, ch || undefined);
5488 parseAnchor : function(a, start, cstart){
5489 if(a && a != 'none'){
5491 if(/^(r|right|b|bottom)$/i.test(a)){ // standard anchor
5492 var diff = cstart - start;
5499 }else if(a.indexOf('%') != -1){
5500 var ratio = parseFloat(a.replace('%', ''))*.01; // percentage
5504 return Math.floor(v*ratio);
5508 a = parseInt(a, 10);
5509 if(!isNaN(a)){ // simple offset adjustment
5523 adjustWidthAnchor : function(value, comp){
5528 adjustHeightAnchor : function(value, comp){
5533 * @property activeItem
5537 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
5539 * @class Ext.layout.ColumnLayout
\r
5540 * @extends Ext.layout.ContainerLayout
\r
5541 * <p>This is the layout style of choice for creating structural layouts in a multi-column format where the width of
\r
5542 * each column can be specified as a percentage or fixed width, but the height is allowed to vary based on the content.
\r
5543 * This class is intended to be extended or created via the layout:'column' {@link Ext.Container#layout} config,
\r
5544 * and should generally not need to be created directly via the new keyword.</p>
\r
5545 * <p>ColumnLayout does not have any direct config options (other than inherited ones), but it does support a
\r
5546 * specific config property of <b><tt>columnWidth</tt></b> that can be included in the config of any panel added to it. The
\r
5547 * layout will use the columnWidth (if present) or width of each panel during layout to determine how to size each panel.
\r
5548 * If width or columnWidth is not specified for a given panel, its width will default to the panel's width (or auto).</p>
\r
5549 * <p>The width property is always evaluated as pixels, and must be a number greater than or equal to 1.
\r
5550 * The columnWidth property is always evaluated as a percentage, and must be a decimal value greater than 0 and
\r
5551 * less than 1 (e.g., .25).</p>
\r
5552 * <p>The basic rules for specifying column widths are pretty simple. The logic makes two passes through the
\r
5553 * set of contained panels. During the first layout pass, all panels that either have a fixed width or none
\r
5554 * specified (auto) are skipped, but their widths are subtracted from the overall container width. During the second
\r
5555 * pass, all panels with columnWidths are assigned pixel widths in proportion to their percentages based on
\r
5556 * the total <b>remaining</b> container width. In other words, percentage width panels are designed to fill the space
\r
5557 * left over by all the fixed-width and/or auto-width panels. Because of this, while you can specify any number of columns
\r
5558 * with different percentages, the columnWidths must always add up to 1 (or 100%) when added together, otherwise your
\r
5559 * layout may not render as expected. Example usage:</p>
\r
5561 // All columns are percentages -- they must add up to 1
\r
5562 var p = new Ext.Panel({
\r
5563 title: 'Column Layout - Percentage Only',
\r
5566 title: 'Column 1',
\r
5569 title: 'Column 2',
\r
5572 title: 'Column 3',
\r
5577 // Mix of width and columnWidth -- all columnWidth values must add up
\r
5578 // to 1. The first column will take up exactly 120px, and the last two
\r
5579 // columns will fill the remaining container width.
\r
5580 var p = new Ext.Panel({
\r
5581 title: 'Column Layout - Mixed',
\r
5584 title: 'Column 1',
\r
5587 title: 'Column 2',
\r
5590 title: 'Column 3',
\r
5596 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
\r
5598 monitorResize:true,
\r
5602 extraCls: 'x-column',
\r
5608 targetCls: 'x-column-layout-ct',
\r
5610 isValidParent : function(c, target){
\r
5611 return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
\r
5614 getLayoutTargetSize : function() {
\r
5615 var target = this.container.getLayoutTarget(), ret;
\r
5617 ret = target.getViewSize();
\r
5618 ret.width -= target.getPadding('lr');
\r
5619 ret.height -= target.getPadding('tb');
\r
5624 renderAll : function(ct, target) {
\r
5625 if(!this.innerCt){
\r
5626 // the innerCt prevents wrapping and shuffling while
\r
5627 // the container is resizing
\r
5628 this.innerCt = target.createChild({cls:'x-column-inner'});
\r
5629 this.innerCt.createChild({cls:'x-clear'});
\r
5631 Ext.layout.ColumnLayout.superclass.renderAll.call(this, ct, this.innerCt);
\r
5635 onLayout : function(ct, target){
\r
5636 var cs = ct.items.items, len = cs.length, c, i;
\r
5638 this.renderAll(ct, target);
\r
5640 var size = this.getLayoutTargetSize();
\r
5642 if(size.width < 1 && size.height < 1){ // display none?
\r
5646 var w = size.width - this.scrollOffset,
\r
5650 this.innerCt.setWidth(w);
\r
5652 // some columns can be percentages while others are fixed
\r
5653 // so we need to make 2 passes
\r
5655 for(i = 0; i < len; i++){
\r
5657 if(!c.columnWidth){
\r
5658 pw -= (c.getWidth() + c.getPositionEl().getMargins('lr'));
\r
5662 pw = pw < 0 ? 0 : pw;
\r
5664 for(i = 0; i < len; i++){
\r
5666 if(c.columnWidth){
\r
5667 c.setSize(Math.floor(c.columnWidth * pw) - c.getPositionEl().getMargins('lr'));
\r
5671 // Browsers differ as to when they account for scrollbars. We need to re-measure to see if the scrollbar
\r
5672 // spaces were accounted for properly. If not, re-layout.
\r
5674 if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
\r
5675 var ts = this.getLayoutTargetSize();
\r
5676 if (ts.width != size.width){
\r
5677 this.adjustmentPass = true;
\r
5678 this.onLayout(ct, target);
\r
5682 delete this.adjustmentPass;
\r
5686 * @property activeItem
\r
5691 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;/**
5692 * @class Ext.layout.BorderLayout
5693 * @extends Ext.layout.ContainerLayout
5694 * <p>This is a multi-pane, application-oriented UI layout style that supports multiple
5695 * nested panels, automatic {@link Ext.layout.BorderLayout.Region#split split} bars between
5696 * {@link Ext.layout.BorderLayout.Region#BorderLayout.Region regions} and built-in
5697 * {@link Ext.layout.BorderLayout.Region#collapsible expanding and collapsing} of regions.</p>
5698 * <p>This class is intended to be extended or created via the <tt>layout:'border'</tt>
5699 * {@link Ext.Container#layout} config, and should generally not need to be created directly
5700 * via the new keyword.</p>
5701 * <p>BorderLayout does not have any direct config options (other than inherited ones).
5702 * All configuration options available for customizing the BorderLayout are at the
5703 * {@link Ext.layout.BorderLayout.Region} and {@link Ext.layout.BorderLayout.SplitRegion}
5705 * <p>Example usage:</p>
5707 var myBorderPanel = new Ext.Panel({
5708 {@link Ext.Component#renderTo renderTo}: document.body,
5709 {@link Ext.BoxComponent#width width}: 700,
5710 {@link Ext.BoxComponent#height height}: 500,
5711 {@link Ext.Panel#title title}: 'Border Layout',
5712 {@link Ext.Container#layout layout}: 'border',
5713 {@link Ext.Container#items items}: [{
5714 {@link Ext.Panel#title title}: 'South Region is resizable',
5715 {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south', // position for region
5716 {@link Ext.BoxComponent#height height}: 100,
5717 {@link Ext.layout.BorderLayout.Region#split split}: true, // enable resizing
5718 {@link Ext.SplitBar#minSize minSize}: 75, // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50}
5719 {@link Ext.SplitBar#maxSize maxSize}: 150,
5720 {@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5'
5722 // xtype: 'panel' implied by default
5723 {@link Ext.Panel#title title}: 'West Region is collapsible',
5724 {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}:'west',
5725 {@link Ext.layout.BorderLayout.Region#margins margins}: '5 0 0 5',
5726 {@link Ext.BoxComponent#width width}: 200,
5727 {@link Ext.layout.BorderLayout.Region#collapsible collapsible}: true, // make collapsible
5728 {@link Ext.layout.BorderLayout.Region#cmargins cmargins}: '5 5 0 5', // adjust top margin when collapsed
5729 {@link Ext.Component#id id}: 'west-region-container',
5730 {@link Ext.Container#layout layout}: 'fit',
5731 {@link Ext.Panel#unstyled unstyled}: true
5733 {@link Ext.Panel#title title}: 'Center Region',
5734 {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'center', // center region is required, no width/height specified
5735 {@link Ext.Component#xtype xtype}: 'container',
5736 {@link Ext.Container#layout layout}: 'fit',
5737 {@link Ext.layout.BorderLayout.Region#margins margins}: '5 5 0 0'
5741 * <p><b><u>Notes</u></b>:</p><div class="mdetail-params"><ul>
5742 * <li>Any container using the BorderLayout <b>must</b> have a child item with <tt>region:'center'</tt>.
5743 * The child item in the center region will always be resized to fill the remaining space not used by
5744 * the other regions in the layout.</li>
5745 * <li>Any child items with a region of <tt>west</tt> or <tt>east</tt> must have <tt>width</tt> defined
5746 * (an integer representing the number of pixels that the region should take up).</li>
5747 * <li>Any child items with a region of <tt>north</tt> or <tt>south</tt> must have <tt>height</tt> defined.</li>
5748 * <li>The regions of a BorderLayout are <b>fixed at render time</b> and thereafter, its child Components may not be removed or added</b>. To add/remove
5749 * Components within a BorderLayout, have them wrapped by an additional Container which is directly
5750 * managed by the BorderLayout. If the region is to be collapsible, the Container used directly
5751 * by the BorderLayout manager should be a Panel. In the following example a Container (an Ext.Panel)
5752 * is added to the west region:
5753 * <div style="margin-left:16px"><pre><code>
5754 wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container');
5755 wrc.{@link Ext.Panel#removeAll removeAll}();
5756 wrc.{@link Ext.Container#add add}({
5757 title: 'Added Panel',
5758 html: 'Some content'
5760 wrc.{@link Ext.Container#doLayout doLayout}();
5761 * </code></pre></div>
5763 * <li> To reference a {@link Ext.layout.BorderLayout.Region Region}:
5764 * <div style="margin-left:16px"><pre><code>
5765 wr = myBorderPanel.layout.west;
5766 * </code></pre></div>
5770 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
5778 targetCls: 'x-border-layout-ct',
5780 getLayoutTargetSize : function() {
5781 var target = this.container.getLayoutTarget();
5782 return target ? target.getViewSize() : {};
5786 onLayout : function(ct, target){
5787 var collapsed, i, c, pos, items = ct.items.items, len = items.length;
5790 for(i = 0; i < len; i++) {
5796 c.collapsed = false;
5798 c.render(target, i);
5799 c.getPositionEl().addClass('x-border-panel');
5801 this[pos] = pos != 'center' && c.split ?
5802 new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
5803 new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
5804 this[pos].render(target, c);
5806 this.rendered = true;
5809 var size = this.getLayoutTargetSize();
5810 if(size.width < 20 || size.height < 20){ // display none?
5812 this.restoreCollapsed = collapsed;
5815 }else if(this.restoreCollapsed){
5816 collapsed = this.restoreCollapsed;
5817 delete this.restoreCollapsed;
5820 var w = size.width, h = size.height,
5821 centerW = w, centerH = h, centerY = 0, centerX = 0,
5822 n = this.north, s = this.south, west = this.west, e = this.east, c = this.center,
5823 b, m, totalWidth, totalHeight;
5824 if(!c && Ext.layout.BorderLayout.WARN !== false){
5825 throw 'No center region defined in BorderLayout ' + ct.id;
5828 if(n && n.isVisible()){
5831 b.width = w - (m.left+m.right);
5834 centerY = b.height + b.y + m.bottom;
5838 if(s && s.isVisible()){
5841 b.width = w - (m.left+m.right);
5843 totalHeight = (b.height + m.top + m.bottom);
5844 b.y = h - totalHeight + m.top;
5845 centerH -= totalHeight;
5848 if(west && west.isVisible()){
5850 m = west.getMargins();
5851 b.height = centerH - (m.top+m.bottom);
5853 b.y = centerY + m.top;
5854 totalWidth = (b.width + m.left + m.right);
5855 centerX += totalWidth;
5856 centerW -= totalWidth;
5857 west.applyLayout(b);
5859 if(e && e.isVisible()){
5862 b.height = centerH - (m.top+m.bottom);
5863 totalWidth = (b.width + m.left + m.right);
5864 b.x = w - totalWidth + m.left;
5865 b.y = centerY + m.top;
5866 centerW -= totalWidth;
5872 x: centerX + m.left,
5874 width: centerW - (m.left+m.right),
5875 height: centerH - (m.top+m.bottom)
5877 c.applyLayout(centerBox);
5880 for(i = 0, len = collapsed.length; i < len; i++){
5881 collapsed[i].collapse(false);
5884 if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue
5887 // Putting a border layout into an overflowed container is NOT correct and will make a second layout pass necessary.
5888 if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
5889 var ts = this.getLayoutTargetSize();
5890 if (ts.width != size.width || ts.height != size.height){
5891 this.adjustmentPass = true;
5892 this.onLayout(ct, target);
5895 delete this.adjustmentPass;
5898 destroy: function() {
5899 var r = ['north', 'south', 'east', 'west'], i, region;
5900 for (i = 0; i < r.length; i++) {
5901 region = this[r[i]];
5905 }else if (region.split){
5906 region.split.destroy(true);
5910 Ext.layout.BorderLayout.superclass.destroy.call(this);
5914 * @property activeItem
5920 * @class Ext.layout.BorderLayout.Region
5921 * <p>This is a region of a {@link Ext.layout.BorderLayout BorderLayout} that acts as a subcontainer
5922 * within the layout. Each region has its own {@link Ext.layout.ContainerLayout layout} that is
5923 * independent of other regions and the containing BorderLayout, and can be any of the
5924 * {@link Ext.layout.ContainerLayout valid Ext layout types}.</p>
5925 * <p>Region size is managed automatically and cannot be changed by the user -- for
5926 * {@link #split resizable regions}, see {@link Ext.layout.BorderLayout.SplitRegion}.</p>
5928 * Create a new Region.
5929 * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
5930 * @param {Object} config The configuration options
5931 * @param {String} position The region position. Valid values are: <tt>north</tt>, <tt>south</tt>,
5932 * <tt>east</tt>, <tt>west</tt> and <tt>center</tt>. Every {@link Ext.layout.BorderLayout BorderLayout}
5933 * <b>must have a center region</b> for the primary content -- all other regions are optional.
5935 Ext.layout.BorderLayout.Region = function(layout, config, pos){
5936 Ext.apply(this, config);
5937 this.layout = layout;
5938 this.position = pos;
5940 if(typeof this.margins == 'string'){
5941 this.margins = this.layout.parseMargins(this.margins);
5943 this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
5944 if(this.collapsible){
5945 if(typeof this.cmargins == 'string'){
5946 this.cmargins = this.layout.parseMargins(this.cmargins);
5948 if(this.collapseMode == 'mini' && !this.cmargins){
5949 this.cmargins = {left:0,top:0,right:0,bottom:0};
5951 this.cmargins = Ext.applyIf(this.cmargins || {},
5952 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
5957 Ext.layout.BorderLayout.Region.prototype = {
5959 * @cfg {Boolean} animFloat
5960 * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
5961 * panel that will close again once the user mouses out of that panel (or clicks out if
5962 * <tt>{@link #autoHide} = false</tt>). Setting <tt>{@link #animFloat} = false</tt> will
5963 * prevent the open and close of these floated panels from being animated (defaults to <tt>true</tt>).
5966 * @cfg {Boolean} autoHide
5967 * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
5968 * panel. If <tt>autoHide = true</tt>, the panel will automatically hide after the user mouses
5969 * out of the panel. If <tt>autoHide = false</tt>, the panel will continue to display until the
5970 * user clicks outside of the panel (defaults to <tt>true</tt>).
5973 * @cfg {String} collapseMode
5974 * <tt>collapseMode</tt> supports two configuration values:<div class="mdetail-params"><ul>
5975 * <li><b><tt>undefined</tt></b> (default)<div class="sub-desc">By default, {@link #collapsible}
5976 * regions are collapsed by clicking the expand/collapse tool button that renders into the region's
5977 * title bar.</div></li>
5978 * <li><b><tt>'mini'</tt></b><div class="sub-desc">Optionally, when <tt>collapseMode</tt> is set to
5979 * <tt>'mini'</tt> the region's split bar will also display a small collapse button in the center of
5980 * the bar. In <tt>'mini'</tt> mode the region will collapse to a thinner bar than in normal mode.
5983 * <p><b>Note</b>: if a collapsible region does not have a title bar, then set <tt>collapseMode =
5984 * 'mini'</tt> and <tt>{@link #split} = true</tt> in order for the region to be {@link #collapsible}
5985 * by the user as the expand/collapse tool button (that would go in the title bar) will not be rendered.</p>
5986 * <p>See also <tt>{@link #cmargins}</tt>.</p>
5989 * @cfg {Object} margins
5990 * An object containing margins to apply to the region when in the expanded state in the
5991 * format:<pre><code>
5994 right: (right margin),
5995 bottom: (bottom margin),
5998 * <p>May also be a string containing space-separated, numeric margin values. The order of the
5999 * sides associated with each value matches the way CSS processes margin values:</p>
6000 * <p><div class="mdetail-params"><ul>
6001 * <li>If there is only one value, it applies to all sides.</li>
6002 * <li>If there are two values, the top and bottom borders are set to the first value and the
6003 * right and left are set to the second.</li>
6004 * <li>If there are three values, the top is set to the first value, the left and right are set
6005 * to the second, and the bottom is set to the third.</li>
6006 * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
6008 * <p>Defaults to:</p><pre><code>
6009 * {top:0, right:0, bottom:0, left:0}
6013 * @cfg {Object} cmargins
6014 * An object containing margins to apply to the region when in the collapsed state in the
6015 * format:<pre><code>
6018 right: (right margin),
6019 bottom: (bottom margin),
6022 * <p>May also be a string containing space-separated, numeric margin values. The order of the
6023 * sides associated with each value matches the way CSS processes margin values.</p>
6025 * <li>If there is only one value, it applies to all sides.</li>
6026 * <li>If there are two values, the top and bottom borders are set to the first value and the
6027 * right and left are set to the second.</li>
6028 * <li>If there are three values, the top is set to the first value, the left and right are set
6029 * to the second, and the bottom is set to the third.</li>
6030 * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
6034 * @cfg {Boolean} collapsible
6035 * <p><tt>true</tt> to allow the user to collapse this region (defaults to <tt>false</tt>). If
6036 * <tt>true</tt>, an expand/collapse tool button will automatically be rendered into the title
6037 * bar of the region, otherwise the button will not be shown.</p>
6038 * <p><b>Note</b>: that a title bar is required to display the collapse/expand toggle button -- if
6039 * no <tt>title</tt> is specified for the region's panel, the region will only be collapsible if
6040 * <tt>{@link #collapseMode} = 'mini'</tt> and <tt>{@link #split} = true</tt>.
6042 collapsible : false,
6044 * @cfg {Boolean} split
6045 * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and
6046 * display a 5px wide {@link Ext.SplitBar} between this region and its neighbor, allowing the user to
6047 * resize the regions dynamically. Defaults to <tt>false</tt> creating a
6048 * {@link Ext.layout.BorderLayout.Region Region}.</p><br>
6049 * <p><b>Notes</b>:</p><div class="mdetail-params"><ul>
6050 * <li>this configuration option is ignored if <tt>region='center'</tt></li>
6051 * <li>when <tt>split == true</tt>, it is common to specify a
6052 * <tt>{@link Ext.SplitBar#minSize minSize}</tt> and <tt>{@link Ext.SplitBar#maxSize maxSize}</tt>
6053 * for the {@link Ext.BoxComponent BoxComponent} representing the region. These are not native
6054 * configs of {@link Ext.BoxComponent BoxComponent}, and are used only by this class.</li>
6055 * <li>if <tt>{@link #collapseMode} = 'mini'</tt> requires <tt>split = true</tt> to reserve space
6056 * for the collapse tool</tt></li>
6061 * @cfg {Boolean} floatable
6062 * <tt>true</tt> to allow clicking a collapsed region's bar to display the region's panel floated
6063 * above the layout, <tt>false</tt> to force the user to fully expand a collapsed region by
6064 * clicking the expand button to see it again (defaults to <tt>true</tt>).
6068 * @cfg {Number} minWidth
6069 * <p>The minimum allowable width in pixels for this region (defaults to <tt>50</tt>).
6070 * <tt>maxWidth</tt> may also be specified.</p><br>
6071 * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
6072 * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
6073 * <tt>minWidth</tt> / <tt>maxWidth</tt>.</p>
6077 * @cfg {Number} minHeight
6078 * The minimum allowable height in pixels for this region (defaults to <tt>50</tt>)
6079 * <tt>maxHeight</tt> may also be specified.</p><br>
6080 * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
6081 * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
6082 * <tt>minHeight</tt> / <tt>maxHeight</tt>.</p>
6087 defaultMargins : {left:0,top:0,right:0,bottom:0},
6089 defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
6091 defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
6092 floatingZIndex: 100,
6095 * True if this region is collapsed. Read-only.
6099 isCollapsed : false,
6102 * This region's panel. Read-only.
6107 * This region's layout. Read-only.
6112 * This region's layout position (north, south, east, west or center). Read-only.
6114 * @property position
6118 render : function(ct, p){
6120 p.el.enableDisplayMode();
6124 var gs = p.getState, ps = this.position;
6125 p.getState = function(){
6126 return Ext.apply(gs.call(p) || {}, this.state);
6127 }.createDelegate(this);
6130 p.allowQueuedExpand = false;
6132 beforecollapse: this.beforeCollapse,
6133 collapse: this.onCollapse,
6134 beforeexpand: this.beforeExpand,
6135 expand: this.onExpand,
6140 if(this.collapsible || this.floatable){
6141 p.collapseEl = 'el';
6142 p.slideAnchor = this.getSlideAnchor();
6144 if(p.tools && p.tools.toggle){
6145 p.tools.toggle.addClass('x-tool-collapse-'+ps);
6146 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
6152 getCollapsedEl : function(){
6153 if(!this.collapsedEl){
6154 if(!this.toolTemplate){
6155 var tt = new Ext.Template(
6156 '<div class="x-tool x-tool-{id}"> </div>'
6158 tt.disableFormats = true;
6160 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
6162 this.collapsedEl = this.targetEl.createChild({
6163 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
6164 id: this.panel.id + '-xcollapsed'
6166 this.collapsedEl.enableDisplayMode('block');
6168 if(this.collapseMode == 'mini'){
6169 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
6170 this.miniCollapsedEl = this.collapsedEl.createChild({
6171 cls: "x-layout-mini x-layout-mini-"+this.position, html: " "
6173 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
6174 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
6175 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
6177 if(this.collapsible !== false && !this.hideCollapseTool) {
6178 var t = this.toolTemplate.append(
6179 this.collapsedEl.dom,
6180 {id:'expand-'+this.position}, true);
6181 t.addClassOnOver('x-tool-expand-'+this.position+'-over');
6182 t.on('click', this.onExpandClick, this, {stopEvent:true});
6184 if(this.floatable !== false || this.titleCollapse){
6185 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
6186 this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
6190 return this.collapsedEl;
6194 onExpandClick : function(e){
6196 this.panel.expand(false);
6198 this.panel.expand();
6203 onCollapseClick : function(e){
6204 this.panel.collapse();
6208 beforeCollapse : function(p, animate){
6209 this.lastAnim = animate;
6211 this.splitEl.hide();
6213 this.getCollapsedEl().show();
6214 var el = this.panel.getEl();
6215 this.originalZIndex = el.getStyle('z-index');
6216 el.setStyle('z-index', 100);
6217 this.isCollapsed = true;
6218 this.layout.layout();
6222 onCollapse : function(animate){
6223 this.panel.el.setStyle('z-index', 1);
6224 if(this.lastAnim === false || this.panel.animCollapse === false){
6225 this.getCollapsedEl().dom.style.visibility = 'visible';
6227 this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
6229 this.state.collapsed = true;
6230 this.panel.saveState();
6234 beforeExpand : function(animate){
6236 this.afterSlideIn();
6238 var c = this.getCollapsedEl();
6240 if(this.position == 'east' || this.position == 'west'){
6241 this.panel.setSize(undefined, c.getHeight());
6243 this.panel.setSize(c.getWidth(), undefined);
6246 c.dom.style.visibility = 'hidden';
6247 this.panel.el.setStyle('z-index', this.floatingZIndex);
6251 onExpand : function(){
6252 this.isCollapsed = false;
6254 this.splitEl.show();
6256 this.layout.layout();
6257 this.panel.el.setStyle('z-index', this.originalZIndex);
6258 this.state.collapsed = false;
6259 this.panel.saveState();
6263 collapseClick : function(e){
6265 e.stopPropagation();
6268 e.stopPropagation();
6274 onHide : function(){
6275 if(this.isCollapsed){
6276 this.getCollapsedEl().hide();
6277 }else if(this.splitEl){
6278 this.splitEl.hide();
6283 onShow : function(){
6284 if(this.isCollapsed){
6285 this.getCollapsedEl().show();
6286 }else if(this.splitEl){
6287 this.splitEl.show();
6292 * True if this region is currently visible, else false.
6295 isVisible : function(){
6296 return !this.panel.hidden;
6300 * Returns the current margins for this region. If the region is collapsed, the
6301 * {@link #cmargins} (collapsed margins) value will be returned, otherwise the
6302 * {@link #margins} value will be returned.
6303 * @return {Object} An object containing the element's margins: <tt>{left: (left
6304 * margin), top: (top margin), right: (right margin), bottom: (bottom margin)}</tt>
6306 getMargins : function(){
6307 return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
6311 * Returns the current size of this region. If the region is collapsed, the size of the
6312 * collapsedEl will be returned, otherwise the size of the region's panel will be returned.
6313 * @return {Object} An object containing the element's size: <tt>{width: (element width),
6314 * height: (element height)}</tt>
6316 getSize : function(){
6317 return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
6321 * Sets the specified panel as the container element for this region.
6322 * @param {Ext.Panel} panel The new panel
6324 setPanel : function(panel){
6329 * Returns the minimum allowable width for this region.
6330 * @return {Number} The minimum width
6332 getMinWidth: function(){
6333 return this.minWidth;
6337 * Returns the minimum allowable height for this region.
6338 * @return {Number} The minimum height
6340 getMinHeight: function(){
6341 return this.minHeight;
6345 applyLayoutCollapsed : function(box){
6346 var ce = this.getCollapsedEl();
6347 ce.setLeftTop(box.x, box.y);
6348 ce.setSize(box.width, box.height);
6352 applyLayout : function(box){
6353 if(this.isCollapsed){
6354 this.applyLayoutCollapsed(box);
6356 this.panel.setPosition(box.x, box.y);
6357 this.panel.setSize(box.width, box.height);
6362 beforeSlide: function(){
6363 this.panel.beforeEffect();
6367 afterSlide : function(){
6368 this.panel.afterEffect();
6372 initAutoHide : function(){
6373 if(this.autoHide !== false){
6374 if(!this.autoHideHd){
6375 var st = new Ext.util.DelayedTask(this.slideIn, this);
6377 "mouseout": function(e){
6378 if(!e.within(this.el, true)){
6382 "mouseover" : function(e){
6388 this.el.on(this.autoHideHd);
6389 this.collapsedEl.on(this.autoHideHd);
6394 clearAutoHide : function(){
6395 if(this.autoHide !== false){
6396 this.el.un("mouseout", this.autoHideHd.mouseout);
6397 this.el.un("mouseover", this.autoHideHd.mouseover);
6398 this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
6399 this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
6404 clearMonitor : function(){
6405 Ext.getDoc().un("click", this.slideInIf, this);
6409 * If this Region is {@link #floatable}, this method slides this Region into full visibility <i>over the top
6410 * of the center Region</i> where it floats until either {@link #slideIn} is called, or other regions of the layout
6411 * are clicked, or the mouse exits the Region.
6413 slideOut : function(){
6414 if(this.isSlid || this.el.hasActiveFx()){
6418 var ts = this.panel.tools, dh, pc;
6419 if(ts && ts.toggle){
6424 // Temporarily clear the collapsed flag so we can onResize the panel on the slide
6425 pc = this.panel.collapsed;
6426 this.panel.collapsed = false;
6428 if(this.position == 'east' || this.position == 'west'){
6429 // Temporarily clear the deferHeight flag so we can size the height on the slide
6430 dh = this.panel.deferHeight;
6431 this.panel.deferHeight = false;
6433 this.panel.setSize(undefined, this.collapsedEl.getHeight());
6435 // Put the deferHeight flag back after setSize
6436 this.panel.deferHeight = dh;
6438 this.panel.setSize(this.collapsedEl.getWidth(), undefined);
6441 // Put the collapsed flag back after onResize
6442 this.panel.collapsed = pc;
6444 this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
6445 this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
6446 this.el.setStyle("z-index", this.floatingZIndex+2);
6447 this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
6448 if(this.animFloat !== false){
6450 this.el.slideIn(this.getSlideAnchor(), {
6451 callback: function(){
6453 this.initAutoHide();
6454 Ext.getDoc().on("click", this.slideInIf, this);
6460 this.initAutoHide();
6461 Ext.getDoc().on("click", this.slideInIf, this);
6466 afterSlideIn : function(){
6467 this.clearAutoHide();
6468 this.isSlid = false;
6469 this.clearMonitor();
6470 this.el.setStyle("z-index", "");
6471 this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
6472 this.el.dom.style.left = this.restoreLT[0];
6473 this.el.dom.style.top = this.restoreLT[1];
6475 var ts = this.panel.tools;
6476 if(ts && ts.toggle){
6482 * If this Region is {@link #floatable}, and this Region has been slid into floating visibility, then this method slides
6483 * this region back into its collapsed state.
6485 slideIn : function(cb){
6486 if(!this.isSlid || this.el.hasActiveFx()){
6490 this.isSlid = false;
6491 if(this.animFloat !== false){
6493 this.el.slideOut(this.getSlideAnchor(), {
6494 callback: function(){
6497 this.afterSlideIn();
6505 this.afterSlideIn();
6510 slideInIf : function(e){
6511 if(!e.within(this.el)){
6541 getAnchor : function(){
6542 return this.anchors[this.position];
6546 getCollapseAnchor : function(){
6547 return this.canchors[this.position];
6551 getSlideAnchor : function(){
6552 return this.sanchors[this.position];
6556 getAlignAdj : function(){
6557 var cm = this.cmargins;
6558 switch(this.position){
6575 getExpandAdj : function(){
6576 var c = this.collapsedEl, cm = this.cmargins;
6577 switch(this.position){
6579 return [-(cm.right+c.getWidth()+cm.left), 0];
6582 return [cm.right+c.getWidth()+cm.left, 0];
6585 return [0, -(cm.top+cm.bottom+c.getHeight())];
6588 return [0, cm.top+cm.bottom+c.getHeight()];
6593 destroy : function(){
6594 Ext.destroy(this.miniCollapsedEl, this.collapsedEl);
6599 * @class Ext.layout.BorderLayout.SplitRegion
6600 * @extends Ext.layout.BorderLayout.Region
6601 * <p>This is a specialized type of {@link Ext.layout.BorderLayout.Region BorderLayout region} that
6602 * has a built-in {@link Ext.SplitBar} for user resizing of regions. The movement of the split bar
6603 * is configurable to move either {@link #tickSize smooth or incrementally}.</p>
6605 * Create a new SplitRegion.
6606 * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
6607 * @param {Object} config The configuration options
6608 * @param {String} position The region position. Valid values are: north, south, east, west and center. Every
6609 * BorderLayout must have a center region for the primary content -- all other regions are optional.
6611 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
6612 Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
6614 this.applyLayout = this.applyFns[pos];
6617 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
6619 * @cfg {Number} tickSize
6620 * The increment, in pixels by which to move this Region's {@link Ext.SplitBar SplitBar}.
6621 * By default, the {@link Ext.SplitBar SplitBar} moves smoothly.
6624 * @cfg {String} splitTip
6625 * The tooltip to display when the user hovers over a
6626 * {@link Ext.layout.BorderLayout.Region#collapsible non-collapsible} region's split bar
6627 * (defaults to <tt>"Drag to resize."</tt>). Only applies if
6628 * <tt>{@link #useSplitTips} = true</tt>.
6630 splitTip : "Drag to resize.",
6632 * @cfg {String} collapsibleSplitTip
6633 * The tooltip to display when the user hovers over a
6634 * {@link Ext.layout.BorderLayout.Region#collapsible collapsible} region's split bar
6635 * (defaults to "Drag to resize. Double click to hide."). Only applies if
6636 * <tt>{@link #useSplitTips} = true</tt>.
6638 collapsibleSplitTip : "Drag to resize. Double click to hide.",
6640 * @cfg {Boolean} useSplitTips
6641 * <tt>true</tt> to display a tooltip when the user hovers over a region's split bar
6642 * (defaults to <tt>false</tt>). The tooltip text will be the value of either
6643 * <tt>{@link #splitTip}</tt> or <tt>{@link #collapsibleSplitTip}</tt> as appropriate.
6645 useSplitTips : false,
6650 orientation: Ext.SplitBar.VERTICAL,
6651 placement: Ext.SplitBar.TOP,
6652 maxFn : 'getVMaxSize',
6653 minProp: 'minHeight',
6654 maxProp: 'maxHeight'
6657 orientation: Ext.SplitBar.VERTICAL,
6658 placement: Ext.SplitBar.BOTTOM,
6659 maxFn : 'getVMaxSize',
6660 minProp: 'minHeight',
6661 maxProp: 'maxHeight'
6664 orientation: Ext.SplitBar.HORIZONTAL,
6665 placement: Ext.SplitBar.RIGHT,
6666 maxFn : 'getHMaxSize',
6667 minProp: 'minWidth',
6671 orientation: Ext.SplitBar.HORIZONTAL,
6672 placement: Ext.SplitBar.LEFT,
6673 maxFn : 'getHMaxSize',
6674 minProp: 'minWidth',
6681 west : function(box){
6682 if(this.isCollapsed){
6683 return this.applyLayoutCollapsed(box);
6685 var sd = this.splitEl.dom, s = sd.style;
6686 this.panel.setPosition(box.x, box.y);
6687 var sw = sd.offsetWidth;
6688 s.left = (box.x+box.width-sw)+'px';
6689 s.top = (box.y)+'px';
6690 s.height = Math.max(0, box.height)+'px';
6691 this.panel.setSize(box.width-sw, box.height);
6693 east : function(box){
6694 if(this.isCollapsed){
6695 return this.applyLayoutCollapsed(box);
6697 var sd = this.splitEl.dom, s = sd.style;
6698 var sw = sd.offsetWidth;
6699 this.panel.setPosition(box.x+sw, box.y);
6700 s.left = (box.x)+'px';
6701 s.top = (box.y)+'px';
6702 s.height = Math.max(0, box.height)+'px';
6703 this.panel.setSize(box.width-sw, box.height);
6705 north : function(box){
6706 if(this.isCollapsed){
6707 return this.applyLayoutCollapsed(box);
6709 var sd = this.splitEl.dom, s = sd.style;
6710 var sh = sd.offsetHeight;
6711 this.panel.setPosition(box.x, box.y);
6712 s.left = (box.x)+'px';
6713 s.top = (box.y+box.height-sh)+'px';
6714 s.width = Math.max(0, box.width)+'px';
6715 this.panel.setSize(box.width, box.height-sh);
6717 south : function(box){
6718 if(this.isCollapsed){
6719 return this.applyLayoutCollapsed(box);
6721 var sd = this.splitEl.dom, s = sd.style;
6722 var sh = sd.offsetHeight;
6723 this.panel.setPosition(box.x, box.y+sh);
6724 s.left = (box.x)+'px';
6725 s.top = (box.y)+'px';
6726 s.width = Math.max(0, box.width)+'px';
6727 this.panel.setSize(box.width, box.height-sh);
6732 render : function(ct, p){
6733 Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
6735 var ps = this.position;
6737 this.splitEl = ct.createChild({
6738 cls: "x-layout-split x-layout-split-"+ps, html: " ",
6739 id: this.panel.id + '-xsplit'
6742 if(this.collapseMode == 'mini'){
6743 this.miniSplitEl = this.splitEl.createChild({
6744 cls: "x-layout-mini x-layout-mini-"+ps, html: " "
6746 this.miniSplitEl.addClassOnOver('x-layout-mini-over');
6747 this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
6750 var s = this.splitSettings[ps];
6752 this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
6753 this.split.tickSize = this.tickSize;
6754 this.split.placement = s.placement;
6755 this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
6756 this.split.minSize = this.minSize || this[s.minProp];
6757 this.split.on("beforeapply", this.onSplitMove, this);
6758 this.split.useShim = this.useShim === true;
6759 this.maxSize = this.maxSize || this[s.maxProp];
6762 this.splitEl.hide();
6765 if(this.useSplitTips){
6766 this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
6768 if(this.collapsible){
6769 this.splitEl.on("dblclick", this.onCollapseClick, this);
6773 //docs inherit from superclass
6774 getSize : function(){
6775 if(this.isCollapsed){
6776 return this.collapsedEl.getSize();
6778 var s = this.panel.getSize();
6779 if(this.position == 'north' || this.position == 'south'){
6780 s.height += this.splitEl.dom.offsetHeight;
6782 s.width += this.splitEl.dom.offsetWidth;
6788 getHMaxSize : function(){
6789 var cmax = this.maxSize || 10000;
6790 var center = this.layout.center;
6791 return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
6795 getVMaxSize : function(){
6796 var cmax = this.maxSize || 10000;
6797 var center = this.layout.center;
6798 return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
6802 onSplitMove : function(split, newSize){
6803 var s = this.panel.getSize();
6804 this.lastSplitSize = newSize;
6805 if(this.position == 'north' || this.position == 'south'){
6806 this.panel.setSize(s.width, newSize);
6807 this.state.height = newSize;
6809 this.panel.setSize(newSize, s.height);
6810 this.state.width = newSize;
6812 this.layout.layout();
6813 this.panel.saveState();
6818 * Returns a reference to the split bar in use by this region.
6819 * @return {Ext.SplitBar} The split bar
6821 getSplitBar : function(){
6826 destroy : function() {
6827 Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
6828 Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
6832 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;/**
6833 * @class Ext.layout.FormLayout
6834 * @extends Ext.layout.AnchorLayout
6835 * <p>This layout manager is specifically designed for rendering and managing child Components of
6836 * {@link Ext.form.FormPanel forms}. It is responsible for rendering the labels of
6837 * {@link Ext.form.Field Field}s.</p>
6839 * <p>This layout manager is used when a Container is configured with the <tt>layout:'form'</tt>
6840 * {@link Ext.Container#layout layout} config option, and should generally not need to be created directly
6841 * via the new keyword. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
6843 * <p>In an application, it will usually be preferrable to use a {@link Ext.form.FormPanel FormPanel}
6844 * (which is configured with FormLayout as its layout class by default) since it also provides built-in
6845 * functionality for {@link Ext.form.BasicForm#doAction loading, validating and submitting} the form.</p>
6847 * <p>A {@link Ext.Container Container} <i>using</i> the FormLayout layout manager (e.g.
6848 * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) can also accept the following
6849 * layout-specific config properties:<div class="mdetail-params"><ul>
6850 * <li><b><tt>{@link Ext.form.FormPanel#hideLabels hideLabels}</tt></b></li>
6851 * <li><b><tt>{@link Ext.form.FormPanel#labelAlign labelAlign}</tt></b></li>
6852 * <li><b><tt>{@link Ext.form.FormPanel#labelPad labelPad}</tt></b></li>
6853 * <li><b><tt>{@link Ext.form.FormPanel#labelSeparator labelSeparator}</tt></b></li>
6854 * <li><b><tt>{@link Ext.form.FormPanel#labelWidth labelWidth}</tt></b></li>
6857 * <p>Any Component (including Fields) managed by FormLayout accepts the following as a config option:
6858 * <div class="mdetail-params"><ul>
6859 * <li><b><tt>{@link Ext.Component#anchor anchor}</tt></b></li>
6862 * <p>Any Component managed by FormLayout may be rendered as a form field (with an associated label) by
6863 * configuring it with a non-null <b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b>. Components configured
6864 * in this way may be configured with the following options which affect the way the FormLayout renders them:
6865 * <div class="mdetail-params"><ul>
6866 * <li><b><tt>{@link Ext.Component#clearCls clearCls}</tt></b></li>
6867 * <li><b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b></li>
6868 * <li><b><tt>{@link Ext.Component#hideLabel hideLabel}</tt></b></li>
6869 * <li><b><tt>{@link Ext.Component#itemCls itemCls}</tt></b></li>
6870 * <li><b><tt>{@link Ext.Component#labelSeparator labelSeparator}</tt></b></li>
6871 * <li><b><tt>{@link Ext.Component#labelStyle labelStyle}</tt></b></li>
6874 * <p>Example usage:</p>
6876 // Required if showing validation messages
6877 Ext.QuickTips.init();
6879 // While you can create a basic Panel with layout:'form', practically
6880 // you should usually use a FormPanel to also get its form functionality
6881 // since it already creates a FormLayout internally.
6882 var form = new Ext.form.FormPanel({
6883 title: 'Form Layout',
6884 bodyStyle: 'padding:15px',
6886 defaultType: 'textfield',
6888 // applied to each contained item
6893 fieldLabel: 'First Name',
6896 {@link Ext.Component#labelSeparator labelSeparator}: ':' // override labelSeparator layout config
6898 fieldLabel: 'Last Name',
6901 fieldLabel: 'Email',
6906 hideLabel: true, // override hideLabels layout config
6916 {@link #labelSeparator}: '~' // superseded by assignment below
6918 // config options applicable to container when layout='form':
6920 labelAlign: 'left', // or 'right' or 'top'
6921 {@link Ext.form.FormPanel#labelSeparator labelSeparator}: '>>', // takes precedence over layoutConfig value
6922 labelWidth: 65, // defaults to 100
6923 labelPad: 8 // defaults to 5, must specify labelWidth to be honored
6927 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
6930 * @cfg {String} labelSeparator
6931 * See {@link Ext.form.FormPanel}.{@link Ext.form.FormPanel#labelSeparator labelSeparator}. Configuration
6932 * of this property at the <b>container</b> level takes precedence.
6934 labelSeparator : ':',
6937 * Read only. The CSS style specification string added to field labels in this layout if not
6938 * otherwise {@link Ext.Component#labelStyle specified by each contained field}.
6940 * @property labelStyle
6944 * @cfg {Boolean} trackLabels
6945 * True to show/hide the field label when the field is hidden. Defaults to <tt>false</tt>.
6952 onRemove: function(c){
6953 Ext.layout.FormLayout.superclass.onRemove.call(this, c);
6954 if(this.trackLabels){
6955 c.un('show', this.onFieldShow, this);
6956 c.un('hide', this.onFieldHide, this);
6958 // check for itemCt, since we may be removing a fieldset or something similar
6959 var el = c.getPositionEl(),
6960 ct = c.getItemCt && c.getItemCt();
6961 if(c.rendered && ct){
6966 Ext.destroyMembers(c, 'label', 'itemCt');
6968 Ext.destroyMembers(c, 'getItemCt', 'customItemCt');
6974 setContainer : function(ct){
6975 Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
6977 ct.addClass('x-form-label-'+ct.labelAlign);
6982 labelStyle: 'display:none',
6983 elementStyle: 'padding-left:0;',
6987 this.labelSeparator = ct.labelSeparator || this.labelSeparator;
6988 ct.labelWidth = ct.labelWidth || 100;
6989 if(Ext.isNumber(ct.labelWidth)){
6990 var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5;
6992 labelAdjust: ct.labelWidth + pad,
6993 labelStyle: 'width:' + ct.labelWidth + 'px;',
6994 elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px'
6997 if(ct.labelAlign == 'top'){
6999 labelStyle: 'width:auto;',
7001 elementStyle: 'padding-left:0;'
7008 isHide: function(c){
7009 return c.hideLabel || this.container.hideLabels;
7012 onFieldShow: function(c){
7013 c.getItemCt().removeClass('x-hide-' + c.hideMode);
7016 onFieldHide: function(c){
7017 c.getItemCt().addClass('x-hide-' + c.hideMode);
7021 getLabelStyle: function(s){
7022 var ls = '', items = [this.labelStyle, s];
7023 for (var i = 0, len = items.length; i < len; ++i){
7026 if (ls.substr(-1, 1) != ';'){
7035 * @cfg {Ext.Template} fieldTpl
7036 * A {@link Ext.Template#compile compile}d {@link Ext.Template} for rendering
7037 * the fully wrapped, labeled and styled form Field. Defaults to:</p><pre><code>
7039 '<div class="x-form-item {itemCls}" tabIndex="-1">',
7040 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
7041 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
7042 '</div><div class="{clearCls}"></div>',
7046 * <p>This may be specified to produce a different DOM structure when rendering form Fields.</p>
7047 * <p>A description of the properties within the template follows:</p><div class="mdetail-params"><ul>
7048 * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
7049 * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
7050 * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
7051 * supplied at the container level.</div></li>
7052 * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
7053 * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
7054 * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
7055 * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
7056 * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
7057 * field (defaults to <tt>''</tt>)</div></li>
7058 * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
7059 * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
7060 * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
7061 * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
7062 * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
7063 * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
7065 * <p>Also see <tt>{@link #getTemplateArgs}</tt></p>
7069 renderItem : function(c, position, target){
7070 if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
7071 var args = this.getTemplateArgs(c);
7072 if(Ext.isNumber(position)){
7073 position = target.dom.childNodes[position] || null;
7076 c.itemCt = this.fieldTpl.insertBefore(position, args, true);
7078 c.itemCt = this.fieldTpl.append(target, args, true);
7081 // Non form fields don't have getItemCt, apply it here
7082 // This will get cleaned up in onRemove
7084 getItemCt: function(){
7090 c.label = c.getItemCt().child('label.x-form-item-label');
7092 c.render('x-form-el-' + c.id);
7093 }else if(!this.isValidParent(c, target)){
7094 Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl());
7096 if(this.trackLabels){
7098 this.onFieldHide(c);
7102 show: this.onFieldShow,
7103 hide: this.onFieldHide
7106 this.configureItem(c);
7108 Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
7113 * <p>Provides template arguments for rendering the fully wrapped, labeled and styled form Field.</p>
7114 * <p>This method returns an object hash containing properties used by the layout's {@link #fieldTpl}
7115 * to create a correctly wrapped, labeled and styled form Field. This may be overriden to
7116 * create custom layouts. The properties which must be returned are:</p><div class="mdetail-params"><ul>
7117 * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
7118 * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
7119 * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
7120 * supplied at the container level.</div></li>
7121 * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
7122 * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
7123 * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
7124 * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
7125 * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
7126 * field (defaults to <tt>''</tt>)</div></li>
7127 * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
7128 * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
7129 * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
7130 * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
7131 * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
7132 * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
7134 * @param (Ext.form.Field} field The {@link Ext.form.Field Field} being rendered.
7135 * @return An object hash containing the properties required to render the Field.
7137 getTemplateArgs: function(field) {
7138 var noLabelSep = !field.fieldLabel || field.hideLabel;
7141 label: field.fieldLabel,
7142 labelStyle: this.getLabelStyle(field.labelStyle),
7143 elementStyle: this.elementStyle||'',
7144 labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator),
7145 itemCls: (field.itemCls||this.container.itemCls||'') + (field.hideLabel ? ' x-hide-label' : ''),
7146 clearCls: field.clearCls || 'x-form-clear-left'
7151 adjustWidthAnchor: function(value, c){
7152 if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){
7153 var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict);
7154 return value - this.labelAdjust + (adjust ? -3 : 0);
7159 adjustHeightAnchor : function(value, c){
7160 if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){
7161 return value - c.label.getHeight();
7167 isValidParent : function(c, target){
7168 return target && this.container.getEl().contains(c.getPositionEl());
7172 * @property activeItem
7177 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
7179 * @class Ext.layout.AccordionLayout
\r
7180 * @extends Ext.layout.FitLayout
\r
7181 * <p>This is a layout that manages multiple Panels in an expandable accordion style such that only
\r
7182 * <b>one Panel can be expanded at any given time</b>. Each Panel has built-in support for expanding and collapsing.</p>
\r
7183 * <p>Note: Only Ext.Panels <b>and all subclasses of Ext.Panel</b> may be used in an accordion layout Container.</p>
\r
7184 * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
\r
7185 * configuration property. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
\r
7186 * <p>Example usage:</p>
\r
7188 var accordion = new Ext.Panel({
\r
7189 title: 'Accordion Layout',
\r
7190 layout:'accordion',
\r
7192 // applied to each contained panel
\r
7193 bodyStyle: 'padding:15px'
\r
7196 // layout-specific configs go here
\r
7197 titleCollapse: false,
\r
7203 html: '<p>Panel content!</p>'
\r
7206 html: '<p>Panel content!</p>'
\r
7209 html: '<p>Panel content!</p>'
\r
7214 Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
\r
7216 * @cfg {Boolean} fill
\r
7217 * True to adjust the active item's height to fill the available space in the container, false to use the
\r
7218 * item's current height, or auto height if not explicitly set (defaults to true).
\r
7222 * @cfg {Boolean} autoWidth
\r
7223 * True to set each contained item's width to 'auto', false to use the item's current width (defaults to true).
\r
7224 * Note that some components, in particular the {@link Ext.grid.GridPanel grid}, will not function properly within
\r
7225 * layouts if they have auto width, so in such cases this config should be set to false.
\r
7229 * @cfg {Boolean} titleCollapse
\r
7230 * True to allow expand/collapse of each contained panel by clicking anywhere on the title bar, false to allow
\r
7231 * expand/collapse only when the toggle tool button is clicked (defaults to true). When set to false,
\r
7232 * {@link #hideCollapseTool} should be false also.
\r
7234 titleCollapse : true,
\r
7236 * @cfg {Boolean} hideCollapseTool
\r
7237 * True to hide the contained panels' collapse/expand toggle buttons, false to display them (defaults to false).
\r
7238 * When set to true, {@link #titleCollapse} should be true also.
\r
7240 hideCollapseTool : false,
\r
7242 * @cfg {Boolean} collapseFirst
\r
7243 * True to make sure the collapse/expand toggle button always renders first (to the left of) any other tools
\r
7244 * in the contained panels' title bars, false to render it last (defaults to false).
\r
7246 collapseFirst : false,
\r
7248 * @cfg {Boolean} animate
\r
7249 * True to slide the contained panels open and closed during expand/collapse using animation, false to open and
\r
7250 * close directly with no animation (defaults to false). Note: to defer to the specific config setting of each
\r
7251 * contained panel for this property, set this to undefined at the layout level.
\r
7255 * @cfg {Boolean} sequence
\r
7256 * <b>Experimental</b>. If animate is set to true, this will result in each animation running in sequence.
\r
7260 * @cfg {Boolean} activeOnTop
\r
7261 * True to swap the position of each panel as it is expanded so that it becomes the first item in the container,
\r
7262 * false to keep the panels in the rendered order. <b>This is NOT compatible with "animate:true"</b> (defaults to false).
\r
7264 activeOnTop : false,
\r
7266 type: 'accordion',
\r
7268 renderItem : function(c){
\r
7269 if(this.animate === false){
\r
7270 c.animCollapse = false;
\r
7272 c.collapsible = true;
\r
7273 if(this.autoWidth){
\r
7274 c.autoWidth = true;
\r
7276 if(this.titleCollapse){
\r
7277 c.titleCollapse = true;
\r
7279 if(this.hideCollapseTool){
\r
7280 c.hideCollapseTool = true;
\r
7282 if(this.collapseFirst !== undefined){
\r
7283 c.collapseFirst = this.collapseFirst;
\r
7285 if(!this.activeItem && !c.collapsed){
\r
7286 this.setActiveItem(c, true);
\r
7287 }else if(this.activeItem && this.activeItem != c){
\r
7288 c.collapsed = true;
\r
7290 Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
\r
7291 c.header.addClass('x-accordion-hd');
\r
7292 c.on('beforeexpand', this.beforeExpand, this);
\r
7295 onRemove: function(c){
\r
7296 Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);
\r
7298 c.header.removeClass('x-accordion-hd');
\r
7300 c.un('beforeexpand', this.beforeExpand, this);
\r
7304 beforeExpand : function(p, anim){
\r
7305 var ai = this.activeItem;
\r
7307 if(this.sequence){
\r
7308 delete this.activeItem;
\r
7309 if (!ai.collapsed){
\r
7310 ai.collapse({callback:function(){
\r
7311 p.expand(anim || true);
\r
7316 ai.collapse(this.animate);
\r
7319 this.setActive(p);
\r
7320 if(this.activeOnTop){
\r
7321 p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
\r
7323 // Items have been hidden an possibly rearranged, we need to get the container size again.
\r
7328 setItemSize : function(item, size){
\r
7329 if(this.fill && item){
\r
7330 var hh = 0, i, ct = this.getRenderedItems(this.container), len = ct.length, p;
\r
7331 // Add up all the header heights
\r
7332 for (i = 0; i < len; i++) {
\r
7333 if((p = ct[i]) != item){
\r
7334 hh += p.header.getHeight();
\r
7337 // Subtract the header heights from the container size
\r
7338 size.height -= hh;
\r
7339 // Call setSize on the container to set the correct height. For Panels, deferedHeight
\r
7340 // will simply store this size for when the expansion is done.
\r
7341 item.setSize(size);
\r
7346 * Sets the active (expanded) item in the layout.
\r
7347 * @param {String/Number} item The string component id or numeric index of the item to activate
\r
7349 setActiveItem : function(item){
\r
7350 this.setActive(item, true);
\r
7354 setActive : function(item, expand){
\r
7355 var ai = this.activeItem;
\r
7356 item = this.container.getComponent(item);
\r
7358 if(item.rendered && item.collapsed && expand){
\r
7362 ai.fireEvent('deactivate', ai);
\r
7364 this.activeItem = item;
\r
7365 item.fireEvent('activate', item);
\r
7370 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
\r
7372 //backwards compat
\r
7373 Ext.layout.Accordion = Ext.layout.AccordionLayout;/**
\r
7374 * @class Ext.layout.TableLayout
\r
7375 * @extends Ext.layout.ContainerLayout
\r
7376 * <p>This layout allows you to easily render content into an HTML table. The total number of columns can be
\r
7377 * specified, and rowspan and colspan can be used to create complex layouts within the table.
\r
7378 * This class is intended to be extended or created via the layout:'table' {@link Ext.Container#layout} config,
\r
7379 * and should generally not need to be created directly via the new keyword.</p>
\r
7380 * <p>Note that when creating a layout via config, the layout-specific config properties must be passed in via
\r
7381 * the {@link Ext.Container#layoutConfig} object which will then be applied internally to the layout. In the
\r
7382 * case of TableLayout, the only valid layout config property is {@link #columns}. However, the items added to a
\r
7383 * TableLayout can supply the following table-specific config properties:</p>
\r
7385 * <li><b>rowspan</b> Applied to the table cell containing the item.</li>
\r
7386 * <li><b>colspan</b> Applied to the table cell containing the item.</li>
\r
7387 * <li><b>cellId</b> An id applied to the table cell containing the item.</li>
\r
7388 * <li><b>cellCls</b> A CSS class name added to the table cell containing the item.</li>
\r
7390 * <p>The basic concept of building up a TableLayout is conceptually very similar to building up a standard
\r
7391 * HTML table. You simply add each panel (or "cell") that you want to include along with any span attributes
\r
7392 * specified as the special config properties of rowspan and colspan which work exactly like their HTML counterparts.
\r
7393 * Rather than explicitly creating and nesting rows and columns as you would in HTML, you simply specify the
\r
7394 * total column count in the layoutConfig and start adding panels in their natural order from left to right,
\r
7395 * top to bottom. The layout will automatically figure out, based on the column count, rowspans and colspans,
\r
7396 * how to position each panel within the table. Just like with HTML tables, your rowspans and colspans must add
\r
7397 * up correctly in your overall layout or you'll end up with missing and/or extra cells! Example usage:</p>
\r
7399 // This code will generate a layout table that is 3 columns by 2 rows
\r
7400 // with some spanning included. The basic layout will be:
\r
7401 // +--------+-----------------+
\r
7403 // | |--------+--------|
\r
7405 // +--------+--------+--------+
\r
7406 var table = new Ext.Panel({
\r
7407 title: 'Table Layout',
\r
7410 // applied to each contained panel
\r
7411 bodyStyle:'padding:20px'
\r
7414 // The total column count must be specified here
\r
7418 html: '<p>Cell A content</p>',
\r
7421 html: '<p>Cell B content</p>',
\r
7424 html: '<p>Cell C content</p>',
\r
7425 cellCls: 'highlight'
\r
7427 html: '<p>Cell D content</p>'
\r
7432 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
\r
7434 * @cfg {Number} columns
\r
7435 * The total number of columns to create in the table for this layout. If not specified, all Components added to
\r
7436 * this layout will be rendered into a single row using one column per Component.
\r
7440 monitorResize:false,
\r
7444 targetCls: 'x-table-layout-ct',
\r
7447 * @cfg {Object} tableAttrs
\r
7448 * <p>An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification
\r
7449 * used to create the layout's <tt><table></tt> element. Example:</p><pre><code>
\r
7466 setContainer : function(ct){
\r
7467 Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
\r
7469 this.currentRow = 0;
\r
7470 this.currentColumn = 0;
\r
7475 onLayout : function(ct, target){
\r
7476 var cs = ct.items.items, len = cs.length, c, i;
\r
7479 target.addClass('x-table-layout-ct');
\r
7481 this.table = target.createChild(
\r
7482 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
\r
7484 this.renderAll(ct, target);
\r
7488 getRow : function(index){
\r
7489 var row = this.table.tBodies[0].childNodes[index];
\r
7491 row = document.createElement('tr');
\r
7492 this.table.tBodies[0].appendChild(row);
\r
7498 getNextCell : function(c){
\r
7499 var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
\r
7500 var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
\r
7501 for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
\r
7502 if(!this.cells[rowIndex]){
\r
7503 this.cells[rowIndex] = [];
\r
7505 for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
\r
7506 this.cells[rowIndex][colIndex] = true;
\r
7509 var td = document.createElement('td');
\r
7513 var cls = 'x-table-layout-cell';
\r
7515 cls += ' ' + c.cellCls;
\r
7517 td.className = cls;
\r
7519 td.colSpan = c.colspan;
\r
7522 td.rowSpan = c.rowspan;
\r
7524 this.getRow(curRow).appendChild(td);
\r
7529 getNextNonSpan: function(colIndex, rowIndex){
\r
7530 var cols = this.columns;
\r
7531 while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
\r
7532 if(cols && colIndex >= cols){
\r
7539 return [colIndex, rowIndex];
\r
7543 renderItem : function(c, position, target){
\r
7544 // Ensure we have our inner table to get cells to render into.
\r
7546 this.table = target.createChild(
\r
7547 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
\r
7549 if(c && !c.rendered){
\r
7550 c.render(this.getNextCell(c));
\r
7551 this.configureItem(c, position);
\r
7552 }else if(c && !this.isValidParent(c, target)){
\r
7553 var container = this.getNextCell(c);
\r
7554 container.insertBefore(c.getPositionEl().dom, null);
\r
7555 c.container = Ext.get(container);
\r
7556 this.configureItem(c, position);
\r
7561 isValidParent : function(c, target){
\r
7562 return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);
\r
7566 * @property activeItem
\r
7571 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;/**
7572 * @class Ext.layout.AbsoluteLayout
7573 * @extends Ext.layout.AnchorLayout
7574 * <p>This is a layout that inherits the anchoring of <b>{@link Ext.layout.AnchorLayout}</b> and adds the
7575 * ability for x/y positioning using the standard x and y component config options.</p>
7576 * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
7577 * configuration property. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
7578 * <p>Example usage:</p>
7580 var form = new Ext.form.FormPanel({
7581 title: 'Absolute Layout',
7584 // layout-specific configs go here
7585 extraCls: 'x-abs-layout-item',
7588 url:'save-form.php',
7589 defaultType: 'textfield',
7599 anchor:'100%' // anchor width by percentage
7609 anchor: '100%' // anchor width by percentage
7615 anchor: '100% 100%' // anchor width and height
7620 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
7622 extraCls: 'x-abs-layout-item',
7626 onLayout : function(ct, target){
7628 this.paddingLeft = target.getPadding('l');
7629 this.paddingTop = target.getPadding('t');
7630 Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
7634 adjustWidthAnchor : function(value, comp){
7635 return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
7639 adjustHeightAnchor : function(value, comp){
7640 return value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
7643 * @property activeItem
7647 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
7649 * @class Ext.layout.BoxLayout
7650 * @extends Ext.layout.ContainerLayout
7651 * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
7653 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
7655 * @cfg {Object} defaultMargins
7656 * <p>If the individual contained items do not have a <tt>margins</tt>
7657 * property specified, the default margins from this property will be
7658 * applied to each item.</p>
7659 * <br><p>This property may be specified as an object containing margins
7660 * to apply in the format:</p><pre><code>
7663 right: (right margin),
7664 bottom: (bottom margin),
7667 * <p>This property may also be specified as a string containing
7668 * space-separated, numeric margin values. The order of the sides associated
7669 * with each value matches the way CSS processes margin values:</p>
7670 * <div class="mdetail-params"><ul>
7671 * <li>If there is only one value, it applies to all sides.</li>
7672 * <li>If there are two values, the top and bottom borders are set to the
7673 * first value and the right and left are set to the second.</li>
7674 * <li>If there are three values, the top is set to the first value, the left
7675 * and right are set to the second, and the bottom is set to the third.</li>
7676 * <li>If there are four values, they apply to the top, right, bottom, and
7677 * left, respectively.</li>
7679 * <p>Defaults to:</p><pre><code>
7680 * {top:0, right:0, bottom:0, left:0}
7683 defaultMargins : {left:0,top:0,right:0,bottom:0},
7685 * @cfg {String} padding
7686 * <p>Sets the padding to be applied to all child items managed by this layout.</p>
7687 * <p>This property must be specified as a string containing
7688 * space-separated, numeric padding values. The order of the sides associated
7689 * with each value matches the way CSS processes padding values:</p>
7690 * <div class="mdetail-params"><ul>
7691 * <li>If there is only one value, it applies to all sides.</li>
7692 * <li>If there are two values, the top and bottom borders are set to the
7693 * first value and the right and left are set to the second.</li>
7694 * <li>If there are three values, the top is set to the first value, the left
7695 * and right are set to the second, and the bottom is set to the third.</li>
7696 * <li>If there are four values, they apply to the top, right, bottom, and
7697 * left, respectively.</li>
7699 * <p>Defaults to: <code>"0"</code></p>
7702 // documented in subclasses
7706 monitorResize : true,
7709 extraCls : 'x-box-item',
7710 targetCls : 'x-box-layout-ct',
7711 innerCls : 'x-box-inner',
7713 constructor : function(config){
7714 Ext.layout.BoxLayout.superclass.constructor.call(this, config);
7715 if(Ext.isString(this.defaultMargins)){
7716 this.defaultMargins = this.parseMargins(this.defaultMargins);
7721 isValidParent : function(c, target){
7722 return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
7726 renderAll : function(ct, target){
7728 // the innerCt prevents wrapping and shuffling while
7729 // the container is resizing
7730 this.innerCt = target.createChild({cls:this.innerCls});
7731 this.padding = this.parseMargins(this.padding);
7733 Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
7736 onLayout : function(ct, target){
7737 this.renderAll(ct, target);
7740 getLayoutTargetSize : function(){
7741 var target = this.container.getLayoutTarget(), ret;
7743 ret = target.getViewSize();
7744 ret.width -= target.getPadding('lr');
7745 ret.height -= target.getPadding('tb');
7751 renderItem : function(c){
7752 if(Ext.isString(c.margins)){
7753 c.margins = this.parseMargins(c.margins);
7754 }else if(!c.margins){
7755 c.margins = this.defaultMargins;
7757 Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
7762 * @class Ext.layout.VBoxLayout
7763 * @extends Ext.layout.BoxLayout
7764 * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical
7765 * space between child items containing a numeric <code>flex</code> configuration.</p>
7766 * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option.
7768 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
7770 * @cfg {String} align
7771 * Controls how the child items of the container are aligned. Acceptable configuration values for this
7773 * <div class="mdetail-params"><ul>
7774 * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally
7775 * at the <b>left</b> side of the container</div></li>
7776 * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the
7777 * <b>mid-width</b> of the container</div></li>
7778 * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill
7779 * the width of the container</div></li>
7780 * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to
7781 * the size of the largest item.</div></li>
7784 align : 'left', // left, center, stretch, strechmax
7787 * @cfg {String} pack
7788 * Controls how the child items of the container are packed together. Acceptable configuration values
7789 * for this property are:
7790 * <div class="mdetail-params"><ul>
7791 * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
7792 * <b>top</b> side of container</div></li>
7793 * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
7794 * <b>mid-height</b> of container</div></li>
7795 * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>
7796 * side of container</div></li>
7800 * @cfg {Number} flex
7801 * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
7802 * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>
7803 * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
7804 * a <tt>flex</tt> value specified. Any child items that have either a <tt>flex = 0</tt> or
7805 * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
7809 onLayout : function(ct, target){
7810 Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);
7812 var cs = this.getRenderedItems(ct), csLen = cs.length,
7813 c, i, cm, ch, margin, cl, diff, aw, availHeight,
7814 size = this.getLayoutTargetSize(),
7816 h = size.height - this.scrollOffset,
7817 l = this.padding.left,
7818 t = this.padding.top,
7819 isStart = this.pack == 'start',
7828 // Do only width calculations and apply those first, as they can affect height
7829 for (i = 0 ; i < csLen; i++) {
7832 margin = cm.top + cm.bottom;
7833 // Max height for align
7834 maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);
7837 var innerCtWidth = maxWidth + this.padding.left + this.padding.right;
7840 this.innerCt.setSize(w, h);
7844 this.innerCt.setSize(innerCtWidth, h);
7847 this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);
7851 var availableWidth = Math.max(0, w - this.padding.left - this.padding.right);
7853 for (i = 0 ; i < csLen; i++) {
7856 if(this.align == 'stretch'){
7857 c.setWidth(((w - (this.padding.left + this.padding.right)) - (cm.left + cm.right)).constrain(
7858 c.minWidth || 0, c.maxWidth || 1000000));
7859 }else if(this.align == 'stretchmax'){
7860 c.setWidth((maxWidth - (cm.left + cm.right)).constrain(
7861 c.minWidth || 0, c.maxWidth || 1000000));
7862 }else if(isStart && c.flex){
7868 // Height calculations
7869 for (i = 0 ; i < csLen; i++) {
7871 // Total of all the flex values
7872 totalFlex += c.flex || 0;
7873 // Don't run height calculations on flexed items
7875 // Render and layout sub-containers without a flex or height, once
7876 if (!c.height && !c.hasLayout && c.doLayout) {
7885 // Determine how much height is available to flex
7886 extraHeight += ch + cm.top + cm.bottom;
7888 // Final avail height calc
7889 availHeight = Math.max(0, (h - extraHeight - this.padding.top - this.padding.bottom));
7891 var leftOver = availHeight;
7892 for (i = 0 ; i < csLen; i++) {
7894 if(isStart && c.flex){
7895 ch = Math.floor(availHeight * (c.flex / totalFlex));
7900 if(this.pack == 'center'){
7901 t += availHeight ? availHeight / 2 : 0;
7902 }else if(this.pack == 'end'){
7907 for (i = 0 ; i < csLen; i++) {
7911 aw = availableWidth;
7912 cl = l + cm.left // default left pos
7914 // Adjust left pos for centering
7915 if(this.align == 'center'){
7916 if((diff = availableWidth - (c.getWidth() + cm.left + cm.right)) > 0){
7922 c.setPosition(cl, t);
7923 if(isStart && c.flex){
7924 ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));
7929 t += ch + cm.bottom;
7931 // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
7932 if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
7933 var ts = this.getLayoutTargetSize();
7934 if (ts.width != size.width || ts.height != size.height){
7935 this.adjustmentPass = true;
7936 this.onLayout(ct, target);
7939 delete this.adjustmentPass;
7943 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
7946 * @class Ext.layout.HBoxLayout
7947 * @extends Ext.layout.BoxLayout
7948 * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal
7949 * space between child items containing a numeric <code>flex</code> configuration.</p>
7950 * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option.
7952 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
7954 * @cfg {String} align
7955 * Controls how the child items of the container are aligned. Acceptable configuration values for this
7957 * <div class="mdetail-params"><ul>
7958 * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically
7959 * at the <b>top</b> of the container</div></li>
7960 * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically in the
7961 * <b>middle</b> of the container</div></li>
7962 * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill
7963 * the height of the container</div></li>
7964 * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to
7965 * the height of the largest item.</div></li>
7967 align : 'top', // top, middle, stretch, strechmax
7970 * @cfg {String} pack
7971 * Controls how the child items of the container are packed together. Acceptable configuration values
7972 * for this property are:
7973 * <div class="mdetail-params"><ul>
7974 * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
7975 * <b>left</b> side of container</div></li>
7976 * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
7977 * <b>mid-width</b> of container</div></li>
7978 * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>
7979 * side of container</div></li>
7983 * @cfg {Number} flex
7984 * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
7985 * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>
7986 * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
7987 * a <tt>flex</tt> value specified. Any child items that have either a <tt>flex = 0</tt> or
7988 * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
7992 onLayout : function(ct, target){
7993 Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);
7995 var cs = this.getRenderedItems(ct), csLen = cs.length,
7996 c, i, cm, cw, ch, diff, availWidth,
7997 size = this.getLayoutTargetSize(),
7998 w = size.width - this.scrollOffset,
8000 l = this.padding.left,
8001 t = this.padding.top,
8002 isStart = this.pack == 'start',
8003 isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
8009 for (i = 0 ; i < csLen; i++) {
8011 // Total of all the flex values
8012 totalFlex += c.flex || 0;
8013 // Don't run width calculations on flexed items
8015 // Render and layout sub-containers without a flex or width, once
8016 if (!c.width && !c.hasLayout && c.doLayout) {
8024 // Determine how much width is available to flex
8025 extraWidth += cw + cm.left + cm.right;
8026 // Max height for align
8027 maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom);
8029 // Final avail width calc
8030 availWidth = Math.max(0, (w - extraWidth - this.padding.left - this.padding.right));
8032 var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom;
8035 this.innerCt.setSize(w, h);
8039 this.innerCt.setSize(w, innerCtHeight);
8042 this.innerCt.setSize(w, h = Math.max(h, innerCtHeight));
8046 var leftOver = availWidth,
8050 availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom);
8052 for (i = 0 ; i < csLen; i++) {
8054 if(isStart && c.flex){
8055 cw = Math.floor(availWidth * (c.flex / totalFlex));
8061 if(this.pack == 'center'){
8062 l += availWidth ? availWidth / 2 : 0;
8063 }else if(this.pack == 'end'){
8066 for (i = 0 ; i < csLen; i++) {
8070 c.setPosition(l, t + cm.top);
8071 if(isStart && c.flex){
8072 cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0));
8074 restore.push(c.getHeight());
8076 c.setSize(cw, availableHeight);
8084 for (i = 0 ; i < csLen; i++) {
8088 if(isStart && c.flex){
8089 ch = restore[idx++];
8091 if(this.align == 'stretch'){
8092 c.setHeight(((h - (this.padding.top + this.padding.bottom)) - (cm.top + cm.bottom)).constrain(
8093 c.minHeight || 0, c.maxHeight || 1000000));
8094 }else if(this.align == 'stretchmax'){
8095 c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain(
8096 c.minHeight || 0, c.maxHeight || 1000000));
8098 if(this.align == 'middle'){
8099 diff = availableHeight - (ch + cm.top + cm.bottom);
8100 ch = t + cm.top + (diff/2);
8102 c.setPosition(c.x, ch);
8105 if(isStart && c.flex){
8110 // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
8111 if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
8112 var ts = this.getLayoutTargetSize();
8113 if (ts.width != size.width || ts.height != size.height){
8114 this.adjustmentPass = true;
8115 this.onLayout(ct, target);
8118 delete this.adjustmentPass;
8122 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
8124 * @class Ext.layout.ToolbarLayout
8125 * @extends Ext.layout.ContainerLayout
8126 * Layout manager implicitly used by Ext.Toolbar.
8128 Ext.layout.ToolbarLayout = Ext.extend(Ext.layout.ContainerLayout, {
8129 monitorResize : true,
8131 lastOverflow : false,
8133 noItemsMenuText : '<div class="x-toolbar-no-items">(None)</div>',
8136 onLayout : function(ct, target){
8138 var align = ct.buttonAlign == 'center' ? 'center' : 'left';
8139 target.addClass('x-toolbar-layout-ct');
8140 target.insertHtml('beforeEnd',
8141 '<table cellspacing="0" class="x-toolbar-ct"><tbody><tr><td class="x-toolbar-left" align="' + align + '"><table cellspacing="0"><tbody><tr class="x-toolbar-left-row"></tr></tbody></table></td><td class="x-toolbar-right" align="right"><table cellspacing="0" class="x-toolbar-right-ct"><tbody><tr><td><table cellspacing="0"><tbody><tr class="x-toolbar-right-row"></tr></tbody></table></td><td><table cellspacing="0"><tbody><tr class="x-toolbar-extras-row"></tr></tbody></table></td></tr></tbody></table></td></tr></tbody></table>');
8142 this.leftTr = target.child('tr.x-toolbar-left-row', true);
8143 this.rightTr = target.child('tr.x-toolbar-right-row', true);
8144 this.extrasTr = target.child('tr.x-toolbar-extras-row', true);
8147 var side = ct.buttonAlign == 'right' ? this.rightTr : this.leftTr,
8149 items = ct.items.items;
8151 for(var i = 0, len = items.length, c; i < len; i++, pos++) {
8154 side = this.rightTr;
8156 }else if(!c.rendered){
8157 c.render(this.insertCell(c, side, pos));
8159 if(!c.xtbHidden && !this.isValidParent(c, side.childNodes[pos])){
8160 var td = this.insertCell(c, side, pos);
8161 td.appendChild(c.getPositionEl().dom);
8162 c.container = Ext.get(td);
8166 //strip extra empty cells
8167 this.cleanup(this.leftTr);
8168 this.cleanup(this.rightTr);
8169 this.cleanup(this.extrasTr);
8170 this.fitToSize(target);
8173 cleanup : function(row){
8174 var cn = row.childNodes, i, c;
8175 for(i = cn.length-1; i >= 0 && (c = cn[i]); i--){
8182 insertCell : function(c, side, pos){
8183 var td = document.createElement('td');
8184 td.className='x-toolbar-cell';
8185 side.insertBefore(td, side.childNodes[pos]||null);
8189 hideItem : function(item){
8190 var h = (this.hiddens = this.hiddens || []);
8192 item.xtbHidden = true;
8193 item.xtbWidth = item.getPositionEl().dom.parentNode.offsetWidth;
8197 unhideItem : function(item){
8199 item.xtbHidden = false;
8200 this.hiddens.remove(item);
8201 if(this.hiddens.length < 1){
8202 delete this.hiddens;
8206 getItemWidth : function(c){
8207 return c.hidden ? (c.xtbWidth || 0) : c.getPositionEl().dom.parentNode.offsetWidth;
8210 fitToSize : function(t){
8211 if(this.container.enableOverflow === false){
8214 var w = t.dom.clientWidth,
8215 lw = this.lastWidth || 0,
8216 iw = t.dom.firstChild.offsetWidth,
8217 clipWidth = w - this.triggerWidth,
8222 if(iw > w || (this.hiddens && w >= lw)){
8223 var i, items = this.container.items.items,
8224 len = items.length, c,
8227 for(i = 0; i < len; i++) {
8230 loopWidth += this.getItemWidth(c);
8231 if(loopWidth > clipWidth){
8232 if(!(c.hidden || c.xtbHidden)){
8235 }else if(c.xtbHidden){
8243 if(!this.lastOverflow){
8244 this.container.fireEvent('overflowchange', this.container, true);
8245 this.lastOverflow = true;
8247 }else if(this.more){
8249 this.more.destroy();
8251 if(this.lastOverflow){
8252 this.container.fireEvent('overflowchange', this.container, false);
8253 this.lastOverflow = false;
8258 createMenuConfig : function(c, hideOnClick){
8259 var cfg = Ext.apply({}, c.initialConfig),
8260 group = c.toggleGroup;
8263 text: c.overflowText || c.text,
8267 disabled: c.disabled,
8271 hideOnClick: hideOnClick
8273 if(group || c.enableToggle){
8278 checkchange: function(item, checked){
8291 addComponentToMenu : function(m, c){
8292 if(c instanceof Ext.Toolbar.Separator){
8294 }else if(Ext.isFunction(c.isXType)){
8295 if(c.isXType('splitbutton')){
8296 m.add(this.createMenuConfig(c, true));
8297 }else if(c.isXType('button')){
8298 m.add(this.createMenuConfig(c, !c.menu));
8299 }else if(c.isXType('buttongroup')){
8300 c.items.each(function(item){
8301 this.addComponentToMenu(m, item);
8307 clearMenu : function(){
8308 var m = this.moreMenu;
8310 m.items.each(function(item){
8317 beforeMoreShow : function(m){
8318 var h = this.container.items.items,
8322 needsSep = function(group, item){
8323 return group.isXType('buttongroup') && !(item instanceof Ext.Toolbar.Separator);
8328 for(var i = 0; i < len; i++){
8331 if(prev && (needsSep(c, prev) || needsSep(prev, c))){
8334 this.addComponentToMenu(m, c);
8338 // put something so the menu isn't empty
8339 // if no compatible items found
8340 if(m.items.length < 1){
8341 m.add(this.noItemsMenuText);
8345 initMore : function(){
8347 this.moreMenu = new Ext.menu.Menu({
8348 ownerCt : this.container,
8350 beforeshow: this.beforeMoreShow,
8355 this.more = new Ext.Button({
8356 iconCls : 'x-toolbar-more-icon',
8357 cls : 'x-toolbar-more',
8358 menu : this.moreMenu,
8359 ownerCt : this.container
8361 var td = this.insertCell(this.more, this.extrasTr, 100);
8362 this.more.render(td);
8366 destroy : function(){
8367 Ext.destroy(this.more, this.moreMenu);
8369 delete this.rightTr;
8370 delete this.extrasTr;
8371 Ext.layout.ToolbarLayout.superclass.destroy.call(this);
8375 Ext.Container.LAYOUTS.toolbar = Ext.layout.ToolbarLayout;/**
8376 * @class Ext.layout.MenuLayout
8377 * @extends Ext.layout.ContainerLayout
8378 * <p>Layout manager used by {@link Ext.menu.Menu}. Generally this class should not need to be used directly.</p>
8380 Ext.layout.MenuLayout = Ext.extend(Ext.layout.ContainerLayout, {
8381 monitorResize : true,
8383 setContainer : function(ct){
8384 this.monitorResize = !ct.floating;
8385 // This event is only fired by the menu in IE, used so we don't couple
8386 // the menu with the layout.
8387 ct.on('autosize', this.doAutoSize, this);
8388 Ext.layout.MenuLayout.superclass.setContainer.call(this, ct);
8391 renderItem : function(c, position, target){
8392 if (!this.itemTpl) {
8393 this.itemTpl = Ext.layout.MenuLayout.prototype.itemTpl = new Ext.XTemplate(
8394 '<li id="{itemId}" class="{itemCls}">',
8395 '<tpl if="needsIcon">',
8396 '<img src="{icon}" class="{iconCls}"/>',
8402 if(c && !c.rendered){
8403 if(Ext.isNumber(position)){
8404 position = target.dom.childNodes[position];
8406 var a = this.getItemArgs(c);
8408 // The Component's positionEl is the <li> it is rendered into
8409 c.render(c.positionEl = position ?
8410 this.itemTpl.insertBefore(position, a, true) :
8411 this.itemTpl.append(target, a, true));
8413 // Link the containing <li> to the item.
8414 c.positionEl.menuItemId = c.getItemId();
8416 // If rendering a regular Component, and it needs an icon,
8417 // move the Component rightwards.
8418 if (!a.isMenuItem && a.needsIcon) {
8419 c.positionEl.addClass('x-menu-list-item-indent');
8421 this.configureItem(c, position);
8422 }else if(c && !this.isValidParent(c, target)){
8423 if(Ext.isNumber(position)){
8424 position = target.dom.childNodes[position];
8426 target.dom.insertBefore(c.getActionEl().dom, position || null);
8430 getItemArgs : function(c) {
8431 var isMenuItem = c instanceof Ext.menu.Item;
8433 isMenuItem: isMenuItem,
8434 needsIcon: !isMenuItem && (c.icon || c.iconCls),
8435 icon: c.icon || Ext.BLANK_IMAGE_URL,
8436 iconCls: 'x-menu-item-icon ' + (c.iconCls || ''),
8437 itemId: 'x-menu-el-' + c.id,
8438 itemCls: 'x-menu-list-item '
8442 // Valid if the Component is in a <li> which is part of our target <ul>
8443 isValidParent : function(c, target) {
8444 return c.el.up('li.x-menu-list-item', 5).dom.parentNode === (target.dom || target);
8447 onLayout : function(ct, target){
8448 Ext.layout.MenuLayout.superclass.onLayout.call(this, ct, target);
8452 doAutoSize : function(){
8453 var ct = this.container, w = ct.width;
8458 ct.setWidth(Ext.isStrict && (Ext.isIE7 || Ext.isIE8) ? 'auto' : ct.minWidth);
8459 var el = ct.getEl(), t = el.dom.offsetWidth; // force recalc
8460 ct.setWidth(ct.getLayoutTarget().getWidth() + el.getFrameWidth('lr'));
8465 Ext.Container.LAYOUTS['menu'] = Ext.layout.MenuLayout;/**
\r
8466 * @class Ext.Viewport
\r
8467 * @extends Ext.Container
\r
8468 * <p>A specialized container representing the viewable application area (the browser viewport).</p>
\r
8469 * <p>The Viewport renders itself to the document body, and automatically sizes itself to the size of
\r
8470 * the browser viewport and manages window resizing. There may only be one Viewport created
\r
8471 * in a page. Inner layouts are available by virtue of the fact that all {@link Ext.Panel Panel}s
\r
8472 * added to the Viewport, either through its {@link #items}, or through the items, or the {@link #add}
\r
8473 * method of any of its child Panels may themselves have a layout.</p>
\r
8474 * <p>The Viewport does not provide scrolling, so child Panels within the Viewport should provide
\r
8475 * for scrolling if needed using the {@link #autoScroll} config.</p>
\r
8476 * <p>An example showing a classic application border layout:</p><pre><code>
\r
8477 new Ext.Viewport({
\r
8481 html: '<h1 class="x-panel-header">Page Title</h1>',
\r
8484 margins: '0 0 5 0'
\r
8487 collapsible: true,
\r
8488 title: 'Navigation',
\r
8490 // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout}
\r
8493 title: 'Title for Panel',
\r
8494 collapsible: true,
\r
8495 html: 'Information goes here',
\r
8501 title: 'Title for the Grid Panel',
\r
8502 collapsible: true,
\r
8506 // remaining grid configuration not shown ...
\r
8507 // notice that the GridPanel is added directly as the region
\r
8508 // it is not "overnested" inside another Panel
\r
8511 xtype: 'tabpanel', // TabPanel itself has no title
\r
8513 title: 'Default Tab',
\r
8514 html: 'The first tab\'s content. Others may be added dynamically'
\r
8520 * Create a new Viewport
\r
8521 * @param {Object} config The config object
\r
8524 Ext.Viewport = Ext.extend(Ext.Container, {
\r
8526 * Privatize config options which, if used, would interfere with the
\r
8527 * correct operation of the Viewport as the sole manager of the
\r
8528 * layout of the document body.
\r
8531 * @cfg {Mixed} applyTo @hide
\r
8534 * @cfg {Boolean} allowDomMove @hide
\r
8537 * @cfg {Boolean} hideParent @hide
\r
8540 * @cfg {Mixed} renderTo @hide
\r
8543 * @cfg {Boolean} hideParent @hide
\r
8546 * @cfg {Number} height @hide
\r
8549 * @cfg {Number} width @hide
\r
8552 * @cfg {Boolean} autoHeight @hide
\r
8555 * @cfg {Boolean} autoWidth @hide
\r
8558 * @cfg {Boolean} deferHeight @hide
\r
8561 * @cfg {Boolean} monitorResize @hide
\r
8564 initComponent : function() {
\r
8565 Ext.Viewport.superclass.initComponent.call(this);
\r
8566 document.getElementsByTagName('html')[0].className += ' x-viewport';
\r
8567 this.el = Ext.getBody();
\r
8568 this.el.setHeight = Ext.emptyFn;
\r
8569 this.el.setWidth = Ext.emptyFn;
\r
8570 this.el.setSize = Ext.emptyFn;
\r
8571 this.el.dom.scroll = 'no';
\r
8572 this.allowDomMove = false;
\r
8573 this.autoWidth = true;
\r
8574 this.autoHeight = true;
\r
8575 Ext.EventManager.onWindowResize(this.fireResize, this);
\r
8576 this.renderTo = this.el;
\r
8579 fireResize : function(w, h){
\r
8580 this.fireEvent('resize', this, w, h, w, h);
\r
8583 Ext.reg('viewport', Ext.Viewport);
\r
8586 * @extends Ext.Container
8587 * <p>Panel is a container that has specific functionality and structural components that make
8588 * it the perfect building block for application-oriented user interfaces.</p>
8589 * <p>Panels are, by virtue of their inheritance from {@link Ext.Container}, capable
8590 * of being configured with a {@link Ext.Container#layout layout}, and containing child Components.</p>
8591 * <p>When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.Container#add adding} Components
8592 * to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether
8593 * those child elements need to be sized using one of Ext's built-in <code><b>{@link Ext.Container#layout layout}</b></code> schemes. By
8594 * default, Panels use the {@link Ext.layout.ContainerLayout ContainerLayout} scheme. This simply renders
8595 * child components, appending them one after the other inside the Container, and <b>does not apply any sizing</b>
8597 * <p>A Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate
8598 * {@link #header}, {@link #footer} and {@link #body} sections (see {@link #frame} for additional
8600 * <p>Panel also provides built-in {@link #collapsible expandable and collapsible behavior}, along with
8601 * a variety of {@link #tools prebuilt tool buttons} that can be wired up to provide other customized
8602 * behavior. Panels can be easily dropped into any {@link Ext.Container Container} or layout, and the
8603 * layout and rendering pipeline is {@link Ext.Container#add completely managed by the framework}.</p>
8605 * @param {Object} config The config object
8608 Ext.Panel = Ext.extend(Ext.Container, {
8610 * The Panel's header {@link Ext.Element Element}. Read-only.
8611 * <p>This Element is used to house the {@link #title} and {@link #tools}</p>
8612 * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
8617 * The Panel's body {@link Ext.Element Element} which may be used to contain HTML content.
8618 * The content may be specified in the {@link #html} config, or it may be loaded using the
8619 * {@link autoLoad} config, or through the Panel's {@link #getUpdater Updater}. Read-only.
8620 * <p>If this is used to load visible HTML elements in either way, then
8621 * the Panel may not be used as a Layout for hosting nested Panels.</p>
8622 * <p>If this Panel is intended to be used as the host of a Layout (See {@link #layout}
8623 * then the body Element must not be loaded or changed - it is under the control
8624 * of the Panel's Layout.
8625 * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
8630 * The Panel's bwrap {@link Ext.Element Element} used to contain other Panel elements
8631 * (tbar, body, bbar, footer). See {@link #bodyCfg}. Read-only.
8636 * True if this panel is collapsed. Read-only.
8638 * @property collapsed
8641 * @cfg {Object} bodyCfg
8642 * <p>A {@link Ext.DomHelper DomHelper} element specification object may be specified for any
8643 * Panel Element.</p>
8644 * <p>By default, the Default element in the table below will be used for the html markup to
8645 * create a child element with the commensurate Default class name (<code>baseCls</code> will be
8646 * replaced by <code>{@link #baseCls}</code>):</p>
8648 * Panel Default Default Custom Additional Additional
8649 * Element element class element class style
8650 * ======== ========================== ========= ============== ===========
8651 * {@link #header} div {@link #baseCls}+'-header' {@link #headerCfg} headerCssClass headerStyle
8652 * {@link #bwrap} div {@link #baseCls}+'-bwrap' {@link #bwrapCfg} bwrapCssClass bwrapStyle
8653 * + tbar div {@link #baseCls}+'-tbar' {@link #tbarCfg} tbarCssClass tbarStyle
8654 * + {@link #body} div {@link #baseCls}+'-body' {@link #bodyCfg} {@link #bodyCssClass} {@link #bodyStyle}
8655 * + bbar div {@link #baseCls}+'-bbar' {@link #bbarCfg} bbarCssClass bbarStyle
8656 * + {@link #footer} div {@link #baseCls}+'-footer' {@link #footerCfg} footerCssClass footerStyle
8658 * <p>Configuring a Custom element may be used, for example, to force the {@link #body} Element
8659 * to use a different form of markup than is created by default. An example of this might be
8660 * to {@link Ext.Element#createChild create a child} Panel containing a custom content, such as
8661 * a header, or forcing centering of all Panel content by having the body be a <center>
8665 title: 'Message Title',
8666 renderTo: Ext.getBody(),
8667 width: 200, height: 130,
8670 cls: 'x-panel-body', // Default class not applied if Custom element specified
8675 cls: 'x-panel-footer' // same as the Default class
8678 footerCssClass: 'custom-footer', // additional css class, see {@link Ext.element#addClass addClass}
8679 footerStyle: 'background-color:red' // see {@link #bodyStyle}
8682 * <p>The example above also explicitly creates a <code>{@link #footer}</code> with custom markup and
8683 * styling applied.</p>
8686 * @cfg {Object} headerCfg
8687 * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
8688 * of this Panel's {@link #header} Element. See <code>{@link #bodyCfg}</code> also.</p>
8691 * @cfg {Object} bwrapCfg
8692 * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
8693 * of this Panel's {@link #bwrap} Element. See <code>{@link #bodyCfg}</code> also.</p>
8696 * @cfg {Object} tbarCfg
8697 * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
8698 * of this Panel's {@link #tbar} Element. See <code>{@link #bodyCfg}</code> also.</p>
8701 * @cfg {Object} bbarCfg
8702 * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
8703 * of this Panel's {@link #bbar} Element. See <code>{@link #bodyCfg}</code> also.</p>
8706 * @cfg {Object} footerCfg
8707 * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
8708 * of this Panel's {@link #footer} Element. See <code>{@link #bodyCfg}</code> also.</p>
8711 * @cfg {Boolean} closable
8712 * Panels themselves do not directly support being closed, but some Panel subclasses do (like
8713 * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}. Specify <code>true</code>
8714 * to enable closing in such situations. Defaults to <code>false</code>.
8717 * The Panel's footer {@link Ext.Element Element}. Read-only.
8718 * <p>This Element is used to house the Panel's <code>{@link #buttons}</code> or <code>{@link #fbar}</code>.</p>
8719 * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
8724 * @cfg {Mixed} applyTo
8725 * <p>The id of the node, a DOM node or an existing Element corresponding to a DIV that is already present in
8726 * the document that specifies some panel-specific structural markup. When <code>applyTo</code> is used,
8727 * constituent parts of the panel can be specified by CSS class name within the main element, and the panel
8728 * will automatically create those components from that markup. Any required components not specified in the
8729 * markup will be autogenerated if necessary.</p>
8730 * <p>The following class names are supported (baseCls will be replaced by {@link #baseCls}):</p>
8731 * <ul><li>baseCls + '-header'</li>
8732 * <li>baseCls + '-header-text'</li>
8733 * <li>baseCls + '-bwrap'</li>
8734 * <li>baseCls + '-tbar'</li>
8735 * <li>baseCls + '-body'</li>
8736 * <li>baseCls + '-bbar'</li>
8737 * <li>baseCls + '-footer'</li></ul>
8738 * <p>Using this config, a call to render() is not required. If applyTo is specified, any value passed for
8739 * {@link #renderTo} will be ignored and the target element's parent node will automatically be used as the
8740 * panel's container.</p>
8743 * @cfg {Object/Array} tbar
8744 * <p>The top toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
8745 * buttons/button configs to be added to the toolbar. Note that this is not available as a property after render.
8746 * To access the top toolbar after render, use {@link #getTopToolbar}.</p>
8747 * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
8748 * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
8749 * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
8750 * submission parameters are collected from the DOM tree.</p>
8753 * @cfg {Object/Array} bbar
8754 * <p>The bottom toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
8755 * buttons/button configs to be added to the toolbar. Note that this is not available as a property after render.
8756 * To access the bottom toolbar after render, use {@link #getBottomToolbar}.</p>
8757 * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
8758 * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
8759 * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
8760 * submission parameters are collected from the DOM tree.</p>
8762 /** @cfg {Object/Array} fbar
8763 * <p>A {@link Ext.Toolbar Toolbar} object, a Toolbar config, or an array of
8764 * {@link Ext.Button Button}s/{@link Ext.Button Button} configs, describing a {@link Ext.Toolbar Toolbar} to be rendered into this Panel's footer element.</p>
8765 * <p>After render, the <code>fbar</code> property will be an {@link Ext.Toolbar Toolbar} instance.</p>
8766 * <p>If <code>{@link #buttons}</code> are specified, they will supersede the <code>fbar</code> configuration property.</p>
8767 * The Panel's <code>{@link #buttonAlign}</code> configuration affects the layout of these items, for example:
8769 var w = new Ext.Window({
8772 bbar: new Ext.Toolbar({
8779 {@link #buttonAlign}: 'left', // anything but 'center' or 'right' and you can use '-', and '->'
8780 // to control the alignment of fbar items
8788 * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
8789 * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
8790 * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
8791 * submission parameters are collected from the DOM tree.</p>
8794 * @cfg {Boolean} header
8795 * <code>true</code> to create the Panel's header element explicitly, <code>false</code> to skip creating
8796 * it. If a <code>{@link #title}</code> is set the header will be created automatically, otherwise it will not.
8797 * If a <code>{@link #title}</code> is set but <code>header</code> is explicitly set to <code>false</code>, the header
8798 * will not be rendered.
8801 * @cfg {Boolean} footer
8802 * <code>true</code> to create the footer element explicitly, false to skip creating it. The footer
8803 * will be created automatically if <code>{@link #buttons}</code> or a <code>{@link #fbar}</code> have
8804 * been configured. See <code>{@link #bodyCfg}</code> for an example.
8807 * @cfg {String} title
8808 * The title text to be used as innerHTML (html tags are accepted) to display in the panel
8809 * <code>{@link #header}</code> (defaults to ''). When a <code>title</code> is specified the
8810 * <code>{@link #header}</code> element will automatically be created and displayed unless
8811 * {@link #header} is explicitly set to <code>false</code>. If you do not want to specify a
8812 * <code>title</code> at config time, but you may want one later, you must either specify a non-empty
8813 * <code>title</code> (a blank space ' ' will do) or <code>header:true</code> so that the container
8814 * element will get created.
8817 * @cfg {Array} buttons
8818 * <code>buttons</code> will be used as <code>{@link Ext.Container#items items}</code> for the toolbar in
8819 * the footer (<code>{@link #fbar}</code>). Typically the value of this configuration property will be
8820 * an array of {@link Ext.Button}s or {@link Ext.Button} configuration objects.
8821 * If an item is configured with <code>minWidth</code> or the Panel is configured with <code>minButtonWidth</code>,
8822 * that width will be applied to the item.
8825 * @cfg {Object/String/Function} autoLoad
8826 * A valid url spec according to the Updater {@link Ext.Updater#update} method.
8827 * If autoLoad is not null, the panel will attempt to load its contents
8828 * immediately upon render.<p>
8829 * The URL will become the default URL for this panel's {@link #body} element,
8830 * so it may be {@link Ext.Element#refresh refresh}ed at any time.</p>
8833 * @cfg {Boolean} frame
8834 * <code>false</code> by default to render with plain 1px square borders. <code>true</code> to render with
8835 * 9 elements, complete with custom rounded corners (also see {@link Ext.Element#boxWrap}).
8836 * <p>The template generated for each condition is depicted below:</p><pre><code>
8839 <div id="developer-specified-id-goes-here" class="x-panel">
8841 <div class="x-panel-header"><span class="x-panel-header-text">Title: (frame:false)</span></div>
8843 <div class="x-panel-bwrap">
8844 <div class="x-panel-body"><p>html value goes here</p></div>
8848 // frame = true (create 9 elements)
8849 <div id="developer-specified-id-goes-here" class="x-panel">
8850 <div class="x-panel-tl"><div class="x-panel-tr"><div class="x-panel-tc">
8851 <div class="x-panel-header"><span class="x-panel-header-text">Title: (frame:true)</span></div>
8852 </div></div></div>
8854 <div class="x-panel-bwrap">
8855 <div class="x-panel-ml"><div class="x-panel-mr"><div class="x-panel-mc">
8856 <div class="x-panel-body"><p>html value goes here</p></div>
8857 </div></div></div>
8859 <div class="x-panel-bl"><div class="x-panel-br"><div class="x-panel-bc"/>
8860 </div></div></div>
8865 * @cfg {Boolean} border
8866 * True to display the borders of the panel's body element, false to hide them (defaults to true). By default,
8867 * the border is a 2px wide inset border, but this can be further altered by setting {@link #bodyBorder} to false.
8870 * @cfg {Boolean} bodyBorder
8871 * True to display an interior border on the body element of the panel, false to hide it (defaults to true).
8872 * This only applies when {@link #border} == true. If border == true and bodyBorder == false, the border will display
8873 * as a 1px wide inset border, giving the entire body element an inset appearance.
8876 * @cfg {String/Object/Function} bodyCssClass
8877 * Additional css class selector to be applied to the {@link #body} element in the format expected by
8878 * {@link Ext.Element#addClass} (defaults to null). See {@link #bodyCfg}.
8881 * @cfg {String/Object/Function} bodyStyle
8882 * Custom CSS styles to be applied to the {@link #body} element in the format expected by
8883 * {@link Ext.Element#applyStyles} (defaults to null). See {@link #bodyCfg}.
8886 * @cfg {String} iconCls
8887 * The CSS class selector that specifies a background image to be used as the header icon (defaults to '').
8888 * <p>An example of specifying a custom icon class would be something like:
8890 // specify the property in the config for the class:
8894 // css class that specifies background image to be used as the icon image:
8895 .my-icon { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
8899 * @cfg {Boolean} collapsible
8900 * True to make the panel collapsible and have the expand/collapse toggle button automatically rendered into
8901 * the header tool button area, false to keep the panel statically sized with no button (defaults to false).
8904 * @cfg {Array} tools
8905 * An array of tool button configs to be added to the header tool area. When rendered, each tool is
8906 * stored as an {@link Ext.Element Element} referenced by a public property called <code><b></b>tools.<i><tool-type></i></code>
8907 * <p>Each tool config may contain the following properties:
8908 * <div class="mdetail-params"><ul>
8909 * <li><b>id</b> : String<div class="sub-desc"><b>Required.</b> The type
8910 * of tool to create. By default, this assigns a CSS class of the form <code>x-tool-<i><tool-type></i></code> to the
8911 * resulting tool Element. Ext provides CSS rules, and an icon sprite containing images for the tool types listed below.
8912 * The developer may implement custom tools by supplying alternate CSS rules and background images:
8914 * <div class="x-tool x-tool-toggle" style="float:left; margin-right:5;"> </div><div><code> toggle</code> (Created by default when {@link #collapsible} is <code>true</code>)</div>
8915 * <div class="x-tool x-tool-close" style="float:left; margin-right:5;"> </div><div><code> close</code></div>
8916 * <div class="x-tool x-tool-minimize" style="float:left; margin-right:5;"> </div><div><code> minimize</code></div>
8917 * <div class="x-tool x-tool-maximize" style="float:left; margin-right:5;"> </div><div><code> maximize</code></div>
8918 * <div class="x-tool x-tool-restore" style="float:left; margin-right:5;"> </div><div><code> restore</code></div>
8919 * <div class="x-tool x-tool-gear" style="float:left; margin-right:5;"> </div><div><code> gear</code></div>
8920 * <div class="x-tool x-tool-pin" style="float:left; margin-right:5;"> </div><div><code> pin</code></div>
8921 * <div class="x-tool x-tool-unpin" style="float:left; margin-right:5;"> </div><div><code> unpin</code></div>
8922 * <div class="x-tool x-tool-right" style="float:left; margin-right:5;"> </div><div><code> right</code></div>
8923 * <div class="x-tool x-tool-left" style="float:left; margin-right:5;"> </div><div><code> left</code></div>
8924 * <div class="x-tool x-tool-up" style="float:left; margin-right:5;"> </div><div><code> up</code></div>
8925 * <div class="x-tool x-tool-down" style="float:left; margin-right:5;"> </div><div><code> down</code></div>
8926 * <div class="x-tool x-tool-refresh" style="float:left; margin-right:5;"> </div><div><code> refresh</code></div>
8927 * <div class="x-tool x-tool-minus" style="float:left; margin-right:5;"> </div><div><code> minus</code></div>
8928 * <div class="x-tool x-tool-plus" style="float:left; margin-right:5;"> </div><div><code> plus</code></div>
8929 * <div class="x-tool x-tool-help" style="float:left; margin-right:5;"> </div><div><code> help</code></div>
8930 * <div class="x-tool x-tool-search" style="float:left; margin-right:5;"> </div><div><code> search</code></div>
8931 * <div class="x-tool x-tool-save" style="float:left; margin-right:5;"> </div><div><code> save</code></div>
8932 * <div class="x-tool x-tool-print" style="float:left; margin-right:5;"> </div><div><code> print</code></div>
8934 * <li><b>handler</b> : Function<div class="sub-desc"><b>Required.</b> The function to
8935 * call when clicked. Arguments passed are:<ul>
8936 * <li><b>event</b> : Ext.EventObject<div class="sub-desc">The click event.</div></li>
8937 * <li><b>toolEl</b> : Ext.Element<div class="sub-desc">The tool Element.</div></li>
8938 * <li><b>panel</b> : Ext.Panel<div class="sub-desc">The host Panel</div></li>
8939 * <li><b>tc</b> : Object<div class="sub-desc">The tool configuration object</div></li>
8941 * <li><b>stopEvent</b> : Boolean<div class="sub-desc">Defaults to true. Specify as false to allow click event to propagate.</div></li>
8942 * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the handler.</div></li>
8943 * <li><b>qtip</b> : String/Object<div class="sub-desc">A tip string, or
8944 * a config argument to {@link Ext.QuickTip#register}</div></li>
8945 * <li><b>hidden</b> : Boolean<div class="sub-desc">True to initially render hidden.</div></li>
8946 * <li><b>on</b> : Object<div class="sub-desc">A listener config object specifiying
8947 * event listeners in the format of an argument to {@link #addListener}</div></li>
8949 * <p>Note that, apart from the toggle tool which is provided when a panel is collapsible, these
8950 * tools only provide the visual button. Any required functionality must be provided by adding
8951 * handlers that implement the necessary behavior.</p>
8952 * <p>Example usage:</p>
8956 qtip: 'Refresh form Data',
8958 handler: function(event, toolEl, panel){
8965 handler: function(event, toolEl, panel){
8970 * <p>For the custom id of <code>'help'</code> define two relevant css classes with a link to
8971 * a 15x15 image:</p>
8973 .x-tool-help {background-image: url(images/help.png);}
8974 .x-tool-help-over {background-image: url(images/help_over.png);}
8975 // if using an image sprite:
8976 .x-tool-help {background-image: url(images/help.png) no-repeat 0 0;}
8977 .x-tool-help-over {background-position:-15px 0;}
8981 * @cfg {Ext.Template/Ext.XTemplate} toolTemplate
8982 * <p>A Template used to create {@link #tools} in the {@link #header} Element. Defaults to:</p><pre><code>
8983 new Ext.Template('<div class="x-tool x-tool-{id}">&#160;</div>')</code></pre>
8984 * <p>This may may be overridden to provide a custom DOM structure for tools based upon a more
8985 * complex XTemplate. The template's data is a single tool configuration object (Not the entire Array)
8986 * as specified in {@link #tools}. In the following example an <a> tag is used to provide a
8987 * visual indication when hovering over the tool:</p><pre><code>
8988 var win = new Ext.Window({
8991 href: '/MyPdfDoc.pdf'
8993 toolTemplate: new Ext.XTemplate(
8994 '<tpl if="id==\'download\'">',
8995 '<a class="x-tool x-tool-pdf" href="{href}"></a>',
8997 '<tpl if="id!=\'download\'">',
8998 '<div class="x-tool x-tool-{id}">&#160;</div>',
9005 * <p>Note that the CSS class 'x-tool-pdf' should have an associated style rule which provides an
9006 * appropriate background image, something like:</p>
9008 a.x-tool-pdf {background-image: url(../shared/extjs/images/pdf.gif)!important;}
9012 * @cfg {Boolean} hideCollapseTool
9013 * <code>true</code> to hide the expand/collapse toggle button when <code>{@link #collapsible} == true</code>,
9014 * <code>false</code> to display it (defaults to <code>false</code>).
9017 * @cfg {Boolean} titleCollapse
9018 * <code>true</code> to allow expanding and collapsing the panel (when <code>{@link #collapsible} = true</code>)
9019 * by clicking anywhere in the header bar, <code>false</code>) to allow it only by clicking to tool button
9020 * (defaults to <code>false</code>)). If this panel is a child item of a border layout also see the
9021 * {@link Ext.layout.BorderLayout.Region BorderLayout.Region}
9022 * <code>{@link Ext.layout.BorderLayout.Region#floatable floatable}</code> config option.
9026 * @cfg {Mixed} floating
9027 * <p>This property is used to configure the underlying {@link Ext.Layer}. Acceptable values for this
9028 * configuration property are:</p><div class="mdetail-params"><ul>
9029 * <li><b><code>false</code></b> : <b>Default.</b><div class="sub-desc">Display the panel inline where it is
9030 * rendered.</div></li>
9031 * <li><b><code>true</code></b> : <div class="sub-desc">Float the panel (absolute position it with automatic
9032 * shimming and shadow).<ul>
9033 * <div class="sub-desc">Setting floating to true will create an Ext.Layer for this panel and display the
9034 * panel at negative offsets so that it is hidden.</div>
9035 * <div class="sub-desc">Since the panel will be absolute positioned, the position must be set explicitly
9036 * <i>after</i> render (e.g., <code>myPanel.setPosition(100,100);</code>).</div>
9037 * <div class="sub-desc"><b>Note</b>: when floating a panel you should always assign a fixed width,
9038 * otherwise it will be auto width and will expand to fill to the right edge of the viewport.</div>
9040 * <li><b><code>{@link Ext.Layer object}</code></b> : <div class="sub-desc">The specified object will be used
9041 * as the configuration object for the {@link Ext.Layer} that will be created.</div></li>
9045 * @cfg {Boolean/String} shadow
9046 * <code>true</code> (or a valid Ext.Shadow {@link Ext.Shadow#mode} value) to display a shadow behind the
9047 * panel, <code>false</code> to display no shadow (defaults to <code>'sides'</code>). Note that this option
9048 * only applies when <code>{@link #floating} = true</code>.
9051 * @cfg {Number} shadowOffset
9052 * The number of pixels to offset the shadow if displayed (defaults to <code>4</code>). Note that this
9053 * option only applies when <code>{@link #floating} = true</code>.
9056 * @cfg {Boolean} shim
9057 * <code>false</code> to disable the iframe shim in browsers which need one (defaults to <code>true</code>).
9058 * Note that this option only applies when <code>{@link #floating} = true</code>.
9061 * @cfg {Object/Array} keys
9062 * A {@link Ext.KeyMap} config object (in the format expected by {@link Ext.KeyMap#addBinding}
9063 * used to assign custom key handling to this panel (defaults to <code>null</code>).
9066 * @cfg {Boolean/Object} draggable
9067 * <p><code>true</code> to enable dragging of this Panel (defaults to <code>false</code>).</p>
9068 * <p>For custom drag/drop implementations, an <b>Ext.Panel.DD</b> config could also be passed
9069 * in this config instead of <code>true</code>. Ext.Panel.DD is an internal, undocumented class which
9070 * moves a proxy Element around in place of the Panel's element, but provides no other behaviour
9071 * during dragging or on drop. It is a subclass of {@link Ext.dd.DragSource}, so behaviour may be
9072 * added by implementing the interface methods of {@link Ext.dd.DragDrop} e.g.:
9078 renderTo: Ext.getBody(),
9084 // Config option of Ext.Panel.DD class.
9085 // It's a floating Panel, so do not show a placeholder proxy in the original position.
9088 // Called for each mousemove event while dragging the DD object.
9089 onDrag : function(e){
9090 // Record the x,y position of the drag proxy so that we can
9091 // position the Panel at end of drag.
9092 var pel = this.proxy.getEl();
9093 this.x = pel.getLeft(true);
9094 this.y = pel.getTop(true);
9096 // Keep the Shadow aligned if there is one.
9097 var s = this.panel.getEl().shadow;
9099 s.realign(this.x, this.y, pel.getWidth(), pel.getHeight());
9103 // Called on the mouseup event.
9104 endDrag : function(e){
9105 this.panel.setPosition(this.x, this.y);
9112 * @cfg {Boolean} disabled
9113 * Render this panel disabled (default is <code>false</code>). An important note when using the disabled
9114 * config on panels is that IE will often fail to initialize the disabled mask element correectly if
9115 * the panel's layout has not yet completed by the time the Panel is disabled during the render process.
9116 * If you experience this issue, you may need to instead use the {@link #afterlayout} event to initialize
9117 * the disabled state:
9126 single: true // important, as many layouts can occur
9133 * @cfg {Boolean} autoHeight
9134 * <code>true</code> to use height:'auto', <code>false</code> to use fixed height (defaults to <code>false</code>).
9135 * <b>Note</b>: Setting <code>autoHeight: true</code> means that the browser will manage the panel's height
9136 * based on its contents, and that Ext will not manage it at all. If the panel is within a layout that
9137 * manages dimensions (<code>fit</code>, <code>border</code>, etc.) then setting <code>autoHeight: true</code>
9138 * can cause issues with scrolling and will not generally work as expected since the panel will take
9139 * on the height of its contents rather than the height required by the Ext layout.
9144 * @cfg {String} baseCls
9145 * The base CSS class to apply to this panel's element (defaults to <code>'x-panel'</code>).
9146 * <p>Another option available by default is to specify <code>'x-plain'</code> which strips all styling
9147 * except for required attributes for Ext layouts to function (e.g. overflow:hidden).
9148 * See <code>{@link #unstyled}</code> also.</p>
9150 baseCls : 'x-panel',
9152 * @cfg {String} collapsedCls
9153 * A CSS class to add to the panel's element after it has been collapsed (defaults to
9154 * <code>'x-panel-collapsed'</code>).
9156 collapsedCls : 'x-panel-collapsed',
9158 * @cfg {Boolean} maskDisabled
9159 * <code>true</code> to mask the panel when it is {@link #disabled}, <code>false</code> to not mask it (defaults
9160 * to <code>true</code>). Either way, the panel will always tell its contained elements to disable themselves
9161 * when it is disabled, but masking the panel can provide an additional visual cue that the panel is
9164 maskDisabled : true,
9166 * @cfg {Boolean} animCollapse
9167 * <code>true</code> to animate the transition when the panel is collapsed, <code>false</code> to skip the
9168 * animation (defaults to <code>true</code> if the {@link Ext.Fx} class is available, otherwise <code>false</code>).
9170 animCollapse : Ext.enableFx,
9172 * @cfg {Boolean} headerAsText
9173 * <code>true</code> to display the panel <code>{@link #title}</code> in the <code>{@link #header}</code>,
9174 * <code>false</code> to hide it (defaults to <code>true</code>).
9176 headerAsText : true,
9178 * @cfg {String} buttonAlign
9179 * The alignment of any {@link #buttons} added to this panel. Valid values are <code>'right'</code>,
9180 * <code>'left'</code> and <code>'center'</code> (defaults to <code>'right'</code>).
9182 buttonAlign : 'right',
9184 * @cfg {Boolean} collapsed
9185 * <code>true</code> to render the panel collapsed, <code>false</code> to render it expanded (defaults to
9186 * <code>false</code>).
9190 * @cfg {Boolean} collapseFirst
9191 * <code>true</code> to make sure the collapse/expand toggle button always renders first (to the left of)
9192 * any other tools in the panel's title bar, <code>false</code> to render it last (defaults to <code>true</code>).
9194 collapseFirst : true,
9196 * @cfg {Number} minButtonWidth
9197 * Minimum width in pixels of all {@link #buttons} in this panel (defaults to <code>75</code>)
9199 minButtonWidth : 75,
9201 * @cfg {Boolean} unstyled
9202 * Overrides the <code>{@link #baseCls}</code> setting to <code>{@link #baseCls} = 'x-plain'</code> which renders
9203 * the panel unstyled except for required attributes for Ext layouts to function (e.g. overflow:hidden).
9206 * @cfg {String} elements
9207 * A comma-delimited list of panel elements to initialize when the panel is rendered. Normally, this list will be
9208 * generated automatically based on the items added to the panel at config time, but sometimes it might be useful to
9209 * make sure a structural element is rendered even if not specified at config time (for example, you may want
9210 * to add a button or toolbar dynamically after the panel has been rendered). Adding those elements to this
9211 * list will allocate the required placeholders in the panel when it is rendered. Valid values are<div class="mdetail-params"><ul>
9212 * <li><code>header</code></li>
9213 * <li><code>tbar</code> (top bar)</li>
9214 * <li><code>body</code></li>
9215 * <li><code>bbar</code> (bottom bar)</li>
9216 * <li><code>footer</code></li>
9218 * Defaults to '<code>body</code>'.
9222 * @cfg {Boolean} preventBodyReset
9223 * Defaults to <code>false</code>. When set to <code>true</code>, an extra css class <code>'x-panel-normal'</code>
9224 * will be added to the panel's element, effectively applying css styles suggested by the W3C
9225 * (see http://www.w3.org/TR/CSS21/sample.html) to the Panel's <b>body</b> element (not the header,
9228 preventBodyReset : false,
9231 * @cfg {Number/String} padding
9232 * A shortcut for setting a padding style on the body element. The value can either be
9233 * a number to be applied to all sides, or a normal css string describing padding.
9234 * Defaults to <tt>undefined</tt>.
9239 /** @cfg {String} resizeEvent
9240 * The event to listen to for resizing in layouts. Defaults to <tt>'bodyresize'</tt>.
9242 resizeEvent: 'bodyresize',
9244 // protected - these could be used to customize the behavior of the window,
9245 // but changing them would not be useful without further mofifications and
9246 // could lead to unexpected or undesirable results.
9247 toolTarget : 'header',
9248 collapseEl : 'bwrap',
9252 // private, notify box this class will handle heights
9259 collapseDefaults : {
9264 initComponent : function(){
9265 Ext.Panel.superclass.initComponent.call(this);
9270 * Fires after the Panel has been resized.
9271 * @param {Ext.Panel} p the Panel which has been resized.
9272 * @param {Number} width The Panel body's new width.
9273 * @param {Number} height The Panel body's new height.
9277 * @event titlechange
9278 * Fires after the Panel title has been {@link #title set} or {@link #setTitle changed}.
9279 * @param {Ext.Panel} p the Panel which has had its title changed.
9280 * @param {String} The new title.
9285 * Fires after the Panel icon class has been {@link #iconCls set} or {@link #setIconClass changed}.
9286 * @param {Ext.Panel} p the Panel which has had its {@link #iconCls icon class} changed.
9287 * @param {String} The new icon class.
9288 * @param {String} The old icon class.
9293 * Fires after the Panel has been collapsed.
9294 * @param {Ext.Panel} p the Panel that has been collapsed.
9299 * Fires after the Panel has been expanded.
9300 * @param {Ext.Panel} p The Panel that has been expanded.
9304 * @event beforecollapse
9305 * Fires before the Panel is collapsed. A handler can return false to cancel the collapse.
9306 * @param {Ext.Panel} p the Panel being collapsed.
9307 * @param {Boolean} animate True if the collapse is animated, else false.
9311 * @event beforeexpand
9312 * Fires before the Panel is expanded. A handler can return false to cancel the expand.
9313 * @param {Ext.Panel} p The Panel being expanded.
9314 * @param {Boolean} animate True if the expand is animated, else false.
9318 * @event beforeclose
9319 * Fires before the Panel is closed. Note that Panels do not directly support being closed, but some
9320 * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel. This event only
9321 * applies to such subclasses.
9322 * A handler can return false to cancel the close.
9323 * @param {Ext.Panel} p The Panel being closed.
9328 * Fires after the Panel is closed. Note that Panels do not directly support being closed, but some
9329 * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.
9330 * @param {Ext.Panel} p The Panel that has been closed.
9335 * Fires after the Panel has been visually activated.
9336 * Note that Panels do not directly support being activated, but some Panel subclasses
9337 * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
9338 * activate and deactivate events under the control of the TabPanel.
9339 * @param {Ext.Panel} p The Panel that has been activated.
9344 * Fires after the Panel has been visually deactivated.
9345 * Note that Panels do not directly support being deactivated, but some Panel subclasses
9346 * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
9347 * activate and deactivate events under the control of the TabPanel.
9348 * @param {Ext.Panel} p The Panel that has been deactivated.
9354 this.baseCls = 'x-plain';
9361 this.elements += ',tbar';
9362 this.topToolbar = this.createToolbar(this.tbar);
9367 this.elements += ',bbar';
9368 this.bottomToolbar = this.createToolbar(this.bbar);
9372 if(this.header === true){
9373 this.elements += ',header';
9375 }else if(this.headerCfg || (this.title && this.header !== false)){
9376 this.elements += ',header';
9379 if(this.footerCfg || this.footer === true){
9380 this.elements += ',footer';
9385 this.fbar = this.buttons;
9386 delete this.buttons;
9389 this.createFbar(this.fbar);
9392 this.on('render', this.doAutoLoad, this, {delay:10});
9397 createFbar : function(fbar){
9398 var min = this.minButtonWidth;
9399 this.elements += ',footer';
9400 this.fbar = this.createToolbar(fbar, {
9401 buttonAlign: this.buttonAlign,
9402 toolbarCls: 'x-panel-fbar',
9403 enableOverflow: false,
9404 defaults: function(c){
9406 minWidth: c.minWidth || min
9410 //@compat addButton and buttons could possibly be removed
9413 * This Panel's Array of buttons as created from the <code>{@link #buttons}</code>
9414 * config property. Read only.
9418 this.fbar.items.each(function(c){
9419 c.minWidth = c.minWidth || this.minButtonWidth;
9421 this.buttons = this.fbar.items.items;
9425 createToolbar: function(tb, options){
9427 // Convert array to proper toolbar config
9428 if(Ext.isArray(tb)){
9433 result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
9434 this.toolbars.push(result);
9439 createElement : function(name, pnode){
9441 pnode.appendChild(this[name].dom);
9445 if(name === 'bwrap' || this.elements.indexOf(name) != -1){
9446 if(this[name+'Cfg']){
9447 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
9449 var el = document.createElement('div');
9450 el.className = this[name+'Cls'];
9451 this[name] = Ext.get(pnode.appendChild(el));
9453 if(this[name+'CssClass']){
9454 this[name].addClass(this[name+'CssClass']);
9456 if(this[name+'Style']){
9457 this[name].applyStyles(this[name+'Style']);
9463 onRender : function(ct, position){
9464 Ext.Panel.superclass.onRender.call(this, ct, position);
9465 this.createClasses();
9473 if(this.collapsible && !this.hideCollapseTool){
9474 this.tools = this.tools ? this.tools.slice(0) : [];
9475 this.tools[this.collapseFirst?'unshift':'push']({
9477 handler : this.toggleCollapse,
9484 this.elements += (this.header !== false) ? ',header' : '';
9488 el.addClass(this.baseCls);
9489 if(d.firstChild){ // existing markup
9490 this.header = el.down('.'+this.headerCls);
9491 this.bwrap = el.down('.'+this.bwrapCls);
9492 var cp = this.bwrap ? this.bwrap : el;
9493 this.tbar = cp.down('.'+this.tbarCls);
9494 this.body = cp.down('.'+this.bodyCls);
9495 this.bbar = cp.down('.'+this.bbarCls);
9496 this.footer = cp.down('.'+this.footerCls);
9497 this.fromMarkup = true;
9499 if (this.preventBodyReset === true) {
9500 el.addClass('x-panel-reset');
9503 el.addClass(this.cls);
9507 this.elements += ',footer';
9510 // This block allows for maximum flexibility and performance when using existing markup
9512 // framing requires special markup
9514 el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
9516 this.createElement('header', d.firstChild.firstChild.firstChild);
9517 this.createElement('bwrap', d);
9519 // append the mid and bottom frame to the bwrap
9520 bw = this.bwrap.dom;
9521 var ml = d.childNodes[1], bl = d.childNodes[2];
9525 var mc = bw.firstChild.firstChild.firstChild;
9526 this.createElement('tbar', mc);
9527 this.createElement('body', mc);
9528 this.createElement('bbar', mc);
9529 this.createElement('footer', bw.lastChild.firstChild.firstChild);
9532 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
9535 * Store a reference to this element so:
9536 * a) We aren't looking it up all the time
9537 * b) The last element is reported incorrectly when using a loadmask
9539 this.ft = Ext.get(this.bwrap.dom.lastChild);
9540 this.mc = Ext.get(mc);
9542 this.createElement('header', d);
9543 this.createElement('bwrap', d);
9545 // append the mid and bottom frame to the bwrap
9546 bw = this.bwrap.dom;
9547 this.createElement('tbar', bw);
9548 this.createElement('body', bw);
9549 this.createElement('bbar', bw);
9550 this.createElement('footer', bw);
9553 this.body.addClass(this.bodyCls + '-noheader');
9555 this.tbar.addClass(this.tbarCls + '-noheader');
9560 if(Ext.isDefined(this.padding)){
9561 this.body.setStyle('padding', this.body.addUnits(this.padding));
9564 if(this.border === false){
9565 this.el.addClass(this.baseCls + '-noborder');
9566 this.body.addClass(this.bodyCls + '-noborder');
9568 this.header.addClass(this.headerCls + '-noborder');
9571 this.footer.addClass(this.footerCls + '-noborder');
9574 this.tbar.addClass(this.tbarCls + '-noborder');
9577 this.bbar.addClass(this.bbarCls + '-noborder');
9581 if(this.bodyBorder === false){
9582 this.body.addClass(this.bodyCls + '-noborder');
9585 this.bwrap.enableDisplayMode('block');
9588 this.header.unselectable();
9590 // for tools, we need to wrap any existing header markup
9591 if(this.headerAsText){
9592 this.header.dom.innerHTML =
9593 '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
9596 this.setIconClass(this.iconCls);
9602 this.makeFloating(this.floating);
9605 if(this.collapsible && this.titleCollapse && this.header){
9606 this.mon(this.header, 'click', this.toggleCollapse, this);
9607 this.header.setStyle('cursor', 'pointer');
9610 this.addTool.apply(this, ts);
9615 this.footer.addClass('x-panel-btns');
9616 this.fbar.ownerCt = this;
9617 this.fbar.render(this.footer);
9618 this.footer.createChild({cls:'x-clear'});
9620 if(this.tbar && this.topToolbar){
9621 this.topToolbar.ownerCt = this;
9622 this.topToolbar.render(this.tbar);
9624 if(this.bbar && this.bottomToolbar){
9625 this.bottomToolbar.ownerCt = this;
9626 this.bottomToolbar.render(this.bbar);
9631 * Sets the CSS class that provides the icon image for this panel. This method will replace any existing
9632 * icon class if one has already been set and fire the {@link #iconchange} event after completion.
9633 * @param {String} cls The new CSS class name
9635 setIconClass : function(cls){
9636 var old = this.iconCls;
9638 if(this.rendered && this.header){
9640 this.header.addClass('x-panel-icon');
9641 this.header.replaceClass(old, this.iconCls);
9643 var hd = this.header,
9644 img = hd.child('img.x-panel-inline-icon');
9646 Ext.fly(img).replaceClass(old, this.iconCls);
9648 Ext.DomHelper.insertBefore(hd.dom.firstChild, {
9649 tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
9654 this.fireEvent('iconchange', this, cls, old);
9658 makeFloating : function(cfg){
9659 this.floating = true;
9660 this.el = new Ext.Layer(Ext.apply({}, cfg, {
9661 shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
9662 shadowOffset: this.shadowOffset,
9664 shim: this.shim === false ? false : undefined
9669 * Returns the {@link Ext.Toolbar toolbar} from the top (<code>{@link #tbar}</code>) section of the panel.
9670 * @return {Ext.Toolbar} The toolbar
9672 getTopToolbar : function(){
9673 return this.topToolbar;
9677 * Returns the {@link Ext.Toolbar toolbar} from the bottom (<code>{@link #bbar}</code>) section of the panel.
9678 * @return {Ext.Toolbar} The toolbar
9680 getBottomToolbar : function(){
9681 return this.bottomToolbar;
9685 * Adds a button to this panel. Note that this method must be called prior to rendering. The preferred
9686 * approach is to add buttons via the {@link #buttons} config.
9687 * @param {String/Object} config A valid {@link Ext.Button} config. A string will become the text for a default
9688 * button config, an object will be treated as a button config object.
9689 * @param {Function} handler The function to be called on button {@link Ext.Button#click}
9690 * @param {Object} scope The scope (<code>this</code> reference) in which the button handler function is executed. Defaults to the Button.
9691 * @return {Ext.Button} The button that was added
9693 addButton : function(config, handler, scope){
9695 this.createFbar([]);
9698 if(Ext.isString(config)){
9699 config = {text: config};
9701 config = Ext.apply({
9706 return this.fbar.add(config);
9710 addTool : function(){
9715 Ext.each(arguments, function(arg){
9716 this.tools.push(arg)
9720 // nowhere to render tools!
9721 if(!this[this.toolTarget]){
9724 if(!this.toolTemplate){
9725 // initialize the global tool template on first use
9726 var tt = new Ext.Template(
9727 '<div class="x-tool x-tool-{id}"> </div>'
9729 tt.disableFormats = true;
9731 Ext.Panel.prototype.toolTemplate = tt;
9733 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9735 if(!this.tools[tc.id]){
9736 var overCls = 'x-tool-'+tc.id+'-over';
9737 var t = this.toolTemplate.insertFirst(this[this.toolTarget], tc, true);
9738 this.tools[tc.id] = t;
9739 t.enableDisplayMode('block');
9740 this.mon(t, 'click', this.createToolHandler(t, tc, overCls, this));
9748 if(Ext.isObject(tc.qtip)){
9749 Ext.QuickTips.register(Ext.apply({
9753 t.dom.qtip = tc.qtip;
9756 t.addClassOnOver(overCls);
9761 onLayout : function(shallow, force){
9762 Ext.Panel.superclass.onLayout.apply(this, arguments);
9763 if(this.hasLayout && this.toolbars.length > 0){
9764 Ext.each(this.toolbars, function(tb){
9765 tb.doLayout(undefined, force);
9771 syncHeight : function(){
9772 var h = this.toolbarHeight,
9774 lsh = this.lastSize.height,
9777 if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
9782 if(h != this.getToolbarHeight()){
9783 h = Math.max(0, this.adjustBodyHeight(lsh - this.getFrameHeight()));
9786 this.toolbarHeight = this.getToolbarHeight();
9787 this.onBodyResize(sz.width, sz.height);
9792 onShow : function(){
9794 return this.el.show();
9796 Ext.Panel.superclass.onShow.call(this);
9800 onHide : function(){
9802 return this.el.hide();
9804 Ext.Panel.superclass.onHide.call(this);
9808 createToolHandler : function(t, tc, overCls, panel){
9810 t.removeClass(overCls);
9811 if(tc.stopEvent !== false){
9815 tc.handler.call(tc.scope || t, e, t, panel, tc);
9821 afterRender : function(){
9822 if(this.floating && !this.hidden){
9826 this.setTitle(this.title);
9828 Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
9829 if (this.collapsed) {
9830 this.collapsed = false;
9831 this.collapse(false);
9837 getKeyMap : function(){
9839 this.keyMap = new Ext.KeyMap(this.el, this.keys);
9845 initEvents : function(){
9850 this.initDraggable();
9852 if(this.toolbars.length > 0){
9853 Ext.each(this.toolbars, function(tb){
9857 afterlayout: this.syncHeight,
9858 remove: this.syncHeight
9867 initDraggable : function(){
9869 * <p>If this Panel is configured {@link #draggable}, this property will contain
9870 * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.</p>
9871 * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource}
9872 * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
9873 * @type Ext.dd.DragSource.
9876 this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
9880 beforeEffect : function(anim){
9882 this.el.beforeAction();
9885 this.el.addClass('x-panel-animated');
9890 afterEffect : function(anim){
9893 this.el.removeClass('x-panel-animated');
9897 // private - wraps up an animation param with internal callbacks
9898 createEffect : function(a, cb, scope){
9906 }else if(!a.callback){
9908 }else { // wrap it up
9909 o.callback = function(){
9911 Ext.callback(a.callback, a.scope);
9914 return Ext.applyIf(o, a);
9918 * Collapses the panel body so that it becomes hidden. Fires the {@link #beforecollapse} event which will
9919 * cancel the collapse action if it returns false.
9920 * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
9921 * {@link #animCollapse} panel config)
9922 * @return {Ext.Panel} this
9924 collapse : function(animate){
9925 if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
9928 var doAnim = animate === true || (animate !== false && this.animCollapse);
9929 this.beforeEffect(doAnim);
9930 this.onCollapse(doAnim, animate);
9935 onCollapse : function(doAnim, animArg){
9937 this[this.collapseEl].slideOut(this.slideAnchor,
9938 Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
9939 this.collapseDefaults));
9941 this[this.collapseEl].hide();
9942 this.afterCollapse(false);
9947 afterCollapse : function(anim){
9948 this.collapsed = true;
9949 this.el.addClass(this.collapsedCls);
9950 this.afterEffect(anim);
9951 this.fireEvent('collapse', this);
9955 * Expands the panel body so that it becomes visible. Fires the {@link #beforeexpand} event which will
9956 * cancel the expand action if it returns false.
9957 * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
9958 * {@link #animCollapse} panel config)
9959 * @return {Ext.Panel} this
9961 expand : function(animate){
9962 if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
9965 var doAnim = animate === true || (animate !== false && this.animCollapse);
9966 this.el.removeClass(this.collapsedCls);
9967 this.beforeEffect(doAnim);
9968 this.onExpand(doAnim, animate);
9973 onExpand : function(doAnim, animArg){
9975 this[this.collapseEl].slideIn(this.slideAnchor,
9976 Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
9977 this.expandDefaults));
9979 this[this.collapseEl].show();
9980 this.afterExpand(false);
9985 afterExpand : function(anim){
9986 this.collapsed = false;
9987 this.afterEffect(anim);
9988 if (this.deferLayout) {
9989 delete this.deferLayout;
9990 this.doLayout(true);
9992 this.fireEvent('expand', this);
9996 * Shortcut for performing an {@link #expand} or {@link #collapse} based on the current state of the panel.
9997 * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
9998 * {@link #animCollapse} panel config)
9999 * @return {Ext.Panel} this
10001 toggleCollapse : function(animate){
10002 this[this.collapsed ? 'expand' : 'collapse'](animate);
10007 onDisable : function(){
10008 if(this.rendered && this.maskDisabled){
10011 Ext.Panel.superclass.onDisable.call(this);
10015 onEnable : function(){
10016 if(this.rendered && this.maskDisabled){
10019 Ext.Panel.superclass.onEnable.call(this);
10023 onResize : function(w, h){
10024 if(Ext.isDefined(w) || Ext.isDefined(h)){
10025 if(!this.collapsed){
10026 // First, set the the Panel's body width.
10027 // If we have auto-widthed it, get the resulting full offset width so we can size the Toolbars to match
10028 // The Toolbars must not buffer this resize operation because we need to know their heights.
10030 if(Ext.isNumber(w)){
10031 this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
10032 } else if (w == 'auto') {
10033 w = this.body.setWidth('auto').dom.offsetWidth;
10035 w = this.body.dom.offsetWidth;
10039 this.tbar.setWidth(w);
10040 if(this.topToolbar){
10041 this.topToolbar.setSize(w);
10045 this.bbar.setWidth(w);
10046 if(this.bottomToolbar){
10047 this.bottomToolbar.setSize(w);
10048 // The bbar does not move on resize without this.
10050 this.bbar.setStyle('position', 'static');
10051 this.bbar.setStyle('position', '');
10056 this.footer.setWidth(w);
10058 this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
10062 // At this point, the Toolbars must be layed out for getFrameHeight to find a result.
10063 if(Ext.isNumber(h)){
10064 h = Math.max(0, this.adjustBodyHeight(h - this.getFrameHeight()));
10065 this.body.setHeight(h);
10066 }else if(h == 'auto'){
10067 this.body.setHeight(h);
10070 if(this.disabled && this.el._mask){
10071 this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
10074 // Adds an event to set the correct height afterExpand. This accounts for the deferHeight flag in panel
10075 this.queuedBodySize = {width: w, height: h};
10076 if(!this.queuedExpand && this.allowQueuedExpand !== false){
10077 this.queuedExpand = true;
10078 this.on('expand', function(){
10079 delete this.queuedExpand;
10080 this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
10081 }, this, {single:true});
10084 this.onBodyResize(w, h);
10087 Ext.Panel.superclass.onResize.call(this);
10091 onBodyResize: function(w, h){
10092 this.fireEvent('bodyresize', this, w, h);
10096 getToolbarHeight: function(){
10099 Ext.each(this.toolbars, function(tb){
10100 h += tb.getHeight();
10107 adjustBodyHeight : function(h){
10112 adjustBodyWidth : function(w){
10117 onPosition : function(){
10122 * Returns the width in pixels of the framing elements of this panel (not including the body width). To
10123 * retrieve the body width see {@link #getInnerWidth}.
10124 * @return {Number} The frame width
10126 getFrameWidth : function(){
10127 var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
10130 var l = this.bwrap.dom.firstChild;
10131 w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
10132 w += this.mc.getFrameWidth('lr');
10138 * Returns the height in pixels of the framing elements of this panel (including any top and bottom bars and
10139 * header and footer elements, but not including the body height). To retrieve the body height see {@link #getInnerHeight}.
10140 * @return {Number} The frame height
10142 getFrameHeight : function(){
10143 var h = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
10144 h += (this.tbar ? this.tbar.getHeight() : 0) +
10145 (this.bbar ? this.bbar.getHeight() : 0);
10148 h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
10150 h += (this.header ? this.header.getHeight() : 0) +
10151 (this.footer ? this.footer.getHeight() : 0);
10157 * Returns the width in pixels of the body element (not including the width of any framing elements).
10158 * For the frame width see {@link #getFrameWidth}.
10159 * @return {Number} The body width
10161 getInnerWidth : function(){
10162 return this.getSize().width - this.getFrameWidth();
10166 * Returns the height in pixels of the body element (not including the height of any framing elements).
10167 * For the frame height see {@link #getFrameHeight}.
10168 * @return {Number} The body height
10170 getInnerHeight : function(){
10171 return this.getSize().height - this.getFrameHeight();
10175 syncShadow : function(){
10177 this.el.sync(true);
10182 getLayoutTarget : function(){
10187 getContentTarget : function(){
10192 * <p>Sets the title text for the panel and optionally the {@link #iconCls icon class}.</p>
10193 * <p>In order to be able to set the title, a header element must have been created
10194 * for the Panel. This is triggered either by configuring the Panel with a non-blank <code>{@link #title}</code>,
10195 * or configuring it with <code><b>{@link #header}: true</b></code>.</p>
10196 * @param {String} title The title text to set
10197 * @param {String} iconCls (optional) {@link #iconCls iconCls} A user-defined CSS class that provides the icon image for this panel
10199 setTitle : function(title, iconCls){
10200 this.title = title;
10201 if(this.header && this.headerAsText){
10202 this.header.child('span').update(title);
10205 this.setIconClass(iconCls);
10207 this.fireEvent('titlechange', this, title);
10212 * Get the {@link Ext.Updater} for this panel. Enables you to perform Ajax updates of this panel's body.
10213 * @return {Ext.Updater} The Updater
10215 getUpdater : function(){
10216 return this.body.getUpdater();
10220 * Loads this content panel immediately with content returned from an XHR call.
10221 * @param {Object/String/Function} config A config object containing any of the following options:
10224 url: 'your-url.php',
10225 params: {param1: 'foo', param2: 'bar'}, // or a URL encoded string
10226 callback: yourFunction,
10227 scope: yourObject, // optional scope for the callback
10230 text: 'Loading...',
10235 * The only required property is url. The optional properties nocache, text and scripts
10236 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their
10237 * associated property on this panel Updater instance.
10238 * @return {Ext.Panel} this
10241 var um = this.body.getUpdater();
10242 um.update.apply(um, arguments);
10247 beforeDestroy : function(){
10248 Ext.Panel.superclass.beforeDestroy.call(this);
10250 this.header.removeAllListeners();
10253 for(var k in this.tools){
10254 Ext.destroy(this.tools[k]);
10257 if(this.toolbars.length > 0){
10258 Ext.each(this.toolbars, function(tb){
10259 tb.un('afterlayout', this.syncHeight, this);
10260 tb.un('remove', this.syncHeight, this);
10263 if(Ext.isArray(this.buttons)){
10264 while(this.buttons.length) {
10265 Ext.destroy(this.buttons[0]);
10295 createClasses : function(){
10296 this.headerCls = this.baseCls + '-header';
10297 this.headerTextCls = this.baseCls + '-header-text';
10298 this.bwrapCls = this.baseCls + '-bwrap';
10299 this.tbarCls = this.baseCls + '-tbar';
10300 this.bodyCls = this.baseCls + '-body';
10301 this.bbarCls = this.baseCls + '-bbar';
10302 this.footerCls = this.baseCls + '-footer';
10306 createGhost : function(cls, useShim, appendTo){
10307 var el = document.createElement('div');
10308 el.className = 'x-panel-ghost ' + (cls ? cls : '');
10310 el.appendChild(this.el.dom.firstChild.cloneNode(true));
10312 Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
10313 el.style.width = this.el.dom.offsetWidth + 'px';;
10315 this.container.dom.appendChild(el);
10317 Ext.getDom(appendTo).appendChild(el);
10319 if(useShim !== false && this.el.useShim !== false){
10320 var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
10324 return new Ext.Element(el);
10329 doAutoLoad : function(){
10330 var u = this.body.getUpdater();
10332 u.setRenderer(this.renderer);
10334 u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
10338 * Retrieve a tool by id.
10339 * @param {String} id
10340 * @return {Object} tool
10342 getTool : function(id) {
10343 return this.tools[id];
10347 * @cfg {String} autoEl @hide
10350 Ext.reg('panel', Ext.Panel);
10352 * @class Ext.Editor
10353 * @extends Ext.Component
10354 * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
10356 * Create a new Editor
10357 * @param {Object} config The config object
10360 Ext.Editor = function(field, config){
10362 this.field = Ext.create(field.field, 'textfield');
10363 config = Ext.apply({}, field); // copy so we don't disturb original config
10364 delete config.field;
10366 this.field = field;
10368 Ext.Editor.superclass.constructor.call(this, config);
10371 Ext.extend(Ext.Editor, Ext.Component, {
10373 * @cfg {Ext.form.Field} field
10374 * The Field object (or descendant) or config object for field
10377 * @cfg {Boolean} allowBlur
10378 * True to {@link #completeEdit complete the editing process} if in edit mode when the
10379 * field is blurred. Defaults to <tt>false</tt>.
10382 * @cfg {Boolean/String} autoSize
10383 * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only,
10384 * or "height" to adopt the height only, "none" to always use the field dimensions. (defaults to false)
10387 * @cfg {Boolean} revertInvalid
10388 * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
10389 * validation fails (defaults to true)
10392 * @cfg {Boolean} ignoreNoChange
10393 * True to skip the edit completion process (no save, no events fired) if the user completes an edit and
10394 * the value has not changed (defaults to false). Applies only to string values - edits for other data types
10395 * will never be ignored.
10398 * @cfg {Boolean} hideEl
10399 * False to keep the bound element visible while the editor is displayed (defaults to true)
10402 * @cfg {Mixed} value
10403 * The data value of the underlying field (defaults to "")
10407 * @cfg {String} alignment
10408 * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?").
10412 * @cfg {Array} offsets
10413 * The offsets to use when aligning (see {@link Ext.Element#alignTo} for more details. Defaults to <tt>[0, 0]</tt>.
10417 * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
10418 * for bottom-right shadow (defaults to "frame")
10422 * @cfg {Boolean} constrain True to constrain the editor to the viewport
10426 * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true)
10428 swallowKeys : true,
10430 * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed. Defaults to <tt>true</tt>.
10432 completeOnEnter : true,
10434 * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed. Defaults to <tt>true</tt>.
10436 cancelOnEsc : true,
10438 * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
10442 initComponent : function(){
10443 Ext.Editor.superclass.initComponent.call(this);
10446 * @event beforestartedit
10447 * Fires when editing is initiated, but before the value changes. Editing can be canceled by returning
10448 * false from the handler of this event.
10449 * @param {Editor} this
10450 * @param {Ext.Element} boundEl The underlying element bound to this editor
10451 * @param {Mixed} value The field value being set
10456 * Fires when this editor is displayed
10457 * @param {Ext.Element} boundEl The underlying element bound to this editor
10458 * @param {Mixed} value The starting field value
10462 * @event beforecomplete
10463 * Fires after a change has been made to the field, but before the change is reflected in the underlying
10464 * field. Saving the change to the field can be canceled by returning false from the handler of this event.
10465 * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
10466 * event will not fire since no edit actually occurred.
10467 * @param {Editor} this
10468 * @param {Mixed} value The current field value
10469 * @param {Mixed} startValue The original field value
10474 * Fires after editing is complete and any changed value has been written to the underlying field.
10475 * @param {Editor} this
10476 * @param {Mixed} value The current field value
10477 * @param {Mixed} startValue The original field value
10481 * @event canceledit
10482 * Fires after editing has been canceled and the editor's value has been reset.
10483 * @param {Editor} this
10484 * @param {Mixed} value The user-entered field value that was discarded
10485 * @param {Mixed} startValue The original field value that was set back into the editor after cancel
10489 * @event specialkey
10490 * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed. You can check
10491 * {@link Ext.EventObject#getKey} to determine which key was pressed.
10492 * @param {Ext.form.Field} this
10493 * @param {Ext.EventObject} e The event object
10500 onRender : function(ct, position){
10501 this.el = new Ext.Layer({
10502 shadow: this.shadow,
10506 shadowOffset: this.shadowOffset || 4,
10508 constrain: this.constrain
10511 this.el.setZIndex(this.zIndex);
10513 this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
10514 if(this.field.msgTarget != 'title'){
10515 this.field.msgTarget = 'qtip';
10517 this.field.inEditor = true;
10518 this.mon(this.field, {
10521 specialkey: this.onSpecialKey
10523 if(this.field.grow){
10524 this.mon(this.field, "autosize", this.el.sync, this.el, {delay:1});
10526 this.field.render(this.el).show();
10527 this.field.getEl().dom.name = '';
10528 if(this.swallowKeys){
10529 this.field.el.swallowEvent([
10530 'keypress', // *** Opera
10531 'keydown' // *** all other browsers
10537 onSpecialKey : function(field, e){
10538 var key = e.getKey(),
10539 complete = this.completeOnEnter && key == e.ENTER,
10540 cancel = this.cancelOnEsc && key == e.ESC;
10541 if(complete || cancel){
10544 this.completeEdit();
10548 if(field.triggerBlur){
10549 field.triggerBlur();
10552 this.fireEvent('specialkey', field, e);
10556 * Starts the editing process and shows the editor.
10557 * @param {Mixed} el The element to edit
10558 * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
10559 * to the innerHTML of el.
10561 startEdit : function(el, value){
10563 this.completeEdit();
10565 this.boundEl = Ext.get(el);
10566 var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
10567 if(!this.rendered){
10568 this.render(this.parentEl || document.body);
10570 if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
10571 this.startValue = v;
10572 this.field.reset();
10573 this.field.setValue(v);
10574 this.realign(true);
10575 this.editing = true;
10581 doAutoSize : function(){
10583 var sz = this.boundEl.getSize(),
10584 fs = this.field.getSize();
10586 switch(this.autoSize){
10588 this.setSize(sz.width, fs.height);
10591 this.setSize(fs.width, sz.height);
10594 this.setSize(fs.width, fs.height);
10597 this.setSize(sz.width, sz.height);
10603 * Sets the height and width of this editor.
10604 * @param {Number} width The new width
10605 * @param {Number} height The new height
10607 setSize : function(w, h){
10608 delete this.field.lastSize;
10609 this.field.setSize(w, h);
10611 if(Ext.isGecko2 || Ext.isOpera){
10612 // prevent layer scrollbars
10613 this.el.setSize(w, h);
10620 * Realigns the editor to the bound field based on the current alignment config value.
10621 * @param {Boolean} autoSize (optional) True to size the field to the dimensions of the bound element.
10623 realign : function(autoSize){
10624 if(autoSize === true){
10627 this.el.alignTo(this.boundEl, this.alignment, this.offsets);
10631 * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
10632 * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
10634 completeEdit : function(remainVisible){
10638 var v = this.getValue();
10639 if(!this.field.isValid()){
10640 if(this.revertInvalid !== false){
10641 this.cancelEdit(remainVisible);
10645 if(String(v) === String(this.startValue) && this.ignoreNoChange){
10646 this.hideEdit(remainVisible);
10649 if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
10650 v = this.getValue();
10651 if(this.updateEl && this.boundEl){
10652 this.boundEl.update(v);
10654 this.hideEdit(remainVisible);
10655 this.fireEvent("complete", this, v, this.startValue);
10660 onShow : function(){
10662 if(this.hideEl !== false){
10663 this.boundEl.hide();
10665 this.field.show().focus(false, true);
10666 this.fireEvent("startedit", this.boundEl, this.startValue);
10670 * Cancels the editing process and hides the editor without persisting any changes. The field value will be
10671 * reverted to the original starting value.
10672 * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
10673 * cancel (defaults to false)
10675 cancelEdit : function(remainVisible){
10677 var v = this.getValue();
10678 this.setValue(this.startValue);
10679 this.hideEdit(remainVisible);
10680 this.fireEvent("canceledit", this, v, this.startValue);
10685 hideEdit: function(remainVisible){
10686 if(remainVisible !== true){
10687 this.editing = false;
10693 onBlur : function(){
10694 // selectSameEditor flag allows the same editor to be started without onBlur firing on itself
10695 if(this.allowBlur !== true && this.editing && this.selectSameEditor !== true){
10696 this.completeEdit();
10701 onHide : function(){
10703 this.completeEdit();
10707 if(this.field.collapse){
10708 this.field.collapse();
10711 if(this.hideEl !== false){
10712 this.boundEl.show();
10717 * Sets the data value of the editor
10718 * @param {Mixed} value Any valid value supported by the underlying field
10720 setValue : function(v){
10721 this.field.setValue(v);
10725 * Gets the data value of the editor
10726 * @return {Mixed} The data value
10728 getValue : function(){
10729 return this.field.getValue();
10732 beforeDestroy : function(){
10733 Ext.destroyMembers(this, 'field');
10735 delete this.parentEl;
10736 delete this.boundEl;
10739 Ext.reg('editor', Ext.Editor);
10741 * @class Ext.ColorPalette
10742 * @extends Ext.Component
10743 * Simple color palette class for choosing colors. The palette can be rendered to any container.<br />
10744 * Here's an example of typical usage:
10746 var cp = new Ext.ColorPalette({value:'993300'}); // initial selected color
10747 cp.render('my-div');
10749 cp.on('select', function(palette, selColor){
10750 // do something with selColor
10754 * Create a new ColorPalette
10755 * @param {Object} config The config object
10756 * @xtype colorpalette
10758 Ext.ColorPalette = Ext.extend(Ext.Component, {
10760 * @cfg {String} tpl An existing XTemplate instance to be used in place of the default template for rendering the component.
10763 * @cfg {String} itemCls
10764 * The CSS class to apply to the containing element (defaults to 'x-color-palette')
10766 itemCls : 'x-color-palette',
10768 * @cfg {String} value
10769 * The initial color to highlight (should be a valid 6-digit color hex code without the # symbol). Note that
10770 * the hex codes are case-sensitive.
10774 * @cfg {String} clickEvent
10775 * The DOM event that will cause a color to be selected. This can be any valid event name (dblclick, contextmenu).
10776 * Defaults to <tt>'click'</tt>.
10778 clickEvent :'click',
10780 ctype : 'Ext.ColorPalette',
10783 * @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the {@link #select} event
10785 allowReselect : false,
10788 * <p>An array of 6-digit color hex code strings (without the # symbol). This array can contain any number
10789 * of colors, and each hex code should be unique. The width of the palette is controlled via CSS by adjusting
10790 * the width property of the 'x-color-palette' class (or assigning a custom class), so you can balance the number
10791 * of colors with the width setting until the box is symmetrical.</p>
10792 * <p>You can override individual colors if needed:</p>
10794 var cp = new Ext.ColorPalette();
10795 cp.colors[0] = 'FF0000'; // change the first box to red
10798 Or you can provide a custom array of your own for complete control:
10800 var cp = new Ext.ColorPalette();
10801 cp.colors = ['000000', '993300', '333300'];
10806 '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
10807 '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
10808 'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
10809 'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
10810 'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
10814 * @cfg {Function} handler
10815 * Optional. A function that will handle the select event of this palette.
10816 * The handler is passed the following parameters:<div class="mdetail-params"><ul>
10817 * <li><code>palette</code> : ColorPalette<div class="sub-desc">The {@link #palette Ext.ColorPalette}.</div></li>
10818 * <li><code>color</code> : String<div class="sub-desc">The 6-digit color hex code (without the # symbol).</div></li>
10822 * @cfg {Object} scope
10823 * The scope (<tt><b>this</b></tt> reference) in which the <code>{@link #handler}</code>
10824 * function will be called. Defaults to this ColorPalette instance.
10828 initComponent : function(){
10829 Ext.ColorPalette.superclass.initComponent.call(this);
10833 * Fires when a color is selected
10834 * @param {ColorPalette} this
10835 * @param {String} color The 6-digit color hex code (without the # symbol)
10841 this.on('select', this.handler, this.scope, true);
10846 onRender : function(container, position){
10851 Ext.ColorPalette.superclass.onRender.call(this, container, position);
10852 var t = this.tpl || new Ext.XTemplate(
10853 '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on"> </span></em></a></tpl>'
10855 t.overwrite(this.el, this.colors);
10856 this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
10857 if(this.clickEvent != 'click'){
10858 this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
10863 afterRender : function(){
10864 Ext.ColorPalette.superclass.afterRender.call(this);
10866 var s = this.value;
10873 handleClick : function(e, t){
10874 e.preventDefault();
10875 if(!this.disabled){
10876 var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
10877 this.select(c.toUpperCase());
10882 * Selects the specified color in the palette (fires the {@link #select} event)
10883 * @param {String} color A valid 6-digit color hex code (# will be stripped if included)
10885 select : function(color){
10886 color = color.replace('#', '');
10887 if(color != this.value || this.allowReselect){
10890 el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
10892 el.child('a.color-'+color).addClass('x-color-palette-sel');
10893 this.value = color;
10894 this.fireEvent('select', this, color);
10899 * @cfg {String} autoEl @hide
10902 Ext.reg('colorpalette', Ext.ColorPalette);
10904 * @class Ext.DatePicker
10905 * @extends Ext.Component
10906 * <p>A popup date picker. This class is used by the {@link Ext.form.DateField DateField} class
10907 * to allow browsing and selection of valid dates.</p>
10908 * <p>All the string values documented below may be overridden by including an Ext locale file in
10911 * Create a new DatePicker
10912 * @param {Object} config The config object
10913 * @xtype datepicker
10915 Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
10917 * @cfg {String} todayText
10918 * The text to display on the button that selects the current date (defaults to <code>'Today'</code>)
10920 todayText : 'Today',
10922 * @cfg {String} okText
10923 * The text to display on the ok button (defaults to <code>' OK '</code> to give the user extra clicking room)
10925 okText : ' OK ',
10927 * @cfg {String} cancelText
10928 * The text to display on the cancel button (defaults to <code>'Cancel'</code>)
10930 cancelText : 'Cancel',
10932 * @cfg {Function} handler
10933 * Optional. A function that will handle the select event of this picker.
10934 * The handler is passed the following parameters:<div class="mdetail-params"><ul>
10935 * <li><code>picker</code> : DatePicker<div class="sub-desc">This DatePicker.</div></li>
10936 * <li><code>date</code> : Date<div class="sub-desc">The selected date.</div></li>
10940 * @cfg {Object} scope
10941 * The scope (<code><b>this</b></code> reference) in which the <code>{@link #handler}</code>
10942 * function will be called. Defaults to this DatePicker instance.
10945 * @cfg {String} todayTip
10946 * A string used to format the message for displaying in a tooltip over the button that
10947 * selects the current date. Defaults to <code>'{0} (Spacebar)'</code> where
10948 * the <code>{0}</code> token is replaced by today's date.
10950 todayTip : '{0} (Spacebar)',
10952 * @cfg {String} minText
10953 * The error text to display if the minDate validation fails (defaults to <code>'This date is before the minimum date'</code>)
10955 minText : 'This date is before the minimum date',
10957 * @cfg {String} maxText
10958 * The error text to display if the maxDate validation fails (defaults to <code>'This date is after the maximum date'</code>)
10960 maxText : 'This date is after the maximum date',
10962 * @cfg {String} format
10963 * The default date format string which can be overriden for localization support. The format must be
10964 * valid according to {@link Date#parseDate} (defaults to <code>'m/d/y'</code>).
10968 * @cfg {String} disabledDaysText
10969 * The tooltip to display when the date falls on a disabled day (defaults to <code>'Disabled'</code>)
10971 disabledDaysText : 'Disabled',
10973 * @cfg {String} disabledDatesText
10974 * The tooltip text to display when the date falls on a disabled date (defaults to <code>'Disabled'</code>)
10976 disabledDatesText : 'Disabled',
10978 * @cfg {Array} monthNames
10979 * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
10981 monthNames : Date.monthNames,
10983 * @cfg {Array} dayNames
10984 * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
10986 dayNames : Date.dayNames,
10988 * @cfg {String} nextText
10989 * The next month navigation button tooltip (defaults to <code>'Next Month (Control+Right)'</code>)
10991 nextText : 'Next Month (Control+Right)',
10993 * @cfg {String} prevText
10994 * The previous month navigation button tooltip (defaults to <code>'Previous Month (Control+Left)'</code>)
10996 prevText : 'Previous Month (Control+Left)',
10998 * @cfg {String} monthYearText
10999 * The header month selector tooltip (defaults to <code>'Choose a month (Control+Up/Down to move years)'</code>)
11001 monthYearText : 'Choose a month (Control+Up/Down to move years)',
11003 * @cfg {Number} startDay
11004 * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
11008 * @cfg {Boolean} showToday
11009 * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar
11010 * that selects the current date (defaults to <code>true</code>).
11014 * @cfg {Date} minDate
11015 * Minimum allowable date (JavaScript date object, defaults to null)
11018 * @cfg {Date} maxDate
11019 * Maximum allowable date (JavaScript date object, defaults to null)
11022 * @cfg {Array} disabledDays
11023 * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
11026 * @cfg {RegExp} disabledDatesRE
11027 * JavaScript regular expression used to disable a pattern of dates (defaults to null). The {@link #disabledDates}
11028 * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the
11029 * disabledDates value.
11032 * @cfg {Array} disabledDates
11033 * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular
11034 * expression so they are very powerful. Some examples:
11036 * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>
11037 * <li>['03/08', '09/16'] would disable those days for every year</li>
11038 * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>
11039 * <li>['03/../2006'] would disable every day in March 2006</li>
11040 * <li>['^03'] would disable every day in every March</li>
11042 * Note that the format of the dates included in the array should exactly match the {@link #format} config.
11043 * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to
11044 * escape the dot when restricting dates. For example: ['03\\.08\\.03'].
11048 // Set by other components to stop the picker focus being updated when the value changes.
11049 focusOnSelect: true,
11052 initComponent : function(){
11053 Ext.DatePicker.superclass.initComponent.call(this);
11055 this.value = this.value ?
11056 this.value.clearTime(true) : new Date().clearTime();
11061 * Fires when a date is selected
11062 * @param {DatePicker} this DatePicker
11063 * @param {Date} date The selected date
11069 this.on('select', this.handler, this.scope || this);
11072 this.initDisabledDays();
11076 initDisabledDays : function(){
11077 if(!this.disabledDatesRE && this.disabledDates){
11078 var dd = this.disabledDates,
11079 len = dd.length - 1,
11082 Ext.each(dd, function(d, i){
11083 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
11088 this.disabledDatesRE = new RegExp(re + ')');
11093 * Replaces any existing disabled dates with new values and refreshes the DatePicker.
11094 * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config
11095 * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.
11097 setDisabledDates : function(dd){
11098 if(Ext.isArray(dd)){
11099 this.disabledDates = dd;
11100 this.disabledDatesRE = null;
11102 this.disabledDatesRE = dd;
11104 this.initDisabledDays();
11105 this.update(this.value, true);
11109 * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.
11110 * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config
11111 * for details on supported values.
11113 setDisabledDays : function(dd){
11114 this.disabledDays = dd;
11115 this.update(this.value, true);
11119 * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
11120 * @param {Date} value The minimum date that can be selected
11122 setMinDate : function(dt){
11124 this.update(this.value, true);
11128 * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
11129 * @param {Date} value The maximum date that can be selected
11131 setMaxDate : function(dt){
11133 this.update(this.value, true);
11137 * Sets the value of the date field
11138 * @param {Date} value The date to set
11140 setValue : function(value){
11141 this.value = value.clearTime(true);
11142 this.update(this.value);
11146 * Gets the current selected value of the date field
11147 * @return {Date} The selected date
11149 getValue : function(){
11154 focus : function(){
11155 this.update(this.activeDate);
11159 onEnable: function(initial){
11160 Ext.DatePicker.superclass.onEnable.call(this);
11161 this.doDisabled(false);
11162 this.update(initial ? this.value : this.activeDate);
11170 onDisable : function(){
11171 Ext.DatePicker.superclass.onDisable.call(this);
11172 this.doDisabled(true);
11173 if(Ext.isIE && !Ext.isIE8){
11174 /* Really strange problem in IE6/7, when disabled, have to explicitly
11175 * repaint each of the nodes to get them to display correctly, simply
11176 * calling repaint on the main element doesn't appear to be enough.
11178 Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
11179 Ext.fly(el).repaint();
11185 doDisabled : function(disabled){
11186 this.keyNav.setDisabled(disabled);
11187 this.prevRepeater.setDisabled(disabled);
11188 this.nextRepeater.setDisabled(disabled);
11189 if(this.showToday){
11190 this.todayKeyListener.setDisabled(disabled);
11191 this.todayBtn.setDisabled(disabled);
11196 onRender : function(container, position){
11198 '<table cellspacing="0">',
11199 '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'"> </a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'"> </a></td></tr>',
11200 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
11201 dn = this.dayNames,
11203 for(i = 0; i < 7; i++){
11204 var d = this.startDay+i;
11208 m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
11210 m[m.length] = '</tr></thead><tbody><tr>';
11211 for(i = 0; i < 42; i++) {
11212 if(i % 7 === 0 && i !== 0){
11213 m[m.length] = '</tr><tr>';
11215 m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
11217 m.push('</tr></tbody></table></td></tr>',
11218 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
11219 '</table><div class="x-date-mp"></div>');
11221 var el = document.createElement('div');
11222 el.className = 'x-date-picker';
11223 el.innerHTML = m.join('');
11225 container.dom.insertBefore(el, position);
11227 this.el = Ext.get(el);
11228 this.eventEl = Ext.get(el.firstChild);
11230 this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
11231 handler: this.showPrevMonth,
11233 preventDefault:true,
11237 this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
11238 handler: this.showNextMonth,
11240 preventDefault:true,
11244 this.monthPicker = this.el.down('div.x-date-mp');
11245 this.monthPicker.enableDisplayMode('block');
11247 this.keyNav = new Ext.KeyNav(this.eventEl, {
11248 'left' : function(e){
11250 this.showPrevMonth();
11252 this.update(this.activeDate.add('d', -1));
11256 'right' : function(e){
11258 this.showNextMonth();
11260 this.update(this.activeDate.add('d', 1));
11264 'up' : function(e){
11266 this.showNextYear();
11268 this.update(this.activeDate.add('d', -7));
11272 'down' : function(e){
11274 this.showPrevYear();
11276 this.update(this.activeDate.add('d', 7));
11280 'pageUp' : function(e){
11281 this.showNextMonth();
11284 'pageDown' : function(e){
11285 this.showPrevMonth();
11288 'enter' : function(e){
11289 e.stopPropagation();
11296 this.el.unselectable();
11298 this.cells = this.el.select('table.x-date-inner tbody td');
11299 this.textNodes = this.el.query('table.x-date-inner tbody span');
11301 this.mbtn = new Ext.Button({
11303 tooltip: this.monthYearText,
11304 renderTo: this.el.child('td.x-date-middle', true)
11306 this.mbtn.el.child('em').addClass('x-btn-arrow');
11308 if(this.showToday){
11309 this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday, this);
11310 var today = (new Date()).dateFormat(this.format);
11311 this.todayBtn = new Ext.Button({
11312 renderTo: this.el.child('td.x-date-bottom', true),
11313 text: String.format(this.todayText, today),
11314 tooltip: String.format(this.todayTip, today),
11315 handler: this.selectToday,
11319 this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
11320 this.mon(this.eventEl, 'click', this.handleDateClick, this, {delegate: 'a.x-date-date'});
11321 this.mon(this.mbtn, 'click', this.showMonthPicker, this);
11322 this.onEnable(true);
11326 createMonthPicker : function(){
11327 if(!this.monthPicker.dom.firstChild){
11328 var buf = ['<table border="0" cellspacing="0">'];
11329 for(var i = 0; i < 6; i++){
11331 '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
11332 '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
11334 '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
11335 '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
11339 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
11341 '</button><button type="button" class="x-date-mp-cancel">',
11343 '</button></td></tr>',
11346 this.monthPicker.update(buf.join(''));
11348 this.mon(this.monthPicker, 'click', this.onMonthClick, this);
11349 this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
11351 this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
11352 this.mpYears = this.monthPicker.select('td.x-date-mp-year');
11354 this.mpMonths.each(function(m, a, i){
11357 m.dom.xmonth = 5 + Math.round(i * 0.5);
11359 m.dom.xmonth = Math.round((i-1) * 0.5);
11366 showMonthPicker : function(){
11367 if(!this.disabled){
11368 this.createMonthPicker();
11369 var size = this.el.getSize();
11370 this.monthPicker.setSize(size);
11371 this.monthPicker.child('table').setSize(size);
11373 this.mpSelMonth = (this.activeDate || this.value).getMonth();
11374 this.updateMPMonth(this.mpSelMonth);
11375 this.mpSelYear = (this.activeDate || this.value).getFullYear();
11376 this.updateMPYear(this.mpSelYear);
11378 this.monthPicker.slideIn('t', {duration:0.2});
11383 updateMPYear : function(y){
11385 var ys = this.mpYears.elements;
11386 for(var i = 1; i <= 10; i++){
11387 var td = ys[i-1], y2;
11389 y2 = y + Math.round(i * 0.5);
11390 td.firstChild.innerHTML = y2;
11393 y2 = y - (5-Math.round(i * 0.5));
11394 td.firstChild.innerHTML = y2;
11397 this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
11402 updateMPMonth : function(sm){
11403 this.mpMonths.each(function(m, a, i){
11404 m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
11409 selectMPMonth : function(m){
11414 onMonthClick : function(e, t){
11416 var el = new Ext.Element(t), pn;
11417 if(el.is('button.x-date-mp-cancel')){
11418 this.hideMonthPicker();
11420 else if(el.is('button.x-date-mp-ok')){
11421 var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
11422 if(d.getMonth() != this.mpSelMonth){
11423 // 'fix' the JS rolling date conversion if needed
11424 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
11427 this.hideMonthPicker();
11429 else if((pn = el.up('td.x-date-mp-month', 2))){
11430 this.mpMonths.removeClass('x-date-mp-sel');
11431 pn.addClass('x-date-mp-sel');
11432 this.mpSelMonth = pn.dom.xmonth;
11434 else if((pn = el.up('td.x-date-mp-year', 2))){
11435 this.mpYears.removeClass('x-date-mp-sel');
11436 pn.addClass('x-date-mp-sel');
11437 this.mpSelYear = pn.dom.xyear;
11439 else if(el.is('a.x-date-mp-prev')){
11440 this.updateMPYear(this.mpyear-10);
11442 else if(el.is('a.x-date-mp-next')){
11443 this.updateMPYear(this.mpyear+10);
11448 onMonthDblClick : function(e, t){
11450 var el = new Ext.Element(t), pn;
11451 if((pn = el.up('td.x-date-mp-month', 2))){
11452 this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
11453 this.hideMonthPicker();
11455 else if((pn = el.up('td.x-date-mp-year', 2))){
11456 this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
11457 this.hideMonthPicker();
11462 hideMonthPicker : function(disableAnim){
11463 if(this.monthPicker){
11464 if(disableAnim === true){
11465 this.monthPicker.hide();
11467 this.monthPicker.slideOut('t', {duration:0.2});
11473 showPrevMonth : function(e){
11474 this.update(this.activeDate.add('mo', -1));
11478 showNextMonth : function(e){
11479 this.update(this.activeDate.add('mo', 1));
11483 showPrevYear : function(){
11484 this.update(this.activeDate.add('y', -1));
11488 showNextYear : function(){
11489 this.update(this.activeDate.add('y', 1));
11493 handleMouseWheel : function(e){
11495 if(!this.disabled){
11496 var delta = e.getWheelDelta();
11498 this.showPrevMonth();
11499 } else if(delta < 0){
11500 this.showNextMonth();
11506 handleDateClick : function(e, t){
11508 if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
11509 this.cancelFocus = this.focusOnSelect === false;
11510 this.setValue(new Date(t.dateValue));
11511 delete this.cancelFocus;
11512 this.fireEvent('select', this, this.value);
11517 selectToday : function(){
11518 if(this.todayBtn && !this.todayBtn.disabled){
11519 this.setValue(new Date().clearTime());
11520 this.fireEvent('select', this, this.value);
11525 update : function(date, forceRefresh){
11527 var vd = this.activeDate, vis = this.isVisible();
11528 this.activeDate = date;
11529 if(!forceRefresh && vd && this.el){
11530 var t = date.getTime();
11531 if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
11532 this.cells.removeClass('x-date-selected');
11533 this.cells.each(function(c){
11534 if(c.dom.firstChild.dateValue == t){
11535 c.addClass('x-date-selected');
11536 if(vis && !this.cancelFocus){
11537 Ext.fly(c.dom.firstChild).focus(50);
11545 var days = date.getDaysInMonth(),
11546 firstOfMonth = date.getFirstDateOfMonth(),
11547 startingPos = firstOfMonth.getDay()-this.startDay;
11549 if(startingPos < 0){
11552 days += startingPos;
11554 var pm = date.add('mo', -1),
11555 prevStart = pm.getDaysInMonth()-startingPos,
11556 cells = this.cells.elements,
11557 textEls = this.textNodes,
11558 // convert everything to numbers so it's fast
11560 d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime(),
11561 today = new Date().clearTime().getTime(),
11562 sel = date.clearTime(true).getTime(),
11563 min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
11564 max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
11565 ddMatch = this.disabledDatesRE,
11566 ddText = this.disabledDatesText,
11567 ddays = this.disabledDays ? this.disabledDays.join('') : false,
11568 ddaysText = this.disabledDaysText,
11569 format = this.format;
11571 if(this.showToday){
11572 var td = new Date().clearTime(),
11573 disable = (td < min || td > max ||
11574 (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
11575 (ddays && ddays.indexOf(td.getDay()) != -1));
11577 if(!this.disabled){
11578 this.todayBtn.setDisabled(disable);
11579 this.todayKeyListener[disable ? 'disable' : 'enable']();
11583 var setCellClass = function(cal, cell){
11585 var t = d.getTime();
11586 cell.firstChild.dateValue = t;
11588 cell.className += ' x-date-today';
11589 cell.title = cal.todayText;
11592 cell.className += ' x-date-selected';
11594 Ext.fly(cell.firstChild).focus(50);
11599 cell.className = ' x-date-disabled';
11600 cell.title = cal.minText;
11604 cell.className = ' x-date-disabled';
11605 cell.title = cal.maxText;
11609 if(ddays.indexOf(d.getDay()) != -1){
11610 cell.title = ddaysText;
11611 cell.className = ' x-date-disabled';
11614 if(ddMatch && format){
11615 var fvalue = d.dateFormat(format);
11616 if(ddMatch.test(fvalue)){
11617 cell.title = ddText.replace('%0', fvalue);
11618 cell.className = ' x-date-disabled';
11624 for(; i < startingPos; i++) {
11625 textEls[i].innerHTML = (++prevStart);
11626 d.setDate(d.getDate()+1);
11627 cells[i].className = 'x-date-prevday';
11628 setCellClass(this, cells[i]);
11630 for(; i < days; i++){
11631 var intDay = i - startingPos + 1;
11632 textEls[i].innerHTML = (intDay);
11633 d.setDate(d.getDate()+1);
11634 cells[i].className = 'x-date-active';
11635 setCellClass(this, cells[i]);
11638 for(; i < 42; i++) {
11639 textEls[i].innerHTML = (++extraDays);
11640 d.setDate(d.getDate()+1);
11641 cells[i].className = 'x-date-nextday';
11642 setCellClass(this, cells[i]);
11645 this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
11647 if(!this.internalRender){
11648 var main = this.el.dom.firstChild,
11649 w = main.offsetWidth;
11650 this.el.setWidth(w + this.el.getBorderWidth('lr'));
11651 Ext.fly(main).setWidth(w);
11652 this.internalRender = true;
11653 // opera does not respect the auto grow header center column
11654 // then, after it gets a width opera refuses to recalculate
11655 // without a second pass
11656 if(Ext.isOpera && !this.secondPass){
11657 main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
11658 this.secondPass = true;
11659 this.update.defer(10, this, [date]);
11666 beforeDestroy : function() {
11678 delete this.textNodes;
11679 delete this.cells.elements;
11684 * @cfg {String} autoEl @hide
11688 Ext.reg('datepicker', Ext.DatePicker);
11690 * @class Ext.LoadMask
11691 * A simple utility class for generically masking elements while loading data. If the {@link #store}
11692 * config option is specified, the masking will be automatically synchronized with the store's loading
11693 * process and the mask element will be cached for reuse. For all other elements, this mask will replace the
11694 * element's Updater load indicator and will be destroyed after the initial load.
11695 * <p>Example usage:</p>
11698 var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
11702 * Create a new LoadMask
11703 * @param {Mixed} el The element or DOM node, or its id
11704 * @param {Object} config The config object
11706 Ext.LoadMask = function(el, config){
11707 this.el = Ext.get(el);
11708 Ext.apply(this, config);
11712 beforeload: this.onBeforeLoad,
11714 exception: this.onLoad
11716 this.removeMask = Ext.value(this.removeMask, false);
11718 var um = this.el.getUpdater();
11719 um.showLoadIndicator = false; // disable the default indicator
11722 beforeupdate: this.onBeforeLoad,
11723 update: this.onLoad,
11724 failure: this.onLoad
11726 this.removeMask = Ext.value(this.removeMask, true);
11730 Ext.LoadMask.prototype = {
11732 * @cfg {Ext.data.Store} store
11733 * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and
11734 * hidden on either load sucess, or load fail.
11737 * @cfg {Boolean} removeMask
11738 * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
11739 * False to persist the mask element reference for multiple uses (e.g., for paged data widgets). Defaults to false.
11742 * @cfg {String} msg
11743 * The text to display in a centered loading message box (defaults to 'Loading...')
11745 msg : 'Loading...',
11747 * @cfg {String} msgCls
11748 * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
11750 msgCls : 'x-mask-loading',
11753 * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
11759 * Disables the mask to prevent it from being displayed
11761 disable : function(){
11762 this.disabled = true;
11766 * Enables the mask so that it can be displayed
11768 enable : function(){
11769 this.disabled = false;
11773 onLoad : function(){
11774 this.el.unmask(this.removeMask);
11778 onBeforeLoad : function(){
11779 if(!this.disabled){
11780 this.el.mask(this.msg, this.msgCls);
11785 * Show this LoadMask over the configured Element.
11788 this.onBeforeLoad();
11792 * Hide this LoadMask.
11799 destroy : function(){
11801 this.store.un('beforeload', this.onBeforeLoad, this);
11802 this.store.un('load', this.onLoad, this);
11803 this.store.un('exception', this.onLoad, this);
11805 var um = this.el.getUpdater();
11806 um.un('beforeupdate', this.onBeforeLoad, this);
11807 um.un('update', this.onLoad, this);
11808 um.un('failure', this.onLoad, this);
11812 * @class Ext.Slider
\r
11813 * @extends Ext.BoxComponent
\r
11814 * Slider which supports vertical or horizontal orientation, keyboard adjustments,
\r
11815 * configurable snapping, axis clicking and animation. Can be added as an item to
\r
11816 * any container. Example usage:
\r
11819 renderTo: Ext.getBody(),
\r
11828 Ext.Slider = Ext.extend(Ext.BoxComponent, {
\r
11830 * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.
\r
11833 * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.
\r
11837 * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.
\r
11841 * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.
\r
11845 * @cfg {Number/Boolean} decimalPrecision.
\r
11846 * <p>The number of decimal places to which to round the Slider's value. Defaults to 0.</p>
\r
11847 * <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>
\r
11849 decimalPrecision: 0,
\r
11851 * @cfg {Number} keyIncrement How many units to change the Slider when adjusting with keyboard navigation. Defaults to 1. If the increment config is larger, it will be used instead.
\r
11855 * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.
\r
11859 clickRange: [5,15],
\r
11861 * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true
\r
11863 clickToChange : true,
\r
11865 * @cfg {Boolean} animate Turn on or off animation. Defaults to true
\r
11870 * True while the thumb is in a drag operation
\r
11875 // private override
\r
11876 initComponent : function(){
\r
11877 if(!Ext.isDefined(this.value)){
\r
11878 this.value = this.minValue;
\r
11880 Ext.Slider.superclass.initComponent.call(this);
\r
11881 this.keyIncrement = Math.max(this.increment, this.keyIncrement);
\r
11884 * @event beforechange
\r
11885 * Fires before the slider value is changed. By returning false from an event handler,
\r
11886 * you can cancel the event and prevent the slider from changing.
\r
11887 * @param {Ext.Slider} slider The slider
\r
11888 * @param {Number} newValue The new value which the slider is being changed to.
\r
11889 * @param {Number} oldValue The old value which the slider was previously.
\r
11894 * Fires when the slider value is changed.
\r
11895 * @param {Ext.Slider} slider The slider
\r
11896 * @param {Number} newValue The new value which the slider has been changed to.
\r
11900 * @event changecomplete
\r
11901 * Fires when the slider value is changed by the user and any drag operations have completed.
\r
11902 * @param {Ext.Slider} slider The slider
\r
11903 * @param {Number} newValue The new value which the slider has been changed to.
\r
11905 'changecomplete',
\r
11907 * @event dragstart
\r
11908 * Fires after a drag operation has started.
\r
11909 * @param {Ext.Slider} slider The slider
\r
11910 * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
\r
11915 * Fires continuously during the drag operation while the mouse is moving.
\r
11916 * @param {Ext.Slider} slider The slider
\r
11917 * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
\r
11922 * Fires after the drag operation has completed.
\r
11923 * @param {Ext.Slider} slider The slider
\r
11924 * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
\r
11929 if(this.vertical){
\r
11930 Ext.apply(this, Ext.Slider.Vertical);
\r
11934 // private override
\r
11935 onRender : function(){
\r
11937 cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
\r
11938 cn:{cls:'x-slider-end',cn:{cls:'x-slider-inner',cn:[{cls:'x-slider-thumb'},{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]}}
\r
11940 Ext.Slider.superclass.onRender.apply(this, arguments);
\r
11941 this.endEl = this.el.first();
\r
11942 this.innerEl = this.endEl.first();
\r
11943 this.thumb = this.innerEl.first();
\r
11944 this.halfThumb = (this.vertical ? this.thumb.getHeight() : this.thumb.getWidth())/2;
\r
11945 this.focusEl = this.thumb.next();
\r
11946 this.initEvents();
\r
11949 // private override
\r
11950 initEvents : function(){
\r
11951 this.thumb.addClassOnOver('x-slider-thumb-over');
\r
11952 this.mon(this.el, {
\r
11954 mousedown: this.onMouseDown,
\r
11955 keydown: this.onKeyDown
\r
11958 this.focusEl.swallowEvent("click", true);
\r
11960 this.tracker = new Ext.dd.DragTracker({
\r
11961 onBeforeStart: this.onBeforeDragStart.createDelegate(this),
\r
11962 onStart: this.onDragStart.createDelegate(this),
\r
11963 onDrag: this.onDrag.createDelegate(this),
\r
11964 onEnd: this.onDragEnd.createDelegate(this),
\r
11968 this.tracker.initEl(this.thumb);
\r
11971 // private override
\r
11972 onMouseDown : function(e){
\r
11973 if(this.disabled){
\r
11976 if(this.clickToChange && e.target != this.thumb.dom){
\r
11977 var local = this.innerEl.translatePoints(e.getXY());
\r
11978 this.onClickChange(local);
\r
11984 onClickChange : function(local){
\r
11985 if(local.top > this.clickRange[0] && local.top < this.clickRange[1]){
\r
11986 this.setValue(Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
\r
11991 onKeyDown : function(e){
\r
11992 if(this.disabled){e.preventDefault();return;}
\r
11993 var k = e.getKey();
\r
11999 this.setValue(this.maxValue, undefined, true);
\r
12001 this.setValue(this.value+this.keyIncrement, undefined, true);
\r
12008 this.setValue(this.minValue, undefined, true);
\r
12010 this.setValue(this.value-this.keyIncrement, undefined, true);
\r
12014 e.preventDefault();
\r
12019 doSnap : function(value){
\r
12020 if(!(this.increment && value)){
\r
12023 var newValue = value,
\r
12024 inc = this.increment,
\r
12030 }else if(m * 2 < -inc){
\r
12034 return newValue.constrain(this.minValue, this.maxValue);
\r
12038 afterRender : function(){
\r
12039 Ext.Slider.superclass.afterRender.apply(this, arguments);
\r
12040 if(this.value !== undefined){
\r
12041 var v = this.normalizeValue(this.value);
\r
12042 if(v !== this.value){
\r
12043 delete this.value;
\r
12044 this.setValue(v, false);
\r
12046 this.moveThumb(this.translateValue(v), false);
\r
12052 getRatio : function(){
\r
12053 var w = this.innerEl.getWidth(),
\r
12054 v = this.maxValue - this.minValue;
\r
12055 return v == 0 ? w : (w/v);
\r
12059 normalizeValue : function(v){
\r
12060 v = this.doSnap(v);
\r
12061 v = Ext.util.Format.round(v, this.decimalPrecision);
\r
12062 v = v.constrain(this.minValue, this.maxValue);
\r
12067 * Sets the minimum value for the slider instance. If the current value is less than the
\r
12068 * minimum value, the current value will be changed.
\r
12069 * @param {Number} val The new minimum value
\r
12071 setMinValue : function(val){
\r
12072 this.minValue = val;
\r
12073 this.syncThumb();
\r
12074 if(this.value < val){
\r
12075 this.setValue(val);
\r
12080 * Sets the maximum value for the slider instance. If the current value is more than the
\r
12081 * maximum value, the current value will be changed.
\r
12082 * @param {Number} val The new maximum value
\r
12084 setMaxValue : function(val){
\r
12085 this.maxValue = val;
\r
12086 this.syncThumb();
\r
12087 if(this.value > val){
\r
12088 this.setValue(val);
\r
12093 * Programmatically sets the value of the Slider. Ensures that the value is constrained within
\r
12094 * the minValue and maxValue.
\r
12095 * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)
\r
12096 * @param {Boolean} animate Turn on or off animation, defaults to true
\r
12098 setValue : function(v, animate, changeComplete){
\r
12099 v = this.normalizeValue(v);
\r
12100 if(v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false){
\r
12102 this.moveThumb(this.translateValue(v), animate !== false);
\r
12103 this.fireEvent('change', this, v);
\r
12104 if(changeComplete){
\r
12105 this.fireEvent('changecomplete', this, v);
\r
12111 translateValue : function(v){
\r
12112 var ratio = this.getRatio();
\r
12113 return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
\r
12116 reverseValue : function(pos){
\r
12117 var ratio = this.getRatio();
\r
12118 return (pos + (this.minValue * ratio)) / ratio;
\r
12122 moveThumb: function(v, animate){
\r
12123 if(!animate || this.animate === false){
\r
12124 this.thumb.setLeft(v);
\r
12126 this.thumb.shift({left: v, stopFx: true, duration:.35});
\r
12131 focus : function(){
\r
12132 this.focusEl.focus(10);
\r
12136 onBeforeDragStart : function(e){
\r
12137 return !this.disabled;
\r
12141 onDragStart: function(e){
\r
12142 this.thumb.addClass('x-slider-thumb-drag');
\r
12143 this.dragging = true;
\r
12144 this.dragStartValue = this.value;
\r
12145 this.fireEvent('dragstart', this, e);
\r
12149 onDrag: function(e){
\r
12150 var pos = this.innerEl.translatePoints(this.tracker.getXY());
\r
12151 this.setValue(Ext.util.Format.round(this.reverseValue(pos.left), this.decimalPrecision), false);
\r
12152 this.fireEvent('drag', this, e);
\r
12156 onDragEnd: function(e){
\r
12157 this.thumb.removeClass('x-slider-thumb-drag');
\r
12158 this.dragging = false;
\r
12159 this.fireEvent('dragend', this, e);
\r
12160 if(this.dragStartValue != this.value){
\r
12161 this.fireEvent('changecomplete', this, this.value);
\r
12166 onResize : function(w, h){
\r
12167 this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
\r
12168 this.syncThumb();
\r
12169 Ext.Slider.superclass.onResize.apply(this, arguments);
\r
12173 onDisable: function(){
\r
12174 Ext.Slider.superclass.onDisable.call(this);
\r
12175 this.thumb.addClass(this.disabledClass);
\r
12177 //IE breaks when using overflow visible and opacity other than 1.
\r
12178 //Create a place holder for the thumb and display it.
\r
12179 var xy = this.thumb.getXY();
\r
12180 this.thumb.hide();
\r
12181 this.innerEl.addClass(this.disabledClass).dom.disabled = true;
\r
12182 if (!this.thumbHolder){
\r
12183 this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});
\r
12185 this.thumbHolder.show().setXY(xy);
\r
12190 onEnable: function(){
\r
12191 Ext.Slider.superclass.onEnable.call(this);
\r
12192 this.thumb.removeClass(this.disabledClass);
\r
12194 this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
\r
12195 if(this.thumbHolder){
\r
12196 this.thumbHolder.hide();
\r
12198 this.thumb.show();
\r
12199 this.syncThumb();
\r
12204 * Synchronizes the thumb position to the proper proportion of the total component width based
\r
12205 * on the current slider {@link #value}. This will be called automatically when the Slider
\r
12206 * is resized by a layout, but if it is rendered auto width, this method can be called from
\r
12207 * another resize handler to sync the Slider if necessary.
\r
12209 syncThumb : function(){
\r
12210 if(this.rendered){
\r
12211 this.moveThumb(this.translateValue(this.value));
\r
12216 * Returns the current value of the slider
\r
12217 * @return {Number} The current value of the slider
\r
12219 getValue : function(){
\r
12220 return this.value;
\r
12224 beforeDestroy : function(){
\r
12225 Ext.destroyMembers(this, 'endEl', 'innerEl', 'thumb', 'halfThumb', 'focusEl', 'tracker', 'thumbHolder');
\r
12226 Ext.Slider.superclass.beforeDestroy.call(this);
\r
12229 Ext.reg('slider', Ext.Slider);
\r
12231 // private class to support vertical sliders
\r
12232 Ext.Slider.Vertical = {
\r
12233 onResize : function(w, h){
\r
12234 this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
\r
12235 this.syncThumb();
\r
12238 getRatio : function(){
\r
12239 var h = this.innerEl.getHeight(),
\r
12240 v = this.maxValue - this.minValue;
\r
12244 moveThumb: function(v, animate){
\r
12245 if(!animate || this.animate === false){
\r
12246 this.thumb.setBottom(v);
\r
12248 this.thumb.shift({bottom: v, stopFx: true, duration:.35});
\r
12252 onDrag: function(e){
\r
12253 var pos = this.innerEl.translatePoints(this.tracker.getXY()),
\r
12254 bottom = this.innerEl.getHeight()-pos.top;
\r
12255 this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), false);
\r
12256 this.fireEvent('drag', this, e);
\r
12259 onClickChange : function(local){
\r
12260 if(local.left > this.clickRange[0] && local.left < this.clickRange[1]){
\r
12261 var bottom = this.innerEl.getHeight() - local.top;
\r
12262 this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), undefined, true);
\r
12266 * @class Ext.ProgressBar
\r
12267 * @extends Ext.BoxComponent
\r
12268 * <p>An updateable progress bar component. The progress bar supports two different modes: manual and automatic.</p>
\r
12269 * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the
\r
12270 * progress bar as needed from your own code. This method is most appropriate when you want to show progress
\r
12271 * throughout an operation that has predictable points of interest at which you can update the control.</p>
\r
12272 * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it
\r
12273 * once the operation is complete. You can optionally have the progress bar wait for a specific amount of time
\r
12274 * and then clear itself. Automatic mode is most appropriate for timed operations or asynchronous operations in
\r
12275 * which you have no need for indicating intermediate progress.</p>
\r
12276 * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0)
\r
12277 * @cfg {String} text The progress bar text (defaults to '')
\r
12278 * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress
\r
12279 * bar's internal text element)
\r
12280 * @cfg {String} id The progress bar element's id (defaults to an auto-generated id)
\r
12281 * @xtype progress
\r
12283 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
\r
12285 * @cfg {String} baseCls
\r
12286 * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress')
\r
12288 baseCls : 'x-progress',
\r
12291 * @cfg {Boolean} animate
\r
12292 * True to animate the progress bar during transitions (defaults to false)
\r
12297 waitTimer : null,
\r
12300 initComponent : function(){
\r
12301 Ext.ProgressBar.superclass.initComponent.call(this);
\r
12305 * Fires after each update interval
\r
12306 * @param {Ext.ProgressBar} this
\r
12307 * @param {Number} The current progress value
\r
12308 * @param {String} The current progress text
\r
12315 onRender : function(ct, position){
\r
12316 var tpl = new Ext.Template(
\r
12317 '<div class="{cls}-wrap">',
\r
12318 '<div class="{cls}-inner">',
\r
12319 '<div class="{cls}-bar">',
\r
12320 '<div class="{cls}-text">',
\r
12321 '<div> </div>',
\r
12324 '<div class="{cls}-text {cls}-text-back">',
\r
12325 '<div> </div>',
\r
12331 this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
\r
12332 : tpl.append(ct, {cls: this.baseCls}, true);
\r
12335 this.el.dom.id = this.id;
\r
12337 var inner = this.el.dom.firstChild;
\r
12338 this.progressBar = Ext.get(inner.firstChild);
\r
12341 //use an external text el
\r
12342 this.textEl = Ext.get(this.textEl);
\r
12343 delete this.textTopEl;
\r
12345 //setup our internal layered text els
\r
12346 this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
\r
12347 var textBackEl = Ext.get(inner.childNodes[1]);
\r
12348 this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
\r
12349 this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
\r
12350 this.textEl.setWidth(inner.offsetWidth);
\r
12352 this.progressBar.setHeight(inner.offsetHeight);
\r
12356 afterRender : function(){
\r
12357 Ext.ProgressBar.superclass.afterRender.call(this);
\r
12359 this.updateProgress(this.value, this.text);
\r
12361 this.updateText(this.text);
\r
12366 * Updates the progress bar value, and optionally its text. If the text argument is not specified,
\r
12367 * any existing text value will be unchanged. To blank out existing text, pass ''. Note that even
\r
12368 * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for
\r
12369 * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control.
\r
12370 * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0)
\r
12371 * @param {String} text (optional) The string to display in the progress text element (defaults to '')
\r
12372 * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is
\r
12373 * not specified, the default for the class is used (default to false)
\r
12374 * @return {Ext.ProgressBar} this
\r
12376 updateProgress : function(value, text, animate){
\r
12377 this.value = value || 0;
\r
12379 this.updateText(text);
\r
12381 if(this.rendered && !this.isDestroyed){
\r
12382 var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
\r
12383 this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
\r
12384 if(this.textTopEl){
\r
12385 //textTopEl should be the same width as the bar so overflow will clip as the bar moves
\r
12386 this.textTopEl.removeClass('x-hidden').setWidth(w);
\r
12389 this.fireEvent('update', this, value, text);
\r
12394 * Initiates an auto-updating progress bar. A duration can be specified, in which case the progress
\r
12395 * bar will automatically reset after a fixed amount of time and optionally call a callback function
\r
12396 * if specified. If no duration is passed in, then the progress bar will run indefinitely and must
\r
12397 * be manually cleared by calling {@link #reset}. The wait method accepts a config object with
\r
12398 * the following properties:
\r
12400 Property Type Description
\r
12401 ---------- ------------ ----------------------------------------------------------------------
\r
12402 duration Number The length of time in milliseconds that the progress bar should
\r
12403 run before resetting itself (defaults to undefined, in which case it
\r
12404 will run indefinitely until reset is called)
\r
12405 interval Number The length of time in milliseconds between each progress update
\r
12406 (defaults to 1000 ms)
\r
12407 animate Boolean Whether to animate the transition of the progress bar. If this value is
\r
12408 not specified, the default for the class is used.
\r
12409 increment Number The number of progress update segments to display within the progress
\r
12410 bar (defaults to 10). If the bar reaches the end and is still
\r
12411 updating, it will automatically wrap back to the beginning.
\r
12412 text String Optional text to display in the progress bar element (defaults to '').
\r
12413 fn Function A callback function to execute after the progress bar finishes auto-
\r
12414 updating. The function will be called with no arguments. This function
\r
12415 will be ignored if duration is not specified since in that case the
\r
12416 progress bar can only be stopped programmatically, so any required function
\r
12417 should be called by the same code after it resets the progress bar.
\r
12418 scope Object The scope that is passed to the callback function (only applies when
\r
12419 duration and fn are both passed).
\r
12424 var p = new Ext.ProgressBar({
\r
12425 renderTo: 'my-el'
\r
12428 //Wait for 5 seconds, then update the status el (progress bar will auto-reset)
\r
12430 interval: 100, //bar will move fast!
\r
12433 text: 'Updating...',
\r
12436 Ext.fly('status').update('Done!');
\r
12440 //Or update indefinitely until some async action completes, then reset manually
\r
12442 myAction.on('complete', function(){
\r
12444 Ext.fly('status').update('Done!');
\r
12447 * @param {Object} config (optional) Configuration options
\r
12448 * @return {Ext.ProgressBar} this
\r
12450 wait : function(o){
\r
12451 if(!this.waitTimer){
\r
12452 var scope = this;
\r
12454 this.updateText(o.text);
\r
12455 this.waitTimer = Ext.TaskMgr.start({
\r
12456 run: function(i){
\r
12457 var inc = o.increment || 10;
\r
12459 this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
\r
12461 interval: o.interval || 1000,
\r
12462 duration: o.duration,
\r
12463 onStop: function(){
\r
12465 o.fn.apply(o.scope || this);
\r
12476 * Returns true if the progress bar is currently in a {@link #wait} operation
\r
12477 * @return {Boolean} True if waiting, else false
\r
12479 isWaiting : function(){
\r
12480 return this.waitTimer !== null;
\r
12484 * Updates the progress bar text. If specified, textEl will be updated, otherwise the progress
\r
12485 * bar itself will display the updated text.
\r
12486 * @param {String} text (optional) The string to display in the progress text element (defaults to '')
\r
12487 * @return {Ext.ProgressBar} this
\r
12489 updateText : function(text){
\r
12490 this.text = text || ' ';
\r
12491 if(this.rendered){
\r
12492 this.textEl.update(this.text);
\r
12498 * Synchronizes the inner bar width to the proper proportion of the total componet width based
\r
12499 * on the current progress {@link #value}. This will be called automatically when the ProgressBar
\r
12500 * is resized by a layout, but if it is rendered auto width, this method can be called from
\r
12501 * another resize handler to sync the ProgressBar if necessary.
\r
12503 syncProgressBar : function(){
\r
12505 this.updateProgress(this.value, this.text);
\r
12511 * Sets the size of the progress bar.
\r
12512 * @param {Number} width The new width in pixels
\r
12513 * @param {Number} height The new height in pixels
\r
12514 * @return {Ext.ProgressBar} this
\r
12516 setSize : function(w, h){
\r
12517 Ext.ProgressBar.superclass.setSize.call(this, w, h);
\r
12518 if(this.textTopEl){
\r
12519 var inner = this.el.dom.firstChild;
\r
12520 this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
\r
12522 this.syncProgressBar();
\r
12527 * Resets the progress bar value to 0 and text to empty string. If hide = true, the progress
\r
12528 * bar will also be hidden (using the {@link #hideMode} property internally).
\r
12529 * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false)
\r
12530 * @return {Ext.ProgressBar} this
\r
12532 reset : function(hide){
\r
12533 this.updateProgress(0);
\r
12534 if(this.textTopEl){
\r
12535 this.textTopEl.addClass('x-hidden');
\r
12537 this.clearTimer();
\r
12538 if(hide === true){
\r
12545 clearTimer : function(){
\r
12546 if(this.waitTimer){
\r
12547 this.waitTimer.onStop = null; //prevent recursion
\r
12548 Ext.TaskMgr.stop(this.waitTimer);
\r
12549 this.waitTimer = null;
\r
12553 onDestroy: function(){
\r
12554 this.clearTimer();
\r
12555 if(this.rendered){
\r
12556 if(this.textEl.isComposite){
\r
12557 this.textEl.clear();
\r
12559 Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');
\r
12561 Ext.ProgressBar.superclass.onDestroy.call(this);
\r
12564 Ext.reg('progress', Ext.ProgressBar);