/**
* @class Ext.container.Container
* @extends Ext.AbstractContainer
* <p>Base class for any {@link Ext.Component} that may contain other Components. Containers handle the
* basic behavior of containing items, namely adding, inserting and removing items.</p>
*
* <p>The most commonly used Container classes are {@link Ext.panel.Panel}, {@link Ext.window.Window} and {@link Ext.tab.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
* <code><b>{@link Ext.Component#autoEl autoEl}</b></code> config option.</p>
*
* <p>The code below illustrates how to explicitly create a Container:
**/// explicitly create a Container
var embeddedColumns = new Ext.container.Container({
autoEl: {tag: 'div'},
layout: {
type: 'hbox'
},
width: 400,
defaults: {
labelWidth: 80,
// implicitly create Container by specifying xtype
xtype: 'datefield',
flex: 1,
style: {
padding: '10px'
}
},
items: [{
xtype: 'datefield',
name: 'startDate',
fieldLabel: 'Start date'
}, {
xtype: 'datefield',
name: 'endDate',
fieldLabel: 'End date'
}]
});
/**</p>
*
* <p><u><b>Layout</b></u></p>
* <p>Container classes delegate the rendering of child Components to a layout
* manager class which must be configured into the Container using the
* <code><b>{@link #layout}</b></code> configuration property.</p>
* <p>When either specifying child <code>{@link #items}</code> of a Container,
* or dynamically {@link #add adding} Components to a Container, remember to
* consider how you wish the Container to arrange those child elements, and
* whether those child elements need to be sized using one of Ext's built-in
* <b><code>{@link #layout}</code></b> schemes. By default, Containers use the
* {@link Ext.layout.container.Auto Auto} scheme which only
* renders child components, appending them one after the other inside the
* 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 <code><b>{@link #layout}</b></code>
* has been specified). If a Container is left to use the default
* {Ext.layout.container.Auto Auto} scheme, none of its
* child components will be resized, or changed in any way when the Container
* is resized.</p>
* <p>Certain layout managers allow dynamic addition of child components.
* Those that do include {@link Ext.layout.container.Card},
* {@link Ext.layout.container.Anchor}, {@link Ext.layout.container.VBox}, {@link Ext.layout.container.HBox}, and
* {@link Ext.layout.container.Table}. For example:
**/// Create the GridPanel.
var myNewGrid = new Ext.grid.GridPanel({
store: myStore,
headers: myHeaders,
title: 'Results', // the title becomes the title of the tab
});
myTabPanel.add(myNewGrid); // {@link Ext.tab.TabPanel} implicitly uses {@link Ext.layout.container.Card Card}
myTabPanel.{@link Ext.tab.TabPanel#setActiveTab setActiveTab}(myNewGrid);
*
/**</p>
* <p>The example above adds a newly created GridPanel to a TabPanel. Note that
* a TabPanel uses {@link Ext.layout.container.Card} as its layout manager which
* means all its child items are sized to {@link Ext.layout.container.Fit fit}
* exactly into its client area.
* <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
* <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 <code><b>{@link #layout}</b></code> configuration, then the overnested
* GridPanel will not be sized as expected.<p>
*
* <p><u><b>Adding via remote configuration</b></u></p>
*
* <p>A server side script can be used to add Components which are generated dynamically on the server.
* An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server
* based on certain parameters:
* </p>
**/// execute an Ajax request to invoke server side script:
Ext.Ajax.request({
url: 'gen-invoice-grid.php',
// send additional parameters to instruct server script
params: {
startDate: Ext.getCmp('start-date').getValue(),
endDate: Ext.getCmp('end-date').getValue()
},
// process the response object to add it to the TabPanel:
success: function(xhr) {
var newComponent = eval(xhr.responseText); // see discussion below
myTabPanel.add(newComponent); // add the component to the TabPanel
myTabPanel.setActiveTab(newComponent);
},
failure: function() {
Ext.Msg.alert("Grid create failed", "Server communication failure");
}
});
/** * <p>The server script needs to return a JSON representation of a configuration object, which, when decoded
* will return a config object with an {@link Ext.Component#xtype xtype}. The server might return the following
* JSON:</p>
**/{
"xtype": 'grid',
"title": 'Invoice Report',
"store": {
"model": 'Invoice',
"proxy": {
"type": 'ajax',
"url": 'get-invoice-data.php',
"reader": {
"type": 'json'
"record": 'transaction',
"idProperty": 'id',
"totalRecords": 'total'
})
},
"autoLoad": {
"params": {
"startDate": '01/01/2008',
"endDate": '01/31/2008'
}
}
},
"headers": [
{"header": "Customer", "width": 250, "dataIndex": 'customer', "sortable": true},
{"header": "Invoice Number", "width": 120, "dataIndex": 'invNo', "sortable": true},
{"header": "Invoice Date", "width": 100, "dataIndex": 'date', "renderer": Ext.util.Format.dateRenderer('M d, y'), "sortable": true},
{"header": "Value", "width": 120, "dataIndex": 'value', "renderer": 'usMoney', "sortable": true}
]
}
/** * <p>When the above code fragment is passed through the <code>eval</code> function in the success handler
* of the Ajax request, the result will be a config object which, when added to a Container, will cause instantiation
* of a GridPanel. <b>Be sure that the Container is configured with a layout which sizes and positions the child items to your requirements.</b></p>
* <p>Note: since the code above is <i>generated</i> by a server script, the <code>autoLoad</code> params for
* the Store, the user's preferred date format, the metadata to allow generation of the Model layout, and the ColumnModel
* can all be generated into the code since these are all known on the server.</p>
*
* @xtype container
*/
Ext.define('Ext.container.Container', {
extend: 'Ext.AbstractContainer',
alias: 'widget.container',
alternateClassName: 'Ext.Container',
/**
* Return the immediate child Component in which the passed element is located.
* @param el The element to test.
* @return {Component} The child item which contains the passed element.
*/
getChildByElement: function(el) {
var item,
itemEl,
i = 0,
it = this.items.items,
ln = it.length;
el = Ext.getDom(el);
for (; i < ln; i++) {
item = it[i];
itemEl = item.getEl();
if ((itemEl.dom === el) || itemEl.contains(el)) {
return item;
}
}
return null;
}
});