Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / docs / source / Container2.html
index 812ac75..2240c5f 100644 (file)
   </script>
 </head>
 <body onload="prettyPrint(); highlight();">
-  <pre class="prettyprint lang-js"><span id='Ext-grid-header-Container'>/**
-</span> * @class Ext.grid.header.Container
- * @extends Ext.container.Container
- * @private
+  <pre class="prettyprint lang-js"><span id='Ext-container-Container'>/**
+</span> * @class Ext.container.Container
+ * @extends Ext.container.AbstractContainer
+ * &lt;p&gt;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.&lt;/p&gt;
  *
- * Container which holds headers and is docked at the top or bottom of a TablePanel.
- * The HeaderContainer drives resizing/moving/hiding of columns within the TableView.
- * As headers are hidden, moved or resized the headercontainer is responsible for
- * triggering changes within the view.
+ * &lt;p&gt;The most commonly used Container classes are {@link Ext.panel.Panel}, {@link Ext.window.Window} and {@link Ext.tab.Panel}.
+ * 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
+ * &lt;code&gt;&lt;b&gt;{@link Ext.Component#autoEl autoEl}&lt;/b&gt;&lt;/code&gt; config option.&lt;/p&gt;
  *
- * @xtype headercontainer
- */
-Ext.define('Ext.grid.header.Container', {
-    extend: 'Ext.container.Container',
-    uses: [
-        'Ext.grid.ColumnLayout',
-        'Ext.grid.column.Column',
-        'Ext.menu.Menu',
-        'Ext.menu.CheckItem',
-        'Ext.menu.Separator',
-        'Ext.grid.plugin.HeaderResizer',
-        'Ext.grid.plugin.HeaderReorderer'
-    ],
-    border: true,
-
-    alias: 'widget.headercontainer',
-
-    baseCls: Ext.baseCSSPrefix + 'grid-header-ct',
-    dock: 'top',
-
-<span id='Ext-grid-header-Container-cfg-weight'>    /**
-</span>     * @cfg {Number} weight
-     * HeaderContainer overrides the default weight of 0 for all docked items to 100.
-     * This is so that it has more priority over things like toolbars.
-     */
-    weight: 100,
-    defaultType: 'gridcolumn',
-<span id='Ext-grid-header-Container-cfg-defaultWidth'>    /**
-</span>     * @cfg {Number} defaultWidth
-     * Width of the header if no width or flex is specified. Defaults to 100.
-     */
-    defaultWidth: 100,
-
-
-    sortAscText: 'Sort Ascending',
-    sortDescText: 'Sort Descending',
-    sortClearText: 'Clear Sort',
-    columnsText: 'Columns',
-
-    lastHeaderCls: Ext.baseCSSPrefix + 'column-header-last',
-    firstHeaderCls: Ext.baseCSSPrefix + 'column-header-first',
-    headerOpenCls: Ext.baseCSSPrefix + 'column-header-open',
-
-    // private; will probably be removed by 4.0
-    triStateSort: false,
-
-    ddLock: false,
-
-    dragging: false,
-
-<span id='Ext-grid-header-Container-property-isGroupHeader'>    /**
-</span>     * &lt;code&gt;true&lt;/code&gt; if this HeaderContainer is in fact a group header which contains sub headers.
-     * @type Boolean
-     * @property isGroupHeader
-     */
-
-<span id='Ext-grid-header-Container-cfg-sortable'>    /**
-</span>     * @cfg {Boolean} sortable
-     * Provides the default sortable state for all Headers within this HeaderContainer.
-     * Also turns on or off the menus in the HeaderContainer. Note that the menu is
-     * shared across every header and therefore turning it off will remove the menu
-     * items for every header.
-     */
-    sortable: true,
-    
-    initComponent: function() {
-        var me = this;
-        
-        me.headerCounter = 0;
-        me.plugins = me.plugins || [];
-
-        // TODO: Pass in configurations to turn on/off dynamic
-        //       resizing and disable resizing all together
-
-        // Only set up a Resizer and Reorderer for the topmost HeaderContainer.
-        // Nested Group Headers are themselves HeaderContainers
-        if (!me.isHeader) {
-            me.resizer   = Ext.create('Ext.grid.plugin.HeaderResizer');
-            me.reorderer = Ext.create('Ext.grid.plugin.HeaderReorderer');
-            if (!me.enableColumnResize) {
-                me.resizer.disable();
-            } 
-            if (!me.enableColumnMove) {
-                me.reorderer.disable();
-            }
-            me.plugins.push(me.reorderer, me.resizer);
-        }
-
-        // Base headers do not need a box layout
-        if (me.isHeader &amp;&amp; !me.items) {
-            me.layout = 'auto';
-        }
-        // HeaderContainer and Group header needs a gridcolumn layout.
-        else {
-            me.layout = {
-                type: 'gridcolumn',
-                availableSpaceOffset: me.availableSpaceOffset,
-                align: 'stretchmax',
-                resetStretch: true
-            };
-        }
-        me.defaults = me.defaults || {};
-        Ext.applyIf(me.defaults, {
-            width: me.defaultWidth,
-            triStateSort: me.triStateSort,
-            sortable: me.sortable
-        });
-        me.callParent();
-        me.addEvents(
-<span id='Ext-grid-header-Container-event-columnresize'>            /**
-</span>             * @event columnresize
-             * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers.
-             * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition
-             * @param {Number} width
-             */
-            'columnresize',
-
-<span id='Ext-grid-header-Container-event-headerclick'>            /**
-</span>             * @event headerclick
-             * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers.
-             * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition
-             * @param {Ext.EventObject} e
-             * @param {HTMLElement} t
-             */
-            'headerclick',
-
-<span id='Ext-grid-header-Container-event-headertriggerclick'>            /**
-</span>             * @event headertriggerclick
-             * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers.
-             * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition
-             * @param {Ext.EventObject} e
-             * @param {HTMLElement} t
-             */
-            'headertriggerclick',
-
-<span id='Ext-grid-header-Container-event-columnmove'>            /**
-</span>             * @event columnmove
-             * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers.
-             * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition
-             * @param {Number} fromIdx
-             * @param {Number} toIdx
-             */
-            'columnmove',
-<span id='Ext-grid-header-Container-event-columnhide'>            /**
-</span>             * @event columnhide
-             * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers.
-             * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition
-             */
-            'columnhide',
-<span id='Ext-grid-header-Container-event-columnshow'>            /**
-</span>             * @event columnshow
-             * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers.
-             * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition
-             */
-            'columnshow',
-<span id='Ext-grid-header-Container-event-sortchange'>            /**
-</span>             * @event sortchange
-             * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers.
-             * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition
-             * @param {String} direction
-             */
-            'sortchange',
-<span id='Ext-grid-header-Container-event-menucreate'>            /**
-</span>             * @event menucreate
-             * Fired immediately after the column header menu is created.
-             * @param {Ext.grid.header.Container} ct This instance
-             * @param {Ext.menu.Menu} menu The Menu that was created
-             */
-            'menucreate'
-        );
-    },
-
-    onDestroy: function() {
-        Ext.destroy(this.resizer, this.reorderer);
-        this.callParent();
-    },
-
-    // Invalidate column cache on add
-    // We cannot refresh the View on every add because this method is called
-    // when the HeaderDropZone moves Headers around, that will also refresh the view
-    onAdd: function(c) {
-        var me = this;
-        if (!c.headerId) {
-            c.headerId = 'h' + (++me.headerCounter);
-        }
-        me.callParent(arguments);
-        me.purgeCache();
-    },
-
-    // Invalidate column cache on remove
-    // We cannot refresh the View on every remove because this method is called
-    // when the HeaderDropZone moves Headers around, that will also refresh the view
-    onRemove: function(c) {
-        var me = this;
-        me.callParent(arguments);
-        me.purgeCache();
-    },
-
-    afterRender: function() {
-        this.callParent();
-        var store   = this.up('[store]').store,
-            sorters = store.sorters,
-            first   = sorters.first(),
-            hd;
-
-        if (first) {
-            hd = this.down('gridcolumn[dataIndex=' + first.property  +']');
-            if (hd) {
-                hd.setSortState(first.direction, false, true);
-            }
-        }
-    },
-
-    afterLayout: function() {
-        if (!this.isHeader) {
-            var me = this,
-                topHeaders = me.query('&gt;gridcolumn:not([hidden])'),
-                viewEl;
-
-            me.callParent(arguments);
-
-            if (topHeaders.length) {
-                topHeaders[0].el.radioCls(me.firstHeaderCls);
-                topHeaders[topHeaders.length - 1].el.radioCls(me.lastHeaderCls);
-            }
-        }
-    },
-
-    onHeaderShow: function(header) {
-        // Pass up to the GridSection
-        var me = this,
-            gridSection = me.ownerCt,
-            menu = me.getMenu(),
-            topItems, topItemsVisible,
-            colCheckItem,
-            itemToEnable,
-            len, i;
-
-        if (menu) {
-
-            colCheckItem = menu.down('menucheckitem[headerId=' + header.id + ']');
-            if (colCheckItem) {
-                colCheckItem.setChecked(true, true);
-            }
-
-            // There's more than one header visible, and we've disabled some checked items... re-enable them
-            topItems = menu.query('#columnItem&gt;menucheckitem[checked]');
-            topItemsVisible = topItems.length;
-            if ((me.getVisibleGridColumns().length &gt; 1) &amp;&amp; me.disabledMenuItems &amp;&amp; me.disabledMenuItems.length) {
-                if (topItemsVisible == 1) {
-                    Ext.Array.remove(me.disabledMenuItems, topItems[0]);
-                }
-                for (i = 0, len = me.disabledMenuItems.length; i &lt; len; i++) {
-                    itemToEnable = me.disabledMenuItems[i];
-                    if (!itemToEnable.isDestroyed) {
-                        itemToEnable[itemToEnable.menu ? 'enableCheckChange' : 'enable']();
-                    }
-                }
-                if (topItemsVisible == 1) {
-                    me.disabledMenuItems = topItems;
-                } else {
-                    me.disabledMenuItems = [];
-                }
-            }
-        }
-
-        // Only update the grid UI when we are notified about base level Header shows;
-        // Group header shows just cause a layout of the HeaderContainer
-        if (!header.isGroupHeader) {
-            if (me.view) {
-                me.view.onHeaderShow(me, header, true);
-            }
-            if (gridSection) {
-                gridSection.onHeaderShow(me, header);
-            }
-        }
-        me.fireEvent('columnshow', me, header);
-
-        // The header's own hide suppresses cascading layouts, so lay the headers out now
-        me.doLayout();
-    },
-
-    onHeaderHide: function(header, suppressLayout) {
-        // Pass up to the GridSection
-        var me = this,
-            gridSection = me.ownerCt,
-            menu = me.getMenu(),
-            colCheckItem;
-
-        if (menu) {
-
-            // If the header was hidden programmatically, sync the Menu state
-            colCheckItem = menu.down('menucheckitem[headerId=' + header.id + ']');
-            if (colCheckItem) {
-                colCheckItem.setChecked(false, true);
-            }
-            me.setDisabledItems();
-        }
-
-        // Only update the UI when we are notified about base level Header hides;
-        if (!header.isGroupHeader) {
-            if (me.view) {
-                me.view.onHeaderHide(me, header, true);
-            }
-            if (gridSection) {
-                gridSection.onHeaderHide(me, header);
-            }
-
-            // The header's own hide suppresses cascading layouts, so lay the headers out now
-            if (!suppressLayout) {
-                me.doLayout();
-            }
-        }
-        me.fireEvent('columnhide', me, header);
-    },
-
-    setDisabledItems: function(){
-        var me = this,
-            menu = me.getMenu(),
-            i = 0,
-            len,
-            itemsToDisable,
-            itemToDisable;
-
-        // Find what to disable. If only one top level item remaining checked, we have to disable stuff.
-        itemsToDisable = menu.query('#columnItem&gt;menucheckitem[checked]');
-        if ((itemsToDisable.length === 1)) {
-            if (!me.disabledMenuItems) {
-                me.disabledMenuItems = [];
-            }
-
-            // If down to only one column visible, also disable any descendant checkitems
-            if ((me.getVisibleGridColumns().length === 1) &amp;&amp; itemsToDisable[0].menu) {
-                itemsToDisable = itemsToDisable.concat(itemsToDisable[0].menu.query('menucheckitem[checked]'));
-            }
-
-            len = itemsToDisable.length;
-            // Disable any further unchecking at any level.
-            for (i = 0; i &lt; len; i++) {
-                itemToDisable = itemsToDisable[i];
-                if (!Ext.Array.contains(me.disabledMenuItems, itemToDisable)) {
-                    itemToDisable[itemToDisable.menu ? 'disableCheckChange' : 'disable']();
-                    me.disabledMenuItems.push(itemToDisable);
-                }
-            }
-        }
-    },
-
-<span id='Ext-grid-header-Container-method-tempLock'>    /**
-</span>     * Temporarily lock the headerCt. This makes it so that clicking on headers
-     * don't trigger actions like sorting or opening of the header menu. This is
-     * done because extraneous events may be fired on the headers after interacting
-     * with a drag drop operation.
-     * @private
-     */
-    tempLock: function() {
-        this.ddLock = true;
-        Ext.Function.defer(function() {
-            this.ddLock = false;
-        }, 200, this);
-    },
-
-    onHeaderResize: function(header, w, suppressFocus) {
-        this.tempLock();
-        if (this.view &amp;&amp; this.view.rendered) {
-            this.view.onHeaderResize(header, w, suppressFocus);
-        }
-        this.fireEvent('columnresize', this, header, w);
-    },
-
-    onHeaderClick: function(header, e, t) {
-        this.fireEvent(&quot;headerclick&quot;, this, header, e, t);
-    },
-
-    onHeaderTriggerClick: function(header, e, t) {
-        // generate and cache menu, provide ability to cancel/etc
-        if (this.fireEvent(&quot;headertriggerclick&quot;, this, header, e, t) !== false) {
-            this.showMenuBy(t, header);
-        }
-    },
-
-    showMenuBy: function(t, header) {
-        var menu = this.getMenu(),
-            ascItem  = menu.down('#ascItem'),
-            descItem = menu.down('#descItem'),
-            sortableMth;
-
-        menu.activeHeader = menu.ownerCt = header;
-        menu.setFloatParent(header);
-        // TODO: remove coupling to Header's titleContainer el
-        header.titleContainer.addCls(this.headerOpenCls);
-
-        // enable or disable asc &amp; desc menu items based on header being sortable
-        sortableMth = header.sortable ? 'enable' : 'disable';
-        if (ascItem) {
-            ascItem[sortableMth]();
-        }
-        if (descItem) {
-            descItem[sortableMth]();
-        }
-        menu.showBy(t);
-    },
-
-    // remove the trigger open class when the menu is hidden
-    onMenuDeactivate: function() {
-        var menu = this.getMenu();
-        // TODO: remove coupling to Header's titleContainer el
-        menu.activeHeader.titleContainer.removeCls(this.headerOpenCls);
-    },
-
-    moveHeader: function(fromIdx, toIdx) {
-
-        // An automatically expiring lock
-        this.tempLock();
-        this.onHeaderMoved(this.move(fromIdx, toIdx), fromIdx, toIdx);
-    },
-
-    purgeCache: function() {
-        var me = this;
-        // Delete column cache - column order has changed.
-        delete me.gridDataColumns;
-
-        // Menu changes when columns are moved. It will be recreated.
-        if (me.menu) {
-            me.menu.destroy();
-            delete me.menu;
-        }
-    },
-
-    onHeaderMoved: function(header, fromIdx, toIdx) {
-        var me = this,
-            gridSection = me.ownerCt;
-
-        if (gridSection) {
-            gridSection.onHeaderMove(me, header, fromIdx, toIdx);
-        }
-        me.fireEvent(&quot;columnmove&quot;, me, header, fromIdx, toIdx);
-    },
-
-<span id='Ext-grid-header-Container-method-getMenu'>    /**
-</span>     * Gets the menu (and will create it if it doesn't already exist)
-     * @private
-     */
-    getMenu: function() {
-        var me = this;
-
-        if (!me.menu) {
-            me.menu = Ext.create('Ext.menu.Menu', {
-                items: me.getMenuItems(),
-                listeners: {
-                    deactivate: me.onMenuDeactivate,
-                    scope: me
-                }
-            });
-            me.setDisabledItems();
-            me.fireEvent('menucreate', me, me.menu);
-        }
-        return me.menu;
-    },
-
-<span id='Ext-grid-header-Container-method-getMenuItems'>    /**
-</span>     * Returns an array of menu items to be placed into the shared menu
-     * across all headers in this header container.
-     * @returns {Array} menuItems
-     */
-    getMenuItems: function() {
-        var me = this,
-            menuItems = [{
-                itemId: 'columnItem',
-                text: me.columnsText,
-                cls: Ext.baseCSSPrefix + 'cols-icon',
-                menu: me.getColumnMenu(me)
-            }];
-
-        if (me.sortable) {
-            menuItems.unshift({
-                itemId: 'ascItem',
-                text: me.sortAscText,
-                cls: 'xg-hmenu-sort-asc',
-                handler: me.onSortAscClick,
-                scope: me
-            },{
-                itemId: 'descItem',
-                text: me.sortDescText,
-                cls: 'xg-hmenu-sort-desc',
-                handler: me.onSortDescClick,
-                scope: me
-            },'-');
-        }
-        return menuItems;
-    },
-
-    // sort asc when clicking on item in menu
-    onSortAscClick: function() {
-        var menu = this.getMenu(),
-            activeHeader = menu.activeHeader;
-
-        activeHeader.setSortState('ASC');
-    },
-
-    // sort desc when clicking on item in menu
-    onSortDescClick: function() {
-        var menu = this.getMenu(),
-            activeHeader = menu.activeHeader;
-
-        activeHeader.setSortState('DESC');
-    },
-
-<span id='Ext-grid-header-Container-method-getColumnMenu'>    /**
-</span>     * Returns an array of menu CheckItems corresponding to all immediate children of the passed Container which have been configured as hideable.
-     */
-    getColumnMenu: function(headerContainer) {
-        var menuItems = [],
-            i = 0,
-            item,
-            items = headerContainer.query('&gt;gridcolumn[hideable]'),
-            itemsLn = items.length,
-            menuItem;
-
-        for (; i &lt; itemsLn; i++) {
-            item = items[i];
-            menuItem = Ext.create('Ext.menu.CheckItem', {
-                text: item.text,
-                checked: !item.hidden,
-                hideOnClick: false,
-                headerId: item.id,
-                menu: item.isGroupHeader ? this.getColumnMenu(item) : undefined,
-                checkHandler: this.onColumnCheckChange,
-                scope: this
-            });
-            if (itemsLn === 1) {
-                menuItem.disabled = true;
-            }
-            menuItems.push(menuItem);
-
-            // If the header is ever destroyed - for instance by dragging out the last remaining sub header,
-            // then the associated menu item must also be destroyed.
-            item.on({
-                destroy: Ext.Function.bind(menuItem.destroy, menuItem)
-            });
-        }
-        return menuItems;
-    },
-
-    onColumnCheckChange: function(checkItem, checked) {
-        var header = Ext.getCmp(checkItem.headerId);
-        header[checked ? 'show' : 'hide']();
-    },
+ * {@img Ext.Container/Ext.Container.png Ext.Container component} 
+ * &lt;p&gt;The code below illustrates how to explicitly create a Container:&lt;pre&gt;&lt;code&gt;
+// explicitly create a Container
+Ext.create('Ext.container.Container', {
+    layout: {
+        type: 'hbox'
+    },
+    width: 400,
+    renderTo: Ext.getBody(),
+    border: 1,
+    style: {borderColor:'#000000', borderStyle:'solid', borderWidth:'1px'},
+    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'
+    }]
+});
+&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
+ *
+ * &lt;p&gt;&lt;u&gt;&lt;b&gt;Layout&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
+ * &lt;p&gt;Container classes delegate the rendering of child Components to a layout
+ * manager class which must be configured into the Container using the
+ * &lt;code&gt;&lt;b&gt;{@link #layout}&lt;/b&gt;&lt;/code&gt; configuration property.&lt;/p&gt;
+ * &lt;p&gt;When either specifying child &lt;code&gt;{@link #items}&lt;/code&gt; 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
+ * &lt;b&gt;&lt;code&gt;{@link #layout}&lt;/code&gt;&lt;/b&gt; 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 &lt;b&gt;does not apply any sizing&lt;/b&gt; at all.&lt;/p&gt;
+ * &lt;p&gt;A common mistake is when a developer neglects to specify a
+ * &lt;b&gt;&lt;code&gt;{@link #layout}&lt;/code&gt;&lt;/b&gt; (e.g. widgets like GridPanels or
+ * TreePanels are added to Containers for which no &lt;code&gt;&lt;b&gt;{@link #layout}&lt;/b&gt;&lt;/code&gt;
+ * 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.&lt;/p&gt;
+ * &lt;p&gt;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:&lt;pre&gt;&lt;code&gt;
+//  Create the GridPanel.
+var myNewGrid = new Ext.grid.Panel({
+    store: myStore,
+    headers: myHeaders,
+    title: 'Results', // the title becomes the title of the tab
+});
 
-<span id='Ext-grid-header-Container-method-getColumnsForTpl'>    /**
-</span>     * Get the columns used for generating a template via TableChunker.
-     * Returns an array of all columns and their
-     *  - dataIndex
-     *  - align
-     *  - width
-     *  - id
-     *  - columnId - used to create an identifying CSS class
-     *  - cls The tdCls configuration from the Column object
-     *  @private
-     */
-    getColumnsForTpl: function(flushCache) {
-        var cols    = [],
-            headers   = this.getGridColumns(flushCache),
-            headersLn = headers.length,
+myTabPanel.add(myNewGrid); // {@link Ext.tab.Panel} implicitly uses {@link Ext.layout.container.Card Card}
+myTabPanel.{@link Ext.tab.Panel#setActiveTab setActiveTab}(myNewGrid);
+ * &lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;
+ * &lt;p&gt;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.
+ * &lt;p&gt;&lt;b&gt;&lt;u&gt;Overnesting is a common problem&lt;/u&gt;&lt;/b&gt;.
+ * An example of overnesting occurs when a GridPanel is added to a TabPanel
+ * by wrapping the GridPanel &lt;i&gt;inside&lt;/i&gt; a wrapping Panel (that has no
+ * &lt;code&gt;&lt;b&gt;{@link #layout}&lt;/b&gt;&lt;/code&gt; specified) and then add that wrapping Panel
+ * to the TabPanel. The point to realize is that a GridPanel &lt;b&gt;is&lt;/b&gt; a
+ * Component which can be added directly to a Container. If the wrapping Panel
+ * has no &lt;code&gt;&lt;b&gt;{@link #layout}&lt;/b&gt;&lt;/code&gt; configuration, then the overnested
+ * GridPanel will not be sized as expected.&lt;p&gt;
+ *
+ * &lt;p&gt;&lt;u&gt;&lt;b&gt;Adding via remote configuration&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
+ *
+ * &lt;p&gt;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:
+ * &lt;/p&gt;&lt;pre&gt;&lt;code&gt;
+// 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(&quot;Grid create failed&quot;, &quot;Server communication failure&quot;);
+    }
+});
+&lt;/code&gt;&lt;/pre&gt;
+ * &lt;p&gt;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:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;
+{
+    &quot;xtype&quot;: 'grid',
+    &quot;title&quot;: 'Invoice Report',
+    &quot;store&quot;: {
+        &quot;model&quot;: 'Invoice',
+        &quot;proxy&quot;: {
+            &quot;type&quot;: 'ajax',
+            &quot;url&quot;: 'get-invoice-data.php',
+            &quot;reader&quot;: {
+                &quot;type&quot;: 'json'
+                &quot;record&quot;: 'transaction',
+                &quot;idProperty&quot;: 'id',
+                &quot;totalRecords&quot;: 'total'
+            })
+        },
+        &quot;autoLoad&quot;: {
+            &quot;params&quot;: {
+                &quot;startDate&quot;: '01/01/2008',
+                &quot;endDate&quot;: '01/31/2008'
+            }
+        }
+    },
+    &quot;headers&quot;: [
+        {&quot;header&quot;: &quot;Customer&quot;, &quot;width&quot;: 250, &quot;dataIndex&quot;: 'customer', &quot;sortable&quot;: true},
+        {&quot;header&quot;: &quot;Invoice Number&quot;, &quot;width&quot;: 120, &quot;dataIndex&quot;: 'invNo', &quot;sortable&quot;: true},
+        {&quot;header&quot;: &quot;Invoice Date&quot;, &quot;width&quot;: 100, &quot;dataIndex&quot;: 'date', &quot;renderer&quot;: Ext.util.Format.dateRenderer('M d, y'), &quot;sortable&quot;: true},
+        {&quot;header&quot;: &quot;Value&quot;, &quot;width&quot;: 120, &quot;dataIndex&quot;: 'value', &quot;renderer&quot;: 'usMoney', &quot;sortable&quot;: true}
+    ]
+}
+&lt;/code&gt;&lt;/pre&gt;
+ * &lt;p&gt;When the above code fragment is passed through the &lt;code&gt;eval&lt;/code&gt; 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. &lt;b&gt;Be sure that the Container is configured with a layout which sizes and positions the child items to your requirements.&lt;/b&gt;&lt;/p&gt;
+ * &lt;p&gt;Note: since the code above is &lt;i&gt;generated&lt;/i&gt; by a server script, the &lt;code&gt;autoLoad&lt;/code&gt; 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.&lt;/p&gt;
+ */
+Ext.define('Ext.container.Container', {
+    extend: 'Ext.container.AbstractContainer',
+    alias: 'widget.container',
+    alternateClassName: 'Ext.Container',
+
+<span id='Ext-container-Container-method-getChildByElement'>    /**
+</span>     * 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,
-            header;
-
-        for (; i &lt; headersLn; i++) {
-            header = headers[i];
-            cols.push({
-                dataIndex: header.dataIndex,
-                align: header.align,
-                width: header.hidden ? 0 : header.getDesiredWidth(),
-                id: header.id,
-                cls: header.tdCls,
-                columnId: header.getItemId()
-            });
-        }
-        return cols;
-    },
-
-<span id='Ext-grid-header-Container-method-getColumnCount'>    /**
-</span>     * Returns the number of &lt;b&gt;grid columns&lt;/b&gt; descended from this HeaderContainer.
-     * Group Columns are HeaderContainers. All grid columns are returned, including hidden ones.
-     */
-    getColumnCount: function() {
-        return this.getGridColumns().length;
-    },
-
-<span id='Ext-grid-header-Container-method-getFullWidth'>    /**
-</span>     * Gets the full width of all columns that are visible.
-     */
-    getFullWidth: function(flushCache) {
-        var fullWidth = 0,
-            headers     = this.getVisibleGridColumns(flushCache),
-            headersLn   = headers.length,
-            i         = 0;
-
-        for (; i &lt; headersLn; i++) {
-            if (!isNaN(headers[i].width)) {
-                // use headers getDesiredWidth if its there
-                if (headers[i].getDesiredWidth) {
-                    fullWidth += headers[i].getDesiredWidth();
-                // if injected a diff cmp use getWidth
-                } else {
-                    fullWidth += headers[i].getWidth();
-                }
-            }
-        }
-        return fullWidth;
-    },
-
-    // invoked internally by a header when not using triStateSorting
-    clearOtherSortStates: function(activeHeader) {
-        var headers   = this.getGridColumns(),
-            headersLn = headers.length,
-            i         = 0,
-            oldSortState;
-
-        for (; i &lt; headersLn; i++) {
-            if (headers[i] !== activeHeader) {
-                oldSortState = headers[i].sortState;
-                // unset the sortstate and dont recurse
-                headers[i].setSortState(null, true);
-                //if (!silent &amp;&amp; oldSortState !== null) {
-                //    this.fireEvent('sortchange', this, headers[i], null);
-                //}
-            }
-        }
-    },
-
-<span id='Ext-grid-header-Container-method-getVisibleGridColumns'>    /**
-</span>     * Returns an array of the &lt;b&gt;visible&lt;b&gt; columns in the grid. This goes down to the lowest column header
-     * level, and does not return &lt;i&gt;grouped&lt;/i&gt; headers which contain sub headers.
-     * @param {Boolean} refreshCache If omitted, the cached set of columns will be returned. Pass true to refresh the cache.
-     * @returns {Array}
-     */
-    getVisibleGridColumns: function(refreshCache) {
-        return Ext.ComponentQuery.query(':not([hidden])', this.getGridColumns(refreshCache));
-    },
-
-<span id='Ext-grid-header-Container-method-getGridColumns'>    /**
-</span>     * Returns an array of all columns which map to Store fields. This goes down to the lowest column header
-     * level, and does not return &lt;i&gt;grouped&lt;/i&gt; headers which contain sub headers.
-     * @param {Boolean} refreshCache If omitted, the cached set of columns will be returned. Pass true to refresh the cache.
-     * @returns {Array}
-     */
-    getGridColumns: function(refreshCache) {
-        var me = this,
-            result = refreshCache ? null : me.gridDataColumns;
-
-        // Not already got the column cache, so collect the base columns
-        if (!result) {
-            me.gridDataColumns = result = [];
-            me.cascade(function(c) {
-                if ((c !== me) &amp;&amp; !c.isGroupHeader) {
-                    result.push(c);
-                }
-            });
-        }
-
-        return result;
-    },
-
-<span id='Ext-grid-header-Container-method-getHeaderIndex'>    /**
-</span>     * Get the index of a leaf level header regardless of what the nesting
-     * structure is.
-     */
-    getHeaderIndex: function(header) {
-        var columns = this.getGridColumns();
-        return Ext.Array.indexOf(columns, header);
-    },
+            it = this.items.items,
+            ln = it.length;
 
-<span id='Ext-grid-header-Container-method-getHeaderAtIndex'>    /**
-</span>     * Get a leaf level header by index regardless of what the nesting
-     * structure is.
-     */
-    getHeaderAtIndex: function(index) {
-        var columns = this.getGridColumns();
-        return columns[index];
-    },
-
-<span id='Ext-grid-header-Container-method-prepareData'>    /**
-</span>     * Maps the record data to base it on the header id's.
-     * This correlates to the markup/template generated by
-     * TableChunker.
-     */
-    prepareData: function(data, rowIdx, record, view, panel) {
-        var obj       = {},
-            headers   = this.gridDataColumns || this.getGridColumns(),
-            headersLn = headers.length,
-            colIdx    = 0,
-            header,
-            headerId,
-            renderer,
-            value,
-            metaData,
-            store = panel.store;
-
-        for (; colIdx &lt; headersLn; colIdx++) {
-            metaData = {
-                tdCls: '',
-                style: ''
-            };
-            header = headers[colIdx];
-            headerId = header.id;
-            renderer = header.renderer;
-            value = data[header.dataIndex];
-
-            // When specifying a renderer as a string, it always resolves
-            // to Ext.util.Format
-            if (typeof renderer === &quot;string&quot;) {
-                header.renderer = renderer = Ext.util.Format[renderer];
-            }
-            
-            if (typeof renderer === &quot;function&quot;) {
-                value = renderer.call(
-                    header.scope || this.ownerCt,
-                    value,
-                    // metadata per cell passing an obj by reference so that
-                    // it can be manipulated inside the renderer
-                    metaData,
-                    record,
-                    rowIdx,
-                    colIdx,
-                    store,
-                    view
-                );
+        el = Ext.getDom(el);
+        for (; i &lt; ln; i++) {
+            item = it[i];
+            itemEl = item.getEl();
+            if ((itemEl.dom === el) || itemEl.contains(el)) {
+                return item;
             }
-
-            // &lt;debug&gt;
-            if (metaData.css) {
-                // This warning attribute is used by the compat layer
-                obj.cssWarning = true;
-                metaData.tdCls = metaData.css;
-                delete metaData.css;
-            }
-            // &lt;/debug&gt;
-            
-            obj[headerId+'-modified'] = record.modified[header.dataIndex] ? Ext.baseCSSPrefix + 'grid-dirty-cell' : Ext.baseCSSPrefix + 'grid-clean-cell';
-            obj[headerId+'-tdCls'] = metaData.tdCls;
-            obj[headerId+'-tdAttr'] = metaData.tdAttr;
-            obj[headerId+'-style'] = metaData.style;
-            if (value === undefined || value === null || value === '') {
-                value = '&amp;#160;';
-            }
-            obj[headerId] = value;
-        }
-        return obj;
-    },
-
-    expandToFit: function(header) {
-        if (this.view) {
-            this.view.expandToFit(header);
         }
+        return null;
     }
 });
 </pre>