X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/c930e9176a5a85509c5b0230e2bff5c22a591432..c8256059947f3aa8f5b0a9a2acf55e2142bb4742:/docs/source/Container.html diff --git a/docs/source/Container.html b/docs/source/Container.html index b9fc4778..d3646da4 100644 --- a/docs/source/Container.html +++ b/docs/source/Container.html @@ -1,11 +1,18 @@ - -
-/** + + + +The source code + + + + +/*! + * Ext JS Library 3.2.1 + * Copyright(c) 2006-2010 Ext JS, Inc. + * licensing@extjs.com + * http://www.extjs.com/license + */ +/** * @class Ext.Container * @extends Ext.BoxComponent ** - *Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the @@ -14,12 +21,12 @@ *
The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}. * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight * Container to be encapsulated by an HTML element to your specifications by using the - * {@link Ext.Component#autoEl autoEl} config option. This is a useful technique when creating + *
* *{@link Ext.Component#autoEl autoEl}
config option. This is a useful technique when creating * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels} * for example.The code below illustrates both how to explicitly create a Container, and how to implicitly - * create one using the 'container' xtype:
*+ * create one using the
'container'
xtype:*// explicitly create a Container var embeddedColumns = new Ext.Container({ autoEl: 'div', // This is the default @@ -64,7 +71,7 @@ var embeddedColumns = new Ext.Container({ * Container, and does not apply any sizing at all. *
A common mistake is when a developer neglects to specify a *
{@link #layout}
(e.g. widgets like GridPanels or - * TreePanels are added to Containers for which no {@link #layout} + * TreePanels are added to Containers for which no{@link #layout}
* has been specified). If a Container is left to use the default * {@link Ext.layout.ContainerLayout ContainerLayout} scheme, none of its * child components will be resized, or changed in any way when the Container @@ -90,10 +97,10 @@ myTabPanel.{@link Ext.TabPanel#setActiveTab setActiveTab}(myNewGrid); *Overnesting is a common problem. * An example of overnesting occurs when a GridPanel is added to a TabPanel * by wrapping the GridPanel inside a wrapping Panel (that has no - * {@link #layout} specified) and then add that wrapping Panel + *
{@link #layout}
specified) and then add that wrapping Panel * to the TabPanel. The point to realize is that a GridPanel is a * Component which can be added directly to a Container. If the wrapping Panel - * has no {@link #layout} configuration, then the overnested + * has no{@link #layout}
configuration, then the overnested * GridPanel will not be sized as expected.* *
Adding via remote configuration
@@ -122,7 +129,7 @@ Ext.Ajax.request({ });The server script needs to return an executable Javascript statement which, when processed - * using eval(), will return either a config object with an {@link Ext.Component#xtype xtype}, + * using
eval()
, will return either a config object with an {@link Ext.Component#xtype xtype}, * or an instantiated Component. The server might return this for example:- *(function() { function formatDate(value){ @@ -162,10 +169,10 @@ Ext.Ajax.request({ return grid; // return instantiated component })();
When the above code fragment is passed through the eval function in the success handler + *
When the above code fragment is passed through the
- *eval
function in the success handler * of the Ajax request, the code is executed by the Javascript processor, and the anonymous function * runs, and returns the instantiated grid component.Note: since the code above is generated by a server script, the baseParams for + *
Note: since the code above is generated by a server script, the
* @@ -195,7 +202,7 @@ new Ext.Window({ }).show(); *baseParams
for * the Store, the metadata to allow generation of the Record layout, and the ColumnModel * can all be generated into the code since these are all known on the server.If the {@link #layout} configuration is not explicitly specified for - * a general purpose container (e.g. Container or Panel) the + * 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). @@ -217,31 +224,31 @@ layout: { }
type
The layout type to be used for this container. If not specified, * a default {@link Ext.layout.ContainerLayout} will be created and used.
- *Valid layout type values are:
+ *Valid layout type
values are:
{@link Ext.layout.AbsoluteLayout absolute}
{@link Ext.layout.AccordionLayout accordion}
{@link Ext.layout.AnchorLayout anchor}
{@link Ext.layout.ContainerLayout auto}
Default{@link Ext.layout.BorderLayout border}
{@link Ext.layout.CardLayout card}
{@link Ext.layout.ColumnLayout column}
{@link Ext.layout.FitLayout fit}
{@link Ext.layout.FormLayout form}
{@link Ext.layout.HBoxLayout hbox}
{@link Ext.layout.MenuLayout menu}
{@link Ext.layout.TableLayout table}
{@link Ext.layout.ToolbarLayout toolbar}
{@link Ext.layout.VBoxLayout vbox}
Additional layout specific configuration properties may also be
* specified. For complete details regarding the valid config options for
- * each layout type, see the layout class corresponding to the type
+ * each layout type, see the layout class corresponding to the type
* specified.
The layout type to be used for this container (see list + *
layout
The layout type
to be used for this container (see list
* of valid layout type values above).
{@link #layoutConfig}
Additional layout specific configuration properties. For complete * details regarding the valid config options for each layout type, see the - * layout class corresponding to the layout specified.
+ * layout class corresponding to thelayout
specified.
*
*/
/**
@@ -273,12 +280,12 @@ layoutConfig: {
*/
/**
* @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 50
.
*/
- 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
@@ -326,14 +333,18 @@ layout: 'anchor', // specify a layout!
*
*/
/**
- * @cfg {Object} defaults
- * A config object that will be applied to all components added to this container either via the {@link #items} - * config or via the {@link #add} or {@link #insert} methods. The defaults config can contain any - * number of name/value property pairs to be added to each item, and should be valid for the types of items - * being added to the container. For example, to automatically apply padding to the body of each of a set of - * contained {@link Ext.Panel} items, you could pass: defaults: {bodyStyle:'padding:15px'}.
Note: defaults will not be applied to config objects if the option is already specified. - * For example:
+ * @cfg {Object|Function} defaults
+ * 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.
+ * If an added item is a config object, and not an instantiated Component, then the default properties are
+ * unconditionally applied. If the added item is an instantiated Component, then the default properties are
+ * applied conditionally so as not to override existing properties in the item.
+ * If the defaults option is specified as a function, then the function will be called using this Container as the
+ * scope (this
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.
+ * For example, to automatically apply padding to the body of each of a set of
+ * contained {@link Ext.Panel} items, you could pass: defaults: {bodyStyle:'padding:15px'}
.
+ * Usage:
defaults: { // defaults are applied to items, not the container
autoScroll:true
},
@@ -371,11 +382,24 @@ items: [
/** @cfg {String} defaultType
* The default {@link Ext.Component xtype} of child Components to create in this Container when
* a child item is specified as a raw configuration object, rather than as an instantiated Component.
- * Defaults to 'panel', except {@link Ext.menu.Menu} which defaults to 'menuitem',
- * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to 'button'.
+ * Defaults to 'panel'
, except {@link Ext.menu.Menu} which defaults to 'menuitem'
,
+ * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to 'button'
.
*/
defaultType : 'panel',
+ /** @cfg {String} resizeEvent
+ * The event to listen to for resizing in layouts. Defaults to 'resize'
.
+ */
+ resizeEvent: 'resize',
+
+ /**
+ * @cfg {Array} bubbleEvents
+ * An array of events that, when fired, should be bubbled to any parent container.
+ * See {@link Ext.util.Observable#enableBubble}.
+ * Defaults to ['add', 'remove']
.
+ */
+ bubbleEvents: ['add', 'remove'],
+
// private
initComponent : function(){
Ext.Container.superclass.initComponent.call(this);
@@ -424,8 +448,6 @@ items: [
'remove'
);
- this.enableBubble('add', 'remove');
-
/**
* The collection of components in this container as a {@link Ext.util.MixedCollection}
* @type MixedCollection
@@ -434,11 +456,7 @@ items: [
var items = this.items;
if(items){
delete this.items;
- if(Ext.isArray(items) && items.length > 0){
- this.add.apply(this, items);
- }else{
- this.add(items);
- }
+ this.add(items);
}
},
@@ -455,34 +473,41 @@ items: [
if(this.layout && this.layout != layout){
this.layout.setContainer(null);
}
- this.initItems();
this.layout = layout;
+ this.initItems();
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(){
+ // Render this Container, this should be done before setLayout is called which
+ // will hook onResize
+ Ext.Container.superclass.afterRender.call(this);
+ if(!this.layout){
+ this.layout = 'auto';
+ }
+ if(Ext.isObject(this.layout) && !this.layout.layout){
+ this.layoutConfig = this.layout;
+ this.layout = this.layoutConfig.type;
+ }
+ if(Ext.isString(this.layout)){
+ this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig);
+ }
+ this.setLayout(this.layout);
- if(this.activeItem !== undefined){
- var item = this.activeItem;
- delete this.activeItem;
- this.layout.setActiveItem(item);
- }
+ // If a CardLayout, the active item set
+ if(this.activeItem !== undefined){
+ var item = this.activeItem;
+ delete this.activeItem;
+ this.layout.setActiveItem(item);
}
+
+ // If we have no ownerCt, render and size all children
if(!this.ownerCt){
- // force a layout if no ownerCt is set
this.doLayout(false, true);
}
+
+ // This is a manually configured flag set by users in conjunction with renderTo.
+ // Not to be confused with the flag by the same name used in Layouts.
if(this.monitorResize === true){
Ext.EventManager.onWindowResize(this.doLayout, this, [false]);
}
@@ -515,10 +540,10 @@ items: [
*
*
Notes :
*
- * - If the Container is already rendered when add
+ *
- If the Container is already rendered when
add
* 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
- * add multiple child components if needed while only refreshing the layout
+ * add
multiple child components if needed while only refreshing the layout
* once. For example:
var tb = new {@link Ext.Toolbar}();
tb.render(document.body); // toolbar is rendered
@@ -530,32 +555,49 @@ tb.{@link #doLayout}(); // refresh the layout
* may not be removed or added. See the Notes for {@link Ext.layout.BorderLayout BorderLayout}
* for more details.
*
- * @param {Object/Array} component
- * Either a single component or an Array of components to add. See
+ * @param {...Object/Array} component
+ *
Either one or more Components to add or an Array of Components to add. See
* {@link #items}
for additional information.
- * @param {Object} (Optional) component_2
- * @param {Object} (Optional) component_n
- * @return {Ext.Component} component The Component (or config object) that was added.
+ * @return {Ext.Component/Array} The Components that were added.
*/
add : function(comp){
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
@@ -578,20 +620,21 @@ tb.{@link #doLayout}(); // refresh the layout
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;
@@ -599,14 +642,18 @@ tb.{@link #doLayout}(); // refresh the layout
// 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;
@@ -634,19 +681,35 @@ tb.{@link #doLayout}(); // refresh the layout
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){
+ var l = this.layout,
+ hasLayout = l && this.rendered;
+
+ if(hasLayout){
+ l.onRemove(c);
+ }
+ this.items.remove(c);
+ c.onRemoved();
+ this.onRemove(c);
+ if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){
+ c.destroy();
+ }
+ if(hasLayout){
+ l.afterRemove(c);
+ }
+ },
+
/**
* Removes all components from this container.
* @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
@@ -674,9 +737,9 @@ tb.{@link #doLayout}(); // refresh the layout
* and gets a direct child component of this container.
* @param {String/Number} comp This parameter may be any of the following:
*
- * - a String : representing the
{@link Ext.Component#itemId itemId}
+ * - a
String
: representing the {@link Ext.Component#itemId itemId}
* or {@link Ext.Component#id id}
of the child component
- * - a Number : representing the position of the child component
+ *
- a
Number
: representing the position of the child component
* within the {@link #items}
property
*
* For additional information see {@link Ext.util.MixedCollection#get}.
@@ -684,14 +747,14 @@ tb.{@link #doLayout}(); // refresh the layout
*/
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);
@@ -700,8 +763,28 @@ tb.{@link #doLayout}(); // refresh the layout
},
// private
- createComponent : function(config){
- return Ext.create(config, this.defaultType);
+ createComponent : function(config, defaultType){
+ if (config.render) {
+ return config;
+ }
+ // add in ownerCt at creation time but then immediately
+ // remove so that onBeforeAdd can handle it
+ var c = Ext.create(Ext.apply({
+ ownerCt: this
+ }, config), defaultType || this.defaultType);
+ delete c.initialConfig.ownerCt;
+ delete c.ownerCt;
+ return c;
+ },
+
+ /**
+ * @private
+ * 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.getVisibilityEl();
+ return el && el.dom && !el.isStyle("display", "none");
},
/**
@@ -712,13 +795,14 @@ tb.{@link #doLayout}(); // refresh the layout
* @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden.
* @return {Ext.Container} this
*/
- doLayout: function(shallow, force){
+
+ doLayout : function(shallow, force){
var rendered = this.rendered,
- forceLayout = this.forceLayout;
+ forceLayout = force || this.forceLayout;
- if(!this.isVisible() || this.collapsed){
+ if(this.collapsed || !this.canLayout()){
this.deferLayout = this.deferLayout || !shallow;
- if(!(force || forceLayout)){
+ if(!forceLayout){
return;
}
shallow = shallow && !this.deferLayout;
@@ -733,23 +817,55 @@ tb.{@link #doLayout}(); // refresh the layout
for(var i = 0, len = cs.length; i < len; i++){
var c = cs[i];
if(c.doLayout){
- c.forceLayout = forceLayout;
- c.doLayout();
+ c.doLayout(false, forceLayout);
}
}
}
if(rendered){
- this.onLayout(shallow, force);
+ this.onLayout(shallow, forceLayout);
}
+ // Initial layout completed
+ this.hasLayout = true;
delete this.forceLayout;
},
- //private
onLayout : Ext.emptyFn,
+ // private
+ shouldBufferLayout: function(){
+ /*
+ * Returns true if the container should buffer a layout.
+ * This is true only if the container has previously been laid out
+ * and has a parent container that is pending a layout.
+ */
+ var hl = this.hasLayout;
+ if(this.ownerCt){
+ // Only ever buffer if we've laid out the first time and we have one pending.
+ return hl ? !this.hasLayoutPending() : false;
+ }
+ // Never buffer initial layout
+ return hl;
+ },
+
+ // private
+ hasLayoutPending: function(){
+ // Traverse hierarchy to see if any parent container has a pending layout.
+ var pending = false;
+ this.ownerCt.bubble(function(c){
+ if(c.layoutPending){
+ pending = true;
+ return false;
+ }
+ });
+ return pending;
+ },
+
onShow : function(){
+ // removes css classes that were added to hide
Ext.Container.superclass.onShow.call(this);
- if(this.deferLayout !== undefined){
+ // If we were sized during the time we were hidden, layout.
+ if(Ext.isDefined(this.deferLayout)){
+ delete this.deferLayout;
this.doLayout(true);
}
},
@@ -761,7 +877,7 @@ tb.{@link #doLayout}(); // refresh the layout
*/
getLayout : function(){
if(!this.layout){
- var layout = new Ext.layout.ContainerLayout(this.layoutConfig);
+ var layout = new Ext.layout.AutoLayout(this.layoutConfig);
this.setLayout(layout);
}
return this.layout;
@@ -769,8 +885,11 @@ tb.{@link #doLayout}(); // refresh the layout
// 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);
@@ -897,6 +1016,6 @@ tb.{@link #doLayout}(); // refresh the layout
Ext.Container.LAYOUTS = {};
Ext.reg('container', Ext.Container);
-
-
+
+
\ No newline at end of file