X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/c930e9176a5a85509c5b0230e2bff5c22a591432..25ef3491bd9ae007ff1fc2b0d7943e6eaaccf775:/pkgs/cmp-foundation-debug.js?ds=sidebyside diff --git a/pkgs/cmp-foundation-debug.js b/pkgs/cmp-foundation-debug.js index 94a91ae5..22f6c94c 100644 --- a/pkgs/cmp-foundation-debug.js +++ b/pkgs/cmp-foundation-debug.js @@ -1,5 +1,5 @@ /*! - * Ext JS Library 3.0.0 + * Ext JS Library 3.0.3 * Copyright(c) 2006-2009 Ext JS, LLC * licensing@extjs.com * http://www.extjs.com/license @@ -11,12 +11,12 @@ * {@link Ext.Component#id id} (see {@link #get}, or the convenience method {@link Ext#getCmp Ext.getCmp}).
*This object also provides a registry of available Component classes
* indexed by a mnemonic code known as the Component's {@link Ext.Component#xtype xtype}.
- * The {@link Ext.Component#xtype xtype} provides a way to avoid instantiating child Components
+ * The {@link Ext.Component#xtype xtype}
provides a way to avoid instantiating child Components
* when creating a full, nested config object for a complete Ext page.
A child Component may be specified simply as a config object
- * as long as the correct {@link Ext.Component#xtype xtype} is specified so that if and when the Component
+ * as long as the correct {@link Ext.Component#xtype xtype}
is specified so that if and when the Component
* needs rendering, the correct type can be looked up for lazy instantiation.
For a list of all available {@link Ext.Component#xtype xtypes}, see {@link Ext.Component}.
+ *For a list of all available {@link Ext.Component#xtype xtypes}
, see {@link Ext.Component}.
undefined
if not found, or null
if a
* Class was found.
*/
get : function(id){
@@ -103,7 +103,7 @@ Ext.ComponentMgr = function(){
* config object's {@link Ext.component#xtype xtype} to determine the class to instantiate.
* @param {Object} config A configuration object for the Component you wish to create.
* @param {Constructor} defaultType The constructor to provide the default Component type if
- * the config object does not contain a xtype. (Optional if the config contains a xtype).
+ * the config object does not contain a xtype
. (Optional if the config contains a xtype
).
* @return {Ext.Component} The newly instantiated Component.
*/
create : function(config, defaultType){
@@ -129,7 +129,7 @@ Ext.ComponentMgr = function(){
* config object's {@link Ext.component#ptype ptype} to determine the class to instantiate.
* @param {Object} config A configuration object for the Plugin you wish to create.
* @param {Constructor} defaultType The constructor to provide the default Plugin type if
- * the config object does not contain a ptype. (Optional if the config contains a ptype).
+ * the config object does not contain a ptype
. (Optional if the config contains a ptype
).
* @return {Ext.Component} The newly instantiated Plugin.
*/
createPlugin : function(config, defaultType){
@@ -156,8 +156,18 @@ Ext.reg = Ext.ComponentMgr.registerType; // this will be called a lot internally
* @method preg
*/
Ext.preg = Ext.ComponentMgr.registerPlugin;
-Ext.create = Ext.ComponentMgr.create;
/**
+ * Shorthand for {@link Ext.ComponentMgr#create}
+ * Creates a new Component from the specified config object using the
+ * config object's {@link Ext.component#xtype xtype} to determine the class to instantiate.
+ * @param {Object} config A configuration object for the Component you wish to create.
+ * @param {Constructor} defaultType The constructor to provide the default Component type if
+ * the config object does not contain a xtype
. (Optional if the config contains a xtype
).
+ * @return {Ext.Component} The newly instantiated Component.
+ * @member Ext
+ * @method create
+ */
+Ext.create = Ext.ComponentMgr.create;/**
* @class Ext.Component
* @extends Ext.util.Observable
* Base class for all Ext components. All subclasses of Component may participate in the automated @@ -445,7 +455,7 @@ Ext.Component = function(config){ Ext.Component.AUTO_ID = 1000; Ext.extend(Ext.Component, Ext.util.Observable, { - // Configs below are used for all Components when rendered by FormLayout. + // Configs below are used for all Components when rendered by FormLayout. /** * @cfg {String} fieldLabel
The label text to display next to this Component (defaults to '').
*Note: this config is only used when this Component is rendered by a Container which @@ -544,7 +554,11 @@ new Ext.FormPanel({ *
See {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl} also.
*/ /** - * @cfg {String} itemClsAn additional CSS class to apply to the div wrapping the form item + * @cfg {String} itemCls + *
Note: this config is only used when this Component is rendered by a Container which + * has been configured to use the {@link Ext.layout.FormLayout FormLayout} layout manager (e.g. + * {@link Ext.form.FormPanel} or specifying layout:'form').
An additional CSS class to apply to the div wrapping the form item * element of this field. If supplied, itemCls at the field level will override * the default itemCls supplied at the container level. The value specified for * itemCls will be added to the default class ('x-form-item').
@@ -554,27 +568,27 @@ new Ext.FormPanel({ * any other element within the markup for the field. *Note: see the note for {@link #fieldLabel}.
-// Apply a style to the field's label:
+// Apply a style to the field's label:
<style>
.required .x-form-item-label {font-weight:bold;color:red;}
</style>
new Ext.FormPanel({
- height: 100,
- renderTo: Ext.getBody(),
- items: [{
- xtype: 'textfield',
- fieldLabel: 'Name',
- itemCls: 'required' //this label will be styled
- },{
- xtype: 'textfield',
- fieldLabel: 'Favorite Color'
- }]
+ height: 100,
+ renderTo: Ext.getBody(),
+ items: [{
+ xtype: 'textfield',
+ fieldLabel: 'Name',
+ itemCls: 'required' //this label will be styled
+ },{
+ xtype: 'textfield',
+ fieldLabel: 'Favorite Color'
+ }]
});
*/
- // Configs below are used for all Components when rendered by AnchorLayout.
+ // Configs below are used for all Components when rendered by AnchorLayout.
/**
* @cfg {String} anchor Note: this config is only used when this Component is rendered * by a Container which has been configured to use an {@link Ext.layout.AnchorLayout AnchorLayout} @@ -913,26 +927,26 @@ new Ext.Panel({ * @property el */ /** - * The component's owner {@link Ext.Container} (defaults to undefined, and is set automatically when - * the component is added to a container). Read-only. - *
Note: to access items within the container see {@link #itemId}.
+ * This Component's owner {@link Ext.Container Container} (defaults to undefined, and is set automatically when + * this Component is added to a Container). Read-only. + *Note: to access items within the Container see {@link #itemId}.
* @type Ext.Container * @property ownerCt */ /** * True if this component is hidden. Read-only. * @type Boolean - * @property + * @property hidden */ /** * True if this component is disabled. Read-only. * @type Boolean - * @property + * @property disabled */ /** * True if this component has been rendered. Read-only. * @type Boolean - * @property + * @property rendered */ rendered : false, @@ -1144,7 +1158,7 @@ var myGrid = new Ext.grid.EditorGridPanel({ }, // private - applyState : function(state, config){ + applyState : function(state){ if(state){ Ext.apply(this, state); } @@ -1251,19 +1265,22 @@ var myGrid = new Ext.grid.EditorGridPanel({ * */ destroy : function(){ - if(this.fireEvent('beforedestroy', this) !== false){ - this.beforeDestroy(); - if(this.rendered){ - this.el.removeAllListeners(); - this.el.remove(); - if(this.actionMode == 'container' || this.removeMode == 'container'){ - this.container.remove(); + if(!this.isDestroyed){ + if(this.fireEvent('beforedestroy', this) !== false){ + this.beforeDestroy(); + if(this.rendered){ + this.el.removeAllListeners(); + this.el.remove(); + if(this.actionMode == 'container' || this.removeMode == 'container'){ + this.container.remove(); + } } + this.onDestroy(); + Ext.ComponentMgr.unregister(this); + this.fireEvent('destroy', this); + this.purgeListeners(); + this.isDestroyed = true; } - this.onDestroy(); - Ext.ComponentMgr.unregister(this); - this.fireEvent('destroy', this); - this.purgeListeners(); } }, @@ -1418,7 +1435,7 @@ new Ext.Panel({ // private onShow : function(){ - this.getVisibiltyEl().removeClass('x-hide-' + this.hideMode); + this.getVisibilityEl().removeClass('x-hide-' + this.hideMode); }, /** @@ -1446,11 +1463,11 @@ new Ext.Panel({ // private onHide : function(){ - this.getVisibiltyEl().addClass('x-hide-' + this.hideMode); + this.getVisibilityEl().addClass('x-hide-' + this.hideMode); }, // private - getVisibiltyEl : function(){ + getVisibilityEl : function(){ return this.hideParent ? this.container : this.getActionEl(); }, @@ -1468,7 +1485,7 @@ new Ext.Panel({ * @return {Boolean} True if this component is visible, false otherwise. */ isVisible : function(){ - return this.rendered && this.getVisibiltyEl().isVisible(); + return this.rendered && this.getVisibilityEl().isVisible(); }, /** @@ -1598,16 +1615,20 @@ alert(t.getXTypes()); // alerts 'component/box/field/textfield' }, this); this.mons = []; }, - - // internal function for auto removal of assigned event handlers on destruction - mon : function(item, ename, fn, scope, opt){ + + // private + createMons: function(){ if(!this.mons){ this.mons = []; this.on('beforedestroy', this.clearMons, this, {single: true}); } + }, + // internal function for auto removal of assigned event handlers on destruction + mon : function(item, ename, fn, scope, opt){ + this.createMons(); if(Ext.isObject(ename)){ - var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/; + var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/; var o = ename; for(var e in o){ @@ -1616,22 +1637,21 @@ alert(t.getXTypes()); // alerts 'component/box/field/textfield' } if(Ext.isFunction(o[e])){ // shared options - this.mons.push({ - item: item, ename: e, fn: o[e], scope: o.scope - }); - item.on(e, o[e], o.scope, o); + this.mons.push({ + item: item, ename: e, fn: o[e], scope: o.scope + }); + item.on(e, o[e], o.scope, o); }else{ // individual options - this.mons.push({ - item: item, ename: e, fn: o[e], scope: o.scope - }); - item.on(e, o[e]); + this.mons.push({ + item: item, ename: e, fn: o[e], scope: o.scope + }); + item.on(e, o[e]); } } return; } - this.mons.push({ item: item, ename: ename, fn: fn, scope: scope }); @@ -1641,6 +1661,7 @@ alert(t.getXTypes()); // alerts 'component/box/field/textfield' // protected, opposite of mon mun : function(item, ename, fn, scope){ var found, mon; + this.createMons(); for(var i = 0, len = this.mons.length; i < len; ++i){ mon = this.mons[i]; if(item === mon.item && ename == mon.ename && fn === mon.fn && scope === mon.scope){ @@ -2611,6 +2632,14 @@ var myImage = new Ext.BoxComponent({ */ Ext.BoxComponent = Ext.extend(Ext.Component, { + // tabTip config is used when a BoxComponent is a child of a TabPanel + /** + * @cfg {String} tabTip + *Note: this config is only used when this BoxComponent is a child item of a TabPanel.
+ * A string to be used as innerHTML (html tags are accepted) to show in a tooltip when mousing over + * the associated tab selector element. {@link Ext.QuickTips}.init() + * must be called in order for the tips to render. + */ // Configs below are used for all Components when rendered by BorderLayout. /** * @cfg {String} regionNote: this config is only used when this BoxComponent is rendered @@ -3010,19 +3039,14 @@ var myPanel = new Ext.Panel({ }, // private - onRender : function(ct, position){ - Ext.BoxComponent.superclass.onRender.call(this, ct, position); + afterRender : function(){ + Ext.BoxComponent.superclass.afterRender.call(this); if(this.resizeEl){ this.resizeEl = Ext.get(this.resizeEl); } if(this.positionEl){ this.positionEl = Ext.get(this.positionEl); } - }, - - // private - afterRender : function(){ - Ext.BoxComponent.superclass.afterRender.call(this); this.boxReady = true; this.setSize(this.width, this.height); if(this.x || this.y){ @@ -3523,894 +3547,953 @@ Ext.SplitBar.TOP = 3; * @type Number */ Ext.SplitBar.BOTTOM = 4; -/** - * @class Ext.Container - * @extends Ext.BoxComponent - *
Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the - * basic behavior of containing items, namely adding, inserting and removing items.
- * - *The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}. - * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight - * Container to be encapsulated by an HTML element to your specifications by using the - * {@link Ext.Component#autoEl autoEl} config option. This is a useful technique when creating - * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels} - * for example.
- * - *The code below illustrates both how to explicitly create a Container, and how to implicitly - * create one using the 'container' xtype:
-// explicitly create a Container
-var embeddedColumns = new Ext.Container({
- autoEl: 'div', // This is the default
- layout: 'column',
- defaults: {
- // implicitly create Container by specifying xtype
- xtype: 'container',
- autoEl: 'div', // This is the default.
- layout: 'form',
- columnWidth: 0.5,
- style: {
- padding: '10px'
- }
- },
-// The two items below will be Ext.Containers, each encapsulated by a <DIV> element.
- items: [{
- items: {
- xtype: 'datefield',
- name: 'startDate',
- fieldLabel: 'Start date'
- }
- }, {
- items: {
- xtype: 'datefield',
- name: 'endDate',
- fieldLabel: 'End date'
- }
- }]
-});
- *
- * Layout
- *Container classes delegate the rendering of child Components to a layout
- * manager class which must be configured into the Container using the
- * {@link #layout}
configuration property.
When either specifying child {@link #items}
of a Container,
- * or dynamically {@link #add adding} Components to a Container, remember to
- * consider how you wish the Container to arrange those child elements, and
- * whether those child elements need to be sized using one of Ext's built-in
- * {@link #layout}
schemes. By default, Containers use the
- * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only
- * renders child components, appending them one after the other inside the
- * Container, and does not apply any sizing at all.
A common mistake is when a developer neglects to specify a
- * {@link #layout}
(e.g. widgets like GridPanels or
- * TreePanels are added to Containers for which no {@link #layout}
- * has been specified). If a Container is left to use the default
- * {@link Ext.layout.ContainerLayout ContainerLayout} scheme, none of its
- * child components will be resized, or changed in any way when the Container
- * is resized.
Certain layout managers allow dynamic addition of child components. - * Those that do include {@link Ext.layout.CardLayout}, - * {@link Ext.layout.AnchorLayout}, {@link Ext.layout.FormLayout}, and - * {@link Ext.layout.TableLayout}. For example:
-// Create the GridPanel.
-var myNewGrid = new Ext.grid.GridPanel({
- store: myStore,
- columns: myColumnModel,
- title: 'Results', // the title becomes the title of the tab
-});
-
-myTabPanel.add(myNewGrid); // {@link Ext.TabPanel} implicitly uses {@link Ext.layout.CardLayout CardLayout}
-myTabPanel.{@link Ext.TabPanel#setActiveTab setActiveTab}(myNewGrid);
- *
- * The example above adds a newly created GridPanel to a TabPanel. Note that - * a TabPanel uses {@link Ext.layout.CardLayout} as its layout manager which - * means all its child items are sized to {@link Ext.layout.FitLayout fit} - * exactly into its client area. - *
Overnesting is a common problem. - * An example of overnesting occurs when a GridPanel is added to a TabPanel - * by wrapping the GridPanel inside a wrapping Panel (that has no - * {@link #layout} specified) and then add that wrapping Panel - * to the TabPanel. The point to realize is that a GridPanel is a - * Component which can be added directly to a Container. If the wrapping Panel - * has no {@link #layout} configuration, then the overnested - * GridPanel will not be sized as expected.
- - * - *
Adding via remote configuration
- * - *A server side script can be used to add Components which are generated dynamically on the server. - * An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server - * based on certain parameters: - *
-// execute an Ajax request to invoke server side script:
-Ext.Ajax.request({
- url: 'gen-invoice-grid.php',
- // send additional parameters to instruct server script
- params: {
- startDate: Ext.getCmp('start-date').getValue(),
- endDate: Ext.getCmp('end-date').getValue()
- },
- // process the response object to add it to the TabPanel:
- success: function(xhr) {
- var newComponent = eval(xhr.responseText); // see discussion below
- myTabPanel.add(newComponent); // add the component to the TabPanel
- myTabPanel.setActiveTab(newComponent);
- },
- failure: function() {
- Ext.Msg.alert("Grid create failed", "Server communication failure");
- }
-});
-
- * The server script needs to return an executable Javascript statement which, when processed - * using eval(), will return either a config object with an {@link Ext.Component#xtype xtype}, - * or an instantiated Component. The server might return this for example:
-(function() {
- function formatDate(value){
- return value ? value.dateFormat('M d, Y') : '';
- };
-
- var store = new Ext.data.Store({
- url: 'get-invoice-data.php',
- baseParams: {
- startDate: '01/01/2008',
- endDate: '01/31/2008'
- },
- reader: new Ext.data.JsonReader({
- record: 'transaction',
- idProperty: 'id',
- totalRecords: 'total'
- }, [
- 'customer',
- 'invNo',
- {name: 'date', type: 'date', dateFormat: 'm/d/Y'},
- {name: 'value', type: 'float'}
- ])
- });
-
- var grid = new Ext.grid.GridPanel({
- title: 'Invoice Report',
- bbar: new Ext.PagingToolbar(store),
- store: store,
- columns: [
- {header: "Customer", width: 250, dataIndex: 'customer', sortable: true},
- {header: "Invoice Number", width: 120, dataIndex: 'invNo', sortable: true},
- {header: "Invoice Date", width: 100, dataIndex: 'date', renderer: formatDate, sortable: true},
- {header: "Value", width: 120, dataIndex: 'value', renderer: 'usMoney', sortable: true}
- ],
- });
- store.load();
- return grid; // return instantiated component
-})();
-
- * When the above code fragment is passed through the eval function in the success handler - * of the Ajax request, the code is executed by the Javascript processor, and the anonymous function - * runs, and returns the instantiated grid component.
- *Note: since the code above is generated by a server script, the baseParams for - * the Store, the metadata to allow generation of the Record layout, and the ColumnModel - * can all be generated into the code since these are all known on the server.
- * - * @xtype container - */ -Ext.Container = Ext.extend(Ext.BoxComponent, { - /** - * @cfg {Boolean} monitorResize - * True to automatically monitor window resize events to handle anything that is sensitive to the current size - * of the viewport. This value is typically managed by the chosen{@link #layout}
and should not need
- * to be set manually.
- */
- /**
- * @cfg {String/Object} layout
- * When creating complex UIs, it is important to remember that sizing and
- * positioning of child items is the responsibility of the Container's
- * layout manager. If you expect child items to be sized in response to
- * user interactions, you must specify a layout manager which
- * creates and manages the type of layout you have in mind. For example:
-new Ext.Window({
- width:300, height: 300,
- layout: 'fit', // explicitly set layout manager: override the default (layout:'auto')
- items: [{
- title: 'Panel inside a Window'
- }]
-}).show();
- *
- * Omitting the {@link #layout} config means that the - * {@link Ext.layout.ContainerLayout default layout manager} will be used which does - * nothing but render child components sequentially into the Container (no sizing or - * positioning will be performed in this situation).
- *The layout manager class for this container may be specified as either as an - * Object or as a String:
- *
-layout: {
- type: 'vbox',
- padding: '5',
- align: 'left'
-}
-
- *
- * The layout type to be used for this container. If not specified, - * a default {@link Ext.layout.ContainerLayout} will be created and used.
- *Valid layout type values are:
- *Additional layout specific configuration properties may also be - * specified. For complete details regarding the valid config options for - * each layout type, see the layout class corresponding to the type - * specified.
- * - *
-layout: 'vbox',
-layoutConfig: {
- padding: '5',
- align: 'left'
-}
-
- * The layout type to be used for this container (see list - * of valid layout type values above).
Additional layout specific configuration properties. For complete - * details regarding the valid config options for each layout type, see the - * layout class corresponding to the layout specified.
- *{@link #layout}
if {@link #layout}
- * has been specified as a string.
- */
- /**
- * @cfg {Boolean/Number} bufferResize
- * When set to true (100 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer
- * the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers
- * with a large quantity of sub-components for which frequent layout calls would be expensive.
- */
- bufferResize: 100,
-
- /**
- * @cfg {String/Number} activeItem
- * A string component id or the numeric index of the component that should be initially activated within the
- * container's layout on render. For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first
- * item in the container's collection). activeItem only applies to layout styles that can display
- * items one at a time (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout} and
- * {@link Ext.layout.FitLayout}). Related to {@link Ext.layout.ContainerLayout#activeItem}.
- */
- /**
- * @cfg {Object/Array} items
- * ** IMPORTANT: be sure to specify a {@link #layout}
! **
- * A single item, or an array of child Components to be added to this container, - * for example:
- *
-// specifying a single item
-items: {...},
-layout: 'fit', // specify a layout!
-
-// specifying multiple items
-items: [{...}, {...}],
-layout: 'anchor', // specify a layout!
- *
- * Each item may be:
- *{@link Ext.Component#xtype xtype}
{@link Ext.Component#xtype xtype}
is not explicitly
- * specified, the {@link #defaultType} for that Container is used.Notes:
- *{@link Ext.Panel#contentEl contentEl}
/
- * {@link Ext.Panel#html html}
with items
.A config object that will be applied to all components added to this container either via the {@link #items} - * config or via the {@link #add} or {@link #insert} methods. The defaults config can contain any - * number of name/value property pairs to be added to each item, and should be valid for the types of items - * being added to the container. For example, to automatically apply padding to the body of each of a set of - * contained {@link Ext.Panel} items, you could pass: defaults: {bodyStyle:'padding:15px'}.
Note: defaults will not be applied to config objects if the option is already specified. - * For example:
-defaults: { // defaults are applied to items, not the container
- autoScroll:true
-},
-items: [
- {
- xtype: 'panel', // defaults do not have precedence over
- id: 'panel1', // options in config objects, so the defaults
- autoScroll: false // will not be applied here, panel1 will be autoScroll:false
- },
- new Ext.Panel({ // defaults do have precedence over options
- id: 'panel2', // options in components, so the defaults
- autoScroll: false // will be applied here, panel2 will be autoScroll:true.
- })
-]
- *
- */
-
-
- /** @cfg {Boolean} autoDestroy
- * If true the container will automatically destroy any contained component that is removed from it, else
- * destruction must be handled manually (defaults to true).
- */
- autoDestroy : true,
-
- /** @cfg {Boolean} forceLayout
- * If true the container will force a layout initially even if hidden or collapsed. This option
- * is useful for forcing forms to render in collapsed or hidden containers. (defaults to false).
- */
- forceLayout: false,
-
- /** @cfg {Boolean} hideBorders
- * True to hide the borders of each contained component, false to defer to the component's existing
- * border settings (defaults to false).
- */
- /** @cfg {String} defaultType
- * The default {@link Ext.Component xtype} of child Components to create in this Container when - * a child item is specified as a raw configuration object, rather than as an instantiated Component.
- *Defaults to 'panel', except {@link Ext.menu.Menu} which defaults to 'menuitem', - * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to 'button'.
- */ - defaultType : 'panel', - - // private - initComponent : function(){ - Ext.Container.superclass.initComponent.call(this); - - this.addEvents( - /** - * @event afterlayout - * Fires when the components in this container are arranged by the associated layout manager. - * @param {Ext.Container} this - * @param {ContainerLayout} layout The ContainerLayout implementation for this container - */ - 'afterlayout', - /** - * @event beforeadd - * Fires before any {@link Ext.Component} is added or inserted into the container. - * A handler can return false to cancel the add. - * @param {Ext.Container} this - * @param {Ext.Component} component The component being added - * @param {Number} index The index at which the component will be added to the container's items collection - */ - 'beforeadd', - /** - * @event beforeremove - * Fires before any {@link Ext.Component} is removed from the container. A handler can return - * false to cancel the remove. - * @param {Ext.Container} this - * @param {Ext.Component} component The component being removed - */ - 'beforeremove', - /** - * @event add - * @bubbles - * Fires after any {@link Ext.Component} is added or inserted into the container. - * @param {Ext.Container} this - * @param {Ext.Component} component The component that was added - * @param {Number} index The index at which the component was added to the container's items collection - */ - 'add', - /** - * @event remove - * @bubbles - * Fires after any {@link Ext.Component} is removed from the container. - * @param {Ext.Container} this - * @param {Ext.Component} component The component that was removed - */ - 'remove' - ); - - this.enableBubble('add', 'remove'); - - /** - * The collection of components in this container as a {@link Ext.util.MixedCollection} - * @type MixedCollection - * @property items - */ - var items = this.items; - if(items){ - delete this.items; - if(Ext.isArray(items) && items.length > 0){ - this.add.apply(this, items); - }else{ - this.add(items); - } - } - }, - - // private - initItems : function(){ - if(!this.items){ - this.items = new Ext.util.MixedCollection(false, this.getComponentId); - this.getLayout(); // initialize the layout - } - }, - - // private - setLayout : function(layout){ - if(this.layout && this.layout != layout){ - this.layout.setContainer(null); - } - this.initItems(); - this.layout = layout; - layout.setContainer(this); - }, - - // private - render : function(){ - Ext.Container.superclass.render.apply(this, arguments); - if(this.layout){ - if(Ext.isObject(this.layout) && !this.layout.layout){ - this.layoutConfig = this.layout; - this.layout = this.layoutConfig.type; - } - if(typeof this.layout == 'string'){ - this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig); - } - this.setLayout(this.layout); - - if(this.activeItem !== undefined){ - var item = this.activeItem; - delete this.activeItem; - this.layout.setActiveItem(item); - } - } - if(!this.ownerCt){ - // force a layout if no ownerCt is set - this.doLayout(false, true); - } - if(this.monitorResize === true){ - Ext.EventManager.onWindowResize(this.doLayout, this, [false]); - } - }, - - /** - *Returns the Element to be used to contain the child Components of this Container.
- *An implementation is provided which returns the Container's {@link #getEl Element}, but - * if there is a more complex structure to a Container, this may be overridden to return - * the element into which the {@link #layout layout} renders child Components.
- * @return {Ext.Element} The Element to render child Components into. - */ - getLayoutTarget : function(){ - return this.el; - }, - - // private - used as the key lookup function for the items collection - getComponentId : function(comp){ - return comp.getItemId(); - }, - - /** - *Adds {@link Ext.Component Component}(s) to this Container.
- *Description : - *
{@link #defaults}
for details).Notes : - *
-var tb = new {@link Ext.Toolbar}();
-tb.render(document.body); // toolbar is rendered
-tb.add({text:'Button 1'}); // add multiple items ({@link #defaultType} for {@link Ext.Toolbar Toolbar} is 'button')
-tb.add({text:'Button 2'});
-tb.{@link #doLayout}(); // refresh the layout
- *
Either a single component or an Array of components to add. See
- * {@link #items}
for additional information.
{@link #items}
property
- * and gets a direct child component of this container.
- * @param {String/Number} comp This parameter may be any of the following:
- * {@link Ext.Component#itemId itemId}
- * or {@link Ext.Component#id id}
of the child component {@link #items}
propertyFor additional information see {@link Ext.util.MixedCollection#get}. - * @return Ext.Component The component (if found). - */ - getComponent : function(comp){ - if(Ext.isObject(comp)){ - return comp; - } - return this.items.get(comp); - }, - - // private - lookupComponent : function(comp){ - if(typeof comp == 'string'){ - return Ext.ComponentMgr.get(comp); - }else if(!comp.events){ - return this.createComponent(comp); - } - return comp; - }, - - // private - createComponent : function(config){ - return Ext.create(config, this.defaultType); - }, - - /** - * Force this container's layout to be recalculated. A call to this function is required after adding a new component - * to an already rendered container, or possibly after changing sizing/position properties of child components. - * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto - * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer) - * @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden. - * @return {Ext.Container} this - */ - doLayout: function(shallow, force){ - var rendered = this.rendered, - forceLayout = this.forceLayout; - - if(!this.isVisible() || this.collapsed){ - this.deferLayout = this.deferLayout || !shallow; - if(!(force || forceLayout)){ - return; - } - shallow = shallow && !this.deferLayout; - } else { - delete this.deferLayout; - } - if(rendered && this.layout){ - this.layout.layout(); - } - if(shallow !== true && this.items){ - var cs = this.items.items; - for(var i = 0, len = cs.length; i < len; i++){ - var c = cs[i]; - if(c.doLayout){ - c.forceLayout = forceLayout; - c.doLayout(); - } - } - } - if(rendered){ - this.onLayout(shallow, force); - } - delete this.forceLayout; - }, - - //private - onLayout : Ext.emptyFn, - - onShow : function(){ - Ext.Container.superclass.onShow.call(this); - if(this.deferLayout !== undefined){ - this.doLayout(true); - } - }, - - /** - * Returns the layout currently in use by the container. If the container does not currently have a layout - * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout. - * @return {ContainerLayout} layout The container's layout - */ - getLayout : function(){ - if(!this.layout){ - var layout = new Ext.layout.ContainerLayout(this.layoutConfig); - this.setLayout(layout); - } - return this.layout; - }, - - // private - beforeDestroy : function(){ - if(this.items){ - Ext.destroy.apply(Ext, this.items.items); - } - if(this.monitorResize){ - Ext.EventManager.removeResizeListener(this.doLayout, this); - } - Ext.destroy(this.layout); - Ext.Container.superclass.beforeDestroy.call(this); - }, - - /** - * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (this) of - * function call will be the scope provided or the current component. The arguments to the function - * will be the args provided or the current component. If the function returns false at any point, - * the bubble is stopped. - * @param {Function} fn The function to call - * @param {Object} scope (optional) The scope of the function (defaults to current node) - * @param {Array} args (optional) The args to call the function with (default to passing the current component) - * @return {Ext.Container} this - */ - bubble : function(fn, scope, args){ - var p = this; - while(p){ - if(fn.apply(scope || p, args || [p]) === false){ - break; - } - p = p.ownerCt; - } - return this; - }, - - /** - * Cascades down the component/container heirarchy from this component (called first), calling the specified function with - * each component. The scope (this) of - * function call will be the scope provided or the current component. The arguments to the function - * will be the args provided or the current component. If the function returns false at any point, - * the cascade is stopped on that branch. - * @param {Function} fn The function to call - * @param {Object} scope (optional) The scope of the function (defaults to current component) - * @param {Array} args (optional) The args to call the function with (defaults to passing the current component) - * @return {Ext.Container} this - */ - cascade : function(fn, scope, args){ - if(fn.apply(scope || this, args || [this]) !== false){ - if(this.items){ - var cs = this.items.items; - for(var i = 0, len = cs.length; i < len; i++){ - if(cs[i].cascade){ - cs[i].cascade(fn, scope, args); - }else{ - fn.apply(scope || cs[i], args || [cs[i]]); - } - } - } - } - return this; - }, - - /** - * Find a component under this container at any level by id - * @param {String} id - * @return Ext.Component - */ - findById : function(id){ - var m, ct = this; - this.cascade(function(c){ - if(ct != c && c.id === id){ - m = c; - return false; - } - }); - return m || null; - }, - - /** - * Find a component under this container at any level by xtype or class - * @param {String/Class} xtype The xtype string for a component, or the class of the component directly - * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is - * the default), or true to check whether this Component is directly of the specified xtype. - * @return {Array} Array of Ext.Components - */ - findByType : function(xtype, shallow){ - return this.findBy(function(c){ - return c.isXType(xtype, shallow); - }); - }, - - /** - * Find a component under this container at any level by property - * @param {String} prop - * @param {String} value - * @return {Array} Array of Ext.Components - */ - find : function(prop, value){ - return this.findBy(function(c){ - return c[prop] === value; - }); - }, - - /** - * Find a component under this container at any level by a custom function. If the passed function returns - * true, the component will be included in the results. The passed function is called with the arguments (component, this container). - * @param {Function} fn The function to call - * @param {Object} scope (optional) - * @return {Array} Array of Ext.Components - */ - findBy : function(fn, scope){ - var m = [], ct = this; - this.cascade(function(c){ - if(ct != c && fn.call(scope || c, c, ct) === true){ - m.push(c); - } - }); - return m; - }, - - /** - * Get a component contained by this container (alias for items.get(key)) - * @param {String/Number} key The index or id of the component - * @return {Ext.Component} Ext.Component - */ - get : function(key){ - return this.items.get(key); - } -}); - -Ext.Container.LAYOUTS = {}; -Ext.reg('container', Ext.Container); +/** + * @class Ext.Container + * @extends Ext.BoxComponent + *
Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the + * basic behavior of containing items, namely adding, inserting and removing items.
+ * + *The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}. + * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight + * Container to be encapsulated by an HTML element to your specifications by using the + * {@link Ext.Component#autoEl autoEl} config option. This is a useful technique when creating + * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels} + * for example.
+ * + *The code below illustrates both how to explicitly create a Container, and how to implicitly + * create one using the 'container' xtype:
+// explicitly create a Container
+var embeddedColumns = new Ext.Container({
+ autoEl: 'div', // This is the default
+ layout: 'column',
+ defaults: {
+ // implicitly create Container by specifying xtype
+ xtype: 'container',
+ autoEl: 'div', // This is the default.
+ layout: 'form',
+ columnWidth: 0.5,
+ style: {
+ padding: '10px'
+ }
+ },
+// The two items below will be Ext.Containers, each encapsulated by a <DIV> element.
+ items: [{
+ items: {
+ xtype: 'datefield',
+ name: 'startDate',
+ fieldLabel: 'Start date'
+ }
+ }, {
+ items: {
+ xtype: 'datefield',
+ name: 'endDate',
+ fieldLabel: 'End date'
+ }
+ }]
+});
+ *
+ * Layout
+ *Container classes delegate the rendering of child Components to a layout
+ * manager class which must be configured into the Container using the
+ * {@link #layout}
configuration property.
When either specifying child {@link #items}
of a Container,
+ * or dynamically {@link #add adding} Components to a Container, remember to
+ * consider how you wish the Container to arrange those child elements, and
+ * whether those child elements need to be sized using one of Ext's built-in
+ * {@link #layout}
schemes. By default, Containers use the
+ * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only
+ * renders child components, appending them one after the other inside the
+ * Container, and does not apply any sizing at all.
A common mistake is when a developer neglects to specify a
+ * {@link #layout}
(e.g. widgets like GridPanels or
+ * TreePanels are added to Containers for which no {@link #layout}
+ * has been specified). If a Container is left to use the default
+ * {@link Ext.layout.ContainerLayout ContainerLayout} scheme, none of its
+ * child components will be resized, or changed in any way when the Container
+ * is resized.
Certain layout managers allow dynamic addition of child components. + * Those that do include {@link Ext.layout.CardLayout}, + * {@link Ext.layout.AnchorLayout}, {@link Ext.layout.FormLayout}, and + * {@link Ext.layout.TableLayout}. For example:
+// Create the GridPanel.
+var myNewGrid = new Ext.grid.GridPanel({
+ store: myStore,
+ columns: myColumnModel,
+ title: 'Results', // the title becomes the title of the tab
+});
+
+myTabPanel.add(myNewGrid); // {@link Ext.TabPanel} implicitly uses {@link Ext.layout.CardLayout CardLayout}
+myTabPanel.{@link Ext.TabPanel#setActiveTab setActiveTab}(myNewGrid);
+ *
+ * The example above adds a newly created GridPanel to a TabPanel. Note that + * a TabPanel uses {@link Ext.layout.CardLayout} as its layout manager which + * means all its child items are sized to {@link Ext.layout.FitLayout fit} + * exactly into its client area. + *
Overnesting is a common problem. + * An example of overnesting occurs when a GridPanel is added to a TabPanel + * by wrapping the GridPanel inside a wrapping Panel (that has no + * {@link #layout} specified) and then add that wrapping Panel + * to the TabPanel. The point to realize is that a GridPanel is a + * Component which can be added directly to a Container. If the wrapping Panel + * has no {@link #layout} configuration, then the overnested + * GridPanel will not be sized as expected.
+ * + *
Adding via remote configuration
+ * + *A server side script can be used to add Components which are generated dynamically on the server. + * An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server + * based on certain parameters: + *
+// execute an Ajax request to invoke server side script:
+Ext.Ajax.request({
+ url: 'gen-invoice-grid.php',
+ // send additional parameters to instruct server script
+ params: {
+ startDate: Ext.getCmp('start-date').getValue(),
+ endDate: Ext.getCmp('end-date').getValue()
+ },
+ // process the response object to add it to the TabPanel:
+ success: function(xhr) {
+ var newComponent = eval(xhr.responseText); // see discussion below
+ myTabPanel.add(newComponent); // add the component to the TabPanel
+ myTabPanel.setActiveTab(newComponent);
+ },
+ failure: function() {
+ Ext.Msg.alert("Grid create failed", "Server communication failure");
+ }
+});
+
+ * The server script needs to return an executable Javascript statement which, when processed + * using eval(), will return either a config object with an {@link Ext.Component#xtype xtype}, + * or an instantiated Component. The server might return this for example:
+(function() {
+ function formatDate(value){
+ return value ? value.dateFormat('M d, Y') : '';
+ };
+
+ var store = new Ext.data.Store({
+ url: 'get-invoice-data.php',
+ baseParams: {
+ startDate: '01/01/2008',
+ endDate: '01/31/2008'
+ },
+ reader: new Ext.data.JsonReader({
+ record: 'transaction',
+ idProperty: 'id',
+ totalRecords: 'total'
+ }, [
+ 'customer',
+ 'invNo',
+ {name: 'date', type: 'date', dateFormat: 'm/d/Y'},
+ {name: 'value', type: 'float'}
+ ])
+ });
+
+ var grid = new Ext.grid.GridPanel({
+ title: 'Invoice Report',
+ bbar: new Ext.PagingToolbar(store),
+ store: store,
+ columns: [
+ {header: "Customer", width: 250, dataIndex: 'customer', sortable: true},
+ {header: "Invoice Number", width: 120, dataIndex: 'invNo', sortable: true},
+ {header: "Invoice Date", width: 100, dataIndex: 'date', renderer: formatDate, sortable: true},
+ {header: "Value", width: 120, dataIndex: 'value', renderer: 'usMoney', sortable: true}
+ ],
+ });
+ store.load();
+ return grid; // return instantiated component
+})();
+
+ * When the above code fragment is passed through the eval function in the success handler + * of the Ajax request, the code is executed by the Javascript processor, and the anonymous function + * runs, and returns the instantiated grid component.
+ *Note: since the code above is generated by a server script, the baseParams for + * the Store, the metadata to allow generation of the Record layout, and the ColumnModel + * can all be generated into the code since these are all known on the server.
+ * + * @xtype container + */ +Ext.Container = Ext.extend(Ext.BoxComponent, { + /** + * @cfg {Boolean} monitorResize + * True to automatically monitor window resize events to handle anything that is sensitive to the current size + * of the viewport. This value is typically managed by the chosen{@link #layout}
and should not need
+ * to be set manually.
+ */
+ /**
+ * @cfg {String/Object} layout
+ * *Important: In order for child items to be correctly sized and
+ * positioned, typically a layout manager must be specified through
+ * the layout
configuration option.
The sizing and positioning of child {@link items} is the responsibility of + * the Container's layout manager which creates and manages the type of layout + * you have in mind. For example:
+new Ext.Window({
+ width:300, height: 300,
+ layout: 'fit', // explicitly set layout manager: override the default (layout:'auto')
+ items: [{
+ title: 'Panel inside a Window'
+ }]
+}).show();
+ *
+ * If the {@link #layout} configuration is not explicitly specified for
+ * a general purpose container (e.g. Container or Panel) the
+ * {@link Ext.layout.ContainerLayout default layout manager} will be used
+ * which does nothing but render child components sequentially into the
+ * Container (no sizing or positioning will be performed in this situation).
+ * Some container classes implicitly specify a default layout
+ * (e.g. FormPanel specifies layout:'form'
). Other specific
+ * purpose classes internally specify/manage their internal layout (e.g.
+ * GridPanel, TabPanel, TreePanel, Toolbar, Menu, etc.).
layout
may be specified as either as an Object or
+ * as a String:
+layout: {
+ type: 'vbox',
+ padding: '5',
+ align: 'left'
+}
+
+ *
+ * The layout type to be used for this container. If not specified, + * a default {@link Ext.layout.ContainerLayout} will be created and used.
+ *Valid layout type values are:
+ *Additional layout specific configuration properties may also be + * specified. For complete details regarding the valid config options for + * each layout type, see the layout class corresponding to the type + * specified.
+ * + *
+layout: 'vbox',
+layoutConfig: {
+ padding: '5',
+ align: 'left'
+}
+
+ * The layout type to be used for this container (see list + * of valid layout type values above).
Additional layout specific configuration properties. For complete + * details regarding the valid config options for each layout type, see the + * layout class corresponding to the layout specified.
+ *{@link #layout}
if {@link #layout}
+ * has been specified as a string.
+ */
+ /**
+ * @cfg {Boolean/Number} bufferResize
+ * When set to true (50 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer
+ * the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers
+ * with a large quantity of sub-components for which frequent layout calls would be expensive. Defaults to 50.
+ */
+ bufferResize: 50,
+
+ /**
+ * @cfg {String/Number} activeItem
+ * A string component id or the numeric index of the component that should be initially activated within the
+ * container's layout on render. For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first
+ * item in the container's collection). activeItem only applies to layout styles that can display
+ * items one at a time (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout} and
+ * {@link Ext.layout.FitLayout}). Related to {@link Ext.layout.ContainerLayout#activeItem}.
+ */
+ /**
+ * @cfg {Object/Array} items
+ * ** IMPORTANT: be sure to {@link #layout specify a layout
} if needed ! **
+ * A single item, or an array of child Components to be added to this container, + * for example:
+ *
+// specifying a single item
+items: {...},
+layout: 'fit', // specify a layout!
+
+// specifying multiple items
+items: [{...}, {...}],
+layout: 'anchor', // specify a layout!
+ *
+ * Each item may be:
+ *{@link Ext.Component#xtype xtype}
{@link Ext.Component#xtype xtype}
is not explicitly
+ * specified, the {@link #defaultType} for that Container is used.Notes:
+ *{@link Ext.Panel#contentEl contentEl}
/
+ * {@link Ext.Panel#html html}
with items
.A config object that will be applied to all components added to this container either via the {@link #items} + * config or via the {@link #add} or {@link #insert} methods. The defaults config can contain any + * number of name/value property pairs to be added to each item, and should be valid for the types of items + * being added to the container. For example, to automatically apply padding to the body of each of a set of + * contained {@link Ext.Panel} items, you could pass: defaults: {bodyStyle:'padding:15px'}.
Note: defaults will not be applied to config objects if the option is already specified. + * For example:
+defaults: { // defaults are applied to items, not the container
+ autoScroll:true
+},
+items: [
+ {
+ xtype: 'panel', // defaults do not have precedence over
+ id: 'panel1', // options in config objects, so the defaults
+ autoScroll: false // will not be applied here, panel1 will be autoScroll:false
+ },
+ new Ext.Panel({ // defaults do have precedence over options
+ id: 'panel2', // options in components, so the defaults
+ autoScroll: false // will be applied here, panel2 will be autoScroll:true.
+ })
+]
+ *
+ */
+
+
+ /** @cfg {Boolean} autoDestroy
+ * If true the container will automatically destroy any contained component that is removed from it, else
+ * destruction must be handled manually (defaults to true).
+ */
+ autoDestroy : true,
+
+ /** @cfg {Boolean} forceLayout
+ * If true the container will force a layout initially even if hidden or collapsed. This option
+ * is useful for forcing forms to render in collapsed or hidden containers. (defaults to false).
+ */
+ forceLayout: false,
+
+ /** @cfg {Boolean} hideBorders
+ * True to hide the borders of each contained component, false to defer to the component's existing
+ * border settings (defaults to false).
+ */
+ /** @cfg {String} defaultType
+ * The default {@link Ext.Component xtype} of child Components to create in this Container when + * a child item is specified as a raw configuration object, rather than as an instantiated Component.
+ *Defaults to 'panel', except {@link Ext.menu.Menu} which defaults to 'menuitem', + * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to 'button'.
+ */ + defaultType : 'panel', + + /** @cfg {String} resizeEvent + * The event to listen to for resizing in layouts. Defaults to 'resize'. + */ + resizeEvent: 'resize', + + /** + * @cfg {Array} bubbleEvents + *An array of events that, when fired, should be bubbled to any parent container. + * Defaults to ['add', 'remove']. + */ + bubbleEvents: ['add', 'remove'], + + // private + initComponent : function(){ + Ext.Container.superclass.initComponent.call(this); + + this.addEvents( + /** + * @event afterlayout + * Fires when the components in this container are arranged by the associated layout manager. + * @param {Ext.Container} this + * @param {ContainerLayout} layout The ContainerLayout implementation for this container + */ + 'afterlayout', + /** + * @event beforeadd + * Fires before any {@link Ext.Component} is added or inserted into the container. + * A handler can return false to cancel the add. + * @param {Ext.Container} this + * @param {Ext.Component} component The component being added + * @param {Number} index The index at which the component will be added to the container's items collection + */ + 'beforeadd', + /** + * @event beforeremove + * Fires before any {@link Ext.Component} is removed from the container. A handler can return + * false to cancel the remove. + * @param {Ext.Container} this + * @param {Ext.Component} component The component being removed + */ + 'beforeremove', + /** + * @event add + * @bubbles + * Fires after any {@link Ext.Component} is added or inserted into the container. + * @param {Ext.Container} this + * @param {Ext.Component} component The component that was added + * @param {Number} index The index at which the component was added to the container's items collection + */ + 'add', + /** + * @event remove + * @bubbles + * Fires after any {@link Ext.Component} is removed from the container. + * @param {Ext.Container} this + * @param {Ext.Component} component The component that was removed + */ + 'remove' + ); + + this.enableBubble(this.bubbleEvents); + + /** + * The collection of components in this container as a {@link Ext.util.MixedCollection} + * @type MixedCollection + * @property items + */ + var items = this.items; + if(items){ + delete this.items; + this.add(items); + } + }, + + // private + initItems : function(){ + if(!this.items){ + this.items = new Ext.util.MixedCollection(false, this.getComponentId); + this.getLayout(); // initialize the layout + } + }, + + // private + setLayout : function(layout){ + if(this.layout && this.layout != layout){ + this.layout.setContainer(null); + } + this.initItems(); + this.layout = layout; + layout.setContainer(this); + }, + + afterRender: function(){ + Ext.Container.superclass.afterRender.call(this); + if(!this.layout){ + this.layout = 'auto'; + } + if(Ext.isObject(this.layout) && !this.layout.layout){ + this.layoutConfig = this.layout; + this.layout = this.layoutConfig.type; + } + if(Ext.isString(this.layout)){ + this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig); + } + this.setLayout(this.layout); + + if(this.activeItem !== undefined){ + var item = this.activeItem; + delete this.activeItem; + this.layout.setActiveItem(item); + } + if(!this.ownerCt){ + // force a layout if no ownerCt is set + this.doLayout(false, true); + } + if(this.monitorResize === true){ + Ext.EventManager.onWindowResize(this.doLayout, this, [false]); + } + }, + + /** + *
Returns the Element to be used to contain the child Components of this Container.
+ *An implementation is provided which returns the Container's {@link #getEl Element}, but + * if there is a more complex structure to a Container, this may be overridden to return + * the element into which the {@link #layout layout} renders child Components.
+ * @return {Ext.Element} The Element to render child Components into. + */ + getLayoutTarget : function(){ + return this.el; + }, + + // private - used as the key lookup function for the items collection + getComponentId : function(comp){ + return comp.getItemId(); + }, + + /** + *Adds {@link Ext.Component Component}(s) to this Container.
+ *Description : + *
{@link #defaults}
for details).Notes : + *
+var tb = new {@link Ext.Toolbar}();
+tb.render(document.body); // toolbar is rendered
+tb.add({text:'Button 1'}); // add multiple items ({@link #defaultType} for {@link Ext.Toolbar Toolbar} is 'button')
+tb.add({text:'Button 2'});
+tb.{@link #doLayout}(); // refresh the layout
+ *
Either a single component or an Array of components to add. See
+ * {@link #items}
for additional information.
{@link #items}
property
+ * and gets a direct child component of this container.
+ * @param {String/Number} comp This parameter may be any of the following:
+ * {@link Ext.Component#itemId itemId}
+ * or {@link Ext.Component#id id}
of the child component {@link #items}
propertyFor additional information see {@link Ext.util.MixedCollection#get}. + * @return Ext.Component The component (if found). + */ + getComponent : function(comp){ + if(Ext.isObject(comp)){ + comp = comp.getItemId(); + } + return this.items.get(comp); + }, + + // private + lookupComponent : function(comp){ + if(Ext.isString(comp)){ + return Ext.ComponentMgr.get(comp); + }else if(!comp.events){ + return this.createComponent(comp); + } + return comp; + }, + + // private + createComponent : function(config){ + return Ext.create(config, this.defaultType); + }, + + // private + canLayout: function() { + var el = this.getVisibilityEl(); + return el && !el.isStyle("display", "none"); + }, + + + /** + * Force this container's layout to be recalculated. A call to this function is required after adding a new component + * to an already rendered container, or possibly after changing sizing/position properties of child components. + * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto + * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer) + * @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden. + * @return {Ext.Container} this + */ + doLayout: function(shallow, force){ + var rendered = this.rendered; + forceLayout = force || this.forceLayout; + + if(!this.canLayout() || this.collapsed){ + this.deferLayout = this.deferLayout || !shallow; + if(!forceLayout){ + return; + } + shallow = shallow && !this.deferLayout; + } else { + delete this.deferLayout; + } + if(rendered && this.layout){ + this.layout.layout(); + } + if(shallow !== true && this.items){ + var cs = this.items.items; + for(var i = 0, len = cs.length; i < len; i++){ + var c = cs[i]; + if(c.doLayout){ + c.doLayout(false, forceLayout); + } + } + } + if(rendered){ + this.onLayout(shallow, forceLayout); + } + // Initial layout completed + this.hasLayout = true; + delete this.forceLayout; + }, + + //private + onLayout : Ext.emptyFn, + + // private + shouldBufferLayout: function(){ + /* + * Returns true if the container should buffer a layout. + * This is true only if the container has previously been laid out + * and has a parent container that is pending a layout. + */ + var hl = this.hasLayout; + if(this.ownerCt){ + // Only ever buffer if we've laid out the first time and we have one pending. + return hl ? !this.hasLayoutPending() : false; + } + // Never buffer initial layout + return hl; + }, + + // private + hasLayoutPending: function(){ + // Traverse hierarchy to see if any parent container has a pending layout. + var pending = false; + this.ownerCt.bubble(function(c){ + if(c.layoutPending){ + pending = true; + return false; + } + }); + return pending; + }, + + onShow : function(){ + Ext.Container.superclass.onShow.call(this); + if(this.deferLayout !== undefined){ + this.doLayout(true); + } + }, + + /** + * Returns the layout currently in use by the container. If the container does not currently have a layout + * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout. + * @return {ContainerLayout} layout The container's layout + */ + getLayout : function(){ + if(!this.layout){ + var layout = new Ext.layout.ContainerLayout(this.layoutConfig); + this.setLayout(layout); + } + return this.layout; + }, + + // private + beforeDestroy : function(){ + if(this.items){ + Ext.destroy.apply(Ext, this.items.items); + } + if(this.monitorResize){ + Ext.EventManager.removeResizeListener(this.doLayout, this); + } + Ext.destroy(this.layout); + Ext.Container.superclass.beforeDestroy.call(this); + }, + + /** + * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (this) of + * function call will be the scope provided or the current component. The arguments to the function + * will be the args provided or the current component. If the function returns false at any point, + * the bubble is stopped. + * @param {Function} fn The function to call + * @param {Object} scope (optional) The scope of the function (defaults to current node) + * @param {Array} args (optional) The args to call the function with (default to passing the current component) + * @return {Ext.Container} this + */ + bubble : function(fn, scope, args){ + var p = this; + while(p){ + if(fn.apply(scope || p, args || [p]) === false){ + break; + } + p = p.ownerCt; + } + return this; + }, + + /** + * Cascades down the component/container heirarchy from this component (called first), calling the specified function with + * each component. The scope (this) of + * function call will be the scope provided or the current component. The arguments to the function + * will be the args provided or the current component. If the function returns false at any point, + * the cascade is stopped on that branch. + * @param {Function} fn The function to call + * @param {Object} scope (optional) The scope of the function (defaults to current component) + * @param {Array} args (optional) The args to call the function with (defaults to passing the current component) + * @return {Ext.Container} this + */ + cascade : function(fn, scope, args){ + if(fn.apply(scope || this, args || [this]) !== false){ + if(this.items){ + var cs = this.items.items; + for(var i = 0, len = cs.length; i < len; i++){ + if(cs[i].cascade){ + cs[i].cascade(fn, scope, args); + }else{ + fn.apply(scope || cs[i], args || [cs[i]]); + } + } + } + } + return this; + }, + + /** + * Find a component under this container at any level by id + * @param {String} id + * @return Ext.Component + */ + findById : function(id){ + var m, ct = this; + this.cascade(function(c){ + if(ct != c && c.id === id){ + m = c; + return false; + } + }); + return m || null; + }, + + /** + * Find a component under this container at any level by xtype or class + * @param {String/Class} xtype The xtype string for a component, or the class of the component directly + * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is + * the default), or true to check whether this Component is directly of the specified xtype. + * @return {Array} Array of Ext.Components + */ + findByType : function(xtype, shallow){ + return this.findBy(function(c){ + return c.isXType(xtype, shallow); + }); + }, + + /** + * Find a component under this container at any level by property + * @param {String} prop + * @param {String} value + * @return {Array} Array of Ext.Components + */ + find : function(prop, value){ + return this.findBy(function(c){ + return c[prop] === value; + }); + }, + + /** + * Find a component under this container at any level by a custom function. If the passed function returns + * true, the component will be included in the results. The passed function is called with the arguments (component, this container). + * @param {Function} fn The function to call + * @param {Object} scope (optional) + * @return {Array} Array of Ext.Components + */ + findBy : function(fn, scope){ + var m = [], ct = this; + this.cascade(function(c){ + if(ct != c && fn.call(scope || c, c, ct) === true){ + m.push(c); + } + }); + return m; + }, + + /** + * Get a component contained by this container (alias for items.get(key)) + * @param {String/Number} key The index or id of the component + * @return {Ext.Component} Ext.Component + */ + get : function(key){ + return this.items.get(key); + } +}); + +Ext.Container.LAYOUTS = {}; +Ext.reg('container', Ext.Container); /** * @class Ext.layout.ContainerLayout *
The ContainerLayout class is the default layout manager delegated by {@link Ext.Container} to @@ -4500,7 +4583,7 @@ Ext.layout.ContainerLayout.prototype = { c.render(target, position); this.configureItem(c, position); }else if(c && !this.isValidParent(c, target)){ - if(typeof position == 'number'){ + if(Ext.isNumber(position)){ position = target.dom.childNodes[position]; } target.dom.insertBefore(c.getDomPositionEl().dom, position || null); @@ -4518,47 +4601,60 @@ Ext.layout.ContainerLayout.prototype = { if (this.renderHidden && c != this.activeItem) { c.hide(); } - if(c.doLayout){ - c.doLayout(false, this.forceLayout); + if(c.doLayout && this.forceLayout){ + c.doLayout(false, true); + } + }, + + onRemove: function(c){ + if(this.activeItem == c){ + delete this.activeItem; + } + if(c.rendered && this.extraCls){ + var t = c.getPositionEl ? c.getPositionEl() : c; + t.removeClass(this.extraCls); } }, // private onResize: function(){ - if(this.container.collapsed){ + var ct = this.container, + b; + + if(ct.collapsed){ return; } - var b = this.container.bufferResize; - if(b){ - if(!this.resizeTask){ - this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this); - this.resizeBuffer = typeof b == 'number' ? b : 100; + if(b = ct.bufferResize){ + // Only allow if we should buffer the layout + if(ct.shouldBufferLayout()){ + if(!this.resizeTask){ + this.resizeTask = new Ext.util.DelayedTask(this.runLayout, this); + this.resizeBuffer = Ext.isNumber(b) ? b : 50; + } + ct.layoutPending = true; + this.resizeTask.delay(this.resizeBuffer); } - this.resizeTask.delay(this.resizeBuffer); }else{ - this.runLayout(); + ct.doLayout(); } }, // private runLayout: function(){ - this.layout(); - this.container.onLayout(); + var ct = this.container; + ct.doLayout(); + delete ct.layoutPending; }, // private setContainer : function(ct){ if(this.monitorResize && ct != this.container){ - if(this.container){ - this.container.un('resize', this.onResize, this); - this.container.un('bodyresize', this.onResize, this); + var old = this.container; + if(old){ + old.un(old.resizeEvent, this.onResize, this); } if(ct){ - ct.on({ - scope: this, - resize: this.onResize, - bodyresize: this.onResize - }); + ct.on(ct.resizeEvent, this.onResize, this); } } this.container = ct; @@ -4566,7 +4662,7 @@ Ext.layout.ContainerLayout.prototype = { // private parseMargins : function(v){ - if(typeof v == 'number'){ + if(Ext.isNumber(v)){ v = v.toString(); } var ms = v.split(' '); @@ -4592,7 +4688,7 @@ Ext.layout.ContainerLayout.prototype = { }, /** - * The {@link Template Ext.Template} used by Field rendering layout classes (such as + * The {@link Ext.Template Ext.Template} used by Field rendering layout classes (such as * {@link Ext.layout.FormLayout}) to create the DOM structure of a fully wrapped, * labeled and styled form Field. A default Template is supplied, but this may be * overriden to create custom field structures. The template processes values returned from @@ -4762,10 +4858,11 @@ Ext.layout.CardLayout = Ext.extend(Ext.layout.FitLayout, { if(this.activeItem){ this.activeItem.hide(); } + var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered); this.activeItem = item; item.show(); - this.container.doLayout(); - if(this.layoutOnCardChange && item.doLayout){ + this.layout(); + if(layout){ item.doLayout(); } } @@ -5196,8 +5293,8 @@ Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, { } c.collapsed = false; if(!c.rendered){ - c.cls = c.cls ? c.cls +' x-border-panel' : 'x-border-panel'; c.render(target, i); + c.getDomPositionEl().addClass('x-border-panel'); } this[pos] = pos != 'center' && c.split ? new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) : @@ -6307,7 +6404,33 @@ Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, { * @type String * @property labelStyle */ + + /** + * @cfg {Boolean} trackLabels + * True to show/hide the field label when the field is hidden. Defaults to false. + */ + trackLabels: false, + + onRemove: function(c){ + Ext.layout.FormLayout.superclass.onRemove.call(this, c); + if(this.trackLabels && !this.isHide(c)){ + c.un('show', this.onFieldShow, this); + c.un('hide', this.onFieldHide, this); + } + // check for itemCt, since we may be removing a fieldset or something similar + var el = c.getPositionEl(), + ct = c.getItemCt && c.getItemCt(); + if(c.rendered && ct){ + el.insertAfter(ct); + Ext.destroy(ct); + Ext.destroyMembers(c, 'label', 'itemCt'); + if(c.customItemCt){ + Ext.destroyMembers(c, 'getItemCt', 'customItemCt'); + } + } + }, + // private setContainer : function(ct){ Ext.layout.FormLayout.superclass.setContainer.call(this, ct); @@ -6316,25 +6439,43 @@ Ext.layout.FormLayout = Ext.extend(Ext.layout.AnchorLayout, { } if(ct.hideLabels){ - this.labelStyle = "display:none"; - this.elementStyle = "padding-left:0;"; - this.labelAdjust = 0; + Ext.apply(this, { + labelStyle: 'display:none', + elementStyle: 'padding-left:0;', + labelAdjust: 0 + }); }else{ this.labelSeparator = ct.labelSeparator || this.labelSeparator; ct.labelWidth = ct.labelWidth || 100; - if(typeof ct.labelWidth == 'number'){ - var pad = (typeof ct.labelPad == 'number' ? ct.labelPad : 5); - this.labelAdjust = ct.labelWidth+pad; - this.labelStyle = "width:"+ct.labelWidth+"px;"; - this.elementStyle = "padding-left:"+(ct.labelWidth+pad)+'px'; + if(Ext.isNumber(ct.labelWidth)){ + var pad = Ext.isNumber(ct.labelPad) ? ct.labelPad : 5; + Ext.apply(this, { + labelAdjust: ct.labelWidth + pad, + labelStyle: 'width:' + ct.labelWidth + 'px;', + elementStyle: 'padding-left:' + (ct.labelWidth + pad) + 'px' + }); } if(ct.labelAlign == 'top'){ - this.labelStyle = "width:auto;"; - this.labelAdjust = 0; - this.elementStyle = "padding-left:0;"; + Ext.apply(this, { + labelStyle: 'width:auto;', + labelAdjust: 0, + elementStyle: 'padding-left:0;' + }); } } }, + + isHide: function(c){ + return c.hideLabel || this.container.hideLabels; + }, + + onFieldShow: function(c){ + c.getItemCt().removeClass('x-hide-' + c.hideMode); + }, + + onFieldHide: function(c){ + c.getItemCt().addClass('x-hide-' + c.hideMode); + }, //private getLabelStyle: function(s){ @@ -6386,17 +6527,43 @@ new Ext.Template( // private renderItem : function(c, position, target){ - if(c && !c.rendered && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){ + if(c && (c.isFormField || c.fieldLabel) && c.inputType != 'hidden'){ var args = this.getTemplateArgs(c); - if(typeof position == 'number'){ + if(Ext.isNumber(position)){ position = target.dom.childNodes[position] || null; } if(position){ - this.fieldTpl.insertBefore(position, args); + c.itemCt = this.fieldTpl.insertBefore(position, args, true); }else{ - this.fieldTpl.append(target, args); + c.itemCt = this.fieldTpl.append(target, args, true); + } + if(!c.rendered){ + c.render('x-form-el-' + c.id); + }else if(!this.isValidParent(c, target)){ + Ext.fly('x-form-el-' + c.id).appendChild(c.getPositionEl()); + } + if(!c.getItemCt){ + // Non form fields don't have getItemCt, apply it here + // This will get cleaned up in onRemove + Ext.apply(c, { + getItemCt: function(){ + return c.itemCt; + }, + customItemCt: true + }); + } + c.label = c.getItemCt().child('label.x-form-item-label'); + if(this.trackLabels && !this.isHide(c)){ + if(c.hidden){ + this.onFieldHide(c); + } + c.on({ + scope: this, + show: this.onFieldShow, + hide: this.onFieldHide + }); } - c.render('x-form-el-'+c.id); + this.configureItem(c); }else { Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments); } @@ -6432,22 +6599,33 @@ new Ext.Template( return { id: field.id, label: field.fieldLabel, - labelStyle: field.labelStyle||this.labelStyle||'', + labelStyle: this.getLabelStyle(field.labelStyle), elementStyle: this.elementStyle||'', - labelSeparator: noLabelSep ? '' : (typeof field.labelSeparator == 'undefined' ? this.labelSeparator : field.labelSeparator), + labelSeparator: noLabelSep ? '' : (Ext.isDefined(field.labelSeparator) ? field.labelSeparator : this.labelSeparator), itemCls: (field.itemCls||this.container.itemCls||'') + (field.hideLabel ? ' x-hide-label' : ''), clearCls: field.clearCls || 'x-form-clear-left' }; }, // private - adjustWidthAnchor : function(value, comp){ - return value - (comp.isFormField || comp.fieldLabel ? (comp.hideLabel ? 0 : this.labelAdjust) : 0); + adjustWidthAnchor: function(value, c){ + if(c.label && !this.isHide(c) && (this.container.labelAlign != 'top')){ + var adjust = Ext.isIE6 || (Ext.isIE && !Ext.isStrict); + return value - this.labelAdjust + (adjust ? -3 : 0); + } + return value; + }, + + adjustHeightAnchor : function(value, c){ + if(c.label && !this.isHide(c) && (this.container.labelAlign == 'top')){ + return value - c.label.getHeight(); + } + return value; }, // private isValidParent : function(c, target){ - return true; + return target && this.container.getEl().contains(c.getDomPositionEl()); } /** @@ -6459,8 +6637,9 @@ new Ext.Template( Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;/** * @class Ext.layout.AccordionLayout * @extends Ext.layout.FitLayout - *
This is a layout that contains multiple panels in an expandable accordion style such that only - * one panel can be open at any given time. Each panel has built-in support for expanding and collapsing. + *
This is a layout that manages multiple Panels in an expandable accordion style such that only + * one Panel can be expanded at any given time. Each Panel has built-in support for expanding and collapsing.
+ *Note: Only Ext.Panels and all subclasses of Ext.Panel may be used in an accordion layout Container.
*This class is intended to be extended or created via the {@link Ext.Container#layout layout} * configuration property. See {@link Ext.Container#layout} for additional details.
*Example usage:
@@ -6569,6 +6748,14 @@ Ext.layout.AccordionLayout = Ext.extend(Ext.layout.FitLayout, { c.header.addClass('x-accordion-hd'); c.on('beforeexpand', this.beforeExpand, this); }, + + onRemove: function(c){ + Ext.layout.AccordionLayout.superclass.onRemove.call(this, c); + if(c.rendered){ + c.header.removeClass('x-accordion-hd'); + } + c.un('beforeexpand', this.beforeExpand, this); + }, // private beforeExpand : function(p, anim){ @@ -6795,16 +6982,18 @@ Ext.layout.TableLayout = Ext.extend(Ext.layout.ContainerLayout, { renderItem : function(c, position, target){ if(c && !c.rendered){ c.render(this.getNextCell(c)); - if(this.extraCls){ - var t = c.getPositionEl ? c.getPositionEl() : c; - t.addClass(this.extraCls); - } + this.configureItem(c, position); + }else if(c && !this.isValidParent(c, target)){ + var container = this.getNextCell(c); + container.insertBefore(c.getDomPositionEl().dom, null); + c.container = Ext.get(container); + this.configureItem(c, position); } }, // private isValidParent : function(c, target){ - return true; + return c.getDomPositionEl().up('table', 5).dom.parentNode === (target.dom || target); } /** @@ -6927,8 +7116,20 @@ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, { defaultMargins : {left:0,top:0,right:0,bottom:0}, /** * @cfg {String} padding - * Defaults to '0'. Sets the padding to be applied to all child items managed by this - * container's layout. + *Sets the padding to be applied to all child items managed by this layout.
+ *This property must be specified as a string containing + * space-separated, numeric padding values. The order of the sides associated + * with each value matches the way CSS processes padding values:
+ *Defaults to: "0"
A layout that arranges items vertically down a Container. This layout optionally divides available vertical
+ * space between child items containing a numeric flex
configuration.
A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal
+ * space between child items containing a numeric flex
configuration.
When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.Container#add adding} Components
* to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether
- * those child elements need to be sized using one of Ext's built-in {@link Ext.Container#layout layout} schemes. By
+ * those child elements need to be sized using one of Ext's built-in {@link Ext.Container#layout layout}
schemes. By
* default, Panels use the {@link Ext.layout.ContainerLayout ContainerLayout} scheme. This simply renders
* child components, appending them one after the other inside the Container, and does not apply any sizing
* at all.
This Element is used to house the {@link #title} and {@link #tools}
- *Note: see the Note for {@link Ext.Component#el el} also.
+ *Note: see the Note for {@link Ext.Component#el el}
also.
If this Panel is intended to be used as the host of a Layout (See {@link #layout}
* then the body Element must not be loaded or changed - it is under the control
* of the Panel's Layout.
- *
Note: see the Note for {@link Ext.Component#el el} also.
+ *Note: see the Note for {@link Ext.Component#el el}
also.
A {@link Ext.DomHelper DomHelper} element specification object may be specified for any * Panel Element.
*By default, the Default element in the table below will be used for the html markup to - * create a child element with the commensurate Default class name (baseCls will be - * replaced by {@link #baseCls}):
+ * create a child element with the commensurate Default class name (baseCls
will be
+ * replaced by {@link #baseCls}
):
* * Panel Default Default Custom Additional Additional * Element element class element class style @@ -7515,51 +7727,51 @@ new Ext.Panel({ footerStyle: 'background-color:red' // see {@link #bodyStyle} }); *- *
The example above also explicitly creates a {@link #footer} with custom markup and + *
The example above also explicitly creates a {@link #footer}
with custom markup and
* styling applied.
A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure - * of this Panel's {@link #header} Element. See {@link #bodyCfg} also.
+ * of this Panel's {@link #header} Element. See{@link #bodyCfg}
also.
*/
/**
* @cfg {Object} bwrapCfg
* A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure - * of this Panel's {@link #bwrap} Element. See {@link #bodyCfg} also.
+ * of this Panel's {@link #bwrap} Element. See{@link #bodyCfg}
also.
*/
/**
* @cfg {Object} tbarCfg
* A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure - * of this Panel's {@link #tbar} Element. See {@link #bodyCfg} also.
+ * of this Panel's {@link #tbar} Element. See{@link #bodyCfg}
also.
*/
/**
* @cfg {Object} bbarCfg
* A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure - * of this Panel's {@link #bbar} Element. See {@link #bodyCfg} also.
+ * of this Panel's {@link #bbar} Element. See{@link #bodyCfg}
also.
*/
/**
* @cfg {Object} footerCfg
* A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure - * of this Panel's {@link #footer} Element. See {@link #bodyCfg} also.
+ * of this Panel's {@link #footer} Element. See{@link #bodyCfg}
also.
*/
/**
* @cfg {Boolean} closable
* Panels themselves do not directly support being closed, but some Panel subclasses do (like
- * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}. Specify true
- * to enable closing in such situations. Defaults to false.
+ * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}. Specify true
+ * to enable closing in such situations. Defaults to false
.
*/
/**
* The Panel's footer {@link Ext.Element Element}. Read-only.
- * This Element is used to house the Panel's {@link #buttons} or {@link #fbar}.
- *Note: see the Note for {@link Ext.Component#el el} also.
+ *This Element is used to house the Panel's {@link #buttons}
or {@link #fbar}
.
Note: see the Note for {@link Ext.Component#el el}
also.
The id of the node, a DOM node or an existing Element corresponding to a DIV that is already present in
- * the document that specifies some panel-specific structural markup. When applyTo is used,
+ * the document that specifies some panel-specific structural markup. When applyTo
is used,
* constituent parts of the panel can be specified by CSS class name within the main element, and the panel
* will automatically create those components from that markup. Any required components not specified in the
* markup will be autogenerated if necessary.
The bottom toolbar of the panel. This can be a {@link Ext.Toolbar} object, a toolbar config, or an array of * buttons/button configs to be added to the toolbar. Note that this is not available as a property after render. * To access the bottom toolbar after render, use {@link #getBottomToolbar}.
- *Note: Although a Toolbar may contain Field components, these will not be updated by a load + *
Note: Although a Toolbar may contain Field components, these will not be updated by a load * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and * so are not scanned to collect form items. However, the values will be submitted because form * submission parameters are collected from the DOM tree.
@@ -7599,8 +7811,8 @@ new Ext.Panel({ *A {@link Ext.Toolbar Toolbar} object, a Toolbar config, or an array of * {@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.
*After render, the fbar
property will be an {@link Ext.Toolbar Toolbar} instance.
If {@link #buttons} are specified, they will supersede the fbar configuration property.
- * The Panel's {@link #buttonAlign} configuration affects the layout of these items, for example: + *If {@link #buttons}
are specified, they will supersede the fbar
configuration property.
{@link #buttonAlign}
configuration affects the layout of these items, for example:
*
var w = new Ext.Window({
height: 250,
@@ -7612,7 +7824,7 @@ var w = new Ext.Window({
text: 'bbar Right'
}]
}),
- {@link #buttonAlign}: 'left', // anything but 'center' or 'right' and you can use "-", and "->"
+ {@link #buttonAlign}: 'left', // anything but 'center' or 'right' and you can use '-', and '->'
// to control the alignment of fbar items
fbar: [{
text: 'fbar Left'
@@ -7621,40 +7833,40 @@ var w = new Ext.Window({
}]
}).show();
*
- * Note: Although a Toolbar may contain Field components, these will not be updated by a load + *
Note: Although a Toolbar may contain Field components, these will not be updated by a load * of an ancestor FormPanel. A Panel's toolbars are not part of the standard Container->Component hierarchy, and * so are not scanned to collect form items. However, the values will be submitted because form * submission parameters are collected from the DOM tree.
*/ /** * @cfg {Boolean} header - * true to create the Panel's header element explicitly, false to skip creating - * it. If a {@link #title} is set the header will be created automatically, otherwise it will not. - * If a {@link #title} is set but header is explicitly set to false, the header + *true
to create the Panel's header element explicitly, false
to skip creating
+ * it. If a {@link #title}
is set the header will be created automatically, otherwise it will not.
+ * If a {@link #title}
is set but header
is explicitly set to false
, the header
* will not be rendered.
*/
/**
* @cfg {Boolean} footer
- * true to create the footer element explicitly, false to skip creating it. The footer
- * will be created automatically if {@link #buttons} or a {@link #fbar} have
- * been configured. See {@link #bodyCfg} for an example.
+ * true
to create the footer element explicitly, false to skip creating it. The footer
+ * will be created automatically if {@link #buttons}
or a {@link #fbar}
have
+ * been configured. See {@link #bodyCfg}
for an example.
*/
/**
* @cfg {String} title
* The title text to be used as innerHTML (html tags are accepted) to display in the panel
- * {@link #header} (defaults to ''). When a title is specified the
- * {@link #header} element will automatically be created and displayed unless
- * {@link #header} is explicitly set to false. If you do not want to specify a
- * title at config time, but you may want one later, you must either specify a non-empty
- * title (a blank space ' ' will do) or header:true so that the container
+ * {@link #header}
(defaults to ''). When a title
is specified the
+ * {@link #header}
element will automatically be created and displayed unless
+ * {@link #header} is explicitly set to false
. If you do not want to specify a
+ * title
at config time, but you may want one later, you must either specify a non-empty
+ * title
(a blank space ' ' will do) or header:true
so that the container
* element will get created.
*/
/**
* @cfg {Array} buttons
- * buttons will be used as {@link Ext.Container#items items} for the toolbar in
- * the footer ({@link #fbar}). Typically the value of this configuration property will be
+ * buttons
will be used as {@link Ext.Container#items items}
for the toolbar in
+ * the footer ({@link #fbar}
). Typically the value of this configuration property will be
* an array of {@link Ext.Button}s or {@link Ext.Button} configuration objects.
- * If an item is configured with minWidth or the Panel is configured with minButtonWidth,
+ * If an item is configured with minWidth
or the Panel is configured with minButtonWidth
,
* that width will be applied to the item.
*/
/**
@@ -7667,7 +7879,7 @@ var w = new Ext.Window({
*/
/**
* @cfg {Boolean} frame
- * false by default to render with plain 1px square borders. true to render with
+ * false
by default to render with plain 1px square borders. true
to render with
* 9 elements, complete with custom rounded corners (also see {@link Ext.Element#boxWrap}).
* The template generated for each condition is depicted below:
*
@@ -7739,33 +7951,33 @@ var w = new Ext.Window({
/**
* @cfg {Array} tools
* An array of tool button configs to be added to the header tool area. When rendered, each tool is
- * stored as an {@link Ext.Element Element} referenced by a public property called tools.<tool-type>
+ * stored as an {@link Ext.Element Element} referenced by a public property called tools.<tool-type>
* Each tool config may contain the following properties:
*
* - id : StringRequired. The type
- * of tool to create. By default, this assigns a CSS class of the form x-tool-<tool-type> to the
+ * of tool to create. By default, this assigns a CSS class of the form
x-tool-<tool-type>
to the
* resulting tool Element. Ext provides CSS rules, and an icon sprite containing images for the tool types listed below.
* The developer may implement custom tools by supplying alternate CSS rules and background images:
*
- * toggle (Created by default when {@link #collapsible} is true)
- * close
- * minimize
- * maximize
- * restore
- * gear
- * pin
- * unpin
- * right
- * left
- * up
- * down
- * refresh
- * minus
- * plus
- * help
- * search
- * save
- * print
+ * toggle
(Created by default when {@link #collapsible} is true
)
+ * close
+ * minimize
+ * maximize
+ * restore
+ * gear
+ * pin
+ * unpin
+ * right
+ * left
+ * up
+ * down
+ * refresh
+ * minus
+ * plus
+ * help
+ * search
+ * save
+ * print
*
* - handler : FunctionRequired. The function to
* call when clicked. Arguments passed are:
@@ -7803,7 +8015,7 @@ tools:[{
}
}]
- * For the custom id of 'help' define two relevant css classes with a link to
+ *
For the custom id of 'help'
define two relevant css classes with a link to
* a 15x15 image:
*
.x-tool-help {background-image: url(images/help.png);}
@@ -7838,7 +8050,7 @@ var win = new Ext.Window({
height:300,
closeAction:'hide'
});
- * Note that the CSS class "x-tool-pdf" should have an associated style rule which provides an
+ *
Note that the CSS class 'x-tool-pdf' should have an associated style rule which provides an
* appropriate background image, something like:
a.x-tool-pdf {background-image: url(../shared/extjs/images/pdf.gif)!important;}
@@ -7846,56 +8058,56 @@ var win = new Ext.Window({
*/
/**
* @cfg {Boolean} hideCollapseTool
- * true to hide the expand/collapse toggle button when {@link #collapsible} == true
,
- * false to display it (defaults to false).
+ * true
to hide the expand/collapse toggle button when {@link #collapsible} == true
,
+ * false
to display it (defaults to false
).
*/
/**
* @cfg {Boolean} titleCollapse
- * true to allow expanding and collapsing the panel (when {@link #collapsible} = true)
- * by clicking anywhere in the header bar, false) to allow it only by clicking to tool button
- * (defaults to false)). If this panel is a child item of a border layout also see the
+ * true
to allow expanding and collapsing the panel (when {@link #collapsible} = true
)
+ * by clicking anywhere in the header bar, false
) to allow it only by clicking to tool button
+ * (defaults to false
)). If this panel is a child item of a border layout also see the
* {@link Ext.layout.BorderLayout.Region BorderLayout.Region}
- * {@link Ext.layout.BorderLayout.Region#floatable floatable} config option.
+ * {@link Ext.layout.BorderLayout.Region#floatable floatable}
config option.
*/
/**
* @cfg {Boolean} autoScroll
- * true to use overflow:'auto' on the panel's body element and show scroll bars automatically when
- * necessary, false to clip any overflowing content (defaults to false).
+ * true
to use overflow:'auto' on the panel's body element and show scroll bars automatically when
+ * necessary, false
to clip any overflowing content (defaults to false
).
*/
/**
* @cfg {Mixed} floating
* This property is used to configure the underlying {@link Ext.Layer}. Acceptable values for this
* configuration property are:
- * - false : Default.Display the panel inline where it is
+ *
false
: Default.Display the panel inline where it is
* rendered.
- * - true : Float the panel (absolute position it with automatic
+ *
true
: Float the panel (absolute position it with automatic
* shimming and shadow).
* Setting floating to true will create an Ext.Layer for this panel and display the
* panel at negative offsets so that it is hidden.
* Since the panel will be absolute positioned, the position must be set explicitly
- * after render (e.g., myPanel.setPosition(100,100);).
+ * after render (e.g., myPanel.setPosition(100,100);
).
* Note: when floating a panel you should always assign a fixed width,
* otherwise it will be auto width and will expand to fill to the right edge of the viewport.
*
- * - {@link Ext.Layer object} : The specified object will be used
+ *
{@link Ext.Layer object}
: The specified object will be used
* as the configuration object for the {@link Ext.Layer} that will be created.
*
*/
/**
* @cfg {Boolean/String} shadow
- * true (or a valid Ext.Shadow {@link Ext.Shadow#mode} value) to display a shadow behind the
- * panel, false to display no shadow (defaults to 'sides'). Note that this option
- * only applies when {@link #floating} = true.
+ * true
(or a valid Ext.Shadow {@link Ext.Shadow#mode} value) to display a shadow behind the
+ * panel, false
to display no shadow (defaults to 'sides'
). Note that this option
+ * only applies when {@link #floating} = true
.
*/
/**
* @cfg {Number} shadowOffset
- * The number of pixels to offset the shadow if displayed (defaults to 4). Note that this
- * option only applies when {@link #floating} = true.
+ * The number of pixels to offset the shadow if displayed (defaults to 4
). Note that this
+ * option only applies when {@link #floating} = true
.
*/
/**
* @cfg {Boolean} shim
- * false to disable the iframe shim in browsers which need one (defaults to true).
- * Note that this option only applies when {@link #floating} = true.
+ * false
to disable the iframe shim in browsers which need one (defaults to true
).
+ * Note that this option only applies when {@link #floating} = true
.
*/
/**
* @cfg {String/Object} html
@@ -7906,36 +8118,34 @@ var win = new Ext.Window({
*/
/**
* @cfg {String} contentEl
- * Specify the id of an existing HTML node to use as the panel's body content
- * (defaults to '').
- * - Description :
+ * Optional. Specify an existing HTML element, or the id
of an existing HTML element to use as this Panel's
+ * {@link #body}
content.
+ *
+ * - Description :
* This config option is used to take an existing HTML element and place it in the body
* of a new panel (it simply moves the specified DOM element into the body element of the Panel
- * when the Panel is rendered to use as the content (it is not going to be the
- * actual panel itself).
- *
- * - Notes :
- * The specified HTML Element is appended to the Panel's {@link #body} Element by the
- * Panel's {@link #afterRender} method after any configured {@link #html HTML} has
- * been inserted, and so the document will not contain this HTML at the time the
+ * after the Panel is rendered to use as the content (it is not going to be the actual panel itself).
+ * - Notes :
+ * The specified HTML element is appended to the Panel's {@link #body} Element by the
+ * Panel's
afterRender
method after any configured {@link #html HTML} has
+ * been inserted, and so the document will not contain this element at the time the
* {@link #render} event is fired.
- * The specified HTML element used will not participate in any layout scheme that the
- * Panel may use. It's just HTML. Layouts operate on child items.
- * Add either the x-hidden or the x-hide-display CSS class to
- * prevent a brief flicker of the content before it is rendered to the panel.
- *
- *
+ * The specified HTML element used will not participate in any {@link Ext.Container#layout layout}
+ * scheme that the Panel may use. It is just HTML. Layouts operate on child {@link Ext.Container#items items}
.
+ * Add either the x-hidden
or the x-hide-display
CSS class to
+ * prevent a brief flicker of the content before it is rendered to the panel.
+ *
*/
/**
* @cfg {Object/Array} keys
* A {@link Ext.KeyMap} config object (in the format expected by {@link Ext.KeyMap#addBinding}
- * used to assign custom key handling to this panel (defaults to null).
+ * used to assign custom key handling to this panel (defaults to null
).
*/
/**
* @cfg {Boolean/Object} draggable
- * true to enable dragging of this Panel (defaults to false).
+ * true
to enable dragging of this Panel (defaults to false
).
* For custom drag/drop implementations, an Ext.Panel.DD config could also be passed
- * in this config instead of true. Ext.Panel.DD is an internal, undocumented class which
+ * in this config instead of true
. Ext.Panel.DD is an internal, undocumented class which
* moves a proxy Element around in place of the Panel's element, but provides no other behaviour
* during dragging or on drop. It is a subclass of {@link Ext.dd.DragSource}, so behaviour may be
* added by implementing the interface methods of {@link Ext.dd.DragDrop} e.g.:
@@ -7977,15 +8187,9 @@ new Ext.Panel({
}).show();
*/
- /**
- * @cfg {String} tabTip
- * A string to be used as innerHTML (html tags are accepted) to show in a tooltip when mousing over
- * the tab of a Ext.Panel which is an item of a {@link Ext.TabPanel}. {@link Ext.QuickTips}.init()
- * must be called in order for the tips to render.
- */
/**
* @cfg {Boolean} disabled
- * Render this panel disabled (default is false). An important note when using the disabled
+ * Render this panel disabled (default is false
). An important note when using the disabled
* config on panels is that IE will often fail to initialize the disabled mask element correectly if
* the panel's layout has not yet completed by the time the Panel is disabled during the render process.
* If you experience this issue, you may need to instead use the {@link #afterlayout} event to initialize
@@ -8006,10 +8210,10 @@ new Ext.Panel({
*/
/**
* @cfg {Boolean} autoHeight
- * true to use height:'auto', false to use fixed height (defaults to false).
- * Note: Setting autoHeight:true means that the browser will manage the panel's height
+ * true
to use height:'auto', false
to use fixed height (defaults to false
).
+ * Note: Setting autoHeight: true
means that the browser will manage the panel's height
* based on its contents, and that Ext will not manage it at all. If the panel is within a layout that
- * manages dimensions (fit, border, etc.) then setting autoHeight:true
+ * manages dimensions (fit
, border
, etc.) then setting autoHeight: true
* can cause issues with scrolling and will not generally work as expected since the panel will take
* on the height of its contents rather than the height required by the Ext layout.
*/
@@ -8017,64 +8221,64 @@ new Ext.Panel({
/**
* @cfg {String} baseCls
- * The base CSS class to apply to this panel's element (defaults to 'x-panel').
- *
Another option available by default is to specify 'x-plain' which strips all styling
+ * The base CSS class to apply to this panel's element (defaults to 'x-panel'
).
+ *
Another option available by default is to specify 'x-plain'
which strips all styling
* except for required attributes for Ext layouts to function (e.g. overflow:hidden).
- * See {@link #unstyled} also.
+ * See {@link #unstyled}
also.
*/
baseCls : 'x-panel',
/**
* @cfg {String} collapsedCls
* A CSS class to add to the panel's element after it has been collapsed (defaults to
- * 'x-panel-collapsed').
+ * 'x-panel-collapsed'
).
*/
collapsedCls : 'x-panel-collapsed',
/**
* @cfg {Boolean} maskDisabled
- * true to mask the panel when it is {@link #disabled}, false to not mask it (defaults
- * to true). Either way, the panel will always tell its contained elements to disable themselves
+ * true
to mask the panel when it is {@link #disabled}, false
to not mask it (defaults
+ * to true
). Either way, the panel will always tell its contained elements to disable themselves
* when it is disabled, but masking the panel can provide an additional visual cue that the panel is
* disabled.
*/
maskDisabled : true,
/**
* @cfg {Boolean} animCollapse
- * true to animate the transition when the panel is collapsed, false to skip the
- * animation (defaults to true if the {@link Ext.Fx} class is available, otherwise false).
+ * true
to animate the transition when the panel is collapsed, false
to skip the
+ * animation (defaults to true
if the {@link Ext.Fx} class is available, otherwise false
).
*/
animCollapse : Ext.enableFx,
/**
* @cfg {Boolean} headerAsText
- * true to display the panel {@link #title} in the {@link #header},
- * false to hide it (defaults to true).
+ * true
to display the panel {@link #title}
in the {@link #header}
,
+ * false
to hide it (defaults to true
).
*/
headerAsText : true,
/**
* @cfg {String} buttonAlign
- * The alignment of any {@link #buttons} added to this panel. Valid values are 'right',
- * 'left' and 'center' (defaults to 'right').
+ * The alignment of any {@link #buttons} added to this panel. Valid values are 'right'
,
+ * 'left'
and 'center'
(defaults to 'right'
).
*/
buttonAlign : 'right',
/**
* @cfg {Boolean} collapsed
- * true to render the panel collapsed, false to render it expanded (defaults to
- * false).
+ * true
to render the panel collapsed, false
to render it expanded (defaults to
+ * false
).
*/
collapsed : false,
/**
* @cfg {Boolean} collapseFirst
- * true to make sure the collapse/expand toggle button always renders first (to the left of)
- * any other tools in the panel's title bar, false to render it last (defaults to true).
+ * true
to make sure the collapse/expand toggle button always renders first (to the left of)
+ * any other tools in the panel's title bar, false
to render it last (defaults to true
).
*/
collapseFirst : true,
/**
* @cfg {Number} minButtonWidth
- * Minimum width in pixels of all {@link #buttons} in this panel (defaults to 75)
+ * Minimum width in pixels of all {@link #buttons} in this panel (defaults to 75
)
*/
minButtonWidth : 75,
/**
* @cfg {Boolean} unstyled
- * Overrides the {@link #baseCls} setting to {@link #baseCls} = 'x-plain' which renders
+ * Overrides the {@link #baseCls}
setting to {@link #baseCls} = 'x-plain'
which renders
* the panel unstyled except for required attributes for Ext layouts to function (e.g. overflow:hidden).
*/
/**
@@ -8084,23 +8288,28 @@ new Ext.Panel({
* make sure a structural element is rendered even if not specified at config time (for example, you may want
* to add a button or toolbar dynamically after the panel has been rendered). Adding those elements to this
* list will allocate the required placeholders in the panel when it is rendered. Valid values are
- * - header
- * - tbar (top bar)
- * - body
- * - bbar (bottom bar)
- * - footer
+ * header
+ * tbar
(top bar)
+ * body
+ * bbar
(bottom bar)
+ * footer
*
- * Defaults to 'body'.
+ * Defaults to 'body
'.
*/
elements : 'body',
/**
* @cfg {Boolean} preventBodyReset
- * Defaults to false. When set to true, an extra css class 'x-panel-normal'
+ * Defaults to false
. When set to true
, an extra css class 'x-panel-normal'
* will be added to the panel's element, effectively applying css styles suggested by the W3C
* (see http://www.w3.org/TR/CSS21/sample.html) to the Panel's body element (not the header,
* footer, etc.).
*/
preventBodyReset : false,
+
+ /** @cfg {String} resizeEvent
+ * The event to listen to for resizing in layouts. Defaults to 'bodyresize'.
+ */
+ resizeEvent: 'bodyresize',
// protected - these could be used to customize the behavior of the window,
// but changing them would not be useful without further mofifications and
@@ -8247,21 +8456,21 @@ new Ext.Panel({
this.elements += ',footer';
var btns = this.buttons;
/**
- * This Panel's Array of buttons as created from the {@link #buttons}
+ * This Panel's Array of buttons as created from the {@link #buttons}
* config property. Read only.
* @type Array
* @property buttons
*/
this.buttons = [];
- for(var i = 0, len = btns.length; i < len; i++) {
- if(btns[i].render){ // button instance
- this.buttons.push(btns[i]);
- }else if(btns[i].xtype){
- this.buttons.push(Ext.create(btns[i], 'button'));
+ Ext.each(btns, function(btn){
+ if(btn.render){ // button instance
+ this.buttons.push(btn);
+ }else if(btn.xtype){
+ this.buttons.push(Ext.create(btn, 'button'));
}else{
- this.addButton(btns[i]);
+ this.addButton(btn);
}
- }
+ }, this);
}
if(this.fbar){
this.elements += ',footer';
@@ -8302,7 +8511,25 @@ new Ext.Panel({
var el = this.el,
d = el.dom,
- bw;
+ bw,
+ ts;
+
+
+ if(this.collapsible && !this.hideCollapseTool){
+ this.tools = this.tools ? this.tools.slice(0) : [];
+ this.tools[this.collapseFirst?'unshift':'push']({
+ id: 'toggle',
+ handler : this.toggleCollapse,
+ scope: this
+ });
+ }
+
+ if(this.tools){
+ ts = this.tools;
+ this.elements += (this.header !== false) ? ',header' : '';
+ }
+ this.tools = {};
+
el.addClass(this.baseCls);
if(d.firstChild){ // existing markup
this.header = el.down('.'+this.headerCls);
@@ -8349,6 +8576,13 @@ new Ext.Panel({
if(!this.footer){
this.bwrap.dom.lastChild.className += ' x-panel-nofooter';
}
+ /*
+ * Store a reference to this element so:
+ * a) We aren't looking it up all the time
+ * b) The last element is reported incorrectly when using a loadmask
+ */
+ this.ft = Ext.get(this.bwrap.dom.lastChild);
+ this.mc = Ext.get(this.bwrap.dom.firstChild.firstChild.firstChild);
}else{
this.createElement('header', d);
this.createElement('bwrap', d);
@@ -8368,7 +8602,7 @@ new Ext.Panel({
}
}
- if(this.padding !== undefined) {
+ if(Ext.isDefined(this.padding)){
this.body.setStyle('padding', this.body.addUnits(this.padding));
}
@@ -8413,26 +8647,12 @@ new Ext.Panel({
this.makeFloating(this.floating);
}
- if(this.collapsible){
- this.tools = this.tools ? this.tools.slice(0) : [];
- if(!this.hideCollapseTool){
- this.tools[this.collapseFirst?'unshift':'push']({
- id: 'toggle',
- handler : this.toggleCollapse,
- scope: this
- });
- }
- if(this.titleCollapse && this.header){
- this.mon(this.header, 'click', this.toggleCollapse, this);
- this.header.setStyle('cursor', 'pointer');
- }
+ if(this.collapsible && this.titleCollapse && this.header){
+ this.mon(this.header, 'click', this.toggleCollapse, this);
+ this.header.setStyle('cursor', 'pointer');
}
- if(this.tools){
- var ts = this.tools;
- this.tools = {};
+ if(ts){
this.addTool.apply(this, ts);
- }else{
- this.tools = {};
}
if(this.buttons && this.buttons.length > 0){
@@ -8479,13 +8699,6 @@ new Ext.Panel({
this.bottomToolbar.render(this.bbar);
this.toolbars.push(this.bottomToolbar);
}
- Ext.each(this.toolbars, function(tb){
- tb.on({
- scope: this,
- afterlayout: this.syncHeight,
- remove: this.syncHeight
- });
- }, this);
},
/**
@@ -8501,12 +8714,12 @@ new Ext.Panel({
this.header.addClass('x-panel-icon');
this.header.replaceClass(old, this.iconCls);
}else{
- var hd = this.header.dom;
- var img = hd.firstChild && String(hd.firstChild.tagName).toLowerCase() == 'img' ? hd.firstChild : null;
+ var hd = this.header,
+ img = hd.child('img.x-panel-inline-icon');
if(img){
Ext.fly(img).replaceClass(old, this.iconCls);
}else{
- Ext.DomHelper.insertBefore(hd.firstChild, {
+ Ext.DomHelper.insertBefore(hd.dom.firstChild, {
tag:'img', src: Ext.BLANK_IMAGE_URL, cls:'x-panel-inline-icon '+this.iconCls
});
}
@@ -8520,7 +8733,7 @@ new Ext.Panel({
this.floating = true;
this.el = new Ext.Layer(
Ext.isObject(cfg) ? cfg : {
- shadow: this.shadow !== undefined ? this.shadow : 'sides',
+ shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
shadowOffset: this.shadowOffset,
constrain:false,
shim: this.shim === false ? false : undefined
@@ -8529,7 +8742,7 @@ new Ext.Panel({
},
/**
- * Returns the {@link Ext.Toolbar toolbar} from the top ({@link #tbar}) section of the panel.
+ * Returns the {@link Ext.Toolbar toolbar} from the top ({@link #tbar}
) section of the panel.
* @return {Ext.Toolbar} The toolbar
*/
getTopToolbar : function(){
@@ -8537,7 +8750,7 @@ new Ext.Panel({
},
/**
- * Returns the {@link Ext.Toolbar toolbar} from the bottom ({@link #bbar}) section of the panel.
+ * Returns the {@link Ext.Toolbar toolbar} from the bottom ({@link #bbar}
) section of the panel.
* @return {Ext.Toolbar} The toolbar
*/
getBottomToolbar : function(){
@@ -8560,7 +8773,7 @@ new Ext.Panel({
minWidth: this.minButtonWidth,
hideParent:true
};
- if(typeof config == "string"){
+ if(Ext.isString(config)){
bc.text = config;
}else{
Ext.apply(bc, config);
@@ -8575,7 +8788,17 @@ new Ext.Panel({
// private
addTool : function(){
- if(!this[this.toolTarget]) { // no where to render tools!
+ if(!this.rendered){
+ if(!this.tools){
+ this.tools = [];
+ }
+ Ext.each(arguments, function(arg){
+ this.tools.push(arg)
+ }, this);
+ return;
+ }
+ // nowhere to render tools!
+ if(!this[this.toolTarget]){
return;
}
if(!this.toolTemplate){
@@ -8615,35 +8838,31 @@ new Ext.Panel({
}
},
- onLayout : function(){
- if(this.toolbars.length > 0){
- this.duringLayout = true;
+ onLayout : function(shallow, force){
+ if(this.hasLayout && this.toolbars.length > 0){
Ext.each(this.toolbars, function(tb){
- tb.doLayout();
+ tb.doLayout(undefined, force);
});
- delete this.duringLayout;
this.syncHeight();
}
},
syncHeight : function(){
- if(!(this.autoHeight || this.duringLayout)){
- var last = this.lastSize;
- if(last && !Ext.isEmpty(last.height)){
- var old = last.height, h = this.el.getHeight();
- if(old != 'auto' && old != h){
- var bd = this.body, bdh = bd.getHeight();
- h = Math.max(bdh + old - h, 0);
- if(bdh > 0 && bdh != h){
- bd.setHeight(h);
- if(Ext.isIE && h <= 0){
- return;
- }
- var sz = bd.getSize();
- this.fireEvent('bodyresize', sz.width, sz.height);
- }
- }
- }
+ var h = this.toolbarHeight,
+ bd = this.body,
+ lsh = this.lastSize.height;
+
+ if(this.autoHeight || !Ext.isDefined(lsh) || lsh == 'auto'){
+ return;
+ }
+
+
+ if(h != this.getToolbarHeight()){
+ h = Math.max(0, this.adjustBodyHeight(lsh - this.getFrameHeight()));
+ bd.setHeight(h);
+ sz = bd.getSize();
+ this.toolbarHeight = this.getToolbarHeight();
+ this.onBodyResize(sz.width, sz.height);
}
},
@@ -8730,6 +8949,19 @@ new Ext.Panel({
if(this.draggable){
this.initDraggable();
}
+ if(this.toolbars.length > 0){
+ Ext.each(this.toolbars, function(tb){
+ tb.doLayout();
+ tb.on({
+ scope: this,
+ afterlayout: this.syncHeight,
+ remove: this.syncHeight
+ });
+ }, this);
+ if(!this.ownerCt){
+ this.syncHeight();
+ }
+ }
},
// private
@@ -8742,21 +8974,25 @@ new Ext.Panel({
* @type Ext.dd.DragSource.
* @property dd
*/
- this.dd = new Ext.Panel.DD(this, typeof this.draggable == 'boolean' ? null : this.draggable);
+ this.dd = new Ext.Panel.DD(this, Ext.isBoolean(this.draggable) ? null : this.draggable);
},
// private
- beforeEffect : function(){
+ beforeEffect : function(anim){
if(this.floating){
this.el.beforeAction();
}
- this.el.addClass('x-panel-animated');
+ if(anim !== false){
+ this.el.addClass('x-panel-animated');
+ }
},
// private
- afterEffect : function(){
+ afterEffect : function(anim){
this.syncShadow();
- this.el.removeClass('x-panel-animated');
+ if(anim !== false){
+ this.el.removeClass('x-panel-animated');
+ }
},
// private - wraps up an animation param with internal callbacks
@@ -8791,7 +9027,7 @@ new Ext.Panel({
return;
}
var doAnim = animate === true || (animate !== false && this.animCollapse);
- this.beforeEffect();
+ this.beforeEffect(doAnim);
this.onCollapse(doAnim, animate);
return this;
},
@@ -8804,15 +9040,15 @@ new Ext.Panel({
this.collapseDefaults));
}else{
this[this.collapseEl].hide();
- this.afterCollapse();
+ this.afterCollapse(false);
}
},
// private
- afterCollapse : function(){
+ afterCollapse : function(anim){
this.collapsed = true;
this.el.addClass(this.collapsedCls);
- this.afterEffect();
+ this.afterEffect(anim);
this.fireEvent('collapse', this);
},
@@ -8829,7 +9065,7 @@ new Ext.Panel({
}
var doAnim = animate === true || (animate !== false && this.animCollapse);
this.el.removeClass(this.collapsedCls);
- this.beforeEffect();
+ this.beforeEffect(doAnim);
this.onExpand(doAnim, animate);
return this;
},
@@ -8842,15 +9078,15 @@ new Ext.Panel({
this.expandDefaults));
}else{
this[this.collapseEl].show();
- this.afterExpand();
+ this.afterExpand(false);
}
},
// private
- afterExpand : function(){
+ afterExpand : function(anim){
this.collapsed = false;
- this.afterEffect();
- if(this.deferLayout !== undefined){
+ this.afterEffect(anim);
+ if(Ext.isDefined(this.deferLayout)){
this.doLayout(true);
}
this.fireEvent('expand', this);
@@ -8885,9 +9121,9 @@ new Ext.Panel({
// private
onResize : function(w, h){
- if(w !== undefined || h !== undefined){
+ if(Ext.isDefined(w) || Ext.isDefined(h)){
if(!this.collapsed){
- if(typeof w == 'number'){
+ if(Ext.isNumber(w)){
w = this.adjustBodyWidth(w - this.getFrameWidth());
if(this.tbar){
this.tbar.setWidth(w);
@@ -8930,7 +9166,7 @@ new Ext.Panel({
this.body.setWidth(w);
}
- if(typeof h == 'number'){
+ if(Ext.isNumber(h)){
h = Math.max(0, this.adjustBodyHeight(h - this.getFrameHeight()));
this.body.setHeight(h);
}else if(h == 'auto'){
@@ -8951,10 +9187,26 @@ new Ext.Panel({
}, this, {single:true});
}
}
- this.fireEvent('bodyresize', this, w, h);
+ this.onBodyResize(w, h);
}
this.syncShadow();
},
+
+ // private
+ onBodyResize: function(w, h){
+ this.fireEvent('bodyresize', this, w, h);
+ },
+
+ // private
+ getToolbarHeight: function(){
+ var h = 0;
+ if(this.rendered){
+ Ext.each(this.toolbars, function(tb){
+ h += tb.getHeight();
+ }, this);
+ }
+ return h;
+ },
// private
adjustBodyHeight : function(h){
@@ -8977,13 +9229,12 @@ new Ext.Panel({
* @return {Number} The frame width
*/
getFrameWidth : function(){
- var w = this.el.getFrameWidth('lr')+this.bwrap.getFrameWidth('lr');
+ var w = this.el.getFrameWidth('lr') + this.bwrap.getFrameWidth('lr');
if(this.frame){
var l = this.bwrap.dom.firstChild;
w += (Ext.fly(l).getFrameWidth('l') + Ext.fly(l.firstChild).getFrameWidth('r'));
- var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
- w += Ext.fly(mc).getFrameWidth('lr');
+ w += this.mc.getFrameWidth('lr');
}
return w;
},
@@ -8994,16 +9245,12 @@ new Ext.Panel({
* @return {Number} The frame height
*/
getFrameHeight : function(){
- var h = this.el.getFrameWidth('tb')+this.bwrap.getFrameWidth('tb');
+ var h = this.el.getFrameWidth('tb') + this.bwrap.getFrameWidth('tb');
h += (this.tbar ? this.tbar.getHeight() : 0) +
(this.bbar ? this.bbar.getHeight() : 0);
if(this.frame){
- var hd = this.el.dom.firstChild;
- var ft = this.bwrap.dom.lastChild;
- h += (hd.offsetHeight + ft.offsetHeight);
- var mc = this.bwrap.dom.firstChild.firstChild.firstChild;
- h += Ext.fly(mc).getFrameWidth('tb');
+ h += this.el.dom.firstChild.offsetHeight + this.ft.dom.offsetHeight + this.mc.getFrameWidth('tb');
}else{
h += (this.header ? this.header.getHeight() : 0) +
(this.footer ? this.footer.getHeight() : 0);
@@ -9044,8 +9291,8 @@ new Ext.Panel({
/**
* Sets the title text for the panel and optionally the {@link #iconCls icon class}.
* In order to be able to set the title, a header element must have been created
- * for the Panel. This is triggered either by configuring the Panel with a non-blank {@link #title},
- * or configuring it with {@link #header}: true.
+ * for the Panel. This is triggered either by configuring the Panel with a non-blank {@link #title}
,
+ * or configuring it with {@link #header}: true
.
* @param {String} title The title text to set
* @param {String} iconCls (optional) {@link #iconCls iconCls} A user-defined CSS class that provides the icon image for this panel
*/
@@ -9074,13 +9321,13 @@ new Ext.Panel({
* @param {Object/String/Function} config A config object containing any of the following options:
panel.load({
- url: "your-url.php",
- params: {param1: "foo", param2: "bar"}, // or a URL encoded string
+ url: 'your-url.php',
+ params: {param1: 'foo', param2: 'bar'}, // or a URL encoded string
callback: yourFunction,
scope: yourObject, // optional scope for the callback
discardUrl: false,
nocache: false,
- text: "Loading...",
+ text: 'Loading...',
timeout: 30,
scripts: false
});
@@ -9105,6 +9352,8 @@ panel.load({
}
}
Ext.Element.uncache(
+ this.ft,
+ this.mc,
this.header,
this.tbar,
this.bbar,
@@ -9122,7 +9371,11 @@ panel.load({
Ext.destroy(this.buttons[b]);
}
}
- Ext.destroy(this.toolbars);
+ if(this.rendered){
+ Ext.destroy(this.toolbars);
+ }else{
+ Ext.destroy(this.topToolbar, this.bottomToolbar);
+ }
Ext.Panel.superclass.beforeDestroy.call(this);
},
@@ -9215,8 +9468,8 @@ Ext.extend(Ext.Editor, Ext.Component, {
*/
/**
* @cfg {Boolean/String} autoSize
- * True for the editor to automatically adopt the size of the element being edited, "width" to adopt the width only,
- * or "height" to adopt the height only (defaults to false)
+ * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only,
+ * or "height" to adopt the height only, "none" to always use the field dimensions. (defaults to false)
*/
/**
* @cfg {Boolean} revertInvalid
@@ -9257,13 +9510,13 @@ Ext.extend(Ext.Editor, Ext.Component, {
*/
swallowKeys : true,
/**
- * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed (defaults to false)
+ * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed. Defaults to true.
*/
- completeOnEnter : false,
+ completeOnEnter : true,
/**
- * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed (defaults to false)
+ * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed. Defaults to true.
*/
- cancelOnEsc : false,
+ cancelOnEsc : true,
/**
* @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
*/
@@ -9345,35 +9598,41 @@ Ext.extend(Ext.Editor, Ext.Component, {
this.field.msgTarget = 'qtip';
}
this.field.inEditor = true;
- this.field.render(this.el);
- if(Ext.isGecko){
- this.field.el.dom.setAttribute('autocomplete', 'off');
+ this.mon(this.field, {
+ scope: this,
+ blur: this.onBlur,
+ specialkey: this.onSpecialKey
+ });
+ if(this.field.grow){
+ this.mon(this.field, "autosize", this.el.sync, this.el, {delay:1});
}
- this.mon(this.field, "specialkey", this.onSpecialKey, this);
+ this.field.render(this.el).show();
+ this.field.getEl().dom.name = '';
if(this.swallowKeys){
- this.field.el.swallowEvent(['keydown','keypress']);
- }
- this.field.show();
- this.mon(this.field, "blur", this.onBlur, this);
- if(this.field.grow){
- this.mon(this.field, "autosize", this.el.sync, this.el, {delay:1});
+ this.field.el.swallowEvent([
+ 'keypress', // *** Opera
+ 'keydown' // *** all other browsers
+ ]);
}
},
// private
onSpecialKey : function(field, e){
- var key = e.getKey();
- if(this.completeOnEnter && key == e.ENTER){
+ var key = e.getKey(),
+ complete = this.completeOnEnter && key == e.ENTER,
+ cancel = this.cancelOnEsc && key == e.ESC;
+ if(complete || cancel){
e.stopEvent();
- this.completeEdit();
- }else if(this.cancelOnEsc && key == e.ESC){
- this.cancelEdit();
- }else{
- this.fireEvent('specialkey', field, e);
- }
- if(this.field.triggerBlur && (key == e.ENTER || key == e.ESC || key == e.TAB)){
- this.field.triggerBlur();
+ if(complete){
+ this.completeEdit();
+ }else{
+ this.cancelEdit();
+ }
+ if(field.triggerBlur){
+ field.triggerBlur();
+ }
}
+ this.fireEvent('specialkey', field, e);
},
/**
@@ -9391,30 +9650,34 @@ Ext.extend(Ext.Editor, Ext.Component, {
if(!this.rendered){
this.render(this.parentEl || document.body);
}
- if(this.fireEvent("beforestartedit", this, this.boundEl, v) === false){
- return;
+ if(this.fireEvent("beforestartedit", this, this.boundEl, v) !== false){
+ this.startValue = v;
+ this.field.setValue(v);
+ this.doAutoSize();
+ this.el.alignTo(this.boundEl, this.alignment);
+ this.editing = true;
+ this.show();
}
- this.startValue = v;
- this.field.setValue(v);
- this.doAutoSize();
- this.el.alignTo(this.boundEl, this.alignment);
- this.editing = true;
- this.show();
},
// private
doAutoSize : function(){
if(this.autoSize){
- var sz = this.boundEl.getSize();
+ var sz = this.boundEl.getSize(),
+ fs = this.field.getSize();
+
switch(this.autoSize){
case "width":
- this.setSize(sz.width, "");
- break;
+ this.setSize(sz.width, fs.height);
+ break;
case "height":
- this.setSize("", sz.height);
- break;
+ this.setSize(fs.width, sz.height);
+ break;
+ case "none":
+ this.setSize(fs.width, fs.height);
+ break;
default:
- this.setSize(sz.width, sz.height);
+ this.setSize(sz.width, sz.height);
}
}
},
@@ -9478,22 +9741,10 @@ Ext.extend(Ext.Editor, Ext.Component, {
if(this.hideEl !== false){
this.boundEl.hide();
}
- this.field.show();
- if(Ext.isIE && !this.fixIEFocus){ // IE has problems with focusing the first time
- this.fixIEFocus = true;
- this.deferredFocus.defer(50, this);
- }else{
- this.field.focus();
- }
+ this.field.show().focus(false, true);
this.fireEvent("startedit", this.boundEl, this.startValue);
},
- deferredFocus : function(){
- if(this.editing){
- this.field.focus();
- }
- },
-
/**
* Cancels the editing process and hides the editor without persisting any changes. The field value will be
* reverted to the original starting value.
@@ -9592,7 +9843,7 @@ Ext.ColorPalette = function(config){
);
if(this.handler){
- this.on("select", this.handler, this.scope, true);
+ this.on('select', this.handler, this.scope, true);
}
};
Ext.extend(Ext.ColorPalette, Ext.Component, {
@@ -9601,18 +9852,18 @@ Ext.extend(Ext.ColorPalette, Ext.Component, {
*/
/**
* @cfg {String} itemCls
- * The CSS class to apply to the containing element (defaults to "x-color-palette")
+ * The CSS class to apply to the containing element (defaults to 'x-color-palette')
*/
- itemCls : "x-color-palette",
+ itemCls : 'x-color-palette',
/**
* @cfg {String} value
* The initial color to highlight (should be a valid 6-digit color hex code without the # symbol). Note that
* the hex codes are case-sensitive.
*/
value : null,
- clickEvent:'click',
+ clickEvent :'click',
// private
- ctype: "Ext.ColorPalette",
+ ctype : 'Ext.ColorPalette',
/**
* @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the {@link #select} event
@@ -9627,30 +9878,44 @@ Ext.extend(Ext.ColorPalette, Ext.Component, {
* You can override individual colors if needed:
*
var cp = new Ext.ColorPalette();
-cp.colors[0] = "FF0000"; // change the first box to red
+cp.colors[0] = 'FF0000'; // change the first box to red
Or you can provide a custom array of your own for complete control:
var cp = new Ext.ColorPalette();
-cp.colors = ["000000", "993300", "333300"];
+cp.colors = ['000000', '993300', '333300'];
* @type Array
*/
colors : [
- "000000", "993300", "333300", "003300", "003366", "000080", "333399", "333333",
- "800000", "FF6600", "808000", "008000", "008080", "0000FF", "666699", "808080",
- "FF0000", "FF9900", "99CC00", "339966", "33CCCC", "3366FF", "800080", "969696",
- "FF00FF", "FFCC00", "FFFF00", "00FF00", "00FFFF", "00CCFF", "993366", "C0C0C0",
- "FF99CC", "FFCC99", "FFFF99", "CCFFCC", "CCFFFF", "99CCFF", "CC99FF", "FFFFFF"
+ '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
+ '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
+ 'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
+ 'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
+ 'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
],
+ /**
+ * @cfg {Function} handler
+ * Optional. A function that will handle the select event of this palette.
+ * The handler is passed the following parameters:
+ * palette
: ColorPaletteThe {@link #palette Ext.ColorPalette}.
+ * color
: StringThe 6-digit color hex code (without the # symbol).
+ *
+ */
+ /**
+ * @cfg {Object} scope
+ * The scope (this reference) in which the {@link #handler}
+ * function will be called. Defaults to this ColorPalette instance.
+ */
+
// private
onRender : function(container, position){
var t = this.tpl || new Ext.XTemplate(
' '
);
- var el = document.createElement("div");
+ var el = document.createElement('div');
el.id = this.getId();
el.className = this.itemCls;
t.overwrite(el, this.colors);
@@ -9686,15 +9951,15 @@ cp.colors = ["000000", "993300", "333300"];
* @param {String} color A valid 6-digit color hex code (# will be stripped if included)
*/
select : function(color){
- color = color.replace("#", "");
+ color = color.replace('#', '');
if(color != this.value || this.allowReselect){
var el = this.el;
if(this.value){
- el.child("a.color-"+this.value).removeClass("x-color-palette-sel");
+ el.child('a.color-'+this.value).removeClass('x-color-palette-sel');
}
- el.child("a.color-"+color).addClass("x-color-palette-sel");
+ el.child('a.color-'+color).addClass('x-color-palette-sel');
this.value = color;
- this.fireEvent("select", this, color);
+ this.fireEvent('select', this, color);
}
}
@@ -9702,7 +9967,8 @@ cp.colors = ["000000", "993300", "333300"];
* @cfg {String} autoEl @hide
*/
});
-Ext.reg('colorpalette', Ext.ColorPalette);/**
+Ext.reg('colorpalette', Ext.ColorPalette);
+/**
* @class Ext.DatePicker
* @extends Ext.Component
* Simple date picker class.
@@ -9727,6 +9993,19 @@ Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
* The text to display on the cancel button (defaults to 'Cancel')
*/
cancelText : 'Cancel',
+ /**
+ * @cfg {Function} handler
+ * Optional. A function that will handle the select event of this picker.
+ * The handler is passed the following parameters:
+ * picker
: DatePickerThe Ext.DatePicker.
+ * date
: DateThe selected date.
+ *
+ */
+ /**
+ * @cfg {Object} scope
+ * The scope (this reference) in which the {@link #handler}
+ * function will be called. Defaults to this DatePicker instance.
+ */
/**
* @cfg {String} todayTip
* The tooltip to display for the button that selects the current date (defaults to '{current date} (Spacebar)')
@@ -9833,7 +10112,7 @@ Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
Ext.DatePicker.superclass.initComponent.call(this);
this.value = this.value ?
- this.value.clearTime() : new Date().clearTime();
+ this.value.clearTime(true) : new Date().clearTime();
this.addEvents(
/**
@@ -9918,11 +10197,8 @@ Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
* @param {Date} value The date to set
*/
setValue : function(value){
- var old = this.value;
this.value = value.clearTime(true);
- if(this.el){
- this.update(this.value);
- }
+ this.update(this.value);
},
/**
@@ -9935,9 +10211,7 @@ Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
// private
focus : function(){
- if(this.el){
- this.update(this.activeDate);
- }
+ this.update(this.activeDate);
},
// private
@@ -9952,7 +10226,7 @@ Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
},
// private
- onDisable: function(){
+ onDisable : function(){
Ext.DatePicker.superclass.onDisable.call(this);
this.doDisabled(true);
if(Ext.isIE && !Ext.isIE8){
@@ -9967,7 +10241,7 @@ Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
},
// private
- doDisabled: function(disabled){
+ doDisabled : function(disabled){
this.keyNav.setDisabled(disabled);
this.prevRepeater.setDisabled(disabled);
this.nextRepeater.setDisabled(disabled);
@@ -10306,142 +10580,142 @@ Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
// private
update : function(date, forceRefresh){
- var vd = this.activeDate, vis = this.isVisible();
- this.activeDate = date;
- if(!forceRefresh && vd && this.el){
- var t = date.getTime();
- if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
- this.cells.removeClass('x-date-selected');
- this.cells.each(function(c){
- if(c.dom.firstChild.dateValue == t){
- c.addClass('x-date-selected');
- if(vis){
- Ext.fly(c.dom.firstChild).focus(50);
- }
- return false;
- }
- });
- return;
- }
- }
- var days = date.getDaysInMonth();
- var firstOfMonth = date.getFirstDateOfMonth();
- var startingPos = firstOfMonth.getDay()-this.startDay;
-
- if(startingPos <= this.startDay){
- startingPos += 7;
- }
-
- var pm = date.add('mo', -1);
- var prevStart = pm.getDaysInMonth()-startingPos;
-
- var cells = this.cells.elements;
- var textEls = this.textNodes;
- days += startingPos;
-
- // convert everything to numbers so it's fast
- var day = 86400000;
- var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
- var today = new Date().clearTime().getTime();
- var sel = date.clearTime().getTime();
- var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
- var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
- var ddMatch = this.disabledDatesRE;
- var ddText = this.disabledDatesText;
- var ddays = this.disabledDays ? this.disabledDays.join('') : false;
- var ddaysText = this.disabledDaysText;
- var format = this.format;
-
- if(this.showToday){
- var td = new Date().clearTime();
- var disable = (td < min || td > max ||
- (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
- (ddays && ddays.indexOf(td.getDay()) != -1));
-
- if(!this.disabled){
- this.todayBtn.setDisabled(disable);
- this.todayKeyListener[disable ? 'disable' : 'enable']();
- }
- }
-
- var setCellClass = function(cal, cell){
- cell.title = '';
- var t = d.getTime();
- cell.firstChild.dateValue = t;
- if(t == today){
- cell.className += ' x-date-today';
- cell.title = cal.todayText;
- }
- if(t == sel){
- cell.className += ' x-date-selected';
- if(vis){
- Ext.fly(cell.firstChild).focus(50);
- }
- }
- // disabling
- if(t < min) {
- cell.className = ' x-date-disabled';
- cell.title = cal.minText;
- return;
- }
- if(t > max) {
- cell.className = ' x-date-disabled';
- cell.title = cal.maxText;
- return;
- }
- if(ddays){
- if(ddays.indexOf(d.getDay()) != -1){
- cell.title = ddaysText;
- cell.className = ' x-date-disabled';
- }
- }
- if(ddMatch && format){
- var fvalue = d.dateFormat(format);
- if(ddMatch.test(fvalue)){
- cell.title = ddText.replace('%0', fvalue);
- cell.className = ' x-date-disabled';
- }
- }
- };
-
- var i = 0;
- for(; i < startingPos; i++) {
- textEls[i].innerHTML = (++prevStart);
- d.setDate(d.getDate()+1);
- cells[i].className = 'x-date-prevday';
- setCellClass(this, cells[i]);
- }
- for(; i < days; i++){
- var intDay = i - startingPos + 1;
- textEls[i].innerHTML = (intDay);
- d.setDate(d.getDate()+1);
- cells[i].className = 'x-date-active';
- setCellClass(this, cells[i]);
- }
- var extraDays = 0;
- for(; i < 42; i++) {
- textEls[i].innerHTML = (++extraDays);
- d.setDate(d.getDate()+1);
- cells[i].className = 'x-date-nextday';
- setCellClass(this, cells[i]);
- }
-
- this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
-
- if(!this.internalRender){
- var main = this.el.dom.firstChild;
- var w = main.offsetWidth;
- this.el.setWidth(w + this.el.getBorderWidth('lr'));
- Ext.fly(main).setWidth(w);
- this.internalRender = true;
- // opera does not respect the auto grow header center column
- // then, after it gets a width opera refuses to recalculate
- // without a second pass
- if(Ext.isOpera && !this.secondPass){
- main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
- this.secondPass = true;
- this.update.defer(10, this, [date]);
- }
+ if(this.rendered){
+ var vd = this.activeDate, vis = this.isVisible();
+ this.activeDate = date;
+ if(!forceRefresh && vd && this.el){
+ var t = date.getTime();
+ if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
+ this.cells.removeClass('x-date-selected');
+ this.cells.each(function(c){
+ if(c.dom.firstChild.dateValue == t){
+ c.addClass('x-date-selected');
+ if(vis){
+ Ext.fly(c.dom.firstChild).focus(50);
+ }
+ return false;
+ }
+ });
+ return;
+ }
+ }
+ var days = date.getDaysInMonth(),
+ firstOfMonth = date.getFirstDateOfMonth(),
+ startingPos = firstOfMonth.getDay()-this.startDay;
+
+ if(startingPos < 0){
+ startingPos += 7;
+ }
+ days += startingPos;
+
+ var pm = date.add('mo', -1),
+ prevStart = pm.getDaysInMonth()-startingPos,
+ cells = this.cells.elements,
+ textEls = this.textNodes,
+ // convert everything to numbers so it's fast
+ day = 86400000,
+ d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime(),
+ today = new Date().clearTime().getTime(),
+ sel = date.clearTime(true).getTime(),
+ min = this.minDate ? this.minDate.clearTime(true) : Number.NEGATIVE_INFINITY,
+ max = this.maxDate ? this.maxDate.clearTime(true) : Number.POSITIVE_INFINITY,
+ ddMatch = this.disabledDatesRE,
+ ddText = this.disabledDatesText,
+ ddays = this.disabledDays ? this.disabledDays.join('') : false,
+ ddaysText = this.disabledDaysText,
+ format = this.format;
+
+ if(this.showToday){
+ var td = new Date().clearTime(),
+ disable = (td < min || td > max ||
+ (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||
+ (ddays && ddays.indexOf(td.getDay()) != -1));
+
+ if(!this.disabled){
+ this.todayBtn.setDisabled(disable);
+ this.todayKeyListener[disable ? 'disable' : 'enable']();
+ }
+ }
+
+ var setCellClass = function(cal, cell){
+ cell.title = '';
+ var t = d.getTime();
+ cell.firstChild.dateValue = t;
+ if(t == today){
+ cell.className += ' x-date-today';
+ cell.title = cal.todayText;
+ }
+ if(t == sel){
+ cell.className += ' x-date-selected';
+ if(vis){
+ Ext.fly(cell.firstChild).focus(50);
+ }
+ }
+ // disabling
+ if(t < min) {
+ cell.className = ' x-date-disabled';
+ cell.title = cal.minText;
+ return;
+ }
+ if(t > max) {
+ cell.className = ' x-date-disabled';
+ cell.title = cal.maxText;
+ return;
+ }
+ if(ddays){
+ if(ddays.indexOf(d.getDay()) != -1){
+ cell.title = ddaysText;
+ cell.className = ' x-date-disabled';
+ }
+ }
+ if(ddMatch && format){
+ var fvalue = d.dateFormat(format);
+ if(ddMatch.test(fvalue)){
+ cell.title = ddText.replace('%0', fvalue);
+ cell.className = ' x-date-disabled';
+ }
+ }
+ };
+
+ var i = 0;
+ for(; i < startingPos; i++) {
+ textEls[i].innerHTML = (++prevStart);
+ d.setDate(d.getDate()+1);
+ cells[i].className = 'x-date-prevday';
+ setCellClass(this, cells[i]);
+ }
+ for(; i < days; i++){
+ var intDay = i - startingPos + 1;
+ textEls[i].innerHTML = (intDay);
+ d.setDate(d.getDate()+1);
+ cells[i].className = 'x-date-active';
+ setCellClass(this, cells[i]);
+ }
+ var extraDays = 0;
+ for(; i < 42; i++) {
+ textEls[i].innerHTML = (++extraDays);
+ d.setDate(d.getDate()+1);
+ cells[i].className = 'x-date-nextday';
+ setCellClass(this, cells[i]);
+ }
+
+ this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());
+
+ if(!this.internalRender){
+ var main = this.el.dom.firstChild,
+ w = main.offsetWidth;
+ this.el.setWidth(w + this.el.getBorderWidth('lr'));
+ Ext.fly(main).setWidth(w);
+ this.internalRender = true;
+ // opera does not respect the auto grow header center column
+ // then, after it gets a width opera refuses to recalculate
+ // without a second pass
+ if(Ext.isOpera && !this.secondPass){
+ main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';
+ this.secondPass = true;
+ this.update.defer(10, this, [date]);
+ }
+ }
}
},
@@ -11195,6 +11469,7 @@ myAction.on('complete', function(){
this.waitTimer = Ext.TaskMgr.start({
run: function(i){
var inc = o.increment || 10;
+ i -= 1;
this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);
},
interval: o.interval || 1000,