/*!
- * Ext JS Library 3.0.0
+ * Ext JS Library 3.1.0
* Copyright(c) 2006-2009 Ext JS, LLC
* licensing@extjs.com
* http://www.extjs.com/license
* {@link Ext.Component#id id} (see {@link #get}, or the convenience method {@link Ext#getCmp Ext.getCmp}).</p>
* <p>This object also provides a registry of available Component <i>classes</i>
* indexed by a mnemonic code known as the Component's {@link Ext.Component#xtype xtype}.
- * The <tt>{@link Ext.Component#xtype xtype}</tt> provides a way to avoid instantiating child Components
+ * The <code>{@link Ext.Component#xtype xtype}</code> provides a way to avoid instantiating child Components
* when creating a full, nested config object for a complete Ext page.</p>
* <p>A child Component may be specified simply as a <i>config object</i>
- * as long as the correct <tt>{@link Ext.Component#xtype xtype}</tt> is specified so that if and when the Component
+ * as long as the correct <code>{@link Ext.Component#xtype xtype}</code> is specified so that if and when the Component
* needs rendering, the correct type can be looked up for lazy instantiation.</p>
- * <p>For a list of all available <tt>{@link Ext.Component#xtype xtypes}</tt>, see {@link Ext.Component}.</p>
+ * <p>For a list of all available <code>{@link Ext.Component#xtype xtypes}</code>, see {@link Ext.Component}.</p>
* @singleton
*/
Ext.ComponentMgr = function(){
* Returns a component by {@link Ext.Component#id id}.
* For additional details see {@link Ext.util.MixedCollection#get}.
* @param {String} id The component {@link Ext.Component#id id}
- * @return Ext.Component The Component, <tt>undefined</tt> if not found, or <tt>null</tt> if a
+ * @return Ext.Component The Component, <code>undefined</code> if not found, or <code>null</code> if a
* Class was found.
*/
get : function(id){
},
/**
- * Registers a function that will be called when a specified component is added to ComponentMgr
+ * Registers a function that will be called when a Component with the specified id is added to ComponentMgr. This will happen on instantiation.
* @param {String} id The component {@link Ext.Component#id id}
* @param {Function} fn The callback function
- * @param {Object} scope The scope of the callback
+ * @param {Object} scope The scope (<code>this</code> reference) in which the callback is executed. Defaults to the Component.
*/
onAvailable : function(id, fn, scope){
all.on("add", function(index, o){
* 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 <tt>xtype</tt>. (Optional if the config contains a <tt>xtype</tt>).
+ * the config object does not contain a <code>xtype</code>. (Optional if the config contains a <code>xtype</code>).
* @return {Ext.Component} The newly instantiated Component.
*/
create : function(config, defaultType){
* 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 <tt>ptype</tt>. (Optional if the config contains a <tt>ptype</tt>).
+ * the config object does not contain a <code>ptype</code>. (Optional if the config contains a <code>ptype</code>).
* @return {Ext.Component} The newly instantiated Plugin.
*/
createPlugin : function(config, defaultType){
- return new ptypes[config.ptype || defaultType](config);
+ var PluginCls = ptypes[config.ptype || defaultType];
+ if (PluginCls.init) {
+ return PluginCls;
+ } else {
+ return new PluginCls(config);
+ }
}
};
}();
* @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 <code>xtype</code>. (Optional if the config contains a <code>xtype</code>).
+ * @return {Ext.Component} The newly instantiated Component.
+ * @member Ext
+ * @method create
+ */
+Ext.create = Ext.ComponentMgr.create;/**
* @class Ext.Component
* @extends Ext.util.Observable
* <p>Base class for all Ext components. All subclasses of Component may participate in the automated
Form components
---------------------------------------
-form {@link Ext.FormPanel}
+form {@link Ext.form.FormPanel}
checkbox {@link Ext.form.Checkbox}
checkboxgroup {@link Ext.form.CheckboxGroup}
combo {@link Ext.form.ComboBox}
Ext.apply(this, config);
this.addEvents(
+ /**
+ * @event added
+ * Fires when a component is added to an Ext.Container
+ * @param {Ext.Component} this
+ * @param {Ext.Container} ownerCt Container which holds the component
+ * @param {number} index Position at which the component was added
+ */
+ 'added',
/**
* @event disable
* Fires after the component is disabled.
* @param {Ext.Component} this
*/
'hide',
+ /**
+ * @event removed
+ * Fires when a component is removed from an Ext.Container
+ * @param {Ext.Component} this
+ * @param {Ext.Container} ownerCt Container which holds the component
+ */
+ 'removed',
/**
* @event beforerender
* Fires before the component is {@link #rendered}. Return false from an
}
if(this.stateful !== false){
- this.initState(config);
+ this.initState();
}
if(this.applyTo){
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 <p>The label text to display next to this Component (defaults to '').</p>
* <br><p><b>Note</b>: this config is only used when this Component is rendered by a Container which
* <p>See {@link Ext.layout.FormLayout}.{@link Ext.layout.FormLayout#fieldTpl fieldTpl} also.</p>
*/
/**
- * @cfg {String} itemCls <p>An additional CSS class to apply to the div wrapping the form item
+ * @cfg {String} itemCls
+ * <p><b>Note</b>: this config is only used when this Component is rendered by a Container which
+ * has been configured to use the <b>{@link Ext.layout.FormLayout FormLayout}</b> layout manager (e.g.
+ * {@link Ext.form.FormPanel} or specifying <tt>layout:'form'</tt>).</p><br>
+ * <p>An additional CSS class to apply to the div wrapping the form item
* element of this field. If supplied, <tt>itemCls</tt> at the <b>field</b> level will override
* the default <tt>itemCls</tt> supplied at the <b>container</b> level. The value specified for
* <tt>itemCls</tt> will be added to the default class (<tt>'x-form-item'</tt>).</p>
* any other element within the markup for the field.</p>
* <br><p><b>Note</b>: see the note for <tt>{@link #fieldLabel}</tt>.</p><br>
* Example use:<pre><code>
-// 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'
+ }]
});
</code></pre>
*/
- // 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 <p><b>Note</b>: this config is only used when this Component is rendered
* by a Container which has been configured to use an <b>{@link Ext.layout.AnchorLayout AnchorLayout}</b>
* @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.
- * <p><b>Note</b>: to access items within the container see <tt>{@link #itemId}</tt>.</p>
+ * 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.
+ * <p><b>Note</b>: to access items within the Container see <tt>{@link #itemId}</tt>.</p>
* @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,
+ /**
+ * @cfg {String} contentEl
+ * <p>Optional. Specify an existing HTML element, or the <code>id</code> of an existing HTML element to use as the content
+ * for this component.</p>
+ * <ul>
+ * <li><b>Description</b> :
+ * <div class="sub-desc">This config option is used to take an existing HTML element and place it in the layout element
+ * of a new component (it simply moves the specified DOM element <i>after the Component is rendered</i> to use as the content.</div></li>
+ * <li><b>Notes</b> :
+ * <div class="sub-desc">The specified HTML element is appended to the layout element of the component <i>after any configured
+ * {@link #html HTML} has been inserted</i>, and so the document will not contain this element at the time the {@link #render} event is fired.</div>
+ * <div class="sub-desc">The specified HTML element used will not participate in any <code><b>{@link Ext.Container#layout layout}</b></code>
+ * scheme that the Component may use. It is just HTML. Layouts operate on child <code><b>{@link Ext.Container#items items}</b></code>.</div>
+ * <div class="sub-desc">Add either the <code>x-hidden</code> or the <code>x-hide-display</code> CSS class to
+ * prevent a brief flicker of the content before it is rendered to the panel.</div></li>
+ * </ul>
+ */
+ /**
+ * @cfg {String/Object} html
+ * An HTML fragment, or a {@link Ext.DomHelper DomHelper} specification to use as the layout element
+ * content (defaults to ''). The HTML content is added after the component is rendered,
+ * so the document will not contain this HTML at the time the {@link #render} event is fired.
+ * This content is inserted into the body <i>before</i> any configured {@link #contentEl} is appended.
+ */
+
+ /**
+ * @cfg {Mixed} tpl
+ * An <bold>{@link Ext.Template}</bold>, <bold>{@link Ext.XTemplate}</bold>
+ * or an array of strings to form an Ext.XTemplate.
+ * Used in conjunction with the <code>{@link #data}</code> and
+ * <code>{@link #tplWriteMode}</code> configurations.
+ */
+
+ /**
+ * @cfg {String} tplWriteMode The Ext.(X)Template method to use when
+ * updating the content area of the Component. Defaults to <tt>'overwrite'</tt>
+ * (see <code>{@link Ext.XTemplate#overwrite}</code>).
+ */
+ tplWriteMode : 'overwrite',
+
+ /**
+ * @cfg {Mixed} data
+ * The initial set of data to apply to the <code>{@link #tpl}</code> to
+ * update the content area of the Component.
+ */
+
+
// private
ctype : 'Ext.Component',
this.el.addClassOnOver(this.overCls);
}
this.fireEvent('render', this);
+
+
+ // Populate content of the component with html, contentEl or
+ // a tpl.
+ var contentTarget = this.getContentTarget();
+ if (this.html){
+ contentTarget.update(Ext.DomHelper.markup(this.html));
+ delete this.html;
+ }
+ if (this.contentEl){
+ var ce = Ext.getDom(this.contentEl);
+ Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
+ contentTarget.appendChild(ce);
+ }
+ if (this.tpl) {
+ if (!this.tpl.compile) {
+ this.tpl = new Ext.XTemplate(this.tpl);
+ }
+ if (this.data) {
+ this.tpl[this.tplWriteMode](contentTarget, this.data);
+ delete this.data;
+ }
+ }
this.afterRender(this.container);
+
+
if(this.hidden){
// call this so we don't fire initial hide events.
this.doHide();
if(this.stateful !== false){
this.initStateEvents();
}
- this.initRef();
this.fireEvent('afterrender', this);
}
return this;
},
- initRef : function(){
+
+ /**
+ * Update the content area of a component.
+ * @param {Mixed} htmlOrData
+ * If this component has been configured with a template via the tpl config
+ * then it will use this argument as data to populate the template.
+ * If this component was not configured with a template, the components
+ * content area will be updated via Ext.Element update
+ * @param {Boolean} loadScripts
+ * (optional) Only legitimate when using the html configuration. Defaults to false
+ * @param {Function} callback
+ * (optional) Only legitimate when using the html configuration. Callback to execute when scripts have finished loading
+ */
+ update: function(htmlOrData, loadScripts, cb) {
+ var contentTarget = this.getContentTarget();
+ if (this.tpl && typeof htmlOrData !== "string") {
+ this.tpl[this.tplWriteMode](contentTarget, htmlOrData || {});
+ } else {
+ var html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
+ contentTarget.update(html, loadScripts, cb);
+ }
+ },
+
+
+ /**
+ * @private
+ * Method to manage awareness of when components are added to their
+ * respective Container, firing an added event.
+ * References are established at add time rather than at render time.
+ * @param {Ext.Container} container Container which holds the component
+ * @param {number} pos Position at which the component was added
+ */
+ onAdded : function(container, pos) {
+ this.ownerCt = container;
+ this.initRef();
+ this.fireEvent('added', this, container, pos);
+ },
+
+ /**
+ * @private
+ * Method to manage awareness of when components are removed from their
+ * respective Container, firing an removed event. References are properly
+ * cleaned up after removing a component from its owning container.
+ */
+ onRemoved : function() {
+ this.removeRef();
+ this.fireEvent('removed', this, this.ownerCt);
+ delete this.ownerCt;
+ },
+
+ /**
+ * @private
+ * Method to establish a reference to a component.
+ */
+ initRef : function() {
/**
* @cfg {String} ref
- * <p>A path specification, relative to the Component's {@link #ownerCt} specifying into which
- * ancestor Container to place a named reference to this Component.</p>
+ * <p>A path specification, relative to the Component's <code>{@link #ownerCt}</code>
+ * specifying into which ancestor Container to place a named reference to this Component.</p>
* <p>The ancestor axis can be traversed by using '/' characters in the path.
* For example, to put a reference to a Toolbar Button into <i>the Panel which owns the Toolbar</i>:</p><pre><code>
var myGrid = new Ext.grid.EditorGridPanel({
}
});
</code></pre>
- * <p>In the code above, if the ref had been <code>'saveButton'</code> the reference would
- * have been placed into the Toolbar. Each '/' in the ref moves up one level from the
- * Component's {@link #ownerCt}.</p>
+ * <p>In the code above, if the <code>ref</code> had been <code>'saveButton'</code>
+ * the reference would have been placed into the Toolbar. Each '/' in the <code>ref</code>
+ * moves up one level from the Component's <code>{@link #ownerCt}</code>.</p>
+ * <p>Also see the <code>{@link #added}</code> and <code>{@link #removed}</code> events.</p>
*/
- if(this.ref){
- var levels = this.ref.split('/');
- var last = levels.length, i = 0;
- var t = this;
- while(i < last){
- if(t.ownerCt){
- t = t.ownerCt;
- }
- i++;
+ if(this.ref && !this.refOwner){
+ var levels = this.ref.split('/'),
+ last = levels.length,
+ i = 0,
+ t = this;
+
+ while(t && i < last){
+ t = t.ownerCt;
+ ++i;
+ }
+ if(t){
+ t[this.refName = levels[--i]] = this;
+ /**
+ * @type Ext.Container
+ * @property refOwner
+ * The ancestor Container into which the {@link #ref} reference was inserted if this Component
+ * is a child of a Container, and has been configured with a <code>ref</code>.
+ */
+ this.refOwner = t;
}
- t[levels[--i]] = this;
+ }
+ },
+
+ removeRef : function() {
+ if (this.refOwner && this.refName) {
+ delete this.refOwner[this.refName];
+ delete this.refOwner;
}
},
// private
- initState : function(config){
+ initState : function(){
if(Ext.state.Manager){
var id = this.getStateId();
if(id){
var state = Ext.state.Manager.get(id);
if(state){
if(this.fireEvent('beforestaterestore', this, state) !== false){
- this.applyState(state);
+ this.applyState(Ext.apply({}, state));
this.fireEvent('staterestore', this, state);
}
}
},
// private
- applyState : function(state, config){
+ applyState : function(state){
if(state){
Ext.apply(this, state);
}
this.el = Ext.get(this.el);
if(this.allowDomMove !== false){
ct.dom.insertBefore(this.el.dom, position);
+ if (div) {
+ Ext.removeNode(div);
+ div = null;
+ }
}
}
},
*
*/
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.destroying = true;
+ this.beforeDestroy();
+ if(this.ownerCt && this.ownerCt.remove){
+ this.ownerCt.remove(this, false);
+ }
+ if(this.rendered){
+ 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.destroying = false;
+ this.isDestroyed = true;
}
- this.onDestroy();
- Ext.ComponentMgr.unregister(this);
- this.fireEvent('destroy', this);
- this.purgeListeners();
+ }
+ },
+
+ deleteMembers : function(){
+ var args = arguments;
+ for(var i = 0, len = args.length; i < len; ++i){
+ delete this[args[i]];
}
},
return this.el;
},
+ // private
+ getContentTarget : function(){
+ return this.el;
+ },
+
/**
* Returns the <code>id</code> of this component or automatically generates and
* returns an <code>id</code> if an <code>id</code> is not defined yet:<pre><code>
// private
onShow : function(){
- this.getVisibiltyEl().removeClass('x-hide-' + this.hideMode);
+ this.getVisibilityEl().removeClass('x-hide-' + this.hideMode);
},
/**
// 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();
},
* @return {Boolean} True if this component is visible, false otherwise.
*/
isVisible : function(){
- return this.rendered && this.getVisibiltyEl().isVisible();
+ return this.rendered && this.getVisibilityEl().isVisible();
},
/**
});
},
- getDomPositionEl : function(){
- return this.getPositionEl ? this.getPositionEl() : this.getEl();
+ // protected
+ getPositionEl : function(){
+ return this.positionEl || this.el;
},
// private
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});
}
+ },
+ /**
+ * <p>Adds listeners to any Observable object (or Elements) which are automatically removed when this Component
+ * is destroyed. Usage:</p><code><pre>
+myGridPanel.mon(myGridPanel.getSelectionModel(), 'selectionchange', handleSelectionChange, null, {buffer: 50});
+</pre></code>
+ * <p>or:</p><code><pre>
+myGridPanel.mon(myGridPanel.getSelectionModel(), {
+ selectionchange: handleSelectionChange,
+ buffer: 50
+});
+</pre></code>
+ * @param {Observable|Element} item The item to which to add a listener/listeners.
+ * @param {Object|String} ename The event name, or an object containing event name properties.
+ * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this
+ * is the handler function.
+ * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this
+ * is the scope (<code>this</code> reference) in which the handler function is executed.
+ * @param {Object} opt Optional. If the <code>ename</code> parameter was an event name, this
+ * is the {@link Ext.util.Observable#addListener addListener} options.
+ */
+ 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){
}
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
});
item.on(ename, fn, scope, opt);
},
- // protected, opposite of mon
+ /**
+ * Removes listeners that were added by the {@link #mon} method.
+ * @param {Observable|Element} item The item from which to remove a listener/listeners.
+ * @param {Object|String} ename The event name, or an object containing event name properties.
+ * @param {Function} fn Optional. If the <code>ename</code> parameter was an event name, this
+ * is the handler function.
+ * @param {Object} scope Optional. If the <code>ename</code> parameter was an event name, this
+ * is the scope (<code>this</code> reference) in which the handler function is executed.
+ */
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){
}
});
-Ext.reg('component', Ext.Component);
-/**\r
+Ext.reg('component', Ext.Component);/**\r
* @class Ext.Action\r
* <p>An Action is a piece of reusable functionality that can be abstracted out of any particular component so that it\r
* can be usefully shared among multiple components. Actions let you share handlers, configuration options and UI\r
* @constructor\r
* @param {Object} config The configuration options\r
*/\r
-Ext.Action = function(config){\r
- this.initialConfig = config;\r
- this.itemId = config.itemId = (config.itemId || config.id || Ext.id());\r
- this.items = [];\r
-}\r
-\r
-Ext.Action.prototype = {\r
+Ext.Action = Ext.extend(Object, {\r
/**\r
* @cfg {String} text The text to set for all components using this action (defaults to '').\r
*/\r
* See {@link Ext.Component}.{@link Ext.Component#itemId itemId}.\r
*/\r
/**\r
- * @cfg {Object} scope The scope in which the {@link #handler} function will execute.\r
+ * @cfg {Object} scope The scope (<tt><b>this</b></tt> reference) in which the\r
+ * <code>{@link #handler}</code> is executed. Defaults to this Button.\r
*/\r
\r
+ constructor : function(config){\r
+ this.initialConfig = config;\r
+ this.itemId = config.itemId = (config.itemId || config.id || Ext.id());\r
+ this.items = [];\r
+ },\r
+ \r
// private\r
isAction : true,\r
\r
},\r
\r
/**\r
- * Sets the function that will be called by each component using this action when its primary event is triggered.\r
+ * Sets the function that will be called by each Component using this action when its primary event is triggered.\r
* @param {Function} fn The function that will be invoked by the action's components. The function\r
* will be called with no arguments.\r
- * @param {Object} scope The scope in which the function will execute\r
+ * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed. Defaults to the Component firing the event.\r
*/\r
setHandler : function(fn, scope){\r
this.initialConfig.handler = fn;\r
},\r
\r
/**\r
- * Executes the specified function once for each component currently tied to this action. The function passed\r
+ * Executes the specified function once for each Component currently tied to this action. The function passed\r
* in should accept a single argument that will be an object that supports the basic Action config/method interface.\r
* @param {Function} fn The function to execute for each component\r
- * @param {Object} scope The scope in which the function will execute\r
+ * @param {Object} scope The scope (<code>this</code> reference) in which the function is executed. Defaults to the Component.\r
*/\r
each : function(fn, scope){\r
Ext.each(this.items, fn, scope);\r
execute : function(){\r
this.initialConfig.handler.apply(this.initialConfig.scope || window, arguments);\r
}\r
-};
+});\r
/**
* @class Ext.Layer
* @extends Ext.Element
}
this.removeAllListeners();
Ext.removeNode(this.dom);
- Ext.Element.uncache(this.id);
+ delete this.dom;
},
remove : function(){
return this;
}
});
-})();/**
+})();
+/**
* @class Ext.Shadow
* Simple class that can provide a shadow effect for any element. Note that the element MUST be absolutely positioned,
* and the shadow does not provide any shimming. This should be used only in simple cases -- for more advanced
*/
Ext.BoxComponent = Ext.extend(Ext.Component, {
+ // tabTip config is used when a BoxComponent is a child of a TabPanel
+ /**
+ * @cfg {String} tabTip
+ * <p><b>Note</b>: this config is only used when this BoxComponent is a child item of a TabPanel.</p>
+ * 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} region <p><b>Note</b>: this config is only used when this BoxComponent is rendered
* The width of this component in pixels (defaults to auto).
* <b>Note</b> to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
*/
+ /**
+ * @cfg {Number} boxMinHeight
+ * <p>The minimum value in pixels which this BoxComponent will set its height to.</p>
+ * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
+ */
+ /**
+ * @cfg {Number} boxMinWidth
+ * <p>The minimum value in pixels which this BoxComponent will set its width to.</p>
+ * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
+ */
+ /**
+ * @cfg {Number} boxMaxHeight
+ * <p>The maximum value in pixels which this BoxComponent will set its height to.</p>
+ * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
+ */
+ /**
+ * @cfg {Number} boxMaxWidth
+ * <p>The maximum value in pixels which this BoxComponent will set its width to.</p>
+ * <p><b>Warning:</b> This will override any size management applied by layout managers.</p>
+ */
/**
* @cfg {Boolean} autoHeight
* <p>True to use height:'auto', false to use fixed height (or allow it to be managed by its parent
});
</code></pre>
*/
+ /**
+ * @cfg {Boolean} autoScroll
+ * <code>true</code> to use overflow:'auto' on the components layout element and show scroll bars automatically when
+ * necessary, <code>false</code> to clip any overflowing content (defaults to <code>false</code>).
+ */
/* // private internal config
* {Boolean} deferHeight
* @return {Ext.BoxComponent} this
*/
setSize : function(w, h){
+
// support for standard size objects
if(typeof w == 'object'){
- h = w.height;
- w = w.width;
+ h = w.height, w = w.width;
+ }
+ if (Ext.isDefined(w) && Ext.isDefined(this.boxMinWidth) && (w < this.boxMinWidth)) {
+ w = this.boxMinWidth;
+ }
+ if (Ext.isDefined(h) && Ext.isDefined(this.boxMinHeight) && (h < this.boxMinHeight)) {
+ h = this.boxMinHeight;
+ }
+ if (Ext.isDefined(w) && Ext.isDefined(this.boxMaxWidth) && (w > this.boxMaxWidth)) {
+ w = this.boxMaxWidth;
+ }
+ if (Ext.isDefined(h) && Ext.isDefined(this.boxMaxHeight) && (h > this.boxMaxHeight)) {
+ h = this.boxMaxHeight;
}
// not rendered
if(!this.boxReady){
- this.width = w;
- this.height = h;
+ this.width = w, this.height = h;
return this;
}
return this;
}
this.lastSize = {width: w, height: h};
- var adj = this.adjustSize(w, h);
- var aw = adj.width, ah = adj.height;
+ var adj = this.adjustSize(w, h),
+ aw = adj.width,
+ ah = adj.height,
+ rz;
if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
- var rz = this.getResizeEl();
+ rz = this.getResizeEl();
if(!this.deferHeight && aw !== undefined && ah !== undefined){
rz.setSize(aw, ah);
}else if(!this.deferHeight && ah !== undefined){
rz.setWidth(aw);
}
this.onResize(aw, ah, w, h);
- this.fireEvent('resize', this, aw, ah, w, h);
}
return this;
},
* contains both the <code><input></code> Element (which is what would be returned
* by its <code>{@link #getEl}</code> method, <i>and</i> the trigger button Element.
* This Element is returned as the <code>resizeEl</code>.
+ * @return {Ext.Element} The Element which is to be resized by size managing layouts.
*/
getResizeEl : function(){
return this.resizeEl || this.el;
},
- // protected
- getPositionEl : function(){
- return this.positionEl || this.el;
+ /**
+ * Sets the overflow on the content element of the component.
+ * @param {Boolean} scroll True to allow the Component to auto scroll.
+ * @return {Ext.BoxComponent} this
+ */
+ setAutoScroll : function(scroll){
+ if(this.rendered){
+ this.getContentTarget().setOverflow(scroll ? 'auto' : '');
+ }
+ this.autoScroll = scroll;
+ return this;
},
/**
},
// 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.setAutoScroll(this.autoScroll);
this.setSize(this.width, this.height);
if(this.x || this.y){
this.setPosition(this.x, this.y);
* @param {Number} rawHeight The height that was originally specified
*/
onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
-
+ this.fireEvent('resize', this, adjWidth, adjHeight, rawWidth, rawHeight);
},
/* // protected
* @param {Mixed} dragElement The element to be dragged and act as the SplitBar.\r
* @param {Mixed} resizingElement The element to be resized based on where the SplitBar element is dragged\r
* @param {Number} orientation (optional) Either Ext.SplitBar.HORIZONTAL or Ext.SplitBar.VERTICAL. (Defaults to HORIZONTAL)\r
- * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or \r
+ * @param {Number} placement (optional) Either Ext.SplitBar.LEFT or Ext.SplitBar.RIGHT for horizontal or\r
Ext.SplitBar.TOP or Ext.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial\r
position of the SplitBar).\r
*/\r
Ext.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){\r
- \r
+\r
/** @private */\r
this.el = Ext.get(dragElement, true);\r
this.el.dom.unselectable = "on";\r
* @type Number\r
*/\r
this.orientation = orientation || Ext.SplitBar.HORIZONTAL;\r
- \r
+\r
/**\r
* The increment, in pixels by which to move this SplitBar. When <i>undefined</i>, the SplitBar moves smoothly.\r
* @type Number\r
* @type Number\r
*/\r
this.minSize = 0;\r
- \r
+\r
/**\r
* The maximum size of the resizing element. (Defaults to 2000)\r
* @type Number\r
*/\r
this.maxSize = 2000;\r
- \r
+\r
/**\r
* Whether to animate the transition to the new size\r
* @type Boolean\r
*/\r
this.animate = false;\r
- \r
+\r
/**\r
* Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.\r
* @type Boolean\r
*/\r
this.useShim = false;\r
- \r
+\r
/** @private */\r
this.shim = null;\r
- \r
+\r
if(!existingProxy){\r
/** @private */\r
this.proxy = Ext.SplitBar.createProxy(this.orientation);\r
}\r
/** @private */\r
this.dd = new Ext.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});\r
- \r
+\r
/** @private */\r
this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);\r
- \r
+\r
/** @private */\r
this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);\r
- \r
+\r
/** @private */\r
this.dragSpecs = {};\r
- \r
+\r
/**\r
* @private The adapter to use to positon and resize elements\r
*/\r
this.adapter = new Ext.SplitBar.BasicLayoutAdapter();\r
this.adapter.init(this);\r
- \r
+\r
if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
/** @private */\r
this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Ext.SplitBar.LEFT : Ext.SplitBar.RIGHT);\r
this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Ext.SplitBar.TOP : Ext.SplitBar.BOTTOM);\r
this.el.addClass("x-splitbar-v");\r
}\r
- \r
+\r
this.addEvents(\r
/**\r
* @event resize\r
if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
this.dd.resetConstraints();\r
this.dd.setXConstraint(\r
- this.placement == Ext.SplitBar.LEFT ? c1 : c2, \r
+ this.placement == Ext.SplitBar.LEFT ? c1 : c2,\r
this.placement == Ext.SplitBar.LEFT ? c2 : c1,\r
this.tickSize\r
);\r
this.dd.resetConstraints();\r
this.dd.setXConstraint(0, 0);\r
this.dd.setYConstraint(\r
- this.placement == Ext.SplitBar.TOP ? c1 : c2, \r
+ this.placement == Ext.SplitBar.TOP ? c1 : c2,\r
this.placement == Ext.SplitBar.TOP ? c2 : c1,\r
this.tickSize\r
);\r
this.dragSpecs.startPoint = [x, y];\r
Ext.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);\r
},\r
- \r
- /** \r
+\r
+ /**\r
* @private Called after the drag operation by the DDProxy\r
*/\r
onEndProxyDrag : function(e){\r
}\r
var newSize;\r
if(this.orientation == Ext.SplitBar.HORIZONTAL){\r
- newSize = this.dragSpecs.startSize + \r
+ newSize = this.dragSpecs.startSize +\r
(this.placement == Ext.SplitBar.LEFT ?\r
endPoint[0] - this.dragSpecs.startPoint[0] :\r
this.dragSpecs.startPoint[0] - endPoint[0]\r
);\r
}else{\r
- newSize = this.dragSpecs.startSize + \r
+ newSize = this.dragSpecs.startSize +\r
(this.placement == Ext.SplitBar.TOP ?\r
endPoint[1] - this.dragSpecs.startPoint[1] :\r
this.dragSpecs.startPoint[1] - endPoint[1]\r
}\r
}\r
},\r
- \r
+\r
/**\r
* Get the adapter this SplitBar uses\r
* @return The adapter object\r
getAdapter : function(){\r
return this.adapter;\r
},\r
- \r
+\r
/**\r
* Set the adapter this SplitBar uses\r
* @param {Object} adapter A SplitBar adapter object\r
this.adapter = adapter;\r
this.adapter.init(this);\r
},\r
- \r
+\r
/**\r
* Gets the minimum size for the resizing element\r
* @return {Number} The minimum size\r
getMinimumSize : function(){\r
return this.minSize;\r
},\r
- \r
+\r
/**\r
* Sets the minimum size for the resizing element\r
* @param {Number} minSize The minimum size\r
setMinimumSize : function(minSize){\r
this.minSize = minSize;\r
},\r
- \r
+\r
/**\r
* Gets the maximum size for the resizing element\r
* @return {Number} The maximum size\r
getMaximumSize : function(){\r
return this.maxSize;\r
},\r
- \r
+\r
/**\r
* Sets the maximum size for the resizing element\r
* @param {Number} maxSize The maximum size\r
setMaximumSize : function(maxSize){\r
this.maxSize = maxSize;\r
},\r
- \r
+\r
/**\r
* Sets the initialize size for the resizing element\r
* @param {Number} size The initial size\r
this.adapter.setElementSize(this, size);\r
this.animate = oldAnimate;\r
},\r
- \r
+\r
/**\r
- * Destroy this splitbar. \r
+ * Destroy this splitbar.\r
* @param {Boolean} removeEl True to remove the element\r
*/\r
destroy : function(removeEl){\r
- Ext.destroy(this.shim, Ext.get(this.proxy));\r
+ Ext.destroy(this.shim, Ext.get(this.proxy));\r
this.dd.unreg();\r
if(removeEl){\r
this.el.remove();\r
}\r
- this.purgeListeners();\r
+ this.purgeListeners();\r
}\r
});\r
\r
*/\r
Ext.SplitBar.createProxy = function(dir){\r
var proxy = new Ext.Element(document.createElement("div"));\r
+ document.body.appendChild(proxy.dom);\r
proxy.unselectable();\r
var cls = 'x-splitbar-proxy';\r
proxy.addClass(cls + ' ' + (dir == Ext.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));\r
- document.body.appendChild(proxy.dom);\r
return proxy.dom;\r
};\r
\r
-/** \r
+/**\r
* @class Ext.SplitBar.BasicLayoutAdapter\r
* Default Adapter. It assumes the splitter and resizing element are not positioned\r
* elements and only gets/sets the width of the element. Generally used for table based layouts.\r
Ext.SplitBar.BasicLayoutAdapter.prototype = {\r
// do nothing for now\r
init : function(s){\r
- \r
+\r
},\r
/**\r
- * Called before drag operations to get the current size of the resizing element. \r
+ * Called before drag operations to get the current size of the resizing element.\r
* @param {Ext.SplitBar} s The SplitBar using this adapter\r
*/\r
getElementSize : function(s){\r
return s.resizingEl.getHeight();\r
}\r
},\r
- \r
+\r
/**\r
* Called after drag operations to set the size of the resizing element.\r
* @param {Ext.SplitBar} s The SplitBar using this adapter\r
s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');\r
}\r
}else{\r
- \r
+\r
if(!s.animate){\r
s.resizingEl.setHeight(newSize);\r
if(onComplete){\r
}\r
};\r
\r
-/** \r
+/**\r
*@class Ext.SplitBar.AbsoluteLayoutAdapter\r
* @extends Ext.SplitBar.BasicLayoutAdapter\r
- * Adapter that moves the splitter element to align with the resized sizing element. \r
+ * Adapter that moves the splitter element to align with the resized sizing element.\r
* Used with an absolute positioned SplitBar.\r
* @param {Mixed} container The container that wraps around the absolute positioned content. If it's\r
* document.body, make sure you assign an id to the body element.\r
init : function(s){\r
this.basic.init(s);\r
},\r
- \r
+\r
getElementSize : function(s){\r
return this.basic.getElementSize(s);\r
},\r
- \r
+\r
setElementSize : function(s, newSize, onComplete){\r
this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));\r
},\r
- \r
+\r
moveSplitter : function(s){\r
var yes = Ext.SplitBar;\r
switch(s.placement){\r
* <p>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
- * <tt><b>{@link Ext.Component#autoEl autoEl}</b></tt> config option. This is a useful technique when creating
+ * <code><b>{@link Ext.Component#autoEl autoEl}</b></code> config option. This is a useful technique when creating
* embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels}
* for example.</p>
*
* <p>The code below illustrates both how to explicitly create a Container, and how to implicitly
- * create one using the <b><tt>'container'</tt></b> xtype:<pre><code>
+ * create one using the <b><code>'container'</code></b> xtype:<pre><code>
// explicitly create a Container
var embeddedColumns = new Ext.Container({
autoEl: 'div', // This is the default
* Container, and <b>does not apply any sizing</b> at all.</p>
* <p>A common mistake is when a developer neglects to specify a
* <b><code>{@link #layout}</code></b> (e.g. widgets like GridPanels or
- * TreePanels are added to Containers for which no <tt><b>{@link #layout}</b></tt>
+ * TreePanels are added to Containers for which no <code><b>{@link #layout}</b></code>
* 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
* <p><b><u>Overnesting is a common problem</u></b>.
* An example of overnesting occurs when a GridPanel is added to a TabPanel
* by wrapping the GridPanel <i>inside</i> a wrapping Panel (that has no
- * <tt><b>{@link #layout}</b></tt> specified) and then add that wrapping Panel
+ * <code><b>{@link #layout}</b></code> specified) and then add that wrapping Panel
* to the TabPanel. The point to realize is that a GridPanel <b>is</b> a
* Component which can be added directly to a Container. If the wrapping Panel
- * has no <tt><b>{@link #layout}</b></tt> configuration, then the overnested
+ * has no <code><b>{@link #layout}</b></code> configuration, then the overnested
* GridPanel will not be sized as expected.<p>
-</code></pre>
*
* <p><u><b>Adding via remote configuration</b></u></p>
*
});
</code></pre>
* <p>The server script needs to return an executable Javascript statement which, when processed
- * using <tt>eval()</tt>, will return either a config object with an {@link Ext.Component#xtype xtype},
+ * using <code>eval()</code>, will return either a config object with an {@link Ext.Component#xtype xtype},
* or an instantiated Component. The server might return this for example:</p><pre><code>
(function() {
function formatDate(value){
return grid; // return instantiated component
})();
</code></pre>
- * <p>When the above code fragment is passed through the <tt>eval</tt> function in the success handler
+ * <p>When the above code fragment is passed through the <code>eval</code> 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.</p>
- * <p>Note: since the code above is <i>generated</i> by a server script, the <tt>baseParams</tt> for
+ * <p>Note: since the code above is <i>generated</i> by a server script, the <code>baseParams</code> 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.</p>
*
*/
/**
* @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, <b>you must specify a layout manager</b> which
- * creates and manages the type of layout you have in mind. For example:<pre><code>
+ * <p><b>*Important</b>: In order for child items to be correctly sized and
+ * positioned, typically a layout manager <b>must</b> be specified through
+ * the <code>layout</code> configuration option.</p>
+ * <br><p>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:</p><pre><code>
new Ext.Window({
width:300, height: 300,
layout: 'fit', // explicitly set layout manager: override the default (layout:'auto')
}]
}).show();
* </code></pre>
- * <p>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).</p>
- * <p>The layout manager class for this container may be specified as either as an
- * Object or as a String:</p>
- * <div><ul class="mdetail-params">
+ * <p>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 <code>layout:'form'</code>). Other specific
+ * purpose classes internally specify/manage their internal layout (e.g.
+ * GridPanel, TabPanel, TreePanel, Toolbar, Menu, etc.).</p>
+ * <br><p><b><code>layout</code></b> may be specified as either as an Object or
+ * as a String:</p><div><ul class="mdetail-params">
*
* <li><u>Specify as an Object</u></li>
* <div><ul class="mdetail-params">
}
</code></pre>
*
- * <li><tt><b>type</b></tt></li>
+ * <li><code><b>type</b></code></li>
* <br/><p>The layout type to be used for this container. If not specified,
* a default {@link Ext.layout.ContainerLayout} will be created and used.</p>
- * <br/><p>Valid layout <tt>type</tt> values are:</p>
+ * <br/><p>Valid layout <code>type</code> values are:</p>
* <div class="sub-desc"><ul class="mdetail-params">
- * <li><tt><b>{@link Ext.layout.AbsoluteLayout absolute}</b></tt></li>
- * <li><tt><b>{@link Ext.layout.AccordionLayout accordion}</b></tt></li>
- * <li><tt><b>{@link Ext.layout.AnchorLayout anchor}</b></tt></li>
- * <li><tt><b>{@link Ext.layout.ContainerLayout auto}</b></tt> <b>Default</b></li>
- * <li><tt><b>{@link Ext.layout.BorderLayout border}</b></tt></li>
- * <li><tt><b>{@link Ext.layout.CardLayout card}</b></tt></li>
- * <li><tt><b>{@link Ext.layout.ColumnLayout column}</b></tt></li>
- * <li><tt><b>{@link Ext.layout.FitLayout fit}</b></tt></li>
- * <li><tt><b>{@link Ext.layout.FormLayout form}</b></tt></li>
- * <li><tt><b>{@link Ext.layout.HBoxLayout hbox}</b></tt></li>
- * <li><tt><b>{@link Ext.layout.MenuLayout menu}</b></tt></li>
- * <li><tt><b>{@link Ext.layout.TableLayout table}</b></tt></li>
- * <li><tt><b>{@link Ext.layout.ToolbarLayout toolbar}</b></tt></li>
- * <li><tt><b>{@link Ext.layout.VBoxLayout vbox}</b></tt></li>
+ * <li><code><b>{@link Ext.layout.AbsoluteLayout absolute}</b></code></li>
+ * <li><code><b>{@link Ext.layout.AccordionLayout accordion}</b></code></li>
+ * <li><code><b>{@link Ext.layout.AnchorLayout anchor}</b></code></li>
+ * <li><code><b>{@link Ext.layout.ContainerLayout auto}</b></code> <b>Default</b></li>
+ * <li><code><b>{@link Ext.layout.BorderLayout border}</b></code></li>
+ * <li><code><b>{@link Ext.layout.CardLayout card}</b></code></li>
+ * <li><code><b>{@link Ext.layout.ColumnLayout column}</b></code></li>
+ * <li><code><b>{@link Ext.layout.FitLayout fit}</b></code></li>
+ * <li><code><b>{@link Ext.layout.FormLayout form}</b></code></li>
+ * <li><code><b>{@link Ext.layout.HBoxLayout hbox}</b></code></li>
+ * <li><code><b>{@link Ext.layout.MenuLayout menu}</b></code></li>
+ * <li><code><b>{@link Ext.layout.TableLayout table}</b></code></li>
+ * <li><code><b>{@link Ext.layout.ToolbarLayout toolbar}</b></code></li>
+ * <li><code><b>{@link Ext.layout.VBoxLayout vbox}</b></code></li>
* </ul></div>
*
* <li>Layout specific configuration properties</li>
* <br/><p>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 <tt>type</tt>
+ * each layout type, see the layout class corresponding to the <code>type</code>
* specified.</p>
*
* </ul></div>
align: 'left'
}
</code></pre>
- * <li><tt><b>layout</b></tt></li>
- * <br/><p>The layout <tt>type</tt> to be used for this container (see list
+ * <li><code><b>layout</b></code></li>
+ * <br/><p>The layout <code>type</code> to be used for this container (see list
* of valid layout type values above).</p><br/>
- * <li><tt><b>{@link #layoutConfig}</b></tt></li>
+ * <li><code><b>{@link #layoutConfig}</b></code></li>
* <br/><p>Additional layout specific configuration properties. For complete
* details regarding the valid config options for each layout type, see the
- * layout class corresponding to the <tt>layout</tt> specified.</p>
+ * layout class corresponding to the <code>layout</code> specified.</p>
* </ul></div></ul></div>
*/
/**
*/
/**
* @cfg {Boolean/Number} bufferResize
- * When set to true (100 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer
+ * 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.
+ * with a large quantity of sub-components for which frequent layout calls would be expensive. Defaults to <code>50</code>.
*/
- bufferResize: 100,
-
+ bufferResize: 50,
+
/**
* @cfg {String/Number} activeItem
* A string component id or the numeric index of the component that should be initially activated within the
*/
/**
* @cfg {Object/Array} items
- * <pre><b>** IMPORTANT</b>: be sure to specify a <b><code>{@link #layout}</code> ! **</b></pre>
+ * <pre><b>** IMPORTANT</b>: be sure to <b>{@link #layout specify a <code>layout</code>} if needed ! **</b></pre>
* <p>A single item, or an array of child Components to be added to this container,
* for example:</p>
* <pre><code>
* </ul></div>
*/
/**
- * @cfg {Object} defaults
- * <p>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 <tt>defaults</tt> 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: <tt>defaults: {bodyStyle:'padding:15px'}</tt>.</p><br/>
- * <p><b>Note</b>: <tt>defaults</tt> will not be applied to config objects if the option is already specified.
- * For example:</p><pre><code>
+ * @cfg {Object|Function} defaults
+ * <p>This option is a means of applying default settings to all added items whether added through the {@link #items}
+ * config or via the {@link #add} or {@link #insert} methods.</p>
+ * <p>If an added item is a config object, and <b>not</b> an instantiated Component, then the default properties are
+ * unconditionally applied. If the added item <b>is</b> an instantiated Component, then the default properties are
+ * applied conditionally so as not to override existing properties in the item.</p>
+ * <p>If the defaults option is specified as a function, then the function will be called using this Container as the
+ * scope (<code>this</code> reference) and passing the added item as the first parameter. Any resulting object
+ * from that call is then applied to the item as default properties.</p>
+ * <p>For example, to automatically apply padding to the body of each of a set of
+ * contained {@link Ext.Panel} items, you could pass: <code>defaults: {bodyStyle:'padding:15px'}</code>.</p>
+ * <p>Usage:</p><pre><code>
defaults: { // defaults are applied to items, not the container
autoScroll:true
},
/** @cfg {String} defaultType
* <p>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.</p>
- * <p>Defaults to <tt>'panel'</tt>, except {@link Ext.menu.Menu} which defaults to <tt>'menuitem'</tt>,
- * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to <tt>'button'</tt>.</p>
+ * <p>Defaults to <code>'panel'</code>, except {@link Ext.menu.Menu} which defaults to <code>'menuitem'</code>,
+ * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to <code>'button'</code>.</p>
*/
defaultType : 'panel',
+ /** @cfg {String} resizeEvent
+ * The event to listen to for resizing in layouts. Defaults to <code>'resize'</code>.
+ */
+ resizeEvent: 'resize',
+
+ /**
+ * @cfg {Array} bubbleEvents
+ * <p>An array of events that, when fired, should be bubbled to any parent container.
+ * See {@link Ext.util.Observable#enableBubble}.
+ * Defaults to <code>['add', 'remove']</code>.
+ */
+ bubbleEvents: ['add', 'remove'],
+
// private
initComponent : function(){
Ext.Container.superclass.initComponent.call(this);
'remove'
);
- this.enableBubble('add', 'remove');
+ this.enableBubble(this.bubbleEvents);
/**
* The collection of components in this container as a {@link Ext.util.MixedCollection}
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);
- }
+ this.add(items);
}
},
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);
+ afterRender: function(){
+ this.layoutDone = false;
+ 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);
- }
+ // BoxComponent's afterRender will set the size.
+ // This will will trigger a layout if the layout is configured to monitor resize
+ Ext.Container.superclass.afterRender.call(this);
+
+ if(Ext.isDefined(this.activeItem)){
+ var item = this.activeItem;
+ delete this.activeItem;
+ this.layout.setActiveItem(item);
}
- if(!this.ownerCt){
- // force a layout if no ownerCt is set
+
+ // If we have no ownerCt and the BoxComponent's sizing did not trigger a layout, force a layout
+ if(!this.ownerCt && !this.layoutDone){
this.doLayout(false, true);
}
+
if(this.monitorResize === true){
Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
}
* </ul></div>
* <br><p><b>Notes</b></u> :
* <div><ul class="mdetail-params">
- * <li>If the Container is <i>already rendered</i> when <tt>add</tt>
+ * <li>If the Container is <i>already rendered</i> when <code>add</code>
* is called, you may need to call {@link #doLayout} to refresh the view which causes
* any unrendered child Components to be rendered. This is required so that you can
- * <tt>add</tt> multiple child components if needed while only refreshing the layout
+ * <code>add</code> multiple child components if needed while only refreshing the layout
* once. For example:<pre><code>
var tb = new {@link Ext.Toolbar}();
tb.render(document.body); // toolbar is rendered
this.initItems();
var args = arguments.length > 1;
if(args || Ext.isArray(comp)){
+ var result = [];
Ext.each(args ? arguments : comp, function(c){
- this.add(c);
+ result.push(this.add(c));
}, this);
- return;
+ return result;
}
var c = this.lookupComponent(this.applyDefaults(comp));
- var pos = this.items.length;
- if(this.fireEvent('beforeadd', this, c, pos) !== false && this.onBeforeAdd(c) !== false){
+ var index = this.items.length;
+ if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
this.items.add(c);
- c.ownerCt = this;
- this.fireEvent('add', this, c, pos);
+ // *onAdded
+ c.onAdded(this, index);
+ this.onAdd(c);
+ this.fireEvent('add', this, c, index);
}
return c;
},
+ onAdd : function(c){
+ // Empty template method
+ },
+
+ // private
+ onAdded : function(container, pos) {
+ //overridden here so we can cascade down, not worth creating a template method.
+ this.ownerCt = container;
+ this.initRef();
+ //initialize references for child items
+ this.cascade(function(c){
+ c.initRef();
+ });
+ this.fireEvent('added', this, container, pos);
+ },
+
/**
* Inserts a Component into this Container at a specified index. Fires the
* {@link #beforeadd} event before inserting, then fires the {@link #add} event after the
this.initItems();
var a = arguments, len = a.length;
if(len > 2){
+ var result = [];
for(var i = len-1; i >= 1; --i) {
- this.insert(index, a[i]);
+ result.push(this.insert(index, a[i]));
}
- return;
+ return result;
}
var c = this.lookupComponent(this.applyDefaults(comp));
-
- if(c.ownerCt == this && this.items.indexOf(c) < index){
- --index;
- }
-
+ index = Math.min(index, this.items.length);
if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
+ if(c.ownerCt == this){
+ this.items.remove(c);
+ }
this.items.insert(index, c);
- c.ownerCt = this;
+ c.onAdded(this, index);
+ this.onAdd(c);
this.fireEvent('add', this, c, index);
}
return c;
// private
applyDefaults : function(c){
- if(this.defaults){
- if(typeof c == 'string'){
+ var d = this.defaults;
+ if(d){
+ if(Ext.isFunction(d)){
+ d = d.call(this, c);
+ }
+ if(Ext.isString(c)){
c = Ext.ComponentMgr.get(c);
- Ext.apply(c, this.defaults);
+ Ext.apply(c, d);
}else if(!c.events){
- Ext.applyIf(c, this.defaults);
+ Ext.applyIf(c, d);
}else{
- Ext.apply(c, this.defaults);
+ Ext.apply(c, d);
}
}
return c;
this.initItems();
var c = this.getComponent(comp);
if(c && this.fireEvent('beforeremove', this, c) !== false){
- this.items.remove(c);
- delete c.ownerCt;
- if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
- c.destroy();
- }
- if(this.layout && this.layout.activeItem == c){
- delete this.layout.activeItem;
- }
+ this.doRemove(c, autoDestroy);
this.fireEvent('remove', this, c);
}
return c;
},
+ onRemove: function(c){
+ // Empty template method
+ },
+
+ // private
+ doRemove: function(c, autoDestroy){
+ if(this.layout && this.rendered){
+ this.layout.onRemove(c);
+ }
+ this.items.remove(c);
+ c.onRemoved();
+ this.onRemove(c);
+ if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
+ c.destroy();
+ }
+ },
+
/**
* Removes all components from this container.
* @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
* and gets a direct child component of this container.
* @param {String/Number} comp This parameter may be any of the following:
* <div><ul class="mdetail-params">
- * <li>a <b><tt>String</tt></b> : representing the <code>{@link Ext.Component#itemId itemId}</code>
+ * <li>a <b><code>String</code></b> : representing the <code>{@link Ext.Component#itemId itemId}</code>
* or <code>{@link Ext.Component#id id}</code> of the child component </li>
- * <li>a <b><tt>Number</tt></b> : representing the position of the child component
+ * <li>a <b><code>Number</code></b> : representing the position of the child component
* within the <code>{@link #items}</code> <b>property</b></li>
* </ul></div>
* <p>For additional information see {@link Ext.util.MixedCollection#get}.
*/
getComponent : function(comp){
if(Ext.isObject(comp)){
- return comp;
+ comp = comp.getItemId();
}
return this.items.get(comp);
},
// private
lookupComponent : function(comp){
- if(typeof comp == 'string'){
+ if(Ext.isString(comp)){
return Ext.ComponentMgr.get(comp);
}else if(!comp.events){
return this.createComponent(comp);
},
// private
- createComponent : function(config){
- return Ext.create(config, this.defaultType);
+ createComponent : function(config, defaultType){
+ // add in ownerCt at creation time but then immediately
+ // remove so that onBeforeAdd can handle it
+ var c = config.render ? config : Ext.create(Ext.apply({
+ ownerCt: this
+ }, config), defaultType || this.defaultType);
+ delete c.ownerCt;
+ return c;
},
/**
- * 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.
+ * We can only lay out if there is a view area in which to layout.
+ * display:none on the layout target, *or any of its parent elements* will mean it has no view area.
+ */
+ canLayout: function() {
+ var el = this.getLayoutTarget(), vs;
+ return !!(el && (vs = el.dom.offsetWidth || el.dom.offsetHeight));
+ },
+
+ /**
+ * 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.
*/
doLayout: function(shallow, force){
var rendered = this.rendered,
- forceLayout = this.forceLayout;
+ forceLayout = force || this.forceLayout,
+ cs, i, len, c;
- if(!this.isVisible() || this.collapsed){
+ this.layoutDone = true;
+ if(!this.canLayout() || this.collapsed){
this.deferLayout = this.deferLayout || !shallow;
- if(!(force || forceLayout)){
+ if(!forceLayout){
return;
}
shallow = shallow && !this.deferLayout;
} else {
delete this.deferLayout;
}
+
+ cs = (shallow !== true && this.items) ? this.items.items : [];
+
+// Inhibit child Containers from relaying on resize since we are about to to explicitly call doLayout on them all!
+ for(i = 0, len = cs.length; i < len; i++){
+ if ((c = cs[i]).layout) {
+ c.suspendLayoutResize = true;
+ }
+ }
+
+// Tell the layout manager to ensure all child items are rendered, and sized according to their rules.
+// Will not cause the child items to relayout.
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();
- }
+
+// Explicitly lay out all child items
+ for(i = 0; i < len; i++){
+ if((c = cs[i]).doLayout){
+ c.doLayout(false, forceLayout);
}
}
if(rendered){
- this.onLayout(shallow, force);
+ this.onLayout(shallow, forceLayout);
}
+ // Initial layout completed
+ this.hasLayout = true;
delete this.forceLayout;
+
+// Re-enable child layouts relaying on resize.
+ for(i = 0; i < len; i++){
+ if ((c = cs[i]).layout) {
+ delete c.suspendLayoutResize;
+ }
+ }
},
//private
onLayout : Ext.emptyFn,
+ onResize: function(adjWidth, adjHeight, rawWidth, rawHeight){
+ Ext.Container.superclass.onResize.apply(this, arguments);
+ if ((this.rendered && this.layout && this.layout.monitorResize) && !this.suspendLayoutResize) {
+ this.layout.onResize();
+ }
+ },
+
+ // private
+ hasLayoutPending: function(){
+ // Traverse hierarchy to see if any parent container has a pending layout.
+ var pending = this.layoutPending;
+ this.ownerCt.bubble(function(c){
+ return !(pending = c.layoutPending);
+ });
+ return pending;
+
+ },
+
onShow : function(){
Ext.Container.superclass.onShow.call(this);
- if(this.deferLayout !== undefined){
+ if(Ext.isDefined(this.deferLayout)){
this.doLayout(true);
}
},
// private
beforeDestroy : function(){
+ var c;
if(this.items){
- Ext.destroy.apply(Ext, this.items.items);
+ while(c = this.items.first()){
+ this.doRemove(c, true);
+ }
}
if(this.monitorResize){
Ext.EventManager.removeResizeListener(this.doLayout, this);
* <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>
* configuration property. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>
*/
-Ext.layout.ContainerLayout = function(config){
- Ext.apply(this, config);
-};
-
-Ext.layout.ContainerLayout.prototype = {
+Ext.layout.ContainerLayout = Ext.extend(Object, {
/**
* @cfg {String} extraCls
* <p>An optional extra CSS class that will be added to the container. This can be useful for adding
// private
activeItem : null,
+ constructor : function(config){
+ Ext.apply(this, config);
+ },
+
// private
layout : function(){
var target = this.container.getLayoutTarget();
+ if(!(this.hasLayout || Ext.isEmpty(this.targetCls))){
+ target.addClass(this.targetCls)
+ }
this.onLayout(this.container, target);
this.container.fireEvent('afterlayout', this.container, this);
+ this.hasLayout = true;
},
// private
// private
isValidParent : function(c, target){
- return target && c.getDomPositionEl().dom.parentNode == (target.dom || target);
+ return target && c.getPositionEl().dom.parentNode == (target.dom || target);
},
// private
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);
+ target.dom.insertBefore(c.getPositionEl().dom, position || null);
c.container = target;
this.configureItem(c, position);
}
},
-
+
// private
configureItem: function(c, position){
if(this.extraCls){
var t = c.getPositionEl ? c.getPositionEl() : c;
t.addClass(this.extraCls);
}
+ // If we are forcing a layout, do so *before* we hide so elements have height/width
+ if(c.doLayout && this.forceLayout){
+ c.doLayout(false, true);
+ }
if (this.renderHidden && c != this.activeItem) {
c.hide();
}
- if(c.doLayout){
- c.doLayout(false, this.forceLayout);
+ },
+
+ 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 = ct.bufferResize;
+
+ 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;
+
+ // Not having an ownerCt negates the buffering: floating and top level
+ // Containers (Viewport, Window, ToolTip, Menu) need to lay out ASAP.
+ if (b && ct.ownerCt) {
+ // If we do NOT already have a layout pending from an ancestor, schedule one.
+ // If there is a layout pending, we do nothing here.
+ // buffering to be deprecated soon
+ if (!ct.hasLayoutPending()){
+ 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(false, this.forceLayout);
}
},
-
+
// private
runLayout: function(){
- this.layout();
- this.container.onLayout();
+ var ct = this.container;
+ ct.doLayout();
+ delete ct.layoutPending;
},
// private
setContainer : function(ct){
+ // No longer use events to handle resize. Instead this will be handled through a direct function call.
+ /*
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;
},
// private
parseMargins : function(v){
- if(typeof v == 'number'){
+ if(Ext.isNumber(v)){
v = v.toString();
}
var ms = v.split(' ');
},
/**
- * 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
t.disableFormats = true;
return t.compile();
})(),
-
+
/*
* Destroys this layout. This is a template method that is empty by default, but should be implemented
* by subclasses that require explicit destruction to purge event handlers or remove DOM nodes.
* @protected
*/
- destroy : Ext.emptyFn
-};
-Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout;/**\r
+ destroy : function(){
+ if(!Ext.isEmpty(this.targetCls)){
+ var target = this.container.getLayoutTarget();
+ if(target){
+ target.removeClass(this.targetCls);
+ }
+ }
+ }
+});
+Ext.Container.LAYOUTS['auto'] = Ext.layout.ContainerLayout;
+/**\r
* @class Ext.layout.FitLayout\r
* @extends Ext.layout.ContainerLayout\r
* <p>This is a base class for layouts that contain <b>a single item</b> that automatically expands to fill the layout's\r
onLayout : function(ct, target){\r
Ext.layout.FitLayout.superclass.onLayout.call(this, ct, target);\r
if(!this.container.collapsed){\r
- var sz = (Ext.isIE6 && Ext.isStrict && target.dom == document.body) ? target.getViewSize() : target.getStyleSize();\r
- this.setItemSize(this.activeItem || ct.items.itemAt(0), sz);\r
+ this.setItemSize(this.activeItem || ct.items.itemAt(0), target.getViewSize(true));\r
}\r
},\r
\r
\r
constructor: function(config){\r
Ext.layout.CardLayout.superclass.constructor.call(this, config);\r
- this.forceLayout = (this.deferredRender === false);\r
+ // this.forceLayout = (this.deferredRender === false);\r
},\r
\r
/**\r
* @param {String/Number} item The string component id or numeric index of the item to activate\r
*/\r
setActiveItem : function(item){\r
+ var ai = this.activeItem;\r
item = this.container.getComponent(item);\r
- if(this.activeItem != item){\r
- if(this.activeItem){\r
- this.activeItem.hide();\r
+ if(ai != item){\r
+ if(ai){\r
+ ai.hide();\r
+ ai.fireEvent('deactivate', ai);\r
}\r
+ var layout = item.doLayout && (this.layoutOnCardChange || !item.rendered);\r
this.activeItem = item;\r
- item.show();\r
- this.container.doLayout();\r
- if(this.layoutOnCardChange && item.doLayout){\r
+ if(item){\r
+ item.show();\r
+ }\r
+ this.layout();\r
+ if(item && layout){\r
item.doLayout();\r
}\r
+ item.fireEvent('activate', item);\r
}\r
},\r
\r
}\r
}\r
});\r
-Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;/**\r
- * @class Ext.layout.AnchorLayout\r
- * @extends Ext.layout.ContainerLayout\r
- * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.\r
- * If the container is resized, all anchored items are automatically rerendered according to their\r
- * <b><tt>{@link #anchor}</tt></b> rules.</p>\r
- * <p>This class is intended to be extended or created via the layout:'anchor' {@link Ext.Container#layout}\r
- * config, and should generally not need to be created directly via the new keyword.</p>\r
- * <p>AnchorLayout does not have any direct config options (other than inherited ones). By default,\r
- * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the\r
- * container using the AnchorLayout can supply an anchoring-specific config property of <b>anchorSize</b>.\r
- * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating\r
- * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring\r
- * logic if necessary. For example:</p>\r
- * <pre><code>\r
-var viewport = new Ext.Viewport({\r
- layout:'anchor',\r
- anchorSize: {width:800, height:600},\r
- items:[{\r
- title:'Item 1',\r
- html:'Content 1',\r
- width:800,\r
- anchor:'right 20%'\r
- },{\r
- title:'Item 2',\r
- html:'Content 2',\r
- width:300,\r
- anchor:'50% 30%'\r
- },{\r
- title:'Item 3',\r
- html:'Content 3',\r
- width:600,\r
- anchor:'-100 50%'\r
- }]\r
-});\r
- * </code></pre>\r
- */\r
-Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
- /**\r
- * @cfg {String} anchor\r
- * <p>This configuation option is to be applied to <b>child <tt>items</tt></b> of a container managed by\r
- * this layout (ie. configured with <tt>layout:'anchor'</tt>).</p><br/>\r
- * \r
- * <p>This value is what tells the layout how an item should be anchored to the container. <tt>items</tt>\r
- * added to an AnchorLayout accept an anchoring-specific config property of <b>anchor</b> which is a string\r
- * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').\r
- * The following types of anchor values are supported:<div class="mdetail-params"><ul>\r
- * \r
- * <li><b>Percentage</b> : Any value between 1 and 100, expressed as a percentage.<div class="sub-desc">\r
- * The first anchor is the percentage width that the item should take up within the container, and the\r
- * second is the percentage height. For example:<pre><code>\r
-// two values specified\r
-anchor: '100% 50%' // render item complete width of the container and\r
- // 1/2 height of the container\r
-// one value specified\r
-anchor: '100%' // the width value; the height will default to auto\r
- * </code></pre></div></li>\r
- * \r
- * <li><b>Offsets</b> : Any positive or negative integer value.<div class="sub-desc">\r
- * This is a raw adjustment where the first anchor is the offset from the right edge of the container,\r
- * and the second is the offset from the bottom edge. For example:<pre><code>\r
-// two values specified\r
-anchor: '-50 -100' // render item the complete width of the container\r
- // minus 50 pixels and\r
- // the complete height minus 100 pixels.\r
-// one value specified\r
-anchor: '-50' // anchor value is assumed to be the right offset value\r
- // bottom offset will default to 0\r
- * </code></pre></div></li>\r
- * \r
- * <li><b>Sides</b> : Valid values are <tt>'right'</tt> (or <tt>'r'</tt>) and <tt>'bottom'</tt>\r
- * (or <tt>'b'</tt>).<div class="sub-desc">\r
- * Either the container must have a fixed size or an anchorSize config value defined at render time in\r
- * order for these to have any effect.</div></li>\r
- *\r
- * <li><b>Mixed</b> : <div class="sub-desc">\r
- * Anchor values can also be mixed as needed. For example, to render the width offset from the container\r
- * right edge by 50 pixels and 75% of the container's height use:\r
- * <pre><code>\r
-anchor: '-50 75%' \r
- * </code></pre></div></li>\r
- * \r
- * \r
- * </ul></div>\r
- */\r
- \r
- // private\r
- monitorResize:true,\r
-\r
- // private\r
- getAnchorViewSize : function(ct, target){\r
- return target.dom == document.body ?\r
- target.getViewSize() : target.getStyleSize();\r
- },\r
-\r
- // private\r
- onLayout : function(ct, target){\r
- Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);\r
-\r
- var size = this.getAnchorViewSize(ct, target);\r
-\r
- var w = size.width, h = size.height;\r
-\r
- if(w < 20 && h < 20){\r
- return;\r
- }\r
-\r
- // find the container anchoring size\r
- var aw, ah;\r
- if(ct.anchorSize){\r
- if(typeof ct.anchorSize == 'number'){\r
- aw = ct.anchorSize;\r
- }else{\r
- aw = ct.anchorSize.width;\r
- ah = ct.anchorSize.height;\r
- }\r
- }else{\r
- aw = ct.initialConfig.width;\r
- ah = ct.initialConfig.height;\r
- }\r
-\r
- var cs = ct.items.items, len = cs.length, i, c, a, cw, ch;\r
- for(i = 0; i < len; i++){\r
- c = cs[i];\r
- if(c.anchor){\r
- a = c.anchorSpec;\r
- if(!a){ // cache all anchor values\r
- var vs = c.anchor.split(' ');\r
- c.anchorSpec = a = {\r
- right: this.parseAnchor(vs[0], c.initialConfig.width, aw),\r
- bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)\r
- };\r
- }\r
- cw = a.right ? this.adjustWidthAnchor(a.right(w), c) : undefined;\r
- ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h), c) : undefined;\r
-\r
- if(cw || ch){\r
- c.setSize(cw || undefined, ch || undefined);\r
- }\r
- }\r
- }\r
- },\r
-\r
- // private\r
- parseAnchor : function(a, start, cstart){\r
- if(a && a != 'none'){\r
- var last;\r
- if(/^(r|right|b|bottom)$/i.test(a)){ // standard anchor\r
- var diff = cstart - start;\r
- return function(v){\r
- if(v !== last){\r
- last = v;\r
- return v - diff;\r
- }\r
- }\r
- }else if(a.indexOf('%') != -1){\r
- var ratio = parseFloat(a.replace('%', ''))*.01; // percentage\r
- return function(v){\r
- if(v !== last){\r
- last = v;\r
- return Math.floor(v*ratio);\r
- }\r
- }\r
- }else{\r
- a = parseInt(a, 10);\r
- if(!isNaN(a)){ // simple offset adjustment\r
- return function(v){\r
- if(v !== last){\r
- last = v;\r
- return v + a;\r
- }\r
- }\r
- }\r
- }\r
- }\r
- return false;\r
- },\r
-\r
- // private\r
- adjustWidthAnchor : function(value, comp){\r
- return value;\r
- },\r
-\r
- // private\r
- adjustHeightAnchor : function(value, comp){\r
- return value;\r
- }\r
- \r
- /**\r
- * @property activeItem\r
- * @hide\r
- */\r
-});\r
-Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;/**\r
+Ext.Container.LAYOUTS['card'] = Ext.layout.CardLayout;/**
+ * @class Ext.layout.AnchorLayout
+ * @extends Ext.layout.ContainerLayout
+ * <p>This is a layout that enables anchoring of contained elements relative to the container's dimensions.
+ * If the container is resized, all anchored items are automatically rerendered according to their
+ * <b><tt>{@link #anchor}</tt></b> rules.</p>
+ * <p>This class is intended to be extended or created via the layout:'anchor' {@link Ext.Container#layout}
+ * config, and should generally not need to be created directly via the new keyword.</p>
+ * <p>AnchorLayout does not have any direct config options (other than inherited ones). By default,
+ * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the
+ * container using the AnchorLayout can supply an anchoring-specific config property of <b>anchorSize</b>.
+ * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating
+ * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring
+ * logic if necessary. For example:</p>
+ * <pre><code>
+var viewport = new Ext.Viewport({
+ layout:'anchor',
+ anchorSize: {width:800, height:600},
+ items:[{
+ title:'Item 1',
+ html:'Content 1',
+ width:800,
+ anchor:'right 20%'
+ },{
+ title:'Item 2',
+ html:'Content 2',
+ width:300,
+ anchor:'50% 30%'
+ },{
+ title:'Item 3',
+ html:'Content 3',
+ width:600,
+ anchor:'-100 50%'
+ }]
+});
+ * </code></pre>
+ */
+Ext.layout.AnchorLayout = Ext.extend(Ext.layout.ContainerLayout, {
+ /**
+ * @cfg {String} anchor
+ * <p>This configuation option is to be applied to <b>child <tt>items</tt></b> of a container managed by
+ * this layout (ie. configured with <tt>layout:'anchor'</tt>).</p><br/>
+ *
+ * <p>This value is what tells the layout how an item should be anchored to the container. <tt>items</tt>
+ * added to an AnchorLayout accept an anchoring-specific config property of <b>anchor</b> which is a string
+ * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').
+ * The following types of anchor values are supported:<div class="mdetail-params"><ul>
+ *
+ * <li><b>Percentage</b> : Any value between 1 and 100, expressed as a percentage.<div class="sub-desc">
+ * The first anchor is the percentage width that the item should take up within the container, and the
+ * second is the percentage height. For example:<pre><code>
+// two values specified
+anchor: '100% 50%' // render item complete width of the container and
+ // 1/2 height of the container
+// one value specified
+anchor: '100%' // the width value; the height will default to auto
+ * </code></pre></div></li>
+ *
+ * <li><b>Offsets</b> : Any positive or negative integer value.<div class="sub-desc">
+ * This is a raw adjustment where the first anchor is the offset from the right edge of the container,
+ * and the second is the offset from the bottom edge. For example:<pre><code>
+// two values specified
+anchor: '-50 -100' // render item the complete width of the container
+ // minus 50 pixels and
+ // the complete height minus 100 pixels.
+// one value specified
+anchor: '-50' // anchor value is assumed to be the right offset value
+ // bottom offset will default to 0
+ * </code></pre></div></li>
+ *
+ * <li><b>Sides</b> : Valid values are <tt>'right'</tt> (or <tt>'r'</tt>) and <tt>'bottom'</tt>
+ * (or <tt>'b'</tt>).<div class="sub-desc">
+ * Either the container must have a fixed size or an anchorSize config value defined at render time in
+ * order for these to have any effect.</div></li>
+ *
+ * <li><b>Mixed</b> : <div class="sub-desc">
+ * Anchor values can also be mixed as needed. For example, to render the width offset from the container
+ * right edge by 50 pixels and 75% of the container's height use:
+ * <pre><code>
+anchor: '-50 75%'
+ * </code></pre></div></li>
+ *
+ *
+ * </ul></div>
+ */
+
+ // private
+ monitorResize:true,
+
+ // private
+ // deprecate
+ getAnchorViewSize : function(ct, target){
+ return target.dom == document.body ?
+ target.getViewSize(true) : target.getStyleSize();
+ },
+
+ // private
+ onLayout : function(ct, target){
+ Ext.layout.AnchorLayout.superclass.onLayout.call(this, ct, target);
+
+ var size = target.getViewSize(true);
+
+ var w = size.width, h = size.height;
+
+ if(w < 20 && h < 20){
+ return;
+ }
+
+ // find the container anchoring size
+ var aw, ah;
+ if(ct.anchorSize){
+ if(typeof ct.anchorSize == 'number'){
+ aw = ct.anchorSize;
+ }else{
+ aw = ct.anchorSize.width;
+ ah = ct.anchorSize.height;
+ }
+ }else{
+ aw = ct.initialConfig.width;
+ ah = ct.initialConfig.height;
+ }
+
+ var cs = ct.items.items, len = cs.length, i, c, a, cw, ch, el, vs;
+ for(i = 0; i < len; i++){
+ c = cs[i];
+ el = c.getPositionEl();
+ if(c.anchor){
+ a = c.anchorSpec;
+ if(!a){ // cache all anchor values
+ vs = c.anchor.split(' ');
+ c.anchorSpec = a = {
+ right: this.parseAnchor(vs[0], c.initialConfig.width, aw),
+ bottom: this.parseAnchor(vs[1], c.initialConfig.height, ah)
+ };
+ }
+ cw = a.right ? this.adjustWidthAnchor(a.right(w) - el.getMargins('lr'), c) : undefined;
+ ch = a.bottom ? this.adjustHeightAnchor(a.bottom(h) - el.getMargins('tb'), c) : undefined;
+
+ if(cw || ch){
+ c.setSize(cw || undefined, ch || undefined);
+ }
+ }
+ }
+ },
+
+ // private
+ parseAnchor : function(a, start, cstart){
+ if(a && a != 'none'){
+ var last;
+ if(/^(r|right|b|bottom)$/i.test(a)){ // standard anchor
+ var diff = cstart - start;
+ return function(v){
+ if(v !== last){
+ last = v;
+ return v - diff;
+ }
+ }
+ }else if(a.indexOf('%') != -1){
+ var ratio = parseFloat(a.replace('%', ''))*.01; // percentage
+ return function(v){
+ if(v !== last){
+ last = v;
+ return Math.floor(v*ratio);
+ }
+ }
+ }else{
+ a = parseInt(a, 10);
+ if(!isNaN(a)){ // simple offset adjustment
+ return function(v){
+ if(v !== last){
+ last = v;
+ return v + a;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ },
+
+ // private
+ adjustWidthAnchor : function(value, comp){
+ return value;
+ },
+
+ // private
+ adjustHeightAnchor : function(value, comp){
+ return value;
+ }
+
+ /**
+ * @property activeItem
+ * @hide
+ */
+});
+Ext.Container.LAYOUTS['anchor'] = Ext.layout.AnchorLayout;
+/**\r
* @class Ext.layout.ColumnLayout\r
* @extends Ext.layout.ContainerLayout\r
* <p>This is the layout style of choice for creating structural layouts in a multi-column format where the width of\r
layout:'column',\r
items: [{\r
title: 'Column 1',\r
- columnWidth: .25 \r
+ columnWidth: .25\r
},{\r
title: 'Column 2',\r
columnWidth: .6\r
Ext.layout.ColumnLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
// private\r
monitorResize:true,\r
- \r
+\r
extraCls: 'x-column',\r
\r
scrollOffset : 0,\r
\r
// private\r
+\r
+ targetCls: 'x-column-layout-ct',\r
+\r
isValidParent : function(c, target){\r
- return (c.getPositionEl ? c.getPositionEl() : c.getEl()).dom.parentNode == this.innerCt.dom;\r
+ return c.getPositionEl().dom.parentNode == this.innerCt.dom;\r
},\r
\r
// private\r
var cs = ct.items.items, len = cs.length, c, i;\r
\r
if(!this.innerCt){\r
- target.addClass('x-column-layout-ct');\r
-\r
// the innerCt prevents wrapping and shuffling while\r
// the container is resizing\r
this.innerCt = target.createChild({cls:'x-column-inner'});\r
}\r
this.renderAll(ct, this.innerCt);\r
\r
- var size = Ext.isIE && target.dom != Ext.getBody().dom ? target.getStyleSize() : target.getViewSize();\r
+ var size = target.getViewSize(true);\r
\r
if(size.width < 1 && size.height < 1){ // display none?\r
return;\r
}\r
\r
- var w = size.width - target.getPadding('lr') - this.scrollOffset,\r
- h = size.height - target.getPadding('tb'),\r
+ var w = size.width - this.scrollOffset,\r
+ h = size.height,\r
pw = w;\r
\r
this.innerCt.setWidth(w);\r
- \r
+\r
// some columns can be percentages while others are fixed\r
// so we need to make 2 passes\r
\r
for(i = 0; i < len; i++){\r
c = cs[i];\r
if(!c.columnWidth){\r
- pw -= (c.getSize().width + c.getEl().getMargins('lr'));\r
+ pw -= (c.getSize().width + c.getPositionEl().getMargins('lr'));\r
}\r
}\r
\r
for(i = 0; i < len; i++){\r
c = cs[i];\r
if(c.columnWidth){\r
- c.setSize(Math.floor(c.columnWidth*pw) - c.getEl().getMargins('lr'));\r
+ c.setSize(Math.floor(c.columnWidth * pw) - c.getPositionEl().getMargins('lr'));\r
}\r
}\r
}\r
- \r
+\r
/**\r
* @property activeItem\r
* @hide\r
{@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south', // position for region
{@link Ext.BoxComponent#height height}: 100,
{@link Ext.layout.BorderLayout.Region#split split}: true, // enable resizing
- {@link Ext.SplitBar#minSize minSize}: 75, // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50}
+ {@link Ext.SplitBar#minSize minSize}: 75, // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50}
{@link Ext.SplitBar#maxSize maxSize}: 150,
{@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5'
},{
// private
rendered : false,
+ targetCls: 'x-border-layout-ct',
+
// private
onLayout : function(ct, target){
var collapsed;
if(!this.rendered){
- target.addClass('x-border-layout-ct');
var items = ct.items.items;
collapsed = [];
for(var i = 0, len = items.length; i < len; i++) {
}
c.collapsed = false;
if(!c.rendered){
- c.cls = c.cls ? c.cls +' x-border-panel' : 'x-border-panel';
c.render(target, i);
+ c.getPositionEl().addClass('x-border-panel');
}
this[pos] = pos != 'center' && c.split ?
new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
this.rendered = true;
}
- var size = target.getViewSize();
+ var size = target.getViewSize(false);
if(size.width < 20 || size.height < 20){ // display none?
if(collapsed){
this.restoreCollapsed = collapsed;
collapsible : false,
/**
* @cfg {Boolean} split
- * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and
+ * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and
* display a 5px wide {@link Ext.SplitBar} between this region and its neighbor, allowing the user to
* resize the regions dynamically. Defaults to <tt>false</tt> creating a
* {@link Ext.layout.BorderLayout.Region Region}.</p><br>
* <p><b>Notes</b>:</p><div class="mdetail-params"><ul>
- * <li>this configuration option is ignored if <tt>region='center'</tt></li>
+ * <li>this configuration option is ignored if <tt>region='center'</tt></li>
* <li>when <tt>split == true</tt>, it is common to specify a
* <tt>{@link Ext.SplitBar#minSize minSize}</tt> and <tt>{@link Ext.SplitBar#maxSize maxSize}</tt>
* for the {@link Ext.BoxComponent BoxComponent} representing the region. These are not native
* configs of {@link Ext.BoxComponent BoxComponent}, and are used only by this class.</li>
* <li>if <tt>{@link #collapseMode} = 'mini'</tt> requires <tt>split = true</tt> to reserve space
- * for the collapse tool</tt></li>
- * </ul></div>
+ * for the collapse tool</tt></li>
+ * </ul></div>
*/
split:false,
/**
* @cfg {Number} minWidth
* <p>The minimum allowable width in pixels for this region (defaults to <tt>50</tt>).
* <tt>maxWidth</tt> may also be specified.</p><br>
- * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
- * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
+ * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
+ * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
* <tt>minWidth</tt> / <tt>maxWidth</tt>.</p>
*/
minWidth:50,
* @cfg {Number} minHeight
* The minimum allowable height in pixels for this region (defaults to <tt>50</tt>)
* <tt>maxHeight</tt> may also be specified.</p><br>
- * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
- * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
+ * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> /
+ * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified
* <tt>minHeight</tt> / <tt>maxHeight</tt>.</p>
*/
minHeight:50,
// private
onExpandClick : function(e){
if(this.isSlid){
- this.afterSlideIn();
this.panel.expand(false);
}else{
this.panel.expand();
this.splitEl.hide();
}
this.getCollapsedEl().show();
- this.panel.el.setStyle('z-index', 100);
+ var el = this.panel.getEl();
+ this.originalZIndex = el.getStyle('z-index');
+ el.setStyle('z-index', 100);
this.isCollapsed = true;
this.layout.layout();
},
// private
beforeExpand : function(animate){
+ if(this.isSlid){
+ this.afterSlideIn();
+ }
var c = this.getCollapsedEl();
this.el.show();
if(this.position == 'east' || this.position == 'west'){
this.splitEl.show();
}
this.layout.layout();
- this.panel.el.setStyle('z-index', 1);
+ this.panel.el.setStyle('z-index', this.originalZIndex);
this.state.collapsed = false;
this.panel.saveState();
},
};
}
this.el.on(this.autoHideHd);
+ this.collapsedEl.on(this.autoHideHd);
}
},
if(this.autoHide !== false){
this.el.un("mouseout", this.autoHideHd.mouseout);
this.el.un("mouseover", this.autoHideHd.mouseover);
+ this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
+ this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
}
},
return [0, cm.top+cm.bottom+c.getHeight()];
break;
}
+ },
+
+ destroy : function(){
+ Ext.destroy(this.miniCollapsedEl, this.collapsedEl);
}
};
// inherit docs
destroy : function() {
- Ext.destroy(
- this.miniSplitEl,
- this.split,
- this.splitEl
- );
+ Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
+ Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
}
});
* @property labelStyle
*/
+ /**
+ * @cfg {Boolean} trackLabels
+ * True to show/hide the field label when the field is hidden. Defaults to <tt>false</tt>.
+ */
+ trackLabels: false,
+
+
+ onRemove: function(c){
+ Ext.layout.FormLayout.superclass.onRemove.call(this, c);
+ if(this.trackLabels){
+ 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){
+ if (el && el.dom) {
+ 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);
}
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;'
+ });
}
}
},
+ // private
+ 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){
var ls = '', items = [this.labelStyle, s];
// 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.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.render('x-form-el-'+c.id);
+ c.label = c.getItemCt().child('label.x-form-item-label');
+ 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(this.trackLabels){
+ if(c.hidden){
+ this.onFieldHide(c);
+ }
+ c.on({
+ scope: this,
+ show: this.onFieldShow,
+ hide: this.onFieldHide
+ });
+ }
+ this.configureItem(c);
}else {
Ext.layout.FormLayout.superclass.renderItem.apply(this, arguments);
}
* <li><b><tt>clearCls</tt></b> : String<div class="sub-desc">The CSS class to apply to the special clearing div
* rendered directly after each form field wrapper (defaults to <tt>'x-form-clear-left'</tt>)</div></li>
* </ul></div>
- * @param field The {@link Field Ext.form.Field} being rendered.
+ * @param (Ext.form.Field} field The {@link Ext.form.Field Field} being rendered.
* @return An object hash containing the properties required to render the Field.
*/
getTemplateArgs: function(field) {
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.getPositionEl());
}
/**
*/
});
-Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;/**\r
+Ext.Container.LAYOUTS['form'] = Ext.layout.FormLayout;
+/**\r
* @class Ext.layout.AccordionLayout\r
* @extends Ext.layout.FitLayout\r
- * <p>This is a layout that contains multiple panels in an expandable accordion style such that only\r
- * <b>one panel can be open at any given time</b>. Each panel has built-in support for expanding and collapsing.\r
+ * <p>This is a layout that manages multiple Panels in an expandable accordion style such that only\r
+ * <b>one Panel can be expanded at any given time</b>. Each Panel has built-in support for expanding and collapsing.</p>\r
+ * <p>Note: Only Ext.Panels <b>and all subclasses of Ext.Panel</b> may be used in an accordion layout Container.</p>\r
* <p>This class is intended to be extended or created via the <tt><b>{@link Ext.Container#layout layout}</b></tt>\r
* configuration property. See <tt><b>{@link Ext.Container#layout}</b></tt> for additional details.</p>\r
* <p>Example usage:</p>\r
c.collapseFirst = this.collapseFirst;\r
}\r
if(!this.activeItem && !c.collapsed){\r
- this.activeItem = c;\r
+ this.setActiveItem(c, true);\r
}else if(this.activeItem && this.activeItem != c){\r
c.collapsed = true;\r
}\r
c.header.addClass('x-accordion-hd');\r
c.on('beforeexpand', this.beforeExpand, this);\r
},\r
+ \r
+ onRemove: function(c){\r
+ Ext.layout.AccordionLayout.superclass.onRemove.call(this, c);\r
+ if(c.rendered){\r
+ c.header.removeClass('x-accordion-hd');\r
+ }\r
+ c.un('beforeexpand', this.beforeExpand, this);\r
+ },\r
\r
// private\r
beforeExpand : function(p, anim){\r
ai.collapse(this.animate);\r
}\r
}\r
- this.activeItem = p;\r
+ this.setActive(p);\r
if(this.activeOnTop){\r
p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);\r
}\r
* @param {String/Number} item The string component id or numeric index of the item to activate\r
*/\r
setActiveItem : function(item){\r
+ this.setActive(item, true);\r
+ },\r
+ \r
+ // private\r
+ setActive : function(item, expand){\r
+ var ai = this.activeItem;\r
item = this.container.getComponent(item);\r
- if(this.activeItem != item){\r
- if(item.rendered && item.collapsed){\r
+ if(ai != item){\r
+ if(item.rendered && item.collapsed && expand){\r
item.expand();\r
}else{\r
+ if(ai){\r
+ ai.fireEvent('deactivate', ai);\r
+ }\r
this.activeItem = item;\r
+ item.fireEvent('activate', item);\r
}\r
}\r
-\r
}\r
});\r
Ext.Container.LAYOUTS.accordion = Ext.layout.AccordionLayout;\r
\r
// private\r
monitorResize:false,\r
+ \r
+ targetCls: 'x-table-layout-ct',\r
\r
/**\r
* @cfg {Object} tableAttrs\r
var cs = ct.items.items, len = cs.length, c, i;\r
\r
if(!this.table){\r
- target.addClass('x-table-layout-ct');\r
-\r
this.table = target.createChild(\r
Ext.apply({tag:'table', cls:'x-table-layout', cellspacing: 0, cn: {tag: 'tbody'}}, this.tableAttrs), null, true);\r
}\r
renderItem : function(c, position, target){\r
if(c && !c.rendered){\r
c.render(this.getNextCell(c));\r
- if(this.extraCls){\r
- var t = c.getPositionEl ? c.getPositionEl() : c;\r
- t.addClass(this.extraCls);\r
- }\r
+ this.configureItem(c, position);\r
+ }else if(c && !this.isValidParent(c, target)){\r
+ var container = this.getNextCell(c);\r
+ container.insertBefore(c.getPositionEl().dom, null);\r
+ c.container = Ext.get(container);\r
+ this.configureItem(c, position);\r
}\r
},\r
\r
// private\r
isValidParent : function(c, target){\r
- return true;\r
+ return c.getPositionEl().up('table', 5).dom.parentNode === (target.dom || target);\r
}\r
\r
/**\r
*/\r
});\r
Ext.Container.LAYOUTS['absolute'] = Ext.layout.AbsoluteLayout;
-/**\r
- * @class Ext.layout.BoxLayout\r
- * @extends Ext.layout.ContainerLayout\r
- * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>\r
- */\r
-Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {\r
- /**\r
- * @cfg {Object} defaultMargins\r
- * <p>If the individual contained items do not have a <tt>margins</tt>\r
- * property specified, the default margins from this property will be\r
- * applied to each item.</p>\r
- * <br><p>This property may be specified as an object containing margins\r
- * to apply in the format:</p><pre><code>\r
-{\r
- top: (top margin),\r
- right: (right margin),\r
- bottom: (bottom margin),\r
- left: (left margin)\r
-}</code></pre>\r
- * <p>This property may also be specified as a string containing\r
- * space-separated, numeric margin values. The order of the sides associated\r
- * with each value matches the way CSS processes margin values:</p>\r
- * <div class="mdetail-params"><ul>\r
- * <li>If there is only one value, it applies to all sides.</li>\r
- * <li>If there are two values, the top and bottom borders are set to the\r
- * first value and the right and left are set to the second.</li>\r
- * <li>If there are three values, the top is set to the first value, the left\r
- * and right are set to the second, and the bottom is set to the third.</li>\r
- * <li>If there are four values, they apply to the top, right, bottom, and\r
- * left, respectively.</li>\r
- * </ul></div>\r
- * <p>Defaults to:</p><pre><code>\r
- * {top:0, right:0, bottom:0, left:0}\r
- * </code></pre>\r
- */\r
- defaultMargins : {left:0,top:0,right:0,bottom:0},\r
- /**\r
- * @cfg {String} padding\r
- * Defaults to <tt>'0'</tt>. Sets the padding to be applied to all child items managed by this\r
- * container's layout. \r
- */\r
- padding : '0',\r
- // documented in subclasses\r
- pack : 'start',\r
-\r
- // private\r
- monitorResize : true,\r
- scrollOffset : 0,\r
- extraCls : 'x-box-item',\r
- ctCls : 'x-box-layout-ct',\r
- innerCls : 'x-box-inner',\r
-\r
- // private\r
- isValidParent : function(c, target){\r
- return c.getEl().dom.parentNode == this.innerCt.dom;\r
- },\r
-\r
- // private\r
- onLayout : function(ct, target){\r
- var cs = ct.items.items, len = cs.length, c, i, last = len-1, cm;\r
-\r
- if(!this.innerCt){\r
- target.addClass(this.ctCls);\r
-\r
- // the innerCt prevents wrapping and shuffling while\r
- // the container is resizing\r
- this.innerCt = target.createChild({cls:this.innerCls});\r
- this.padding = this.parseMargins(this.padding); \r
- }\r
- this.renderAll(ct, this.innerCt);\r
- },\r
-\r
- // private\r
- renderItem : function(c){\r
- if(typeof c.margins == 'string'){\r
- c.margins = this.parseMargins(c.margins);\r
- }else if(!c.margins){\r
- c.margins = this.defaultMargins;\r
- }\r
- Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);\r
- },\r
-\r
+/**
+ * @class Ext.layout.BoxLayout
+ * @extends Ext.layout.ContainerLayout
+ * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
+ */
+Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
+ /**
+ * @cfg {Object} defaultMargins
+ * <p>If the individual contained items do not have a <tt>margins</tt>
+ * property specified, the default margins from this property will be
+ * applied to each item.</p>
+ * <br><p>This property may be specified as an object containing margins
+ * to apply in the format:</p><pre><code>
+{
+ top: (top margin),
+ right: (right margin),
+ bottom: (bottom margin),
+ left: (left margin)
+}</code></pre>
+ * <p>This property may also be specified as a string containing
+ * space-separated, numeric margin values. The order of the sides associated
+ * with each value matches the way CSS processes margin values:</p>
+ * <div class="mdetail-params"><ul>
+ * <li>If there is only one value, it applies to all sides.</li>
+ * <li>If there are two values, the top and bottom borders are set to the
+ * first value and the right and left are set to the second.</li>
+ * <li>If there are three values, the top is set to the first value, the left
+ * and right are set to the second, and the bottom is set to the third.</li>
+ * <li>If there are four values, they apply to the top, right, bottom, and
+ * left, respectively.</li>
+ * </ul></div>
+ * <p>Defaults to:</p><pre><code>
+ * {top:0, right:0, bottom:0, left:0}
+ * </code></pre>
+ */
+ defaultMargins : {left:0,top:0,right:0,bottom:0},
+ /**
+ * @cfg {String} padding
+ * <p>Sets the padding to be applied to all child items managed by this layout.</p>
+ * <p>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:</p>
+ * <div class="mdetail-params"><ul>
+ * <li>If there is only one value, it applies to all sides.</li>
+ * <li>If there are two values, the top and bottom borders are set to the
+ * first value and the right and left are set to the second.</li>
+ * <li>If there are three values, the top is set to the first value, the left
+ * and right are set to the second, and the bottom is set to the third.</li>
+ * <li>If there are four values, they apply to the top, right, bottom, and
+ * left, respectively.</li>
+ * </ul></div>
+ * <p>Defaults to: <code>"0"</code></p>
+ */
+ padding : '0',
+ // documented in subclasses
+ pack : 'start',
+
+ // private
+ monitorResize : true,
+ scrollOffset : 0,
+ extraCls : 'x-box-item',
+ targetCls : 'x-box-layout-ct',
+ innerCls : 'x-box-inner',
+
+ constructor : function(config){
+ Ext.layout.BoxLayout.superclass.constructor.call(this, config);
+ if(Ext.isString(this.defaultMargins)){
+ this.defaultMargins = this.parseMargins(this.defaultMargins);
+ }
+ },
+
+ // private
+ isValidParent : function(c, target){
+ return c.getPositionEl().dom.parentNode == this.innerCt.dom;
+ },
+
+ // private
+ onLayout : function(ct, target){
+ var cs = ct.items.items, len = cs.length, c, i, last = len-1, cm;
+
+ if(!this.innerCt){
+ // the innerCt prevents wrapping and shuffling while
+ // the container is resizing
+ this.innerCt = target.createChild({cls:this.innerCls});
+ this.padding = this.parseMargins(this.padding);
+ }
+ this.renderAll(ct, this.innerCt);
+ },
+
+ // private
+ renderItem : function(c){
+ if(Ext.isString(c.margins)){
+ c.margins = this.parseMargins(c.margins);
+ }else if(!c.margins){
+ c.margins = this.defaultMargins;
+ }
+ Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
+ },
+
+ // deprecate
getTargetSize : function(target){
- return (Ext.isIE6 && Ext.isStrict && target.dom == document.body) ? target.getStyleSize() : target.getViewSize();\r
- },\r
- \r
- getItems: function(ct){\r
- var items = [];\r
- ct.items.each(function(c){\r
- if(c.isVisible()){\r
- items.push(c);\r
- }\r
- });\r
- return items;\r
- }\r
-\r
- /**\r
- * @property activeItem\r
- * @hide\r
- */\r
-});\r
-\r
-/**\r
- * @class Ext.layout.VBoxLayout\r
- * @extends Ext.layout.BoxLayout\r
- * A layout that arranges items vertically\r
- */\r
-Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {\r
- /**\r
- * @cfg {String} align\r
- * Controls how the child items of the container are aligned. Acceptable configuration values for this\r
- * property are:\r
- * <div class="mdetail-params"><ul>\r
- * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally\r
- * at the <b>left</b> side of the container</div></li>\r
- * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the\r
- * <b>mid-width</b> of the container</div></li>\r
- * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill\r
- * the width of the container</div></li>\r
- * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to\r
- * the size of the largest item.</div></li>\r
- * </ul></div>\r
- */\r
- align : 'left', // left, center, stretch, strechmax\r
- /**\r
- * @cfg {String} pack\r
- * Controls how the child items of the container are packed together. Acceptable configuration values\r
- * for this property are:\r
- * <div class="mdetail-params"><ul>\r
- * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at\r
- * <b>top</b> side of container</div></li>\r
- * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at\r
- * <b>mid-height</b> of container</div></li>\r
- * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>\r
- * side of container</div></li>\r
- * </ul></div>\r
- */\r
- /**\r
- * @cfg {Number} flex\r
- * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed\r
- * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>\r
- * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with\r
- * a <tt>flex</tt> value specified. Any child items that have either a <tt>flex = 0</tt> or\r
- * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).\r
- */\r
-\r
- // private\r
- onLayout : function(ct, target){\r
- Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);\r
- \r
- \r
- var cs = this.getItems(ct), cm, ch, margin,\r
- size = this.getTargetSize(target),\r
- w = size.width - target.getPadding('lr') - this.scrollOffset,\r
- h = size.height - target.getPadding('tb'),\r
- l = this.padding.left, t = this.padding.top,\r
- isStart = this.pack == 'start',\r
- isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,\r
- stretchWidth = w - (this.padding.left + this.padding.right),\r
- extraHeight = 0,\r
- maxWidth = 0,\r
- totalFlex = 0,\r
- flexHeight = 0,\r
- usedHeight = 0;\r
- \r
- Ext.each(cs, function(c){\r
- cm = c.margins;\r
- totalFlex += c.flex || 0;\r
- ch = c.getHeight();\r
- margin = cm.top + cm.bottom;\r
- extraHeight += ch + margin;\r
- flexHeight += margin + (c.flex ? 0 : ch);\r
- maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);\r
- });\r
- extraHeight = h - extraHeight - this.padding.top - this.padding.bottom;\r
- \r
- var innerCtWidth = maxWidth + this.padding.left + this.padding.right;\r
- switch(this.align){\r
- case 'stretch':\r
- this.innerCt.setSize(w, h);\r
- break;\r
- case 'stretchmax':\r
- case 'left':\r
- this.innerCt.setSize(innerCtWidth, h);\r
- break;\r
- case 'center':\r
- this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);\r
- break;\r
- }\r
-\r
- var availHeight = Math.max(0, h - this.padding.top - this.padding.bottom - flexHeight),\r
- leftOver = availHeight,\r
- heights = [],\r
- restore = [],\r
- idx = 0,\r
- availableWidth = Math.max(0, w - this.padding.left - this.padding.right);\r
- \r
-\r
- Ext.each(cs, function(c){\r
- if(isStart && c.flex){\r
- ch = Math.floor(availHeight * (c.flex / totalFlex));\r
- leftOver -= ch;\r
- heights.push(ch);\r
- }\r
- }); \r
- \r
- if(this.pack == 'center'){\r
- t += extraHeight ? extraHeight / 2 : 0;\r
- }else if(this.pack == 'end'){\r
- t += extraHeight;\r
- }\r
- Ext.each(cs, function(c){\r
- cm = c.margins;\r
- t += cm.top;\r
- c.setPosition(l + cm.left, t);\r
- if(isStart && c.flex){\r
- ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));\r
- if(isRestore){\r
- restore.push(c.getWidth());\r
- }\r
- c.setSize(availableWidth, ch);\r
- }else{\r
- ch = c.getHeight();\r
- }\r
- t += ch + cm.bottom;\r
- });\r
- \r
- idx = 0;\r
- Ext.each(cs, function(c){\r
- cm = c.margins;\r
- if(this.align == 'stretch'){\r
- c.setWidth((stretchWidth - (cm.left + cm.right)).constrain(\r
- c.minWidth || 0, c.maxWidth || 1000000));\r
- }else if(this.align == 'stretchmax'){\r
- c.setWidth((maxWidth - (cm.left + cm.right)).constrain(\r
- c.minWidth || 0, c.maxWidth || 1000000));\r
- }else{\r
- if(this.align == 'center'){\r
- var diff = availableWidth - (c.getWidth() + cm.left + cm.right);\r
- if(diff > 0){\r
- c.setPosition(l + cm.left + (diff/2), c.y);\r
- }\r
- }\r
- if(isStart && c.flex){\r
- c.setWidth(restore[idx++]);\r
- }\r
- }\r
- }, this);\r
- }\r
- /**\r
- * @property activeItem\r
- * @hide\r
- */\r
-});\r
-\r
-Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;\r
-\r
-/**\r
- * @class Ext.layout.HBoxLayout\r
- * @extends Ext.layout.BoxLayout\r
- * A layout that arranges items horizontally\r
- */\r
-Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {\r
- /**\r
- * @cfg {String} align\r
- * Controls how the child items of the container are aligned. Acceptable configuration values for this\r
- * property are:\r
- * <div class="mdetail-params"><ul>\r
- * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically\r
- * at the <b>left</b> side of the container</div></li>\r
- * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically at the\r
- * <b>mid-height</b> of the container</div></li>\r
- * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill\r
- * the height of the container</div></li>\r
- * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to\r
- * the size of the largest item.</div></li>\r
- */\r
- align : 'top', // top, middle, stretch, strechmax\r
- /**\r
- * @cfg {String} pack\r
- * Controls how the child items of the container are packed together. Acceptable configuration values\r
- * for this property are:\r
- * <div class="mdetail-params"><ul>\r
- * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at\r
- * <b>left</b> side of container</div></li>\r
- * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at\r
- * <b>mid-width</b> of container</div></li>\r
- * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>\r
- * side of container</div></li>\r
- * </ul></div>\r
- */\r
- /**\r
- * @cfg {Number} flex\r
- * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed\r
- * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>\r
- * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with\r
- * a <tt>flex</tt> value specified. Any child items that have either a <tt>flex = 0</tt> or\r
- * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).\r
- */\r
-\r
- // private\r
- onLayout : function(ct, target){\r
- Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);\r
- \r
- var cs = this.getItems(ct), cm, cw, margin,\r
- size = this.getTargetSize(target),\r
- w = size.width - target.getPadding('lr') - this.scrollOffset,\r
- h = size.height - target.getPadding('tb'),\r
- l = this.padding.left, t = this.padding.top,\r
- isStart = this.pack == 'start',\r
- isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,\r
- stretchHeight = h - (this.padding.top + this.padding.bottom),\r
- extraWidth = 0,\r
- maxHeight = 0,\r
- totalFlex = 0,\r
- flexWidth = 0,\r
- usedWidth = 0;\r
- \r
- Ext.each(cs, function(c){\r
- cm = c.margins;\r
- totalFlex += c.flex || 0;\r
- cw = c.getWidth();\r
- margin = cm.left + cm.right;\r
- extraWidth += cw + margin;\r
- flexWidth += margin + (c.flex ? 0 : cw);\r
- maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom);\r
- });\r
- extraWidth = w - extraWidth - this.padding.left - this.padding.right;\r
- \r
- var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom;\r
- switch(this.align){\r
- case 'stretch':\r
- this.innerCt.setSize(w, h);\r
- break;\r
- case 'stretchmax':\r
- case 'top':\r
- this.innerCt.setSize(w, innerCtHeight);\r
- break;\r
- case 'middle':\r
- this.innerCt.setSize(w, h = Math.max(h, innerCtHeight));\r
- break;\r
- }\r
- \r
-\r
- var availWidth = Math.max(0, w - this.padding.left - this.padding.right - flexWidth),\r
- leftOver = availWidth,\r
- widths = [],\r
- restore = [],\r
- idx = 0,\r
- availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom);\r
- \r
-\r
- Ext.each(cs, function(c){\r
- if(isStart && c.flex){\r
- cw = Math.floor(availWidth * (c.flex / totalFlex));\r
- leftOver -= cw;\r
- widths.push(cw);\r
- }\r
- }); \r
- \r
- if(this.pack == 'center'){\r
- l += extraWidth ? extraWidth / 2 : 0;\r
- }else if(this.pack == 'end'){\r
- l += extraWidth;\r
- }\r
- Ext.each(cs, function(c){\r
- cm = c.margins;\r
- l += cm.left;\r
- c.setPosition(l, t + cm.top);\r
- if(isStart && c.flex){\r
- cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0));\r
- if(isRestore){\r
- restore.push(c.getHeight());\r
- }\r
- c.setSize(cw, availableHeight);\r
- }else{\r
- cw = c.getWidth();\r
- }\r
- l += cw + cm.right;\r
- });\r
- \r
- idx = 0;\r
- Ext.each(cs, function(c){\r
- var cm = c.margins;\r
- if(this.align == 'stretch'){\r
- c.setHeight((stretchHeight - (cm.top + cm.bottom)).constrain(\r
- c.minHeight || 0, c.maxHeight || 1000000));\r
- }else if(this.align == 'stretchmax'){\r
- c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain(\r
- c.minHeight || 0, c.maxHeight || 1000000));\r
- }else{\r
- if(this.align == 'middle'){\r
- var diff = availableHeight - (c.getHeight() + cm.top + cm.bottom);\r
- if(diff > 0){\r
- c.setPosition(c.x, t + cm.top + (diff/2));\r
- }\r
- }\r
- if(isStart && c.flex){\r
- c.setHeight(restore[idx++]);\r
- }\r
- }\r
- }, this);\r
- }\r
-\r
- /**\r
- * @property activeItem\r
- * @hide\r
- */\r
-});\r
-\r
+ return (Ext.isIE6 && Ext.isStrict && target.dom == document.body) ? target.getStyleSize() : target.getViewSize(true);
+ },
+
+ getItems: function(ct){
+ var items = [];
+ ct.items.each(function(c){
+ if(c.isVisible()){
+ items.push(c);
+ }
+ });
+ return items;
+ }
+});
+
+/**
+ * @class Ext.layout.VBoxLayout
+ * @extends Ext.layout.BoxLayout
+ * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical
+ * space between child items containing a numeric <code>flex</code> configuration.</p>
+ * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option.
+ */
+Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
+ /**
+ * @cfg {String} align
+ * Controls how the child items of the container are aligned. Acceptable configuration values for this
+ * property are:
+ * <div class="mdetail-params"><ul>
+ * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally
+ * at the <b>left</b> side of the container</div></li>
+ * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the
+ * <b>mid-width</b> of the container</div></li>
+ * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill
+ * the width of the container</div></li>
+ * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to
+ * the size of the largest item.</div></li>
+ * </ul></div>
+ */
+ align : 'left', // left, center, stretch, strechmax
+ /**
+ * @cfg {String} pack
+ * Controls how the child items of the container are packed together. Acceptable configuration values
+ * for this property are:
+ * <div class="mdetail-params"><ul>
+ * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
+ * <b>top</b> side of container</div></li>
+ * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
+ * <b>mid-height</b> of container</div></li>
+ * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>
+ * side of container</div></li>
+ * </ul></div>
+ */
+ /**
+ * @cfg {Number} flex
+ * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
+ * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>
+ * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
+ * a <tt>flex</tt> value specified. Any child items that have either a <tt>flex = 0</tt> or
+ * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
+ */
+
+ // private
+ onLayout : function(ct, target){
+ Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);
+
+ var cs = this.getItems(ct), cm, ch, margin, cl, diff, aw,
+ size = target.getViewSize(true),
+ w = size.width,
+ h = size.height - this.scrollOffset,
+ l = this.padding.left, t = this.padding.top,
+ isStart = this.pack == 'start',
+ stretchWidth = w - (this.padding.left + this.padding.right),
+ extraHeight = 0,
+ maxWidth = 0,
+ totalFlex = 0,
+ flexHeight = 0,
+ usedHeight = 0,
+ idx = 0,
+ heights = [],
+ restore = [],
+ c,
+ csLen = cs.length;
+
+ // Do only width calculations and apply those first, as they can affect height
+ for (i = 0 ; i < csLen; i++) {
+ c = cs[i];
+ cm = c.margins;
+ margin = cm.top + cm.bottom;
+ maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);
+ }
+
+ var innerCtWidth = maxWidth + this.padding.left + this.padding.right;
+ switch(this.align){
+ case 'stretch':
+ this.innerCt.setSize(w, h);
+ break;
+ case 'stretchmax':
+ case 'left':
+ this.innerCt.setSize(innerCtWidth, h);
+ break;
+ case 'center':
+ this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);
+ break;
+ }
+
+ var availableWidth = Math.max(0, w - this.padding.left - this.padding.right);
+ // Apply widths
+ for (i = 0 ; i < csLen; i++) {
+ c = cs[i];
+ cm = c.margins;
+ if(this.align == 'stretch'){
+ c.setWidth((stretchWidth - (cm.left + cm.right)).constrain(
+ c.minWidth || 0, c.maxWidth || 1000000));
+ }else if(this.align == 'stretchmax'){
+ c.setWidth((maxWidth - (cm.left + cm.right)).constrain(
+ c.minWidth || 0, c.maxWidth || 1000000));
+ }else if(isStart && c.flex){
+ c.setWidth();
+ }
+
+ }
+
+ // Do height calculations
+ for (i = 0 ; i < csLen; i++) {
+ c = cs[i];
+ cm = c.margins;
+ totalFlex += c.flex || 0;
+ ch = c.getHeight();
+ margin = cm.top + cm.bottom;
+ extraHeight += ch + margin;
+ flexHeight += margin + (c.flex ? 0 : ch);
+ }
+ extraHeight = h - extraHeight - this.padding.top - this.padding.bottom;
+
+ var availHeight = Math.max(0, h - this.padding.top - this.padding.bottom - flexHeight),
+ leftOver = availHeight;
+ for (i = 0 ; i < csLen; i++) {
+ c = cs[i];
+ if(isStart && c.flex){
+ ch = Math.floor(availHeight * (c.flex / totalFlex));
+ leftOver -= ch;
+ heights.push(ch);
+ }
+ }
+ if(this.pack == 'center'){
+ t += extraHeight ? extraHeight / 2 : 0;
+ }else if(this.pack == 'end'){
+ t += extraHeight;
+ }
+ idx = 0;
+ // Apply heights
+ for (i = 0 ; i < csLen; i++) {
+ c = cs[i];
+ cm = c.margins;
+ t += cm.top;
+ aw = availableWidth;
+ cl = l + cm.left // default left pos
+
+// Adjust left pos for centering
+ if(this.align == 'center'){
+ if((diff = availableWidth - (c.getWidth() + cm.left + cm.right)) > 0){
+ cl += (diff/2);
+ aw -= diff;
+ }
+ }
+
+ c.setPosition(cl, t);
+ if(isStart && c.flex){
+ ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));
+ c.setSize(aw, ch);
+ }else{
+ ch = c.getHeight();
+ }
+ t += ch + cm.bottom;
+ }
+ }
+});
+
+Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
+
+/**
+ * @class Ext.layout.HBoxLayout
+ * @extends Ext.layout.BoxLayout
+ * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal
+ * space between child items containing a numeric <code>flex</code> configuration.</p>
+ * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option.
+ */
+Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
+ /**
+ * @cfg {String} align
+ * Controls how the child items of the container are aligned. Acceptable configuration values for this
+ * property are:
+ * <div class="mdetail-params"><ul>
+ * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically
+ * at the <b>top</b> of the container</div></li>
+ * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically in the
+ * <b>middle</b> of the container</div></li>
+ * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill
+ * the height of the container</div></li>
+ * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to
+ * the height of the largest item.</div></li>
+ */
+ align : 'top', // top, middle, stretch, strechmax
+ /**
+ * @cfg {String} pack
+ * Controls how the child items of the container are packed together. Acceptable configuration values
+ * for this property are:
+ * <div class="mdetail-params"><ul>
+ * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
+ * <b>left</b> side of container</div></li>
+ * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
+ * <b>mid-width</b> of container</div></li>
+ * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>
+ * side of container</div></li>
+ * </ul></div>
+ */
+ /**
+ * @cfg {Number} flex
+ * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
+ * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>
+ * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
+ * a <tt>flex</tt> value specified. Any child items that have either a <tt>flex = 0</tt> or
+ * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
+ */
+
+ // private
+ onLayout : function(ct, target){
+ Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);
+
+ var cs = this.getItems(ct), cm, cw, margin, ch, diff,
+ size = target.getViewSize(true),
+ w = size.width - this.scrollOffset,
+ h = size.height,
+ l = this.padding.left, t = this.padding.top,
+ isStart = this.pack == 'start',
+ isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
+ stretchHeight = h - (this.padding.top + this.padding.bottom),
+ extraWidth = 0,
+ maxHeight = 0,
+ totalFlex = 0,
+ flexWidth = 0,
+ usedWidth = 0;
+
+ Ext.each(cs, function(c){
+ cm = c.margins;
+ totalFlex += c.flex || 0;
+ cw = c.getWidth();
+ margin = cm.left + cm.right;
+ extraWidth += cw + margin;
+ flexWidth += margin + (c.flex ? 0 : cw);
+ maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom);
+ });
+ extraWidth = w - extraWidth - this.padding.left - this.padding.right;
+
+ var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom;
+ switch(this.align){
+ case 'stretch':
+ this.innerCt.setSize(w, h);
+ break;
+ case 'stretchmax':
+ case 'top':
+ this.innerCt.setSize(w, innerCtHeight);
+ break;
+ case 'middle':
+ this.innerCt.setSize(w, h = Math.max(h, innerCtHeight));
+ break;
+ }
+
+
+ var availWidth = Math.max(0, w - this.padding.left - this.padding.right - flexWidth),
+ leftOver = availWidth,
+ widths = [],
+ restore = [],
+ idx = 0,
+ availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom);
+
+
+ Ext.each(cs, function(c){
+ if(isStart && c.flex){
+ cw = Math.floor(availWidth * (c.flex / totalFlex));
+ leftOver -= cw;
+ widths.push(cw);
+ }
+ });
+
+ if(this.pack == 'center'){
+ l += extraWidth ? extraWidth / 2 : 0;
+ }else if(this.pack == 'end'){
+ l += extraWidth;
+ }
+ Ext.each(cs, function(c){
+ cm = c.margins;
+ l += cm.left;
+ c.setPosition(l, t + cm.top);
+ if(isStart && c.flex){
+ cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0));
+ if(isRestore){
+ restore.push(c.getHeight());
+ }
+ c.setSize(cw, availableHeight);
+ }else{
+ cw = c.getWidth();
+ }
+ l += cw + cm.right;
+ });
+
+ idx = 0;
+ Ext.each(cs, function(c){
+ cm = c.margins;
+ ch = c.getHeight();
+ if(isStart && c.flex){
+ ch = restore[idx++];
+ }
+ if(this.align == 'stretch'){
+ c.setHeight((stretchHeight - (cm.top + cm.bottom)).constrain(
+ c.minHeight || 0, c.maxHeight || 1000000));
+ }else if(this.align == 'stretchmax'){
+ c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain(
+ c.minHeight || 0, c.maxHeight || 1000000));
+ }else{
+ if(this.align == 'middle'){
+ diff = availableHeight - (ch + cm.top + cm.bottom);
+ ch = t + cm.top + (diff/2);
+ if(diff > 0){
+ c.setPosition(c.x, ch);
+ }
+ }
+ if(isStart && c.flex){
+ c.setHeight(ch);
+ }
+ }
+ }, this);
+ }
+});
+
Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
/**\r
* @class Ext.Viewport\r
collapsible: true,\r
title: 'Navigation',\r
width: 200\r
- // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout} \r
+ // the west region might typically utilize a {@link Ext.tree.TreePanel TreePanel} or a Panel with {@link Ext.layout.AccordionLayout Accordion layout}\r
}, {\r
region: 'south',\r
title: 'Title for Panel',\r
* @xtype viewport\r
*/\r
Ext.Viewport = Ext.extend(Ext.Container, {\r
- /*\r
- * Privatize config options which, if used, would interfere with the\r
- * correct operation of the Viewport as the sole manager of the\r
- * layout of the document body.\r
- */\r
+ /*\r
+ * Privatize config options which, if used, would interfere with the\r
+ * correct operation of the Viewport as the sole manager of the\r
+ * layout of the document body.\r
+ */\r
/**\r
* @cfg {Mixed} applyTo @hide\r
- */\r
+ */\r
/**\r
* @cfg {Boolean} allowDomMove @hide\r
- */\r
+ */\r
/**\r
* @cfg {Boolean} hideParent @hide\r
- */\r
+ */\r
/**\r
* @cfg {Mixed} renderTo @hide\r
- */\r
+ */\r
/**\r
* @cfg {Boolean} hideParent @hide\r
- */\r
+ */\r
/**\r
* @cfg {Number} height @hide\r
- */\r
+ */\r
/**\r
* @cfg {Number} width @hide\r
- */\r
+ */\r
/**\r
* @cfg {Boolean} autoHeight @hide\r
- */\r
+ */\r
/**\r
* @cfg {Boolean} autoWidth @hide\r
- */\r
+ */\r
/**\r
* @cfg {Boolean} deferHeight @hide\r
- */\r
+ */\r
/**\r
* @cfg {Boolean} monitorResize @hide\r
- */\r
+ */\r
+\r
initComponent : function() {\r
Ext.Viewport.superclass.initComponent.call(this);\r
document.getElementsByTagName('html')[0].className += ' x-viewport';\r
},\r
\r
fireResize : function(w, h){\r
- this.fireEvent('resize', this, w, h, w, h);\r
+ this.onResize(w, h, w, h);\r
}\r
});\r
-Ext.reg('viewport', Ext.Viewport);/**
+Ext.reg('viewport', Ext.Viewport);\r
+/**
* @class Ext.Panel
* @extends Ext.Container
* <p>Panel is a container that has specific functionality and structural components that make
* of being configured with a {@link Ext.Container#layout layout}, and containing child Components.</p>
* <p>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 <tt><b>{@link Ext.Container#layout layout}</b></tt> schemes. By
+ * those child elements need to be sized using one of Ext's built-in <code><b>{@link Ext.Container#layout layout}</b></code> schemes. By
* 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 <b>does not apply any sizing</b>
* at all.</p>
/**
* The Panel's header {@link Ext.Element Element}. Read-only.
* <p>This Element is used to house the {@link #title} and {@link #tools}</p>
- * <br><p><b>Note</b>: see the Note for <tt>{@link Ext.Component#el el} also.</p>
+ * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
* @type Ext.Element
* @property header
*/
* <p>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.
- * <br><p><b>Note</b>: see the Note for <tt>{@link Ext.Component#el el} also.</p>
+ * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
* @type Ext.Element
* @property body
*/
* <p>A {@link Ext.DomHelper DomHelper} element specification object may be specified for any
* Panel Element.</p>
* <p>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 (<tt>baseCls</tt> will be
- * replaced by <tt>{@link #baseCls}</tt>):</p>
+ * create a child element with the commensurate Default class name (<code>baseCls</code> will be
+ * replaced by <code>{@link #baseCls}</code>):</p>
* <pre>
* Panel Default Default Custom Additional Additional
* Element element class element class style
footerStyle: 'background-color:red' // see {@link #bodyStyle}
});
* </code></pre>
- * <p>The example above also explicitly creates a <tt>{@link #footer}</tt> with custom markup and
+ * <p>The example above also explicitly creates a <code>{@link #footer}</code> with custom markup and
* styling applied.</p>
*/
/**
* @cfg {Object} headerCfg
* <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
- * of this Panel's {@link #header} Element. See <tt>{@link #bodyCfg}</tt> also.</p>
+ * of this Panel's {@link #header} Element. See <code>{@link #bodyCfg}</code> also.</p>
*/
/**
* @cfg {Object} bwrapCfg
* <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
- * of this Panel's {@link #bwrap} Element. See <tt>{@link #bodyCfg}</tt> also.</p>
+ * of this Panel's {@link #bwrap} Element. See <code>{@link #bodyCfg}</code> also.</p>
*/
/**
* @cfg {Object} tbarCfg
* <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
- * of this Panel's {@link #tbar} Element. See <tt>{@link #bodyCfg}</tt> also.</p>
+ * of this Panel's {@link #tbar} Element. See <code>{@link #bodyCfg}</code> also.</p>
*/
/**
* @cfg {Object} bbarCfg
* <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
- * of this Panel's {@link #bbar} Element. See <tt>{@link #bodyCfg}</tt> also.</p>
+ * of this Panel's {@link #bbar} Element. See <code>{@link #bodyCfg}</code> also.</p>
*/
/**
* @cfg {Object} footerCfg
* <p>A {@link Ext.DomHelper DomHelper} element specification object specifying the element structure
- * of this Panel's {@link #footer} Element. See <tt>{@link #bodyCfg}</tt> also.</p>
+ * of this Panel's {@link #footer} Element. See <code>{@link #bodyCfg}</code> also.</p>
*/
/**
* @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 <tt>true</tt>
- * to enable closing in such situations. Defaults to <tt>false</tt>.
+ * {@link Ext.Window}) or a Panel Class within an {@link Ext.TabPanel}. Specify <code>true</code>
+ * to enable closing in such situations. Defaults to <code>false</code>.
*/
/**
* The Panel's footer {@link Ext.Element Element}. Read-only.
- * <p>This Element is used to house the Panel's <tt>{@link #buttons}</tt> or <tt>{@link #fbar}</tt>.</p>
- * <br><p><b>Note</b>: see the Note for <tt>{@link Ext.Component#el el} also.</p>
+ * <p>This Element is used to house the Panel's <code>{@link #buttons}</code> or <code>{@link #fbar}</code>.</p>
+ * <br><p><b>Note</b>: see the Note for <code>{@link Ext.Component#el el}</code> also.</p>
* @type Ext.Element
* @property footer
*/
/**
* @cfg {Mixed} applyTo
* <p>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 <tt>applyTo</tt> is used,
+ * the document that specifies some panel-specific structural markup. When <code>applyTo</code> 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.</p>
* <p>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}.</p>
- * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not<b> be updated by a load
+ * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> 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 <b>will</b> be submitted because form
* submission parameters are collected from the DOM tree.</p>
* <p>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.</p>
* <p>After render, the <code>fbar</code> property will be an {@link Ext.Toolbar Toolbar} instance.</p>
- * <p>If <tt>{@link #buttons}</tt> are specified, they will supersede the <tt>fbar</tt> configuration property.</p>
- * The Panel's <tt>{@link #buttonAlign}</tt> configuration affects the layout of these items, for example:
+ * <p>If <code>{@link #buttons}</code> are specified, they will supersede the <code>fbar</code> configuration property.</p>
+ * The Panel's <code>{@link #buttonAlign}</code> configuration affects the layout of these items, for example:
* <pre><code>
var w = new Ext.Window({
height: 250,
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'
}]
}).show();
* </code></pre>
- * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not<b> be updated by a load
+ * <p><b>Note:</b> Although a Toolbar may contain Field components, these will <b>not</b> 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 <b>will</b> be submitted because form
* submission parameters are collected from the DOM tree.</p>
*/
/**
* @cfg {Boolean} header
- * <tt>true</tt> to create the Panel's header element explicitly, <tt>false</tt> to skip creating
- * it. If a <tt>{@link #title}</tt> is set the header will be created automatically, otherwise it will not.
- * If a <tt>{@link #title}</tt> is set but <tt>header</tt> is explicitly set to <tt>false</tt>, the header
+ * <code>true</code> to create the Panel's header element explicitly, <code>false</code> to skip creating
+ * it. If a <code>{@link #title}</code> is set the header will be created automatically, otherwise it will not.
+ * If a <code>{@link #title}</code> is set but <code>header</code> is explicitly set to <code>false</code>, the header
* will not be rendered.
*/
/**
* @cfg {Boolean} footer
- * <tt>true</tt> to create the footer element explicitly, false to skip creating it. The footer
- * will be created automatically if <tt>{@link #buttons}</tt> or a <tt>{@link #fbar}</tt> have
- * been configured. See <tt>{@link #bodyCfg}</tt> for an example.
+ * <code>true</code> to create the footer element explicitly, false to skip creating it. The footer
+ * will be created automatically if <code>{@link #buttons}</code> or a <code>{@link #fbar}</code> have
+ * been configured. See <code>{@link #bodyCfg}</code> for an example.
*/
/**
* @cfg {String} title
* The title text to be used as innerHTML (html tags are accepted) to display in the panel
- * <tt>{@link #header}</tt> (defaults to ''). When a <tt>title</tt> is specified the
- * <tt>{@link #header}</tt> element will automatically be created and displayed unless
- * {@link #header} is explicitly set to <tt>false</tt>. If you do not want to specify a
- * <tt>title</tt> at config time, but you may want one later, you must either specify a non-empty
- * <tt>title</tt> (a blank space ' ' will do) or <tt>header:true</tt> so that the container
+ * <code>{@link #header}</code> (defaults to ''). When a <code>title</code> is specified the
+ * <code>{@link #header}</code> element will automatically be created and displayed unless
+ * {@link #header} is explicitly set to <code>false</code>. If you do not want to specify a
+ * <code>title</code> at config time, but you may want one later, you must either specify a non-empty
+ * <code>title</code> (a blank space ' ' will do) or <code>header:true</code> so that the container
* element will get created.
*/
/**
* @cfg {Array} buttons
- * <tt>buttons</tt> will be used as <tt>{@link Ext.Container#items items}</tt> for the toolbar in
- * the footer (<tt>{@link #fbar}</tt>). Typically the value of this configuration property will be
+ * <code>buttons</code> will be used as <code>{@link Ext.Container#items items}</code> for the toolbar in
+ * the footer (<code>{@link #fbar}</code>). 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 <tt>minWidth</tt> or the Panel is configured with <tt>minButtonWidth</tt>,
+ * If an item is configured with <code>minWidth</code> or the Panel is configured with <code>minButtonWidth</code>,
* that width will be applied to the item.
*/
/**
*/
/**
* @cfg {Boolean} frame
- * <tt>false</tt> by default to render with plain 1px square borders. <tt>true</tt> to render with
+ * <code>false</code> by default to render with plain 1px square borders. <code>true</code> to render with
* 9 elements, complete with custom rounded corners (also see {@link Ext.Element#boxWrap}).
* <p>The template generated for each condition is depicted below:</p><pre><code>
*
/**
* @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 <tt><b></b>tools.<i><tool-type></i></tt>
+ * stored as an {@link Ext.Element Element} referenced by a public property called <code><b></b>tools.<i><tool-type></i></code>
* <p>Each tool config may contain the following properties:
* <div class="mdetail-params"><ul>
* <li><b>id</b> : String<div class="sub-desc"><b>Required.</b> The type
- * of tool to create. By default, this assigns a CSS class of the form <tt>x-tool-<i><tool-type></i></tt> to the
+ * of tool to create. By default, this assigns a CSS class of the form <code>x-tool-<i><tool-type></i></code> 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:
* <ul>
- * <div class="x-tool x-tool-toggle" style="float:left; margin-right:5;"> </div><div><tt> toggle</tt> (Created by default when {@link #collapsible} is <tt>true</tt>)</div>
- * <div class="x-tool x-tool-close" style="float:left; margin-right:5;"> </div><div><tt> close</tt></div>
- * <div class="x-tool x-tool-minimize" style="float:left; margin-right:5;"> </div><div><tt> minimize</tt></div>
- * <div class="x-tool x-tool-maximize" style="float:left; margin-right:5;"> </div><div><tt> maximize</tt></div>
- * <div class="x-tool x-tool-restore" style="float:left; margin-right:5;"> </div><div><tt> restore</tt></div>
- * <div class="x-tool x-tool-gear" style="float:left; margin-right:5;"> </div><div><tt> gear</tt></div>
- * <div class="x-tool x-tool-pin" style="float:left; margin-right:5;"> </div><div><tt> pin</tt></div>
- * <div class="x-tool x-tool-unpin" style="float:left; margin-right:5;"> </div><div><tt> unpin</tt></div>
- * <div class="x-tool x-tool-right" style="float:left; margin-right:5;"> </div><div><tt> right</tt></div>
- * <div class="x-tool x-tool-left" style="float:left; margin-right:5;"> </div><div><tt> left</tt></div>
- * <div class="x-tool x-tool-up" style="float:left; margin-right:5;"> </div><div><tt> up</tt></div>
- * <div class="x-tool x-tool-down" style="float:left; margin-right:5;"> </div><div><tt> down</tt></div>
- * <div class="x-tool x-tool-refresh" style="float:left; margin-right:5;"> </div><div><tt> refresh</tt></div>
- * <div class="x-tool x-tool-minus" style="float:left; margin-right:5;"> </div><div><tt> minus</tt></div>
- * <div class="x-tool x-tool-plus" style="float:left; margin-right:5;"> </div><div><tt> plus</tt></div>
- * <div class="x-tool x-tool-help" style="float:left; margin-right:5;"> </div><div><tt> help</tt></div>
- * <div class="x-tool x-tool-search" style="float:left; margin-right:5;"> </div><div><tt> search</tt></div>
- * <div class="x-tool x-tool-save" style="float:left; margin-right:5;"> </div><div><tt> save</tt></div>
- * <div class="x-tool x-tool-print" style="float:left; margin-right:5;"> </div><div><tt> print</tt></div>
+ * <div class="x-tool x-tool-toggle" style="float:left; margin-right:5;"> </div><div><code> toggle</code> (Created by default when {@link #collapsible} is <code>true</code>)</div>
+ * <div class="x-tool x-tool-close" style="float:left; margin-right:5;"> </div><div><code> close</code></div>
+ * <div class="x-tool x-tool-minimize" style="float:left; margin-right:5;"> </div><div><code> minimize</code></div>
+ * <div class="x-tool x-tool-maximize" style="float:left; margin-right:5;"> </div><div><code> maximize</code></div>
+ * <div class="x-tool x-tool-restore" style="float:left; margin-right:5;"> </div><div><code> restore</code></div>
+ * <div class="x-tool x-tool-gear" style="float:left; margin-right:5;"> </div><div><code> gear</code></div>
+ * <div class="x-tool x-tool-pin" style="float:left; margin-right:5;"> </div><div><code> pin</code></div>
+ * <div class="x-tool x-tool-unpin" style="float:left; margin-right:5;"> </div><div><code> unpin</code></div>
+ * <div class="x-tool x-tool-right" style="float:left; margin-right:5;"> </div><div><code> right</code></div>
+ * <div class="x-tool x-tool-left" style="float:left; margin-right:5;"> </div><div><code> left</code></div>
+ * <div class="x-tool x-tool-up" style="float:left; margin-right:5;"> </div><div><code> up</code></div>
+ * <div class="x-tool x-tool-down" style="float:left; margin-right:5;"> </div><div><code> down</code></div>
+ * <div class="x-tool x-tool-refresh" style="float:left; margin-right:5;"> </div><div><code> refresh</code></div>
+ * <div class="x-tool x-tool-minus" style="float:left; margin-right:5;"> </div><div><code> minus</code></div>
+ * <div class="x-tool x-tool-plus" style="float:left; margin-right:5;"> </div><div><code> plus</code></div>
+ * <div class="x-tool x-tool-help" style="float:left; margin-right:5;"> </div><div><code> help</code></div>
+ * <div class="x-tool x-tool-search" style="float:left; margin-right:5;"> </div><div><code> search</code></div>
+ * <div class="x-tool x-tool-save" style="float:left; margin-right:5;"> </div><div><code> save</code></div>
+ * <div class="x-tool x-tool-print" style="float:left; margin-right:5;"> </div><div><code> print</code></div>
* </ul></div></li>
* <li><b>handler</b> : Function<div class="sub-desc"><b>Required.</b> The function to
* call when clicked. Arguments passed are:<ul>
* <li><b>event</b> : Ext.EventObject<div class="sub-desc">The click event.</div></li>
* <li><b>toolEl</b> : Ext.Element<div class="sub-desc">The tool Element.</div></li>
* <li><b>panel</b> : Ext.Panel<div class="sub-desc">The host Panel</div></li>
- * <li><b>tc</b> : Ext.Panel<div class="sub-desc">The tool configuration object</div></li>
+ * <li><b>tc</b> : Object<div class="sub-desc">The tool configuration object</div></li>
* </ul></div></li>
* <li><b>stopEvent</b> : Boolean<div class="sub-desc">Defaults to true. Specify as false to allow click event to propagate.</div></li>
* <li><b>scope</b> : Object<div class="sub-desc">The scope in which to call the handler.</div></li>
}
}]
</code></pre>
- * <p>For the custom id of <tt>'help'</tt> define two relevant css classes with a link to
+ * <p>For the custom id of <code>'help'</code> define two relevant css classes with a link to
* a 15x15 image:</p>
* <pre><code>
.x-tool-help {background-image: url(images/help.png);}
height:300,
closeAction:'hide'
});</code></pre>
- * <p>Note that the CSS class "x-tool-pdf" should have an associated style rule which provides an
+ * <p>Note that the CSS class 'x-tool-pdf' should have an associated style rule which provides an
* appropriate background image, something like:</p>
<pre><code>
a.x-tool-pdf {background-image: url(../shared/extjs/images/pdf.gif)!important;}
*/
/**
* @cfg {Boolean} hideCollapseTool
- * <tt>true</tt> to hide the expand/collapse toggle button when <code>{@link #collapsible} == true</code>,
- * <tt>false</tt> to display it (defaults to <tt>false</tt>).
+ * <code>true</code> to hide the expand/collapse toggle button when <code>{@link #collapsible} == true</code>,
+ * <code>false</code> to display it (defaults to <code>false</code>).
*/
/**
* @cfg {Boolean} titleCollapse
- * <tt>true</tt> to allow expanding and collapsing the panel (when <tt>{@link #collapsible} = true</tt>)
- * by clicking anywhere in the header bar, <tt>false</tt>) to allow it only by clicking to tool button
- * (defaults to <tt>false</tt>)). If this panel is a child item of a border layout also see the
+ * <code>true</code> to allow expanding and collapsing the panel (when <code>{@link #collapsible} = true</code>)
+ * by clicking anywhere in the header bar, <code>false</code>) to allow it only by clicking to tool button
+ * (defaults to <code>false</code>)). If this panel is a child item of a border layout also see the
* {@link Ext.layout.BorderLayout.Region BorderLayout.Region}
- * <tt>{@link Ext.layout.BorderLayout.Region#floatable floatable}</tt> config option.
- */
- /**
- * @cfg {Boolean} autoScroll
- * <tt>true</tt> to use overflow:'auto' on the panel's body element and show scroll bars automatically when
- * necessary, <tt>false</tt> to clip any overflowing content (defaults to <tt>false</tt>).
+ * <code>{@link Ext.layout.BorderLayout.Region#floatable floatable}</code> config option.
*/
+
/**
* @cfg {Mixed} floating
* <p>This property is used to configure the underlying {@link Ext.Layer}. Acceptable values for this
* configuration property are:</p><div class="mdetail-params"><ul>
- * <li><b><tt>false</tt></b> : <b>Default.</b><div class="sub-desc">Display the panel inline where it is
+ * <li><b><code>false</code></b> : <b>Default.</b><div class="sub-desc">Display the panel inline where it is
* rendered.</div></li>
- * <li><b><tt>true</tt></b> : <div class="sub-desc">Float the panel (absolute position it with automatic
+ * <li><b><code>true</code></b> : <div class="sub-desc">Float the panel (absolute position it with automatic
* shimming and shadow).<ul>
* <div class="sub-desc">Setting floating to true will create an Ext.Layer for this panel and display the
* panel at negative offsets so that it is hidden.</div>
* <div class="sub-desc">Since the panel will be absolute positioned, the position must be set explicitly
- * <i>after</i> render (e.g., <tt>myPanel.setPosition(100,100);</tt>).</div>
+ * <i>after</i> render (e.g., <code>myPanel.setPosition(100,100);</code>).</div>
* <div class="sub-desc"><b>Note</b>: 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.</div>
* </ul></div></li>
- * <li><b><tt>{@link Ext.Layer object}</tt></b> : <div class="sub-desc">The specified object will be used
+ * <li><b><code>{@link Ext.Layer object}</code></b> : <div class="sub-desc">The specified object will be used
* as the configuration object for the {@link Ext.Layer} that will be created.</div></li>
* </ul></div>
*/
/**
* @cfg {Boolean/String} shadow
- * <tt>true</tt> (or a valid Ext.Shadow {@link Ext.Shadow#mode} value) to display a shadow behind the
- * panel, <tt>false</tt> to display no shadow (defaults to <tt>'sides'</tt>). Note that this option
- * only applies when <tt>{@link #floating} = true</tt>.
+ * <code>true</code> (or a valid Ext.Shadow {@link Ext.Shadow#mode} value) to display a shadow behind the
+ * panel, <code>false</code> to display no shadow (defaults to <code>'sides'</code>). Note that this option
+ * only applies when <code>{@link #floating} = true</code>.
*/
/**
* @cfg {Number} shadowOffset
- * The number of pixels to offset the shadow if displayed (defaults to <tt>4</tt>). Note that this
- * option only applies when <tt>{@link #floating} = true</tt>.
+ * The number of pixels to offset the shadow if displayed (defaults to <code>4</code>). Note that this
+ * option only applies when <code>{@link #floating} = true</code>.
*/
/**
* @cfg {Boolean} shim
- * <tt>false</tt> to disable the iframe shim in browsers which need one (defaults to <tt>true</tt>).
- * Note that this option only applies when <tt>{@link #floating} = true</tt>.
- */
- /**
- * @cfg {String/Object} html
- * An HTML fragment, or a {@link Ext.DomHelper DomHelper} specification to use as the panel's body
- * content (defaults to ''). The HTML content is added by the Panel's {@link #afterRender} method,
- * and so the document will not contain this HTML at the time the {@link #render} event is fired.
- * This content is inserted into the body <i>before</i> any configured {@link #contentEl} is appended.
- */
- /**
- * @cfg {String} contentEl
- * <p>Specify the <tt>id</tt> of an existing HTML node to use as the panel's body content
- * (defaults to '').</p><div><ul>
- * <li><b>Description</b> : <ul>
- * <div class="sub-desc">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
- * <i>when the Panel is rendered</i> to use as the content (it is not going to be the
- * actual panel itself).</div>
- * </ul></li>
- * <li><b>Notes</b> : <ul>
- * <div class="sub-desc">The specified HTML Element is appended to the Panel's {@link #body} Element by the
- * Panel's {@link #afterRender} method <i>after any configured {@link #html HTML} has
- * been inserted</i>, and so the document will not contain this HTML at the time the
- * {@link #render} event is fired.</div>
- * <div class="sub-desc">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.</div>
- * <div class="sub-desc">Add either the <tt>x-hidden</tt> or the <tt>x-hide-display</tt> CSS class to
- * prevent a brief flicker of the content before it is rendered to the panel.</div>
- * </ul></li>
- * </ul></div>
+ * <code>false</code> to disable the iframe shim in browsers which need one (defaults to <code>true</code>).
+ * Note that this option only applies when <code>{@link #floating} = true</code>.
*/
/**
* @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 <tt>null</tt>).
+ * used to assign custom key handling to this panel (defaults to <code>null</code>).
*/
/**
* @cfg {Boolean/Object} draggable
- * <p><tt>true</tt> to enable dragging of this Panel (defaults to <tt>false</tt>).</p>
+ * <p><code>true</code> to enable dragging of this Panel (defaults to <code>false</code>).</p>
* <p>For custom drag/drop implementations, an <b>Ext.Panel.DD</b> config could also be passed
- * in this config instead of <tt>true</tt>. Ext.Panel.DD is an internal, undocumented class which
+ * in this config instead of <code>true</code>. 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.:
}).show();
</code></pre>
*/
- /**
- * @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 <tt>false</tt>). An important note when using the disabled
+ * Render this panel disabled (default is <code>false</code>). 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
*/
/**
* @cfg {Boolean} autoHeight
- * <tt>true</tt> to use height:'auto', <tt>false</tt> to use fixed height (defaults to <tt>false</tt>).
- * <b>Note</b>: Setting <tt>autoHeight:true</tt> means that the browser will manage the panel's height
+ * <code>true</code> to use height:'auto', <code>false</code> to use fixed height (defaults to <code>false</code>).
+ * <b>Note</b>: Setting <code>autoHeight: true</code> 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 (<tt>fit</tt>, <tt>border</tt>, etc.) then setting <tt>autoHeight:true</tt>
+ * manages dimensions (<code>fit</code>, <code>border</code>, etc.) then setting <code>autoHeight: true</code>
* 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.
*/
/**
* @cfg {String} baseCls
- * The base CSS class to apply to this panel's element (defaults to <tt>'x-panel'</tt>).
- * <p>Another option available by default is to specify <tt>'x-plain'</tt> which strips all styling
+ * The base CSS class to apply to this panel's element (defaults to <code>'x-panel'</code>).
+ * <p>Another option available by default is to specify <code>'x-plain'</code> which strips all styling
* except for required attributes for Ext layouts to function (e.g. overflow:hidden).
- * See <tt>{@link #unstyled}</tt> also.</p>
+ * See <code>{@link #unstyled}</code> also.</p>
*/
baseCls : 'x-panel',
/**
* @cfg {String} collapsedCls
* A CSS class to add to the panel's element after it has been collapsed (defaults to
- * <tt>'x-panel-collapsed'</tt>).
+ * <code>'x-panel-collapsed'</code>).
*/
collapsedCls : 'x-panel-collapsed',
/**
* @cfg {Boolean} maskDisabled
- * <tt>true</tt> to mask the panel when it is {@link #disabled}, <tt>false</tt> to not mask it (defaults
- * to <tt>true</tt>). Either way, the panel will always tell its contained elements to disable themselves
+ * <code>true</code> to mask the panel when it is {@link #disabled}, <code>false</code> to not mask it (defaults
+ * to <code>true</code>). 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
- * <tt>true</tt> to animate the transition when the panel is collapsed, <tt>false</tt> to skip the
- * animation (defaults to <tt>true</tt> if the {@link Ext.Fx} class is available, otherwise <tt>false</tt>).
+ * <code>true</code> to animate the transition when the panel is collapsed, <code>false</code> to skip the
+ * animation (defaults to <code>true</code> if the {@link Ext.Fx} class is available, otherwise <code>false</code>).
*/
animCollapse : Ext.enableFx,
/**
* @cfg {Boolean} headerAsText
- * <tt>true</tt> to display the panel <tt>{@link #title}</tt> in the <tt>{@link #header}</tt>,
- * <tt>false</tt> to hide it (defaults to <tt>true</tt>).
+ * <code>true</code> to display the panel <code>{@link #title}</code> in the <code>{@link #header}</code>,
+ * <code>false</code> to hide it (defaults to <code>true</code>).
*/
headerAsText : true,
/**
* @cfg {String} buttonAlign
- * The alignment of any {@link #buttons} added to this panel. Valid values are <tt>'right'</tt>,
- * <tt>'left'</tt> and <tt>'center'</tt> (defaults to <tt>'right'</tt>).
+ * The alignment of any {@link #buttons} added to this panel. Valid values are <code>'right'</code>,
+ * <code>'left'</code> and <code>'center'</code> (defaults to <code>'right'</code>).
*/
buttonAlign : 'right',
/**
* @cfg {Boolean} collapsed
- * <tt>true</tt> to render the panel collapsed, <tt>false</tt> to render it expanded (defaults to
- * <tt>false</tt>).
+ * <code>true</code> to render the panel collapsed, <code>false</code> to render it expanded (defaults to
+ * <code>false</code>).
*/
collapsed : false,
/**
* @cfg {Boolean} collapseFirst
- * <tt>true</tt> to make sure the collapse/expand toggle button always renders first (to the left of)
- * any other tools in the panel's title bar, <tt>false</tt> to render it last (defaults to <tt>true</tt>).
+ * <code>true</code> to make sure the collapse/expand toggle button always renders first (to the left of)
+ * any other tools in the panel's title bar, <code>false</code> to render it last (defaults to <code>true</code>).
*/
collapseFirst : true,
/**
* @cfg {Number} minButtonWidth
- * Minimum width in pixels of all {@link #buttons} in this panel (defaults to <tt>75</tt>)
+ * Minimum width in pixels of all {@link #buttons} in this panel (defaults to <code>75</code>)
*/
minButtonWidth : 75,
/**
* @cfg {Boolean} unstyled
- * Overrides the <tt>{@link #baseCls}</tt> setting to <tt>{@link #baseCls} = 'x-plain'</tt> which renders
+ * Overrides the <code>{@link #baseCls}</code> setting to <code>{@link #baseCls} = 'x-plain'</code> which renders
* the panel unstyled except for required attributes for Ext layouts to function (e.g. overflow:hidden).
*/
/**
* 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<div class="mdetail-params"><ul>
- * <li><tt>header</tt></li>
- * <li><tt>tbar</tt> (top bar)</li>
- * <li><tt>body</tt></li>
- * <li><tt>bbar</tt> (bottom bar)</li>
- * <li><tt>footer</tt></li>
+ * <li><code>header</code></li>
+ * <li><code>tbar</code> (top bar)</li>
+ * <li><code>body</code></li>
+ * <li><code>bbar</code> (bottom bar)</li>
+ * <li><code>footer</code></li>
* </ul></div>
- * Defaults to '<tt>body</tt>'.
+ * Defaults to '<code>body</code>'.
*/
elements : 'body',
/**
* @cfg {Boolean} preventBodyReset
- * Defaults to <tt>false</tt>. When set to <tt>true</tt>, an extra css class <tt>'x-panel-normal'</tt>
+ * Defaults to <code>false</code>. When set to <code>true</code>, an extra css class <code>'x-panel-normal'</code>
* 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 <b>body</b> element (not the header,
* footer, etc.).
*/
preventBodyReset : false,
+ /**
+ * @cfg {Number/String} padding
+ * A shortcut for setting a padding style on the body element. The value can either be
+ * a number to be applied to all sides, or a normal css string describing padding.
+ * Defaults to <tt>undefined</tt>.
+ *
+ */
+ padding: undefined,
+
+ /** @cfg {String} resizeEvent
+ * The event to listen to for resizing in layouts. Defaults to <tt>'bodyresize'</tt>.
+ */
+ 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
// could lead to unexpected or undesirable results.
this.baseCls = 'x-plain';
}
+
+ this.toolbars = [];
// shortcuts
if(this.tbar){
this.elements += ',tbar';
- if(Ext.isObject(this.tbar)){
- this.topToolbar = this.tbar;
- }
+ this.topToolbar = this.createToolbar(this.tbar);
delete this.tbar;
+
}
if(this.bbar){
this.elements += ',bbar';
- if(Ext.isObject(this.bbar)){
- this.bottomToolbar = this.bbar;
- }
+ this.bottomToolbar = this.createToolbar(this.bbar);
delete this.bbar;
}
}
if(this.buttons){
- this.elements += ',footer';
- var btns = this.buttons;
- /**
- * This Panel's Array of buttons as created from the <tt>{@link #buttons}</tt>
- * 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'));
- }else{
- this.addButton(btns[i]);
- }
- }
+ this.fbar = this.buttons;
+ delete this.buttons;
}
if(this.fbar){
- this.elements += ',footer';
+ this.createFbar(this.fbar);
}
if(this.autoLoad){
this.on('render', this.doAutoLoad, this, {delay:10});
}
},
+ // private
+ createFbar : function(fbar){
+ var min = this.minButtonWidth;
+ this.elements += ',footer';
+ this.fbar = this.createToolbar(fbar, {
+ buttonAlign: this.buttonAlign,
+ toolbarCls: 'x-panel-fbar',
+ enableOverflow: false,
+ defaults: function(c){
+ return {
+ minWidth: c.minWidth || min
+ };
+ }
+ });
+ //@compat addButton and buttons could possibly be removed
+ //@target 4.0
+ /**
+ * This Panel's Array of buttons as created from the <code>{@link #buttons}</code>
+ * config property. Read only.
+ * @type Array
+ * @property buttons
+ */
+ this.fbar.items.each(function(c){
+ c.minWidth = c.minWidth || this.minButtonWidth;
+ }, this);
+ this.buttons = this.fbar.items.items;
+ },
+
+ // private
+ createToolbar: function(tb, options){
+ var result;
+ // Convert array to proper toolbar config
+ if(Ext.isArray(tb)){
+ tb = {
+ items: tb
+ };
+ }
+ result = tb.events ? Ext.apply(tb, options) : this.createComponent(Ext.apply({}, tb, options), 'toolbar');
+ result.ownerCt = this;
+ result.bufferResize = false;
+ this.toolbars.push(result);
+ return result;
+ },
+
// private
createElement : function(name, pnode){
if(this[name]){
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);
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(mc);
}else{
this.createElement('header', d);
this.createElement('bwrap', d);
}
}
- if(this.padding !== undefined) {
+ if(Ext.isDefined(this.padding)){
this.body.setStyle('padding', this.body.addUnits(this.padding));
}
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){
- this.fbar = new Ext.Toolbar({
- items: this.buttons,
- toolbarCls: 'x-panel-fbar'
- });
}
- this.toolbars = [];
if(this.fbar){
- this.fbar = Ext.create(this.fbar, 'toolbar');
- this.fbar.enableOverflow = false;
- if(this.fbar.items){
- this.fbar.items.each(function(c){
- c.minWidth = c.minWidth || this.minButtonWidth;
- }, this);
- }
- this.fbar.toolbarCls = 'x-panel-fbar';
-
- var bct = this.footer.createChild({cls: 'x-panel-btns x-panel-btns-'+this.buttonAlign});
- this.fbar.ownerCt = this;
- this.fbar.render(bct);
- bct.createChild({cls:'x-clear'});
- this.toolbars.push(this.fbar);
+ this.footer.addClass('x-panel-btns');
+ this.fbar.render(this.footer);
+ this.footer.createChild({cls:'x-clear'});
}
if(this.tbar && this.topToolbar){
- if(Ext.isArray(this.topToolbar)){
- this.topToolbar = new Ext.Toolbar(this.topToolbar);
- }else if(!this.topToolbar.events){
- this.topToolbar = Ext.create(this.topToolbar, 'toolbar');
- }
- this.topToolbar.ownerCt = this;
this.topToolbar.render(this.tbar);
- this.toolbars.push(this.topToolbar);
}
if(this.bbar && this.bottomToolbar){
- if(Ext.isArray(this.bottomToolbar)){
- this.bottomToolbar = new Ext.Toolbar(this.bottomToolbar);
- }else if(!this.bottomToolbar.events){
- this.bottomToolbar = Ext.create(this.bottomToolbar, 'toolbar');
- }
- this.bottomToolbar.ownerCt = this;
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);
},
/**
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
});
}
// private
makeFloating : function(cfg){
this.floating = true;
- this.el = new Ext.Layer(
- Ext.isObject(cfg) ? cfg : {
- shadow: this.shadow !== undefined ? this.shadow : 'sides',
- shadowOffset: this.shadowOffset,
- constrain:false,
- shim: this.shim === false ? false : undefined
- }, this.el
- );
+ this.el = new Ext.Layer(Ext.apply({}, cfg, {
+ shadow: Ext.isDefined(this.shadow) ? this.shadow : 'sides',
+ shadowOffset: this.shadowOffset,
+ constrain:false,
+ shim: this.shim === false ? false : undefined
+ }), this.el);
},
/**
- * Returns the {@link Ext.Toolbar toolbar} from the top (<tt>{@link #tbar}</tt>) section of the panel.
+ * Returns the {@link Ext.Toolbar toolbar} from the top (<code>{@link #tbar}</code>) section of the panel.
* @return {Ext.Toolbar} The toolbar
*/
getTopToolbar : function(){
},
/**
- * Returns the {@link Ext.Toolbar toolbar} from the bottom (<tt>{@link #bbar}</tt>) section of the panel.
+ * Returns the {@link Ext.Toolbar toolbar} from the bottom (<code>{@link #bbar}</code>) section of the panel.
* @return {Ext.Toolbar} The toolbar
*/
getBottomToolbar : function(){
* @param {String/Object} config A valid {@link Ext.Button} config. A string will become the text for a default
* button config, an object will be treated as a button config object.
* @param {Function} handler The function to be called on button {@link Ext.Button#click}
- * @param {Object} scope The scope to use for the button handler function
+ * @param {Object} scope The scope (<code>this</code> reference) in which the button handler function is executed. Defaults to the Button.
* @return {Ext.Button} The button that was added
*/
addButton : function(config, handler, scope){
- var bc = {
- handler: handler,
- scope: scope,
- minWidth: this.minButtonWidth,
- hideParent:true
- };
- if(typeof config == "string"){
- bc.text = config;
- }else{
- Ext.apply(bc, config);
+ if(!this.fbar){
+ this.createFbar([]);
}
- var btn = new Ext.Button(bc);
- if(!this.buttons){
- this.buttons = [];
+ if(handler){
+ if(Ext.isString(config)){
+ config = {text: config};
+ }
+ config = Ext.apply({
+ handler: handler,
+ scope: scope
+ }, config)
}
- this.buttons.push(btn);
- return btn;
+ return this.fbar.add(config);
},
// 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){
}
},
- 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,
+ sz;
+
+ 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);
}
},
};
},
- // private
+ // private
afterRender : function(){
if(this.floating && !this.hidden){
this.el.show();
if(this.title){
this.setTitle(this.title);
}
- this.setAutoScroll();
- if(this.html){
- this.body.update(Ext.isObject(this.html) ?
- Ext.DomHelper.markup(this.html) :
- this.html);
- delete this.html;
- }
- if(this.contentEl){
- var ce = Ext.getDom(this.contentEl);
- Ext.fly(ce).removeClass(['x-hidden', 'x-hide-display']);
- this.body.dom.appendChild(ce);
- }
if(this.collapsed){
this.collapsed = false;
this.collapse(false);
}
Ext.Panel.superclass.afterRender.call(this); // do sizing calcs last
this.initEvents();
- },
-
- // private
- setAutoScroll : function(){
- if(this.rendered && this.autoScroll){
- var el = this.body || this.el;
- if(el){
- el.setOverflow('auto');
- }
- }
- },
+ },
// private
getKeyMap : function(){
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
* @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
return;
}
var doAnim = animate === true || (animate !== false && this.animCollapse);
- this.beforeEffect();
+ this.beforeEffect(doAnim);
this.onCollapse(doAnim, animate);
return this;
},
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);
},
}
var doAnim = animate === true || (animate !== false && this.animCollapse);
this.el.removeClass(this.collapsedCls);
- this.beforeEffect();
+ this.beforeEffect(doAnim);
this.onExpand(doAnim, animate);
return this;
},
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);
// private
onResize : function(w, h){
- if(w !== undefined || h !== undefined){
+ if(Ext.isDefined(w) || Ext.isDefined(h)){
if(!this.collapsed){
- if(typeof w == 'number'){
- w = this.adjustBodyWidth(w - this.getFrameWidth());
- if(this.tbar){
- this.tbar.setWidth(w);
- if(this.topToolbar){
- this.topToolbar.setSize(w);
- }
+ // First, set the the Panel's body width.
+ // If we have auto-widthed it, get the resulting full offset width so we can size the Toolbars to match
+ // The Toolbars must not buffer this resize operation because we need to know their heights.
+
+ if(Ext.isNumber(w)){
+ this.body.setWidth(w = this.adjustBodyWidth(w - this.getFrameWidth()));
+ } else if (w == 'auto') {
+ w = this.body.setWidth('auto').dom.offsetWidth;
+ } else {
+ w = this.body.dom.offsetWidth;
+ }
+
+ if(this.tbar){
+ this.tbar.setWidth(w);
+ if(this.topToolbar){
+ this.topToolbar.setSize(w);
}
- if(this.bbar){
- this.bbar.setWidth(w);
- if(this.bottomToolbar){
- this.bottomToolbar.setSize(w);
+ }
+ if(this.bbar){
+ this.bbar.setWidth(w);
+ if(this.bottomToolbar){
+ this.bottomToolbar.setSize(w);
+ // The bbar does not move on resize without this.
+ if (Ext.isIE) {
+ this.bbar.setStyle('position', 'static');
+ this.bbar.setStyle('position', '');
}
}
+ }
+ if(this.footer){
+ this.footer.setWidth(w);
if(this.fbar){
- var f = this.fbar,
- fWidth = 1,
- strict = Ext.isStrict;
- if(this.buttonAlign == 'left'){
- fWidth = w - f.container.getFrameWidth('lr');
- }else{
- //center/right alignment off in webkit
- if(Ext.isIE || Ext.isWebKit){
- //center alignment ok on webkit.
- //right broken in both, center on IE
- if(!(this.buttonAlign == 'center' && Ext.isWebKit) && (!strict || (!Ext.isIE8 && strict))){
- (function(){
- f.setWidth(f.getEl().child('.x-toolbar-ct').getWidth());
- }).defer(1);
- }else{
- fWidth = 'auto';
- }
- }else{
- fWidth = 'auto';
- }
- }
- f.setWidth(fWidth);
+ this.fbar.setSize(Ext.isIE ? (w - this.footer.getFrameWidth('lr')) : 'auto');
}
- this.body.setWidth(w);
- }else if(w == 'auto'){
- this.body.setWidth(w);
}
- if(typeof h == 'number'){
+ // At this point, the Toolbars must be layed out for getFrameHeight to find a result.
+ if(Ext.isNumber(h)){
h = Math.max(0, this.adjustBodyHeight(h - this.getFrameHeight()));
this.body.setHeight(h);
}else if(h == 'auto'){
this.on('expand', function(){
delete this.queuedExpand;
this.onResize(this.queuedBodySize.width, this.queuedBodySize.height);
- this.doLayout();
}, this, {single:true});
}
}
- this.fireEvent('bodyresize', this, w, h);
+ this.onBodyResize(w, h);
}
this.syncShadow();
+ Ext.Panel.superclass.onResize.call(this);
+ },
+
+ // 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
* @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;
},
* @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);
return this.body;
},
+ // private
+ getContentTarget : function(){
+ return this.body;
+ },
+
/**
* <p>Sets the title text for the panel and optionally the {@link #iconCls icon class}.</p>
* <p>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 <tt>{@link #title}</tt>,
- * or configuring it with <tt><b>{@link #header}: true</b></tt>.</p>
+ * for the Panel. This is triggered either by configuring the Panel with a non-blank <code>{@link #title}</code>,
+ * or configuring it with <code><b>{@link #header}: true</b></code>.</p>
* @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
*/
* @param {Object/String/Function} config A config object containing any of the following options:
<pre><code>
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
});
// private
beforeDestroy : function(){
+ Ext.Panel.superclass.beforeDestroy.call(this);
if(this.header){
this.header.removeAllListeners();
- if(this.headerAsText){
- Ext.Element.uncache(this.header.child('span'));
- }
}
- Ext.Element.uncache(
- this.header,
- this.tbar,
- this.bbar,
- this.footer,
- this.body,
- this.bwrap
- );
if(this.tools){
for(var k in this.tools){
Ext.destroy(this.tools[k]);
}
}
- if(this.buttons){
- for(var b in this.buttons){
- Ext.destroy(this.buttons[b]);
+ if(Ext.isArray(this.buttons)){
+ while(this.buttons.length) {
+ Ext.destroy(this.buttons[0]);
}
}
- Ext.destroy(this.toolbars);
- Ext.Panel.superclass.beforeDestroy.call(this);
+ if(this.rendered){
+ Ext.destroy(
+ this.ft,
+ this.header,
+ this.footer,
+ this.toolbars,
+ this.tbar,
+ this.bbar,
+ this.body,
+ this.mc,
+ this.bwrap
+ );
+ if (this.fbar) {
+ Ext.destroy(
+ this.fbar,
+ this.fbar.el
+ );
+ }
+ }else{
+ Ext.destroy(
+ this.topToolbar,
+ this.bottomToolbar
+ );
+ }
},
// private
*/
/**
* @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
* The position to align to (see {@link Ext.Element#alignTo} for more details, defaults to "c-c?").
*/
alignment: "c-c?",
+ /**
+ * @cfg {Array} offsets
+ * The offsets to use when aligning (see {@link Ext.Element#alignTo} for more details. Defaults to <tt>[0, 0]</tt>.
+ */
+ offsets: [0, 0],
/**
* @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
* for bottom-right shadow (defaults to "frame")
*/
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 <tt>true</tt>.
*/
- 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 <tt>true</tt>.
*/
- cancelOnEsc : false,
+ cancelOnEsc : true,
/**
* @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
*/
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);
},
/**
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.reset();
+ this.field.setValue(v);
+ this.realign(true);
+ 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);
}
}
},
/**
* Realigns the editor to the bound field based on the current alignment config value.
+ * @param {Boolean} autoSize (optional) True to size the field to the dimensions of the bound element.
*/
- realign : function(){
- this.el.alignTo(this.boundEl, this.alignment);
+ realign : function(autoSize){
+ if(autoSize === true){
+ this.doAutoSize();
+ }
+ this.el.alignTo(this.boundEl, this.alignment, this.offsets);
},
/**
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.
},
beforeDestroy : function(){
- Ext.destroy(this.field);
- this.field = null;
+ Ext.destroyMembers(this, 'field');
+
+ delete this.parentEl;
+ delete this.boundEl;
}
});
-Ext.reg('editor', Ext.Editor);/**
+Ext.reg('editor', Ext.Editor);
+/**
* @class Ext.ColorPalette
* @extends Ext.Component
* Simple color palette class for choosing colors. The palette can be rendered to any container.<br />
* @param {Object} config The config object
* @xtype colorpalette
*/
-Ext.ColorPalette = function(config){
- Ext.ColorPalette.superclass.constructor.call(this, config);
- this.addEvents(
- /**
- * @event select
- * Fires when a color is selected
- * @param {ColorPalette} this
- * @param {String} color The 6-digit color hex code (without the # symbol)
- */
- 'select'
- );
-
- if(this.handler){
- this.on("select", this.handler, this.scope, true);
- }
-};
-Ext.extend(Ext.ColorPalette, Ext.Component, {
+Ext.ColorPalette = Ext.extend(Ext.Component, {
/**
* @cfg {String} tpl An existing XTemplate instance to be used in place of the default template for rendering the 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',
+ /**
+ * @cfg {String} clickEvent
+ * The DOM event that will cause a color to be selected. This can be any valid event name (dblclick, contextmenu).
+ * Defaults to <tt>'click'</tt>.
+ */
+ 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
* <p>You can override individual colors if needed:</p>
* <pre><code>
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
</code></pre>
Or you can provide a custom array of your own for complete control:
<pre><code>
var cp = new Ext.ColorPalette();
-cp.colors = ["000000", "993300", "333300"];
+cp.colors = ['000000', '993300', '333300'];
</code></pre>
* @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:<div class="mdetail-params"><ul>
+ * <li><code>palette</code> : ColorPalette<div class="sub-desc">The {@link #palette Ext.ColorPalette}.</div></li>
+ * <li><code>color</code> : String<div class="sub-desc">The 6-digit color hex code (without the # symbol).</div></li>
+ * </ul></div>
+ */
+ /**
+ * @cfg {Object} scope
+ * The scope (<tt><b>this</b></tt> reference) in which the <code>{@link #handler}</code>
+ * function will be called. Defaults to this ColorPalette instance.
+ */
+
+ // private
+ initComponent : function(){
+ Ext.ColorPalette.superclass.initComponent.call(this);
+ this.addEvents(
+ /**
+ * @event select
+ * Fires when a color is selected
+ * @param {ColorPalette} this
+ * @param {String} color The 6-digit color hex code (without the # symbol)
+ */
+ 'select'
+ );
+
+ if(this.handler){
+ this.on('select', this.handler, this.scope, true);
+ }
+ },
+
// private
onRender : function(container, position){
+ this.autoEl = {
+ tag: 'div',
+ cls: this.itemCls
+ };
+ Ext.ColorPalette.superclass.onRender.call(this, container, position);
var t = this.tpl || new Ext.XTemplate(
'<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on"> </span></em></a></tpl>'
);
- var el = document.createElement("div");
- el.id = this.getId();
- el.className = this.itemCls;
- t.overwrite(el, this.colors);
- container.dom.insertBefore(el, position);
- this.el = Ext.get(el);
+ t.overwrite(this.el, this.colors);
this.mon(this.el, this.clickEvent, this.handleClick, this, {delegate: 'a'});
if(this.clickEvent != 'click'){
this.mon(this.el, 'click', Ext.emptyFn, this, {delegate: 'a', preventDefault: true});
* @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);
}
}
* @cfg {String} autoEl @hide
*/
});
-Ext.reg('colorpalette', Ext.ColorPalette);/**\r
- * @class Ext.DatePicker\r
- * @extends Ext.Component\r
- * Simple date picker class.\r
- * @constructor\r
- * Create a new DatePicker\r
- * @param {Object} config The config object\r
- * @xtype datepicker\r
- */\r
-Ext.DatePicker = Ext.extend(Ext.BoxComponent, {\r
- /**\r
- * @cfg {String} todayText\r
- * The text to display on the button that selects the current date (defaults to <tt>'Today'</tt>)\r
- */\r
- todayText : 'Today',\r
- /**\r
- * @cfg {String} okText\r
- * The text to display on the ok button (defaults to <tt>' OK '</tt> to give the user extra clicking room)\r
- */\r
- okText : ' OK ',\r
- /**\r
- * @cfg {String} cancelText\r
- * The text to display on the cancel button (defaults to <tt>'Cancel'</tt>)\r
- */\r
- cancelText : 'Cancel',\r
- /**\r
- * @cfg {String} todayTip\r
- * The tooltip to display for the button that selects the current date (defaults to <tt>'{current date} (Spacebar)'</tt>)\r
- */\r
- todayTip : '{0} (Spacebar)',\r
- /**\r
- * @cfg {String} minText\r
- * The error text to display if the minDate validation fails (defaults to <tt>'This date is before the minimum date'</tt>)\r
- */\r
- minText : 'This date is before the minimum date',\r
- /**\r
- * @cfg {String} maxText\r
- * The error text to display if the maxDate validation fails (defaults to <tt>'This date is after the maximum date'</tt>)\r
- */\r
- maxText : 'This date is after the maximum date',\r
- /**\r
- * @cfg {String} format\r
- * The default date format string which can be overriden for localization support. The format must be\r
- * valid according to {@link Date#parseDate} (defaults to <tt>'m/d/y'</tt>).\r
- */\r
- format : 'm/d/y',\r
- /**\r
- * @cfg {String} disabledDaysText\r
- * The tooltip to display when the date falls on a disabled day (defaults to <tt>'Disabled'</tt>)\r
- */\r
- disabledDaysText : 'Disabled',\r
- /**\r
- * @cfg {String} disabledDatesText\r
- * The tooltip text to display when the date falls on a disabled date (defaults to <tt>'Disabled'</tt>)\r
- */\r
- disabledDatesText : 'Disabled',\r
- /**\r
- * @cfg {Array} monthNames\r
- * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)\r
- */\r
- monthNames : Date.monthNames,\r
- /**\r
- * @cfg {Array} dayNames\r
- * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)\r
- */\r
- dayNames : Date.dayNames,\r
- /**\r
- * @cfg {String} nextText\r
- * The next month navigation button tooltip (defaults to <tt>'Next Month (Control+Right)'</tt>)\r
- */\r
- nextText : 'Next Month (Control+Right)',\r
- /**\r
- * @cfg {String} prevText\r
- * The previous month navigation button tooltip (defaults to <tt>'Previous Month (Control+Left)'</tt>)\r
- */\r
- prevText : 'Previous Month (Control+Left)',\r
- /**\r
- * @cfg {String} monthYearText\r
- * The header month selector tooltip (defaults to <tt>'Choose a month (Control+Up/Down to move years)'</tt>)\r
- */\r
- monthYearText : 'Choose a month (Control+Up/Down to move years)',\r
- /**\r
- * @cfg {Number} startDay\r
- * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)\r
- */\r
- startDay : 0,\r
- /**\r
- * @cfg {Boolean} showToday\r
- * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar\r
- * that selects the current date (defaults to <tt>true</tt>).\r
- */\r
- showToday : true,\r
- /**\r
- * @cfg {Date} minDate\r
- * Minimum allowable date (JavaScript date object, defaults to null)\r
- */\r
- /**\r
- * @cfg {Date} maxDate\r
- * Maximum allowable date (JavaScript date object, defaults to null)\r
- */\r
- /**\r
- * @cfg {Array} disabledDays\r
- * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).\r
- */\r
- /**\r
- * @cfg {RegExp} disabledDatesRE\r
- * JavaScript regular expression used to disable a pattern of dates (defaults to null). The {@link #disabledDates}\r
- * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the\r
- * disabledDates value.\r
- */\r
- /**\r
- * @cfg {Array} disabledDates\r
- * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular\r
- * expression so they are very powerful. Some examples:\r
- * <ul>\r
- * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>\r
- * <li>['03/08', '09/16'] would disable those days for every year</li>\r
- * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>\r
- * <li>['03/../2006'] would disable every day in March 2006</li>\r
- * <li>['^03'] would disable every day in every March</li>\r
- * </ul>\r
- * Note that the format of the dates included in the array should exactly match the {@link #format} config.\r
- * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to\r
- * escape the dot when restricting dates. For example: ['03\\.08\\.03'].\r
- */\r
-\r
- // private\r
- initComponent : function(){\r
- Ext.DatePicker.superclass.initComponent.call(this);\r
-\r
- this.value = this.value ?\r
- this.value.clearTime() : new Date().clearTime();\r
-\r
- this.addEvents(\r
- /**\r
- * @event select\r
- * Fires when a date is selected\r
- * @param {DatePicker} this\r
- * @param {Date} date The selected date\r
- */\r
- 'select'\r
- );\r
-\r
- if(this.handler){\r
- this.on('select', this.handler, this.scope || this);\r
- }\r
-\r
- this.initDisabledDays();\r
- },\r
-\r
- // private\r
- initDisabledDays : function(){\r
- if(!this.disabledDatesRE && this.disabledDates){\r
- var dd = this.disabledDates,\r
- len = dd.length - 1,\r
- re = '(?:';\r
- \r
- Ext.each(dd, function(d, i){\r
- re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];\r
- if(i != len){\r
- re += '|';\r
- }\r
- }, this);\r
- this.disabledDatesRE = new RegExp(re + ')');\r
- }\r
- },\r
-\r
- /**\r
- * Replaces any existing disabled dates with new values and refreshes the DatePicker.\r
- * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config\r
- * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.\r
- */\r
- setDisabledDates : function(dd){\r
- if(Ext.isArray(dd)){\r
- this.disabledDates = dd;\r
- this.disabledDatesRE = null;\r
- }else{\r
- this.disabledDatesRE = dd;\r
- }\r
- this.initDisabledDays();\r
- this.update(this.value, true);\r
- },\r
-\r
- /**\r
- * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.\r
- * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config\r
- * for details on supported values.\r
- */\r
- setDisabledDays : function(dd){\r
- this.disabledDays = dd;\r
- this.update(this.value, true);\r
- },\r
-\r
- /**\r
- * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.\r
- * @param {Date} value The minimum date that can be selected\r
- */\r
- setMinDate : function(dt){\r
- this.minDate = dt;\r
- this.update(this.value, true);\r
- },\r
-\r
- /**\r
- * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.\r
- * @param {Date} value The maximum date that can be selected\r
- */\r
- setMaxDate : function(dt){\r
- this.maxDate = dt;\r
- this.update(this.value, true);\r
- },\r
-\r
- /**\r
- * Sets the value of the date field\r
- * @param {Date} value The date to set\r
- */\r
- setValue : function(value){\r
- var old = this.value;\r
- this.value = value.clearTime(true);\r
- if(this.el){\r
- this.update(this.value);\r
- }\r
- },\r
-\r
- /**\r
- * Gets the current selected value of the date field\r
- * @return {Date} The selected date\r
- */\r
- getValue : function(){\r
- return this.value;\r
- },\r
-\r
- // private\r
- focus : function(){\r
- if(this.el){\r
- this.update(this.activeDate);\r
- }\r
- },\r
- \r
- // private\r
- onEnable: function(initial){\r
- Ext.DatePicker.superclass.onEnable.call(this); \r
- this.doDisabled(false);\r
- this.update(initial ? this.value : this.activeDate);\r
- if(Ext.isIE){\r
- this.el.repaint();\r
- }\r
- \r
- },\r
- \r
- // private\r
- onDisable: function(){\r
- Ext.DatePicker.superclass.onDisable.call(this); \r
- this.doDisabled(true);\r
- if(Ext.isIE && !Ext.isIE8){\r
- /* Really strange problem in IE6/7, when disabled, have to explicitly\r
- * repaint each of the nodes to get them to display correctly, simply\r
- * calling repaint on the main element doesn't appear to be enough.\r
- */\r
- Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){\r
- Ext.fly(el).repaint();\r
- });\r
- }\r
- },\r
- \r
- // private\r
- doDisabled: function(disabled){\r
- this.keyNav.setDisabled(disabled);\r
- this.prevRepeater.setDisabled(disabled);\r
- this.nextRepeater.setDisabled(disabled);\r
- if(this.showToday){\r
- this.todayKeyListener.setDisabled(disabled);\r
- this.todayBtn.setDisabled(disabled);\r
- }\r
- },\r
-\r
- // private\r
- onRender : function(container, position){\r
- var m = [\r
- '<table cellspacing="0">',\r
- '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'"> </a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'"> </a></td></tr>',\r
- '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],\r
- dn = this.dayNames,\r
- i;\r
- for(i = 0; i < 7; i++){\r
- var d = this.startDay+i;\r
- if(d > 6){\r
- d = d-7;\r
- }\r
- m.push('<th><span>', dn[d].substr(0,1), '</span></th>');\r
- }\r
- m[m.length] = '</tr></thead><tbody><tr>';\r
- for(i = 0; i < 42; i++) {\r
- if(i % 7 === 0 && i !== 0){\r
- m[m.length] = '</tr><tr>';\r
- }\r
- m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';\r
- }\r
- m.push('</tr></tbody></table></td></tr>',\r
- this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',\r
- '</table><div class="x-date-mp"></div>');\r
-\r
- var el = document.createElement('div');\r
- el.className = 'x-date-picker';\r
- el.innerHTML = m.join('');\r
-\r
- container.dom.insertBefore(el, position);\r
-\r
- this.el = Ext.get(el);\r
- this.eventEl = Ext.get(el.firstChild);\r
-\r
- this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {\r
- handler: this.showPrevMonth,\r
- scope: this,\r
- preventDefault:true,\r
- stopDefault:true\r
- });\r
-\r
- this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {\r
- handler: this.showNextMonth,\r
- scope: this,\r
- preventDefault:true,\r
- stopDefault:true\r
- });\r
-\r
- this.monthPicker = this.el.down('div.x-date-mp');\r
- this.monthPicker.enableDisplayMode('block');\r
-\r
- this.keyNav = new Ext.KeyNav(this.eventEl, {\r
- 'left' : function(e){\r
- if(e.ctrlKey){\r
- this.showPrevMonth();\r
- }else{\r
- this.update(this.activeDate.add('d', -1)); \r
- }\r
- },\r
-\r
- 'right' : function(e){\r
- if(e.ctrlKey){\r
- this.showNextMonth();\r
- }else{\r
- this.update(this.activeDate.add('d', 1)); \r
- }\r
- },\r
-\r
- 'up' : function(e){\r
- if(e.ctrlKey){\r
- this.showNextYear();\r
- }else{\r
- this.update(this.activeDate.add('d', -7));\r
- }\r
- },\r
-\r
- 'down' : function(e){\r
- if(e.ctrlKey){\r
- this.showPrevYear();\r
- }else{\r
- this.update(this.activeDate.add('d', 7));\r
- }\r
- },\r
-\r
- 'pageUp' : function(e){\r
- this.showNextMonth();\r
- },\r
-\r
- 'pageDown' : function(e){\r
- this.showPrevMonth();\r
- },\r
-\r
- 'enter' : function(e){\r
- e.stopPropagation();\r
- return true;\r
- },\r
-\r
- scope : this\r
- });\r
-\r
- this.el.unselectable();\r
-\r
- this.cells = this.el.select('table.x-date-inner tbody td');\r
- this.textNodes = this.el.query('table.x-date-inner tbody span');\r
-\r
- this.mbtn = new Ext.Button({\r
- text: ' ',\r
- tooltip: this.monthYearText,\r
- renderTo: this.el.child('td.x-date-middle', true)\r
- });\r
- this.mbtn.el.child('em').addClass('x-btn-arrow');\r
-\r
- if(this.showToday){\r
- this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday, this);\r
- var today = (new Date()).dateFormat(this.format);\r
- this.todayBtn = new Ext.Button({\r
- renderTo: this.el.child('td.x-date-bottom', true),\r
- text: String.format(this.todayText, today),\r
- tooltip: String.format(this.todayTip, today),\r
- handler: this.selectToday,\r
- scope: this\r
- });\r
- }\r
- this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);\r
- this.mon(this.eventEl, 'click', this.handleDateClick, this, {delegate: 'a.x-date-date'});\r
- this.mon(this.mbtn, 'click', this.showMonthPicker, this);\r
- this.onEnable(true);\r
- },\r
-\r
- // private\r
- createMonthPicker : function(){\r
- if(!this.monthPicker.dom.firstChild){\r
- var buf = ['<table border="0" cellspacing="0">'];\r
- for(var i = 0; i < 6; i++){\r
- buf.push(\r
- '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',\r
- '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',\r
- i === 0 ?\r
- '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :\r
- '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'\r
- );\r
- }\r
- buf.push(\r
- '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',\r
- this.okText,\r
- '</button><button type="button" class="x-date-mp-cancel">',\r
- this.cancelText,\r
- '</button></td></tr>',\r
- '</table>'\r
- );\r
- this.monthPicker.update(buf.join(''));\r
-\r
- this.mon(this.monthPicker, 'click', this.onMonthClick, this);\r
- this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);\r
-\r
- this.mpMonths = this.monthPicker.select('td.x-date-mp-month');\r
- this.mpYears = this.monthPicker.select('td.x-date-mp-year');\r
-\r
- this.mpMonths.each(function(m, a, i){\r
- i += 1;\r
- if((i%2) === 0){\r
- m.dom.xmonth = 5 + Math.round(i * 0.5);\r
- }else{\r
- m.dom.xmonth = Math.round((i-1) * 0.5);\r
- }\r
- });\r
- }\r
- },\r
-\r
- // private\r
- showMonthPicker : function(){\r
- if(!this.disabled){\r
- this.createMonthPicker();\r
- var size = this.el.getSize();\r
- this.monthPicker.setSize(size);\r
- this.monthPicker.child('table').setSize(size);\r
-\r
- this.mpSelMonth = (this.activeDate || this.value).getMonth();\r
- this.updateMPMonth(this.mpSelMonth);\r
- this.mpSelYear = (this.activeDate || this.value).getFullYear();\r
- this.updateMPYear(this.mpSelYear);\r
-\r
- this.monthPicker.slideIn('t', {duration:0.2});\r
- }\r
- },\r
-\r
- // private\r
- updateMPYear : function(y){\r
- this.mpyear = y;\r
- var ys = this.mpYears.elements;\r
- for(var i = 1; i <= 10; i++){\r
- var td = ys[i-1], y2;\r
- if((i%2) === 0){\r
- y2 = y + Math.round(i * 0.5);\r
- td.firstChild.innerHTML = y2;\r
- td.xyear = y2;\r
- }else{\r
- y2 = y - (5-Math.round(i * 0.5));\r
- td.firstChild.innerHTML = y2;\r
- td.xyear = y2;\r
- }\r
- this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');\r
- }\r
- },\r
-\r
- // private\r
- updateMPMonth : function(sm){\r
- this.mpMonths.each(function(m, a, i){\r
- m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');\r
- });\r
- },\r
-\r
- // private\r
- selectMPMonth : function(m){\r
-\r
- },\r
-\r
- // private\r
- onMonthClick : function(e, t){\r
- e.stopEvent();\r
- var el = new Ext.Element(t), pn;\r
- if(el.is('button.x-date-mp-cancel')){\r
- this.hideMonthPicker();\r
- }\r
- else if(el.is('button.x-date-mp-ok')){\r
- var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());\r
- if(d.getMonth() != this.mpSelMonth){\r
- // 'fix' the JS rolling date conversion if needed\r
- d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();\r
- }\r
- this.update(d);\r
- this.hideMonthPicker();\r
- }\r
- else if((pn = el.up('td.x-date-mp-month', 2))){\r
- this.mpMonths.removeClass('x-date-mp-sel');\r
- pn.addClass('x-date-mp-sel');\r
- this.mpSelMonth = pn.dom.xmonth;\r
- }\r
- else if((pn = el.up('td.x-date-mp-year', 2))){\r
- this.mpYears.removeClass('x-date-mp-sel');\r
- pn.addClass('x-date-mp-sel');\r
- this.mpSelYear = pn.dom.xyear;\r
- }\r
- else if(el.is('a.x-date-mp-prev')){\r
- this.updateMPYear(this.mpyear-10);\r
- }\r
- else if(el.is('a.x-date-mp-next')){\r
- this.updateMPYear(this.mpyear+10);\r
- }\r
- },\r
-\r
- // private\r
- onMonthDblClick : function(e, t){\r
- e.stopEvent();\r
- var el = new Ext.Element(t), pn;\r
- if((pn = el.up('td.x-date-mp-month', 2))){\r
- this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));\r
- this.hideMonthPicker();\r
- }\r
- else if((pn = el.up('td.x-date-mp-year', 2))){\r
- this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));\r
- this.hideMonthPicker();\r
- }\r
- },\r
-\r
- // private\r
- hideMonthPicker : function(disableAnim){\r
- if(this.monthPicker){\r
- if(disableAnim === true){\r
- this.monthPicker.hide();\r
- }else{\r
- this.monthPicker.slideOut('t', {duration:0.2});\r
- }\r
- }\r
- },\r
-\r
- // private\r
- showPrevMonth : function(e){\r
- this.update(this.activeDate.add('mo', -1));\r
- },\r
-\r
- // private\r
- showNextMonth : function(e){\r
- this.update(this.activeDate.add('mo', 1));\r
- },\r
-\r
- // private\r
- showPrevYear : function(){\r
- this.update(this.activeDate.add('y', -1));\r
- },\r
-\r
- // private\r
- showNextYear : function(){\r
- this.update(this.activeDate.add('y', 1));\r
- },\r
-\r
- // private\r
- handleMouseWheel : function(e){\r
- e.stopEvent();\r
- if(!this.disabled){\r
- var delta = e.getWheelDelta();\r
- if(delta > 0){\r
- this.showPrevMonth();\r
- } else if(delta < 0){\r
- this.showNextMonth();\r
- }\r
- }\r
- },\r
-\r
- // private\r
- handleDateClick : function(e, t){\r
- e.stopEvent();\r
- if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){\r
- this.setValue(new Date(t.dateValue));\r
- this.fireEvent('select', this, this.value);\r
- }\r
- },\r
-\r
- // private\r
- selectToday : function(){\r
- if(this.todayBtn && !this.todayBtn.disabled){\r
- this.setValue(new Date().clearTime());\r
- this.fireEvent('select', this, this.value);\r
- }\r
- },\r
-\r
- // private\r
- update : function(date, forceRefresh){\r
- var vd = this.activeDate, vis = this.isVisible();\r
- this.activeDate = date;\r
- if(!forceRefresh && vd && this.el){\r
- var t = date.getTime();\r
- if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){\r
- this.cells.removeClass('x-date-selected');\r
- this.cells.each(function(c){\r
- if(c.dom.firstChild.dateValue == t){\r
- c.addClass('x-date-selected');\r
- if(vis){\r
- Ext.fly(c.dom.firstChild).focus(50);\r
- }\r
- return false;\r
- }\r
- });\r
- return;\r
- }\r
- }\r
- var days = date.getDaysInMonth();\r
- var firstOfMonth = date.getFirstDateOfMonth();\r
- var startingPos = firstOfMonth.getDay()-this.startDay;\r
-\r
- if(startingPos <= this.startDay){\r
- startingPos += 7;\r
- }\r
-\r
- var pm = date.add('mo', -1);\r
- var prevStart = pm.getDaysInMonth()-startingPos;\r
-\r
- var cells = this.cells.elements;\r
- var textEls = this.textNodes;\r
- days += startingPos;\r
-\r
- // convert everything to numbers so it's fast\r
- var day = 86400000;\r
- var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();\r
- var today = new Date().clearTime().getTime();\r
- var sel = date.clearTime().getTime();\r
- var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;\r
- var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;\r
- var ddMatch = this.disabledDatesRE;\r
- var ddText = this.disabledDatesText;\r
- var ddays = this.disabledDays ? this.disabledDays.join('') : false;\r
- var ddaysText = this.disabledDaysText;\r
- var format = this.format;\r
-\r
- if(this.showToday){\r
- var td = new Date().clearTime();\r
- var disable = (td < min || td > max ||\r
- (ddMatch && format && ddMatch.test(td.dateFormat(format))) ||\r
- (ddays && ddays.indexOf(td.getDay()) != -1));\r
-\r
- if(!this.disabled){\r
- this.todayBtn.setDisabled(disable);\r
- this.todayKeyListener[disable ? 'disable' : 'enable']();\r
- }\r
- }\r
-\r
- var setCellClass = function(cal, cell){\r
- cell.title = '';\r
- var t = d.getTime();\r
- cell.firstChild.dateValue = t;\r
- if(t == today){\r
- cell.className += ' x-date-today';\r
- cell.title = cal.todayText;\r
- }\r
- if(t == sel){\r
- cell.className += ' x-date-selected';\r
- if(vis){\r
- Ext.fly(cell.firstChild).focus(50);\r
- }\r
- }\r
- // disabling\r
- if(t < min) {\r
- cell.className = ' x-date-disabled';\r
- cell.title = cal.minText;\r
- return;\r
- }\r
- if(t > max) {\r
- cell.className = ' x-date-disabled';\r
- cell.title = cal.maxText;\r
- return;\r
- }\r
- if(ddays){\r
- if(ddays.indexOf(d.getDay()) != -1){\r
- cell.title = ddaysText;\r
- cell.className = ' x-date-disabled';\r
- }\r
- }\r
- if(ddMatch && format){\r
- var fvalue = d.dateFormat(format);\r
- if(ddMatch.test(fvalue)){\r
- cell.title = ddText.replace('%0', fvalue);\r
- cell.className = ' x-date-disabled';\r
- }\r
- }\r
- };\r
-\r
- var i = 0;\r
- for(; i < startingPos; i++) {\r
- textEls[i].innerHTML = (++prevStart);\r
- d.setDate(d.getDate()+1);\r
- cells[i].className = 'x-date-prevday';\r
- setCellClass(this, cells[i]);\r
- }\r
- for(; i < days; i++){\r
- var intDay = i - startingPos + 1;\r
- textEls[i].innerHTML = (intDay);\r
- d.setDate(d.getDate()+1);\r
- cells[i].className = 'x-date-active';\r
- setCellClass(this, cells[i]);\r
- }\r
- var extraDays = 0;\r
- for(; i < 42; i++) {\r
- textEls[i].innerHTML = (++extraDays);\r
- d.setDate(d.getDate()+1);\r
- cells[i].className = 'x-date-nextday';\r
- setCellClass(this, cells[i]);\r
- }\r
-\r
- this.mbtn.setText(this.monthNames[date.getMonth()] + ' ' + date.getFullYear());\r
-\r
- if(!this.internalRender){\r
- var main = this.el.dom.firstChild;\r
- var w = main.offsetWidth;\r
- this.el.setWidth(w + this.el.getBorderWidth('lr'));\r
- Ext.fly(main).setWidth(w);\r
- this.internalRender = true;\r
- // opera does not respect the auto grow header center column\r
- // then, after it gets a width opera refuses to recalculate\r
- // without a second pass\r
- if(Ext.isOpera && !this.secondPass){\r
- main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + 'px';\r
- this.secondPass = true;\r
- this.update.defer(10, this, [date]);\r
- }\r
- }\r
- },\r
-\r
- // private\r
- beforeDestroy : function() {\r
- if(this.rendered){\r
- this.keyNav.disable();\r
- this.keyNav = null;\r
- Ext.destroy(\r
- this.leftClickRpt,\r
- this.rightClickRpt,\r
- this.monthPicker,\r
- this.eventEl,\r
- this.mbtn,\r
- this.todayBtn\r
- );\r
- }\r
- }\r
-\r
- /**\r
- * @cfg {String} autoEl @hide\r
- */\r
-});\r
-\r
-Ext.reg('datepicker', Ext.DatePicker);\r
+Ext.reg('colorpalette', Ext.ColorPalette);
+/**
+ * @class Ext.DatePicker
+ * @extends Ext.Component
+ * <p>A popup date picker. This class is used by the {@link Ext.form.DateField DateField} class
+ * to allow browsing and selection of valid dates.</p>
+ * <p>All the string values documented below may be overridden by including an Ext locale file in
+ * your page.</p>
+ * @constructor
+ * Create a new DatePicker
+ * @param {Object} config The config object
+ * @xtype datepicker
+ */
+Ext.DatePicker = Ext.extend(Ext.BoxComponent, {
+ /**
+ * @cfg {String} todayText
+ * The text to display on the button that selects the current date (defaults to <code>'Today'</code>)
+ */
+ todayText : 'Today',
+ /**
+ * @cfg {String} okText
+ * The text to display on the ok button (defaults to <code>' OK '</code> to give the user extra clicking room)
+ */
+ okText : ' OK ',
+ /**
+ * @cfg {String} cancelText
+ * The text to display on the cancel button (defaults to <code>'Cancel'</code>)
+ */
+ cancelText : 'Cancel',
+ /**
+ * @cfg {Function} handler
+ * Optional. A function that will handle the select event of this picker.
+ * The handler is passed the following parameters:<div class="mdetail-params"><ul>
+ * <li><code>picker</code> : DatePicker<div class="sub-desc">This DatePicker.</div></li>
+ * <li><code>date</code> : Date<div class="sub-desc">The selected date.</div></li>
+ * </ul></div>
+ */
+ /**
+ * @cfg {Object} scope
+ * The scope (<code><b>this</b></code> reference) in which the <code>{@link #handler}</code>
+ * function will be called. Defaults to this DatePicker instance.
+ */
+ /**
+ * @cfg {String} todayTip
+ * A string used to format the message for displaying in a tooltip over the button that
+ * selects the current date. Defaults to <code>'{0} (Spacebar)'</code> where
+ * the <code>{0}</code> token is replaced by today's date.
+ */
+ todayTip : '{0} (Spacebar)',
+ /**
+ * @cfg {String} minText
+ * The error text to display if the minDate validation fails (defaults to <code>'This date is before the minimum date'</code>)
+ */
+ minText : 'This date is before the minimum date',
+ /**
+ * @cfg {String} maxText
+ * The error text to display if the maxDate validation fails (defaults to <code>'This date is after the maximum date'</code>)
+ */
+ maxText : 'This date is after the maximum date',
+ /**
+ * @cfg {String} format
+ * The default date format string which can be overriden for localization support. The format must be
+ * valid according to {@link Date#parseDate} (defaults to <code>'m/d/y'</code>).
+ */
+ format : 'm/d/y',
+ /**
+ * @cfg {String} disabledDaysText
+ * The tooltip to display when the date falls on a disabled day (defaults to <code>'Disabled'</code>)
+ */
+ disabledDaysText : 'Disabled',
+ /**
+ * @cfg {String} disabledDatesText
+ * The tooltip text to display when the date falls on a disabled date (defaults to <code>'Disabled'</code>)
+ */
+ disabledDatesText : 'Disabled',
+ /**
+ * @cfg {Array} monthNames
+ * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
+ */
+ monthNames : Date.monthNames,
+ /**
+ * @cfg {Array} dayNames
+ * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
+ */
+ dayNames : Date.dayNames,
+ /**
+ * @cfg {String} nextText
+ * The next month navigation button tooltip (defaults to <code>'Next Month (Control+Right)'</code>)
+ */
+ nextText : 'Next Month (Control+Right)',
+ /**
+ * @cfg {String} prevText
+ * The previous month navigation button tooltip (defaults to <code>'Previous Month (Control+Left)'</code>)
+ */
+ prevText : 'Previous Month (Control+Left)',
+ /**
+ * @cfg {String} monthYearText
+ * The header month selector tooltip (defaults to <code>'Choose a month (Control+Up/Down to move years)'</code>)
+ */
+ monthYearText : 'Choose a month (Control+Up/Down to move years)',
+ /**
+ * @cfg {Number} startDay
+ * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
+ */
+ startDay : 0,
+ /**
+ * @cfg {Boolean} showToday
+ * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar
+ * that selects the current date (defaults to <code>true</code>).
+ */
+ showToday : true,
+ /**
+ * @cfg {Date} minDate
+ * Minimum allowable date (JavaScript date object, defaults to null)
+ */
+ /**
+ * @cfg {Date} maxDate
+ * Maximum allowable date (JavaScript date object, defaults to null)
+ */
+ /**
+ * @cfg {Array} disabledDays
+ * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
+ */
+ /**
+ * @cfg {RegExp} disabledDatesRE
+ * JavaScript regular expression used to disable a pattern of dates (defaults to null). The {@link #disabledDates}
+ * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the
+ * disabledDates value.
+ */
+ /**
+ * @cfg {Array} disabledDates
+ * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular
+ * expression so they are very powerful. Some examples:
+ * <ul>
+ * <li>['03/08/2003', '09/16/2003'] would disable those exact dates</li>
+ * <li>['03/08', '09/16'] would disable those days for every year</li>
+ * <li>['^03/08'] would only match the beginning (useful if you are using short years)</li>
+ * <li>['03/../2006'] would disable every day in March 2006</li>
+ * <li>['^03'] would disable every day in every March</li>
+ * </ul>
+ * Note that the format of the dates included in the array should exactly match the {@link #format} config.
+ * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to
+ * escape the dot when restricting dates. For example: ['03\\.08\\.03'].
+ */
+
+ // private
+ // Set by other components to stop the picker focus being updated when the value changes.
+ focusOnSelect: true,
+
+ // private
+ initComponent : function(){
+ Ext.DatePicker.superclass.initComponent.call(this);
+
+ this.value = this.value ?
+ this.value.clearTime(true) : new Date().clearTime();
+
+ this.addEvents(
+ /**
+ * @event select
+ * Fires when a date is selected
+ * @param {DatePicker} this DatePicker
+ * @param {Date} date The selected date
+ */
+ 'select'
+ );
+
+ if(this.handler){
+ this.on('select', this.handler, this.scope || this);
+ }
+
+ this.initDisabledDays();
+ },
+
+ // private
+ initDisabledDays : function(){
+ if(!this.disabledDatesRE && this.disabledDates){
+ var dd = this.disabledDates,
+ len = dd.length - 1,
+ re = '(?:';
+
+ Ext.each(dd, function(d, i){
+ re += Ext.isDate(d) ? '^' + Ext.escapeRe(d.dateFormat(this.format)) + '$' : dd[i];
+ if(i != len){
+ re += '|';
+ }
+ }, this);
+ this.disabledDatesRE = new RegExp(re + ')');
+ }
+ },
+
+ /**
+ * Replaces any existing disabled dates with new values and refreshes the DatePicker.
+ * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config
+ * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.
+ */
+ setDisabledDates : function(dd){
+ if(Ext.isArray(dd)){
+ this.disabledDates = dd;
+ this.disabledDatesRE = null;
+ }else{
+ this.disabledDatesRE = dd;
+ }
+ this.initDisabledDays();
+ this.update(this.value, true);
+ },
+
+ /**
+ * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.
+ * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config
+ * for details on supported values.
+ */
+ setDisabledDays : function(dd){
+ this.disabledDays = dd;
+ this.update(this.value, true);
+ },
+
+ /**
+ * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
+ * @param {Date} value The minimum date that can be selected
+ */
+ setMinDate : function(dt){
+ this.minDate = dt;
+ this.update(this.value, true);
+ },
+
+ /**
+ * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
+ * @param {Date} value The maximum date that can be selected
+ */
+ setMaxDate : function(dt){
+ this.maxDate = dt;
+ this.update(this.value, true);
+ },
+
+ /**
+ * Sets the value of the date field
+ * @param {Date} value The date to set
+ */
+ setValue : function(value){
+ this.value = value.clearTime(true);
+ this.update(this.value);
+ },
+
+ /**
+ * Gets the current selected value of the date field
+ * @return {Date} The selected date
+ */
+ getValue : function(){
+ return this.value;
+ },
+
+ // private
+ focus : function(){
+ this.update(this.activeDate);
+ },
+
+ // private
+ onEnable: function(initial){
+ Ext.DatePicker.superclass.onEnable.call(this);
+ this.doDisabled(false);
+ this.update(initial ? this.value : this.activeDate);
+ if(Ext.isIE){
+ this.el.repaint();
+ }
+
+ },
+
+ // private
+ onDisable : function(){
+ Ext.DatePicker.superclass.onDisable.call(this);
+ this.doDisabled(true);
+ if(Ext.isIE && !Ext.isIE8){
+ /* Really strange problem in IE6/7, when disabled, have to explicitly
+ * repaint each of the nodes to get them to display correctly, simply
+ * calling repaint on the main element doesn't appear to be enough.
+ */
+ Ext.each([].concat(this.textNodes, this.el.query('th span')), function(el){
+ Ext.fly(el).repaint();
+ });
+ }
+ },
+
+ // private
+ doDisabled : function(disabled){
+ this.keyNav.setDisabled(disabled);
+ this.prevRepeater.setDisabled(disabled);
+ this.nextRepeater.setDisabled(disabled);
+ if(this.showToday){
+ this.todayKeyListener.setDisabled(disabled);
+ this.todayBtn.setDisabled(disabled);
+ }
+ },
+
+ // private
+ onRender : function(container, position){
+ var m = [
+ '<table cellspacing="0">',
+ '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'"> </a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'"> </a></td></tr>',
+ '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'],
+ dn = this.dayNames,
+ i;
+ for(i = 0; i < 7; i++){
+ var d = this.startDay+i;
+ if(d > 6){
+ d = d-7;
+ }
+ m.push('<th><span>', dn[d].substr(0,1), '</span></th>');
+ }
+ m[m.length] = '</tr></thead><tbody><tr>';
+ for(i = 0; i < 42; i++) {
+ if(i % 7 === 0 && i !== 0){
+ m[m.length] = '</tr><tr>';
+ }
+ m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
+ }
+ m.push('</tr></tbody></table></td></tr>',
+ this.showToday ? '<tr><td colspan="3" class="x-date-bottom" align="center"></td></tr>' : '',
+ '</table><div class="x-date-mp"></div>');
+
+ var el = document.createElement('div');
+ el.className = 'x-date-picker';
+ el.innerHTML = m.join('');
+
+ container.dom.insertBefore(el, position);
+
+ this.el = Ext.get(el);
+ this.eventEl = Ext.get(el.firstChild);
+
+ this.prevRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-left a'), {
+ handler: this.showPrevMonth,
+ scope: this,
+ preventDefault:true,
+ stopDefault:true
+ });
+
+ this.nextRepeater = new Ext.util.ClickRepeater(this.el.child('td.x-date-right a'), {
+ handler: this.showNextMonth,
+ scope: this,
+ preventDefault:true,
+ stopDefault:true
+ });
+
+ this.monthPicker = this.el.down('div.x-date-mp');
+ this.monthPicker.enableDisplayMode('block');
+
+ this.keyNav = new Ext.KeyNav(this.eventEl, {
+ 'left' : function(e){
+ if(e.ctrlKey){
+ this.showPrevMonth();
+ }else{
+ this.update(this.activeDate.add('d', -1));
+ }
+ },
+
+ 'right' : function(e){
+ if(e.ctrlKey){
+ this.showNextMonth();
+ }else{
+ this.update(this.activeDate.add('d', 1));
+ }
+ },
+
+ 'up' : function(e){
+ if(e.ctrlKey){
+ this.showNextYear();
+ }else{
+ this.update(this.activeDate.add('d', -7));
+ }
+ },
+
+ 'down' : function(e){
+ if(e.ctrlKey){
+ this.showPrevYear();
+ }else{
+ this.update(this.activeDate.add('d', 7));
+ }
+ },
+
+ 'pageUp' : function(e){
+ this.showNextMonth();
+ },
+
+ 'pageDown' : function(e){
+ this.showPrevMonth();
+ },
+
+ 'enter' : function(e){
+ e.stopPropagation();
+ return true;
+ },
+
+ scope : this
+ });
+
+ this.el.unselectable();
+
+ this.cells = this.el.select('table.x-date-inner tbody td');
+ this.textNodes = this.el.query('table.x-date-inner tbody span');
+
+ this.mbtn = new Ext.Button({
+ text: ' ',
+ tooltip: this.monthYearText,
+ renderTo: this.el.child('td.x-date-middle', true)
+ });
+ this.mbtn.el.child('em').addClass('x-btn-arrow');
+
+ if(this.showToday){
+ this.todayKeyListener = this.eventEl.addKeyListener(Ext.EventObject.SPACE, this.selectToday, this);
+ var today = (new Date()).dateFormat(this.format);
+ this.todayBtn = new Ext.Button({
+ renderTo: this.el.child('td.x-date-bottom', true),
+ text: String.format(this.todayText, today),
+ tooltip: String.format(this.todayTip, today),
+ handler: this.selectToday,
+ scope: this
+ });
+ }
+ this.mon(this.eventEl, 'mousewheel', this.handleMouseWheel, this);
+ this.mon(this.eventEl, 'click', this.handleDateClick, this, {delegate: 'a.x-date-date'});
+ this.mon(this.mbtn, 'click', this.showMonthPicker, this);
+ this.onEnable(true);
+ },
+
+ // private
+ createMonthPicker : function(){
+ if(!this.monthPicker.dom.firstChild){
+ var buf = ['<table border="0" cellspacing="0">'];
+ for(var i = 0; i < 6; i++){
+ buf.push(
+ '<tr><td class="x-date-mp-month"><a href="#">', Date.getShortMonthName(i), '</a></td>',
+ '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', Date.getShortMonthName(i + 6), '</a></td>',
+ i === 0 ?
+ '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
+ '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
+ );
+ }
+ buf.push(
+ '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
+ this.okText,
+ '</button><button type="button" class="x-date-mp-cancel">',
+ this.cancelText,
+ '</button></td></tr>',
+ '</table>'
+ );
+ this.monthPicker.update(buf.join(''));
+
+ this.mon(this.monthPicker, 'click', this.onMonthClick, this);
+ this.mon(this.monthPicker, 'dblclick', this.onMonthDblClick, this);
+
+ this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
+ this.mpYears = this.monthPicker.select('td.x-date-mp-year');
+
+ this.mpMonths.each(function(m, a, i){
+ i += 1;
+ if((i%2) === 0){
+ m.dom.xmonth = 5 + Math.round(i * 0.5);
+ }else{
+ m.dom.xmonth = Math.round((i-1) * 0.5);
+ }
+ });
+ }
+ },
+
+ // private
+ showMonthPicker : function(){
+ if(!this.disabled){
+ this.createMonthPicker();
+ var size = this.el.getSize();
+ this.monthPicker.setSize(size);
+ this.monthPicker.child('table').setSize(size);
+
+ this.mpSelMonth = (this.activeDate || this.value).getMonth();
+ this.updateMPMonth(this.mpSelMonth);
+ this.mpSelYear = (this.activeDate || this.value).getFullYear();
+ this.updateMPYear(this.mpSelYear);
+
+ this.monthPicker.slideIn('t', {duration:0.2});
+ }
+ },
+
+ // private
+ updateMPYear : function(y){
+ this.mpyear = y;
+ var ys = this.mpYears.elements;
+ for(var i = 1; i <= 10; i++){
+ var td = ys[i-1], y2;
+ if((i%2) === 0){
+ y2 = y + Math.round(i * 0.5);
+ td.firstChild.innerHTML = y2;
+ td.xyear = y2;
+ }else{
+ y2 = y - (5-Math.round(i * 0.5));
+ td.firstChild.innerHTML = y2;
+ td.xyear = y2;
+ }
+ this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
+ }
+ },
+
+ // private
+ updateMPMonth : function(sm){
+ this.mpMonths.each(function(m, a, i){
+ m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
+ });
+ },
+
+ // private
+ selectMPMonth : function(m){
+
+ },
+
+ // private
+ onMonthClick : function(e, t){
+ e.stopEvent();
+ var el = new Ext.Element(t), pn;
+ if(el.is('button.x-date-mp-cancel')){
+ this.hideMonthPicker();
+ }
+ else if(el.is('button.x-date-mp-ok')){
+ var d = new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate());
+ if(d.getMonth() != this.mpSelMonth){
+ // 'fix' the JS rolling date conversion if needed
+ d = new Date(this.mpSelYear, this.mpSelMonth, 1).getLastDateOfMonth();
+ }
+ this.update(d);
+ this.hideMonthPicker();
+ }
+ else if((pn = el.up('td.x-date-mp-month', 2))){
+ this.mpMonths.removeClass('x-date-mp-sel');
+ pn.addClass('x-date-mp-sel');
+ this.mpSelMonth = pn.dom.xmonth;
+ }
+ else if((pn = el.up('td.x-date-mp-year', 2))){
+ this.mpYears.removeClass('x-date-mp-sel');
+ pn.addClass('x-date-mp-sel');
+ this.mpSelYear = pn.dom.xyear;
+ }
+ else if(el.is('a.x-date-mp-prev')){
+ this.updateMPYear(this.mpyear-10);
+ }
+ else if(el.is('a.x-date-mp-next')){
+ this.updateMPYear(this.mpyear+10);
+ }
+ },
+
+ // private
+ onMonthDblClick : function(e, t){
+ e.stopEvent();
+ var el = new Ext.Element(t), pn;
+ if((pn = el.up('td.x-date-mp-month', 2))){
+ this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
+ this.hideMonthPicker();
+ }
+ else if((pn = el.up('td.x-date-mp-year', 2))){
+ this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
+ this.hideMonthPicker();
+ }
+ },
+
+ // private
+ hideMonthPicker : function(disableAnim){
+ if(this.monthPicker){
+ if(disableAnim === true){
+ this.monthPicker.hide();
+ }else{
+ this.monthPicker.slideOut('t', {duration:0.2});
+ }
+ }
+ },
+
+ // private
+ showPrevMonth : function(e){
+ this.update(this.activeDate.add('mo', -1));
+ },
+
+ // private
+ showNextMonth : function(e){
+ this.update(this.activeDate.add('mo', 1));
+ },
+
+ // private
+ showPrevYear : function(){
+ this.update(this.activeDate.add('y', -1));
+ },
+
+ // private
+ showNextYear : function(){
+ this.update(this.activeDate.add('y', 1));
+ },
+
+ // private
+ handleMouseWheel : function(e){
+ e.stopEvent();
+ if(!this.disabled){
+ var delta = e.getWheelDelta();
+ if(delta > 0){
+ this.showPrevMonth();
+ } else if(delta < 0){
+ this.showNextMonth();
+ }
+ }
+ },
+
+ // private
+ handleDateClick : function(e, t){
+ e.stopEvent();
+ if(!this.disabled && t.dateValue && !Ext.fly(t.parentNode).hasClass('x-date-disabled')){
+ this.cancelFocus = this.focusOnSelect === false;
+ this.setValue(new Date(t.dateValue));
+ delete this.cancelFocus;
+ this.fireEvent('select', this, this.value);
+ }
+ },
+
+ // private
+ selectToday : function(){
+ if(this.todayBtn && !this.todayBtn.disabled){
+ this.setValue(new Date().clearTime());
+ this.fireEvent('select', this, this.value);
+ }
+ },
+
+ // private
+ update : function(date, forceRefresh){
+ 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 && !this.cancelFocus){
+ Ext.fly(c.dom.firstChild).focus(50);
+ }
+ return false;
+ }
+ }, this);
+ 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]);
+ }
+ }
+ }
+ },
+
+ // private
+ beforeDestroy : function() {
+ if(this.rendered){
+ Ext.destroy(
+ this.keyNav,
+ this.monthPicker,
+ this.eventEl,
+ this.mbtn,
+ this.nextRepeater,
+ this.prevRepeater,
+ this.cells.el,
+ this.todayBtn
+ );
+ delete this.textNodes;
+ delete this.cells.elements;
+ }
+ }
+
+ /**
+ * @cfg {String} autoEl @hide
+ */
+});
+
+Ext.reg('datepicker', Ext.DatePicker);
/**
* @class Ext.LoadMask
* A simple utility class for generically masking elements while loading data. If the {@link #store}
this.el = Ext.get(el);
Ext.apply(this, config);
if(this.store){
- this.store.on('beforeload', this.onBeforeLoad, this);
- this.store.on('load', this.onLoad, this);
- this.store.on('exception', this.onLoad, this);
+ this.store.on({
+ scope: this,
+ beforeload: this.onBeforeLoad,
+ load: this.onLoad,
+ exception: this.onLoad
+ });
this.removeMask = Ext.value(this.removeMask, false);
}else{
var um = this.el.getUpdater();
um.showLoadIndicator = false; // disable the default indicator
- um.on('beforeupdate', this.onBeforeLoad, this);
- um.on('update', this.onLoad, this);
- um.on('failure', this.onLoad, this);
+ um.on({
+ scope: this,
+ beforeupdate: this.onBeforeLoad,
+ update: this.onLoad,
+ failure: this.onLoad
+ });
this.removeMask = Ext.value(this.removeMask, true);
}
};
autoStart: 300\r
});\r
this.tracker.initEl(this.thumb);\r
- this.on('beforedestroy', this.tracker.destroy, this.tracker);\r
},\r
\r
// private override\r
onMouseDown : function(e){\r
- if(this.disabled) {return;}\r
+ if(this.disabled){\r
+ return;\r
+ }\r
if(this.clickToChange && e.target != this.thumb.dom){\r
var local = this.innerEl.translatePoints(e.getXY());\r
this.onClickChange(local);\r
\r
// private\r
doSnap : function(value){\r
- if(!this.increment || this.increment == 1 || !value) {\r
+ if(!(this.increment && value)){\r
return value;\r
}\r
- var newValue = value, inc = this.increment;\r
- var m = value % inc;\r
+ var newValue = value, \r
+ inc = this.increment,\r
+ m = value % inc;\r
if(m != 0){\r
newValue -= m;\r
if(m * 2 > inc){\r
\r
// private\r
getRatio : function(){\r
- var w = this.innerEl.getWidth();\r
- var v = this.maxValue - this.minValue;\r
+ var w = this.innerEl.getWidth(),\r
+ v = this.maxValue - this.minValue;\r
return v == 0 ? w : (w/v);\r
},\r
\r
// private\r
translateValue : function(v){\r
var ratio = this.getRatio();\r
- return (v * ratio)-(this.minValue * ratio)-this.halfThumb;\r
+ return (v * ratio) - (this.minValue * ratio) - this.halfThumb;\r
},\r
\r
reverseValue : function(pos){\r
var ratio = this.getRatio();\r
- return (pos+this.halfThumb+(this.minValue * ratio))/ratio;\r
+ return (pos + this.halfThumb + (this.minValue * ratio)) / ratio;\r
},\r
\r
// private\r
this.thumb.removeClass(this.disabledClass);\r
if(Ext.isIE){\r
this.innerEl.removeClass(this.disabledClass).dom.disabled = false;\r
- if (this.thumbHolder){\r
+ if(this.thumbHolder){\r
this.thumbHolder.hide();\r
}\r
this.thumb.show();\r
*/\r
getValue : function(){\r
return this.value;\r
+ },\r
+ \r
+ // private\r
+ beforeDestroy : function(){\r
+ Ext.destroyMembers(this, 'endEl', 'innerEl', 'thumb', 'halfThumb', 'focusEl', 'tracker', 'thumbHolder');\r
+ Ext.Slider.superclass.beforeDestroy.call(this);\r
}\r
});\r
Ext.reg('slider', Ext.Slider);\r
},\r
\r
getRatio : function(){\r
- var h = this.innerEl.getHeight();\r
- var v = this.maxValue - this.minValue;\r
+ var h = this.innerEl.getHeight(),\r
+ v = this.maxValue - this.minValue;\r
return h/v;\r
},\r
\r
},\r
\r
onDrag: function(e){\r
- var pos = this.innerEl.translatePoints(this.tracker.getXY());\r
- var bottom = this.innerEl.getHeight()-pos.top;\r
+ var pos = this.innerEl.translatePoints(this.tracker.getXY()),\r
+ bottom = this.innerEl.getHeight()-pos.top;\r
this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), false);\r
this.fireEvent('drag', this, e);\r
},\r
\r
onClickChange : function(local){\r
if(local.left > this.clickRange[0] && local.left < this.clickRange[1]){\r
- var bottom = this.innerEl.getHeight()-local.top;\r
+ var bottom = this.innerEl.getHeight() - local.top;\r
this.setValue(this.minValue + Ext.util.Format.round(bottom/this.getRatio(), this.decimalPrecision), undefined, true);\r
}\r
}\r
this.waitTimer = Ext.TaskMgr.start({\r
run: function(i){\r
var inc = o.increment || 10;\r
+ i -= 1;\r
this.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate);\r
},\r
interval: o.interval || 1000,\r
this.hide();\r
}\r
return this;\r
+ },\r
+ \r
+ onDestroy: function(){\r
+ if(this.rendered){\r
+ if(this.textEl.isComposite){\r
+ this.textEl.clear();\r
+ }\r
+ Ext.destroyMembers(this, 'textEl', 'progressBar', 'textTopEl');\r
+ }\r
+ Ext.ProgressBar.superclass.onDestroy.call(this);\r
}\r
});\r
Ext.reg('progress', Ext.ProgressBar);
\ No newline at end of file