3 * Copyright(c) 2006-2009 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 <tt>{@link Ext.Component#xtype xtype}</tt> provides a way to avoid instantiating child Components
15 * when creating a full, nested config object for a complete Ext page.</p>
16 * <p>A child Component may be specified simply as a <i>config object</i>
17 * as long as the correct <tt>{@link Ext.Component#xtype xtype}</tt> is specified so that if and when the Component
18 * needs rendering, the correct type can be looked up for lazy instantiation.</p>
19 * <p>For a list of all available <tt>{@link Ext.Component#xtype xtypes}</tt>, see {@link Ext.Component}.</p>
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, <tt>undefined</tt> if not found, or <tt>null</tt> if a
56 * Registers a function that will be called when a specified component is added to ComponentMgr
57 * @param {String} id The component {@link Ext.Component#id id}
58 * @param {Function} fn The callback function
59 * @param {Object} scope The scope of the callback
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 * Checks if a Component type is registered.
79 * @param {Ext.Component} xtype The mnemonic string by which the Component class may be looked up
80 * @return {Boolean} Whether the type is registered.
82 isRegistered : function(xtype){
83 return types[xtype] !== undefined;
87 * <p>Registers a new Component constructor, keyed by a new
88 * {@link Ext.Component#xtype}.</p>
89 * <p>Use this method (or its alias {@link Ext#reg Ext.reg}) to register new
90 * subclasses of {@link Ext.Component} so that lazy instantiation may be used when specifying
92 * see {@link Ext.Container#items}</p>
93 * @param {String} xtype The mnemonic string by which the Component class may be looked up.
94 * @param {Constructor} cls The new Component class.
96 registerType : function(xtype, cls){
102 * Creates a new Component from the specified config object using the
103 * config object's {@link Ext.component#xtype xtype} to determine the class to instantiate.
104 * @param {Object} config A configuration object for the Component you wish to create.
105 * @param {Constructor} defaultType The constructor to provide the default Component type if
106 * the config object does not contain a <tt>xtype</tt>. (Optional if the config contains a <tt>xtype</tt>).
107 * @return {Ext.Component} The newly instantiated Component.
109 create : function(config, defaultType){
110 return config.render ? config : new types[config.xtype || defaultType](config);
114 * <p>Registers a new Plugin constructor, keyed by a new
115 * {@link Ext.Component#ptype}.</p>
116 * <p>Use this method (or its alias {@link Ext#preg Ext.preg}) to register new
117 * plugins for {@link Ext.Component}s so that lazy instantiation may be used when specifying
119 * @param {String} ptype The mnemonic string by which the Plugin class may be looked up.
120 * @param {Constructor} cls The new Plugin class.
122 registerPlugin : function(ptype, cls){
128 * Creates a new Plugin from the specified config object using the
129 * config object's {@link Ext.component#ptype ptype} to determine the class to instantiate.
130 * @param {Object} config A configuration object for the Plugin you wish to create.
131 * @param {Constructor} defaultType The constructor to provide the default Plugin type if
132 * the config object does not contain a <tt>ptype</tt>. (Optional if the config contains a <tt>ptype</tt>).
133 * @return {Ext.Component} The newly instantiated Plugin.
135 createPlugin : function(config, defaultType){
136 return new ptypes[config.ptype || defaultType](config);
142 * Shorthand for {@link Ext.ComponentMgr#registerType}
143 * @param {String} xtype The {@link Ext.component#xtype mnemonic string} by which the Component class
145 * @param {Constructor} cls The new Component class.
149 Ext.reg = Ext.ComponentMgr.registerType; // this will be called a lot internally, shorthand to keep the bytes down
151 * Shorthand for {@link Ext.ComponentMgr#registerPlugin}
152 * @param {String} ptype The {@link Ext.component#ptype mnemonic string} by which the Plugin class
154 * @param {Constructor} cls The new Plugin class.
158 Ext.preg = Ext.ComponentMgr.registerPlugin;
159 Ext.create = Ext.ComponentMgr.create;
161 * @class Ext.Component
162 * @extends Ext.util.Observable
163 * <p>Base class for all Ext components. All subclasses of Component may participate in the automated
164 * Ext component lifecycle of creation, rendering and destruction which is provided by the {@link Ext.Container Container} class.
165 * Components may be added to a Container through the {@link Ext.Container#items items} config option at the time the Container is created,
166 * or they may be added dynamically via the {@link Ext.Container#add add} method.</p>
167 * <p>The Component base class has built-in support for basic hide/show and enable/disable behavior.</p>
168 * <p>All Components are registered with the {@link Ext.ComponentMgr} on construction so that they can be referenced at any time via
169 * {@link Ext#getCmp}, passing the {@link #id}.</p>
170 * <p>All user-developed visual widgets that are required to participate in automated lifecycle and size management should subclass Component (or
171 * {@link Ext.BoxComponent} if managed box model handling is required, ie height and width management).</p>
172 * <p>See the <a href="http://extjs.com/learn/Tutorial:Creating_new_UI_controls">Creating new UI controls</a> tutorial for details on how
173 * and to either extend or augment ExtJs base classes to create custom Components.</p>
174 * <p>Every component has a specific xtype, which is its Ext-specific type name, along with methods for checking the
175 * xtype like {@link #getXType} and {@link #isXType}. This is the list of all valid xtypes:</p>
178 ------------- ------------------
179 box {@link Ext.BoxComponent}
180 button {@link Ext.Button}
181 buttongroup {@link Ext.ButtonGroup}
182 colorpalette {@link Ext.ColorPalette}
183 component {@link Ext.Component}
184 container {@link Ext.Container}
185 cycle {@link Ext.CycleButton}
186 dataview {@link Ext.DataView}
187 datepicker {@link Ext.DatePicker}
188 editor {@link Ext.Editor}
189 editorgrid {@link Ext.grid.EditorGridPanel}
190 flash {@link Ext.FlashComponent}
191 grid {@link Ext.grid.GridPanel}
192 listview {@link Ext.ListView}
193 panel {@link Ext.Panel}
194 progress {@link Ext.ProgressBar}
195 propertygrid {@link Ext.grid.PropertyGrid}
196 slider {@link Ext.Slider}
197 spacer {@link Ext.Spacer}
198 splitbutton {@link Ext.SplitButton}
199 tabpanel {@link Ext.TabPanel}
200 treepanel {@link Ext.tree.TreePanel}
201 viewport {@link Ext.ViewPort}
202 window {@link Ext.Window}
205 ---------------------------------------
206 paging {@link Ext.PagingToolbar}
207 toolbar {@link Ext.Toolbar}
208 tbbutton {@link Ext.Toolbar.Button} (deprecated; use button)
209 tbfill {@link Ext.Toolbar.Fill}
210 tbitem {@link Ext.Toolbar.Item}
211 tbseparator {@link Ext.Toolbar.Separator}
212 tbspacer {@link Ext.Toolbar.Spacer}
213 tbsplit {@link Ext.Toolbar.SplitButton} (deprecated; use splitbutton)
214 tbtext {@link Ext.Toolbar.TextItem}
217 ---------------------------------------
218 menu {@link Ext.menu.Menu}
219 colormenu {@link Ext.menu.ColorMenu}
220 datemenu {@link Ext.menu.DateMenu}
221 menubaseitem {@link Ext.menu.BaseItem}
222 menucheckitem {@link Ext.menu.CheckItem}
223 menuitem {@link Ext.menu.Item}
224 menuseparator {@link Ext.menu.Separator}
225 menutextitem {@link Ext.menu.TextItem}
228 ---------------------------------------
229 form {@link Ext.FormPanel}
230 checkbox {@link Ext.form.Checkbox}
231 checkboxgroup {@link Ext.form.CheckboxGroup}
232 combo {@link Ext.form.ComboBox}
233 datefield {@link Ext.form.DateField}
234 displayfield {@link Ext.form.DisplayField}
235 field {@link Ext.form.Field}
236 fieldset {@link Ext.form.FieldSet}
237 hidden {@link Ext.form.Hidden}
238 htmleditor {@link Ext.form.HtmlEditor}
239 label {@link Ext.form.Label}
240 numberfield {@link Ext.form.NumberField}
241 radio {@link Ext.form.Radio}
242 radiogroup {@link Ext.form.RadioGroup}
243 textarea {@link Ext.form.TextArea}
244 textfield {@link Ext.form.TextField}
245 timefield {@link Ext.form.TimeField}
246 trigger {@link Ext.form.TriggerField}
249 ---------------------------------------
250 chart {@link Ext.chart.Chart}
251 barchart {@link Ext.chart.BarChart}
252 cartesianchart {@link Ext.chart.CartesianChart}
253 columnchart {@link Ext.chart.ColumnChart}
254 linechart {@link Ext.chart.LineChart}
255 piechart {@link Ext.chart.PieChart}
258 ---------------------------------------
259 arraystore {@link Ext.data.ArrayStore}
260 directstore {@link Ext.data.DirectStore}
261 groupingstore {@link Ext.data.GroupingStore}
262 jsonstore {@link Ext.data.JsonStore}
263 simplestore {@link Ext.data.SimpleStore} (deprecated; use arraystore)
264 store {@link Ext.data.Store}
265 xmlstore {@link Ext.data.XmlStore}
268 * @param {Ext.Element/String/Object} config The configuration options may be specified as either:
269 * <div class="mdetail-params"><ul>
270 * <li><b>an element</b> :
271 * <p class="sub-desc">it is set as the internal element and its id used as the component id</p></li>
272 * <li><b>a string</b> :
273 * <p class="sub-desc">it is assumed to be the id of an existing element and is used as the component id</p></li>
274 * <li><b>anything else</b> :
275 * <p class="sub-desc">it is assumed to be a standard config object and is applied to the component</p></li>
278 Ext.Component = function(config){
279 config = config || {};
280 if(config.initialConfig){
281 if(config.isAction){ // actions
282 this.baseAction = config;
284 config = config.initialConfig; // component cloning / action set up
285 }else if(config.tagName || config.dom || Ext.isString(config)){ // element object
286 config = {applyTo: config, id: config.id || config};
290 * This Component's initial configuration specification. Read-only.
292 * @property initialConfig
294 this.initialConfig = config;
296 Ext.apply(this, config);
300 * Fires after the component is disabled.
301 * @param {Ext.Component} this
306 * Fires after the component is enabled.
307 * @param {Ext.Component} this
312 * Fires before the component is shown by calling the {@link #show} method.
313 * Return false from an event handler to stop the show.
314 * @param {Ext.Component} this
319 * Fires after the component is shown when calling the {@link #show} method.
320 * @param {Ext.Component} this
325 * Fires before the component is hidden by calling the {@link #hide} method.
326 * Return false from an event handler to stop the hide.
327 * @param {Ext.Component} this
332 * Fires after the component is hidden.
333 * Fires after the component is hidden when calling the {@link #hide} method.
334 * @param {Ext.Component} this
338 * @event beforerender
339 * Fires before the component is {@link #rendered}. Return false from an
340 * event handler to stop the {@link #render}.
341 * @param {Ext.Component} this
346 * Fires after the component markup is {@link #rendered}.
347 * @param {Ext.Component} this
352 * <p>Fires after the component rendering is finished.</p>
353 * <p>The afterrender event is fired after this Component has been {@link #rendered}, been postprocesed
354 * by any afterRender method defined for the Component, and, if {@link #stateful}, after state
355 * has been restored.</p>
356 * @param {Ext.Component} this
360 * @event beforedestroy
361 * Fires before the component is {@link #destroy}ed. Return false from an event handler to stop the {@link #destroy}.
362 * @param {Ext.Component} this
367 * Fires after the component is {@link #destroy}ed.
368 * @param {Ext.Component} this
372 * @event beforestaterestore
373 * Fires before the state of the component is restored. Return false from an event handler to stop the restore.
374 * @param {Ext.Component} this
375 * @param {Object} state The hash of state values returned from the StateProvider. If this
376 * event is not vetoed, then the state object is passed to <b><tt>applyState</tt></b>. By default,
377 * that simply copies property values into this Component. The method maybe overriden to
378 * provide custom state restoration.
380 'beforestaterestore',
382 * @event staterestore
383 * Fires after the state of the component is restored.
384 * @param {Ext.Component} this
385 * @param {Object} state The hash of state values returned from the StateProvider. This is passed
386 * to <b><tt>applyState</tt></b>. By default, that simply copies property values into this
387 * Component. The method maybe overriden to provide custom state restoration.
391 * @event beforestatesave
392 * Fires before the state of the component is saved to the configured state provider. Return false to stop the save.
393 * @param {Ext.Component} this
394 * @param {Object} state The hash of state values. This is determined by calling
395 * <b><tt>getState()</tt></b> on the Component. This method must be provided by the
396 * developer to return whetever representation of state is required, by default, Ext.Component
397 * has a null implementation.
402 * Fires after the state of the component is saved to the configured state provider.
403 * @param {Ext.Component} this
404 * @param {Object} state The hash of state values. This is determined by calling
405 * <b><tt>getState()</tt></b> on the Component. This method must be provided by the
406 * developer to return whetever representation of state is required, by default, Ext.Component
407 * has a null implementation.
412 Ext.ComponentMgr.register(this);
413 Ext.Component.superclass.constructor.call(this);
416 this.baseAction.addComponent(this);
419 this.initComponent();
422 if(Ext.isArray(this.plugins)){
423 for(var i = 0, len = this.plugins.length; i < len; i++){
424 this.plugins[i] = this.initPlugin(this.plugins[i]);
427 this.plugins = this.initPlugin(this.plugins);
431 if(this.stateful !== false){
432 this.initState(config);
436 this.applyToMarkup(this.applyTo);
438 }else if(this.renderTo){
439 this.render(this.renderTo);
440 delete this.renderTo;
445 Ext.Component.AUTO_ID = 1000;
447 Ext.extend(Ext.Component, Ext.util.Observable, {
448 // Configs below are used for all Components when rendered by FormLayout.
450 * @cfg {String} fieldLabel <p>The label text to display next to this Component (defaults to '').</p>
451 * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container which
452 * has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout manager (e.g.
453 * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>).</p><br>
454 * <p>Also see <tt>{@link #hideLabel}</tt> and
455 * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</p>
456 * Example use:<pre><code>
459 renderTo: Ext.getBody(),
468 * @cfg {String} labelStyle <p>A CSS style specification string to apply directly to this field's
469 * label. Defaults to the container's labelStyle value if set (e.g.,
470 * <tt>{@link Ext.layout.FormLayout#labelStyle}</tt> , or '').</p>
471 * <br><p><b>Note</b>: see the note for <code>{@link #clearCls}</code>.</p><br>
472 * <p>Also see <code>{@link #hideLabel}</code> and
473 * <code>{@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</code></p>
474 * Example use:<pre><code>
477 renderTo: Ext.getBody(),
481 labelStyle: 'font-weight:bold;'
487 * @cfg {String} labelSeparator <p>The separator to display after the text of each
488 * <tt>{@link #fieldLabel}</tt>. This property may be configured at various levels.
489 * The order of precedence is:
490 * <div class="mdetail-params"><ul>
491 * <li>field / component level</li>
492 * <li>container level</li>
493 * <li>{@link Ext.layout.FormLayout#labelSeparator layout level} (defaults to colon <tt>':'</tt>)</li>
495 * To display no separator for this field's label specify empty string ''.</p>
496 * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</tt>.</p><br>
497 * <p>Also see <tt>{@link #hideLabel}</tt> and
498 * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}.</p>
499 * Example use:<pre><code>
502 renderTo: Ext.getBody(),
504 labelSeparator: '~' // layout config has lowest priority (defaults to ':')
506 {@link Ext.layout.FormLayout#labelSeparator labelSeparator}: '>>', // config at container level
509 fieldLabel: 'Field 1',
510 labelSeparator: '...' // field/component level config supersedes others
513 fieldLabel: 'Field 2' // labelSeparator will be '='
519 * @cfg {Boolean} hideLabel <p><tt>true</tt> to completely hide the label element
520 * ({@link #fieldLabel label} and {@link #labelSeparator separator}). Defaults to <tt>false</tt>.
521 * By default, even if you do not specify a <tt>{@link #fieldLabel}</tt> the space will still be
522 * reserved so that the field will line up with other fields that do have labels.
523 * Setting this to <tt>true</tt> will cause the field to not reserve that space.</p>
524 * <br><p><b>Note</b>: see the note for <tt>{@link #clearCls}</tt>.</p><br>
525 * Example use:<pre><code>
528 renderTo: Ext.getBody(),
537 * @cfg {String} clearCls <p>The CSS class used to to apply to the special clearing div rendered
538 * directly after each form field wrapper to provide field clearing (defaults to
539 * <tt>'x-form-clear-left'</tt>).</p>
540 * <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container
541 * which has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout
542 * manager (e.g. {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) and either a
543 * <tt>{@link #fieldLabel}</tt> is specified or <tt>isFormField=true</tt> is specified.</p><br>
544 * <p>See {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl} also.</p>
547 * @cfg {String} itemCls <p>An additional CSS class to apply to the div wrapping the form item
548 * element of this field. If supplied, <tt>itemCls</tt> at the <b>field</b> level will override
549 * the default <tt>itemCls</tt> supplied at the <b>container</b> level. The value specified for
550 * <tt>itemCls</tt> will be added to the default class (<tt>'x-form-item'</tt>).</p>
551 * <p>Since it is applied to the item wrapper (see
552 * {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl}), it allows
553 * you to write standard CSS rules that can apply to the field, the label (if specified), or
554 * any other element within the markup for the field.</p>
555 * <br><p><b>Note</b>: see the note for <tt>{@link #fieldLabel}</tt>.</p><br>
556 * Example use:<pre><code>
557 // Apply a style to the field's label:
559 .required .x-form-item-label {font-weight:bold;color:red;}
564 renderTo: Ext.getBody(),
568 itemCls: 'required' //this label will be styled
571 fieldLabel: 'Favorite Color'
577 // Configs below are used for all Components when rendered by AnchorLayout.
579 * @cfg {String} anchor <p><b>Note</b>: this config is only used when this Component is rendered
580 * by a Container which has been configured to use an <b>{@link Ext.layout.AnchorLayout AnchorLayout}</b>
581 * based layout manager, for example:<div class="mdetail-params"><ul>
582 * <li>{@link Ext.form.FormPanel}</li>
583 * <li>specifying <code>layout: 'anchor' // or 'form', or 'absolute'</code></li>
585 * <p>See {@link Ext.layout.AnchorLayout}.{@link Ext.layout.AnchorLayout#anchor anchor} also.</p>
590 * <p>The <b>unique</b> id of this component (defaults to an {@link #getId auto-assigned id}).
591 * You should assign an id if you need to be able to access the component later and you do
592 * not have an object reference available (e.g., using {@link Ext}.{@link Ext#getCmp getCmp}).</p>
593 * <p>Note that this id will also be used as the element id for the containing HTML element
594 * that is rendered to the page for this component. This allows you to write id-based CSS
595 * rules to style the specific instance of this component uniquely, and also to select
596 * sub-elements using this component's id as the parent.</p>
597 * <p><b>Note</b>: to avoid complications imposed by a unique <tt>id</tt> also see
598 * <code>{@link #itemId}</code> and <code>{@link #ref}</code>.</p>
599 * <p><b>Note</b>: to access the container of an item see <code>{@link #ownerCt}</code>.</p>
602 * @cfg {String} itemId
603 * <p>An <tt>itemId</tt> can be used as an alternative way to get a reference to a component
604 * when no object reference is available. Instead of using an <code>{@link #id}</code> with
605 * {@link Ext}.{@link Ext#getCmp getCmp}, use <code>itemId</code> with
606 * {@link Ext.Container}.{@link Ext.Container#getComponent getComponent} which will retrieve
607 * <code>itemId</code>'s or <tt>{@link #id}</tt>'s. Since <code>itemId</code>'s are an index to the
608 * container's internal MixedCollection, the <code>itemId</code> is scoped locally to the container --
609 * avoiding potential conflicts with {@link Ext.ComponentMgr} which requires a <b>unique</b>
610 * <code>{@link #id}</code>.</p>
612 var c = new Ext.Panel({ //
613 {@link Ext.BoxComponent#height height}: 300,
614 {@link #renderTo}: document.body,
615 {@link Ext.Container#layout layout}: 'auto',
616 {@link Ext.Container#items items}: [
619 {@link Ext.Panel#title title}: 'Panel 1',
620 {@link Ext.BoxComponent#height height}: 150
624 {@link Ext.Panel#title title}: 'Panel 2',
625 {@link Ext.BoxComponent#height height}: 150
629 p1 = c.{@link Ext.Container#getComponent getComponent}('p1'); // not the same as {@link Ext#getCmp Ext.getCmp()}
630 p2 = p1.{@link #ownerCt}.{@link Ext.Container#getComponent getComponent}('p2'); // reference via a sibling
632 * <p>Also see <tt>{@link #id}</tt> and <code>{@link #ref}</code>.</p>
633 * <p><b>Note</b>: to access the container of an item see <tt>{@link #ownerCt}</tt>.</p>
636 * @cfg {String} xtype
637 * The registered <tt>xtype</tt> to create. This config option is not used when passing
638 * a config object into a constructor. This config option is used only when
639 * lazy instantiation is being used, and a child item of a Container is being
640 * specified not as a fully instantiated Component, but as a <i>Component config
641 * object</i>. The <tt>xtype</tt> will be looked up at render time up to determine what
642 * type of child Component to create.<br><br>
643 * The predefined xtypes are listed {@link Ext.Component here}.
645 * If you subclass Components to create your own Components, you may register
646 * them using {@link Ext.ComponentMgr#registerType} in order to be able to
647 * take advantage of lazy instantiation and rendering.
650 * @cfg {String} ptype
651 * The registered <tt>ptype</tt> to create. This config option is not used when passing
652 * a config object into a constructor. This config option is used only when
653 * lazy instantiation is being used, and a Plugin is being
654 * specified not as a fully instantiated Component, but as a <i>Component config
655 * object</i>. The <tt>ptype</tt> will be looked up at render time up to determine what
656 * type of Plugin to create.<br><br>
657 * If you create your own Plugins, you may register them using
658 * {@link Ext.ComponentMgr#registerPlugin} in order to be able to
659 * take advantage of lazy instantiation and rendering.
663 * An optional extra CSS class that will be added to this component's Element (defaults to ''). This can be
664 * useful for adding customized styles to the component or any of its children using standard CSS rules.
667 * @cfg {String} overCls
668 * An optional extra CSS class that will be added to this component's Element when the mouse moves
669 * over the Element, and removed when the mouse moves out. (defaults to ''). This can be
670 * useful for adding customized 'active' or 'hover' styles to the component or any of its children using standard CSS rules.
673 * @cfg {String} style
674 * A custom style specification to be applied to this component's Element. Should be a valid argument to
675 * {@link Ext.Element#applyStyles}.
679 renderTo: Ext.getBody(),
680 width: 400, height: 300,
701 * @cfg {String} ctCls
702 * <p>An optional extra CSS class that will be added to this component's container. This can be useful for
703 * adding customized styles to the container or any of its children using standard CSS rules. See
704 * {@link Ext.layout.ContainerLayout}.{@link Ext.layout.ContainerLayout#extraCls extraCls} also.</p>
705 * <p><b>Note</b>: <tt>ctCls</tt> defaults to <tt>''</tt> except for the following class
706 * which assigns a value by default:
707 * <div class="mdetail-params"><ul>
708 * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-layout-ct'</tt></li>
710 * To configure the above Class with an extra CSS class append to the default. For example,
711 * for BoxLayout (Hbox and Vbox):<pre><code>
712 * ctCls: 'x-box-layout-ct custom-class'
717 * @cfg {Boolean} disabled
718 * Render this component disabled (default is false).
722 * @cfg {Boolean} hidden
723 * Render this component hidden (default is false). If <tt>true</tt>, the
724 * {@link #hide} method will be called internally.
728 * @cfg {Object/Array} plugins
729 * An object or array of objects that will provide custom functionality for this component. The only
730 * requirement for a valid plugin is that it contain an init method that accepts a reference of type Ext.Component.
731 * When a component is created, if any plugins are available, the component will call the init method on each
732 * plugin, passing a reference to itself. Each plugin can then call methods or respond to events on the
733 * component as needed to provide its functionality.
736 * @cfg {Mixed} applyTo
737 * <p>Specify the id of the element, a DOM element or an existing Element corresponding to a DIV
738 * that is already present in the document that specifies some structural markup for this
739 * component.</p><div><ul>
740 * <li><b>Description</b> : <ul>
741 * <div class="sub-desc">When <tt>applyTo</tt> is used, constituent parts of the component can also be specified
742 * by id or CSS class name within the main element, and the component being created may attempt
743 * to create its subcomponents from that markup if applicable.</div>
745 * <li><b>Notes</b> : <ul>
746 * <div class="sub-desc">When using this config, a call to render() is not required.</div>
747 * <div class="sub-desc">If applyTo is specified, any value passed for {@link #renderTo} will be ignored and the target
748 * element's parent node will automatically be used as the component's container.</div>
753 * @cfg {Mixed} renderTo
754 * <p>Specify the id of the element, a DOM element or an existing Element that this component
755 * will be rendered into.</p><div><ul>
756 * <li><b>Notes</b> : <ul>
757 * <div class="sub-desc">Do <u>not</u> use this option if the Component is to be a child item of
758 * a {@link Ext.Container Container}. It is the responsibility of the
759 * {@link Ext.Container Container}'s {@link Ext.Container#layout layout manager}
760 * to render and manage its child items.</div>
761 * <div class="sub-desc">When using this config, a call to render() is not required.</div>
764 * <p>See <tt>{@link #render}</tt> also.</p>
767 * @cfg {Boolean} stateful
768 * <p>A flag which causes the Component to attempt to restore the state of
769 * internal properties from a saved state on startup. The component must have
770 * either a <code>{@link #stateId}</code> or <code>{@link #id}</code> assigned
771 * for state to be managed. Auto-generated ids are not guaranteed to be stable
772 * across page loads and cannot be relied upon to save and restore the same
773 * state for a component.<p>
774 * <p>For state saving to work, the state manager's provider must have been
775 * set to an implementation of {@link Ext.state.Provider} which overrides the
776 * {@link Ext.state.Provider#set set} and {@link Ext.state.Provider#get get}
777 * methods to save and recall name/value pairs. A built-in implementation,
778 * {@link Ext.state.CookieProvider} is available.</p>
779 * <p>To set the state provider for the current page:</p>
781 Ext.state.Manager.setProvider(new Ext.state.CookieProvider({
782 expires: new Date(new Date().getTime()+(1000*60*60*24*7)), //7 days from now
785 * <p>A stateful Component attempts to save state when one of the events
786 * listed in the <code>{@link #stateEvents}</code> configuration fires.</p>
787 * <p>To save state, a stateful Component first serializes its state by
788 * calling <b><code>getState</code></b>. By default, this function does
789 * nothing. The developer must provide an implementation which returns an
790 * object hash which represents the Component's restorable state.</p>
791 * <p>The value yielded by getState is passed to {@link Ext.state.Manager#set}
792 * which uses the configured {@link Ext.state.Provider} to save the object
793 * keyed by the Component's <code>{@link stateId}</code>, or, if that is not
794 * specified, its <code>{@link #id}</code>.</p>
795 * <p>During construction, a stateful Component attempts to <i>restore</i>
796 * its state by calling {@link Ext.state.Manager#get} passing the
797 * <code>{@link #stateId}</code>, or, if that is not specified, the
798 * <code>{@link #id}</code>.</p>
799 * <p>The resulting object is passed to <b><code>applyState</code></b>.
800 * The default implementation of <code>applyState</code> simply copies
801 * properties into the object, but a developer may override this to support
802 * more behaviour.</p>
803 * <p>You can perform extra processing on state save and restore by attaching
804 * handlers to the {@link #beforestaterestore}, {@link #staterestore},
805 * {@link #beforestatesave} and {@link #statesave} events.</p>
808 * @cfg {String} stateId
809 * The unique id for this component to use for state management purposes
810 * (defaults to the component id if one was set, otherwise null if the
811 * component is using a generated id).
812 * <p>See <code>{@link #stateful}</code> for an explanation of saving and
813 * restoring Component state.</p>
816 * @cfg {Array} stateEvents
817 * <p>An array of events that, when fired, should trigger this component to
818 * save its state (defaults to none). <code>stateEvents</code> may be any type
819 * of event supported by this component, including browser or custom events
820 * (e.g., <tt>['click', 'customerchange']</tt>).</p>
821 * <p>See <code>{@link #stateful}</code> for an explanation of saving and
822 * restoring Component state.</p>
825 * @cfg {Mixed} autoEl
826 * <p>A tag name or {@link Ext.DomHelper DomHelper} spec used to create the {@link #getEl Element} which will
827 * encapsulate this Component.</p>
828 * <p>You do not normally need to specify this. For the base classes {@link Ext.Component}, {@link Ext.BoxComponent},
829 * and {@link Ext.Container}, this defaults to <b><tt>'div'</tt></b>. The more complex Ext classes use a more complex
830 * DOM structure created by their own onRender methods.</p>
831 * <p>This is intended to allow the developer to create application-specific utility Components encapsulated by
832 * different DOM elements. Example usage:</p><pre><code>
837 src: 'http://www.example.com/example.jpg'
843 html: 'autoEl is cool!'
848 cls: 'ux-unordered-list',
852 html: 'First list item'
860 * @cfg {String} disabledClass
861 * CSS class added to the component when it is disabled (defaults to 'x-item-disabled').
863 disabledClass : 'x-item-disabled',
865 * @cfg {Boolean} allowDomMove
866 * Whether the component can move the Dom node when rendering (defaults to true).
870 * @cfg {Boolean} autoShow
871 * True if the component should check for hidden classes (e.g. 'x-hidden' or 'x-hide-display') and remove
872 * them on render (defaults to false).
876 * @cfg {String} hideMode
877 * <p>How this component should be hidden. Supported values are <tt>'visibility'</tt>
878 * (css visibility), <tt>'offsets'</tt> (negative offset position) and <tt>'display'</tt>
880 * <br><p><b>Note</b>: the default of <tt>'display'</tt> is generally preferred
881 * since items are automatically laid out when they are first shown (no sizing
882 * is done while hidden).</p>
884 hideMode : 'display',
886 * @cfg {Boolean} hideParent
887 * True to hide and show the component's container when hide/show is called on the component, false to hide
888 * and show the component itself (defaults to false). For example, this can be used as a shortcut for a hide
889 * button on a window by setting hide:true on the button when adding it to its parent container.
893 * <p>The {@link Ext.Element} which encapsulates this Component. Read-only.</p>
894 * <p>This will <i>usually</i> be a <DIV> element created by the class's onRender method, but
895 * that may be overridden using the <code>{@link #autoEl}</code> config.</p>
896 * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br>
897 * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners
898 * for this Component's own Observable events), see the {@link Ext.util.Observable#listeners listeners}
899 * config for a suggestion, or use a render listener directly:</p><pre><code>
901 title: 'The Clickable Panel',
903 render: function(p) {
904 // Append the Panel to the click handler's argument list.
905 p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));
907 single: true // Remove the listener after first invocation
911 * <p>See also <tt>{@link #getEl getEl}</p>
916 * The component's owner {@link Ext.Container} (defaults to undefined, and is set automatically when
917 * the component is added to a container). Read-only.
918 * <p><b>Note</b>: to access items within the container see <tt>{@link #itemId}</tt>.</p>
919 * @type Ext.Container
923 * True if this component is hidden. Read-only.
928 * True if this component is disabled. Read-only.
933 * True if this component has been rendered. Read-only.
940 ctype : 'Ext.Component',
946 getActionEl : function(){
947 return this[this.actionMode];
950 initPlugin : function(p){
951 if(p.ptype && !Ext.isFunction(p.init)){
952 p = Ext.ComponentMgr.createPlugin(p);
953 }else if(Ext.isString(p)){
954 p = Ext.ComponentMgr.createPlugin({
963 * Function to be implemented by Component subclasses to be part of standard component initialization flow (it is empty by default).
965 // Traditional constructor:
966 Ext.Foo = function(config){
967 // call superclass constructor:
968 Ext.Foo.superclass.constructor.call(this, config);
974 Ext.extend(Ext.Foo, Ext.Bar, {
978 // initComponent replaces the constructor:
979 Ext.Foo = Ext.extend(Ext.Bar, {
980 initComponent : function(){
981 // call superclass initComponent
982 Ext.Container.superclass.initComponent.call(this);
991 initComponent : Ext.emptyFn,
994 * <p>Render this Component into the passed HTML element.</p>
995 * <p><b>If you are using a {@link Ext.Container Container} object to house this Component, then
996 * do not use the render method.</b></p>
997 * <p>A Container's child Components are rendered by that Container's
998 * {@link Ext.Container#layout layout} manager when the Container is first rendered.</p>
999 * <p>Certain layout managers allow dynamic addition of child components. Those that do
1000 * include {@link Ext.layout.CardLayout}, {@link Ext.layout.AnchorLayout},
1001 * {@link Ext.layout.FormLayout}, {@link Ext.layout.TableLayout}.</p>
1002 * <p>If the Container is already rendered when a new child Component is added, you may need to call
1003 * the Container's {@link Ext.Container#doLayout doLayout} to refresh the view which causes any
1004 * unrendered child Components to be rendered. This is required so that you can add multiple
1005 * child components if needed while only refreshing the layout once.</p>
1006 * <p>When creating complex UIs, it is important to remember that sizing and positioning
1007 * of child items is the responsibility of the Container's {@link Ext.Container#layout layout} manager.
1008 * If you expect child items to be sized in response to user interactions, you must
1009 * configure the Container with a layout manager which creates and manages the type of layout you
1011 * <p><b>Omitting the Container's {@link Ext.Container#layout layout} config means that a basic
1012 * layout manager is used which does nothing but render child components sequentially into the
1013 * Container. No sizing or positioning will be performed in this situation.</b></p>
1014 * @param {Element/HTMLElement/String} container (optional) The element this Component should be
1015 * rendered into. If it is being created from existing markup, this should be omitted.
1016 * @param {String/Number} position (optional) The element ID or DOM node index within the container <b>before</b>
1017 * which this component will be inserted (defaults to appending to the end of the container)
1019 render : function(container, position){
1020 if(!this.rendered && this.fireEvent('beforerender', this) !== false){
1021 if(!container && this.el){
1022 this.el = Ext.get(this.el);
1023 container = this.el.dom.parentNode;
1024 this.allowDomMove = false;
1026 this.container = Ext.get(container);
1028 this.container.addClass(this.ctCls);
1030 this.rendered = true;
1031 if(position !== undefined){
1032 if(Ext.isNumber(position)){
1033 position = this.container.dom.childNodes[position];
1035 position = Ext.getDom(position);
1038 this.onRender(this.container, position || null);
1040 this.el.removeClass(['x-hidden','x-hide-' + this.hideMode]);
1043 this.el.addClass(this.cls);
1047 this.el.applyStyles(this.style);
1051 this.el.addClassOnOver(this.overCls);
1053 this.fireEvent('render', this);
1054 this.afterRender(this.container);
1056 // call this so we don't fire initial hide events.
1060 // pass silent so the event doesn't fire the first time.
1064 if(this.stateful !== false){
1065 this.initStateEvents();
1068 this.fireEvent('afterrender', this);
1073 initRef : function(){
1076 * <p>A path specification, relative to the Component's {@link #ownerCt} specifying into which
1077 * ancestor Container to place a named reference to this Component.</p>
1078 * <p>The ancestor axis can be traversed by using '/' characters in the path.
1079 * For example, to put a reference to a Toolbar Button into <i>the Panel which owns the Toolbar</i>:</p><pre><code>
1080 var myGrid = new Ext.grid.EditorGridPanel({
1081 title: 'My EditorGridPanel',
1083 colModel: myColModel,
1086 handler: saveChanges,
1088 ref: '../saveButton'
1091 afteredit: function() {
1092 // The button reference is in the GridPanel
1093 myGrid.saveButton.enable();
1098 * <p>In the code above, if the ref had been <code>'saveButton'</code> the reference would
1099 * have been placed into the Toolbar. Each '/' in the ref moves up one level from the
1100 * Component's {@link #ownerCt}.</p>
1103 var levels = this.ref.split('/');
1104 var last = levels.length, i = 0;
1112 t[levels[--i]] = this;
1117 initState : function(config){
1118 if(Ext.state.Manager){
1119 var id = this.getStateId();
1121 var state = Ext.state.Manager.get(id);
1123 if(this.fireEvent('beforestaterestore', this, state) !== false){
1124 this.applyState(state);
1125 this.fireEvent('staterestore', this, state);
1133 getStateId : function(){
1134 return this.stateId || ((this.id.indexOf('ext-comp-') == 0 || this.id.indexOf('ext-gen') == 0) ? null : this.id);
1138 initStateEvents : function(){
1139 if(this.stateEvents){
1140 for(var i = 0, e; e = this.stateEvents[i]; i++){
1141 this.on(e, this.saveState, this, {delay:100});
1147 applyState : function(state, config){
1149 Ext.apply(this, state);
1154 getState : function(){
1159 saveState : function(){
1160 if(Ext.state.Manager && this.stateful !== false){
1161 var id = this.getStateId();
1163 var state = this.getState();
1164 if(this.fireEvent('beforestatesave', this, state) !== false){
1165 Ext.state.Manager.set(id, state);
1166 this.fireEvent('statesave', this, state);
1173 * Apply this component to existing markup that is valid. With this function, no call to render() is required.
1174 * @param {String/HTMLElement} el
1176 applyToMarkup : function(el){
1177 this.allowDomMove = false;
1178 this.el = Ext.get(el);
1179 this.render(this.el.dom.parentNode);
1183 * Adds a CSS class to the component's underlying element.
1184 * @param {string} cls The CSS class name to add
1185 * @return {Ext.Component} this
1187 addClass : function(cls){
1189 this.el.addClass(cls);
1191 this.cls = this.cls ? this.cls + ' ' + cls : cls;
1197 * Removes a CSS class from the component's underlying element.
1198 * @param {string} cls The CSS class name to remove
1199 * @return {Ext.Component} this
1201 removeClass : function(cls){
1203 this.el.removeClass(cls);
1205 this.cls = this.cls.split(' ').remove(cls).join(' ');
1211 // default function is not really useful
1212 onRender : function(ct, position){
1213 if(!this.el && this.autoEl){
1214 if(Ext.isString(this.autoEl)){
1215 this.el = document.createElement(this.autoEl);
1217 var div = document.createElement('div');
1218 Ext.DomHelper.overwrite(div, this.autoEl);
1219 this.el = div.firstChild;
1222 this.el.id = this.getId();
1226 this.el = Ext.get(this.el);
1227 if(this.allowDomMove !== false){
1228 ct.dom.insertBefore(this.el.dom, position);
1234 getAutoCreate : function(){
1235 var cfg = Ext.isObject(this.autoCreate) ?
1236 this.autoCreate : Ext.apply({}, this.defaultAutoCreate);
1237 if(this.id && !cfg.id){
1244 afterRender : Ext.emptyFn,
1247 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
1248 * removing the component from its {@link Ext.Container} (if applicable) and unregistering it from
1249 * {@link Ext.ComponentMgr}. Destruction is generally handled automatically by the framework and this method
1250 * should usually not need to be called directly.
1253 destroy : function(){
1254 if(this.fireEvent('beforedestroy', this) !== false){
1255 this.beforeDestroy();
1257 this.el.removeAllListeners();
1259 if(this.actionMode == 'container' || this.removeMode == 'container'){
1260 this.container.remove();
1264 Ext.ComponentMgr.unregister(this);
1265 this.fireEvent('destroy', this);
1266 this.purgeListeners();
1271 beforeDestroy : Ext.emptyFn,
1274 onDestroy : Ext.emptyFn,
1277 * <p>Returns the {@link Ext.Element} which encapsulates this Component.</p>
1278 * <p>This will <i>usually</i> be a <DIV> element created by the class's onRender method, but
1279 * that may be overridden using the {@link #autoEl} config.</p>
1280 * <br><p><b>Note</b>: this element will not be available until this Component has been rendered.</p><br>
1281 * <p>To add listeners for <b>DOM events</b> to this Component (as opposed to listeners
1282 * for this Component's own Observable events), see the {@link #listeners} config for a suggestion,
1283 * or use a render listener directly:</p><pre><code>
1285 title: 'The Clickable Panel',
1287 render: function(p) {
1288 // Append the Panel to the click handler's argument list.
1289 p.getEl().on('click', handlePanelClick.createDelegate(null, [p], true));
1291 single: true // Remove the listener after first invocation
1295 * @return {Ext.Element} The Element which encapsulates this Component.
1302 * Returns the <code>id</code> of this component or automatically generates and
1303 * returns an <code>id</code> if an <code>id</code> is not defined yet:<pre><code>
1304 * 'ext-comp-' + (++Ext.Component.AUTO_ID)
1306 * @return {String} id
1309 return this.id || (this.id = 'ext-comp-' + (++Ext.Component.AUTO_ID));
1313 * Returns the <code>{@link #itemId}</code> of this component. If an
1314 * <code>{@link #itemId}</code> was not assigned through configuration the
1315 * <code>id</code> is returned using <code>{@link #getId}</code>.
1318 getItemId : function(){
1319 return this.itemId || this.getId();
1323 * Try to focus this component.
1324 * @param {Boolean} selectText (optional) If applicable, true to also select the text in this component
1325 * @param {Boolean/Number} delay (optional) Delay the focus this number of milliseconds (true for 10 milliseconds)
1326 * @return {Ext.Component} this
1328 focus : function(selectText, delay){
1330 this.focus.defer(Ext.isNumber(delay) ? delay : 10, this, [selectText, false]);
1335 if(selectText === true){
1336 this.el.dom.select();
1351 * Disable this component and fire the 'disable' event.
1352 * @return {Ext.Component} this
1354 disable : function(/* private */ silent){
1358 this.disabled = true;
1359 if(silent !== true){
1360 this.fireEvent('disable', this);
1366 onDisable : function(){
1367 this.getActionEl().addClass(this.disabledClass);
1368 this.el.dom.disabled = true;
1372 * Enable this component and fire the 'enable' event.
1373 * @return {Ext.Component} this
1375 enable : function(){
1379 this.disabled = false;
1380 this.fireEvent('enable', this);
1385 onEnable : function(){
1386 this.getActionEl().removeClass(this.disabledClass);
1387 this.el.dom.disabled = false;
1391 * Convenience function for setting disabled/enabled by boolean.
1392 * @param {Boolean} disabled
1393 * @return {Ext.Component} this
1395 setDisabled : function(disabled){
1396 return this[disabled ? 'disable' : 'enable']();
1400 * Show this component. Listen to the '{@link #beforeshow}' event and return
1401 * <tt>false</tt> to cancel showing the component. Fires the '{@link #show}'
1402 * event after showing the component.
1403 * @return {Ext.Component} this
1406 if(this.fireEvent('beforeshow', this) !== false){
1407 this.hidden = false;
1408 if(this.autoRender){
1409 this.render(Ext.isBoolean(this.autoRender) ? Ext.getBody() : this.autoRender);
1414 this.fireEvent('show', this);
1420 onShow : function(){
1421 this.getVisibiltyEl().removeClass('x-hide-' + this.hideMode);
1425 * Hide this component. Listen to the '{@link #beforehide}' event and return
1426 * <tt>false</tt> to cancel hiding the component. Fires the '{@link #hide}'
1427 * event after hiding the component. Note this method is called internally if
1428 * the component is configured to be <code>{@link #hidden}</code>.
1429 * @return {Ext.Component} this
1432 if(this.fireEvent('beforehide', this) !== false){
1434 this.fireEvent('hide', this);
1448 onHide : function(){
1449 this.getVisibiltyEl().addClass('x-hide-' + this.hideMode);
1453 getVisibiltyEl : function(){
1454 return this.hideParent ? this.container : this.getActionEl();
1458 * Convenience function to hide or show this component by boolean.
1459 * @param {Boolean} visible True to show, false to hide
1460 * @return {Ext.Component} this
1462 setVisible : function(visible){
1463 return this[visible ? 'show' : 'hide']();
1467 * Returns true if this component is visible.
1468 * @return {Boolean} True if this component is visible, false otherwise.
1470 isVisible : function(){
1471 return this.rendered && this.getVisibiltyEl().isVisible();
1475 * Clone the current component using the original config values passed into this instance by default.
1476 * @param {Object} overrides A new config containing any properties to override in the cloned version.
1477 * An id property can be passed on this object, otherwise one will be generated to avoid duplicates.
1478 * @return {Ext.Component} clone The cloned copy of this component
1480 cloneConfig : function(overrides){
1481 overrides = overrides || {};
1482 var id = overrides.id || Ext.id();
1483 var cfg = Ext.applyIf(overrides, this.initialConfig);
1484 cfg.id = id; // prevent dup id
1485 return new this.constructor(cfg);
1489 * Gets the xtype for this component as registered with {@link Ext.ComponentMgr}. For a list of all
1490 * available xtypes, see the {@link Ext.Component} header. Example usage:
1492 var t = new Ext.form.TextField();
1493 alert(t.getXType()); // alerts 'textfield'
1495 * @return {String} The xtype
1497 getXType : function(){
1498 return this.constructor.xtype;
1502 * <p>Tests whether or not this Component is of a specific xtype. This can test whether this Component is descended
1503 * from the xtype (default) or whether it is directly of the xtype specified (shallow = true).</p>
1504 * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1505 * to participate in determination of inherited xtypes.</b></p>
1506 * <p>For a list of all available xtypes, see the {@link Ext.Component} header.</p>
1507 * <p>Example usage:</p>
1509 var t = new Ext.form.TextField();
1510 var isText = t.isXType('textfield'); // true
1511 var isBoxSubclass = t.isXType('box'); // true, descended from BoxComponent
1512 var isBoxInstance = t.isXType('box', true); // false, not a direct BoxComponent instance
1514 * @param {String} xtype The xtype to check for this Component
1515 * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
1516 * the default), or true to check whether this Component is directly of the specified xtype.
1517 * @return {Boolean} True if this component descends from the specified xtype, false otherwise.
1519 isXType : function(xtype, shallow){
1520 //assume a string by default
1521 if (Ext.isFunction(xtype)){
1522 xtype = xtype.xtype; //handle being passed the class, e.g. Ext.Component
1523 }else if (Ext.isObject(xtype)){
1524 xtype = xtype.constructor.xtype; //handle being passed an instance
1527 return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1 : this.constructor.xtype == xtype;
1531 * <p>Returns this Component's xtype hierarchy as a slash-delimited string. For a list of all
1532 * available xtypes, see the {@link Ext.Component} header.</p>
1533 * <p><b>If using your own subclasses, be aware that a Component must register its own xtype
1534 * to participate in determination of inherited xtypes.</b></p>
1535 * <p>Example usage:</p>
1537 var t = new Ext.form.TextField();
1538 alert(t.getXTypes()); // alerts 'component/box/field/textfield'
1540 * @return {String} The xtype hierarchy string
1542 getXTypes : function(){
1543 var tc = this.constructor;
1545 var c = [], sc = this;
1546 while(sc && sc.constructor.xtype){
1547 c.unshift(sc.constructor.xtype);
1548 sc = sc.constructor.superclass;
1551 tc.xtypes = c.join('/');
1557 * Find a container above this component at any level by a custom function. If the passed function returns
1558 * true, the container will be returned.
1559 * @param {Function} fn The custom function to call with the arguments (container, this component).
1560 * @return {Ext.Container} The first Container for which the custom function returns true
1562 findParentBy : function(fn) {
1563 for (var p = this.ownerCt; (p != null) && !fn(p, this); p = p.ownerCt);
1568 * Find a container above this component at any level by xtype or class
1569 * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
1570 * @return {Ext.Container} The first Container which matches the given xtype or class
1572 findParentByType : function(xtype) {
1573 return Ext.isFunction(xtype) ?
1574 this.findParentBy(function(p){
1575 return p.constructor === xtype;
1577 this.findParentBy(function(p){
1578 return p.constructor.xtype === xtype;
1582 getDomPositionEl : function(){
1583 return this.getPositionEl ? this.getPositionEl() : this.getEl();
1587 purgeListeners : function(){
1588 Ext.Component.superclass.purgeListeners.call(this);
1590 this.on('beforedestroy', this.clearMons, this, {single: true});
1595 clearMons : function(){
1596 Ext.each(this.mons, function(m){
1597 m.item.un(m.ename, m.fn, m.scope);
1602 // internal function for auto removal of assigned event handlers on destruction
1603 mon : function(item, ename, fn, scope, opt){
1606 this.on('beforedestroy', this.clearMons, this, {single: true});
1609 if(Ext.isObject(ename)){
1610 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
1617 if(Ext.isFunction(o[e])){
1620 item: item, ename: e, fn: o[e], scope: o.scope
1622 item.on(e, o[e], o.scope, o);
1624 // individual options
1626 item: item, ename: e, fn: o[e], scope: o.scope
1636 item: item, ename: ename, fn: fn, scope: scope
1638 item.on(ename, fn, scope, opt);
1641 // protected, opposite of mon
1642 mun : function(item, ename, fn, scope){
1644 for(var i = 0, len = this.mons.length; i < len; ++i){
1646 if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){
1647 this.mons.splice(i, 1);
1648 item.un(ename, fn, scope);
1657 * Returns the next component in the owning container
1658 * @return Ext.Component
1660 nextSibling : function(){
1662 var index = this.ownerCt.items.indexOf(this);
1663 if(index != -1 && index+1 < this.ownerCt.items.getCount()){
1664 return this.ownerCt.items.itemAt(index+1);
1671 * Returns the previous component in the owning container
1672 * @return Ext.Component
1674 previousSibling : function(){
1676 var index = this.ownerCt.items.indexOf(this);
1678 return this.ownerCt.items.itemAt(index-1);
1685 * Provides the link for Observable's fireEvent method to bubble up the ownership hierarchy.
1686 * @return {Ext.Container} the Container which owns this Component.
1688 getBubbleTarget : function(){
1689 return this.ownerCt;
1693 Ext.reg('component', Ext.Component);
1695 * @class Ext.Action
\r
1696 * <p>An Action is a piece of reusable functionality that can be abstracted out of any particular component so that it
\r
1697 * can be usefully shared among multiple components. Actions let you share handlers, configuration options and UI
\r
1698 * updates across any components that support the Action interface (primarily {@link Ext.Toolbar}, {@link Ext.Button}
\r
1699 * and {@link Ext.menu.Menu} components).</p>
\r
1700 * <p>Aside from supporting the config object interface, any component that needs to use Actions must also support
\r
1701 * the following method list, as these will be called as needed by the Action class: setText(string), setIconCls(string),
\r
1702 * setDisabled(boolean), setVisible(boolean) and setHandler(function).</p>
\r
1703 * Example usage:<br>
\r
1705 // Define the shared action. Each component below will have the same
\r
1706 // display text and icon, and will display the same message on click.
\r
1707 var action = new Ext.Action({
\r
1708 {@link #text}: 'Do something',
\r
1709 {@link #handler}: function(){
\r
1710 Ext.Msg.alert('Click', 'You did something.');
\r
1712 {@link #iconCls}: 'do-something',
\r
1713 {@link #itemId}: 'myAction'
\r
1716 var panel = new Ext.Panel({
\r
1721 // Add the action directly to a toolbar as a menu button
\r
1724 text: 'Action Menu',
\r
1725 // Add the action to a menu as a text item
\r
1730 // Add the action to the panel body as a standard button
\r
1731 new Ext.Button(action)
\r
1733 renderTo: Ext.getBody()
\r
1736 // Change the text for all components using the action
\r
1737 action.setText('Something else');
\r
1739 // Reference an action through a container using the itemId
\r
1740 var btn = panel.getComponent('myAction');
\r
1741 var aRef = btn.baseAction;
\r
1742 aRef.setText('New text');
\r
1745 * @param {Object} config The configuration options
\r
1747 Ext.Action = function(config){
\r
1748 this.initialConfig = config;
\r
1749 this.itemId = config.itemId = (config.itemId || config.id || Ext.id());
\r
1753 Ext.Action.prototype = {
\r
1755 * @cfg {String} text The text to set for all components using this action (defaults to '').
\r
1758 * @cfg {String} iconCls
\r
1759 * The CSS class selector that specifies a background image to be used as the header icon for
\r
1760 * all components using this action (defaults to '').
\r
1761 * <p>An example of specifying a custom icon class would be something like:
\r
1763 // specify the property in the config for the class:
\r
1765 iconCls: 'do-something'
\r
1767 // css class that specifies background image to be used as the icon image:
\r
1768 .do-something { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
\r
1772 * @cfg {Boolean} disabled True to disable all components using this action, false to enable them (defaults to false).
\r
1775 * @cfg {Boolean} hidden True to hide all components using this action, false to show them (defaults to false).
\r
1778 * @cfg {Function} handler The function that will be invoked by each component tied to this action
\r
1779 * when the component's primary event is triggered (defaults to undefined).
\r
1782 * @cfg {String} itemId
\r
1783 * See {@link Ext.Component}.{@link Ext.Component#itemId itemId}.
\r
1786 * @cfg {Object} scope The scope in which the {@link #handler} function will execute.
\r
1793 * Sets the text to be displayed by all components using this action.
\r
1794 * @param {String} text The text to display
\r
1796 setText : function(text){
\r
1797 this.initialConfig.text = text;
\r
1798 this.callEach('setText', [text]);
\r
1802 * Gets the text currently displayed by all components using this action.
\r
1804 getText : function(){
\r
1805 return this.initialConfig.text;
\r
1809 * Sets the icon CSS class for all components using this action. The class should supply
\r
1810 * a background image that will be used as the icon image.
\r
1811 * @param {String} cls The CSS class supplying the icon image
\r
1813 setIconClass : function(cls){
\r
1814 this.initialConfig.iconCls = cls;
\r
1815 this.callEach('setIconClass', [cls]);
\r
1819 * Gets the icon CSS class currently used by all components using this action.
\r
1821 getIconClass : function(){
\r
1822 return this.initialConfig.iconCls;
\r
1826 * Sets the disabled state of all components using this action. Shortcut method
\r
1827 * for {@link #enable} and {@link #disable}.
\r
1828 * @param {Boolean} disabled True to disable the component, false to enable it
\r
1830 setDisabled : function(v){
\r
1831 this.initialConfig.disabled = v;
\r
1832 this.callEach('setDisabled', [v]);
\r
1836 * Enables all components using this action.
\r
1838 enable : function(){
\r
1839 this.setDisabled(false);
\r
1843 * Disables all components using this action.
\r
1845 disable : function(){
\r
1846 this.setDisabled(true);
\r
1850 * Returns true if the components using this action are currently disabled, else returns false.
\r
1852 isDisabled : function(){
\r
1853 return this.initialConfig.disabled;
\r
1857 * Sets the hidden state of all components using this action. Shortcut method
\r
1858 * for <code>{@link #hide}</code> and <code>{@link #show}</code>.
\r
1859 * @param {Boolean} hidden True to hide the component, false to show it
\r
1861 setHidden : function(v){
\r
1862 this.initialConfig.hidden = v;
\r
1863 this.callEach('setVisible', [!v]);
\r
1867 * Shows all components using this action.
\r
1869 show : function(){
\r
1870 this.setHidden(false);
\r
1874 * Hides all components using this action.
\r
1876 hide : function(){
\r
1877 this.setHidden(true);
\r
1881 * Returns true if the components using this action are currently hidden, else returns false.
\r
1883 isHidden : function(){
\r
1884 return this.initialConfig.hidden;
\r
1888 * Sets the function that will be called by each component using this action when its primary event is triggered.
\r
1889 * @param {Function} fn The function that will be invoked by the action's components. The function
\r
1890 * will be called with no arguments.
\r
1891 * @param {Object} scope The scope in which the function will execute
\r
1893 setHandler : function(fn, scope){
\r
1894 this.initialConfig.handler = fn;
\r
1895 this.initialConfig.scope = scope;
\r
1896 this.callEach('setHandler', [fn, scope]);
\r
1900 * Executes the specified function once for each component currently tied to this action. The function passed
\r
1901 * in should accept a single argument that will be an object that supports the basic Action config/method interface.
\r
1902 * @param {Function} fn The function to execute for each component
\r
1903 * @param {Object} scope The scope in which the function will execute
\r
1905 each : function(fn, scope){
\r
1906 Ext.each(this.items, fn, scope);
\r
1910 callEach : function(fnName, args){
\r
1911 var cs = this.items;
\r
1912 for(var i = 0, len = cs.length; i < len; i++){
\r
1913 cs[i][fnName].apply(cs[i], args);
\r
1918 addComponent : function(comp){
\r
1919 this.items.push(comp);
\r
1920 comp.on('destroy', this.removeComponent, this);
\r
1924 removeComponent : function(comp){
\r
1925 this.items.remove(comp);
\r
1929 * Executes this action manually using the handler function specified in the original config object
\r
1930 * or the handler function set with <code>{@link #setHandler}</code>. Any arguments passed to this
\r
1931 * function will be passed on to the handler function.
\r
1932 * @param {Mixed} arg1 (optional) Variable number of arguments passed to the handler function
\r
1933 * @param {Mixed} arg2 (optional)
\r
1934 * @param {Mixed} etc... (optional)
\r
1936 execute : function(){
\r
1937 this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);
\r
1942 * @extends Ext.Element
1943 * An extended {@link Ext.Element} object that supports a shadow and shim, constrain to viewport and
1944 * automatic maintaining of shadow/shim positions.
1945 * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true)
1946 * @cfg {String/Boolean} shadow True to automatically create an {@link Ext.Shadow}, or a string indicating the
1947 * shadow's display {@link Ext.Shadow#mode}. False to disable the shadow. (defaults to false)
1948 * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: 'div', cls: 'x-layer'}).
1949 * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true)
1950 * @cfg {String} cls CSS class to add to the element
1951 * @cfg {Number} zindex Starting z-index (defaults to 11000)
1952 * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 4)
1953 * @cfg {Boolean} useDisplay
1954 * Defaults to use css offsets to hide the Layer. Specify <tt>true</tt>
1955 * to use css style <tt>'display:none;'</tt> to hide the Layer.
1957 * @param {Object} config An object with config options.
1958 * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element. If the element is not found it creates it.
1961 Ext.Layer = function(config, existingEl){
1962 config = config || {};
1963 var dh = Ext.DomHelper;
1964 var cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body;
1966 this.dom = Ext.getDom(existingEl);
1969 var o = config.dh || {tag: 'div', cls: 'x-layer'};
1970 this.dom = dh.append(pel, o);
1973 this.addClass(config.cls);
1975 this.constrain = config.constrain !== false;
1976 this.setVisibilityMode(Ext.Element.VISIBILITY);
1978 this.id = this.dom.id = config.id;
1980 this.id = Ext.id(this.dom);
1982 this.zindex = config.zindex || this.getZIndex();
1983 this.position('absolute', this.zindex);
1985 this.shadowOffset = config.shadowOffset || 4;
1986 this.shadow = new Ext.Shadow({
1987 offset : this.shadowOffset,
1988 mode : config.shadow
1991 this.shadowOffset = 0;
1993 this.useShim = config.shim !== false && Ext.useShims;
1994 this.useDisplay = config.useDisplay;
1998 var supr = Ext.Element.prototype;
2000 // shims are shared among layer to keep from having 100 iframes
2003 Ext.extend(Ext.Layer, Ext.Element, {
2005 getZIndex : function(){
2006 return this.zindex || parseInt((this.getShim() || this).getStyle('z-index'), 10) || 11000;
2009 getShim : function(){
2016 var shim = shims.shift();
2018 shim = this.createShim();
2019 shim.enableDisplayMode('block');
2020 shim.dom.style.display = 'none';
2021 shim.dom.style.visibility = 'visible';
2023 var pn = this.dom.parentNode;
2024 if(shim.dom.parentNode != pn){
2025 pn.insertBefore(shim.dom, this.dom);
2027 shim.setStyle('z-index', this.getZIndex()-2);
2032 hideShim : function(){
2034 this.shim.setDisplayed(false);
2035 shims.push(this.shim);
2040 disableShadow : function(){
2042 this.shadowDisabled = true;
2044 this.lastShadowOffset = this.shadowOffset;
2045 this.shadowOffset = 0;
2049 enableShadow : function(show){
2051 this.shadowDisabled = false;
2052 this.shadowOffset = this.lastShadowOffset;
2053 delete this.lastShadowOffset;
2061 // this code can execute repeatedly in milliseconds (i.e. during a drag) so
2062 // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
2063 sync : function(doShow){
2064 var sw = this.shadow;
2065 if(!this.updating && this.isVisible() && (sw || this.useShim)){
2066 var sh = this.getShim();
2068 var w = this.getWidth(),
2069 h = this.getHeight();
2071 var l = this.getLeft(true),
2072 t = this.getTop(true);
2074 if(sw && !this.shadowDisabled){
2075 if(doShow && !sw.isVisible()){
2078 sw.realign(l, t, w, h);
2084 // fit the shim behind the shadow, so it is shimmed too
2085 var a = sw.adjusts, s = sh.dom.style;
2086 s.left = (Math.min(l, l+a.l))+'px';
2087 s.top = (Math.min(t, t+a.t))+'px';
2088 s.width = (w+a.w)+'px';
2089 s.height = (h+a.h)+'px';
2096 sh.setLeftTop(l, t);
2103 destroy : function(){
2108 this.removeAllListeners();
2109 Ext.removeNode(this.dom);
2110 Ext.Element.uncache(this.id);
2113 remove : function(){
2118 beginUpdate : function(){
2119 this.updating = true;
2123 endUpdate : function(){
2124 this.updating = false;
2129 hideUnders : function(negOffset){
2137 constrainXY : function(){
2139 var vw = Ext.lib.Dom.getViewWidth(),
2140 vh = Ext.lib.Dom.getViewHeight();
2141 var s = Ext.getDoc().getScroll();
2143 var xy = this.getXY();
2144 var x = xy[0], y = xy[1];
2145 var so = this.shadowOffset;
2146 var w = this.dom.offsetWidth+so, h = this.dom.offsetHeight+so;
2147 // only move it if it needs it
2149 // first validate right/bottom
2150 if((x + w) > vw+s.left){
2154 if((y + h) > vh+s.top){
2158 // then make sure top/left isn't negative
2169 var ay = this.avoidY;
2170 if(y <= ay && (y+h) >= ay){
2176 supr.setXY.call(this, xy);
2183 isVisible : function(){
2184 return this.visible;
2188 showAction : function(){
2189 this.visible = true; // track visibility to prevent getStyle calls
2190 if(this.useDisplay === true){
2191 this.setDisplayed('');
2192 }else if(this.lastXY){
2193 supr.setXY.call(this, this.lastXY);
2194 }else if(this.lastLT){
2195 supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
2200 hideAction : function(){
2201 this.visible = false;
2202 if(this.useDisplay === true){
2203 this.setDisplayed(false);
2205 this.setLeftTop(-10000,-10000);
2209 // overridden Element method
2210 setVisible : function(v, a, d, c, e){
2215 var cb = function(){
2220 }.createDelegate(this);
2221 supr.setVisible.call(this, true, true, d, cb, e);
2224 this.hideUnders(true);
2233 }.createDelegate(this);
2235 supr.setVisible.call(this, v, a, d, cb, e);
2245 storeXY : function(xy){
2250 storeLeftTop : function(left, top){
2252 this.lastLT = [left, top];
2256 beforeFx : function(){
2257 this.beforeAction();
2258 return Ext.Layer.superclass.beforeFx.apply(this, arguments);
2262 afterFx : function(){
2263 Ext.Layer.superclass.afterFx.apply(this, arguments);
2264 this.sync(this.isVisible());
2268 beforeAction : function(){
2269 if(!this.updating && this.shadow){
2274 // overridden Element method
2275 setLeft : function(left){
2276 this.storeLeftTop(left, this.getTop(true));
2277 supr.setLeft.apply(this, arguments);
2282 setTop : function(top){
2283 this.storeLeftTop(this.getLeft(true), top);
2284 supr.setTop.apply(this, arguments);
2289 setLeftTop : function(left, top){
2290 this.storeLeftTop(left, top);
2291 supr.setLeftTop.apply(this, arguments);
2296 setXY : function(xy, a, d, c, e){
2298 this.beforeAction();
2300 var cb = this.createCB(c);
2301 supr.setXY.call(this, xy, a, d, cb, e);
2309 createCB : function(c){
2320 // overridden Element method
2321 setX : function(x, a, d, c, e){
2322 this.setXY([x, this.getY()], a, d, c, e);
2326 // overridden Element method
2327 setY : function(y, a, d, c, e){
2328 this.setXY([this.getX(), y], a, d, c, e);
2332 // overridden Element method
2333 setSize : function(w, h, a, d, c, e){
2334 this.beforeAction();
2335 var cb = this.createCB(c);
2336 supr.setSize.call(this, w, h, a, d, cb, e);
2343 // overridden Element method
2344 setWidth : function(w, a, d, c, e){
2345 this.beforeAction();
2346 var cb = this.createCB(c);
2347 supr.setWidth.call(this, w, a, d, cb, e);
2354 // overridden Element method
2355 setHeight : function(h, a, d, c, e){
2356 this.beforeAction();
2357 var cb = this.createCB(c);
2358 supr.setHeight.call(this, h, a, d, cb, e);
2365 // overridden Element method
2366 setBounds : function(x, y, w, h, a, d, c, e){
2367 this.beforeAction();
2368 var cb = this.createCB(c);
2370 this.storeXY([x, y]);
2371 supr.setXY.call(this, [x, y]);
2372 supr.setSize.call(this, w, h, a, d, cb, e);
2375 supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
2381 * Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
2382 * incremented by two more than the value passed in so that it always shows above any shadow or shim (the shadow
2383 * element, if any, will be assigned z-index + 1, and the shim element, if any, will be assigned the unmodified z-index).
2384 * @param {Number} zindex The new z-index to set
2385 * @return {this} The Layer
2387 setZIndex : function(zindex){
2388 this.zindex = zindex;
2389 this.setStyle('z-index', zindex + 2);
2391 this.shadow.setZIndex(zindex + 1);
2394 this.shim.setStyle('z-index', zindex);
2401 * Simple class that can provide a shadow effect for any element. Note that the element MUST be absolutely positioned,
2402 * and the shadow does not provide any shimming. This should be used only in simple cases -- for more advanced
2403 * functionality that can also provide the same shadow effect, see the {@link Ext.Layer} class.
2405 * Create a new Shadow
2406 * @param {Object} config The config object
2408 Ext.Shadow = function(config){
2409 Ext.apply(this, config);
2410 if(typeof this.mode != "string"){
2411 this.mode = this.defaultMode;
2413 var o = this.offset, a = {h: 0};
2414 var rad = Math.floor(this.offset/2);
2415 switch(this.mode.toLowerCase()){ // all this hideous nonsense calculates the various offsets for shadows
2421 a.l -= this.offset + rad;
2422 a.t -= this.offset + rad;
2433 a.l -= (this.offset - rad);
2434 a.t -= this.offset + rad;
2436 a.w -= (this.offset - rad)*2;
2447 a.l -= (this.offset - rad);
2448 a.t -= (this.offset - rad);
2450 a.w -= (this.offset + rad + 1);
2451 a.h -= (this.offset + rad);
2460 Ext.Shadow.prototype = {
2462 * @cfg {String} mode
2463 * The shadow display mode. Supports the following options:<div class="mdetail-params"><ul>
2464 * <li><b><tt>sides</tt></b> : Shadow displays on both sides and bottom only</li>
2465 * <li><b><tt>frame</tt></b> : Shadow displays equally on all four sides</li>
2466 * <li><b><tt>drop</tt></b> : Traditional bottom-right drop shadow</li>
2470 * @cfg {String} offset
2471 * The number of pixels to offset the shadow from the element (defaults to <tt>4</tt>)
2476 defaultMode: "drop",
2479 * Displays the shadow under the target element
2480 * @param {Mixed} targetEl The id or element under which the shadow should display
2482 show : function(target){
2483 target = Ext.get(target);
2485 this.el = Ext.Shadow.Pool.pull();
2486 if(this.el.dom.nextSibling != target.dom){
2487 this.el.insertBefore(target);
2490 this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
2492 this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
2495 target.getLeft(true),
2496 target.getTop(true),
2500 this.el.dom.style.display = "block";
2504 * Returns true if the shadow is visible, else false
2506 isVisible : function(){
2507 return this.el ? true : false;
2511 * Direct alignment when values are already available. Show must be called at least once before
2512 * calling this method to ensure it is initialized.
2513 * @param {Number} left The target element left position
2514 * @param {Number} top The target element top position
2515 * @param {Number} width The target element width
2516 * @param {Number} height The target element height
2518 realign : function(l, t, w, h){
2522 var a = this.adjusts, d = this.el.dom, s = d.style;
2524 s.left = (l+a.l)+"px";
2525 s.top = (t+a.t)+"px";
2526 var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
2527 if(s.width != sws || s.height != shs){
2531 var cn = d.childNodes;
2532 var sww = Math.max(0, (sw-12))+"px";
2533 cn[0].childNodes[1].style.width = sww;
2534 cn[1].childNodes[1].style.width = sww;
2535 cn[2].childNodes[1].style.width = sww;
2536 cn[1].style.height = Math.max(0, (sh-12))+"px";
2546 this.el.dom.style.display = "none";
2547 Ext.Shadow.Pool.push(this.el);
2553 * Adjust the z-index of this shadow
2554 * @param {Number} zindex The new z-index
2556 setZIndex : function(z){
2559 this.el.setStyle("z-index", z);
2564 // Private utility class that manages the internal Shadow cache
2565 Ext.Shadow.Pool = function(){
2567 var markup = Ext.isIE ?
2568 '<div class="x-ie-shadow"></div>' :
2569 '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';
2574 sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
2575 sh.autoBoxAdjust = false;
2580 push : function(sh){
2585 * @class Ext.BoxComponent
2586 * @extends Ext.Component
2587 * <p>Base class for any {@link Ext.Component Component} that is to be sized as a box, using width and height.</p>
2588 * <p>BoxComponent provides automatic box model adjustments for sizing and positioning and will work correctly
2589 * within the Component rendering model.</p>
2590 * <p>A BoxComponent may be created as a custom Component which encapsulates any HTML element, either a pre-existing
2591 * element, or one that is created to your specifications at render time. Usually, to participate in layouts,
2592 * a Component will need to be a <b>Box</b>Component in order to have its width and height managed.</p>
2593 * <p>To use a pre-existing element as a BoxComponent, configure it so that you preset the <b>el</b> property to the
2594 * element to reference:<pre><code>
2595 var pageHeader = new Ext.BoxComponent({
2598 * This may then be {@link Ext.Container#add added} to a {@link Ext.Container Container} as a child item.</p>
2599 * <p>To create a BoxComponent based around a HTML element to be created at render time, use the
2600 * {@link Ext.Component#autoEl autoEl} config option which takes the form of a
2601 * {@link Ext.DomHelper DomHelper} specification:<pre><code>
2602 var myImage = new Ext.BoxComponent({
2605 src: '/images/my-image.jpg'
2607 });</code></pre></p>
2609 * @param {Ext.Element/String/Object} config The configuration options.
2612 Ext.BoxComponent = Ext.extend(Ext.Component, {
2614 // Configs below are used for all Components when rendered by BorderLayout.
2616 * @cfg {String} region <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2617 * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2618 * layout manager (e.g. specifying <tt>layout:'border'</tt>).</p><br>
2619 * <p>See {@link Ext.layout.BorderLayout} also.</p>
2621 // margins config is used when a BoxComponent is rendered by BorderLayout or BoxLayout.
2623 * @cfg {Object} margins <p><b>Note</b>: this config is only used when this BoxComponent is rendered
2624 * by a Container which has been configured to use the <b>{@link Ext.layout.BorderLayout BorderLayout}</b>
2625 * or one of the two <b>{@link Ext.layout.BoxLayout BoxLayout} subclasses.</b></p>
2626 * <p>An object containing margins to apply to this BoxComponent in the
2627 * format:</p><pre><code>
2630 right: (right margin),
2631 bottom: (bottom margin),
2634 * <p>May also be a string containing space-separated, numeric margin values. The order of the
2635 * sides associated with each value matches the way CSS processes margin values:</p>
2636 * <p><div class="mdetail-params"><ul>
2637 * <li>If there is only one value, it applies to all sides.</li>
2638 * <li>If there are two values, the top and bottom borders are set to the first value and the
2639 * right and left are set to the second.</li>
2640 * <li>If there are three values, the top is set to the first value, the left and right are set
2641 * to the second, and the bottom is set to the third.</li>
2642 * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
2644 * <p>Defaults to:</p><pre><code>
2645 * {top:0, right:0, bottom:0, left:0}
2650 * The local x (left) coordinate for this component if contained within a positioning container.
2654 * The local y (top) coordinate for this component if contained within a positioning container.
2657 * @cfg {Number} pageX
2658 * The page level x coordinate for this component if contained within a positioning container.
2661 * @cfg {Number} pageY
2662 * The page level y coordinate for this component if contained within a positioning container.
2665 * @cfg {Number} height
2666 * The height of this component in pixels (defaults to auto).
2667 * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
2670 * @cfg {Number} width
2671 * The width of this component in pixels (defaults to auto).
2672 * <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
2675 * @cfg {Boolean} autoHeight
2676 * <p>True to use height:'auto', false to use fixed height (or allow it to be managed by its parent
2677 * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
2678 * <p><b>Note</b>: Although many components inherit this config option, not all will
2679 * function as expected with a height of 'auto'. Setting autoHeight:true means that the
2680 * browser will manage height based on the element's contents, and that Ext will not manage it at all.</p>
2681 * <p>If the <i>browser</i> is managing the height, be aware that resizes performed by the browser in response
2682 * to changes within the structure of the Component cannot be detected. Therefore changes to the height might
2683 * result in elements needing to be synchronized with the new height. Example:</p><pre><code>
2684 var w = new Ext.Window({
2689 title: 'Collapse Me',
2694 beforecollapse: function() {
2697 beforeexpand: function() {
2700 collapse: function() {
2703 expand: function() {
2712 * @cfg {Boolean} autoWidth
2713 * <p>True to use width:'auto', false to use fixed width (or allow it to be managed by its parent
2714 * Container's {@link Ext.Container#layout layout manager}. Defaults to false.</p>
2715 * <p><b>Note</b>: Although many components inherit this config option, not all will
2716 * function as expected with a width of 'auto'. Setting autoWidth:true means that the
2717 * browser will manage width based on the element's contents, and that Ext will not manage it at all.</p>
2718 * <p>If the <i>browser</i> is managing the width, be aware that resizes performed by the browser in response
2719 * to changes within the structure of the Component cannot be detected. Therefore changes to the width might
2720 * result in elements needing to be synchronized with the new width. For example, where the target element is:</p><pre><code>
2721 <div id='grid-container' style='margin-left:25%;width:50%'></div>
2723 * A Panel rendered into that target element must listen for browser window resize in order to relay its
2724 * child items when the browser changes its width:<pre><code>
2725 var myPanel = new Ext.Panel({
2726 renderTo: 'grid-container',
2727 monitorResize: true, // relay on browser resize
2749 /* // private internal config
2750 * {Boolean} deferHeight
2751 * True to defer height calculations to an external component, false to allow this component to set its own
2752 * height (defaults to false).
2756 initComponent : function(){
2757 Ext.BoxComponent.superclass.initComponent.call(this);
2761 * Fires after the component is resized.
2762 * @param {Ext.Component} this
2763 * @param {Number} adjWidth The box-adjusted width that was set
2764 * @param {Number} adjHeight The box-adjusted height that was set
2765 * @param {Number} rawWidth The width that was originally specified
2766 * @param {Number} rawHeight The height that was originally specified
2771 * Fires after the component is moved.
2772 * @param {Ext.Component} this
2773 * @param {Number} x The new x position
2774 * @param {Number} y The new y position
2780 // private, set in afterRender to signify that the component has been rendered
2782 // private, used to defer height settings to subclasses
2786 * Sets the width and height of this BoxComponent. This method fires the {@link #resize} event. This method can accept
2787 * either width and height as separate arguments, or you can pass a size object like <code>{width:10, height:20}</code>.
2788 * @param {Mixed} width The new width to set. This may be one of:<div class="mdetail-params"><ul>
2789 * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
2790 * <li>A String used to set the CSS width style.</li>
2791 * <li>A size object in the format <code>{width: widthValue, height: heightValue}</code>.</li>
2792 * <li><code>undefined</code> to leave the width unchanged.</li>
2794 * @param {Mixed} height The new height to set (not required if a size object is passed as the first arg).
2795 * This may be one of:<div class="mdetail-params"><ul>
2796 * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
2797 * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
2798 * <li><code>undefined</code> to leave the height unchanged.</li>
2800 * @return {Ext.BoxComponent} this
2802 setSize : function(w, h){
2803 // support for standard size objects
2804 if(typeof w == 'object'){
2815 // prevent recalcs when not needed
2816 if(this.cacheSizes !== false && this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
2819 this.lastSize = {width: w, height: h};
2820 var adj = this.adjustSize(w, h);
2821 var aw = adj.width, ah = adj.height;
2822 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
2823 var rz = this.getResizeEl();
2824 if(!this.deferHeight && aw !== undefined && ah !== undefined){
2826 }else if(!this.deferHeight && ah !== undefined){
2828 }else if(aw !== undefined){
2831 this.onResize(aw, ah, w, h);
2832 this.fireEvent('resize', this, aw, ah, w, h);
2838 * Sets the width of the component. This method fires the {@link #resize} event.
2839 * @param {Number} width The new width to setThis may be one of:<div class="mdetail-params"><ul>
2840 * <li>A Number specifying the new width in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
2841 * <li>A String used to set the CSS width style.</li>
2843 * @return {Ext.BoxComponent} this
2845 setWidth : function(width){
2846 return this.setSize(width);
2850 * Sets the height of the component. This method fires the {@link #resize} event.
2851 * @param {Number} height The new height to set. This may be one of:<div class="mdetail-params"><ul>
2852 * <li>A Number specifying the new height in the {@link #getEl Element}'s {@link Ext.Element#defaultUnit}s (by default, pixels).</li>
2853 * <li>A String used to set the CSS height style.</li>
2854 * <li><i>undefined</i> to leave the height unchanged.</li>
2856 * @return {Ext.BoxComponent} this
2858 setHeight : function(height){
2859 return this.setSize(undefined, height);
2863 * Gets the current size of the component's underlying element.
2864 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
2866 getSize : function(){
2867 return this.getResizeEl().getSize();
2871 * Gets the current width of the component's underlying element.
2874 getWidth : function(){
2875 return this.getResizeEl().getWidth();
2879 * Gets the current height of the component's underlying element.
2882 getHeight : function(){
2883 return this.getResizeEl().getHeight();
2887 * Gets the current size of the component's underlying element, including space taken by its margins.
2888 * @return {Object} An object containing the element's size {width: (element width + left/right margins), height: (element height + top/bottom margins)}
2890 getOuterSize : function(){
2891 var el = this.getResizeEl();
2892 return {width: el.getWidth() + el.getMargins('lr'),
2893 height: el.getHeight() + el.getMargins('tb')};
2897 * Gets the current XY position of the component's underlying element.
2898 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
2899 * @return {Array} The XY position of the element (e.g., [100, 200])
2901 getPosition : function(local){
2902 var el = this.getPositionEl();
2904 return [el.getLeft(true), el.getTop(true)];
2906 return this.xy || el.getXY();
2910 * Gets the current box measurements of the component's underlying element.
2911 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
2912 * @return {Object} box An object in the format {x, y, width, height}
2914 getBox : function(local){
2915 var pos = this.getPosition(local);
2916 var s = this.getSize();
2923 * Sets the current box measurements of the component's underlying element.
2924 * @param {Object} box An object in the format {x, y, width, height}
2925 * @return {Ext.BoxComponent} this
2927 updateBox : function(box){
2928 this.setSize(box.width, box.height);
2929 this.setPagePosition(box.x, box.y);
2934 * <p>Returns the outermost Element of this Component which defines the Components overall size.</p>
2935 * <p><i>Usually</i> this will return the same Element as <code>{@link #getEl}</code>,
2936 * but in some cases, a Component may have some more wrapping Elements around its main
2937 * active Element.</p>
2938 * <p>An example is a ComboBox. It is encased in a <i>wrapping</i> Element which
2939 * contains both the <code><input></code> Element (which is what would be returned
2940 * by its <code>{@link #getEl}</code> method, <i>and</i> the trigger button Element.
2941 * This Element is returned as the <code>resizeEl</code>.
2943 getResizeEl : function(){
2944 return this.resizeEl || this.el;
2948 getPositionEl : function(){
2949 return this.positionEl || this.el;
2953 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
2954 * This method fires the {@link #move} event.
2955 * @param {Number} left The new left
2956 * @param {Number} top The new top
2957 * @return {Ext.BoxComponent} this
2959 setPosition : function(x, y){
2960 if(x && typeof x[1] == 'number'){
2969 var adj = this.adjustPosition(x, y);
2970 var ax = adj.x, ay = adj.y;
2972 var el = this.getPositionEl();
2973 if(ax !== undefined || ay !== undefined){
2974 if(ax !== undefined && ay !== undefined){
2975 el.setLeftTop(ax, ay);
2976 }else if(ax !== undefined){
2978 }else if(ay !== undefined){
2981 this.onPosition(ax, ay);
2982 this.fireEvent('move', this, ax, ay);
2988 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
2989 * This method fires the {@link #move} event.
2990 * @param {Number} x The new x position
2991 * @param {Number} y The new y position
2992 * @return {Ext.BoxComponent} this
2994 setPagePosition : function(x, y){
2995 if(x && typeof x[1] == 'number'){
3004 if(x === undefined || y === undefined){ // cannot translate undefined points
3007 var p = this.getPositionEl().translatePoints(x, y);
3008 this.setPosition(p.left, p.top);
3013 onRender : function(ct, position){
3014 Ext.BoxComponent.superclass.onRender.call(this, ct, position);
3016 this.resizeEl = Ext.get(this.resizeEl);
3018 if(this.positionEl){
3019 this.positionEl = Ext.get(this.positionEl);
3024 afterRender : function(){
3025 Ext.BoxComponent.superclass.afterRender.call(this);
3026 this.boxReady = true;
3027 this.setSize(this.width, this.height);
3028 if(this.x || this.y){
3029 this.setPosition(this.x, this.y);
3030 }else if(this.pageX || this.pageY){
3031 this.setPagePosition(this.pageX, this.pageY);
3036 * Force the component's size to recalculate based on the underlying element's current height and width.
3037 * @return {Ext.BoxComponent} this
3039 syncSize : function(){
3040 delete this.lastSize;
3041 this.setSize(this.autoWidth ? undefined : this.getResizeEl().getWidth(), this.autoHeight ? undefined : this.getResizeEl().getHeight());
3046 * Called after the component is resized, this method is empty by default but can be implemented by any
3047 * subclass that needs to perform custom logic after a resize occurs.
3048 * @param {Number} adjWidth The box-adjusted width that was set
3049 * @param {Number} adjHeight The box-adjusted height that was set
3050 * @param {Number} rawWidth The width that was originally specified
3051 * @param {Number} rawHeight The height that was originally specified
3053 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
3058 * Called after the component is moved, this method is empty by default but can be implemented by any
3059 * subclass that needs to perform custom logic after a move occurs.
3060 * @param {Number} x The new x position
3061 * @param {Number} y The new y position
3063 onPosition : function(x, y){
3068 adjustSize : function(w, h){
3072 if(this.autoHeight){
3075 return {width : w, height: h};
3079 adjustPosition : function(x, y){
3080 return {x : x, y: y};
3083 Ext.reg('box', Ext.BoxComponent);
3088 * @extends Ext.BoxComponent
3089 * <p>Used to provide a sizable space in a layout.</p>
3091 * @param {Object} config
3093 Ext.Spacer = Ext.extend(Ext.BoxComponent, {
3096 Ext.reg('spacer', Ext.Spacer);/**
\r
3097 * @class Ext.SplitBar
\r
3098 * @extends Ext.util.Observable
\r
3099 * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).
\r
3103 var split = new Ext.SplitBar("elementToDrag", "elementToSize",
\r
3104 Ext.SplitBar.HORIZONTAL, Ext.SplitBar.LEFT);
\r
3105 split.setAdapter(new Ext.SplitBar.AbsoluteLayoutAdapter("container"));
\r
3106 split.minSize = 100;
\r
3107 split.maxSize = 600;
\r
3108 split.animate = true;
\r
3109 split.on('moved', splitterMoved);
\r
3112 * Create a new SplitBar
\r
3113 * @param {Mixed} dragElement The element to be dragged and act as the SplitBar.
\r
3114 * @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged
\r
3115 * @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
\r
3116 * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or
\r
3117 Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial
\r
3118 position of the SplitBar).
\r
3120 Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
\r
3123 this.el = Ext.get(dragElement, true);
\r
3124 this.el.dom.unselectable = "on";
\r
3126 this.resizingEl = Ext.get(resizingElement, true);
\r
3130 * The orientation of the split. Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
\r
3131 * Note: If this is changed after creating the SplitBar, the placement property must be manually updated
\r
3134 this.orientation = orientation || Ext.SplitBar.HORIZONTAL;
\r
3137 * The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.
\r
3139 * @property tickSize
\r
3142 * The minimum size of the resizing element. (Defaults to 0)
\r
3148 * The maximum size of the resizing element. (Defaults to 2000)
\r
3151 this.maxSize = 2000;
\r
3154 * Whether to animate the transition to the new size
\r
3157 this.animate = false;
\r
3160 * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.
\r
3163 this.useShim = false;
\r
3168 if(!existingProxy){
\r
3170 this.proxy = Ext.SplitBar.createProxy(this.orientation);
\r
3172 this.proxy = Ext.get(existingProxy).dom;
\r
3175 this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
\r
3178 this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
\r
3181 this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
\r
3184 this.dragSpecs = {};
\r
3187 * @private The adapter to use to positon and resize elements
\r
3189 this.adapter = new Ext.SplitBar.BasicLayoutAdapter();
\r
3190 this.adapter.init(this);
\r
3192 if(this.orientation == Ext.SplitBar.HORIZONTAL){
\r
3194 this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);
\r
3195 this.el.addClass("x-splitbar-h");
\r
3198 this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);
\r
3199 this.el.addClass("x-splitbar-v");
\r
3205 * Fires when the splitter is moved (alias for {@link #moved})
\r
3206 * @param {Ext.SplitBar} this
\r
3207 * @param {Number} newSize the new width or height
\r
3212 * Fires when the splitter is moved
\r
3213 * @param {Ext.SplitBar} this
\r
3214 * @param {Number} newSize the new width or height
\r
3218 * @event beforeresize
\r
3219 * Fires before the splitter is dragged
\r
3220 * @param {Ext.SplitBar} this
\r
3227 Ext.SplitBar.superclass.constructor.call(this);
\r
3230 Ext.extend(Ext.SplitBar, Ext.util.Observable, {
\r
3231 onStartProxyDrag : function(x, y){
\r
3232 this.fireEvent("beforeresize", this);
\r
3233 this.overlay = Ext.DomHelper.append(document.body, {cls: "x-drag-overlay", html: " "}, true);
\r
3234 this.overlay.unselectable();
\r
3235 this.overlay.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
\r
3236 this.overlay.show();
\r
3237 Ext.get(this.proxy).setDisplayed("block");
\r
3238 var size = this.adapter.getElementSize(this);
\r
3239 this.activeMinSize = this.getMinimumSize();
\r
3240 this.activeMaxSize = this.getMaximumSize();
\r
3241 var c1 = size - this.activeMinSize;
\r
3242 var c2 = Math.max(this.activeMaxSize - size, 0);
\r
3243 if(this.orientation == Ext.SplitBar.HORIZONTAL){
\r
3244 this.dd.resetConstraints();
\r
3245 this.dd.setXConstraint(
\r
3246 this.placement == Ext.SplitBar.LEFT ? c1 : c2,
\r
3247 this.placement == Ext.SplitBar.LEFT ? c2 : c1,
\r
3250 this.dd.setYConstraint(0, 0);
\r
3252 this.dd.resetConstraints();
\r
3253 this.dd.setXConstraint(0, 0);
\r
3254 this.dd.setYConstraint(
\r
3255 this.placement == Ext.SplitBar.TOP ? c1 : c2,
\r
3256 this.placement == Ext.SplitBar.TOP ? c2 : c1,
\r
3260 this.dragSpecs.startSize = size;
\r
3261 this.dragSpecs.startPoint = [x, y];
\r
3262 Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
\r
3266 * @private Called after the drag operation by the DDProxy
\r
3268 onEndProxyDrag : function(e){
\r
3269 Ext.get(this.proxy).setDisplayed(false);
\r
3270 var endPoint = Ext.lib.Event.getXY(e);
\r
3272 Ext.destroy(this.overlay);
\r
3273 delete this.overlay;
\r
3276 if(this.orientation == Ext.SplitBar.HORIZONTAL){
\r
3277 newSize = this.dragSpecs.startSize +
\r
3278 (this.placement == Ext.SplitBar.LEFT ?
\r
3279 endPoint[0] - this.dragSpecs.startPoint[0] :
\r
3280 this.dragSpecs.startPoint[0] - endPoint[0]
\r
3283 newSize = this.dragSpecs.startSize +
\r
3284 (this.placement == Ext.SplitBar.TOP ?
\r
3285 endPoint[1] - this.dragSpecs.startPoint[1] :
\r
3286 this.dragSpecs.startPoint[1] - endPoint[1]
\r
3289 newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
\r
3290 if(newSize != this.dragSpecs.startSize){
\r
3291 if(this.fireEvent('beforeapply', this, newSize) !== false){
\r
3292 this.adapter.setElementSize(this, newSize);
\r
3293 this.fireEvent("moved", this, newSize);
\r
3294 this.fireEvent("resize", this, newSize);
\r
3300 * Get the adapter this SplitBar uses
\r
3301 * @return The adapter object
\r
3303 getAdapter : function(){
\r
3304 return this.adapter;
\r
3308 * Set the adapter this SplitBar uses
\r
3309 * @param {Object} adapter A SplitBar adapter object
\r
3311 setAdapter : function(adapter){
\r
3312 this.adapter = adapter;
\r
3313 this.adapter.init(this);
\r
3317 * Gets the minimum size for the resizing element
\r
3318 * @return {Number} The minimum size
\r
3320 getMinimumSize : function(){
\r
3321 return this.minSize;
\r
3325 * Sets the minimum size for the resizing element
\r
3326 * @param {Number} minSize The minimum size
\r
3328 setMinimumSize : function(minSize){
\r
3329 this.minSize = minSize;
\r
3333 * Gets the maximum size for the resizing element
\r
3334 * @return {Number} The maximum size
\r
3336 getMaximumSize : function(){
\r
3337 return this.maxSize;
\r
3341 * Sets the maximum size for the resizing element
\r
3342 * @param {Number} maxSize The maximum size
\r
3344 setMaximumSize : function(maxSize){
\r
3345 this.maxSize = maxSize;
\r
3349 * Sets the initialize size for the resizing element
\r
3350 * @param {Number} size The initial size
\r
3352 setCurrentSize : function(size){
\r
3353 var oldAnimate = this.animate;
\r
3354 this.animate = false;
\r
3355 this.adapter.setElementSize(this, size);
\r
3356 this.animate = oldAnimate;
\r
3360 * Destroy this splitbar.
\r
3361 * @param {Boolean} removeEl True to remove the element
\r
3363 destroy : function(removeEl){
\r
3364 Ext.destroy(this.shim, Ext.get(this.proxy));
\r
3369 this.purgeListeners();
\r
3374 * @private static Create our own proxy element element. So it will be the same same size on all browsers, we won't use borders. Instead we use a background color.
\r
3376 Ext.SplitBar.createProxy = function(dir){
\r
3377 var proxy = new Ext.Element(document.createElement("div"));
\r
3378 proxy.unselectable();
\r
3379 var cls = 'x-splitbar-proxy';
\r
3380 proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
\r
3381 document.body.appendChild(proxy.dom);
\r
3386 * @class Ext.SplitBar.BasicLayoutAdapter
\r
3387 * Default Adapter. It assumes the splitter and resizing element are not positioned
\r
3388 * elements and only gets/sets the width of the element. Generally used for table based layouts.
\r
3390 Ext.SplitBar.BasicLayoutAdapter = function(){
\r
3393 Ext.SplitBar.BasicLayoutAdapter.prototype = {
\r
3394 // do nothing for now
\r
3395 init : function(s){
\r
3399 * Called before drag operations to get the current size of the resizing element.
\r
3400 * @param {Ext.SplitBar} s The SplitBar using this adapter
\r
3402 getElementSize : function(s){
\r
3403 if(s.orientation == Ext.SplitBar.HORIZONTAL){
\r
3404 return s.resizingEl.getWidth();
\r
3406 return s.resizingEl.getHeight();
\r
3411 * Called after drag operations to set the size of the resizing element.
\r
3412 * @param {Ext.SplitBar} s The SplitBar using this adapter
\r
3413 * @param {Number} newSize The new size to set
\r
3414 * @param {Function} onComplete A function to be invoked when resizing is complete
\r
3416 setElementSize : function(s, newSize, onComplete){
\r
3417 if(s.orientation == Ext.SplitBar.HORIZONTAL){
\r
3419 s.resizingEl.setWidth(newSize);
\r
3421 onComplete(s, newSize);
\r
3424 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
\r
3429 s.resizingEl.setHeight(newSize);
\r
3431 onComplete(s, newSize);
\r
3434 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
\r
3441 *@class Ext.SplitBar.AbsoluteLayoutAdapter
\r
3442 * @extends Ext.SplitBar.BasicLayoutAdapter
\r
3443 * Adapter that moves the splitter element to align with the resized sizing element.
\r
3444 * Used with an absolute positioned SplitBar.
\r
3445 * @param {Mixed} container The container that wraps around the absolute positioned content. If it's
\r
3446 * document.body, make sure you assign an id to the body element.
\r
3448 Ext.SplitBar.AbsoluteLayoutAdapter = function(container){
\r
3449 this.basic = new Ext.SplitBar.BasicLayoutAdapter();
\r
3450 this.container = Ext.get(container);
\r
3453 Ext.SplitBar.AbsoluteLayoutAdapter.prototype = {
\r
3454 init : function(s){
\r
3455 this.basic.init(s);
\r
3458 getElementSize : function(s){
\r
3459 return this.basic.getElementSize(s);
\r
3462 setElementSize : function(s, newSize, onComplete){
\r
3463 this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
\r
3466 moveSplitter : function(s){
\r
3467 var yes = Ext.SplitBar;
\r
3468 switch(s.placement){
\r
3470 s.el.setX(s.resizingEl.getRight());
\r
3473 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
\r
3476 s.el.setY(s.resizingEl.getBottom());
\r
3479 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
\r
3486 * Orientation constant - Create a vertical SplitBar
\r
3490 Ext.SplitBar.VERTICAL = 1;
\r
3493 * Orientation constant - Create a horizontal SplitBar
\r
3497 Ext.SplitBar.HORIZONTAL = 2;
\r
3500 * Placement constant - The resizing element is to the left of the splitter element
\r
3504 Ext.SplitBar.LEFT = 1;
\r
3507 * Placement constant - The resizing element is to the right of the splitter element
\r
3511 Ext.SplitBar.RIGHT = 2;
\r
3514 * Placement constant - The resizing element is positioned above the splitter element
\r
3518 Ext.SplitBar.TOP = 3;
\r
3521 * Placement constant - The resizing element is positioned under splitter element
\r
3525 Ext.SplitBar.BOTTOM = 4;
\r
3527 * @class Ext.Container
3528 * @extends Ext.BoxComponent
3529 * <p>Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the
3530 * basic behavior of containing items, namely adding, inserting and removing items.</p>
3532 * <p>The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}.
3533 * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight
3534 * Container to be encapsulated by an HTML element to your specifications by using the
3535 * <tt><b>{@link Ext.Component#autoEl autoEl}</b></tt> config option. This is a useful technique when creating
3536 * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels}
3539 * <p>The code below illustrates both how to explicitly create a Container, and how to implicitly
3540 * create one using the <b><tt>'container'</tt></b> xtype:<pre><code>
3541 // explicitly create a Container
3542 var embeddedColumns = new Ext.Container({
3543 autoEl: 'div', // This is the default
3546 // implicitly create Container by specifying xtype
3548 autoEl: 'div', // This is the default.
3555 // The two items below will be Ext.Containers, each encapsulated by a <DIV> element.
3560 fieldLabel: 'Start date'
3566 fieldLabel: 'End date'
3569 });</code></pre></p>
3571 * <p><u><b>Layout</b></u></p>
3572 * <p>Container classes delegate the rendering of child Components to a layout
3573 * manager class which must be configured into the Container using the
3574 * <code><b>{@link #layout}</b></code> configuration property.</p>
3575 * <p>When either specifying child <code>{@link #items}</code> of a Container,
3576 * or dynamically {@link #add adding} Components to a Container, remember to
3577 * consider how you wish the Container to arrange those child elements, and
3578 * whether those child elements need to be sized using one of Ext's built-in
3579 * <b><code>{@link #layout}</code></b> schemes. By default, Containers use the
3580 * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only
3581 * renders child components, appending them one after the other inside the
3582 * Container, and <b>does not apply any sizing</b> at all.</p>
3583 * <p>A common mistake is when a developer neglects to specify a
3584 * <b><code>{@link #layout}</code></b> (e.g. widgets like GridPanels or
3585 * TreePanels are added to Containers for which no <tt><b>{@link #layout}</b></tt>
3586 * has been specified). If a Container is left to use the default
3587 * {@link Ext.layout.ContainerLayout ContainerLayout} scheme, none of its
3588 * child components will be resized, or changed in any way when the Container
3590 * <p>Certain layout managers allow dynamic addition of child components.
3591 * Those that do include {@link Ext.layout.CardLayout},
3592 * {@link Ext.layout.AnchorLayout}, {@link Ext.layout.FormLayout}, and
3593 * {@link Ext.layout.TableLayout}. For example:<pre><code>
3594 // Create the GridPanel.
3595 var myNewGrid = new Ext.grid.GridPanel({
3597 columns: myColumnModel,
3598 title: 'Results', // the title becomes the title of the tab
3601 myTabPanel.add(myNewGrid); // {@link Ext.TabPanel} implicitly uses {@link Ext.layout.CardLayout CardLayout}
3602 myTabPanel.{@link Ext.TabPanel#setActiveTab setActiveTab}(myNewGrid);
3604 * <p>The example above adds a newly created GridPanel to a TabPanel. Note that
3605 * a TabPanel uses {@link Ext.layout.CardLayout} as its layout manager which
3606 * means all its child items are sized to {@link Ext.layout.FitLayout fit}
3607 * exactly into its client area.
3608 * <p><b><u>Overnesting is a common problem</u></b>.
3609 * An example of overnesting occurs when a GridPanel is added to a TabPanel
3610 * by wrapping the GridPanel <i>inside</i> a wrapping Panel (that has no
3611 * <tt><b>{@link #layout}</b></tt> specified) and then add that wrapping Panel
3612 * to the TabPanel. The point to realize is that a GridPanel <b>is</b> a
3613 * Component which can be added directly to a Container. If the wrapping Panel
3614 * has no <tt><b>{@link #layout}</b></tt> configuration, then the overnested
3615 * GridPanel will not be sized as expected.<p>
3618 * <p><u><b>Adding via remote configuration</b></u></p>
3620 * <p>A server side script can be used to add Components which are generated dynamically on the server.
3621 * An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server
3622 * based on certain parameters:
3624 // execute an Ajax request to invoke server side script:
3626 url: 'gen-invoice-grid.php',
3627 // send additional parameters to instruct server script
3629 startDate: Ext.getCmp('start-date').getValue(),
3630 endDate: Ext.getCmp('end-date').getValue()
3632 // process the response object to add it to the TabPanel:
3633 success: function(xhr) {
3634 var newComponent = eval(xhr.responseText); // see discussion below
3635 myTabPanel.add(newComponent); // add the component to the TabPanel
3636 myTabPanel.setActiveTab(newComponent);
3638 failure: function() {
3639 Ext.Msg.alert("Grid create failed", "Server communication failure");
3643 * <p>The server script needs to return an executable Javascript statement which, when processed
3644 * using <tt>eval()</tt>, will return either a config object with an {@link Ext.Component#xtype xtype},
3645 * or an instantiated Component. The server might return this for example:</p><pre><code>
3647 function formatDate(value){
3648 return value ? value.dateFormat('M d, Y') : '';
3651 var store = new Ext.data.Store({
3652 url: 'get-invoice-data.php',
3654 startDate: '01/01/2008',
3655 endDate: '01/31/2008'
3657 reader: new Ext.data.JsonReader({
3658 record: 'transaction',
3660 totalRecords: 'total'
3664 {name: 'date', type: 'date', dateFormat: 'm/d/Y'},
3665 {name: 'value', type: 'float'}
3669 var grid = new Ext.grid.GridPanel({
3670 title: 'Invoice Report',
3671 bbar: new Ext.PagingToolbar(store),
3674 {header: "Customer", width: 250, dataIndex: 'customer', sortable: true},
3675 {header: "Invoice Number", width: 120, dataIndex: 'invNo', sortable: true},
3676 {header: "Invoice Date", width: 100, dataIndex: 'date', renderer: formatDate, sortable: true},
3677 {header: "Value", width: 120, dataIndex: 'value', renderer: 'usMoney', sortable: true}
3681 return grid; // return instantiated component
3684 * <p>When the above code fragment is passed through the <tt>eval</tt> function in the success handler
3685 * of the Ajax request, the code is executed by the Javascript processor, and the anonymous function
3686 * runs, and returns the instantiated grid component.</p>
3687 * <p>Note: since the code above is <i>generated</i> by a server script, the <tt>baseParams</tt> for
3688 * the Store, the metadata to allow generation of the Record layout, and the ColumnModel
3689 * can all be generated into the code since these are all known on the server.</p>
3693 Ext.Container = Ext.extend(Ext.BoxComponent, {
3695 * @cfg {Boolean} monitorResize
3696 * True to automatically monitor window resize events to handle anything that is sensitive to the current size
3697 * of the viewport. This value is typically managed by the chosen <code>{@link #layout}</code> and should not need
3698 * to be set manually.
3701 * @cfg {String/Object} layout
3702 * When creating complex UIs, it is important to remember that sizing and
3703 * positioning of child items is the responsibility of the Container's
3704 * layout manager. If you expect child items to be sized in response to
3705 * user interactions, <b>you must specify a layout manager</b> which
3706 * creates and manages the type of layout you have in mind. For example:<pre><code>
3708 width:300, height: 300,
3709 layout: 'fit', // explicitly set layout manager: override the default (layout:'auto')
3711 title: 'Panel inside a Window'
3715 * <p>Omitting the {@link #layout} config means that the
3716 * {@link Ext.layout.ContainerLayout default layout manager} will be used which does
3717 * nothing but render child components sequentially into the Container (no sizing or
3718 * positioning will be performed in this situation).</p>
3719 * <p>The layout manager class for this container may be specified as either as an
3720 * Object or as a String:</p>
3721 * <div><ul class="mdetail-params">
3723 * <li><u>Specify as an Object</u></li>
3724 * <div><ul class="mdetail-params">
3725 * <li>Example usage:</li>
3734 * <li><tt><b>type</b></tt></li>
3735 * <br/><p>The layout type to be used for this container. If not specified,
3736 * a default {@link Ext.layout.ContainerLayout} will be created and used.</p>
3737 * <br/><p>Valid layout <tt>type</tt> values are:</p>
3738 * <div class="sub-desc"><ul class="mdetail-params">
3739 * <li><tt><b>{@link Ext.layout.AbsoluteLayout absolute}</b></tt></li>
3740 * <li><tt><b>{@link Ext.layout.AccordionLayout accordion}</b></tt></li>
3741 * <li><tt><b>{@link Ext.layout.AnchorLayout anchor}</b></tt></li>
3742 * <li><tt><b>{@link Ext.layout.ContainerLayout auto}</b></tt> <b>Default</b></li>
3743 * <li><tt><b>{@link Ext.layout.BorderLayout border}</b></tt></li>
3744 * <li><tt><b>{@link Ext.layout.CardLayout card}</b></tt></li>
3745 * <li><tt><b>{@link Ext.layout.ColumnLayout column}</b></tt></li>
3746 * <li><tt><b>{@link Ext.layout.FitLayout fit}</b></tt></li>
3747 * <li><tt><b>{@link Ext.layout.FormLayout form}</b></tt></li>
3748 * <li><tt><b>{@link Ext.layout.HBoxLayout hbox}</b></tt></li>
3749 * <li><tt><b>{@link Ext.layout.MenuLayout menu}</b></tt></li>
3750 * <li><tt><b>{@link Ext.layout.TableLayout table}</b></tt></li>
3751 * <li><tt><b>{@link Ext.layout.ToolbarLayout toolbar}</b></tt></li>
3752 * <li><tt><b>{@link Ext.layout.VBoxLayout vbox}</b></tt></li>
3755 * <li>Layout specific configuration properties</li>
3756 * <br/><p>Additional layout specific configuration properties may also be
3757 * specified. For complete details regarding the valid config options for
3758 * each layout type, see the layout class corresponding to the <tt>type</tt>
3763 * <li><u>Specify as a String</u></li>
3764 * <div><ul class="mdetail-params">
3765 * <li>Example usage:</li>
3773 * <li><tt><b>layout</b></tt></li>
3774 * <br/><p>The layout <tt>type</tt> to be used for this container (see list
3775 * of valid layout type values above).</p><br/>
3776 * <li><tt><b>{@link #layoutConfig}</b></tt></li>
3777 * <br/><p>Additional layout specific configuration properties. For complete
3778 * details regarding the valid config options for each layout type, see the
3779 * layout class corresponding to the <tt>layout</tt> specified.</p>
3780 * </ul></div></ul></div>
3783 * @cfg {Object} layoutConfig
3784 * This is a config object containing properties specific to the chosen
3785 * <b><code>{@link #layout}</code></b> if <b><code>{@link #layout}</code></b>
3786 * has been specified as a <i>string</i>.</p>
3789 * @cfg {Boolean/Number} bufferResize
3790 * When set to true (100 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer
3791 * the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers
3792 * with a large quantity of sub-components for which frequent layout calls would be expensive.
3797 * @cfg {String/Number} activeItem
3798 * A string component id or the numeric index of the component that should be initially activated within the
3799 * container's layout on render. For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first
3800 * item in the container's collection). activeItem only applies to layout styles that can display
3801 * items one at a time (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout} and
3802 * {@link Ext.layout.FitLayout}). Related to {@link Ext.layout.ContainerLayout#activeItem}.
3805 * @cfg {Object/Array} items
3806 * <pre><b>** IMPORTANT</b>: be sure to specify a <b><code>{@link #layout}</code> ! **</b></pre>
3807 * <p>A single item, or an array of child Components to be added to this container,
3810 // specifying a single item
3812 layout: 'fit', // specify a layout!
3814 // specifying multiple items
3815 items: [{...}, {...}],
3816 layout: 'anchor', // specify a layout!
3818 * <p>Each item may be:</p>
3819 * <div><ul class="mdetail-params">
3820 * <li>any type of object based on {@link Ext.Component}</li>
3821 * <li>a fully instanciated object or</li>
3822 * <li>an object literal that:</li>
3823 * <div><ul class="mdetail-params">
3824 * <li>has a specified <code>{@link Ext.Component#xtype xtype}</code></li>
3825 * <li>the {@link Ext.Component#xtype} specified is associated with the Component
3826 * desired and should be chosen from one of the available xtypes as listed
3827 * in {@link Ext.Component}.</li>
3828 * <li>If an <code>{@link Ext.Component#xtype xtype}</code> is not explicitly
3829 * specified, the {@link #defaultType} for that Container is used.</li>
3830 * <li>will be "lazily instanciated", avoiding the overhead of constructing a fully
3831 * instanciated Component object</li>
3832 * </ul></div></ul></div>
3833 * <p><b>Notes</b>:</p>
3834 * <div><ul class="mdetail-params">
3835 * <li>Ext uses lazy rendering. Child Components will only be rendered
3836 * should it become necessary. Items are automatically laid out when they are first
3837 * shown (no sizing is done while hidden), or in response to a {@link #doLayout} call.</li>
3838 * <li>Do not specify <code>{@link Ext.Panel#contentEl contentEl}</code>/
3839 * <code>{@link Ext.Panel#html html}</code> with <code>items</code>.</li>
3843 * @cfg {Object} defaults
3844 * <p>A config object that will be applied to all components added to this container either via the {@link #items}
3845 * config or via the {@link #add} or {@link #insert} methods. The <tt>defaults</tt> config can contain any
3846 * number of name/value property pairs to be added to each item, and should be valid for the types of items
3847 * being added to the container. For example, to automatically apply padding to the body of each of a set of
3848 * contained {@link Ext.Panel} items, you could pass: <tt>defaults: {bodyStyle:'padding:15px'}</tt>.</p><br/>
3849 * <p><b>Note</b>: <tt>defaults</tt> will not be applied to config objects if the option is already specified.
3850 * For example:</p><pre><code>
3851 defaults: { // defaults are applied to items, not the container
3856 xtype: 'panel', // defaults <b>do not</b> have precedence over
3857 id: 'panel1', // options in config objects, so the defaults
3858 autoScroll: false // will not be applied here, panel1 will be autoScroll:false
3860 new Ext.Panel({ // defaults <b>do</b> have precedence over options
3861 id: 'panel2', // options in components, so the defaults
3862 autoScroll: false // will be applied here, panel2 will be autoScroll:true.
3869 /** @cfg {Boolean} autoDestroy
3870 * If true the container will automatically destroy any contained component that is removed from it, else
3871 * destruction must be handled manually (defaults to true).
3875 /** @cfg {Boolean} forceLayout
3876 * If true the container will force a layout initially even if hidden or collapsed. This option
3877 * is useful for forcing forms to render in collapsed or hidden containers. (defaults to false).
3881 /** @cfg {Boolean} hideBorders
3882 * True to hide the borders of each contained component, false to defer to the component's existing
3883 * border settings (defaults to false).
3885 /** @cfg {String} defaultType
3886 * <p>The default {@link Ext.Component xtype} of child Components to create in this Container when
3887 * a child item is specified as a raw configuration object, rather than as an instantiated Component.</p>
3888 * <p>Defaults to <tt>'panel'</tt>, except {@link Ext.menu.Menu} which defaults to <tt>'menuitem'</tt>,
3889 * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to <tt>'button'</tt>.</p>
3891 defaultType : 'panel',
3894 initComponent : function(){
3895 Ext.Container.superclass.initComponent.call(this);
3899 * @event afterlayout
3900 * Fires when the components in this container are arranged by the associated layout manager.
3901 * @param {Ext.Container} this
3902 * @param {ContainerLayout} layout The ContainerLayout implementation for this container
3907 * Fires before any {@link Ext.Component} is added or inserted into the container.
3908 * A handler can return false to cancel the add.
3909 * @param {Ext.Container} this
3910 * @param {Ext.Component} component The component being added
3911 * @param {Number} index The index at which the component will be added to the container's items collection
3915 * @event beforeremove
3916 * Fires before any {@link Ext.Component} is removed from the container. A handler can return
3917 * false to cancel the remove.
3918 * @param {Ext.Container} this
3919 * @param {Ext.Component} component The component being removed
3925 * Fires after any {@link Ext.Component} is added or inserted into the container.
3926 * @param {Ext.Container} this
3927 * @param {Ext.Component} component The component that was added
3928 * @param {Number} index The index at which the component was added to the container's items collection
3934 * Fires after any {@link Ext.Component} is removed from the container.
3935 * @param {Ext.Container} this
3936 * @param {Ext.Component} component The component that was removed
3941 this.enableBubble('add', 'remove');
3944 * The collection of components in this container as a {@link Ext.util.MixedCollection}
3945 * @type MixedCollection
3948 var items = this.items;
3951 if(Ext.isArray(items) && items.length > 0){
3952 this.add.apply(this, items);
3960 initItems : function(){
3962 this.items = new Ext.util.MixedCollection(false, this.getComponentId);
3963 this.getLayout(); // initialize the layout
3968 setLayout : function(layout){
3969 if(this.layout && this.layout != layout){
3970 this.layout.setContainer(null);
3973 this.layout = layout;
3974 layout.setContainer(this);
3978 render : function(){
3979 Ext.Container.superclass.render.apply(this, arguments);
3981 if(Ext.isObject(this.layout) && !this.layout.layout){
3982 this.layoutConfig = this.layout;
3983 this.layout = this.layoutConfig.type;
3985 if(typeof this.layout == 'string'){
3986 this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
3988 this.setLayout(this.layout);
3990 if(this.activeItem !== undefined){
3991 var item = this.activeItem;
3992 delete this.activeItem;
3993 this.layout.setActiveItem(item);
3997 // force a layout if no ownerCt is set
3998 this.doLayout(false, true);
4000 if(this.monitorResize === true){
4001 Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
4006 * <p>Returns the Element to be used to contain the child Components of this Container.</p>
4007 * <p>An implementation is provided which returns the Container's {@link #getEl Element}, but
4008 * if there is a more complex structure to a Container, this may be overridden to return
4009 * the element into which the {@link #layout layout} renders child Components.</p>
4010 * @return {Ext.Element} The Element to render child Components into.
4012 getLayoutTarget : function(){
4016 // private - used as the key lookup function for the items collection
4017 getComponentId : function(comp){
4018 return comp.getItemId();
4022 * <p>Adds {@link Ext.Component Component}(s) to this Container.</p>
4023 * <br><p><b>Description</b></u> :
4024 * <div><ul class="mdetail-params">
4025 * <li>Fires the {@link #beforeadd} event before adding</li>
4026 * <li>The Container's {@link #defaults default config values} will be applied
4027 * accordingly (see <code>{@link #defaults}</code> for details).</li>
4028 * <li>Fires the {@link #add} event after the component has been added.</li>
4030 * <br><p><b>Notes</b></u> :
4031 * <div><ul class="mdetail-params">
4032 * <li>If the Container is <i>already rendered</i> when <tt>add</tt>
4033 * is called, you may need to call {@link #doLayout} to refresh the view which causes
4034 * any unrendered child Components to be rendered. This is required so that you can
4035 * <tt>add</tt> multiple child components if needed while only refreshing the layout
4036 * once. For example:<pre><code>
4037 var tb = new {@link Ext.Toolbar}();
4038 tb.render(document.body); // toolbar is rendered
4039 tb.add({text:'Button 1'}); // add multiple items ({@link #defaultType} for {@link Ext.Toolbar Toolbar} is 'button')
4040 tb.add({text:'Button 2'});
4041 tb.{@link #doLayout}(); // refresh the layout
4042 * </code></pre></li>
4043 * <li><i>Warning:</i> Containers directly managed by the BorderLayout layout manager
4044 * may not be removed or added. See the Notes for {@link Ext.layout.BorderLayout BorderLayout}
4045 * for more details.</li>
4047 * @param {Object/Array} component
4048 * <p>Either a single component or an Array of components to add. See
4049 * <code>{@link #items}</code> for additional information.</p>
4050 * @param {Object} (Optional) component_2
4051 * @param {Object} (Optional) component_n
4052 * @return {Ext.Component} component The Component (or config object) that was added.
4054 add : function(comp){
4056 var args = arguments.length > 1;
4057 if(args || Ext.isArray(comp)){
4058 Ext.each(args ? arguments : comp, function(c){
4063 var c = this.lookupComponent(this.applyDefaults(comp));
4064 var pos = this.items.length;
4065 if(this.fireEvent('beforeadd', this, c, pos) !== false && this.onBeforeAdd(c) !== false){
4068 this.fireEvent('add', this, c, pos);
4074 * Inserts a Component into this Container at a specified index. Fires the
4075 * {@link #beforeadd} event before inserting, then fires the {@link #add} event after the
4076 * Component has been inserted.
4077 * @param {Number} index The index at which the Component will be inserted
4078 * into the Container's items collection
4079 * @param {Ext.Component} component The child Component to insert.<br><br>
4080 * Ext uses lazy rendering, and will only render the inserted Component should
4081 * it become necessary.<br><br>
4082 * A Component config object may be passed in order to avoid the overhead of
4083 * constructing a real Component object if lazy rendering might mean that the
4084 * inserted Component will not be rendered immediately. To take advantage of
4085 * this 'lazy instantiation', set the {@link Ext.Component#xtype} config
4086 * property to the registered type of the Component wanted.<br><br>
4087 * For a list of all available xtypes, see {@link Ext.Component}.
4088 * @return {Ext.Component} component The Component (or config object) that was
4089 * inserted with the Container's default config values applied.
4091 insert : function(index, comp){
4093 var a = arguments, len = a.length;
4095 for(var i = len-1; i >= 1; --i) {
4096 this.insert(index, a[i]);
4100 var c = this.lookupComponent(this.applyDefaults(comp));
4102 if(c.ownerCt == this && this.items.indexOf(c) < index){
4106 if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
4107 this.items.insert(index, c);
4109 this.fireEvent('add', this, c, index);
4115 applyDefaults : function(c){
4117 if(typeof c == 'string'){
4118 c = Ext.ComponentMgr.get(c);
4119 Ext.apply(c, this.defaults);
4120 }else if(!c.events){
4121 Ext.applyIf(c, this.defaults);
4123 Ext.apply(c, this.defaults);
4130 onBeforeAdd : function(item){
4132 item.ownerCt.remove(item, false);
4134 if(this.hideBorders === true){
4135 item.border = (item.border === true);
4140 * Removes a component from this container. Fires the {@link #beforeremove} event before removing, then fires
4141 * the {@link #remove} event after the component has been removed.
4142 * @param {Component/String} component The component reference or id to remove.
4143 * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
4144 * Defaults to the value of this Container's {@link #autoDestroy} config.
4145 * @return {Ext.Component} component The Component that was removed.
4147 remove : function(comp, autoDestroy){
4149 var c = this.getComponent(comp);
4150 if(c && this.fireEvent('beforeremove', this, c) !== false){
4151 this.items.remove(c);
4153 if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
4156 if(this.layout && this.layout.activeItem == c){
4157 delete this.layout.activeItem;
4159 this.fireEvent('remove', this, c);
4165 * Removes all components from this container.
4166 * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
4167 * Defaults to the value of this Container's {@link #autoDestroy} config.
4168 * @return {Array} Array of the destroyed components
4170 removeAll: function(autoDestroy){
4172 var item, rem = [], items = [];
4173 this.items.each(function(i){
4176 for (var i = 0, len = rem.length; i < len; ++i){
4178 this.remove(item, autoDestroy);
4179 if(item.ownerCt !== this){
4187 * Examines this container's <code>{@link #items}</code> <b>property</b>
4188 * and gets a direct child component of this container.
4189 * @param {String/Number} comp This parameter may be any of the following:
4190 * <div><ul class="mdetail-params">
4191 * <li>a <b><tt>String</tt></b> : representing the <code>{@link Ext.Component#itemId itemId}</code>
4192 * or <code>{@link Ext.Component#id id}</code> of the child component </li>
4193 * <li>a <b><tt>Number</tt></b> : representing the position of the child component
4194 * within the <code>{@link #items}</code> <b>property</b></li>
4196 * <p>For additional information see {@link Ext.util.MixedCollection#get}.
4197 * @return Ext.Component The component (if found).
4199 getComponent : function(comp){
4200 if(Ext.isObject(comp)){
4203 return this.items.get(comp);
4207 lookupComponent : function(comp){
4208 if(typeof comp == 'string'){
4209 return Ext.ComponentMgr.get(comp);
4210 }else if(!comp.events){
4211 return this.createComponent(comp);
4217 createComponent : function(config){
4218 return Ext.create(config, this.defaultType);
4222 * Force this container's layout to be recalculated. A call to this function is required after adding a new component
4223 * to an already rendered container, or possibly after changing sizing/position properties of child components.
4224 * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto
4225 * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer)
4226 * @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden.
4227 * @return {Ext.Container} this
4229 doLayout: function(shallow, force){
4230 var rendered = this.rendered,
4231 forceLayout = this.forceLayout;
4233 if(!this.isVisible() || this.collapsed){
4234 this.deferLayout = this.deferLayout || !shallow;
4235 if(!(force || forceLayout)){
4238 shallow = shallow && !this.deferLayout;
4240 delete this.deferLayout;
4242 if(rendered && this.layout){
4243 this.layout.layout();
4245 if(shallow !== true && this.items){
4246 var cs = this.items.items;
4247 for(var i = 0, len = cs.length; i < len; i++){
4250 c.forceLayout = forceLayout;
4256 this.onLayout(shallow, force);
4258 delete this.forceLayout;
4262 onLayout : Ext.emptyFn,
4264 onShow : function(){
4265 Ext.Container.superclass.onShow.call(this);
4266 if(this.deferLayout !== undefined){
4267 this.doLayout(true);
4272 * Returns the layout currently in use by the container. If the container does not currently have a layout
4273 * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout.
4274 * @return {ContainerLayout} layout The container's layout
4276 getLayout : function(){
4278 var layout = new Ext.layout.ContainerLayout(this.layoutConfig);
4279 this.setLayout(layout);
4285 beforeDestroy : function(){
4287 Ext.destroy.apply(Ext, this.items.items);
4289 if(this.monitorResize){
4290 Ext.EventManager.removeResizeListener(this.doLayout, this);
4292 Ext.destroy(this.layout);
4293 Ext.Container.superclass.beforeDestroy.call(this);
4297 * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of
4298 * function call will be the scope provided or the current component. The arguments to the function
4299 * will be the args provided or the current component. If the function returns false at any point,
4300 * the bubble is stopped.
4301 * @param {Function} fn The function to call
4302 * @param {Object} scope (optional) The scope of the function (defaults to current node)
4303 * @param {Array} args (optional) The args to call the function with (default to passing the current component)
4304 * @return {Ext.Container} this
4306 bubble : function(fn, scope, args){
4309 if(fn.apply(scope || p, args || [p]) === false){
4318 * Cascades down the component/container heirarchy from this component (called first), calling the specified function with
4319 * each component. The scope (<i>this</i>) of
4320 * function call will be the scope provided or the current component. The arguments to the function
4321 * will be the args provided or the current component. If the function returns false at any point,
4322 * the cascade is stopped on that branch.
4323 * @param {Function} fn The function to call
4324 * @param {Object} scope (optional) The scope of the function (defaults to current component)
4325 * @param {Array} args (optional) The args to call the function with (defaults to passing the current component)
4326 * @return {Ext.Container} this
4328 cascade : function(fn, scope, args){
4329 if(fn.apply(scope || this, args || [this]) !== false){
4331 var cs = this.items.items;
4332 for(var i = 0, len = cs.length; i < len; i++){
4334 cs[i].cascade(fn, scope, args);
4336 fn.apply(scope || cs[i], args || [cs[i]]);
4345 * Find a component under this container at any level by id
4346 * @param {String} id
4347 * @return Ext.Component
4349 findById : function(id){
4351 this.cascade(function(c){
4352 if(ct != c && c.id === id){
4361 * Find a component under this container at any level by xtype or class
4362 * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
4363 * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
4364 * the default), or true to check whether this Component is directly of the specified xtype.
4365 * @return {Array} Array of Ext.Components
4367 findByType : function(xtype, shallow){
4368 return this.findBy(function(c){
4369 return c.isXType(xtype, shallow);
4374 * Find a component under this container at any level by property
4375 * @param {String} prop
4376 * @param {String} value
4377 * @return {Array} Array of Ext.Components
4379 find : function(prop, value){
4380 return this.findBy(function(c){
4381 return c[prop] === value;
4386 * Find a component under this container at any level by a custom function. If the passed function returns
4387 * true, the component will be included in the results. The passed function is called with the arguments (component, this container).
4388 * @param {Function} fn The function to call
4389 * @param {Object} scope (optional)
4390 * @return {Array} Array of Ext.Components
4392 findBy : function(fn, scope){
4393 var m = [], ct = this;
4394 this.cascade(function(c){
4395 if(ct != c && fn.call(scope || c, c, ct) === true){
4403 * Get a component contained by this container (alias for items.get(key))
4404 * @param {String/Number} key The index or id of the component
4405 * @return {Ext.Component} Ext.Component
4407 get : function(key){
4408 return this.items.get(key);
4412 Ext.Container.LAYOUTS = {};
4413 Ext.reg('container', Ext.Container);
4415 * @class Ext.layout.ContainerLayout
4416 * <p>The ContainerLayout class is the default layout manager delegated by {@link Ext.Container} to
4417 * render any child Components when no <tt>{@link Ext.Container#layout layout}</tt> is configured into
4418 * a {@link Ext.Container Container}. ContainerLayout provides the basic foundation for all other layout
4419 * classes in Ext. It simply renders all child Components into the Container, performing no sizing or
4420 * positioning services. To utilize a layout that provides sizing and positioning of child Components,
4421 * specify an appropriate <tt>{@link Ext.Container#layout layout}</tt>.</p>
4422 * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
4423 * configuration property. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
4425 Ext.layout.ContainerLayout = function(config){
4426 Ext.apply(this, config);
4429 Ext.layout.ContainerLayout.prototype = {
4431 * @cfg {String} extraCls
4432 * <p>An optional extra CSS class that will be added to the container. This can be useful for adding
4433 * customized styles to the container or any of its children using standard CSS rules. See
4434 * {@link Ext.Component}.{@link Ext.Component#ctCls ctCls} also.</p>
4435 * <p><b>Note</b>: <tt>extraCls</tt> defaults to <tt>''</tt> except for the following classes
4436 * which assign a value by default:
4437 * <div class="mdetail-params"><ul>
4438 * <li>{@link Ext.layout.AbsoluteLayout Absolute Layout} : <tt>'x-abs-layout-item'</tt></li>
4439 * <li>{@link Ext.layout.Box Box Layout} : <tt>'x-box-item'</tt></li>
4440 * <li>{@link Ext.layout.ColumnLayout Column Layout} : <tt>'x-column'</tt></li>
4442 * To configure the above Classes with an extra CSS class append to the default. For example,
4443 * for ColumnLayout:<pre><code>
4444 * extraCls: 'x-column custom-class'
4449 * @cfg {Boolean} renderHidden
4450 * True to hide each contained item on render (defaults to false).
4454 * A reference to the {@link Ext.Component} that is active. For example, <pre><code>
4455 * if(myPanel.layout.activeItem.id == 'item-1') { ... }
4457 * <tt>activeItem</tt> only applies to layout styles that can display items one at a time
4458 * (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout}
4459 * and {@link Ext.layout.FitLayout}). Read-only. Related to {@link Ext.Container#activeItem}.
4460 * @type {Ext.Component}
4461 * @property activeItem
4465 monitorResize:false,
4470 layout : function(){
4471 var target = this.container.getLayoutTarget();
4472 this.onLayout(this.container, target);
4473 this.container.fireEvent('afterlayout', this.container, this);
4477 onLayout : function(ct, target){
4478 this.renderAll(ct, target);
4482 isValidParent : function(c, target){
4483 return target && c.getDomPositionEl().dom.parentNode == (target.dom || target);
4487 renderAll : function(ct, target){
4488 var items = ct.items.items;
4489 for(var i = 0, len = items.length; i < len; i++) {
4491 if(c && (!c.rendered || !this.isValidParent(c, target))){
4492 this.renderItem(c, i, target);
4498 renderItem : function(c, position, target){
4499 if(c && !c.rendered){
4500 c.render(target, position);
4501 this.configureItem(c, position);
4502 }else if(c && !this.isValidParent(c, target)){
4503 if(typeof position == 'number'){
4504 position = target.dom.childNodes[position];
4506 target.dom.insertBefore(c.getDomPositionEl().dom, position || null);
4507 c.container = target;
4508 this.configureItem(c, position);
4513 configureItem: function(c, position){
4515 var t = c.getPositionEl ? c.getPositionEl() : c;
4516 t.addClass(this.extraCls);
4518 if (this.renderHidden && c != this.activeItem) {
4522 c.doLayout(false, this.forceLayout);
4527 onResize: function(){
4528 if(this.container.collapsed){
4531 var b = this.container.bufferResize;
4533 if(!this.resizeTask){
4534 this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this);
4535 this.resizeBuffer = typeof b == 'number' ? b : 100;
4537 this.resizeTask.delay(this.resizeBuffer);
4544 runLayout: function(){
4546 this.container.onLayout();
4550 setContainer : function(ct){
4551 if(this.monitorResize && ct != this.container){
4553 this.container.un('resize', this.onResize, this);
4554 this.container.un('bodyresize', this.onResize, this);
4559 resize: this.onResize,
4560 bodyresize: this.onResize
4564 this.container = ct;
4568 parseMargins : function(v){
4569 if(typeof v == 'number'){
4572 var ms = v.split(' ');
4573 var len = ms.length;
4587 top:parseInt(ms[0], 10) || 0,
4588 right:parseInt(ms[1], 10) || 0,
4589 bottom:parseInt(ms[2], 10) || 0,
4590 left:parseInt(ms[3], 10) || 0
4595 * The {@link Template Ext.Template} used by Field rendering layout classes (such as
4596 * {@link Ext.layout.FormLayout}) to create the DOM structure of a fully wrapped,
4597 * labeled and styled form Field. A default Template is supplied, but this may be
4598 * overriden to create custom field structures. The template processes values returned from
4599 * {@link Ext.layout.FormLayout#getTemplateArgs}.
4600 * @property fieldTpl
4601 * @type Ext.Template
4603 fieldTpl: (function() {
4604 var t = new Ext.Template(
4605 '<div class="x-form-item {itemCls}" tabIndex="-1">',
4606 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
4607 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
4608 '</div><div class="{clearCls}"></div>',
4611 t.disableFormats = true;
4616 * Destroys this layout. This is a template method that is empty by default, but should be implemented
4617 * by subclasses that require explicit destruction to purge event handlers or remove DOM nodes.
4620 destroy : Ext.emptyFn
4622 Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout;/**
\r
4623 * @class Ext.layout.FitLayout
\r
4624 * @extends Ext.layout.ContainerLayout
\r
4625 * <p>This is a base class for layouts that contain <b>a single item</b> that automatically expands to fill the layout's
\r
4626 * container. This class is intended to be extended or created via the <tt>layout:'fit'</tt> {@link Ext.Container#layout}
\r
4627 * config, and should generally not need to be created directly via the new keyword.</p>
\r
4628 * <p>FitLayout does not have any direct config options (other than inherited ones). To fit a panel to a container
\r
4629 * using FitLayout, simply set layout:'fit' on the container and add a single panel to it. If the container has
\r
4630 * multiple panels, only the first one will be displayed. Example usage:</p>
\r
4632 var p = new Ext.Panel({
\r
4633 title: 'Fit Layout',
\r
4636 title: 'Inner Panel',
\r
4637 html: '<p>This is the inner panel content</p>',
\r
4643 Ext.layout.FitLayout = Ext.extend(Ext.layout.ContainerLayout, {
\r
4645 monitorResize:true,
\r
4648 onLayout : function(ct, target){
\r
4649 Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);
\r
4650 if(!this.container.collapsed){
\r
4651 var sz = (Ext.isIE6 && Ext.isStrict && target.dom == document.body) ? target.getViewSize() : target.getStyleSize();
\r
4652 this.setItemSize(this.activeItem || ct.items.itemAt(0), sz);
\r
4657 setItemSize : function(item, size){
\r
4658 if(item && size.height > 0){ // display none?
\r
4659 item.setSize(size);
\r
4663 Ext.Container.LAYOUTS['fit'] = Ext.layout.FitLayout;/**
\r
4664 * @class Ext.layout.CardLayout
\r
4665 * @extends Ext.layout.FitLayout
\r
4666 * <p>This layout manages multiple child Components, each fitted to the Container, where only a single child Component can be
\r
4667 * visible at any given time. This layout style is most commonly used for wizards, tab implementations, etc.
\r
4668 * This class is intended to be extended or created via the layout:'card' {@link Ext.Container#layout} config,
\r
4669 * and should generally not need to be created directly via the new keyword.</p>
\r
4670 * <p>The CardLayout's focal method is {@link #setActiveItem}. Since only one panel is displayed at a time,
\r
4671 * the only way to move from one Component to the next is by calling setActiveItem, passing the id or index of
\r
4672 * the next panel to display. The layout itself does not provide a user interface for handling this navigation,
\r
4673 * so that functionality must be provided by the developer.</p>
\r
4674 * <p>In the following example, a simplistic wizard setup is demonstrated. A button bar is added
\r
4675 * to the footer of the containing panel to provide navigation buttons. The buttons will be handled by a
\r
4676 * common navigation routine -- for this example, the implementation of that routine has been ommitted since
\r
4677 * it can be any type of custom logic. Note that other uses of a CardLayout (like a tab control) would require a
\r
4678 * completely different implementation. For serious implementations, a better approach would be to extend
\r
4679 * CardLayout to provide the custom functionality needed. Example usage:</p>
\r
4681 var navHandler = function(direction){
\r
4682 // This routine could contain business logic required to manage the navigation steps.
\r
4683 // It would call setActiveItem as needed, manage navigation button state, handle any
\r
4684 // branching logic that might be required, handle alternate actions like cancellation
\r
4685 // or finalization, etc. A complete wizard implementation could get pretty
\r
4686 // sophisticated depending on the complexity required, and should probably be
\r
4687 // done as a subclass of CardLayout in a real-world implementation.
\r
4690 var card = new Ext.Panel({
\r
4691 title: 'Example Wizard',
\r
4693 activeItem: 0, // make sure the active item is set on the container config!
\r
4694 bodyStyle: 'padding:15px',
\r
4696 // applied to each contained panel
\r
4699 // just an example of one possible navigation scheme, using buttons
\r
4704 handler: navHandler.createDelegate(this, [-1]),
\r
4707 '->', // greedy spacer so that the buttons are aligned to each side
\r
4711 handler: navHandler.createDelegate(this, [1])
\r
4714 // the panels (or "cards") within the layout
\r
4717 html: '<h1>Welcome to the Wizard!</h1><p>Step 1 of 3</p>'
\r
4720 html: '<p>Step 2 of 3</p>'
\r
4723 html: '<h1>Congratulations!</h1><p>Step 3 of 3 - Complete</p>'
\r
4728 Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, {
\r
4730 * @cfg {Boolean} deferredRender
\r
4731 * True to render each contained item at the time it becomes active, false to render all contained items
\r
4732 * as soon as the layout is rendered (defaults to false). If there is a significant amount of content or
\r
4733 * a lot of heavy controls being rendered into panels that are not displayed by default, setting this to
\r
4734 * true might improve performance.
\r
4736 deferredRender : false,
\r
4739 * @cfg {Boolean} layoutOnCardChange
\r
4740 * True to force a layout of the active item when the active card is changed. Defaults to false.
\r
4742 layoutOnCardChange : false,
\r
4745 * @cfg {Boolean} renderHidden @hide
\r
4748 renderHidden : true,
\r
4750 constructor: function(config){
\r
4751 Ext.layout.CardLayout.superclass.constructor.call(this, config);
\r
4752 this.forceLayout = (this.deferredRender === false);
\r
4756 * Sets the active (visible) item in the layout.
\r
4757 * @param {String/Number} item The string component id or numeric index of the item to activate
\r
4759 setActiveItem : function(item){
\r
4760 item = this.container.getComponent(item);
\r
4761 if(this.activeItem != item){
\r
4762 if(this.activeItem){
\r
4763 this.activeItem.hide();
\r
4765 this.activeItem = item;
\r
4767 this.container.doLayout();
\r
4768 if(this.layoutOnCardChange && item.doLayout){
\r
4775 renderAll : function(ct, target){
\r
4776 if(this.deferredRender){
\r
4777 this.renderItem(this.activeItem, undefined, target);
\r
4779 Ext.layout.CardLayout.superclass.renderAll.call(this, ct, target);
\r
4783 Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;/**
\r
4784 * @class Ext.layout.AnchorLayout
\r
4785 * @extends Ext.layout.ContainerLayout
\r
4786 * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.
\r
4787 * If the container is resized, all anchored items are automatically rerendered according to their
\r
4788 * <b><tt>{@link #anchor}</tt></b> rules.</p>
\r
4789 * <p>This class is intended to be extended or created via the layout:'anchor' {@link Ext.Container#layout}
\r
4790 * config, and should generally not need to be created directly via the new keyword.</p>
\r
4791 * <p>AnchorLayout does not have any direct config options (other than inherited ones). By default,
\r
4792 * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the
\r
4793 * container using the AnchorLayout can supply an anchoring-specific config property of <b>anchorSize</b>.
\r
4794 * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating
\r
4795 * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring
\r
4796 * logic if necessary. For example:</p>
\r
4798 var viewport = new Ext.Viewport({
\r
4800 anchorSize: {width:800, height:600},
\r
4805 anchor:'right 20%'
\r
4820 Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
\r
4822 * @cfg {String} anchor
\r
4823 * <p>This configuation option is to be applied to <b>child <tt>items</tt></b> of a container managed by
\r
4824 * this layout (ie. configured with <tt>layout:'anchor'</tt>).</p><br/>
\r
4826 * <p>This value is what tells the layout how an item should be anchored to the container. <tt>items</tt>
\r
4827 * added to an AnchorLayout accept an anchoring-specific config property of <b>anchor</b> which is a string
\r
4828 * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').
\r
4829 * The following types of anchor values are supported:<div class="mdetail-params"><ul>
\r
4831 * <li><b>Percentage</b> : Any value between 1 and 100, expressed as a percentage.<div class="sub-desc">
\r
4832 * The first anchor is the percentage width that the item should take up within the container, and the
\r
4833 * second is the percentage height. For example:<pre><code>
\r
4834 // two values specified
\r
4835 anchor: '100% 50%' // render item complete width of the container and
\r
4836 // 1/2 height of the container
\r
4837 // one value specified
\r
4838 anchor: '100%' // the width value; the height will default to auto
\r
4839 * </code></pre></div></li>
\r
4841 * <li><b>Offsets</b> : Any positive or negative integer value.<div class="sub-desc">
\r
4842 * This is a raw adjustment where the first anchor is the offset from the right edge of the container,
\r
4843 * and the second is the offset from the bottom edge. For example:<pre><code>
\r
4844 // two values specified
\r
4845 anchor: '-50 -100' // render item the complete width of the container
\r
4846 // minus 50 pixels and
\r
4847 // the complete height minus 100 pixels.
\r
4848 // one value specified
\r
4849 anchor: '-50' // anchor value is assumed to be the right offset value
\r
4850 // bottom offset will default to 0
\r
4851 * </code></pre></div></li>
\r
4853 * <li><b>Sides</b> : Valid values are <tt>'right'</tt> (or <tt>'r'</tt>) and <tt>'bottom'</tt>
\r
4854 * (or <tt>'b'</tt>).<div class="sub-desc">
\r
4855 * Either the container must have a fixed size or an anchorSize config value defined at render time in
\r
4856 * order for these to have any effect.</div></li>
\r
4858 * <li><b>Mixed</b> : <div class="sub-desc">
\r
4859 * Anchor values can also be mixed as needed. For example, to render the width offset from the container
\r
4860 * right edge by 50 pixels and 75% of the container's height use:
\r
4862 anchor: '-50 75%'
\r
4863 * </code></pre></div></li>
\r
4870 monitorResize:true,
\r
4873 getAnchorViewSize : function(ct, target){
\r
4874 return target.dom == document.body ?
\r
4875 target.getViewSize() : target.getStyleSize();
\r
4879 onLayout : function(ct, target){
\r
4880 Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
\r
4882 var size = this.getAnchorViewSize(ct, target);
\r
4884 var w = size.width, h = size.height;
\r
4886 if(w < 20 && h < 20){
\r
4890 // find the container anchoring size
\r
4892 if(ct.anchorSize){
\r
4893 if(typeof ct.anchorSize == 'number'){
\r
4894 aw = ct.anchorSize;
\r
4896 aw = ct.anchorSize.width;
\r
4897 ah = ct.anchorSize.height;
\r
4900 aw = ct.initialConfig.width;
\r
4901 ah = ct.initialConfig.height;
\r
4904 var cs = ct.items.items, len = cs.length, i, c, a, cw, ch;
\r
4905 for(i = 0; i < len; i++){
\r
4909 if(!a){ // cache all anchor values
\r
4910 var vs = c.anchor.split(' ');
\r
4911 c.anchorSpec = a = {
\r
4912 right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
\r
4913 bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
\r
4916 cw = a.right ? this.adjustWidthAnchor(a.right(w), c) : undefined;
\r
4917 ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h), c) : undefined;
\r
4920 c.setSize(cw || undefined, ch || undefined);
\r
4927 parseAnchor : function(a, start, cstart){
\r
4928 if(a && a != 'none'){
\r
4930 if(/^(r|right|b|bottom)$/i.test(a)){ // standard anchor
\r
4931 var diff = cstart - start;
\r
4932 return function(v){
\r
4938 }else if(a.indexOf('%') != -1){
\r
4939 var ratio = parseFloat(a.replace('%', ''))*.01; // percentage
\r
4940 return function(v){
\r
4943 return Math.floor(v*ratio);
\r
4947 a = parseInt(a, 10);
\r
4948 if(!isNaN(a)){ // simple offset adjustment
\r
4949 return function(v){
\r
4962 adjustWidthAnchor : function(value, comp){
\r
4967 adjustHeightAnchor : function(value, comp){
\r
4972 * @property activeItem
\r
4976 Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;/**
\r
4977 * @class Ext.layout.ColumnLayout
\r
4978 * @extends Ext.layout.ContainerLayout
\r
4979 * <p>This is the layout style of choice for creating structural layouts in a multi-column format where the width of
\r
4980 * each column can be specified as a percentage or fixed width, but the height is allowed to vary based on the content.
\r
4981 * This class is intended to be extended or created via the layout:'column' {@link Ext.Container#layout} config,
\r
4982 * and should generally not need to be created directly via the new keyword.</p>
\r
4983 * <p>ColumnLayout does not have any direct config options (other than inherited ones), but it does support a
\r
4984 * specific config property of <b><tt>columnWidth</tt></b> that can be included in the config of any panel added to it. The
\r
4985 * layout will use the columnWidth (if present) or width of each panel during layout to determine how to size each panel.
\r
4986 * If width or columnWidth is not specified for a given panel, its width will default to the panel's width (or auto).</p>
\r
4987 * <p>The width property is always evaluated as pixels, and must be a number greater than or equal to 1.
\r
4988 * The columnWidth property is always evaluated as a percentage, and must be a decimal value greater than 0 and
\r
4989 * less than 1 (e.g., .25).</p>
\r
4990 * <p>The basic rules for specifying column widths are pretty simple. The logic makes two passes through the
\r
4991 * set of contained panels. During the first layout pass, all panels that either have a fixed width or none
\r
4992 * specified (auto) are skipped, but their widths are subtracted from the overall container width. During the second
\r
4993 * pass, all panels with columnWidths are assigned pixel widths in proportion to their percentages based on
\r
4994 * the total <b>remaining</b> container width. In other words, percentage width panels are designed to fill the space
\r
4995 * left over by all the fixed-width and/or auto-width panels. Because of this, while you can specify any number of columns
\r
4996 * with different percentages, the columnWidths must always add up to 1 (or 100%) when added together, otherwise your
\r
4997 * layout may not render as expected. Example usage:</p>
\r
4999 // All columns are percentages -- they must add up to 1
\r
5000 var p = new Ext.Panel({
\r
5001 title: 'Column Layout - Percentage Only',
\r
5004 title: 'Column 1',
\r
5007 title: 'Column 2',
\r
5010 title: 'Column 3',
\r
5015 // Mix of width and columnWidth -- all columnWidth values must add up
\r
5016 // to 1. The first column will take up exactly 120px, and the last two
\r
5017 // columns will fill the remaining container width.
\r
5018 var p = new Ext.Panel({
\r
5019 title: 'Column Layout - Mixed',
\r
5022 title: 'Column 1',
\r
5025 title: 'Column 2',
\r
5028 title: 'Column 3',
\r
5034 Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {
\r
5036 monitorResize:true,
\r
5038 extraCls: 'x-column',
\r
5043 isValidParent : function(c, target){
\r
5044 return (c.getPositionEl ? c.getPositionEl() : c.getEl()).dom.parentNode == this.innerCt.dom;
\r
5048 onLayout : function(ct, target){
\r
5049 var cs = ct.items.items, len = cs.length, c, i;
\r
5051 if(!this.innerCt){
\r
5052 target.addClass('x-column-layout-ct');
\r
5054 // the innerCt prevents wrapping and shuffling while
\r
5055 // the container is resizing
\r
5056 this.innerCt = target.createChild({cls:'x-column-inner'});
\r
5057 this.innerCt.createChild({cls:'x-clear'});
\r
5059 this.renderAll(ct, this.innerCt);
\r
5061 var size = Ext.isIE && target.dom != Ext.getBody().dom ? target.getStyleSize() : target.getViewSize();
\r
5063 if(size.width < 1 && size.height < 1){ // display none?
\r
5067 var w = size.width - target.getPadding('lr') - this.scrollOffset,
\r
5068 h = size.height - target.getPadding('tb'),
\r
5071 this.innerCt.setWidth(w);
\r
5073 // some columns can be percentages while others are fixed
\r
5074 // so we need to make 2 passes
\r
5076 for(i = 0; i < len; i++){
\r
5078 if(!c.columnWidth){
\r
5079 pw -= (c.getSize().width + c.getEl().getMargins('lr'));
\r
5083 pw = pw < 0 ? 0 : pw;
\r
5085 for(i = 0; i < len; i++){
\r
5087 if(c.columnWidth){
\r
5088 c.setSize(Math.floor(c.columnWidth*pw) - c.getEl().getMargins('lr'));
\r
5094 * @property activeItem
\r
5099 Ext.Container.LAYOUTS['column'] = Ext.layout.ColumnLayout;/**
5100 * @class Ext.layout.BorderLayout
5101 * @extends Ext.layout.ContainerLayout
5102 * <p>This is a multi-pane, application-oriented UI layout style that supports multiple
5103 * nested panels, automatic {@link Ext.layout.BorderLayout.Region#split split} bars between
5104 * {@link Ext.layout.BorderLayout.Region#BorderLayout.Region regions} and built-in
5105 * {@link Ext.layout.BorderLayout.Region#collapsible expanding and collapsing} of regions.</p>
5106 * <p>This class is intended to be extended or created via the <tt>layout:'border'</tt>
5107 * {@link Ext.Container#layout} config, and should generally not need to be created directly
5108 * via the new keyword.</p>
5109 * <p>BorderLayout does not have any direct config options (other than inherited ones).
5110 * All configuration options available for customizing the BorderLayout are at the
5111 * {@link Ext.layout.BorderLayout.Region} and {@link Ext.layout.BorderLayout.SplitRegion}
5113 * <p>Example usage:</p>
5115 var myBorderPanel = new Ext.Panel({
5116 {@link Ext.Component#renderTo renderTo}: document.body,
5117 {@link Ext.BoxComponent#width width}: 700,
5118 {@link Ext.BoxComponent#height height}: 500,
5119 {@link Ext.Panel#title title}: 'Border Layout',
5120 {@link Ext.Container#layout layout}: 'border',
5121 {@link Ext.Container#items items}: [{
5122 {@link Ext.Panel#title title}: 'South Region is resizable',
5123 {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south', // position for region
5124 {@link Ext.BoxComponent#height height}: 100,
5125 {@link Ext.layout.BorderLayout.Region#split split}: true, // enable resizing
5126 {@link Ext.SplitBar#minSize minSize}: 75, // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50}
5127 {@link Ext.SplitBar#maxSize maxSize}: 150,
5128 {@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5'
5130 // xtype: 'panel' implied by default
5131 {@link Ext.Panel#title title}: 'West Region is collapsible',
5132 {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}:'west',
5133 {@link Ext.layout.BorderLayout.Region#margins margins}: '5 0 0 5',
5134 {@link Ext.BoxComponent#width width}: 200,
5135 {@link Ext.layout.BorderLayout.Region#collapsible collapsible}: true, // make collapsible
5136 {@link Ext.layout.BorderLayout.Region#cmargins cmargins}: '5 5 0 5', // adjust top margin when collapsed
5137 {@link Ext.Component#id id}: 'west-region-container',
5138 {@link Ext.Container#layout layout}: 'fit',
5139 {@link Ext.Panel#unstyled unstyled}: true
5141 {@link Ext.Panel#title title}: 'Center Region',
5142 {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'center', // center region is required, no width/height specified
5143 {@link Ext.Component#xtype xtype}: 'container',
5144 {@link Ext.Container#layout layout}: 'fit',
5145 {@link Ext.layout.BorderLayout.Region#margins margins}: '5 5 0 0'
5149 * <p><b><u>Notes</u></b>:</p><div class="mdetail-params"><ul>
5150 * <li>Any container using the BorderLayout <b>must</b> have a child item with <tt>region:'center'</tt>.
5151 * The child item in the center region will always be resized to fill the remaining space not used by
5152 * the other regions in the layout.</li>
5153 * <li>Any child items with a region of <tt>west</tt> or <tt>east</tt> must have <tt>width</tt> defined
5154 * (an integer representing the number of pixels that the region should take up).</li>
5155 * <li>Any child items with a region of <tt>north</tt> or <tt>south</tt> must have <tt>height</tt> defined.</li>
5156 * <li>The regions of a BorderLayout are <b>fixed at render time</b> and thereafter, its child Components may not be removed or added</b>. To add/remove
5157 * Components within a BorderLayout, have them wrapped by an additional Container which is directly
5158 * managed by the BorderLayout. If the region is to be collapsible, the Container used directly
5159 * by the BorderLayout manager should be a Panel. In the following example a Container (an Ext.Panel)
5160 * is added to the west region:
5161 * <div style="margin-left:16px"><pre><code>
5162 wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container');
5163 wrc.{@link Ext.Panel#removeAll removeAll}();
5164 wrc.{@link Ext.Container#add add}({
5165 title: 'Added Panel',
5166 html: 'Some content'
5168 wrc.{@link Ext.Container#doLayout doLayout}();
5169 * </code></pre></div>
5171 * <li> To reference a {@link Ext.layout.BorderLayout.Region Region}:
5172 * <div style="margin-left:16px"><pre><code>
5173 wr = myBorderPanel.layout.west;
5174 * </code></pre></div>
5178 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
5185 onLayout : function(ct, target){
5188 target.addClass('x-border-layout-ct');
5189 var items = ct.items.items;
5191 for(var i = 0, len = items.length; i < len; i++) {
5197 c.collapsed = false;
5199 c.cls = c.cls ? c.cls +' x-border-panel' : 'x-border-panel';
5200 c.render(target, i);
5202 this[pos] = pos != 'center' && c.split ?
5203 new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
5204 new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
5205 this[pos].render(target, c);
5207 this.rendered = true;
5210 var size = target.getViewSize();
5211 if(size.width < 20 || size.height < 20){ // display none?
5213 this.restoreCollapsed = collapsed;
5216 }else if(this.restoreCollapsed){
5217 collapsed = this.restoreCollapsed;
5218 delete this.restoreCollapsed;
5221 var w = size.width, h = size.height;
5222 var centerW = w, centerH = h, centerY = 0, centerX = 0;
5224 var n = this.north, s = this.south, west = this.west, e = this.east, c = this.center;
5225 if(!c && Ext.layout.BorderLayout.WARN !== false){
5226 throw 'No center region defined in BorderLayout ' + ct.id;
5229 if(n && n.isVisible()){
5230 var b = n.getSize();
5231 var m = n.getMargins();
5232 b.width = w - (m.left+m.right);
5235 centerY = b.height + b.y + m.bottom;
5239 if(s && s.isVisible()){
5240 var b = s.getSize();
5241 var m = s.getMargins();
5242 b.width = w - (m.left+m.right);
5244 var totalHeight = (b.height + m.top + m.bottom);
5245 b.y = h - totalHeight + m.top;
5246 centerH -= totalHeight;
5249 if(west && west.isVisible()){
5250 var b = west.getSize();
5251 var m = west.getMargins();
5252 b.height = centerH - (m.top+m.bottom);
5254 b.y = centerY + m.top;
5255 var totalWidth = (b.width + m.left + m.right);
5256 centerX += totalWidth;
5257 centerW -= totalWidth;
5258 west.applyLayout(b);
5260 if(e && e.isVisible()){
5261 var b = e.getSize();
5262 var m = e.getMargins();
5263 b.height = centerH - (m.top+m.bottom);
5264 var totalWidth = (b.width + m.left + m.right);
5265 b.x = w - totalWidth + m.left;
5266 b.y = centerY + m.top;
5267 centerW -= totalWidth;
5271 var m = c.getMargins();
5273 x: centerX + m.left,
5275 width: centerW - (m.left+m.right),
5276 height: centerH - (m.top+m.bottom)
5278 c.applyLayout(centerBox);
5281 for(var i = 0, len = collapsed.length; i < len; i++){
5282 collapsed[i].collapse(false);
5285 if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue
5290 destroy: function() {
5291 var r = ['north', 'south', 'east', 'west'];
5292 for (var i = 0; i < r.length; i++) {
5293 var region = this[r[i]];
5297 }else if (region.split){
5298 region.split.destroy(true);
5302 Ext.layout.BorderLayout.superclass.destroy.call(this);
5306 * @property activeItem
5312 * @class Ext.layout.BorderLayout.Region
5313 * <p>This is a region of a {@link Ext.layout.BorderLayout BorderLayout} that acts as a subcontainer
5314 * within the layout. Each region has its own {@link Ext.layout.ContainerLayout layout} that is
5315 * independent of other regions and the containing BorderLayout, and can be any of the
5316 * {@link Ext.layout.ContainerLayout valid Ext layout types}.</p>
5317 * <p>Region size is managed automatically and cannot be changed by the user -- for
5318 * {@link #split resizable regions}, see {@link Ext.layout.BorderLayout.SplitRegion}.</p>
5320 * Create a new Region.
5321 * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
5322 * @param {Object} config The configuration options
5323 * @param {String} position The region position. Valid values are: <tt>north</tt>, <tt>south</tt>,
5324 * <tt>east</tt>, <tt>west</tt> and <tt>center</tt>. Every {@link Ext.layout.BorderLayout BorderLayout}
5325 * <b>must have a center region</b> for the primary content -- all other regions are optional.
5327 Ext.layout.BorderLayout.Region = function(layout, config, pos){
5328 Ext.apply(this, config);
5329 this.layout = layout;
5330 this.position = pos;
5332 if(typeof this.margins == 'string'){
5333 this.margins = this.layout.parseMargins(this.margins);
5335 this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
5336 if(this.collapsible){
5337 if(typeof this.cmargins == 'string'){
5338 this.cmargins = this.layout.parseMargins(this.cmargins);
5340 if(this.collapseMode == 'mini' && !this.cmargins){
5341 this.cmargins = {left:0,top:0,right:0,bottom:0};
5343 this.cmargins = Ext.applyIf(this.cmargins || {},
5344 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
5349 Ext.layout.BorderLayout.Region.prototype = {
5351 * @cfg {Boolean} animFloat
5352 * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
5353 * panel that will close again once the user mouses out of that panel (or clicks out if
5354 * <tt>{@link #autoHide} = false</tt>). Setting <tt>{@link #animFloat} = false</tt> will
5355 * prevent the open and close of these floated panels from being animated (defaults to <tt>true</tt>).
5358 * @cfg {Boolean} autoHide
5359 * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
5360 * panel. If <tt>autoHide = true</tt>, the panel will automatically hide after the user mouses
5361 * out of the panel. If <tt>autoHide = false</tt>, the panel will continue to display until the
5362 * user clicks outside of the panel (defaults to <tt>true</tt>).
5365 * @cfg {String} collapseMode
5366 * <tt>collapseMode</tt> supports two configuration values:<div class="mdetail-params"><ul>
5367 * <li><b><tt>undefined</tt></b> (default)<div class="sub-desc">By default, {@link #collapsible}
5368 * regions are collapsed by clicking the expand/collapse tool button that renders into the region's
5369 * title bar.</div></li>
5370 * <li><b><tt>'mini'</tt></b><div class="sub-desc">Optionally, when <tt>collapseMode</tt> is set to
5371 * <tt>'mini'</tt> the region's split bar will also display a small collapse button in the center of
5372 * the bar. In <tt>'mini'</tt> mode the region will collapse to a thinner bar than in normal mode.
5375 * <p><b>Note</b>: if a collapsible region does not have a title bar, then set <tt>collapseMode =
5376 * 'mini'</tt> and <tt>{@link #split} = true</tt> in order for the region to be {@link #collapsible}
5377 * by the user as the expand/collapse tool button (that would go in the title bar) will not be rendered.</p>
5378 * <p>See also <tt>{@link #cmargins}</tt>.</p>
5381 * @cfg {Object} margins
5382 * An object containing margins to apply to the region when in the expanded state in the
5383 * format:<pre><code>
5386 right: (right margin),
5387 bottom: (bottom margin),
5390 * <p>May also be a string containing space-separated, numeric margin values. The order of the
5391 * sides associated with each value matches the way CSS processes margin values:</p>
5392 * <p><div class="mdetail-params"><ul>
5393 * <li>If there is only one value, it applies to all sides.</li>
5394 * <li>If there are two values, the top and bottom borders are set to the first value and the
5395 * right and left are set to the second.</li>
5396 * <li>If there are three values, the top is set to the first value, the left and right are set
5397 * to the second, and the bottom is set to the third.</li>
5398 * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
5400 * <p>Defaults to:</p><pre><code>
5401 * {top:0, right:0, bottom:0, left:0}
5405 * @cfg {Object} cmargins
5406 * An object containing margins to apply to the region when in the collapsed state in the
5407 * format:<pre><code>
5410 right: (right margin),
5411 bottom: (bottom margin),
5414 * <p>May also be a string containing space-separated, numeric margin values. The order of the
5415 * sides associated with each value matches the way CSS processes margin values.</p>
5417 * <li>If there is only one value, it applies to all sides.</li>
5418 * <li>If there are two values, the top and bottom borders are set to the first value and the
5419 * right and left are set to the second.</li>
5420 * <li>If there are three values, the top is set to the first value, the left and right are set
5421 * to the second, and the bottom is set to the third.</li>
5422 * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
5426 * @cfg {Boolean} collapsible
5427 * <p><tt>true</tt> to allow the user to collapse this region (defaults to <tt>false</tt>). If
5428 * <tt>true</tt>, an expand/collapse tool button will automatically be rendered into the title
5429 * bar of the region, otherwise the button will not be shown.</p>
5430 * <p><b>Note</b>: that a title bar is required to display the collapse/expand toggle button -- if
5431 * no <tt>title</tt> is specified for the region's panel, the region will only be collapsible if
5432 * <tt>{@link #collapseMode} = 'mini'</tt> and <tt>{@link #split} = true</tt>.
5434 collapsible : false,
5436 * @cfg {Boolean} split
5437 * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and
5438 * display a 5px wide {@link Ext.SplitBar} between this region and its neighbor, allowing the user to
5439 * resize the regions dynamically. Defaults to <tt>false</tt> creating a
5440 * {@link Ext.layout.BorderLayout.Region Region}.</p><br>
5441 * <p><b>Notes</b>:</p><div class="mdetail-params"><ul>
5442 * <li>this configuration option is ignored if <tt>region='center'</tt></li>
5443 * <li>when <tt>split == true</tt>, it is common to specify a
5444 * <tt>{@link Ext.SplitBar#minSize minSize}</tt> and <tt>{@link Ext.SplitBar#maxSize maxSize}</tt>
5445 * for the {@link Ext.BoxComponent BoxComponent} representing the region. These are not native
5446 * configs of {@link Ext.BoxComponent BoxComponent}, and are used only by this class.</li>
5447 * <li>if <tt>{@link #collapseMode} = 'mini'</tt> requires <tt>split = true</tt> to reserve space
5448 * for the collapse tool</tt></li>
5453 * @cfg {Boolean} floatable
5454 * <tt>true</tt> to allow clicking a collapsed region's bar to display the region's panel floated
5455 * above the layout, <tt>false</tt> to force the user to fully expand a collapsed region by
5456 * clicking the expand button to see it again (defaults to <tt>true</tt>).
5460 * @cfg {Number} minWidth
5461 * <p>The minimum allowable width in pixels for this region (defaults to <tt>50</tt>).
5462 * <tt>maxWidth</tt> may also be specified.</p><br>
5463 * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
5464 * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
5465 * <tt>minWidth</tt> / <tt>maxWidth</tt>.</p>
5469 * @cfg {Number} minHeight
5470 * The minimum allowable height in pixels for this region (defaults to <tt>50</tt>)
5471 * <tt>maxHeight</tt> may also be specified.</p><br>
5472 * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
5473 * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
5474 * <tt>minHeight</tt> / <tt>maxHeight</tt>.</p>
5479 defaultMargins : {left:0,top:0,right:0,bottom:0},
5481 defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
5483 defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
5484 floatingZIndex: 100,
5487 * True if this region is collapsed. Read-only.
5491 isCollapsed : false,
5494 * This region's panel. Read-only.
5499 * This region's layout. Read-only.
5504 * This region's layout position (north, south, east, west or center). Read-only.
5506 * @property position
5510 render : function(ct, p){
5512 p.el.enableDisplayMode();
5516 var gs = p.getState, ps = this.position;
5517 p.getState = function(){
5518 return Ext.apply(gs.call(p) || {}, this.state);
5519 }.createDelegate(this);
5522 p.allowQueuedExpand = false;
5524 beforecollapse: this.beforeCollapse,
5525 collapse: this.onCollapse,
5526 beforeexpand: this.beforeExpand,
5527 expand: this.onExpand,
5532 if(this.collapsible || this.floatable){
5533 p.collapseEl = 'el';
5534 p.slideAnchor = this.getSlideAnchor();
5536 if(p.tools && p.tools.toggle){
5537 p.tools.toggle.addClass('x-tool-collapse-'+ps);
5538 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
5544 getCollapsedEl : function(){
5545 if(!this.collapsedEl){
5546 if(!this.toolTemplate){
5547 var tt = new Ext.Template(
5548 '<div class="x-tool x-tool-{id}"> </div>'
5550 tt.disableFormats = true;
5552 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
5554 this.collapsedEl = this.targetEl.createChild({
5555 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
5556 id: this.panel.id + '-xcollapsed'
5558 this.collapsedEl.enableDisplayMode('block');
5560 if(this.collapseMode == 'mini'){
5561 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
5562 this.miniCollapsedEl = this.collapsedEl.createChild({
5563 cls: "x-layout-mini x-layout-mini-"+this.position, html: " "
5565 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
5566 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
5567 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
5569 if(this.collapsible !== false && !this.hideCollapseTool) {
5570 var t = this.toolTemplate.append(
5571 this.collapsedEl.dom,
5572 {id:'expand-'+this.position}, true);
5573 t.addClassOnOver('x-tool-expand-'+this.position+'-over');
5574 t.on('click', this.onExpandClick, this, {stopEvent:true});
5576 if(this.floatable !== false || this.titleCollapse){
5577 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
5578 this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
5582 return this.collapsedEl;
5586 onExpandClick : function(e){
5588 this.afterSlideIn();
5589 this.panel.expand(false);
5591 this.panel.expand();
5596 onCollapseClick : function(e){
5597 this.panel.collapse();
5601 beforeCollapse : function(p, animate){
5602 this.lastAnim = animate;
5604 this.splitEl.hide();
5606 this.getCollapsedEl().show();
5607 this.panel.el.setStyle('z-index', 100);
5608 this.isCollapsed = true;
5609 this.layout.layout();
5613 onCollapse : function(animate){
5614 this.panel.el.setStyle('z-index', 1);
5615 if(this.lastAnim === false || this.panel.animCollapse === false){
5616 this.getCollapsedEl().dom.style.visibility = 'visible';
5618 this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
5620 this.state.collapsed = true;
5621 this.panel.saveState();
5625 beforeExpand : function(animate){
5626 var c = this.getCollapsedEl();
5628 if(this.position == 'east' || this.position == 'west'){
5629 this.panel.setSize(undefined, c.getHeight());
5631 this.panel.setSize(c.getWidth(), undefined);
5634 c.dom.style.visibility = 'hidden';
5635 this.panel.el.setStyle('z-index', this.floatingZIndex);
5639 onExpand : function(){
5640 this.isCollapsed = false;
5642 this.splitEl.show();
5644 this.layout.layout();
5645 this.panel.el.setStyle('z-index', 1);
5646 this.state.collapsed = false;
5647 this.panel.saveState();
5651 collapseClick : function(e){
5653 e.stopPropagation();
5656 e.stopPropagation();
5662 onHide : function(){
5663 if(this.isCollapsed){
5664 this.getCollapsedEl().hide();
5665 }else if(this.splitEl){
5666 this.splitEl.hide();
5671 onShow : function(){
5672 if(this.isCollapsed){
5673 this.getCollapsedEl().show();
5674 }else if(this.splitEl){
5675 this.splitEl.show();
5680 * True if this region is currently visible, else false.
5683 isVisible : function(){
5684 return !this.panel.hidden;
5688 * Returns the current margins for this region. If the region is collapsed, the
5689 * {@link #cmargins} (collapsed margins) value will be returned, otherwise the
5690 * {@link #margins} value will be returned.
5691 * @return {Object} An object containing the element's margins: <tt>{left: (left
5692 * margin), top: (top margin), right: (right margin), bottom: (bottom margin)}</tt>
5694 getMargins : function(){
5695 return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
5699 * Returns the current size of this region. If the region is collapsed, the size of the
5700 * collapsedEl will be returned, otherwise the size of the region's panel will be returned.
5701 * @return {Object} An object containing the element's size: <tt>{width: (element width),
5702 * height: (element height)}</tt>
5704 getSize : function(){
5705 return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
5709 * Sets the specified panel as the container element for this region.
5710 * @param {Ext.Panel} panel The new panel
5712 setPanel : function(panel){
5717 * Returns the minimum allowable width for this region.
5718 * @return {Number} The minimum width
5720 getMinWidth: function(){
5721 return this.minWidth;
5725 * Returns the minimum allowable height for this region.
5726 * @return {Number} The minimum height
5728 getMinHeight: function(){
5729 return this.minHeight;
5733 applyLayoutCollapsed : function(box){
5734 var ce = this.getCollapsedEl();
5735 ce.setLeftTop(box.x, box.y);
5736 ce.setSize(box.width, box.height);
5740 applyLayout : function(box){
5741 if(this.isCollapsed){
5742 this.applyLayoutCollapsed(box);
5744 this.panel.setPosition(box.x, box.y);
5745 this.panel.setSize(box.width, box.height);
5750 beforeSlide: function(){
5751 this.panel.beforeEffect();
5755 afterSlide : function(){
5756 this.panel.afterEffect();
5760 initAutoHide : function(){
5761 if(this.autoHide !== false){
5762 if(!this.autoHideHd){
5763 var st = new Ext.util.DelayedTask(this.slideIn, this);
5765 "mouseout": function(e){
5766 if(!e.within(this.el, true)){
5770 "mouseover" : function(e){
5776 this.el.on(this.autoHideHd);
5781 clearAutoHide : function(){
5782 if(this.autoHide !== false){
5783 this.el.un("mouseout", this.autoHideHd.mouseout);
5784 this.el.un("mouseover", this.autoHideHd.mouseover);
5789 clearMonitor : function(){
5790 Ext.getDoc().un("click", this.slideInIf, this);
5794 * If this Region is {@link #floatable}, this method slides this Region into full visibility <i>over the top
5795 * of the center Region</i> where it floats until either {@link #slideIn} is called, or other regions of the layout
5796 * are clicked, or the mouse exits the Region.
5798 slideOut : function(){
5799 if(this.isSlid || this.el.hasActiveFx()){
5803 var ts = this.panel.tools;
5804 if(ts && ts.toggle){
5808 if(this.position == 'east' || this.position == 'west'){
5809 this.panel.setSize(undefined, this.collapsedEl.getHeight());
5811 this.panel.setSize(this.collapsedEl.getWidth(), undefined);
5813 this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
5814 this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
5815 this.el.setStyle("z-index", this.floatingZIndex+2);
5816 this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
5817 if(this.animFloat !== false){
5819 this.el.slideIn(this.getSlideAnchor(), {
5820 callback: function(){
5822 this.initAutoHide();
5823 Ext.getDoc().on("click", this.slideInIf, this);
5829 this.initAutoHide();
5830 Ext.getDoc().on("click", this.slideInIf, this);
5835 afterSlideIn : function(){
5836 this.clearAutoHide();
5837 this.isSlid = false;
5838 this.clearMonitor();
5839 this.el.setStyle("z-index", "");
5840 this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
5841 this.el.dom.style.left = this.restoreLT[0];
5842 this.el.dom.style.top = this.restoreLT[1];
5844 var ts = this.panel.tools;
5845 if(ts && ts.toggle){
5851 * If this Region is {@link #floatable}, and this Region has been slid into floating visibility, then this method slides
5852 * this region back into its collapsed state.
5854 slideIn : function(cb){
5855 if(!this.isSlid || this.el.hasActiveFx()){
5859 this.isSlid = false;
5860 if(this.animFloat !== false){
5862 this.el.slideOut(this.getSlideAnchor(), {
5863 callback: function(){
5866 this.afterSlideIn();
5874 this.afterSlideIn();
5879 slideInIf : function(e){
5880 if(!e.within(this.el)){
5910 getAnchor : function(){
5911 return this.anchors[this.position];
5915 getCollapseAnchor : function(){
5916 return this.canchors[this.position];
5920 getSlideAnchor : function(){
5921 return this.sanchors[this.position];
5925 getAlignAdj : function(){
5926 var cm = this.cmargins;
5927 switch(this.position){
5944 getExpandAdj : function(){
5945 var c = this.collapsedEl, cm = this.cmargins;
5946 switch(this.position){
5948 return [-(cm.right+c.getWidth()+cm.left), 0];
5951 return [cm.right+c.getWidth()+cm.left, 0];
5954 return [0, -(cm.top+cm.bottom+c.getHeight())];
5957 return [0, cm.top+cm.bottom+c.getHeight()];
5964 * @class Ext.layout.BorderLayout.SplitRegion
5965 * @extends Ext.layout.BorderLayout.Region
5966 * <p>This is a specialized type of {@link Ext.layout.BorderLayout.Region BorderLayout region} that
5967 * has a built-in {@link Ext.SplitBar} for user resizing of regions. The movement of the split bar
5968 * is configurable to move either {@link #tickSize smooth or incrementally}.</p>
5970 * Create a new SplitRegion.
5971 * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
5972 * @param {Object} config The configuration options
5973 * @param {String} position The region position. Valid values are: north, south, east, west and center. Every
5974 * BorderLayout must have a center region for the primary content -- all other regions are optional.
5976 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
5977 Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
5979 this.applyLayout = this.applyFns[pos];
5982 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
5984 * @cfg {Number} tickSize
5985 * The increment, in pixels by which to move this Region's {@link Ext.SplitBar SplitBar}.
5986 * By default, the {@link Ext.SplitBar SplitBar} moves smoothly.
5989 * @cfg {String} splitTip
5990 * The tooltip to display when the user hovers over a
5991 * {@link Ext.layout.BorderLayout.Region#collapsible non-collapsible} region's split bar
5992 * (defaults to <tt>"Drag to resize."</tt>). Only applies if
5993 * <tt>{@link #useSplitTips} = true</tt>.
5995 splitTip : "Drag to resize.",
5997 * @cfg {String} collapsibleSplitTip
5998 * The tooltip to display when the user hovers over a
5999 * {@link Ext.layout.BorderLayout.Region#collapsible collapsible} region's split bar
6000 * (defaults to "Drag to resize. Double click to hide."). Only applies if
6001 * <tt>{@link #useSplitTips} = true</tt>.
6003 collapsibleSplitTip : "Drag to resize. Double click to hide.",
6005 * @cfg {Boolean} useSplitTips
6006 * <tt>true</tt> to display a tooltip when the user hovers over a region's split bar
6007 * (defaults to <tt>false</tt>). The tooltip text will be the value of either
6008 * <tt>{@link #splitTip}</tt> or <tt>{@link #collapsibleSplitTip}</tt> as appropriate.
6010 useSplitTips : false,
6015 orientation: Ext.SplitBar.VERTICAL,
6016 placement: Ext.SplitBar.TOP,
6017 maxFn : 'getVMaxSize',
6018 minProp: 'minHeight',
6019 maxProp: 'maxHeight'
6022 orientation: Ext.SplitBar.VERTICAL,
6023 placement: Ext.SplitBar.BOTTOM,
6024 maxFn : 'getVMaxSize',
6025 minProp: 'minHeight',
6026 maxProp: 'maxHeight'
6029 orientation: Ext.SplitBar.HORIZONTAL,
6030 placement: Ext.SplitBar.RIGHT,
6031 maxFn : 'getHMaxSize',
6032 minProp: 'minWidth',
6036 orientation: Ext.SplitBar.HORIZONTAL,
6037 placement: Ext.SplitBar.LEFT,
6038 maxFn : 'getHMaxSize',
6039 minProp: 'minWidth',
6046 west : function(box){
6047 if(this.isCollapsed){
6048 return this.applyLayoutCollapsed(box);
6050 var sd = this.splitEl.dom, s = sd.style;
6051 this.panel.setPosition(box.x, box.y);
6052 var sw = sd.offsetWidth;
6053 s.left = (box.x+box.width-sw)+'px';
6054 s.top = (box.y)+'px';
6055 s.height = Math.max(0, box.height)+'px';
6056 this.panel.setSize(box.width-sw, box.height);
6058 east : function(box){
6059 if(this.isCollapsed){
6060 return this.applyLayoutCollapsed(box);
6062 var sd = this.splitEl.dom, s = sd.style;
6063 var sw = sd.offsetWidth;
6064 this.panel.setPosition(box.x+sw, box.y);
6065 s.left = (box.x)+'px';
6066 s.top = (box.y)+'px';
6067 s.height = Math.max(0, box.height)+'px';
6068 this.panel.setSize(box.width-sw, box.height);
6070 north : function(box){
6071 if(this.isCollapsed){
6072 return this.applyLayoutCollapsed(box);
6074 var sd = this.splitEl.dom, s = sd.style;
6075 var sh = sd.offsetHeight;
6076 this.panel.setPosition(box.x, box.y);
6077 s.left = (box.x)+'px';
6078 s.top = (box.y+box.height-sh)+'px';
6079 s.width = Math.max(0, box.width)+'px';
6080 this.panel.setSize(box.width, box.height-sh);
6082 south : function(box){
6083 if(this.isCollapsed){
6084 return this.applyLayoutCollapsed(box);
6086 var sd = this.splitEl.dom, s = sd.style;
6087 var sh = sd.offsetHeight;
6088 this.panel.setPosition(box.x, box.y+sh);
6089 s.left = (box.x)+'px';
6090 s.top = (box.y)+'px';
6091 s.width = Math.max(0, box.width)+'px';
6092 this.panel.setSize(box.width, box.height-sh);
6097 render : function(ct, p){
6098 Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
6100 var ps = this.position;
6102 this.splitEl = ct.createChild({
6103 cls: "x-layout-split x-layout-split-"+ps, html: " ",
6104 id: this.panel.id + '-xsplit'
6107 if(this.collapseMode == 'mini'){
6108 this.miniSplitEl = this.splitEl.createChild({
6109 cls: "x-layout-mini x-layout-mini-"+ps, html: " "
6111 this.miniSplitEl.addClassOnOver('x-layout-mini-over');
6112 this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
6115 var s = this.splitSettings[ps];
6117 this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
6118 this.split.tickSize = this.tickSize;
6119 this.split.placement = s.placement;
6120 this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
6121 this.split.minSize = this.minSize || this[s.minProp];
6122 this.split.on("beforeapply", this.onSplitMove, this);
6123 this.split.useShim = this.useShim === true;
6124 this.maxSize = this.maxSize || this[s.maxProp];
6127 this.splitEl.hide();
6130 if(this.useSplitTips){
6131 this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
6133 if(this.collapsible){
6134 this.splitEl.on("dblclick", this.onCollapseClick, this);
6138 //docs inherit from superclass
6139 getSize : function(){
6140 if(this.isCollapsed){
6141 return this.collapsedEl.getSize();
6143 var s = this.panel.getSize();
6144 if(this.position == 'north' || this.position == 'south'){
6145 s.height += this.splitEl.dom.offsetHeight;
6147 s.width += this.splitEl.dom.offsetWidth;
6153 getHMaxSize : function(){
6154 var cmax = this.maxSize || 10000;
6155 var center = this.layout.center;
6156 return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
6160 getVMaxSize : function(){
6161 var cmax = this.maxSize || 10000;
6162 var center = this.layout.center;
6163 return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
6167 onSplitMove : function(split, newSize){
6168 var s = this.panel.getSize();
6169 this.lastSplitSize = newSize;
6170 if(this.position == 'north' || this.position == 'south'){
6171 this.panel.setSize(s.width, newSize);
6172 this.state.height = newSize;
6174 this.panel.setSize(newSize, s.height);
6175 this.state.width = newSize;
6177 this.layout.layout();
6178 this.panel.saveState();
6183 * Returns a reference to the split bar in use by this region.
6184 * @return {Ext.SplitBar} The split bar
6186 getSplitBar : function(){
6191 destroy : function() {
6200 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;/**
6201 * @class Ext.layout.FormLayout
6202 * @extends Ext.layout.AnchorLayout
6203 * <p>This layout manager is specifically designed for rendering and managing child Components of
6204 * {@link Ext.form.FormPanel forms}. It is responsible for rendering the labels of
6205 * {@link Ext.form.Field Field}s.</p>
6207 * <p>This layout manager is used when a Container is configured with the <tt>layout:'form'</tt>
6208 * {@link Ext.Container#layout layout} config option, and should generally not need to be created directly
6209 * via the new keyword. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
6211 * <p>In an application, it will usually be preferrable to use a {@link Ext.form.FormPanel FormPanel}
6212 * (which is configured with FormLayout as its layout class by default) since it also provides built-in
6213 * functionality for {@link Ext.form.BasicForm#doAction loading, validating and submitting} the form.</p>
6215 * <p>A {@link Ext.Container Container} <i>using</i> the FormLayout layout manager (e.g.
6216 * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>) can also accept the following
6217 * layout-specific config properties:<div class="mdetail-params"><ul>
6218 * <li><b><tt>{@link Ext.form.FormPanel#hideLabels hideLabels}</tt></b></li>
6219 * <li><b><tt>{@link Ext.form.FormPanel#labelAlign labelAlign}</tt></b></li>
6220 * <li><b><tt>{@link Ext.form.FormPanel#labelPad labelPad}</tt></b></li>
6221 * <li><b><tt>{@link Ext.form.FormPanel#labelSeparator labelSeparator}</tt></b></li>
6222 * <li><b><tt>{@link Ext.form.FormPanel#labelWidth labelWidth}</tt></b></li>
6225 * <p>Any Component (including Fields) managed by FormLayout accepts the following as a config option:
6226 * <div class="mdetail-params"><ul>
6227 * <li><b><tt>{@link Ext.Component#anchor anchor}</tt></b></li>
6230 * <p>Any Component managed by FormLayout may be rendered as a form field (with an associated label) by
6231 * configuring it with a non-null <b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b>. Components configured
6232 * in this way may be configured with the following options which affect the way the FormLayout renders them:
6233 * <div class="mdetail-params"><ul>
6234 * <li><b><tt>{@link Ext.Component#clearCls clearCls}</tt></b></li>
6235 * <li><b><tt>{@link Ext.Component#fieldLabel fieldLabel}</tt></b></li>
6236 * <li><b><tt>{@link Ext.Component#hideLabel hideLabel}</tt></b></li>
6237 * <li><b><tt>{@link Ext.Component#itemCls itemCls}</tt></b></li>
6238 * <li><b><tt>{@link Ext.Component#labelSeparator labelSeparator}</tt></b></li>
6239 * <li><b><tt>{@link Ext.Component#labelStyle labelStyle}</tt></b></li>
6242 * <p>Example usage:</p>
6244 // Required if showing validation messages
6245 Ext.QuickTips.init();
6247 // While you can create a basic Panel with layout:'form', practically
6248 // you should usually use a FormPanel to also get its form functionality
6249 // since it already creates a FormLayout internally.
6250 var form = new Ext.form.FormPanel({
6251 title: 'Form Layout',
6252 bodyStyle: 'padding:15px',
6254 defaultType: 'textfield',
6256 // applied to each contained item
6261 fieldLabel: 'First Name',
6264 {@link Ext.Component#labelSeparator labelSeparator}: ':' // override labelSeparator layout config
6266 fieldLabel: 'Last Name',
6269 fieldLabel: 'Email',
6274 hideLabel: true, // override hideLabels layout config
6284 {@link #labelSeparator}: '~' // superseded by assignment below
6286 // config options applicable to container when layout='form':
6288 labelAlign: 'left', // or 'right' or 'top'
6289 {@link Ext.form.FormPanel#labelSeparator labelSeparator}: '>>', // takes precedence over layoutConfig value
6290 labelWidth: 65, // defaults to 100
6291 labelPad: 8 // defaults to 5, must specify labelWidth to be honored
6295 Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, {
6298 * @cfg {String} labelSeparator
6299 * See {@link Ext.form.FormPanel}.{@link Ext.form.FormPanel#labelSeparator labelSeparator}. Configuration
6300 * of this property at the <b>container</b> level takes precedence.
6302 labelSeparator : ':',
6305 * Read only. The CSS style specification string added to field labels in this layout if not
6306 * otherwise {@link Ext.Component#labelStyle specified by each contained field}.
6308 * @property labelStyle
6312 setContainer : function(ct){
6313 Ext.layout.FormLayout.superclass.setContainer.call(this, ct);
6315 ct.addClass('x-form-label-'+ct.labelAlign);
6319 this.labelStyle = "display:none";
6320 this.elementStyle = "padding-left:0;";
6321 this.labelAdjust = 0;
6323 this.labelSeparator = ct.labelSeparator || this.labelSeparator;
6324 ct.labelWidth = ct.labelWidth || 100;
6325 if(typeof ct.labelWidth == 'number'){
6326 var pad = (typeof ct.labelPad == 'number' ? ct.labelPad : 5);
6327 this.labelAdjust = ct.labelWidth+pad;
6328 this.labelStyle = "width:"+ct.labelWidth+"px;";
6329 this.elementStyle = "padding-left:"+(ct.labelWidth+pad)+'px';
6331 if(ct.labelAlign == 'top'){
6332 this.labelStyle = "width:auto;";
6333 this.labelAdjust = 0;
6334 this.elementStyle = "padding-left:0;";
6340 getLabelStyle: function(s){
6341 var ls = '', items = [this.labelStyle, s];
6342 for (var i = 0, len = items.length; i < len; ++i){
6345 if (ls.substr(-1, 1) != ';'){
6354 * @cfg {Ext.Template} fieldTpl
6355 * A {@link Ext.Template#compile compile}d {@link Ext.Template} for rendering
6356 * the fully wrapped, labeled and styled form Field. Defaults to:</p><pre><code>
6358 '<div class="x-form-item {itemCls}" tabIndex="-1">',
6359 '<label for="{id}" style="{labelStyle}" class="x-form-item-label">{label}{labelSeparator}</label>',
6360 '<div class="x-form-element" id="x-form-el-{id}" style="{elementStyle}">',
6361 '</div><div class="{clearCls}"></div>',
6365 * <p>This may be specified to produce a different DOM structure when rendering form Fields.</p>
6366 * <p>A description of the properties within the template follows:</p><div class="mdetail-params"><ul>
6367 * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
6368 * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
6369 * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
6370 * supplied at the container level.</div></li>
6371 * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
6372 * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
6373 * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
6374 * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
6375 * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
6376 * field (defaults to <tt>''</tt>)</div></li>
6377 * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
6378 * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
6379 * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
6380 * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
6381 * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
6382 * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
6384 * <p>Also see <tt>{@link #getTemplateArgs}</tt></p>
6388 renderItem : function(c, position, target){
6389 if(c && !c.rendered && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){
6390 var args = this.getTemplateArgs(c);
6391 if(typeof position == 'number'){
6392 position = target.dom.childNodes[position] || null;
6395 this.fieldTpl.insertBefore(position, args);
6397 this.fieldTpl.append(target, args);
6399 c.render('x-form-el-'+c.id);
6401 Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
6406 * <p>Provides template arguments for rendering the fully wrapped, labeled and styled form Field.</p>
6407 * <p>This method returns an object hash containing properties used by the layout's {@link #fieldTpl}
6408 * to create a correctly wrapped, labeled and styled form Field. This may be overriden to
6409 * create custom layouts. The properties which must be returned are:</p><div class="mdetail-params"><ul>
6410 * <li><b><tt>itemCls</tt></b> : String<div class="sub-desc">The CSS class applied to the outermost div wrapper
6411 * that contains this field label and field element (the default class is <tt>'x-form-item'</tt> and <tt>itemCls</tt>
6412 * will be added to that). If supplied, <tt>itemCls</tt> at the field level will override the default <tt>itemCls</tt>
6413 * supplied at the container level.</div></li>
6414 * <li><b><tt>id</tt></b> : String<div class="sub-desc">The id of the Field</div></li>
6415 * <li><b><tt>{@link #labelStyle}</tt></b> : String<div class="sub-desc">
6416 * A CSS style specification string to add to the field label for this field (defaults to <tt>''</tt> or the
6417 * {@link #labelStyle layout's value for <tt>labelStyle</tt>}).</div></li>
6418 * <li><b><tt>label</tt></b> : String<div class="sub-desc">The text to display as the label for this
6419 * field (defaults to <tt>''</tt>)</div></li>
6420 * <li><b><tt>{@link #labelSeparator}</tt></b> : String<div class="sub-desc">The separator to display after
6421 * the text of the label for this field (defaults to a colon <tt>':'</tt> or the
6422 * {@link #labelSeparator layout's value for labelSeparator}). To hide the separator use empty string ''.</div></li>
6423 * <li><b><tt>elementStyle</tt></b> : String<div class="sub-desc">The styles text for the input element's wrapper.</div></li>
6424 * <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
6425 * rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
6427 * @param field The {@link Field Ext.form.Field} being rendered.
6428 * @return An object hash containing the properties required to render the Field.
6430 getTemplateArgs: function(field) {
6431 var noLabelSep = !field.fieldLabel || field.hideLabel;
6434 label: field.fieldLabel,
6435 labelStyle: field.labelStyle||this.labelStyle||'',
6436 elementStyle: this.elementStyle||'',
6437 labelSeparator: noLabelSep ? '' : (typeof field.labelSeparator == 'undefined' ? this.labelSeparator : field.labelSeparator),
6438 itemCls: (field.itemCls||this.container.itemCls||'') + (field.hideLabel ? ' x-hide-label' : ''),
6439 clearCls: field.clearCls || 'x-form-clear-left'
6444 adjustWidthAnchor : function(value, comp){
6445 return value - (comp.isFormField || comp.fieldLabel ? (comp.hideLabel ? 0 : this.labelAdjust) : 0);
6449 isValidParent : function(c, target){
6454 * @property activeItem
6459 Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;/**
\r
6460 * @class Ext.layout.AccordionLayout
\r
6461 * @extends Ext.layout.FitLayout
\r
6462 * <p>This is a layout that contains multiple panels in an expandable accordion style such that only
\r
6463 * <b>one panel can be open at any given time</b>. Each panel has built-in support for expanding and collapsing.
\r
6464 * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
\r
6465 * configuration property. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
\r
6466 * <p>Example usage:</p>
\r
6468 var accordion = new Ext.Panel({
\r
6469 title: 'Accordion Layout',
\r
6470 layout:'accordion',
\r
6472 // applied to each contained panel
\r
6473 bodyStyle: 'padding:15px'
\r
6476 // layout-specific configs go here
\r
6477 titleCollapse: false,
\r
6483 html: '<p>Panel content!</p>'
\r
6486 html: '<p>Panel content!</p>'
\r
6489 html: '<p>Panel content!</p>'
\r
6494 Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, {
\r
6496 * @cfg {Boolean} fill
\r
6497 * True to adjust the active item's height to fill the available space in the container, false to use the
\r
6498 * item's current height, or auto height if not explicitly set (defaults to true).
\r
6502 * @cfg {Boolean} autoWidth
\r
6503 * True to set each contained item's width to 'auto', false to use the item's current width (defaults to true).
\r
6504 * Note that some components, in particular the {@link Ext.grid.GridPanel grid}, will not function properly within
\r
6505 * layouts if they have auto width, so in such cases this config should be set to false.
\r
6509 * @cfg {Boolean} titleCollapse
\r
6510 * True to allow expand/collapse of each contained panel by clicking anywhere on the title bar, false to allow
\r
6511 * expand/collapse only when the toggle tool button is clicked (defaults to true). When set to false,
\r
6512 * {@link #hideCollapseTool} should be false also.
\r
6514 titleCollapse : true,
\r
6516 * @cfg {Boolean} hideCollapseTool
\r
6517 * True to hide the contained panels' collapse/expand toggle buttons, false to display them (defaults to false).
\r
6518 * When set to true, {@link #titleCollapse} should be true also.
\r
6520 hideCollapseTool : false,
\r
6522 * @cfg {Boolean} collapseFirst
\r
6523 * True to make sure the collapse/expand toggle button always renders first (to the left of) any other tools
\r
6524 * in the contained panels' title bars, false to render it last (defaults to false).
\r
6526 collapseFirst : false,
\r
6528 * @cfg {Boolean} animate
\r
6529 * True to slide the contained panels open and closed during expand/collapse using animation, false to open and
\r
6530 * close directly with no animation (defaults to false). Note: to defer to the specific config setting of each
\r
6531 * contained panel for this property, set this to undefined at the layout level.
\r
6535 * @cfg {Boolean} sequence
\r
6536 * <b>Experimental</b>. If animate is set to true, this will result in each animation running in sequence.
\r
6540 * @cfg {Boolean} activeOnTop
\r
6541 * True to swap the position of each panel as it is expanded so that it becomes the first item in the container,
\r
6542 * false to keep the panels in the rendered order. <b>This is NOT compatible with "animate:true"</b> (defaults to false).
\r
6544 activeOnTop : false,
\r
6546 renderItem : function(c){
\r
6547 if(this.animate === false){
\r
6548 c.animCollapse = false;
\r
6550 c.collapsible = true;
\r
6551 if(this.autoWidth){
\r
6552 c.autoWidth = true;
\r
6554 if(this.titleCollapse){
\r
6555 c.titleCollapse = true;
\r
6557 if(this.hideCollapseTool){
\r
6558 c.hideCollapseTool = true;
\r
6560 if(this.collapseFirst !== undefined){
\r
6561 c.collapseFirst = this.collapseFirst;
\r
6563 if(!this.activeItem && !c.collapsed){
\r
6564 this.activeItem = c;
\r
6565 }else if(this.activeItem && this.activeItem != c){
\r
6566 c.collapsed = true;
\r
6568 Ext.layout.AccordionLayout.superclass.renderItem.apply(this, arguments);
\r
6569 c.header.addClass('x-accordion-hd');
\r
6570 c.on('beforeexpand', this.beforeExpand, this);
\r
6574 beforeExpand : function(p, anim){
\r
6575 var ai = this.activeItem;
\r
6577 if(this.sequence){
\r
6578 delete this.activeItem;
\r
6579 if (!ai.collapsed){
\r
6580 ai.collapse({callback:function(){
\r
6581 p.expand(anim || true);
\r
6586 ai.collapse(this.animate);
\r
6589 this.activeItem = p;
\r
6590 if(this.activeOnTop){
\r
6591 p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
\r
6597 setItemSize : function(item, size){
\r
6598 if(this.fill && item){
\r
6600 this.container.items.each(function(p){
\r
6602 hh += p.header.getHeight();
\r
6605 size.height -= hh;
\r
6606 item.setSize(size);
\r
6611 * Sets the active (expanded) item in the layout.
\r
6612 * @param {String/Number} item The string component id or numeric index of the item to activate
\r
6614 setActiveItem : function(item){
\r
6615 item = this.container.getComponent(item);
\r
6616 if(this.activeItem != item){
\r
6617 if(item.rendered && item.collapsed){
\r
6620 this.activeItem = item;
\r
6626 Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;
\r
6628 //backwards compat
\r
6629 Ext.layout.Accordion = Ext.layout.AccordionLayout;/**
\r
6630 * @class Ext.layout.TableLayout
\r
6631 * @extends Ext.layout.ContainerLayout
\r
6632 * <p>This layout allows you to easily render content into an HTML table. The total number of columns can be
\r
6633 * specified, and rowspan and colspan can be used to create complex layouts within the table.
\r
6634 * This class is intended to be extended or created via the layout:'table' {@link Ext.Container#layout} config,
\r
6635 * and should generally not need to be created directly via the new keyword.</p>
\r
6636 * <p>Note that when creating a layout via config, the layout-specific config properties must be passed in via
\r
6637 * the {@link Ext.Container#layoutConfig} object which will then be applied internally to the layout. In the
\r
6638 * case of TableLayout, the only valid layout config property is {@link #columns}. However, the items added to a
\r
6639 * TableLayout can supply the following table-specific config properties:</p>
\r
6641 * <li><b>rowspan</b> Applied to the table cell containing the item.</li>
\r
6642 * <li><b>colspan</b> Applied to the table cell containing the item.</li>
\r
6643 * <li><b>cellId</b> An id applied to the table cell containing the item.</li>
\r
6644 * <li><b>cellCls</b> A CSS class name added to the table cell containing the item.</li>
\r
6646 * <p>The basic concept of building up a TableLayout is conceptually very similar to building up a standard
\r
6647 * HTML table. You simply add each panel (or "cell") that you want to include along with any span attributes
\r
6648 * specified as the special config properties of rowspan and colspan which work exactly like their HTML counterparts.
\r
6649 * Rather than explicitly creating and nesting rows and columns as you would in HTML, you simply specify the
\r
6650 * total column count in the layoutConfig and start adding panels in their natural order from left to right,
\r
6651 * top to bottom. The layout will automatically figure out, based on the column count, rowspans and colspans,
\r
6652 * how to position each panel within the table. Just like with HTML tables, your rowspans and colspans must add
\r
6653 * up correctly in your overall layout or you'll end up with missing and/or extra cells! Example usage:</p>
\r
6655 // This code will generate a layout table that is 3 columns by 2 rows
\r
6656 // with some spanning included. The basic layout will be:
\r
6657 // +--------+-----------------+
\r
6659 // | |--------+--------|
\r
6661 // +--------+--------+--------+
\r
6662 var table = new Ext.Panel({
\r
6663 title: 'Table Layout',
\r
6666 // applied to each contained panel
\r
6667 bodyStyle:'padding:20px'
\r
6670 // The total column count must be specified here
\r
6674 html: '<p>Cell A content</p>',
\r
6677 html: '<p>Cell B content</p>',
\r
6680 html: '<p>Cell C content</p>',
\r
6681 cellCls: 'highlight'
\r
6683 html: '<p>Cell D content</p>'
\r
6688 Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, {
\r
6690 * @cfg {Number} columns
\r
6691 * The total number of columns to create in the table for this layout. If not specified, all Components added to
\r
6692 * this layout will be rendered into a single row using one column per Component.
\r
6696 monitorResize:false,
\r
6699 * @cfg {Object} tableAttrs
\r
6700 * <p>An object containing properties which are added to the {@link Ext.DomHelper DomHelper} specification
\r
6701 * used to create the layout's <tt><table></tt> element. Example:</p><pre><code>
\r
6718 setContainer : function(ct){
\r
6719 Ext.layout.TableLayout.superclass.setContainer.call(this, ct);
\r
6721 this.currentRow = 0;
\r
6722 this.currentColumn = 0;
\r
6727 onLayout : function(ct, target){
\r
6728 var cs = ct.items.items, len = cs.length, c, i;
\r
6731 target.addClass('x-table-layout-ct');
\r
6733 this.table = target.createChild(
\r
6734 Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);
\r
6736 this.renderAll(ct, target);
\r
6740 getRow : function(index){
\r
6741 var row = this.table.tBodies[0].childNodes[index];
\r
6743 row = document.createElement('tr');
\r
6744 this.table.tBodies[0].appendChild(row);
\r
6750 getNextCell : function(c){
\r
6751 var cell = this.getNextNonSpan(this.currentColumn, this.currentRow);
\r
6752 var curCol = this.currentColumn = cell[0], curRow = this.currentRow = cell[1];
\r
6753 for(var rowIndex = curRow; rowIndex < curRow + (c.rowspan || 1); rowIndex++){
\r
6754 if(!this.cells[rowIndex]){
\r
6755 this.cells[rowIndex] = [];
\r
6757 for(var colIndex = curCol; colIndex < curCol + (c.colspan || 1); colIndex++){
\r
6758 this.cells[rowIndex][colIndex] = true;
\r
6761 var td = document.createElement('td');
\r
6765 var cls = 'x-table-layout-cell';
\r
6767 cls += ' ' + c.cellCls;
\r
6769 td.className = cls;
\r
6771 td.colSpan = c.colspan;
\r
6774 td.rowSpan = c.rowspan;
\r
6776 this.getRow(curRow).appendChild(td);
\r
6781 getNextNonSpan: function(colIndex, rowIndex){
\r
6782 var cols = this.columns;
\r
6783 while((cols && colIndex >= cols) || (this.cells[rowIndex] && this.cells[rowIndex][colIndex])) {
\r
6784 if(cols && colIndex >= cols){
\r
6791 return [colIndex, rowIndex];
\r
6795 renderItem : function(c, position, target){
\r
6796 if(c && !c.rendered){
\r
6797 c.render(this.getNextCell(c));
\r
6798 if(this.extraCls){
\r
6799 var t = c.getPositionEl ? c.getPositionEl() : c;
\r
6800 t.addClass(this.extraCls);
\r
6806 isValidParent : function(c, target){
\r
6811 * @property activeItem
\r
6816 Ext.Container.LAYOUTS['table'] = Ext.layout.TableLayout;/**
\r
6817 * @class Ext.layout.AbsoluteLayout
\r
6818 * @extends Ext.layout.AnchorLayout
\r
6819 * <p>This is a layout that inherits the anchoring of <b>{@link Ext.layout.AnchorLayout}</b> and adds the
\r
6820 * ability for x/y positioning using the standard x and y component config options.</p>
\r
6821 * <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
\r
6822 * configuration property. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
\r
6823 * <p>Example usage:</p>
\r
6825 var form = new Ext.form.FormPanel({
\r
6826 title: 'Absolute Layout',
\r
6827 layout:'absolute',
\r
6829 // layout-specific configs go here
\r
6830 extraCls: 'x-abs-layout-item',
\r
6832 baseCls: 'x-plain',
\r
6833 url:'save-form.php',
\r
6834 defaultType: 'textfield',
\r
6844 anchor:'100%' // anchor width by percentage
\r
6854 anchor: '100%' // anchor width by percentage
\r
6858 xtype: 'textarea',
\r
6860 anchor: '100% 100%' // anchor width and height
\r
6865 Ext.layout.AbsoluteLayout = Ext.extend(Ext.layout.AnchorLayout, {
\r
6867 extraCls: 'x-abs-layout-item',
\r
6869 onLayout : function(ct, target){
\r
6870 target.position();
\r
6871 this.paddingLeft = target.getPadding('l');
\r
6872 this.paddingTop = target.getPadding('t');
\r
6874 Ext.layout.AbsoluteLayout.superclass.onLayout.call(this, ct, target);
\r
6878 adjustWidthAnchor : function(value, comp){
\r
6879 return value ? value - comp.getPosition(true)[0] + this.paddingLeft : value;
\r
6883 adjustHeightAnchor : function(value, comp){
\r
6884 return value ? value - comp.getPosition(true)[1] + this.paddingTop : value;
\r
6887 * @property activeItem
\r
6891 Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
6893 * @class Ext.layout.BoxLayout
\r
6894 * @extends Ext.layout.ContainerLayout
\r
6895 * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
\r
6897 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
\r
6899 * @cfg {Object} defaultMargins
\r
6900 * <p>If the individual contained items do not have a <tt>margins</tt>
\r
6901 * property specified, the default margins from this property will be
\r
6902 * applied to each item.</p>
\r
6903 * <br><p>This property may be specified as an object containing margins
\r
6904 * to apply in the format:</p><pre><code>
\r
6906 top: (top margin),
\r
6907 right: (right margin),
\r
6908 bottom: (bottom margin),
\r
6909 left: (left margin)
\r
6911 * <p>This property may also be specified as a string containing
\r
6912 * space-separated, numeric margin values. The order of the sides associated
\r
6913 * with each value matches the way CSS processes margin values:</p>
\r
6914 * <div class="mdetail-params"><ul>
\r
6915 * <li>If there is only one value, it applies to all sides.</li>
\r
6916 * <li>If there are two values, the top and bottom borders are set to the
\r
6917 * first value and the right and left are set to the second.</li>
\r
6918 * <li>If there are three values, the top is set to the first value, the left
\r
6919 * and right are set to the second, and the bottom is set to the third.</li>
\r
6920 * <li>If there are four values, they apply to the top, right, bottom, and
\r
6921 * left, respectively.</li>
\r
6923 * <p>Defaults to:</p><pre><code>
\r
6924 * {top:0, right:0, bottom:0, left:0}
\r
6927 defaultMargins : {left:0,top:0,right:0,bottom:0},
\r
6929 * @cfg {String} padding
\r
6930 * Defaults to <tt>'0'</tt>. Sets the padding to be applied to all child items managed by this
\r
6931 * container's layout.
\r
6934 // documented in subclasses
\r
6938 monitorResize : true,
\r
6940 extraCls : 'x-box-item',
\r
6941 ctCls : 'x-box-layout-ct',
\r
6942 innerCls : 'x-box-inner',
\r
6945 isValidParent : function(c, target){
\r
6946 return c.getEl().dom.parentNode == this.innerCt.dom;
\r
6950 onLayout : function(ct, target){
\r
6951 var cs = ct.items.items, len = cs.length, c, i, last = len-1, cm;
\r
6953 if(!this.innerCt){
\r
6954 target.addClass(this.ctCls);
\r
6956 // the innerCt prevents wrapping and shuffling while
\r
6957 // the container is resizing
\r
6958 this.innerCt = target.createChild({cls:this.innerCls});
\r
6959 this.padding = this.parseMargins(this.padding);
\r
6961 this.renderAll(ct, this.innerCt);
\r
6965 renderItem : function(c){
\r
6966 if(typeof c.margins == 'string'){
\r
6967 c.margins = this.parseMargins(c.margins);
\r
6968 }else if(!c.margins){
\r
6969 c.margins = this.defaultMargins;
\r
6971 Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
\r
6974 getTargetSize : function(target){
6975 return (Ext.isIE6 && Ext.isStrict && target.dom == document.body) ? target.getStyleSize() : target.getViewSize();
\r
6978 getItems: function(ct){
\r
6980 ct.items.each(function(c){
\r
6981 if(c.isVisible()){
\r
6989 * @property activeItem
\r
6995 * @class Ext.layout.VBoxLayout
\r
6996 * @extends Ext.layout.BoxLayout
\r
6997 * A layout that arranges items vertically
\r
6999 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
\r
7001 * @cfg {String} align
\r
7002 * Controls how the child items of the container are aligned. Acceptable configuration values for this
\r
7004 * <div class="mdetail-params"><ul>
\r
7005 * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally
\r
7006 * at the <b>left</b> side of the container</div></li>
\r
7007 * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the
\r
7008 * <b>mid-width</b> of the container</div></li>
\r
7009 * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill
\r
7010 * the width of the container</div></li>
\r
7011 * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to
\r
7012 * the size of the largest item.</div></li>
\r
7015 align : 'left', // left, center, stretch, strechmax
\r
7017 * @cfg {String} pack
\r
7018 * Controls how the child items of the container are packed together. Acceptable configuration values
\r
7019 * for this property are:
\r
7020 * <div class="mdetail-params"><ul>
\r
7021 * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
\r
7022 * <b>top</b> side of container</div></li>
\r
7023 * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
\r
7024 * <b>mid-height</b> of container</div></li>
\r
7025 * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>
\r
7026 * side of container</div></li>
\r
7030 * @cfg {Number} flex
\r
7031 * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
\r
7032 * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>
\r
7033 * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
\r
7034 * a <tt>flex</tt> value specified. Any child items that have either a <tt>flex = 0</tt> or
\r
7035 * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
\r
7039 onLayout : function(ct, target){
\r
7040 Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);
\r
7043 var cs = this.getItems(ct), cm, ch, margin,
\r
7044 size = this.getTargetSize(target),
\r
7045 w = size.width - target.getPadding('lr') - this.scrollOffset,
\r
7046 h = size.height - target.getPadding('tb'),
\r
7047 l = this.padding.left, t = this.padding.top,
\r
7048 isStart = this.pack == 'start',
\r
7049 isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
\r
7050 stretchWidth = w - (this.padding.left + this.padding.right),
\r
7057 Ext.each(cs, function(c){
\r
7059 totalFlex += c.flex || 0;
\r
7060 ch = c.getHeight();
\r
7061 margin = cm.top + cm.bottom;
\r
7062 extraHeight += ch + margin;
\r
7063 flexHeight += margin + (c.flex ? 0 : ch);
\r
7064 maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);
\r
7066 extraHeight = h - extraHeight - this.padding.top - this.padding.bottom;
\r
7068 var innerCtWidth = maxWidth + this.padding.left + this.padding.right;
\r
7069 switch(this.align){
\r
7071 this.innerCt.setSize(w, h);
\r
7073 case 'stretchmax':
\r
7075 this.innerCt.setSize(innerCtWidth, h);
\r
7078 this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);
\r
7082 var availHeight = Math.max(0, h - this.padding.top - this.padding.bottom - flexHeight),
\r
7083 leftOver = availHeight,
\r
7087 availableWidth = Math.max(0, w - this.padding.left - this.padding.right);
\r
7090 Ext.each(cs, function(c){
\r
7091 if(isStart && c.flex){
\r
7092 ch = Math.floor(availHeight * (c.flex / totalFlex));
\r
7098 if(this.pack == 'center'){
\r
7099 t += extraHeight ? extraHeight / 2 : 0;
\r
7100 }else if(this.pack == 'end'){
\r
7103 Ext.each(cs, function(c){
\r
7106 c.setPosition(l + cm.left, t);
\r
7107 if(isStart && c.flex){
\r
7108 ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));
\r
7110 restore.push(c.getWidth());
\r
7112 c.setSize(availableWidth, ch);
\r
7114 ch = c.getHeight();
\r
7116 t += ch + cm.bottom;
\r
7120 Ext.each(cs, function(c){
\r
7122 if(this.align == 'stretch'){
\r
7123 c.setWidth((stretchWidth - (cm.left + cm.right)).constrain(
\r
7124 c.minWidth || 0, c.maxWidth || 1000000));
\r
7125 }else if(this.align == 'stretchmax'){
\r
7126 c.setWidth((maxWidth - (cm.left + cm.right)).constrain(
\r
7127 c.minWidth || 0, c.maxWidth || 1000000));
\r
7129 if(this.align == 'center'){
\r
7130 var diff = availableWidth - (c.getWidth() + cm.left + cm.right);
\r
7132 c.setPosition(l + cm.left + (diff/2), c.y);
\r
7135 if(isStart && c.flex){
\r
7136 c.setWidth(restore[idx++]);
\r
7142 * @property activeItem
\r
7147 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
\r
7150 * @class Ext.layout.HBoxLayout
\r
7151 * @extends Ext.layout.BoxLayout
\r
7152 * A layout that arranges items horizontally
\r
7154 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
\r
7156 * @cfg {String} align
\r
7157 * Controls how the child items of the container are aligned. Acceptable configuration values for this
\r
7159 * <div class="mdetail-params"><ul>
\r
7160 * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically
\r
7161 * at the <b>left</b> side of the container</div></li>
\r
7162 * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically at the
\r
7163 * <b>mid-height</b> of the container</div></li>
\r
7164 * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill
\r
7165 * the height of the container</div></li>
\r
7166 * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to
\r
7167 * the size of the largest item.</div></li>
\r
7169 align : 'top', // top, middle, stretch, strechmax
\r
7171 * @cfg {String} pack
\r
7172 * Controls how the child items of the container are packed together. Acceptable configuration values
\r
7173 * for this property are:
\r
7174 * <div class="mdetail-params"><ul>
\r
7175 * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
\r
7176 * <b>left</b> side of container</div></li>
\r
7177 * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
\r
7178 * <b>mid-width</b> of container</div></li>
\r
7179 * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>
\r
7180 * side of container</div></li>
\r
7184 * @cfg {Number} flex
\r
7185 * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
\r
7186 * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>
\r
7187 * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
\r
7188 * a <tt>flex</tt> value specified. Any child items that have either a <tt>flex = 0</tt> or
\r
7189 * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
\r
7193 onLayout : function(ct, target){
\r
7194 Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);
\r
7196 var cs = this.getItems(ct), cm, cw, margin,
\r
7197 size = this.getTargetSize(target),
\r
7198 w = size.width - target.getPadding('lr') - this.scrollOffset,
\r
7199 h = size.height - target.getPadding('tb'),
\r
7200 l = this.padding.left, t = this.padding.top,
\r
7201 isStart = this.pack == 'start',
\r
7202 isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
\r
7203 stretchHeight = h - (this.padding.top + this.padding.bottom),
\r
7210 Ext.each(cs, function(c){
\r
7212 totalFlex += c.flex || 0;
\r
7213 cw = c.getWidth();
\r
7214 margin = cm.left + cm.right;
\r
7215 extraWidth += cw + margin;
\r
7216 flexWidth += margin + (c.flex ? 0 : cw);
\r
7217 maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom);
\r
7219 extraWidth = w - extraWidth - this.padding.left - this.padding.right;
\r
7221 var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom;
\r
7222 switch(this.align){
\r
7224 this.innerCt.setSize(w, h);
\r
7226 case 'stretchmax':
\r
7228 this.innerCt.setSize(w, innerCtHeight);
\r
7231 this.innerCt.setSize(w, h = Math.max(h, innerCtHeight));
\r
7236 var availWidth = Math.max(0, w - this.padding.left - this.padding.right - flexWidth),
\r
7237 leftOver = availWidth,
\r
7241 availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom);
\r
7244 Ext.each(cs, function(c){
\r
7245 if(isStart && c.flex){
\r
7246 cw = Math.floor(availWidth * (c.flex / totalFlex));
\r
7252 if(this.pack == 'center'){
\r
7253 l += extraWidth ? extraWidth / 2 : 0;
\r
7254 }else if(this.pack == 'end'){
\r
7257 Ext.each(cs, function(c){
\r
7260 c.setPosition(l, t + cm.top);
\r
7261 if(isStart && c.flex){
\r
7262 cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0));
\r
7264 restore.push(c.getHeight());
\r
7266 c.setSize(cw, availableHeight);
\r
7268 cw = c.getWidth();
\r
7270 l += cw + cm.right;
\r
7274 Ext.each(cs, function(c){
\r
7275 var cm = c.margins;
\r
7276 if(this.align == 'stretch'){
\r
7277 c.setHeight((stretchHeight - (cm.top + cm.bottom)).constrain(
\r
7278 c.minHeight || 0, c.maxHeight || 1000000));
\r
7279 }else if(this.align == 'stretchmax'){
\r
7280 c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain(
\r
7281 c.minHeight || 0, c.maxHeight || 1000000));
\r
7283 if(this.align == 'middle'){
\r
7284 var diff = availableHeight - (c.getHeight() + cm.top + cm.bottom);
\r
7286 c.setPosition(c.x, t + cm.top + (diff/2));
\r
7289 if(isStart && c.flex){
\r
7290 c.setHeight(restore[idx++]);
\r
7297 * @property activeItem
\r
7302 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
7304 * @class Ext.Viewport
\r
7305 * @extends Ext.Container
\r
7306 * <p>A specialized container representing the viewable application area (the browser viewport).</p>
\r
7307 * <p>The Viewport renders itself to the document body, and automatically sizes itself to the size of
\r
7308 * the browser viewport and manages window resizing. There may only be one Viewport created
\r
7309 * in a page. Inner layouts are available by virtue of the fact that all {@link Ext.Panel Panel}s
\r
7310 * added to the Viewport, either through its {@link #items}, or through the items, or the {@link #add}
\r
7311 * method of any of its child Panels may themselves have a layout.</p>
\r
7312 * <p>The Viewport does not provide scrolling, so child Panels within the Viewport should provide
\r
7313 * for scrolling if needed using the {@link #autoScroll} config.</p>
\r
7314 * <p>An example showing a classic application border layout:</p><pre><code>
\r
7315 new Ext.Viewport({
\r
7319 html: '<h1 class="x-panel-header">Page Title</h1>',
\r
7322 margins: '0 0 5 0'
\r
7325 collapsible: true,
\r
7326 title: 'Navigation',
\r
7328 // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout}
\r
7331 title: 'Title for Panel',
\r
7332 collapsible: true,
\r
7333 html: 'Information goes here',
\r
7339 title: 'Title for the Grid Panel',
\r
7340 collapsible: true,
\r
7344 // remaining grid configuration not shown ...
\r
7345 // notice that the GridPanel is added directly as the region
\r
7346 // it is not "overnested" inside another Panel
\r
7349 xtype: 'tabpanel', // TabPanel itself has no title
\r
7351 title: 'Default Tab',
\r
7352 html: 'The first tab\'s content. Others may be added dynamically'
\r
7358 * Create a new Viewport
\r
7359 * @param {Object} config The config object
\r
7362 Ext.Viewport = Ext.extend(Ext.Container, {
\r
7364 * Privatize config options which, if used, would interfere with the
\r
7365 * correct operation of the Viewport as the sole manager of the
\r
7366 * layout of the document body.
\r
7369 * @cfg {Mixed} applyTo @hide
\r
7372 * @cfg {Boolean} allowDomMove @hide
\r
7375 * @cfg {Boolean} hideParent @hide
\r
7378 * @cfg {Mixed} renderTo @hide
\r
7381 * @cfg {Boolean} hideParent @hide
\r
7384 * @cfg {Number} height @hide
\r
7387 * @cfg {Number} width @hide
\r
7390 * @cfg {Boolean} autoHeight @hide
\r
7393 * @cfg {Boolean} autoWidth @hide
\r
7396 * @cfg {Boolean} deferHeight @hide
\r
7399 * @cfg {Boolean} monitorResize @hide
\r
7401 initComponent : function() {
\r
7402 Ext.Viewport.superclass.initComponent.call(this);
\r
7403 document.getElementsByTagName('html')[0].className += ' x-viewport';
\r
7404 this.el = Ext.getBody();
\r
7405 this.el.setHeight = Ext.emptyFn;
\r
7406 this.el.setWidth = Ext.emptyFn;
\r
7407 this.el.setSize = Ext.emptyFn;
\r
7408 this.el.dom.scroll = 'no';
\r
7409 this.allowDomMove = false;
\r
7410 this.autoWidth = true;
\r
7411 this.autoHeight = true;
\r
7412 Ext.EventManager.onWindowResize(this.fireResize, this);
\r
7413 this.renderTo = this.el;
\r
7416 fireResize : function(w, h){
\r
7417 this.fireEvent('resize', this, w, h, w, h);
\r
7420 Ext.reg('viewport', Ext.Viewport);/**
7422 * @extends Ext.Container
7423 * <p>Panel is a container that has specific functionality and structural components that make
7424 * it the perfect building block for application-oriented user interfaces.</p>
7425 * <p>Panels are, by virtue of their inheritance from {@link Ext.Container}, capable
7426 * of being configured with a {@link Ext.Container#layout layout}, and containing child Components.</p>
7427 * <p>When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.Container#add adding} Components
7428 * to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether
7429 * those child elements need to be sized using one of Ext's built-in <tt><b>{@link Ext.Container#layout layout}</b></tt> schemes. By
7430 * default, Panels use the {@link Ext.layout.ContainerLayout ContainerLayout} scheme. This simply renders
7431 * child components, appending them one after the other inside the Container, and <b>does not apply any sizing</b>
7433 * <p>A Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate
7434 * {@link #header}, {@link #footer} and {@link #body} sections (see {@link #frame} for additional
7436 * <p>Panel also provides built-in {@link #collapsible expandable and collapsible behavior}, along with
7437 * a variety of {@link #tools prebuilt tool buttons} that can be wired up to provide other customized
7438 * behavior. Panels can be easily dropped into any {@link Ext.Container Container} or layout, and the
7439 * layout and rendering pipeline is {@link Ext.Container#add completely managed by the framework}.</p>
7441 * @param {Object} config The config object
7444 Ext.Panel = Ext.extend(Ext.Container, {
7446 * The Panel's header {@link Ext.Element Element}. Read-only.
7447 * <p>This Element is used to house the {@link #title} and {@link #tools}</p>
7448 * <br><p><b>Note</b>: see the Note for <tt>{@link Ext.Component#el el} also.</p>
7453 * The Panel's body {@link Ext.Element Element} which may be used to contain HTML content.
7454 * The content may be specified in the {@link #html} config, or it may be loaded using the
7455 * {@link autoLoad} config, or through the Panel's {@link #getUpdater Updater}. Read-only.
7456 * <p>If this is used to load visible HTML elements in either way, then
7457 * the Panel may not be used as a Layout for hosting nested Panels.</p>
7458 * <p>If this Panel is intended to be used as the host of a Layout (See {@link #layout}
7459 * then the body Element must not be loaded or changed - it is under the control
7460 * of the Panel's Layout.
7461 * <br><p><b>Note</b>: see the Note for <tt>{@link Ext.Component#el el} also.</p>
7466 * The Panel's bwrap {@link Ext.Element Element} used to contain other Panel elements
7467 * (tbar, body, bbar, footer). See {@link #bodyCfg}. Read-only.
7472 * True if this panel is collapsed. Read-only.
7474 * @property collapsed
7477 * @cfg {Object} bodyCfg
7478 * <p>A {@link Ext.DomHelper DomHelper} element specification object may be specified for any
7479 * Panel Element.</p>
7480 * <p>By default, the Default element in the table below will be used for the html markup to
7481 * create a child element with the commensurate Default class name (<tt>baseCls</tt> will be
7482 * replaced by <tt>{@link #baseCls}</tt>):</p>
7484 * Panel Default Default Custom Additional Additional
7485 * Element element class element class style
7486 * ======== ========================== ========= ============== ===========
7487 * {@link #header} div {@link #baseCls}+'-header' {@link #headerCfg} headerCssClass headerStyle
7488 * {@link #bwrap} div {@link #baseCls}+'-bwrap' {@link #bwrapCfg} bwrapCssClass bwrapStyle
7489 * + tbar div {@link #baseCls}+'-tbar' {@link #tbarCfg} tbarCssClass tbarStyle
7490 * + {@link #body} div {@link #baseCls}+'-body' {@link #bodyCfg} {@link #bodyCssClass} {@link #bodyStyle}
7491 * + bbar div {@link #baseCls}+'-bbar' {@link #bbarCfg} bbarCssClass bbarStyle
7492 * + {@link #footer} div {@link #baseCls}+'-footer' {@link #footerCfg} footerCssClass footerStyle
7494 * <p>Configuring a Custom element may be used, for example, to force the {@link #body} Element
7495 * to use a different form of markup than is created by default. An example of this might be
7496 * to {@link Ext.Element#createChild create a child} Panel containing a custom content, such as
7497 * a header, or forcing centering of all Panel content by having the body be a <center>
7501 title: 'Message Title',
7502 renderTo: Ext.getBody(),
7503 width: 200, height: 130,
7506 cls: 'x-panel-body', // Default class not applied if Custom element specified
7511 cls: 'x-panel-footer' // same as the Default class
7514 footerCssClass: 'custom-footer', // additional css class, see {@link Ext.element#addClass addClass}
7515 footerStyle: 'background-color:red' // see {@link #bodyStyle}
7518 * <p>The example above also explicitly creates a <tt>{@link #footer}</tt> with custom markup and
7519 * styling applied.</p>
7522 * @cfg {Object} headerCfg
7523 * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
7524 * of this Panel's {@link #header} Element. See <tt>{@link #bodyCfg}</tt> also.</p>
7527 * @cfg {Object} bwrapCfg
7528 * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
7529 * of this Panel's {@link #bwrap} Element. See <tt>{@link #bodyCfg}</tt> also.</p>
7532 * @cfg {Object} tbarCfg
7533 * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
7534 * of this Panel's {@link #tbar} Element. See <tt>{@link #bodyCfg}</tt> also.</p>
7537 * @cfg {Object} bbarCfg
7538 * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
7539 * of this Panel's {@link #bbar} Element. See <tt>{@link #bodyCfg}</tt> also.</p>
7542 * @cfg {Object} footerCfg
7543 * <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
7544 * of this Panel's {@link #footer} Element. See <tt>{@link #bodyCfg}</tt> also.</p>
7547 * @cfg {Boolean} closable
7548 * Panels themselves do not directly support being closed, but some Panel subclasses do (like
7549 * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}. Specify <tt>true</tt>
7550 * to enable closing in such situations. Defaults to <tt>false</tt>.
7553 * The Panel's footer {@link Ext.Element Element}. Read-only.
7554 * <p>This Element is used to house the Panel's <tt>{@link #buttons}</tt> or <tt>{@link #fbar}</tt>.</p>
7555 * <br><p><b>Note</b>: see the Note for <tt>{@link Ext.Component#el el} also.</p>
7560 * @cfg {Mixed} applyTo
7561 * <p>The id of the node, a DOM node or an existing Element corresponding to a DIV that is already present in
7562 * the document that specifies some panel-specific structural markup. When <tt>applyTo</tt> is used,
7563 * constituent parts of the panel can be specified by CSS class name within the main element, and the panel
7564 * will automatically create those components from that markup. Any required components not specified in the
7565 * markup will be autogenerated if necessary.</p>
7566 * <p>The following class names are supported (baseCls will be replaced by {@link #baseCls}):</p>
7567 * <ul><li>baseCls + '-header'</li>
7568 * <li>baseCls + '-header-text'</li>
7569 * <li>baseCls + '-bwrap'</li>
7570 * <li>baseCls + '-tbar'</li>
7571 * <li>baseCls + '-body'</li>
7572 * <li>baseCls + '-bbar'</li>
7573 * <li>baseCls + '-footer'</li></ul>
7574 * <p>Using this config, a call to render() is not required. If applyTo is specified, any value passed for
7575 * {@link #renderTo} will be ignored and the target element's parent node will automatically be used as the
7576 * panel's container.</p>
7579 * @cfg {Object/Array} tbar
7580 * <p>The top toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
7581 * buttons/button configs to be added to the toolbar. Note that this is not available as a property after render.
7582 * To access the top toolbar after render, use {@link #getTopToolbar}.</p>
7583 * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> be updated by a load
7584 * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
7585 * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
7586 * submission parameters are collected from the DOM tree.</p>
7589 * @cfg {Object/Array} bbar
7590 * <p>The bottom toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of
7591 * buttons/button configs to be added to the toolbar. Note that this is not available as a property after render.
7592 * To access the bottom toolbar after render, use {@link #getBottomToolbar}.</p>
7593 * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not<b> be updated by a load
7594 * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
7595 * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
7596 * submission parameters are collected from the DOM tree.</p>
7598 /** @cfg {Object/Array} fbar
7599 * <p>A {@link Ext.Toolbar Toolbar} object, a Toolbar config, or an array of
7600 * {@link Ext.Button Button}s/{@link Ext.Button Button} configs, describing a {@link Ext.Toolbar Toolbar} to be rendered into this Panel's footer element.</p>
7601 * <p>After render, the <code>fbar</code> property will be an {@link Ext.Toolbar Toolbar} instance.</p>
7602 * <p>If <tt>{@link #buttons}</tt> are specified, they will supersede the <tt>fbar</tt> configuration property.</p>
7603 * The Panel's <tt>{@link #buttonAlign}</tt> configuration affects the layout of these items, for example:
7605 var w = new Ext.Window({
7608 bbar: new Ext.Toolbar({
7615 {@link #buttonAlign}: 'left', // anything but 'center' or 'right' and you can use "-", and "->"
7616 // to control the alignment of fbar items
7624 * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not<b> be updated by a load
7625 * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and
7626 * so are not scanned to collect form items. However, the values <b>will</b> be submitted because form
7627 * submission parameters are collected from the DOM tree.</p>
7630 * @cfg {Boolean} header
7631 * <tt>true</tt> to create the Panel's header element explicitly, <tt>false</tt> to skip creating
7632 * it. If a <tt>{@link #title}</tt> is set the header will be created automatically, otherwise it will not.
7633 * If a <tt>{@link #title}</tt> is set but <tt>header</tt> is explicitly set to <tt>false</tt>, the header
7634 * will not be rendered.
7637 * @cfg {Boolean} footer
7638 * <tt>true</tt> to create the footer element explicitly, false to skip creating it. The footer
7639 * will be created automatically if <tt>{@link #buttons}</tt> or a <tt>{@link #fbar}</tt> have
7640 * been configured. See <tt>{@link #bodyCfg}</tt> for an example.
7643 * @cfg {String} title
7644 * The title text to be used as innerHTML (html tags are accepted) to display in the panel
7645 * <tt>{@link #header}</tt> (defaults to ''). When a <tt>title</tt> is specified the
7646 * <tt>{@link #header}</tt> element will automatically be created and displayed unless
7647 * {@link #header} is explicitly set to <tt>false</tt>. If you do not want to specify a
7648 * <tt>title</tt> at config time, but you may want one later, you must either specify a non-empty
7649 * <tt>title</tt> (a blank space ' ' will do) or <tt>header:true</tt> so that the container
7650 * element will get created.
7653 * @cfg {Array} buttons
7654 * <tt>buttons</tt> will be used as <tt>{@link Ext.Container#items items}</tt> for the toolbar in
7655 * the footer (<tt>{@link #fbar}</tt>). Typically the value of this configuration property will be
7656 * an array of {@link Ext.Button}s or {@link Ext.Button} configuration objects.
7657 * If an item is configured with <tt>minWidth</tt> or the Panel is configured with <tt>minButtonWidth</tt>,
7658 * that width will be applied to the item.
7661 * @cfg {Object/String/Function} autoLoad
7662 * A valid url spec according to the Updater {@link Ext.Updater#update} method.
7663 * If autoLoad is not null, the panel will attempt to load its contents
7664 * immediately upon render.<p>
7665 * The URL will become the default URL for this panel's {@link #body} element,
7666 * so it may be {@link Ext.Element#refresh refresh}ed at any time.</p>
7669 * @cfg {Boolean} frame
7670 * <tt>false</tt> by default to render with plain 1px square borders. <tt>true</tt> to render with
7671 * 9 elements, complete with custom rounded corners (also see {@link Ext.Element#boxWrap}).
7672 * <p>The template generated for each condition is depicted below:</p><pre><code>
7675 <div id="developer-specified-id-goes-here" class="x-panel">
7677 <div class="x-panel-header"><span class="x-panel-header-text">Title: (frame:false)</span></div>
7679 <div class="x-panel-bwrap">
7680 <div class="x-panel-body"><p>html value goes here</p></div>
7684 // frame = true (create 9 elements)
7685 <div id="developer-specified-id-goes-here" class="x-panel">
7686 <div class="x-panel-tl"><div class="x-panel-tr"><div class="x-panel-tc">
7687 <div class="x-panel-header"><span class="x-panel-header-text">Title: (frame:true)</span></div>
7688 </div></div></div>
7690 <div class="x-panel-bwrap">
7691 <div class="x-panel-ml"><div class="x-panel-mr"><div class="x-panel-mc">
7692 <div class="x-panel-body"><p>html value goes here</p></div>
7693 </div></div></div>
7695 <div class="x-panel-bl"><div class="x-panel-br"><div class="x-panel-bc"/>
7696 </div></div></div>
7701 * @cfg {Boolean} border
7702 * True to display the borders of the panel's body element, false to hide them (defaults to true). By default,
7703 * the border is a 2px wide inset border, but this can be further altered by setting {@link #bodyBorder} to false.
7706 * @cfg {Boolean} bodyBorder
7707 * True to display an interior border on the body element of the panel, false to hide it (defaults to true).
7708 * This only applies when {@link #border} == true. If border == true and bodyBorder == false, the border will display
7709 * as a 1px wide inset border, giving the entire body element an inset appearance.
7712 * @cfg {String/Object/Function} bodyCssClass
7713 * Additional css class selector to be applied to the {@link #body} element in the format expected by
7714 * {@link Ext.Element#addClass} (defaults to null). See {@link #bodyCfg}.
7717 * @cfg {String/Object/Function} bodyStyle
7718 * Custom CSS styles to be applied to the {@link #body} element in the format expected by
7719 * {@link Ext.Element#applyStyles} (defaults to null). See {@link #bodyCfg}.
7722 * @cfg {String} iconCls
7723 * The CSS class selector that specifies a background image to be used as the header icon (defaults to '').
7724 * <p>An example of specifying a custom icon class would be something like:
7726 // specify the property in the config for the class:
7730 // css class that specifies background image to be used as the icon image:
7731 .my-icon { background-image: url(../images/my-icon.gif) 0 6px no-repeat !important; }
7735 * @cfg {Boolean} collapsible
7736 * True to make the panel collapsible and have the expand/collapse toggle button automatically rendered into
7737 * the header tool button area, false to keep the panel statically sized with no button (defaults to false).
7740 * @cfg {Array} tools
7741 * An array of tool button configs to be added to the header tool area. When rendered, each tool is
7742 * stored as an {@link Ext.Element Element} referenced by a public property called <tt><b></b>tools.<i><tool-type></i></tt>
7743 * <p>Each tool config may contain the following properties:
7744 * <div class="mdetail-params"><ul>
7745 * <li><b>id</b> : String<div class="sub-desc"><b>Required.</b> The type
7746 * of tool to create. By default, this assigns a CSS class of the form <tt>x-tool-<i><tool-type></i></tt> to the
7747 * resulting tool Element. Ext provides CSS rules, and an icon sprite containing images for the tool types listed below.
7748 * The developer may implement custom tools by supplying alternate CSS rules and background images:
7750 * <div class="x-tool x-tool-toggle" style="float:left; margin-right:5;"> </div><div><tt> toggle</tt> (Created by default when {@link #collapsible} is <tt>true</tt>)</div>
7751 * <div class="x-tool x-tool-close" style="float:left; margin-right:5;"> </div><div><tt> close</tt></div>
7752 * <div class="x-tool x-tool-minimize" style="float:left; margin-right:5;"> </div><div><tt> minimize</tt></div>
7753 * <div class="x-tool x-tool-maximize" style="float:left; margin-right:5;"> </div><div><tt> maximize</tt></div>
7754 * <div class="x-tool x-tool-restore" style="float:left; margin-right:5;"> </div><div><tt> restore</tt></div>
7755 * <div class="x-tool x-tool-gear" style="float:left; margin-right:5;"> </div><div><tt> gear</tt></div>
7756 * <div class="x-tool x-tool-pin" style="float:left; margin-right:5;"> </div><div><tt> pin</tt></div>
7757 * <div class="x-tool x-tool-unpin" style="float:left; margin-right:5;"> </div><div><tt> unpin</tt></div>
7758 * <div class="x-tool x-tool-right" style="float:left; margin-right:5;"> </div><div><tt> right</tt></div>
7759 * <div class="x-tool x-tool-left" style="float:left; margin-right:5;"> </div><div><tt> left</tt></div>
7760 * <div class="x-tool x-tool-up" style="float:left; margin-right:5;"> </div><div><tt> up</tt></div>
7761 * <div class="x-tool x-tool-down" style="float:left; margin-right:5;"> </div><div><tt> down</tt></div>
7762 * <div class="x-tool x-tool-refresh" style="float:left; margin-right:5;"> </div><div><tt> refresh</tt></div>
7763 * <div class="x-tool x-tool-minus" style="float:left; margin-right:5;"> </div><div><tt> minus</tt></div>
7764 * <div class="x-tool x-tool-plus" style="float:left; margin-right:5;"> </div><div><tt> plus</tt></div>
7765 * <div class="x-tool x-tool-help" style="float:left; margin-right:5;"> </div><div><tt> help</tt></div>
7766 * <div class="x-tool x-tool-search" style="float:left; margin-right:5;"> </div><div><tt> search</tt></div>
7767 * <div class="x-tool x-tool-save" style="float:left; margin-right:5;"> </div><div><tt> save</tt></div>
7768 * <div class="x-tool x-tool-print" style="float:left; margin-right:5;"> </div><div><tt> print</tt></div>
7770 * <li><b>handler</b> : Function<div class="sub-desc"><b>Required.</b> The function to
7771 * call when clicked. Arguments passed are:<ul>
7772 * <li><b>event</b> : Ext.EventObject<div class="sub-desc">The click event.</div></li>
7773 * <li><b>toolEl</b> : Ext.Element<div class="sub-desc">The tool Element.</div></li>
7774 * <li><b>panel</b> : Ext.Panel<div class="sub-desc">The host Panel</div></li>
7775 * <li><b>tc</b> : Ext.Panel<div class="sub-desc">The tool configuration object</div></li>
7777 * <li><b>stopEvent</b> : Boolean<div class="sub-desc">Defaults to true. Specify as false to allow click event to propagate.</div></li>
7778 * <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the handler.</div></li>
7779 * <li><b>qtip</b> : String/Object<div class="sub-desc">A tip string, or
7780 * a config argument to {@link Ext.QuickTip#register}</div></li>
7781 * <li><b>hidden</b> : Boolean<div class="sub-desc">True to initially render hidden.</div></li>
7782 * <li><b>on</b> : Object<div class="sub-desc">A listener config object specifiying
7783 * event listeners in the format of an argument to {@link #addListener}</div></li>
7785 * <p>Note that, apart from the toggle tool which is provided when a panel is collapsible, these
7786 * tools only provide the visual button. Any required functionality must be provided by adding
7787 * handlers that implement the necessary behavior.</p>
7788 * <p>Example usage:</p>
7792 qtip: 'Refresh form Data',
7794 handler: function(event, toolEl, panel){
7801 handler: function(event, toolEl, panel){
7806 * <p>For the custom id of <tt>'help'</tt> define two relevant css classes with a link to
7807 * a 15x15 image:</p>
7809 .x-tool-help {background-image: url(images/help.png);}
7810 .x-tool-help-over {background-image: url(images/help_over.png);}
7811 // if using an image sprite:
7812 .x-tool-help {background-image: url(images/help.png) no-repeat 0 0;}
7813 .x-tool-help-over {background-position:-15px 0;}
7817 * @cfg {Ext.Template/Ext.XTemplate} toolTemplate
7818 * <p>A Template used to create {@link #tools} in the {@link #header} Element. Defaults to:</p><pre><code>
7819 new Ext.Template('<div class="x-tool x-tool-{id}">&#160;</div>')</code></pre>
7820 * <p>This may may be overridden to provide a custom DOM structure for tools based upon a more
7821 * complex XTemplate. The template's data is a single tool configuration object (Not the entire Array)
7822 * as specified in {@link #tools}. In the following example an <a> tag is used to provide a
7823 * visual indication when hovering over the tool:</p><pre><code>
7824 var win = new Ext.Window({
7827 href: '/MyPdfDoc.pdf'
7829 toolTemplate: new Ext.XTemplate(
7830 '<tpl if="id==\'download\'">',
7831 '<a class="x-tool x-tool-pdf" href="{href}"></a>',
7833 '<tpl if="id!=\'download\'">',
7834 '<div class="x-tool x-tool-{id}">&#160;</div>',
7841 * <p>Note that the CSS class "x-tool-pdf" should have an associated style rule which provides an
7842 * appropriate background image, something like:</p>
7844 a.x-tool-pdf {background-image: url(../shared/extjs/images/pdf.gif)!important;}
7848 * @cfg {Boolean} hideCollapseTool
7849 * <tt>true</tt> to hide the expand/collapse toggle button when <code>{@link #collapsible} == true</code>,
7850 * <tt>false</tt> to display it (defaults to <tt>false</tt>).
7853 * @cfg {Boolean} titleCollapse
7854 * <tt>true</tt> to allow expanding and collapsing the panel (when <tt>{@link #collapsible} = true</tt>)
7855 * by clicking anywhere in the header bar, <tt>false</tt>) to allow it only by clicking to tool button
7856 * (defaults to <tt>false</tt>)). If this panel is a child item of a border layout also see the
7857 * {@link Ext.layout.BorderLayout.Region BorderLayout.Region}
7858 * <tt>{@link Ext.layout.BorderLayout.Region#floatable floatable}</tt> config option.
7861 * @cfg {Boolean} autoScroll
7862 * <tt>true</tt> to use overflow:'auto' on the panel's body element and show scroll bars automatically when
7863 * necessary, <tt>false</tt> to clip any overflowing content (defaults to <tt>false</tt>).
7866 * @cfg {Mixed} floating
7867 * <p>This property is used to configure the underlying {@link Ext.Layer}. Acceptable values for this
7868 * configuration property are:</p><div class="mdetail-params"><ul>
7869 * <li><b><tt>false</tt></b> : <b>Default.</b><div class="sub-desc">Display the panel inline where it is
7870 * rendered.</div></li>
7871 * <li><b><tt>true</tt></b> : <div class="sub-desc">Float the panel (absolute position it with automatic
7872 * shimming and shadow).<ul>
7873 * <div class="sub-desc">Setting floating to true will create an Ext.Layer for this panel and display the
7874 * panel at negative offsets so that it is hidden.</div>
7875 * <div class="sub-desc">Since the panel will be absolute positioned, the position must be set explicitly
7876 * <i>after</i> render (e.g., <tt>myPanel.setPosition(100,100);</tt>).</div>
7877 * <div class="sub-desc"><b>Note</b>: when floating a panel you should always assign a fixed width,
7878 * otherwise it will be auto width and will expand to fill to the right edge of the viewport.</div>
7880 * <li><b><tt>{@link Ext.Layer object}</tt></b> : <div class="sub-desc">The specified object will be used
7881 * as the configuration object for the {@link Ext.Layer} that will be created.</div></li>
7885 * @cfg {Boolean/String} shadow
7886 * <tt>true</tt> (or a valid Ext.Shadow {@link Ext.Shadow#mode} value) to display a shadow behind the
7887 * panel, <tt>false</tt> to display no shadow (defaults to <tt>'sides'</tt>). Note that this option
7888 * only applies when <tt>{@link #floating} = true</tt>.
7891 * @cfg {Number} shadowOffset
7892 * The number of pixels to offset the shadow if displayed (defaults to <tt>4</tt>). Note that this
7893 * option only applies when <tt>{@link #floating} = true</tt>.
7896 * @cfg {Boolean} shim
7897 * <tt>false</tt> to disable the iframe shim in browsers which need one (defaults to <tt>true</tt>).
7898 * Note that this option only applies when <tt>{@link #floating} = true</tt>.
7901 * @cfg {String/Object} html
7902 * An HTML fragment, or a {@link Ext.DomHelper DomHelper} specification to use as the panel's body
7903 * content (defaults to ''). The HTML content is added by the Panel's {@link #afterRender} method,
7904 * and so the document will not contain this HTML at the time the {@link #render} event is fired.
7905 * This content is inserted into the body <i>before</i> any configured {@link #contentEl} is appended.
7908 * @cfg {String} contentEl
7909 * <p>Specify the <tt>id</tt> of an existing HTML node to use as the panel's body content
7910 * (defaults to '').</p><div><ul>
7911 * <li><b>Description</b> : <ul>
7912 * <div class="sub-desc">This config option is used to take an existing HTML element and place it in the body
7913 * of a new panel (it simply moves the specified DOM element into the body element of the Panel
7914 * <i>when the Panel is rendered</i> to use as the content (it is not going to be the
7915 * actual panel itself).</div>
7917 * <li><b>Notes</b> : <ul>
7918 * <div class="sub-desc">The specified HTML Element is appended to the Panel's {@link #body} Element by the
7919 * Panel's {@link #afterRender} method <i>after any configured {@link #html HTML} has
7920 * been inserted</i>, and so the document will not contain this HTML at the time the
7921 * {@link #render} event is fired.</div>
7922 * <div class="sub-desc">The specified HTML element used will not participate in any layout scheme that the
7923 * Panel may use. It's just HTML. Layouts operate on child items.</div>
7924 * <div class="sub-desc">Add either the <tt>x-hidden</tt> or the <tt>x-hide-display</tt> CSS class to
7925 * prevent a brief flicker of the content before it is rendered to the panel.</div>
7930 * @cfg {Object/Array} keys
7931 * A {@link Ext.KeyMap} config object (in the format expected by {@link Ext.KeyMap#addBinding}
7932 * used to assign custom key handling to this panel (defaults to <tt>null</tt>).
7935 * @cfg {Boolean/Object} draggable
7936 * <p><tt>true</tt> to enable dragging of this Panel (defaults to <tt>false</tt>).</p>
7937 * <p>For custom drag/drop implementations, an <b>Ext.Panel.DD</b> config could also be passed
7938 * in this config instead of <tt>true</tt>. Ext.Panel.DD is an internal, undocumented class which
7939 * moves a proxy Element around in place of the Panel's element, but provides no other behaviour
7940 * during dragging or on drop. It is a subclass of {@link Ext.dd.DragSource}, so behaviour may be
7941 * added by implementing the interface methods of {@link Ext.dd.DragDrop} e.g.:
7947 renderTo: Ext.getBody(),
7953 // Config option of Ext.Panel.DD class.
7954 // It's a floating Panel, so do not show a placeholder proxy in the original position.
7957 // Called for each mousemove event while dragging the DD object.
7958 onDrag : function(e){
7959 // Record the x,y position of the drag proxy so that we can
7960 // position the Panel at end of drag.
7961 var pel = this.proxy.getEl();
7962 this.x = pel.getLeft(true);
7963 this.y = pel.getTop(true);
7965 // Keep the Shadow aligned if there is one.
7966 var s = this.panel.getEl().shadow;
7968 s.realign(this.x, this.y, pel.getWidth(), pel.getHeight());
7972 // Called on the mouseup event.
7973 endDrag : function(e){
7974 this.panel.setPosition(this.x, this.y);
7981 * @cfg {String} tabTip
7982 * A string to be used as innerHTML (html tags are accepted) to show in a tooltip when mousing over
7983 * the tab of a Ext.Panel which is an item of a {@link Ext.TabPanel}. {@link Ext.QuickTips}.init()
7984 * must be called in order for the tips to render.
7987 * @cfg {Boolean} disabled
7988 * Render this panel disabled (default is <tt>false</tt>). An important note when using the disabled
7989 * config on panels is that IE will often fail to initialize the disabled mask element correectly if
7990 * the panel's layout has not yet completed by the time the Panel is disabled during the render process.
7991 * If you experience this issue, you may need to instead use the {@link #afterlayout} event to initialize
7992 * the disabled state:
8001 single: true // important, as many layouts can occur
8008 * @cfg {Boolean} autoHeight
8009 * <tt>true</tt> to use height:'auto', <tt>false</tt> to use fixed height (defaults to <tt>false</tt>).
8010 * <b>Note</b>: Setting <tt>autoHeight:true</tt> means that the browser will manage the panel's height
8011 * based on its contents, and that Ext will not manage it at all. If the panel is within a layout that
8012 * manages dimensions (<tt>fit</tt>, <tt>border</tt>, etc.) then setting <tt>autoHeight:true</tt>
8013 * can cause issues with scrolling and will not generally work as expected since the panel will take
8014 * on the height of its contents rather than the height required by the Ext layout.
8019 * @cfg {String} baseCls
8020 * The base CSS class to apply to this panel's element (defaults to <tt>'x-panel'</tt>).
8021 * <p>Another option available by default is to specify <tt>'x-plain'</tt> which strips all styling
8022 * except for required attributes for Ext layouts to function (e.g. overflow:hidden).
8023 * See <tt>{@link #unstyled}</tt> also.</p>
8025 baseCls : 'x-panel',
8027 * @cfg {String} collapsedCls
8028 * A CSS class to add to the panel's element after it has been collapsed (defaults to
8029 * <tt>'x-panel-collapsed'</tt>).
8031 collapsedCls : 'x-panel-collapsed',
8033 * @cfg {Boolean} maskDisabled
8034 * <tt>true</tt> to mask the panel when it is {@link #disabled}, <tt>false</tt> to not mask it (defaults
8035 * to <tt>true</tt>). Either way, the panel will always tell its contained elements to disable themselves
8036 * when it is disabled, but masking the panel can provide an additional visual cue that the panel is
8039 maskDisabled : true,
8041 * @cfg {Boolean} animCollapse
8042 * <tt>true</tt> to animate the transition when the panel is collapsed, <tt>false</tt> to skip the
8043 * animation (defaults to <tt>true</tt> if the {@link Ext.Fx} class is available, otherwise <tt>false</tt>).
8045 animCollapse : Ext.enableFx,
8047 * @cfg {Boolean} headerAsText
8048 * <tt>true</tt> to display the panel <tt>{@link #title}</tt> in the <tt>{@link #header}</tt>,
8049 * <tt>false</tt> to hide it (defaults to <tt>true</tt>).
8051 headerAsText : true,
8053 * @cfg {String} buttonAlign
8054 * The alignment of any {@link #buttons} added to this panel. Valid values are <tt>'right'</tt>,
8055 * <tt>'left'</tt> and <tt>'center'</tt> (defaults to <tt>'right'</tt>).
8057 buttonAlign : 'right',
8059 * @cfg {Boolean} collapsed
8060 * <tt>true</tt> to render the panel collapsed, <tt>false</tt> to render it expanded (defaults to
8065 * @cfg {Boolean} collapseFirst
8066 * <tt>true</tt> to make sure the collapse/expand toggle button always renders first (to the left of)
8067 * any other tools in the panel's title bar, <tt>false</tt> to render it last (defaults to <tt>true</tt>).
8069 collapseFirst : true,
8071 * @cfg {Number} minButtonWidth
8072 * Minimum width in pixels of all {@link #buttons} in this panel (defaults to <tt>75</tt>)
8074 minButtonWidth : 75,
8076 * @cfg {Boolean} unstyled
8077 * Overrides the <tt>{@link #baseCls}</tt> setting to <tt>{@link #baseCls} = 'x-plain'</tt> which renders
8078 * the panel unstyled except for required attributes for Ext layouts to function (e.g. overflow:hidden).
8081 * @cfg {String} elements
8082 * A comma-delimited list of panel elements to initialize when the panel is rendered. Normally, this list will be
8083 * generated automatically based on the items added to the panel at config time, but sometimes it might be useful to
8084 * make sure a structural element is rendered even if not specified at config time (for example, you may want
8085 * to add a button or toolbar dynamically after the panel has been rendered). Adding those elements to this
8086 * list will allocate the required placeholders in the panel when it is rendered. Valid values are<div class="mdetail-params"><ul>
8087 * <li><tt>header</tt></li>
8088 * <li><tt>tbar</tt> (top bar)</li>
8089 * <li><tt>body</tt></li>
8090 * <li><tt>bbar</tt> (bottom bar)</li>
8091 * <li><tt>footer</tt></li>
8093 * Defaults to '<tt>body</tt>'.
8097 * @cfg {Boolean} preventBodyReset
8098 * Defaults to <tt>false</tt>. When set to <tt>true</tt>, an extra css class <tt>'x-panel-normal'</tt>
8099 * will be added to the panel's element, effectively applying css styles suggested by the W3C
8100 * (see http://www.w3.org/TR/CSS21/sample.html) to the Panel's <b>body</b> element (not the header,
8103 preventBodyReset : false,
8105 // protected - these could be used to customize the behavior of the window,
8106 // but changing them would not be useful without further mofifications and
8107 // could lead to unexpected or undesirable results.
8108 toolTarget : 'header',
8109 collapseEl : 'bwrap',
8113 // private, notify box this class will handle heights
8120 collapseDefaults : {
8125 initComponent : function(){
8126 Ext.Panel.superclass.initComponent.call(this);
8131 * Fires after the Panel has been resized.
8132 * @param {Ext.Panel} p the Panel which has been resized.
8133 * @param {Number} width The Panel's new width.
8134 * @param {Number} height The Panel's new height.
8138 * @event titlechange
8139 * Fires after the Panel title has been {@link #title set} or {@link #setTitle changed}.
8140 * @param {Ext.Panel} p the Panel which has had its title changed.
8141 * @param {String} The new title.
8146 * Fires after the Panel icon class has been {@link #iconCls set} or {@link #setIconClass changed}.
8147 * @param {Ext.Panel} p the Panel which has had its {@link #iconCls icon class} changed.
8148 * @param {String} The new icon class.
8149 * @param {String} The old icon class.
8154 * Fires after the Panel has been collapsed.
8155 * @param {Ext.Panel} p the Panel that has been collapsed.
8160 * Fires after the Panel has been expanded.
8161 * @param {Ext.Panel} p The Panel that has been expanded.
8165 * @event beforecollapse
8166 * Fires before the Panel is collapsed. A handler can return false to cancel the collapse.
8167 * @param {Ext.Panel} p the Panel being collapsed.
8168 * @param {Boolean} animate True if the collapse is animated, else false.
8172 * @event beforeexpand
8173 * Fires before the Panel is expanded. A handler can return false to cancel the expand.
8174 * @param {Ext.Panel} p The Panel being expanded.
8175 * @param {Boolean} animate True if the expand is animated, else false.
8179 * @event beforeclose
8180 * Fires before the Panel is closed. Note that Panels do not directly support being closed, but some
8181 * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel. This event only
8182 * applies to such subclasses.
8183 * A handler can return false to cancel the close.
8184 * @param {Ext.Panel} p The Panel being closed.
8189 * Fires after the Panel is closed. Note that Panels do not directly support being closed, but some
8190 * Panel subclasses do (like {@link Ext.Window}) or a Panel within a Ext.TabPanel.
8191 * @param {Ext.Panel} p The Panel that has been closed.
8196 * Fires after the Panel has been visually activated.
8197 * Note that Panels do not directly support being activated, but some Panel subclasses
8198 * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
8199 * activate and deactivate events under the control of the TabPanel.
8200 * @param {Ext.Panel} p The Panel that has been activated.
8205 * Fires after the Panel has been visually deactivated.
8206 * Note that Panels do not directly support being deactivated, but some Panel subclasses
8207 * do (like {@link Ext.Window}). Panels which are child Components of a TabPanel fire the
8208 * activate and deactivate events under the control of the TabPanel.
8209 * @param {Ext.Panel} p The Panel that has been deactivated.
8215 this.baseCls = 'x-plain';
8220 this.elements += ',tbar';
8221 if(Ext.isObject(this.tbar)){
8222 this.topToolbar = this.tbar;
8227 this.elements += ',bbar';
8228 if(Ext.isObject(this.bbar)){
8229 this.bottomToolbar = this.bbar;
8234 if(this.header === true){
8235 this.elements += ',header';
8237 }else if(this.headerCfg || (this.title && this.header !== false)){
8238 this.elements += ',header';
8241 if(this.footerCfg || this.footer === true){
8242 this.elements += ',footer';
8247 this.elements += ',footer';
8248 var btns = this.buttons;
8250 * This Panel's Array of buttons as created from the <tt>{@link #buttons}</tt>
8251 * config property. Read only.
8256 for(var i = 0, len = btns.length; i < len; i++) {
8257 if(btns[i].render){ // button instance
8258 this.buttons.push(btns[i]);
8259 }else if(btns[i].xtype){
8260 this.buttons.push(Ext.create(btns[i], 'button'));
8262 this.addButton(btns[i]);
8267 this.elements += ',footer';
8270 this.on('render', this.doAutoLoad, this, {delay:10});
8275 createElement : function(name, pnode){
8277 pnode.appendChild(this[name].dom);
8281 if(name === 'bwrap' || this.elements.indexOf(name) != -1){
8282 if(this[name+'Cfg']){
8283 this[name] = Ext.fly(pnode).createChild(this[name+'Cfg']);
8285 var el = document.createElement('div');
8286 el.className = this[name+'Cls'];
8287 this[name] = Ext.get(pnode.appendChild(el));
8289 if(this[name+'CssClass']){
8290 this[name].addClass(this[name+'CssClass']);
8292 if(this[name+'Style']){
8293 this[name].applyStyles(this[name+'Style']);
8299 onRender : function(ct, position){
8300 Ext.Panel.superclass.onRender.call(this, ct, position);
8301 this.createClasses();
8306 el.addClass(this.baseCls);
8307 if(d.firstChild){ // existing markup
8308 this.header = el.down('.'+this.headerCls);
8309 this.bwrap = el.down('.'+this.bwrapCls);
8310 var cp = this.bwrap ? this.bwrap : el;
8311 this.tbar = cp.down('.'+this.tbarCls);
8312 this.body = cp.down('.'+this.bodyCls);
8313 this.bbar = cp.down('.'+this.bbarCls);
8314 this.footer = cp.down('.'+this.footerCls);
8315 this.fromMarkup = true;
8317 if (this.preventBodyReset === true) {
8318 el.addClass('x-panel-reset');
8321 el.addClass(this.cls);
8325 this.elements += ',footer';
8328 // This block allows for maximum flexibility and performance when using existing markup
8330 // framing requires special markup
8332 el.insertHtml('afterBegin', String.format(Ext.Element.boxMarkup, this.baseCls));
8334 this.createElement('header', d.firstChild.firstChild.firstChild);
8335 this.createElement('bwrap', d);
8337 // append the mid and bottom frame to the bwrap
8338 bw = this.bwrap.dom;
8339 var ml = d.childNodes[1], bl = d.childNodes[2];
8343 var mc = bw.firstChild.firstChild.firstChild;
8344 this.createElement('tbar', mc);
8345 this.createElement('body', mc);
8346 this.createElement('bbar', mc);
8347 this.createElement('footer', bw.lastChild.firstChild.firstChild);
8350 this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
8353 this.createElement('header', d);
8354 this.createElement('bwrap', d);
8356 // append the mid and bottom frame to the bwrap
8357 bw = this.bwrap.dom;
8358 this.createElement('tbar', bw);
8359 this.createElement('body', bw);
8360 this.createElement('bbar', bw);
8361 this.createElement('footer', bw);
8364 this.body.addClass(this.bodyCls + '-noheader');
8366 this.tbar.addClass(this.tbarCls + '-noheader');
8371 if(this.padding !== undefined) {
8372 this.body.setStyle('padding', this.body.addUnits(this.padding));
8375 if(this.border === false){
8376 this.el.addClass(this.baseCls + '-noborder');
8377 this.body.addClass(this.bodyCls + '-noborder');
8379 this.header.addClass(this.headerCls + '-noborder');
8382 this.footer.addClass(this.footerCls + '-noborder');
8385 this.tbar.addClass(this.tbarCls + '-noborder');
8388 this.bbar.addClass(this.bbarCls + '-noborder');
8392 if(this.bodyBorder === false){
8393 this.body.addClass(this.bodyCls + '-noborder');
8396 this.bwrap.enableDisplayMode('block');
8399 this.header.unselectable();
8401 // for tools, we need to wrap any existing header markup
8402 if(this.headerAsText){
8403 this.header.dom.innerHTML =
8404 '<span class="' + this.headerTextCls + '">'+this.header.dom.innerHTML+'</span>';
8407 this.setIconClass(this.iconCls);
8413 this.makeFloating(this.floating);
8416 if(this.collapsible){
8417 this.tools = this.tools ? this.tools.slice(0) : [];
8418 if(!this.hideCollapseTool){
8419 this.tools[this.collapseFirst?'unshift':'push']({
8421 handler : this.toggleCollapse,
8425 if(this.titleCollapse && this.header){
8426 this.mon(this.header, 'click', this.toggleCollapse, this);
8427 this.header.setStyle('cursor', 'pointer');
8431 var ts = this.tools;
8433 this.addTool.apply(this, ts);
8438 if(this.buttons && this.buttons.length > 0){
8439 this.fbar = new Ext.Toolbar({
8440 items: this.buttons,
8441 toolbarCls: 'x-panel-fbar'
8446 this.fbar = Ext.create(this.fbar, 'toolbar');
8447 this.fbar.enableOverflow = false;
8448 if(this.fbar.items){
8449 this.fbar.items.each(function(c){
8450 c.minWidth = c.minWidth || this.minButtonWidth;
8453 this.fbar.toolbarCls = 'x-panel-fbar';
8455 var bct = this.footer.createChild({cls: 'x-panel-btns x-panel-btns-'+this.buttonAlign});
8456 this.fbar.ownerCt = this;
8457 this.fbar.render(bct);
8458 bct.createChild({cls:'x-clear'});
8459 this.toolbars.push(this.fbar);
8462 if(this.tbar && this.topToolbar){
8463 if(Ext.isArray(this.topToolbar)){
8464 this.topToolbar = new Ext.Toolbar(this.topToolbar);
8465 }else if(!this.topToolbar.events){
8466 this.topToolbar = Ext.create(this.topToolbar, 'toolbar');
8468 this.topToolbar.ownerCt = this;
8469 this.topToolbar.render(this.tbar);
8470 this.toolbars.push(this.topToolbar);
8472 if(this.bbar && this.bottomToolbar){
8473 if(Ext.isArray(this.bottomToolbar)){
8474 this.bottomToolbar = new Ext.Toolbar(this.bottomToolbar);
8475 }else if(!this.bottomToolbar.events){
8476 this.bottomToolbar = Ext.create(this.bottomToolbar, 'toolbar');
8478 this.bottomToolbar.ownerCt = this;
8479 this.bottomToolbar.render(this.bbar);
8480 this.toolbars.push(this.bottomToolbar);
8482 Ext.each(this.toolbars, function(tb){
8485 afterlayout: this.syncHeight,
8486 remove: this.syncHeight
8492 * Sets the CSS class that provides the icon image for this panel. This method will replace any existing
8493 * icon class if one has already been set and fire the {@link #iconchange} event after completion.
8494 * @param {String} cls The new CSS class name
8496 setIconClass : function(cls){
8497 var old = this.iconCls;
8499 if(this.rendered && this.header){
8501 this.header.addClass('x-panel-icon');
8502 this.header.replaceClass(old, this.iconCls);
8504 var hd = this.header.dom;
8505 var img = hd.firstChild && String(hd.firstChild.tagName).toLowerCase() == 'img' ? hd.firstChild : null;
8507 Ext.fly(img).replaceClass(old, this.iconCls);
8509 Ext.DomHelper.insertBefore(hd.firstChild, {
8510 tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
8515 this.fireEvent('iconchange', this, cls, old);
8519 makeFloating : function(cfg){
8520 this.floating = true;
8521 this.el = new Ext.Layer(
8522 Ext.isObject(cfg) ? cfg : {
8523 shadow: this.shadow !== undefined ? this.shadow : 'sides',
8524 shadowOffset: this.shadowOffset,
8526 shim: this.shim === false ? false : undefined
8532 * Returns the {@link Ext.Toolbar toolbar} from the top (<tt>{@link #tbar}</tt>) section of the panel.
8533 * @return {Ext.Toolbar} The toolbar
8535 getTopToolbar : function(){
8536 return this.topToolbar;
8540 * Returns the {@link Ext.Toolbar toolbar} from the bottom (<tt>{@link #bbar}</tt>) section of the panel.
8541 * @return {Ext.Toolbar} The toolbar
8543 getBottomToolbar : function(){
8544 return this.bottomToolbar;
8548 * Adds a button to this panel. Note that this method must be called prior to rendering. The preferred
8549 * approach is to add buttons via the {@link #buttons} config.
8550 * @param {String/Object} config A valid {@link Ext.Button} config. A string will become the text for a default
8551 * button config, an object will be treated as a button config object.
8552 * @param {Function} handler The function to be called on button {@link Ext.Button#click}
8553 * @param {Object} scope The scope to use for the button handler function
8554 * @return {Ext.Button} The button that was added
8556 addButton : function(config, handler, scope){
8560 minWidth: this.minButtonWidth,
8563 if(typeof config == "string"){
8566 Ext.apply(bc, config);
8568 var btn = new Ext.Button(bc);
8572 this.buttons.push(btn);
8577 addTool : function(){
8578 if(!this[this.toolTarget]) { // no where to render tools!
8581 if(!this.toolTemplate){
8582 // initialize the global tool template on first use
8583 var tt = new Ext.Template(
8584 '<div class="x-tool x-tool-{id}"> </div>'
8586 tt.disableFormats = true;
8588 Ext.Panel.prototype.toolTemplate = tt;
8590 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
8592 if(!this.tools[tc.id]){
8593 var overCls = 'x-tool-'+tc.id+'-over';
8594 var t = this.toolTemplate.insertFirst((tc.align !== 'left') ? this[this.toolTarget] : this[this.toolTarget].child('span'), tc, true);
8595 this.tools[tc.id] = t;
8596 t.enableDisplayMode('block');
8597 this.mon(t, 'click', this.createToolHandler(t, tc, overCls, this));
8605 if(Ext.isObject(tc.qtip)){
8606 Ext.QuickTips.register(Ext.apply({
8610 t.dom.qtip = tc.qtip;
8613 t.addClassOnOver(overCls);
8618 onLayout : function(){
8619 if(this.toolbars.length > 0){
8620 this.duringLayout = true;
8621 Ext.each(this.toolbars, function(tb){
8624 delete this.duringLayout;
8629 syncHeight : function(){
8630 if(!(this.autoHeight || this.duringLayout)){
8631 var last = this.lastSize;
8632 if(last && !Ext.isEmpty(last.height)){
8633 var old = last.height, h = this.el.getHeight();
8634 if(old != 'auto' && old != h){
8635 var bd = this.body, bdh = bd.getHeight();
8636 h = Math.max(bdh + old - h, 0);
8637 if(bdh > 0 && bdh != h){
8639 if(Ext.isIE && h <= 0){
8642 var sz = bd.getSize();
8643 this.fireEvent('bodyresize', sz.width, sz.height);
8651 onShow : function(){
8653 return this.el.show();
8655 Ext.Panel.superclass.onShow.call(this);
8659 onHide : function(){
8661 return this.el.hide();
8663 Ext.Panel.superclass.onHide.call(this);
8667 createToolHandler : function(t, tc, overCls, panel){
8669 t.removeClass(overCls);
8670 if(tc.stopEvent !== false){
8674 tc.handler.call(tc.scope || t, e, t, panel, tc);
8680 afterRender : function(){
8681 if(this.floating && !this.hidden){
8685 this.setTitle(this.title);
8687 this.setAutoScroll();
8689 this.body.update(Ext.isObject(this.html) ?
8690 Ext.DomHelper.markup(this.html) :
8695 var ce = Ext.getDom(this.contentEl);
8696 Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
8697 this.body.dom.appendChild(ce);
8700 this.collapsed = false;
8701 this.collapse(false);
8703 Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
8708 setAutoScroll : function(){
8709 if(this.rendered && this.autoScroll){
8710 var el = this.body || this.el;
8712 el.setOverflow('auto');
8718 getKeyMap : function(){
8720 this.keyMap = new Ext.KeyMap(this.el, this.keys);
8726 initEvents : function(){
8731 this.initDraggable();
8736 initDraggable : function(){
8738 * <p>If this Panel is configured {@link #draggable}, this property will contain
8739 * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.</p>
8740 * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource}
8741 * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
8742 * @type Ext.dd.DragSource.
8745 this.dd = new Ext.Panel.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
8749 beforeEffect : function(){
8751 this.el.beforeAction();
8753 this.el.addClass('x-panel-animated');
8757 afterEffect : function(){
8759 this.el.removeClass('x-panel-animated');
8762 // private - wraps up an animation param with internal callbacks
8763 createEffect : function(a, cb, scope){
8771 }else if(!a.callback){
8773 }else { // wrap it up
8774 o.callback = function(){
8776 Ext.callback(a.callback, a.scope);
8779 return Ext.applyIf(o, a);
8783 * Collapses the panel body so that it becomes hidden. Fires the {@link #beforecollapse} event which will
8784 * cancel the collapse action if it returns false.
8785 * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
8786 * {@link #animCollapse} panel config)
8787 * @return {Ext.Panel} this
8789 collapse : function(animate){
8790 if(this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforecollapse', this, animate) === false){
8793 var doAnim = animate === true || (animate !== false && this.animCollapse);
8794 this.beforeEffect();
8795 this.onCollapse(doAnim, animate);
8800 onCollapse : function(doAnim, animArg){
8802 this[this.collapseEl].slideOut(this.slideAnchor,
8803 Ext.apply(this.createEffect(animArg||true, this.afterCollapse, this),
8804 this.collapseDefaults));
8806 this[this.collapseEl].hide();
8807 this.afterCollapse();
8812 afterCollapse : function(){
8813 this.collapsed = true;
8814 this.el.addClass(this.collapsedCls);
8816 this.fireEvent('collapse', this);
8820 * Expands the panel body so that it becomes visible. Fires the {@link #beforeexpand} event which will
8821 * cancel the expand action if it returns false.
8822 * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
8823 * {@link #animCollapse} panel config)
8824 * @return {Ext.Panel} this
8826 expand : function(animate){
8827 if(!this.collapsed || this.el.hasFxBlock() || this.fireEvent('beforeexpand', this, animate) === false){
8830 var doAnim = animate === true || (animate !== false && this.animCollapse);
8831 this.el.removeClass(this.collapsedCls);
8832 this.beforeEffect();
8833 this.onExpand(doAnim, animate);
8838 onExpand : function(doAnim, animArg){
8840 this[this.collapseEl].slideIn(this.slideAnchor,
8841 Ext.apply(this.createEffect(animArg||true, this.afterExpand, this),
8842 this.expandDefaults));
8844 this[this.collapseEl].show();
8850 afterExpand : function(){
8851 this.collapsed = false;
8853 if(this.deferLayout !== undefined){
8854 this.doLayout(true);
8856 this.fireEvent('expand', this);
8860 * Shortcut for performing an {@link #expand} or {@link #collapse} based on the current state of the panel.
8861 * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
8862 * {@link #animCollapse} panel config)
8863 * @return {Ext.Panel} this
8865 toggleCollapse : function(animate){
8866 this[this.collapsed ? 'expand' : 'collapse'](animate);
8871 onDisable : function(){
8872 if(this.rendered && this.maskDisabled){
8875 Ext.Panel.superclass.onDisable.call(this);
8879 onEnable : function(){
8880 if(this.rendered && this.maskDisabled){
8883 Ext.Panel.superclass.onEnable.call(this);
8887 onResize : function(w, h){
8888 if(w !== undefined || h !== undefined){
8889 if(!this.collapsed){
8890 if(typeof w == 'number'){
8891 w = this.adjustBodyWidth(w - this.getFrameWidth());
8893 this.tbar.setWidth(w);
8894 if(this.topToolbar){
8895 this.topToolbar.setSize(w);
8899 this.bbar.setWidth(w);
8900 if(this.bottomToolbar){
8901 this.bottomToolbar.setSize(w);
8907 strict = Ext.isStrict;
8908 if(this.buttonAlign == 'left'){
8909 fWidth = w - f.container.getFrameWidth('lr');
8911 //center/right alignment off in webkit
8912 if(Ext.isIE || Ext.isWebKit){
8913 //center alignment ok on webkit.
8914 //right broken in both, center on IE
8915 if(!(this.buttonAlign == 'center' && Ext.isWebKit) && (!strict || (!Ext.isIE8 && strict))){
8917 f.setWidth(f.getEl().child('.x-toolbar-ct').getWidth());
8928 this.body.setWidth(w);
8929 }else if(w == 'auto'){
8930 this.body.setWidth(w);
8933 if(typeof h == 'number'){
8934 h = Math.max(0, this.adjustBodyHeight(h - this.getFrameHeight()));
8935 this.body.setHeight(h);
8936 }else if(h == 'auto'){
8937 this.body.setHeight(h);
8940 if(this.disabled && this.el._mask){
8941 this.el._mask.setSize(this.el.dom.clientWidth, this.el.getHeight());
8944 this.queuedBodySize = {width: w, height: h};
8945 if(!this.queuedExpand && this.allowQueuedExpand !== false){
8946 this.queuedExpand = true;
8947 this.on('expand', function(){
8948 delete this.queuedExpand;
8949 this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
8951 }, this, {single:true});
8954 this.fireEvent('bodyresize', this, w, h);
8960 adjustBodyHeight : function(h){
8965 adjustBodyWidth : function(w){
8970 onPosition : function(){
8975 * Returns the width in pixels of the framing elements of this panel (not including the body width). To
8976 * retrieve the body width see {@link #getInnerWidth}.
8977 * @return {Number} The frame width
8979 getFrameWidth : function(){
8980 var w = this.el.getFrameWidth('lr')+this.bwrap.getFrameWidth('lr');
8983 var l = this.bwrap.dom.firstChild;
8984 w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
8985 var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
8986 w += Ext.fly(mc).getFrameWidth('lr');
8992 * Returns the height in pixels of the framing elements of this panel (including any top and bottom bars and
8993 * header and footer elements, but not including the body height). To retrieve the body height see {@link #getInnerHeight}.
8994 * @return {Number} The frame height
8996 getFrameHeight : function(){
8997 var h = this.el.getFrameWidth('tb')+this.bwrap.getFrameWidth('tb');
8998 h += (this.tbar ? this.tbar.getHeight() : 0) +
8999 (this.bbar ? this.bbar.getHeight() : 0);
9002 var hd = this.el.dom.firstChild;
9003 var ft = this.bwrap.dom.lastChild;
9004 h += (hd.offsetHeight + ft.offsetHeight);
9005 var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
9006 h += Ext.fly(mc).getFrameWidth('tb');
9008 h += (this.header ? this.header.getHeight() : 0) +
9009 (this.footer ? this.footer.getHeight() : 0);
9015 * Returns the width in pixels of the body element (not including the width of any framing elements).
9016 * For the frame width see {@link #getFrameWidth}.
9017 * @return {Number} The body width
9019 getInnerWidth : function(){
9020 return this.getSize().width - this.getFrameWidth();
9024 * Returns the height in pixels of the body element (not including the height of any framing elements).
9025 * For the frame height see {@link #getFrameHeight}.
9026 * @return {Number} The body height
9028 getInnerHeight : function(){
9029 return this.getSize().height - this.getFrameHeight();
9033 syncShadow : function(){
9040 getLayoutTarget : function(){
9045 * <p>Sets the title text for the panel and optionally the {@link #iconCls icon class}.</p>
9046 * <p>In order to be able to set the title, a header element must have been created
9047 * for the Panel. This is triggered either by configuring the Panel with a non-blank <tt>{@link #title}</tt>,
9048 * or configuring it with <tt><b>{@link #header}: true</b></tt>.</p>
9049 * @param {String} title The title text to set
9050 * @param {String} iconCls (optional) {@link #iconCls iconCls} A user-defined CSS class that provides the icon image for this panel
9052 setTitle : function(title, iconCls){
9054 if(this.header && this.headerAsText){
9055 this.header.child('span').update(title);
9058 this.setIconClass(iconCls);
9060 this.fireEvent('titlechange', this, title);
9065 * Get the {@link Ext.Updater} for this panel. Enables you to perform Ajax updates of this panel's body.
9066 * @return {Ext.Updater} The Updater
9068 getUpdater : function(){
9069 return this.body.getUpdater();
9073 * Loads this content panel immediately with content returned from an XHR call.
9074 * @param {Object/String/Function} config A config object containing any of the following options:
9077 url: "your-url.php",
9078 params: {param1: "foo", param2: "bar"}, // or a URL encoded string
9079 callback: yourFunction,
9080 scope: yourObject, // optional scope for the callback
9088 * The only required property is url. The optional properties nocache, text and scripts
9089 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their
9090 * associated property on this panel Updater instance.
9091 * @return {Ext.Panel} this
9094 var um = this.body.getUpdater();
9095 um.update.apply(um, arguments);
9100 beforeDestroy : function(){
9102 this.header.removeAllListeners();
9103 if(this.headerAsText){
9104 Ext.Element.uncache(this.header.child('span'));
9107 Ext.Element.uncache(
9116 for(var k in this.tools){
9117 Ext.destroy(this.tools[k]);
9121 for(var b in this.buttons){
9122 Ext.destroy(this.buttons[b]);
9125 Ext.destroy(this.toolbars);
9126 Ext.Panel.superclass.beforeDestroy.call(this);
9130 createClasses : function(){
9131 this.headerCls = this.baseCls + '-header';
9132 this.headerTextCls = this.baseCls + '-header-text';
9133 this.bwrapCls = this.baseCls + '-bwrap';
9134 this.tbarCls = this.baseCls + '-tbar';
9135 this.bodyCls = this.baseCls + '-body';
9136 this.bbarCls = this.baseCls + '-bbar';
9137 this.footerCls = this.baseCls + '-footer';
9141 createGhost : function(cls, useShim, appendTo){
9142 var el = document.createElement('div');
9143 el.className = 'x-panel-ghost ' + (cls ? cls : '');
9145 el.appendChild(this.el.dom.firstChild.cloneNode(true));
9147 Ext.fly(el.appendChild(document.createElement('ul'))).setHeight(this.bwrap.getHeight());
9148 el.style.width = this.el.dom.offsetWidth + 'px';;
9150 this.container.dom.appendChild(el);
9152 Ext.getDom(appendTo).appendChild(el);
9154 if(useShim !== false && this.el.useShim !== false){
9155 var layer = new Ext.Layer({shadow:false, useDisplay:true, constrain:false}, el);
9159 return new Ext.Element(el);
9164 doAutoLoad : function(){
9165 var u = this.body.getUpdater();
9167 u.setRenderer(this.renderer);
9169 u.update(Ext.isObject(this.autoLoad) ? this.autoLoad : {url: this.autoLoad});
9173 * Retrieve a tool by id.
9174 * @param {String} id
9175 * @return {Object} tool
9177 getTool : function(id) {
9178 return this.tools[id];
9182 * @cfg {String} autoEl @hide
9185 Ext.reg('panel', Ext.Panel);
9188 * @extends Ext.Component
9189 * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
9191 * Create a new Editor
9192 * @param {Object} config The config object
9195 Ext.Editor = function(field, config){
9197 this.field = Ext.create(field.field, 'textfield');
9198 config = Ext.apply({}, field); // copy so we don't disturb original config
9199 delete config.field;
9203 Ext.Editor.superclass.constructor.call(this, config);
9206 Ext.extend(Ext.Editor, Ext.Component, {
9208 * @cfg {Ext.form.Field} field
9209 * The Field object (or descendant) or config object for field
9212 * @cfg {Boolean} allowBlur
9213 * True to {@link #completeEdit complete the editing process} if in edit mode when the
9214 * field is blurred. Defaults to <tt>false</tt>.
9217 * @cfg {Boolean/String} autoSize
9218 * True for the editor to automatically adopt the size of the element being edited, "width" to adopt the width only,
9219 * or "height" to adopt the height only (defaults to false)
9222 * @cfg {Boolean} revertInvalid
9223 * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
9224 * validation fails (defaults to true)
9227 * @cfg {Boolean} ignoreNoChange
9228 * True to skip the edit completion process (no save, no events fired) if the user completes an edit and
9229 * the value has not changed (defaults to false). Applies only to string values - edits for other data types
9230 * will never be ignored.
9233 * @cfg {Boolean} hideEl
9234 * False to keep the bound element visible while the editor is displayed (defaults to true)
9237 * @cfg {Mixed} value
9238 * The data value of the underlying field (defaults to "")
9242 * @cfg {String} alignment
9243 * The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?").
9247 * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
9248 * for bottom-right shadow (defaults to "frame")
9252 * @cfg {Boolean} constrain True to constrain the editor to the viewport
9256 * @cfg {Boolean} swallowKeys Handle the keydown/keypress events so they don't propagate (defaults to true)
9260 * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed (defaults to false)
9262 completeOnEnter : false,
9264 * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed (defaults to false)
9266 cancelOnEsc : false,
9268 * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
9272 initComponent : function(){
9273 Ext.Editor.superclass.initComponent.call(this);
9276 * @event beforestartedit
9277 * Fires when editing is initiated, but before the value changes. Editing can be canceled by returning
9278 * false from the handler of this event.
9279 * @param {Editor} this
9280 * @param {Ext.Element} boundEl The underlying element bound to this editor
9281 * @param {Mixed} value The field value being set
9286 * Fires when this editor is displayed
9287 * @param {Ext.Element} boundEl The underlying element bound to this editor
9288 * @param {Mixed} value The starting field value
9292 * @event beforecomplete
9293 * Fires after a change has been made to the field, but before the change is reflected in the underlying
9294 * field. Saving the change to the field can be canceled by returning false from the handler of this event.
9295 * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
9296 * event will not fire since no edit actually occurred.
9297 * @param {Editor} this
9298 * @param {Mixed} value The current field value
9299 * @param {Mixed} startValue The original field value
9304 * Fires after editing is complete and any changed value has been written to the underlying field.
9305 * @param {Editor} this
9306 * @param {Mixed} value The current field value
9307 * @param {Mixed} startValue The original field value
9312 * Fires after editing has been canceled and the editor's value has been reset.
9313 * @param {Editor} this
9314 * @param {Mixed} value The user-entered field value that was discarded
9315 * @param {Mixed} startValue The original field value that was set back into the editor after cancel
9320 * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed. You can check
9321 * {@link Ext.EventObject#getKey} to determine which key was pressed.
9322 * @param {Ext.form.Field} this
9323 * @param {Ext.EventObject} e The event object
9330 onRender : function(ct, position){
9331 this.el = new Ext.Layer({
9332 shadow: this.shadow,
9336 shadowOffset: this.shadowOffset || 4,
9338 constrain: this.constrain
9341 this.el.setZIndex(this.zIndex);
9343 this.el.setStyle("overflow", Ext.isGecko ? "auto" : "hidden");
9344 if(this.field.msgTarget != 'title'){
9345 this.field.msgTarget = 'qtip';
9347 this.field.inEditor = true;
9348 this.field.render(this.el);
9350 this.field.el.dom.setAttribute('autocomplete', 'off');
9352 this.mon(this.field, "specialkey", this.onSpecialKey, this);
9353 if(this.swallowKeys){
9354 this.field.el.swallowEvent(['keydown','keypress']);
9357 this.mon(this.field, "blur", this.onBlur, this);
9358 if(this.field.grow){
9359 this.mon(this.field, "autosize", this.el.sync, this.el, {delay:1});
9364 onSpecialKey : function(field, e){
9365 var key = e.getKey();
9366 if(this.completeOnEnter && key == e.ENTER){
9368 this.completeEdit();
9369 }else if(this.cancelOnEsc && key == e.ESC){
9372 this.fireEvent('specialkey', field, e);
9374 if(this.field.triggerBlur && (key == e.ENTER || key == e.ESC || key == e.TAB)){
9375 this.field.triggerBlur();
9380 * Starts the editing process and shows the editor.
9381 * @param {Mixed} el The element to edit
9382 * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
9383 * to the innerHTML of el.
9385 startEdit : function(el, value){
9387 this.completeEdit();
9389 this.boundEl = Ext.get(el);
9390 var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
9392 this.render(this.parentEl || document.body);
9394 if(this.fireEvent("beforestartedit", this, this.boundEl, v) === false){
9397 this.startValue = v;
9398 this.field.setValue(v);
9400 this.el.alignTo(this.boundEl, this.alignment);
9401 this.editing = true;
9406 doAutoSize : function(){
9408 var sz = this.boundEl.getSize();
9409 switch(this.autoSize){
9411 this.setSize(sz.width, "");
9414 this.setSize("", sz.height);
9417 this.setSize(sz.width, sz.height);
9423 * Sets the height and width of this editor.
9424 * @param {Number} width The new width
9425 * @param {Number} height The new height
9427 setSize : function(w, h){
9428 delete this.field.lastSize;
9429 this.field.setSize(w, h);
9431 if(Ext.isGecko2 || Ext.isOpera){
9432 // prevent layer scrollbars
9433 this.el.setSize(w, h);
9440 * Realigns the editor to the bound field based on the current alignment config value.
9442 realign : function(){
9443 this.el.alignTo(this.boundEl, this.alignment);
9447 * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
9448 * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
9450 completeEdit : function(remainVisible){
9454 var v = this.getValue();
9455 if(!this.field.isValid()){
9456 if(this.revertInvalid !== false){
9457 this.cancelEdit(remainVisible);
9461 if(String(v) === String(this.startValue) && this.ignoreNoChange){
9462 this.hideEdit(remainVisible);
9465 if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
9466 v = this.getValue();
9467 if(this.updateEl && this.boundEl){
9468 this.boundEl.update(v);
9470 this.hideEdit(remainVisible);
9471 this.fireEvent("complete", this, v, this.startValue);
9476 onShow : function(){
9478 if(this.hideEl !== false){
9479 this.boundEl.hide();
9482 if(Ext.isIE && !this.fixIEFocus){ // IE has problems with focusing the first time
9483 this.fixIEFocus = true;
9484 this.deferredFocus.defer(50, this);
9488 this.fireEvent("startedit", this.boundEl, this.startValue);
9491 deferredFocus : function(){
9498 * Cancels the editing process and hides the editor without persisting any changes. The field value will be
9499 * reverted to the original starting value.
9500 * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
9501 * cancel (defaults to false)
9503 cancelEdit : function(remainVisible){
9505 var v = this.getValue();
9506 this.setValue(this.startValue);
9507 this.hideEdit(remainVisible);
9508 this.fireEvent("canceledit", this, v, this.startValue);
9513 hideEdit: function(remainVisible){
9514 if(remainVisible !== true){
9515 this.editing = false;
9521 onBlur : function(){
9522 if(this.allowBlur !== true && this.editing){
9523 this.completeEdit();
9528 onHide : function(){
9530 this.completeEdit();
9534 if(this.field.collapse){
9535 this.field.collapse();
9538 if(this.hideEl !== false){
9539 this.boundEl.show();
9544 * Sets the data value of the editor
9545 * @param {Mixed} value Any valid value supported by the underlying field
9547 setValue : function(v){
9548 this.field.setValue(v);
9552 * Gets the data value of the editor
9553 * @return {Mixed} The data value
9555 getValue : function(){
9556 return this.field.getValue();
9559 beforeDestroy : function(){
9560 Ext.destroy(this.field);
9564 Ext.reg('editor', Ext.Editor);/**
9565 * @class Ext.ColorPalette
9566 * @extends Ext.Component
9567 * Simple color palette class for choosing colors. The palette can be rendered to any container.<br />
9568 * Here's an example of typical usage:
9570 var cp = new Ext.ColorPalette({value:'993300'}); // initial selected color
9571 cp.render('my-div');
9573 cp.on('select', function(palette, selColor){
9574 // do something with selColor
9578 * Create a new ColorPalette
9579 * @param {Object} config The config object
9580 * @xtype colorpalette
9582 Ext.ColorPalette = function(config){
9583 Ext.ColorPalette.superclass.constructor.call(this, config);
9587 * Fires when a color is selected
9588 * @param {ColorPalette} this
9589 * @param {String} color The 6-digit color hex code (without the # symbol)
9595 this.on("select", this.handler, this.scope, true);
9598 Ext.extend(Ext.ColorPalette, Ext.Component, {
9600 * @cfg {String} tpl An existing XTemplate instance to be used in place of the default template for rendering the component.
9603 * @cfg {String} itemCls
9604 * The CSS class to apply to the containing element (defaults to "x-color-palette")
9606 itemCls : "x-color-palette",
9608 * @cfg {String} value
9609 * The initial color to highlight (should be a valid 6-digit color hex code without the # symbol). Note that
9610 * the hex codes are case-sensitive.
9615 ctype: "Ext.ColorPalette",
9618 * @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the {@link #select} event
9620 allowReselect : false,
9623 * <p>An array of 6-digit color hex code strings (without the # symbol). This array can contain any number
9624 * of colors, and each hex code should be unique. The width of the palette is controlled via CSS by adjusting
9625 * the width property of the 'x-color-palette' class (or assigning a custom class), so you can balance the number
9626 * of colors with the width setting until the box is symmetrical.</p>
9627 * <p>You can override individual colors if needed:</p>
9629 var cp = new Ext.ColorPalette();
9630 cp.colors[0] = "FF0000"; // change the first box to red
9633 Or you can provide a custom array of your own for complete control:
9635 var cp = new Ext.ColorPalette();
9636 cp.colors = ["000000", "993300", "333300"];
9641 "000000", "993300", "333300", "003300", "003366", "000080", "333399", "333333",
9642 "800000", "FF6600", "808000", "008000", "008080", "0000FF", "666699", "808080",
9643 "FF0000", "FF9900", "99CC00", "339966", "33CCCC", "3366FF", "800080", "969696",
9644 "FF00FF", "FFCC00", "FFFF00", "00FF00", "00FFFF", "00CCFF", "993366", "C0C0C0",
9645 "FF99CC", "FFCC99", "FFFF99", "CCFFCC", "CCFFFF", "99CCFF", "CC99FF", "FFFFFF"
9649 onRender : function(container, position){
9650 var t = this.tpl || new Ext.XTemplate(
9651 '<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on"> </span></em></a></tpl>'
9653 var el = document.createElement("div");
9654 el.id = this.getId();
9655 el.className = this.itemCls;
9656 t.overwrite(el, this.colors);
9657 container.dom.insertBefore(el, position);
9658 this.el = Ext.get(el);
9659 this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
9660 if(this.clickEvent != 'click'){
9661 this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
9666 afterRender : function(){
9667 Ext.ColorPalette.superclass.afterRender.call(this);
9676 handleClick : function(e, t){
9679 var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
9680 this.select(c.toUpperCase());
9685 * Selects the specified color in the palette (fires the {@link #select} event)
9686 * @param {String} color A valid 6-digit color hex code (# will be stripped if included)
9688 select : function(color){
9689 color = color.replace("#", "");
9690 if(color != this.value || this.allowReselect){
9693 el.child("a.color-"+this.value).removeClass("x-color-palette-sel");
9695 el.child("a.color-"+color).addClass("x-color-palette-sel");
9697 this.fireEvent("select", this, color);
9702 * @cfg {String} autoEl @hide
9705 Ext.reg('colorpalette', Ext.ColorPalette);/**
\r
9706 * @class Ext.DatePicker
\r
9707 * @extends Ext.Component
\r
9708 * Simple date picker class.
\r
9710 * Create a new DatePicker
\r
9711 * @param {Object} config The config object
\r
9712 * @xtype datepicker
\r
9714 Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
\r
9716 * @cfg {String} todayText
\r
9717 * The text to display on the button that selects the current date (defaults to <tt>'Today'</tt>)
\r
9719 todayText : 'Today',
\r
9721 * @cfg {String} okText
\r
9722 * The text to display on the ok button (defaults to <tt>' OK '</tt> to give the user extra clicking room)
\r
9724 okText : ' OK ',
\r
9726 * @cfg {String} cancelText
\r
9727 * The text to display on the cancel button (defaults to <tt>'Cancel'</tt>)
\r
9729 cancelText : 'Cancel',
\r
9731 * @cfg {String} todayTip
\r
9732 * The tooltip to display for the button that selects the current date (defaults to <tt>'{current date} (Spacebar)'</tt>)
\r
9734 todayTip : '{0} (Spacebar)',
\r
9736 * @cfg {String} minText
\r
9737 * The error text to display if the minDate validation fails (defaults to <tt>'This date is before the minimum date'</tt>)
\r
9739 minText : 'This date is before the minimum date',
\r
9741 * @cfg {String} maxText
\r
9742 * The error text to display if the maxDate validation fails (defaults to <tt>'This date is after the maximum date'</tt>)
\r
9744 maxText : 'This date is after the maximum date',
\r
9746 * @cfg {String} format
\r
9747 * The default date format string which can be overriden for localization support. The format must be
\r
9748 * valid according to {@link Date#parseDate} (defaults to <tt>'m/d/y'</tt>).
\r
9752 * @cfg {String} disabledDaysText
\r
9753 * The tooltip to display when the date falls on a disabled day (defaults to <tt>'Disabled'</tt>)
\r
9755 disabledDaysText : 'Disabled',
\r
9757 * @cfg {String} disabledDatesText
\r
9758 * The tooltip text to display when the date falls on a disabled date (defaults to <tt>'Disabled'</tt>)
\r
9760 disabledDatesText : 'Disabled',
\r
9762 * @cfg {Array} monthNames
\r
9763 * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
\r
9765 monthNames : Date.monthNames,
\r
9767 * @cfg {Array} dayNames
\r
9768 * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
\r
9770 dayNames : Date.dayNames,
\r
9772 * @cfg {String} nextText
\r
9773 * The next month navigation button tooltip (defaults to <tt>'Next Month (Control+Right)'</tt>)
\r
9775 nextText : 'Next Month (Control+Right)',
\r
9777 * @cfg {String} prevText
\r
9778 * The previous month navigation button tooltip (defaults to <tt>'Previous Month (Control+Left)'</tt>)
\r
9780 prevText : 'Previous Month (Control+Left)',
\r
9782 * @cfg {String} monthYearText
\r
9783 * The header month selector tooltip (defaults to <tt>'Choose a month (Control+Up/Down to move years)'</tt>)
\r
9785 monthYearText : 'Choose a month (Control+Up/Down to move years)',
\r
9787 * @cfg {Number} startDay
\r
9788 * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
\r
9792 * @cfg {Boolean} showToday
\r
9793 * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar
\r
9794 * that selects the current date (defaults to <tt>true</tt>).
\r
9798 * @cfg {Date} minDate
\r
9799 * Minimum allowable date (JavaScript date object, defaults to null)
\r
9802 * @cfg {Date} maxDate
\r
9803 * Maximum allowable date (JavaScript date object, defaults to null)
\r
9806 * @cfg {Array} disabledDays
\r
9807 * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
\r
9810 * @cfg {RegExp} disabledDatesRE
\r
9811 * JavaScript regular expression used to disable a pattern of dates (defaults to null). The {@link #disabledDates}
\r
9812 * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the
\r
9813 * disabledDates value.
\r
9816 * @cfg {Array} disabledDates
\r
9817 * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular
\r
9818 * expression so they are very powerful. Some examples:
\r
9820 * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>
\r
9821 * <li>['03/08', '09/16'] would disable those days for every year</li>
\r
9822 * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>
\r
9823 * <li>['03/../2006'] would disable every day in March 2006</li>
\r
9824 * <li>['^03'] would disable every day in every March</li>
\r
9826 * Note that the format of the dates included in the array should exactly match the {@link #format} config.
\r
9827 * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to
\r
9828 * escape the dot when restricting dates. For example: ['03\\.08\\.03'].
\r
9832 initComponent : function(){
\r
9833 Ext.DatePicker.superclass.initComponent.call(this);
\r
9835 this.value = this.value ?
\r
9836 this.value.clearTime() : new Date().clearTime();
\r
9841 * Fires when a date is selected
\r
9842 * @param {DatePicker} this
\r
9843 * @param {Date} date The selected date
\r
9849 this.on('select', this.handler, this.scope || this);
\r
9852 this.initDisabledDays();
\r
9856 initDisabledDays : function(){
\r
9857 if(!this.disabledDatesRE && this.disabledDates){
\r
9858 var dd = this.disabledDates,
\r
9859 len = dd.length - 1,
\r
9862 Ext.each(dd, function(d, i){
\r
9863 re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
\r
9868 this.disabledDatesRE = new RegExp(re + ')');
\r
9873 * Replaces any existing disabled dates with new values and refreshes the DatePicker.
\r
9874 * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config
\r
9875 * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.
\r
9877 setDisabledDates : function(dd){
\r
9878 if(Ext.isArray(dd)){
\r
9879 this.disabledDates = dd;
\r
9880 this.disabledDatesRE = null;
\r
9882 this.disabledDatesRE = dd;
\r
9884 this.initDisabledDays();
\r
9885 this.update(this.value, true);
\r
9889 * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.
\r
9890 * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config
\r
9891 * for details on supported values.
\r
9893 setDisabledDays : function(dd){
\r
9894 this.disabledDays = dd;
\r
9895 this.update(this.value, true);
\r
9899 * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
\r
9900 * @param {Date} value The minimum date that can be selected
\r
9902 setMinDate : function(dt){
\r
9903 this.minDate = dt;
\r
9904 this.update(this.value, true);
\r
9908 * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
\r
9909 * @param {Date} value The maximum date that can be selected
\r
9911 setMaxDate : function(dt){
\r
9912 this.maxDate = dt;
\r
9913 this.update(this.value, true);
\r
9917 * Sets the value of the date field
\r
9918 * @param {Date} value The date to set
\r
9920 setValue : function(value){
\r
9921 var old = this.value;
\r
9922 this.value = value.clearTime(true);
\r
9924 this.update(this.value);
\r
9929 * Gets the current selected value of the date field
\r
9930 * @return {Date} The selected date
\r
9932 getValue : function(){
\r
9933 return this.value;
\r
9937 focus : function(){
\r
9939 this.update(this.activeDate);
\r
9944 onEnable: function(initial){
\r
9945 Ext.DatePicker.superclass.onEnable.call(this);
\r
9946 this.doDisabled(false);
\r
9947 this.update(initial ? this.value : this.activeDate);
\r
9949 this.el.repaint();
\r
9955 onDisable: function(){
\r
9956 Ext.DatePicker.superclass.onDisable.call(this);
\r
9957 this.doDisabled(true);
\r
9958 if(Ext.isIE && !Ext.isIE8){
\r
9959 /* Really strange problem in IE6/7, when disabled, have to explicitly
\r
9960 * repaint each of the nodes to get them to display correctly, simply
\r
9961 * calling repaint on the main element doesn't appear to be enough.
\r
9963 Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
\r
9964 Ext.fly(el).repaint();
\r
9970 doDisabled: function(disabled){
\r
9971 this.keyNav.setDisabled(disabled);
\r
9972 this.prevRepeater.setDisabled(disabled);
\r
9973 this.nextRepeater.setDisabled(disabled);
\r
9974 if(this.showToday){
\r
9975 this.todayKeyListener.setDisabled(disabled);
\r
9976 this.todayBtn.setDisabled(disabled);
\r
9981 onRender : function(container, position){
\r
9983 '<table cellspacing="0">',
\r
9984 '<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>',
\r
9985 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
\r
9986 dn = this.dayNames,
\r
9988 for(i = 0; i < 7; i++){
\r
9989 var d = this.startDay+i;
\r
9993 m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
\r
9995 m[m.length] = '</tr></thead><tbody><tr>';
\r
9996 for(i = 0; i < 42; i++) {
\r
9997 if(i % 7 === 0 && i !== 0){
\r
9998 m[m.length] = '</tr><tr>';
\r
10000 m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
\r
10002 m.push('</tr></tbody></table></td></tr>',
\r
10003 this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
\r
10004 '</table><div class="x-date-mp"></div>');
\r
10006 var el = document.createElement('div');
\r
10007 el.className = 'x-date-picker';
\r
10008 el.innerHTML = m.join('');
\r
10010 container.dom.insertBefore(el, position);
\r
10012 this.el = Ext.get(el);
\r
10013 this.eventEl = Ext.get(el.firstChild);
\r
10015 this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
\r
10016 handler: this.showPrevMonth,
\r
10018 preventDefault:true,
\r
10022 this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
\r
10023 handler: this.showNextMonth,
\r
10025 preventDefault:true,
\r
10029 this.monthPicker = this.el.down('div.x-date-mp');
\r
10030 this.monthPicker.enableDisplayMode('block');
\r
10032 this.keyNav = new Ext.KeyNav(this.eventEl, {
\r
10033 'left' : function(e){
\r
10035 this.showPrevMonth();
\r
10037 this.update(this.activeDate.add('d', -1));
\r
10041 'right' : function(e){
\r
10043 this.showNextMonth();
\r
10045 this.update(this.activeDate.add('d', 1));
\r
10049 'up' : function(e){
\r
10051 this.showNextYear();
\r
10053 this.update(this.activeDate.add('d', -7));
\r
10057 'down' : function(e){
\r
10059 this.showPrevYear();
\r
10061 this.update(this.activeDate.add('d', 7));
\r
10065 'pageUp' : function(e){
\r
10066 this.showNextMonth();
\r
10069 'pageDown' : function(e){
\r
10070 this.showPrevMonth();
\r
10073 'enter' : function(e){
\r
10074 e.stopPropagation();
\r
10081 this.el.unselectable();
\r
10083 this.cells = this.el.select('table.x-date-inner tbody td');
\r
10084 this.textNodes = this.el.query('table.x-date-inner tbody span');
\r
10086 this.mbtn = new Ext.Button({
\r
10088 tooltip: this.monthYearText,
\r
10089 renderTo: this.el.child('td.x-date-middle', true)
\r
10091 this.mbtn.el.child('em').addClass('x-btn-arrow');
\r
10093 if(this.showToday){
\r
10094 this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday, this);
\r
10095 var today = (new Date()).dateFormat(this.format);
\r
10096 this.todayBtn = new Ext.Button({
\r
10097 renderTo: this.el.child('td.x-date-bottom', true),
\r
10098 text: String.format(this.todayText, today),
\r
10099 tooltip: String.format(this.todayTip, today),
\r
10100 handler: this.selectToday,
\r
10104 this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
\r
10105 this.mon(this.eventEl, 'click', this.handleDateClick, this, {delegate: 'a.x-date-date'});
\r
10106 this.mon(this.mbtn, 'click', this.showMonthPicker, this);
\r
10107 this.onEnable(true);
\r
10111 createMonthPicker : function(){
\r
10112 if(!this.monthPicker.dom.firstChild){
\r
10113 var buf = ['<table border="0" cellspacing="0">'];
\r
10114 for(var i = 0; i < 6; i++){
\r
10116 '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
\r
10117 '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
\r
10119 '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
\r
10120 '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
\r
10124 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
\r
10126 '</button><button type="button" class="x-date-mp-cancel">',
\r
10128 '</button></td></tr>',
\r
10131 this.monthPicker.update(buf.join(''));
\r
10133 this.mon(this.monthPicker, 'click', this.onMonthClick, this);
\r
10134 this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
\r
10136 this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
\r
10137 this.mpYears = this.monthPicker.select('td.x-date-mp-year');
\r
10139 this.mpMonths.each(function(m, a, i){
\r
10142 m.dom.xmonth = 5 + Math.round(i * 0.5);
\r
10144 m.dom.xmonth = Math.round((i-1) * 0.5);
\r
10151 showMonthPicker : function(){
\r
10152 if(!this.disabled){
\r
10153 this.createMonthPicker();
\r
10154 var size = this.el.getSize();
\r
10155 this.monthPicker.setSize(size);
\r
10156 this.monthPicker.child('table').setSize(size);
\r
10158 this.mpSelMonth = (this.activeDate || this.value).getMonth();
\r
10159 this.updateMPMonth(this.mpSelMonth);
\r
10160 this.mpSelYear = (this.activeDate || this.value).getFullYear();
\r
10161 this.updateMPYear(this.mpSelYear);
\r
10163 this.monthPicker.slideIn('t', {duration:0.2});
\r
10168 updateMPYear : function(y){
\r
10170 var ys = this.mpYears.elements;
\r
10171 for(var i = 1; i <= 10; i++){
\r
10172 var td = ys[i-1], y2;
\r
10174 y2 = y + Math.round(i * 0.5);
\r
10175 td.firstChild.innerHTML = y2;
\r
10178 y2 = y - (5-Math.round(i * 0.5));
\r
10179 td.firstChild.innerHTML = y2;
\r
10182 this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
\r
10187 updateMPMonth : function(sm){
\r
10188 this.mpMonths.each(function(m, a, i){
\r
10189 m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
\r
10194 selectMPMonth : function(m){
\r
10199 onMonthClick : function(e, t){
\r
10201 var el = new Ext.Element(t), pn;
\r
10202 if(el.is('button.x-date-mp-cancel')){
\r
10203 this.hideMonthPicker();
\r
10205 else if(el.is('button.x-date-mp-ok')){
\r
10206 var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
\r
10207 if(d.getMonth() != this.mpSelMonth){
\r
10208 // 'fix' the JS rolling date conversion if needed
\r
10209 d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
\r
10212 this.hideMonthPicker();
\r
10214 else if((pn = el.up('td.x-date-mp-month', 2))){
\r
10215 this.mpMonths.removeClass('x-date-mp-sel');
\r
10216 pn.addClass('x-date-mp-sel');
\r
10217 this.mpSelMonth = pn.dom.xmonth;
\r
10219 else if((pn = el.up('td.x-date-mp-year', 2))){
\r
10220 this.mpYears.removeClass('x-date-mp-sel');
\r
10221 pn.addClass('x-date-mp-sel');
\r
10222 this.mpSelYear = pn.dom.xyear;
\r
10224 else if(el.is('a.x-date-mp-prev')){
\r
10225 this.updateMPYear(this.mpyear-10);
\r
10227 else if(el.is('a.x-date-mp-next')){
\r
10228 this.updateMPYear(this.mpyear+10);
\r
10233 onMonthDblClick : function(e, t){
\r
10235 var el = new Ext.Element(t), pn;
\r
10236 if((pn = el.up('td.x-date-mp-month', 2))){
\r
10237 this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
\r
10238 this.hideMonthPicker();
\r
10240 else if((pn = el.up('td.x-date-mp-year', 2))){
\r
10241 this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
\r
10242 this.hideMonthPicker();
\r
10247 hideMonthPicker : function(disableAnim){
\r
10248 if(this.monthPicker){
\r
10249 if(disableAnim === true){
\r
10250 this.monthPicker.hide();
\r
10252 this.monthPicker.slideOut('t', {duration:0.2});
\r
10258 showPrevMonth : function(e){
\r
10259 this.update(this.activeDate.add('mo', -1));
\r
10263 showNextMonth : function(e){
\r
10264 this.update(this.activeDate.add('mo', 1));
\r
10268 showPrevYear : function(){
\r
10269 this.update(this.activeDate.add('y', -1));
\r
10273 showNextYear : function(){
\r
10274 this.update(this.activeDate.add('y', 1));
\r
10278 handleMouseWheel : function(e){
\r
10280 if(!this.disabled){
\r
10281 var delta = e.getWheelDelta();
\r
10283 this.showPrevMonth();
\r
10284 } else if(delta < 0){
\r
10285 this.showNextMonth();
\r
10291 handleDateClick : function(e, t){
\r
10293 if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
\r
10294 this.setValue(new Date(t.dateValue));
\r
10295 this.fireEvent('select', this, this.value);
\r
10300 selectToday : function(){
\r
10301 if(this.todayBtn && !this.todayBtn.disabled){
\r
10302 this.setValue(new Date().clearTime());
\r
10303 this.fireEvent('select', this, this.value);
\r
10308 update : function(date, forceRefresh){
\r
10309 var vd = this.activeDate, vis = this.isVisible();
\r
10310 this.activeDate = date;
\r
10311 if(!forceRefresh && vd && this.el){
\r
10312 var t = date.getTime();
\r
10313 if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
\r
10314 this.cells.removeClass('x-date-selected');
\r
10315 this.cells.each(function(c){
\r
10316 if(c.dom.firstChild.dateValue == t){
\r
10317 c.addClass('x-date-selected');
\r
10319 Ext.fly(c.dom.firstChild).focus(50);
\r
10327 var days = date.getDaysInMonth();
\r
10328 var firstOfMonth = date.getFirstDateOfMonth();
\r
10329 var startingPos = firstOfMonth.getDay()-this.startDay;
\r
10331 if(startingPos <= this.startDay){
\r
10332 startingPos += 7;
\r
10335 var pm = date.add('mo', -1);
\r
10336 var prevStart = pm.getDaysInMonth()-startingPos;
\r
10338 var cells = this.cells.elements;
\r
10339 var textEls = this.textNodes;
\r
10340 days += startingPos;
\r
10342 // convert everything to numbers so it's fast
\r
10343 var day = 86400000;
\r
10344 var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
\r
10345 var today = new Date().clearTime().getTime();
\r
10346 var sel = date.clearTime().getTime();
\r
10347 var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
\r
10348 var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
\r
10349 var ddMatch = this.disabledDatesRE;
\r
10350 var ddText = this.disabledDatesText;
\r
10351 var ddays = this.disabledDays ? this.disabledDays.join('') : false;
\r
10352 var ddaysText = this.disabledDaysText;
\r
10353 var format = this.format;
\r
10355 if(this.showToday){
\r
10356 var td = new Date().clearTime();
\r
10357 var disable = (td < min || td > max ||
\r
10358 (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
\r
10359 (ddays && ddays.indexOf(td.getDay()) != -1));
\r
10361 if(!this.disabled){
\r
10362 this.todayBtn.setDisabled(disable);
\r
10363 this.todayKeyListener[disable ? 'disable' : 'enable']();
\r
10367 var setCellClass = function(cal, cell){
\r
10369 var t = d.getTime();
\r
10370 cell.firstChild.dateValue = t;
\r
10372 cell.className += ' x-date-today';
\r
10373 cell.title = cal.todayText;
\r
10376 cell.className += ' x-date-selected';
\r
10378 Ext.fly(cell.firstChild).focus(50);
\r
10383 cell.className = ' x-date-disabled';
\r
10384 cell.title = cal.minText;
\r
10388 cell.className = ' x-date-disabled';
\r
10389 cell.title = cal.maxText;
\r
10393 if(ddays.indexOf(d.getDay()) != -1){
\r
10394 cell.title = ddaysText;
\r
10395 cell.className = ' x-date-disabled';
\r
10398 if(ddMatch && format){
\r
10399 var fvalue = d.dateFormat(format);
\r
10400 if(ddMatch.test(fvalue)){
\r
10401 cell.title = ddText.replace('%0', fvalue);
\r
10402 cell.className = ' x-date-disabled';
\r
10408 for(; i < startingPos; i++) {
\r
10409 textEls[i].innerHTML = (++prevStart);
\r
10410 d.setDate(d.getDate()+1);
\r
10411 cells[i].className = 'x-date-prevday';
\r
10412 setCellClass(this, cells[i]);
\r
10414 for(; i < days; i++){
\r
10415 var intDay = i - startingPos + 1;
\r
10416 textEls[i].innerHTML = (intDay);
\r
10417 d.setDate(d.getDate()+1);
\r
10418 cells[i].className = 'x-date-active';
\r
10419 setCellClass(this, cells[i]);
\r
10421 var extraDays = 0;
\r
10422 for(; i < 42; i++) {
\r
10423 textEls[i].innerHTML = (++extraDays);
\r
10424 d.setDate(d.getDate()+1);
\r
10425 cells[i].className = 'x-date-nextday';
\r
10426 setCellClass(this, cells[i]);
\r
10429 this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
\r
10431 if(!this.internalRender){
\r
10432 var main = this.el.dom.firstChild;
\r
10433 var w = main.offsetWidth;
\r
10434 this.el.setWidth(w + this.el.getBorderWidth('lr'));
\r
10435 Ext.fly(main).setWidth(w);
\r
10436 this.internalRender = true;
\r
10437 // opera does not respect the auto grow header center column
\r
10438 // then, after it gets a width opera refuses to recalculate
\r
10439 // without a second pass
\r
10440 if(Ext.isOpera && !this.secondPass){
\r
10441 main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
\r
10442 this.secondPass = true;
\r
10443 this.update.defer(10, this, [date]);
\r
10449 beforeDestroy : function() {
\r
10450 if(this.rendered){
\r
10451 this.keyNav.disable();
\r
10452 this.keyNav = null;
\r
10454 this.leftClickRpt,
\r
10455 this.rightClickRpt,
\r
10456 this.monthPicker,
\r
10465 * @cfg {String} autoEl @hide
\r
10469 Ext.reg('datepicker', Ext.DatePicker);
\r
10471 * @class Ext.LoadMask
10472 * A simple utility class for generically masking elements while loading data. If the {@link #store}
10473 * config option is specified, the masking will be automatically synchronized with the store's loading
10474 * process and the mask element will be cached for reuse. For all other elements, this mask will replace the
10475 * element's Updater load indicator and will be destroyed after the initial load.
10476 * <p>Example usage:</p>
10479 var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
10483 * Create a new LoadMask
10484 * @param {Mixed} el The element or DOM node, or its id
10485 * @param {Object} config The config object
10487 Ext.LoadMask = function(el, config){
10488 this.el = Ext.get(el);
10489 Ext.apply(this, config);
10491 this.store.on('beforeload', this.onBeforeLoad, this);
10492 this.store.on('load', this.onLoad, this);
10493 this.store.on('exception', this.onLoad, this);
10494 this.removeMask = Ext.value(this.removeMask, false);
10496 var um = this.el.getUpdater();
10497 um.showLoadIndicator = false; // disable the default indicator
10498 um.on('beforeupdate', this.onBeforeLoad, this);
10499 um.on('update', this.onLoad, this);
10500 um.on('failure', this.onLoad, this);
10501 this.removeMask = Ext.value(this.removeMask, true);
10505 Ext.LoadMask.prototype = {
10507 * @cfg {Ext.data.Store} store
10508 * Optional Store to which the mask is bound. The mask is displayed when a load request is issued, and
10509 * hidden on either load sucess, or load fail.
10512 * @cfg {Boolean} removeMask
10513 * True to create a single-use mask that is automatically destroyed after loading (useful for page loads),
10514 * False to persist the mask element reference for multiple uses (e.g., for paged data widgets). Defaults to false.
10517 * @cfg {String} msg
10518 * The text to display in a centered loading message box (defaults to 'Loading...')
10520 msg : 'Loading...',
10522 * @cfg {String} msgCls
10523 * The CSS class to apply to the loading message element (defaults to "x-mask-loading")
10525 msgCls : 'x-mask-loading',
10528 * Read-only. True if the mask is currently disabled so that it will not be displayed (defaults to false)
10534 * Disables the mask to prevent it from being displayed
10536 disable : function(){
10537 this.disabled = true;
10541 * Enables the mask so that it can be displayed
10543 enable : function(){
10544 this.disabled = false;
10548 onLoad : function(){
10549 this.el.unmask(this.removeMask);
10553 onBeforeLoad : function(){
10554 if(!this.disabled){
10555 this.el.mask(this.msg, this.msgCls);
10560 * Show this LoadMask over the configured Element.
10563 this.onBeforeLoad();
10567 * Hide this LoadMask.
10574 destroy : function(){
10576 this.store.un('beforeload', this.onBeforeLoad, this);
10577 this.store.un('load', this.onLoad, this);
10578 this.store.un('exception', this.onLoad, this);
10580 var um = this.el.getUpdater();
10581 um.un('beforeupdate', this.onBeforeLoad, this);
10582 um.un('update', this.onLoad, this);
10583 um.un('failure', this.onLoad, this);
10587 * @class Ext.Slider
\r
10588 * @extends Ext.BoxComponent
\r
10589 * Slider which supports vertical or horizontal orientation, keyboard adjustments,
\r
10590 * configurable snapping, axis clicking and animation. Can be added as an item to
\r
10591 * any container. Example usage:
\r
10594 renderTo: Ext.getBody(),
\r
10603 Ext.Slider = Ext.extend(Ext.BoxComponent, {
\r
10605 * @cfg {Number} value The value to initialize the slider with. Defaults to minValue.
\r
10608 * @cfg {Boolean} vertical Orient the Slider vertically rather than horizontally, defaults to false.
\r
10612 * @cfg {Number} minValue The minimum value for the Slider. Defaults to 0.
\r
10616 * @cfg {Number} maxValue The maximum value for the Slider. Defaults to 100.
\r
10620 * @cfg {Number/Boolean} decimalPrecision.
\r
10621 * <p>The number of decimal places to which to round the Slider's value. Defaults to 0.</p>
\r
10622 * <p>To disable rounding, configure as <tt><b>false</b></tt>.</p>
\r
10624 decimalPrecision: 0,
\r
10626 * @cfg {Number} keyIncrement How many units to change the Slider when adjusting with keyboard navigation. Defaults to 1. If the increment config is larger, it will be used instead.
\r
10630 * @cfg {Number} increment How many units to change the slider when adjusting by drag and drop. Use this option to enable 'snapping'.
\r
10634 clickRange: [5,15],
\r
10636 * @cfg {Boolean} clickToChange Determines whether or not clicking on the Slider axis will change the slider. Defaults to true
\r
10638 clickToChange : true,
\r
10640 * @cfg {Boolean} animate Turn on or off animation. Defaults to true
\r
10645 * True while the thumb is in a drag operation
\r
10650 // private override
\r
10651 initComponent : function(){
\r
10652 if(!Ext.isDefined(this.value)){
\r
10653 this.value = this.minValue;
\r
10655 Ext.Slider.superclass.initComponent.call(this);
\r
10656 this.keyIncrement = Math.max(this.increment, this.keyIncrement);
\r
10659 * @event beforechange
\r
10660 * Fires before the slider value is changed. By returning false from an event handler,
\r
10661 * you can cancel the event and prevent the slider from changing.
\r
10662 * @param {Ext.Slider} slider The slider
\r
10663 * @param {Number} newValue The new value which the slider is being changed to.
\r
10664 * @param {Number} oldValue The old value which the slider was previously.
\r
10669 * Fires when the slider value is changed.
\r
10670 * @param {Ext.Slider} slider The slider
\r
10671 * @param {Number} newValue The new value which the slider has been changed to.
\r
10675 * @event changecomplete
\r
10676 * Fires when the slider value is changed by the user and any drag operations have completed.
\r
10677 * @param {Ext.Slider} slider The slider
\r
10678 * @param {Number} newValue The new value which the slider has been changed to.
\r
10680 'changecomplete',
\r
10682 * @event dragstart
\r
10683 * Fires after a drag operation has started.
\r
10684 * @param {Ext.Slider} slider The slider
\r
10685 * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
\r
10690 * Fires continuously during the drag operation while the mouse is moving.
\r
10691 * @param {Ext.Slider} slider The slider
\r
10692 * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
\r
10697 * Fires after the drag operation has completed.
\r
10698 * @param {Ext.Slider} slider The slider
\r
10699 * @param {Ext.EventObject} e The event fired from Ext.dd.DragTracker
\r
10704 if(this.vertical){
\r
10705 Ext.apply(this, Ext.Slider.Vertical);
\r
10709 // private override
\r
10710 onRender : function(){
\r
10712 cls: 'x-slider ' + (this.vertical ? 'x-slider-vert' : 'x-slider-horz'),
\r
10713 cn:{cls:'x-slider-end',cn:{cls:'x-slider-inner',cn:[{cls:'x-slider-thumb'},{tag:'a', cls:'x-slider-focus', href:"#", tabIndex: '-1', hidefocus:'on'}]}}
\r
10715 Ext.Slider.superclass.onRender.apply(this, arguments);
\r
10716 this.endEl = this.el.first();
\r
10717 this.innerEl = this.endEl.first();
\r
10718 this.thumb = this.innerEl.first();
\r
10719 this.halfThumb = (this.vertical ? this.thumb.getHeight() : this.thumb.getWidth())/2;
\r
10720 this.focusEl = this.thumb.next();
\r
10721 this.initEvents();
\r
10724 // private override
\r
10725 initEvents : function(){
\r
10726 this.thumb.addClassOnOver('x-slider-thumb-over');
\r
10727 this.mon(this.el, {
\r
10729 mousedown: this.onMouseDown,
\r
10730 keydown: this.onKeyDown
\r
10733 this.focusEl.swallowEvent("click", true);
\r
10735 this.tracker = new Ext.dd.DragTracker({
\r
10736 onBeforeStart: this.onBeforeDragStart.createDelegate(this),
\r
10737 onStart: this.onDragStart.createDelegate(this),
\r
10738 onDrag: this.onDrag.createDelegate(this),
\r
10739 onEnd: this.onDragEnd.createDelegate(this),
\r
10743 this.tracker.initEl(this.thumb);
\r
10744 this.on('beforedestroy', this.tracker.destroy, this.tracker);
\r
10747 // private override
\r
10748 onMouseDown : function(e){
\r
10749 if(this.disabled) {return;}
\r
10750 if(this.clickToChange && e.target != this.thumb.dom){
\r
10751 var local = this.innerEl.translatePoints(e.getXY());
\r
10752 this.onClickChange(local);
\r
10758 onClickChange : function(local){
\r
10759 if(local.top > this.clickRange[0] && local.top < this.clickRange[1]){
\r
10760 this.setValue(Ext.util.Format.round(this.reverseValue(local.left), this.decimalPrecision), undefined, true);
\r
10765 onKeyDown : function(e){
\r
10766 if(this.disabled){e.preventDefault();return;}
\r
10767 var k = e.getKey();
\r
10773 this.setValue(this.maxValue, undefined, true);
\r
10775 this.setValue(this.value+this.keyIncrement, undefined, true);
\r
10782 this.setValue(this.minValue, undefined, true);
\r
10784 this.setValue(this.value-this.keyIncrement, undefined, true);
\r
10788 e.preventDefault();
\r
10793 doSnap : function(value){
\r
10794 if(!this.increment || this.increment == 1 || !value) {
\r
10797 var newValue = value, inc = this.increment;
\r
10798 var m = value % inc;
\r
10803 }else if(m * 2 < -inc){
\r
10807 return newValue.constrain(this.minValue, this.maxValue);
\r
10811 afterRender : function(){
\r
10812 Ext.Slider.superclass.afterRender.apply(this, arguments);
\r
10813 if(this.value !== undefined){
\r
10814 var v = this.normalizeValue(this.value);
\r
10815 if(v !== this.value){
\r
10816 delete this.value;
\r
10817 this.setValue(v, false);
\r
10819 this.moveThumb(this.translateValue(v), false);
\r
10825 getRatio : function(){
\r
10826 var w = this.innerEl.getWidth();
\r
10827 var v = this.maxValue - this.minValue;
\r
10828 return v == 0 ? w : (w/v);
\r
10832 normalizeValue : function(v){
\r
10833 v = this.doSnap(v);
\r
10834 v = Ext.util.Format.round(v, this.decimalPrecision);
\r
10835 v = v.constrain(this.minValue, this.maxValue);
\r
10840 * Programmatically sets the value of the Slider. Ensures that the value is constrained within
\r
10841 * the minValue and maxValue.
\r
10842 * @param {Number} value The value to set the slider to. (This will be constrained within minValue and maxValue)
\r
10843 * @param {Boolean} animate Turn on or off animation, defaults to true
\r
10845 setValue : function(v, animate, changeComplete){
\r
10846 v = this.normalizeValue(v);
\r
10847 if(v !== this.value && this.fireEvent('beforechange', this, v, this.value) !== false){
\r
10849 this.moveThumb(this.translateValue(v), animate !== false);
\r
10850 this.fireEvent('change', this, v);
\r
10851 if(changeComplete){
\r
10852 this.fireEvent('changecomplete', this, v);
\r
10858 translateValue : function(v){
\r
10859 var ratio = this.getRatio();
\r
10860 return (v * ratio)-(this.minValue * ratio)-this.halfThumb;
\r
10863 reverseValue : function(pos){
\r
10864 var ratio = this.getRatio();
\r
10865 return (pos+this.halfThumb+(this.minValue * ratio))/ratio;
\r
10869 moveThumb: function(v, animate){
\r
10870 if(!animate || this.animate === false){
\r
10871 this.thumb.setLeft(v);
\r
10873 this.thumb.shift({left: v, stopFx: true, duration:.35});
\r
10878 focus : function(){
\r
10879 this.focusEl.focus(10);
\r
10883 onBeforeDragStart : function(e){
\r
10884 return !this.disabled;
\r
10888 onDragStart: function(e){
\r
10889 this.thumb.addClass('x-slider-thumb-drag');
\r
10890 this.dragging = true;
\r
10891 this.dragStartValue = this.value;
\r
10892 this.fireEvent('dragstart', this, e);
\r
10896 onDrag: function(e){
\r
10897 var pos = this.innerEl.translatePoints(this.tracker.getXY());
\r
10898 this.setValue(Ext.util.Format.round(this.reverseValue(pos.left), this.decimalPrecision), false);
\r
10899 this.fireEvent('drag', this, e);
\r
10903 onDragEnd: function(e){
\r
10904 this.thumb.removeClass('x-slider-thumb-drag');
\r
10905 this.dragging = false;
\r
10906 this.fireEvent('dragend', this, e);
\r
10907 if(this.dragStartValue != this.value){
\r
10908 this.fireEvent('changecomplete', this, this.value);
\r
10913 onResize : function(w, h){
\r
10914 this.innerEl.setWidth(w - (this.el.getPadding('l') + this.endEl.getPadding('r')));
\r
10915 this.syncThumb();
\r
10919 onDisable: function(){
\r
10920 Ext.Slider.superclass.onDisable.call(this);
\r
10921 this.thumb.addClass(this.disabledClass);
\r
10923 //IE breaks when using overflow visible and opacity other than 1.
\r
10924 //Create a place holder for the thumb and display it.
\r
10925 var xy = this.thumb.getXY();
\r
10926 this.thumb.hide();
\r
10927 this.innerEl.addClass(this.disabledClass).dom.disabled = true;
\r
10928 if (!this.thumbHolder){
\r
10929 this.thumbHolder = this.endEl.createChild({cls: 'x-slider-thumb ' + this.disabledClass});
\r
10931 this.thumbHolder.show().setXY(xy);
\r
10936 onEnable: function(){
\r
10937 Ext.Slider.superclass.onEnable.call(this);
\r
10938 this.thumb.removeClass(this.disabledClass);
\r
10940 this.innerEl.removeClass(this.disabledClass).dom.disabled = false;
\r
10941 if (this.thumbHolder){
\r
10942 this.thumbHolder.hide();
\r
10944 this.thumb.show();
\r
10945 this.syncThumb();
\r
10950 * Synchronizes the thumb position to the proper proportion of the total component width based
\r
10951 * on the current slider {@link #value}. This will be called automatically when the Slider
\r
10952 * is resized by a layout, but if it is rendered auto width, this method can be called from
\r
10953 * another resize handler to sync the Slider if necessary.
\r
10955 syncThumb : function(){
\r
10956 if(this.rendered){
\r
10957 this.moveThumb(this.translateValue(this.value));
\r
10962 * Returns the current value of the slider
\r
10963 * @return {Number} The current value of the slider
\r
10965 getValue : function(){
\r
10966 return this.value;
\r
10969 Ext.reg('slider', Ext.Slider);
\r
10971 // private class to support vertical sliders
\r
10972 Ext.Slider.Vertical = {
\r
10973 onResize : function(w, h){
\r
10974 this.innerEl.setHeight(h - (this.el.getPadding('t') + this.endEl.getPadding('b')));
\r
10975 this.syncThumb();
\r
10978 getRatio : function(){
\r
10979 var h = this.innerEl.getHeight();
\r
10980 var v = this.maxValue - this.minValue;
\r
10984 moveThumb: function(v, animate){
\r
10985 if(!animate || this.animate === false){
\r
10986 this.thumb.setBottom(v);
\r
10988 this.thumb.shift({bottom: v, stopFx: true, duration:.35});
\r
10992 onDrag: function(e){
\r
10993 var pos = this.innerEl.translatePoints(this.tracker.getXY());
\r
10994 var bottom = this.innerEl.getHeight()-pos.top;
\r
10995 this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), false);
\r
10996 this.fireEvent('drag', this, e);
\r
10999 onClickChange : function(local){
\r
11000 if(local.left > this.clickRange[0] && local.left < this.clickRange[1]){
\r
11001 var bottom = this.innerEl.getHeight()-local.top;
\r
11002 this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), undefined, true);
\r
11006 * @class Ext.ProgressBar
\r
11007 * @extends Ext.BoxComponent
\r
11008 * <p>An updateable progress bar component. The progress bar supports two different modes: manual and automatic.</p>
\r
11009 * <p>In manual mode, you are responsible for showing, updating (via {@link #updateProgress}) and clearing the
\r
11010 * progress bar as needed from your own code. This method is most appropriate when you want to show progress
\r
11011 * throughout an operation that has predictable points of interest at which you can update the control.</p>
\r
11012 * <p>In automatic mode, you simply call {@link #wait} and let the progress bar run indefinitely, only clearing it
\r
11013 * once the operation is complete. You can optionally have the progress bar wait for a specific amount of time
\r
11014 * and then clear itself. Automatic mode is most appropriate for timed operations or asynchronous operations in
\r
11015 * which you have no need for indicating intermediate progress.</p>
\r
11016 * @cfg {Float} value A floating point value between 0 and 1 (e.g., .5, defaults to 0)
\r
11017 * @cfg {String} text The progress bar text (defaults to '')
\r
11018 * @cfg {Mixed} textEl The element to render the progress text to (defaults to the progress
\r
11019 * bar's internal text element)
\r
11020 * @cfg {String} id The progress bar element's id (defaults to an auto-generated id)
\r
11021 * @xtype progress
\r
11023 Ext.ProgressBar = Ext.extend(Ext.BoxComponent, {
\r
11025 * @cfg {String} baseCls
\r
11026 * The base CSS class to apply to the progress bar's wrapper element (defaults to 'x-progress')
\r
11028 baseCls : 'x-progress',
\r
11031 * @cfg {Boolean} animate
\r
11032 * True to animate the progress bar during transitions (defaults to false)
\r
11037 waitTimer : null,
\r
11040 initComponent : function(){
\r
11041 Ext.ProgressBar.superclass.initComponent.call(this);
\r
11045 * Fires after each update interval
\r
11046 * @param {Ext.ProgressBar} this
\r
11047 * @param {Number} The current progress value
\r
11048 * @param {String} The current progress text
\r
11055 onRender : function(ct, position){
\r
11056 var tpl = new Ext.Template(
\r
11057 '<div class="{cls}-wrap">',
\r
11058 '<div class="{cls}-inner">',
\r
11059 '<div class="{cls}-bar">',
\r
11060 '<div class="{cls}-text">',
\r
11061 '<div> </div>',
\r
11064 '<div class="{cls}-text {cls}-text-back">',
\r
11065 '<div> </div>',
\r
11071 this.el = position ? tpl.insertBefore(position, {cls: this.baseCls}, true)
\r
11072 : tpl.append(ct, {cls: this.baseCls}, true);
\r
11075 this.el.dom.id = this.id;
\r
11077 var inner = this.el.dom.firstChild;
\r
11078 this.progressBar = Ext.get(inner.firstChild);
\r
11081 //use an external text el
\r
11082 this.textEl = Ext.get(this.textEl);
\r
11083 delete this.textTopEl;
\r
11085 //setup our internal layered text els
\r
11086 this.textTopEl = Ext.get(this.progressBar.dom.firstChild);
\r
11087 var textBackEl = Ext.get(inner.childNodes[1]);
\r
11088 this.textTopEl.setStyle("z-index", 99).addClass('x-hidden');
\r
11089 this.textEl = new Ext.CompositeElement([this.textTopEl.dom.firstChild, textBackEl.dom.firstChild]);
\r
11090 this.textEl.setWidth(inner.offsetWidth);
\r
11092 this.progressBar.setHeight(inner.offsetHeight);
\r
11096 afterRender : function(){
\r
11097 Ext.ProgressBar.superclass.afterRender.call(this);
\r
11099 this.updateProgress(this.value, this.text);
\r
11101 this.updateText(this.text);
\r
11106 * Updates the progress bar value, and optionally its text. If the text argument is not specified,
\r
11107 * any existing text value will be unchanged. To blank out existing text, pass ''. Note that even
\r
11108 * if the progress bar value exceeds 1, it will never automatically reset -- you are responsible for
\r
11109 * determining when the progress is complete and calling {@link #reset} to clear and/or hide the control.
\r
11110 * @param {Float} value (optional) A floating point value between 0 and 1 (e.g., .5, defaults to 0)
\r
11111 * @param {String} text (optional) The string to display in the progress text element (defaults to '')
\r
11112 * @param {Boolean} animate (optional) Whether to animate the transition of the progress bar. If this value is
\r
11113 * not specified, the default for the class is used (default to false)
\r
11114 * @return {Ext.ProgressBar} this
\r
11116 updateProgress : function(value, text, animate){
\r
11117 this.value = value || 0;
\r
11119 this.updateText(text);
\r
11121 if(this.rendered){
\r
11122 var w = Math.floor(value*this.el.dom.firstChild.offsetWidth);
\r
11123 this.progressBar.setWidth(w, animate === true || (animate !== false && this.animate));
\r
11124 if(this.textTopEl){
\r
11125 //textTopEl should be the same width as the bar so overflow will clip as the bar moves
\r
11126 this.textTopEl.removeClass('x-hidden').setWidth(w);
\r
11129 this.fireEvent('update', this, value, text);
\r
11134 * Initiates an auto-updating progress bar. A duration can be specified, in which case the progress
\r
11135 * bar will automatically reset after a fixed amount of time and optionally call a callback function
\r
11136 * if specified. If no duration is passed in, then the progress bar will run indefinitely and must
\r
11137 * be manually cleared by calling {@link #reset}. The wait method accepts a config object with
\r
11138 * the following properties:
\r
11140 Property Type Description
\r
11141 ---------- ------------ ----------------------------------------------------------------------
\r
11142 duration Number The length of time in milliseconds that the progress bar should
\r
11143 run before resetting itself (defaults to undefined, in which case it
\r
11144 will run indefinitely until reset is called)
\r
11145 interval Number The length of time in milliseconds between each progress update
\r
11146 (defaults to 1000 ms)
\r
11147 animate Boolean Whether to animate the transition of the progress bar. If this value is
\r
11148 not specified, the default for the class is used.
\r
11149 increment Number The number of progress update segments to display within the progress
\r
11150 bar (defaults to 10). If the bar reaches the end and is still
\r
11151 updating, it will automatically wrap back to the beginning.
\r
11152 text String Optional text to display in the progress bar element (defaults to '').
\r
11153 fn Function A callback function to execute after the progress bar finishes auto-
\r
11154 updating. The function will be called with no arguments. This function
\r
11155 will be ignored if duration is not specified since in that case the
\r
11156 progress bar can only be stopped programmatically, so any required function
\r
11157 should be called by the same code after it resets the progress bar.
\r
11158 scope Object The scope that is passed to the callback function (only applies when
\r
11159 duration and fn are both passed).
\r
11164 var p = new Ext.ProgressBar({
\r
11165 renderTo: 'my-el'
\r
11168 //Wait for 5 seconds, then update the status el (progress bar will auto-reset)
\r
11170 interval: 100, //bar will move fast!
\r
11173 text: 'Updating...',
\r
11176 Ext.fly('status').update('Done!');
\r
11180 //Or update indefinitely until some async action completes, then reset manually
\r
11182 myAction.on('complete', function(){
\r
11184 Ext.fly('status').update('Done!');
\r
11187 * @param {Object} config (optional) Configuration options
\r
11188 * @return {Ext.ProgressBar} this
\r
11190 wait : function(o){
\r
11191 if(!this.waitTimer){
\r
11192 var scope = this;
\r
11194 this.updateText(o.text);
\r
11195 this.waitTimer = Ext.TaskMgr.start({
\r
11196 run: function(i){
\r
11197 var inc = o.increment || 10;
\r
11198 this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
\r
11200 interval: o.interval || 1000,
\r
11201 duration: o.duration,
\r
11202 onStop: function(){
\r
11204 o.fn.apply(o.scope || this);
\r
11215 * Returns true if the progress bar is currently in a {@link #wait} operation
\r
11216 * @return {Boolean} True if waiting, else false
\r
11218 isWaiting : function(){
\r
11219 return this.waitTimer !== null;
\r
11223 * Updates the progress bar text. If specified, textEl will be updated, otherwise the progress
\r
11224 * bar itself will display the updated text.
\r
11225 * @param {String} text (optional) The string to display in the progress text element (defaults to '')
\r
11226 * @return {Ext.ProgressBar} this
\r
11228 updateText : function(text){
\r
11229 this.text = text || ' ';
\r
11230 if(this.rendered){
\r
11231 this.textEl.update(this.text);
\r
11237 * Synchronizes the inner bar width to the proper proportion of the total componet width based
\r
11238 * on the current progress {@link #value}. This will be called automatically when the ProgressBar
\r
11239 * is resized by a layout, but if it is rendered auto width, this method can be called from
\r
11240 * another resize handler to sync the ProgressBar if necessary.
\r
11242 syncProgressBar : function(){
\r
11244 this.updateProgress(this.value, this.text);
\r
11250 * Sets the size of the progress bar.
\r
11251 * @param {Number} width The new width in pixels
\r
11252 * @param {Number} height The new height in pixels
\r
11253 * @return {Ext.ProgressBar} this
\r
11255 setSize : function(w, h){
\r
11256 Ext.ProgressBar.superclass.setSize.call(this, w, h);
\r
11257 if(this.textTopEl){
\r
11258 var inner = this.el.dom.firstChild;
\r
11259 this.textEl.setSize(inner.offsetWidth, inner.offsetHeight);
\r
11261 this.syncProgressBar();
\r
11266 * Resets the progress bar value to 0 and text to empty string. If hide = true, the progress
\r
11267 * bar will also be hidden (using the {@link #hideMode} property internally).
\r
11268 * @param {Boolean} hide (optional) True to hide the progress bar (defaults to false)
\r
11269 * @return {Ext.ProgressBar} this
\r
11271 reset : function(hide){
\r
11272 this.updateProgress(0);
\r
11273 if(this.textTopEl){
\r
11274 this.textTopEl.addClass('x-hidden');
\r
11276 if(this.waitTimer){
\r
11277 this.waitTimer.onStop = null; //prevent recursion
\r
11278 Ext.TaskMgr.stop(this.waitTimer);
\r
11279 this.waitTimer = null;
\r
11281 if(hide === true){
\r
11287 Ext.reg('progress', Ext.ProgressBar);