The source code

    /*!
     * Ext JS Library 3.4.0
     * Copyright(c) 2006-2011 Sencha Inc.
     * licensing@sencha.com
     * http://www.sencha.com/license
     */
    /**
     * @class Ext.Container
     * @extends Ext.BoxComponent
     * Base class for any {@link Ext.BoxComponent} that may contain other Components. Containers handle the
     * basic behavior of containing items, namely adding, inserting and removing items.
     *
     * The most commonly used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}.
     * If you do not need the capabilities offered by the aforementioned classes you can create a lightweight
     * Container to be encapsulated by an HTML element to your specifications by using the
     * {@link Ext.Component#autoEl autoEl} config option. This is a useful technique when creating
     * embedded {@link Ext.layout.ColumnLayout column} layouts inside {@link Ext.form.FormPanel FormPanels}
     * for example.
     *
     * The code below illustrates both how to explicitly create a Container, and how to implicitly
     * create one using the 'container' xtype:
    // explicitly create a Container
    var embeddedColumns = new Ext.Container({
        autoEl: 'div',  // This is the default
        layout: 'column',
        defaults: {
            // implicitly create Container by specifying xtype
            xtype: 'container',
            autoEl: 'div', // This is the default.
            layout: 'form',
            columnWidth: 0.5,
            style: {
                padding: '10px'
            }
        },
    //  The two items below will be Ext.Containers, each encapsulated by a <DIV> element.
        items: [{
            items: {
                xtype: 'datefield',
                name: 'startDate',
                fieldLabel: 'Start date'
            }
        }, {
            items: {
                xtype: 'datefield',
                name: 'endDate',
                fieldLabel: 'End date'
            }
        }]
    });
     *
     * Layout
     * Container classes delegate the rendering of child Components to a layout
     * manager class which must be configured into the Container using the
     * {@link #layout} configuration property.
     * When either specifying child {@link #items} of a Container,
     * or dynamically {@link #add adding} Components to a Container, remember to
     * consider how you wish the Container to arrange those child elements, and
     * whether those child elements need to be sized using one of Ext's built-in
     * {@link #layout} schemes. By default, Containers use the
     * {@link Ext.layout.ContainerLayout ContainerLayout} scheme which only
     * renders child components, appending them one after the other inside the
     * Container, and does not apply any sizing at all.
     * A common mistake is when a developer neglects to specify a
     * {@link #layout} (e.g. widgets like GridPanels or
     * TreePanels are added to Containers for which no {@link #layout}
     * has been specified). If a Container is left to use the default
     * {@link Ext.layout.ContainerLayout ContainerLayout} scheme, none of its
     * child components will be resized, or changed in any way when the Container
     * is resized.
     * Certain layout managers allow dynamic addition of child components.
     * Those that do include {@link Ext.layout.CardLayout},
     * {@link Ext.layout.AnchorLayout}, {@link Ext.layout.FormLayout}, and
     * {@link Ext.layout.TableLayout}. For example:
    //  Create the GridPanel.
    var myNewGrid = new Ext.grid.GridPanel({
        store: myStore,
        columns: myColumnModel,
        title: 'Results', // the title becomes the title of the tab
    });

    myTabPanel.add(myNewGrid); // {@link Ext.TabPanel} implicitly uses {@link Ext.layout.CardLayout CardLayout}
    myTabPanel.{@link Ext.TabPanel#setActiveTab setActiveTab}(myNewGrid);
     *
     * The example above adds a newly created GridPanel to a TabPanel. Note that
     * a TabPanel uses {@link Ext.layout.CardLayout} as its layout manager which
     * means all its child items are sized to {@link Ext.layout.FitLayout fit}
     * exactly into its client area.
     * Overnesting is a common problem.
     * An example of overnesting occurs when a GridPanel is added to a TabPanel
     * by wrapping the GridPanel inside a wrapping Panel (that has no
     * {@link #layout} specified) and then add that wrapping Panel
     * to the TabPanel. The point to realize is that a GridPanel is a
     * Component which can be added directly to a Container. If the wrapping Panel
     * has no {@link #layout} configuration, then the overnested
     * GridPanel will not be sized as expected.
     *
     * Adding via remote configuration
     *
     * A server side script can be used to add Components which are generated dynamically on the server.
     * An example of adding a GridPanel to a TabPanel where the GridPanel is generated by the server
     * based on certain parameters:
     *
    // execute an Ajax request to invoke server side script:
    Ext.Ajax.request({
        url: 'gen-invoice-grid.php',
        // send additional parameters to instruct server script
        params: {
            startDate: Ext.getCmp('start-date').getValue(),
            endDate: Ext.getCmp('end-date').getValue()
        },
        // process the response object to add it to the TabPanel:
        success: function(xhr) {
            var newComponent = eval(xhr.responseText); // see discussion below
            myTabPanel.add(newComponent); // add the component to the TabPanel
            myTabPanel.setActiveTab(newComponent);
        },
        failure: function() {
            Ext.Msg.alert("Grid create failed", "Server communication failure");
        }
    });

     * The server script needs to return an executable Javascript statement which, when processed
     * using eval(), will return either a config object with an {@link Ext.Component#xtype xtype},
     * or an instantiated Component. The server might return this for example:
    (function() {
        function formatDate(value){
            return value ? value.dateFormat('M d, Y') : '';
        };

        var store = new Ext.data.Store({
            url: 'get-invoice-data.php',
            baseParams: {
                startDate: '01/01/2008',
                endDate: '01/31/2008'
            },
            reader: new Ext.data.JsonReader({
                record: 'transaction',
                idProperty: 'id',
                totalRecords: 'total'
            }, [
               'customer',
               'invNo',
               {name: 'date', type: 'date', dateFormat: 'm/d/Y'},
               {name: 'value', type: 'float'}
            ])
        });

        var grid = new Ext.grid.GridPanel({
            title: 'Invoice Report',
            bbar: new Ext.PagingToolbar(store),
            store: store,
            columns: [
                {header: "Customer", width: 250, dataIndex: 'customer', sortable: true},
                {header: "Invoice Number", width: 120, dataIndex: 'invNo', sortable: true},
                {header: "Invoice Date", width: 100, dataIndex: 'date', renderer: formatDate, sortable: true},
                {header: "Value", width: 120, dataIndex: 'value', renderer: 'usMoney', sortable: true}
            ],
        });
        store.load();
        return grid;  // return instantiated component
    })();

     * When the above code fragment is passed through the eval function in the success handler
     * of the Ajax request, the code is executed by the Javascript processor, and the anonymous function
     * runs, and returns the instantiated grid component.
     * Note: since the code above is generated by a server script, the baseParams for
     * the Store, the metadata to allow generation of the Record layout, and the ColumnModel
     * can all be generated into the code since these are all known on the server.
     *
     * @xtype container
     */
    Ext.Container = Ext.extend(Ext.BoxComponent, {
        /**
         * @cfg {Boolean} monitorResize
         * True to automatically monitor window resize events to handle anything that is sensitive to the current size
         * of the viewport.  This value is typically managed by the chosen {@link #layout} and should not need
         * to be set manually.
         */
        /**
         * @cfg {String/Object} layout
         * *Important: In order for child items to be correctly sized and
         * positioned, typically a layout manager must be specified through
         * the layout configuration option.
         *
    The sizing and positioning of child {@link items} is the responsibility of
         * the Container's layout manager which creates and manages the type of layout
         * you have in mind.  For example:
    new Ext.Window({
        width:300, height: 300,
        layout: 'fit', // explicitly set layout manager: override the default (layout:'auto')
        items: [{
            title: 'Panel inside a Window'
        }]
    }).show();
         *
         * If the {@link #layout} configuration is not explicitly specified for
         * a general purpose container (e.g. Container or Panel) the
         * {@link Ext.layout.ContainerLayout default layout manager} will be used
         * which does nothing but render child components sequentially into the
         * Container (no sizing or positioning will be performed in this situation).
         * Some container classes implicitly specify a default layout
         * (e.g. FormPanel specifies layout:'form'). Other specific
         * purpose classes internally specify/manage their internal layout (e.g.
         * GridPanel, TabPanel, TreePanel, Toolbar, Menu, etc.).
         *
    layout may be specified as either as an Object or
         * as a String:
         *
         * Specify as an Object
         *
         * Example usage:

    layout: {
        type: 'vbox',
        padding: '5',
        align: 'left'
    }

         *
         * 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:
         *
         * {@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}
         *
         *
         * Layout specific configuration properties
         *
    Additional layout specific configuration properties may also be
         * specified. For complete details regarding the valid config options for
         * each layout type, see the layout class corresponding to the type
         * specified.
         *
         *
         *
         * Specify as a String
         *
         * Example usage:

    layout: 'vbox',
    layoutConfig: {
        padding: '5',
        align: 'left'
    }

         * 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.
         *
         */
        /**
         * @cfg {Object} layoutConfig
         * This is a config object containing properties specific to the chosen
         * {@link #layout} if {@link #layout}
         * has been specified as a string.
         */
        /**
         * @cfg {Boolean/Number} bufferResize
         * When set to true (50 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer
         * the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers
         * with a large quantity of sub-components for which frequent layout calls would be expensive. Defaults to 50.
         */
        bufferResize: 50,

        /**
         * @cfg {String/Number} activeItem
         * A string component id or the numeric index of the component that should be initially activated within the
         * container's layout on render.  For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first
         * item in the container's collection).  activeItem only applies to layout styles that can display
         * items one at a time (like {@link Ext.layout.AccordionLayout}, {@link Ext.layout.CardLayout} and
         * {@link Ext.layout.FitLayout}).  Related to {@link Ext.layout.ContainerLayout#activeItem}.
         */
        /**
         * @cfg {Object/Array} items
         * ** IMPORTANT: be sure to {@link #layout specify a layout} if needed ! **
         * A single item, or an array of child Components to be added to this container,
         * for example:
         *
    // specifying a single item
    items: {...},
    layout: 'fit',    // specify a layout!

    // specifying multiple items
    items: [{...}, {...}],
    layout: 'anchor', // specify a layout!
         *
         * Each item may be:
         *
         * any type of object based on {@link Ext.Component}
         * a fully instanciated object or
         * an object literal that:
         *
         * has a specified {@link Ext.Component#xtype xtype}
         * the {@link Ext.Component#xtype} specified is associated with the Component
         * desired and should be chosen from one of the available xtypes as listed
         * in {@link Ext.Component}.
         * If an {@link Ext.Component#xtype xtype} is not explicitly
         * specified, the {@link #defaultType} for that Container is used.
         * will be "lazily instanciated", avoiding the overhead of constructing a fully
         * instanciated Component object
         *
         * Notes:
         *
         * Ext uses lazy rendering. Child Components will only be rendered
         * should it become necessary. Items are automatically laid out when they are first
         * shown (no sizing is done while hidden), or in response to a {@link #doLayout} call.
         * Do not specify {@link Ext.Panel#contentEl contentEl}/
         * {@link Ext.Panel#html html} with items.
         *
         */
        /**
         * @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
    },
    items: [
        {
            xtype: 'panel',   // defaults do not have precedence over
            id: 'panel1',     // options in config objects, so the defaults
            autoScroll: false // will not be applied here, panel1 will be autoScroll:false
        },
        new Ext.Panel({       // defaults do have precedence over options
            id: 'panel2',     // options in components, so the defaults
            autoScroll: false // will be applied here, panel2 will be autoScroll:true.
        })
    ]
         *
         */

        /** @cfg {Boolean} autoDestroy
         * If true the container will automatically destroy any contained component that is removed from it, else
         * destruction must be handled manually (defaults to true).
         */
        autoDestroy : true,

        /** @cfg {Boolean} forceLayout
         * If true the container will force a layout initially even if hidden or collapsed. This option
         * is useful for forcing forms to render in collapsed or hidden containers. (defaults to false).
         */
        forceLayout: false,

        /** @cfg {Boolean} hideBorders
         * True to hide the borders of each contained component, false to defer to the component's existing
         * border settings (defaults to false).
         */
        /** @cfg {String} defaultType
         * The default {@link Ext.Component xtype} of child Components to create in this Container when
         * a child item is specified as a raw configuration object, rather than as an instantiated Component.
         * Defaults to 'panel', except {@link Ext.menu.Menu} which defaults to 'menuitem',
         * and {@link Ext.Toolbar} and {@link Ext.ButtonGroup} which default to 'button'.
         */
        defaultType : 'panel',

        /** @cfg {String} resizeEvent
         * The event to listen to for resizing in layouts. Defaults to 'resize'.
         */
        resizeEvent: 'resize',

        /**
         * @cfg {Array} bubbleEvents
         * An array of events that, when fired, should be bubbled to any parent container.
         * See {@link Ext.util.Observable#enableBubble}.
         * Defaults to ['add', 'remove'].
         */
        bubbleEvents: ['add', 'remove'],

        // private
        initComponent : function(){
            Ext.Container.superclass.initComponent.call(this);

            this.addEvents(
                /**
                 * @event afterlayout
                 * Fires when the components in this container are arranged by the associated layout manager.
                 * @param {Ext.Container} this
                 * @param {ContainerLayout} layout The ContainerLayout implementation for this container
                 */
                'afterlayout',
                /**
                 * @event beforeadd
                 * Fires before any {@link Ext.Component} is added or inserted into the container.
                 * A handler can return false to cancel the add.
                 * @param {Ext.Container} this
                 * @param {Ext.Component} component The component being added
                 * @param {Number} index The index at which the component will be added to the container's items collection
                 */
                'beforeadd',
                /**
                 * @event beforeremove
                 * Fires before any {@link Ext.Component} is removed from the container.  A handler can return
                 * false to cancel the remove.
                 * @param {Ext.Container} this
                 * @param {Ext.Component} component The component being removed
                 */
                'beforeremove',
                /**
                 * @event add
                 * @bubbles
                 * Fires after any {@link Ext.Component} is added or inserted into the container.
                 * @param {Ext.Container} this
                 * @param {Ext.Component} component The component that was added
                 * @param {Number} index The index at which the component was added to the container's items collection
                 */
                'add',
                /**
                 * @event remove
                 * @bubbles
                 * Fires after any {@link Ext.Component} is removed from the container.
                 * @param {Ext.Container} this
                 * @param {Ext.Component} component The component that was removed
                 */
                'remove'
            );

            /**
             * The collection of components in this container as a {@link Ext.util.MixedCollection}
             * @type MixedCollection
             * @property items
             */
            var items = this.items;
            if(items){
                delete this.items;
                this.add(items);
            }
        },

        // private
        initItems : function(){
            if(!this.items){
                this.items = new Ext.util.MixedCollection(false, this.getComponentId);
                this.getLayout(); // initialize the layout
            }
        },

        // private
        setLayout : function(layout){
            if(this.layout && this.layout != layout){
                this.layout.setContainer(null);
            }
            this.layout = layout;
            this.initItems();
            layout.setContainer(this);
        },

        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 a CardLayout, the active item set
            if(this.activeItem !== undefined && this.layout.setActiveItem){
                var item = this.activeItem;
                delete this.activeItem;
                this.layout.setActiveItem(item);
            }

            // If we have no ownerCt, render and size all children
            if(!this.ownerCt){
                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]);
            }
        },

        /**
         * Returns the Element to be used to contain the child Components of this Container.
         * An implementation is provided which returns the Container's {@link #getEl Element}, but
         * if there is a more complex structure to a Container, this may be overridden to return
         * the element into which the {@link #layout layout} renders child Components.
         * @return {Ext.Element} The Element to render child Components into.
         */
        getLayoutTarget : function(){
            return this.el;
        },

        // private - used as the key lookup function for the items collection
        getComponentId : function(comp){
            return comp.getItemId();
        },

        /**
         * Adds {@link Ext.Component Component}(s) to this Container.
         *
    Description :
         *
         * Fires the {@link #beforeadd} event before adding
         * The Container's {@link #defaults default config values} will be applied
         * accordingly (see {@link #defaults} for details).
         * Fires the {@link #add} event after the component has been added.
         *
         *
    Notes :
         *
         * 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
         * once. For example:
    var tb = new {@link Ext.Toolbar}();
    tb.render(document.body);  // toolbar is rendered
    tb.add({text:'Button 1'}); // add multiple items ({@link #defaultType} for {@link Ext.Toolbar Toolbar} is 'button')
    tb.add({text:'Button 2'});
    tb.{@link #doLayout}();             // refresh the layout
         *
         * Warning: Containers directly managed by the BorderLayout layout manager
         * may not be removed or added.  See the Notes for {@link Ext.layout.BorderLayout BorderLayout}
         * for more details.
         *
         * @param {...Object/Array} component
         * Either one or more Components to add or an Array of Components to add.  See
         * {@link #items} for additional information.
         * @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){
                    result.push(this.add(c));
                }, this);
                return result;
            }
            var c = this.lookupComponent(this.applyDefaults(comp));
            var index = this.items.length;
            if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){
                this.items.add(c);
                // *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
         * Component has been inserted.
         * @param {Number} index The index at which the Component will be inserted
         * into the Container's items collection
         * @param {Ext.Component} component The child Component to insert.

         * Ext uses lazy rendering, and will only render the inserted Component should
         * it become necessary.

         * A Component config object may be passed in order to avoid the overhead of
         * constructing a real Component object if lazy rendering might mean that the
         * inserted Component will not be rendered immediately. To take advantage of
         * this 'lazy instantiation', set the {@link Ext.Component#xtype} config
         * property to the registered type of the Component wanted.

         * For a list of all available xtypes, see {@link Ext.Component}.
         * @return {Ext.Component} component The Component (or config object) that was
         * inserted with the Container's default config values applied.
         */
        insert : function(index, comp) {
            var args   = arguments,
                length = args.length,
                result = [],
                i, c;

            this.initItems();

            if (length > 2) {
                for (i = length - 1; i >= 1; --i) {
                    result.push(this.insert(index, args[i]));
                }
                return result;
            }

            c = this.lookupComponent(this.applyDefaults(comp));
            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.onAdded(this, index);
                this.onAdd(c);
                this.fireEvent('add', this, c, index);
            }

            return c;
        },

        // private
        applyDefaults : function(c){
            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, d);
                }else if(!c.events){
                    Ext.applyIf(c.isAction ? c.initialConfig : c, d);
                }else{
                    Ext.apply(c, d);
                }
            }
            return c;
        },

        // private
        onBeforeAdd : function(item){
            if(item.ownerCt){
                item.ownerCt.remove(item, false);
            }
            if(this.hideBorders === true){
                item.border = (item.border === true);
            }
        },

        /**
         * Removes a component from this container.  Fires the {@link #beforeremove} event before removing, then fires
         * the {@link #remove} event after the component has been removed.
         * @param {Component/String} component The component reference or id to remove.
         * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function.
         * Defaults to the value of this Container's {@link #autoDestroy} config.
         * @return {Ext.Component} component The Component that was removed.
         */
        remove : function(comp, autoDestroy){
            this.initItems();
            var c = this.getComponent(comp);
            if(c && this.fireEvent('beforeremove', this, c) !== false){
                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.
         * Defaults to the value of this Container's {@link #autoDestroy} config.
         * @return {Array} Array of the destroyed components
         */
        removeAll: function(autoDestroy){
            this.initItems();
            var item, rem = [], items = [];
            this.items.each(function(i){
                rem.push(i);
            });
            for (var i = 0, len = rem.length; i < len; ++i){
                item = rem[i];
                this.remove(item, autoDestroy);
                if(item.ownerCt !== this){
                    items.push(item);
                }
            }
            return items;
        },

        /**
         * Examines this container's {@link #items} property
         * 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}
         * or {@link Ext.Component#id id} 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}.
         * @return Ext.Component The component (if found).
         */
        getComponent : function(comp){
            if(Ext.isObject(comp)){
                comp = comp.getItemId();
            }
            return this.items.get(comp);
        },

        // private
        lookupComponent : function(comp){
            if(Ext.isString(comp)){
                return Ext.ComponentMgr.get(comp);
            }else if(!comp.events){
                return this.createComponent(comp);
            }
            return comp;
        },

        // private
        createComponent : function(config, 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");
        },

        /**
         * Force this container's layout to be recalculated. A call to this function is required after adding a new component
         * to an already rendered container, or possibly after changing sizing/position properties of child components.
         * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto
         * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer)
         * @param {Boolean} force (optional) True to force a layout to occur, even if the item is hidden.
         * @return {Ext.Container} this
         */

        doLayout : function(shallow, force){
            var rendered = this.rendered,
                forceLayout = force || this.forceLayout;

            if(this.collapsed || !this.canLayout()){
                this.deferLayout = this.deferLayout || !shallow;
                if(!forceLayout){
                    return;
                }
                shallow = shallow && !this.deferLayout;
            } else {
                delete this.deferLayout;
            }
            if(rendered && this.layout){
                this.layout.layout();
            }
            if(shallow !== true && this.items){
                var cs = this.items.items;
                for(var i = 0, len = cs.length; i < len; i++){
                    var c = cs[i];
                    if(c.doLayout){
                        c.doLayout(false, forceLayout);
                    }
                }
            }
            if(rendered){
                this.onLayout(shallow, forceLayout);
            }
            // Initial layout completed
            this.hasLayout = true;
            delete this.forceLayout;
        },

        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 we were sized during the time we were hidden, layout.
            if(Ext.isDefined(this.deferLayout)){
                delete this.deferLayout;
                this.doLayout(true);
            }
        },

        /**
         * Returns the layout currently in use by the container.  If the container does not currently have a layout
         * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout.
         * @return {ContainerLayout} layout The container's layout
         */
        getLayout : function(){
            if(!this.layout){
                var layout = new Ext.layout.AutoLayout(this.layoutConfig);
                this.setLayout(layout);
            }
            return this.layout;
        },

        // private
        beforeDestroy : function(){
            var c;
            if(this.items){
                while(c = this.items.first()){
                    this.doRemove(c, true);
                }
            }
            if(this.monitorResize){
                Ext.EventManager.removeResizeListener(this.doLayout, this);
            }
            Ext.destroy(this.layout);
            Ext.Container.superclass.beforeDestroy.call(this);
        },

        /**
         * Cascades down the component/container heirarchy from this component (called first), calling the specified function with
         * each component. The scope (this) of
         * function call will be the scope provided or the current component. The arguments to the function
         * will be the args provided or the current component. If the function returns false at any point,
         * the cascade is stopped on that branch.
         * @param {Function} fn The function to call
         * @param {Object} scope (optional) The scope of the function (defaults to current component)
         * @param {Array} args (optional) The args to call the function with (defaults to passing the current component)
         * @return {Ext.Container} this
         */
        cascade : function(fn, scope, args){
            if(fn.apply(scope || this, args || [this]) !== false){
                if(this.items){
                    var cs = this.items.items;
                    for(var i = 0, len = cs.length; i < len; i++){
                        if(cs[i].cascade){
                            cs[i].cascade(fn, scope, args);
                        }else{
                            fn.apply(scope || cs[i], args || [cs[i]]);
                        }
                    }
                }
            }
            return this;
        },

        /**
         * Find a component under this container at any level by id
         * @param {String} id
         * @deprecated Fairly useless method, since you can just use Ext.getCmp. Should be removed for 4.0
         * If you need to test if an id belongs to a container, you can use getCmp and findParent*.
         * @return Ext.Component
         */
        findById : function(id){
            var m = null,
                ct = this;
            this.cascade(function(c){
                if(ct != c && c.id === id){
                    m = c;
                    return false;
                }
            });
            return m;
        },

        /**
         * Find a component under this container at any level by xtype or class
         * @param {String/Class} xtype The xtype string for a component, or the class of the component directly
         * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is
         * the default), or true to check whether this Component is directly of the specified xtype.
         * @return {Array} Array of Ext.Components
         */
        findByType : function(xtype, shallow){
            return this.findBy(function(c){
                return c.isXType(xtype, shallow);
            });
        },

        /**
         * Find a component under this container at any level by property
         * @param {String} prop
         * @param {String} value
         * @return {Array} Array of Ext.Components
         */
        find : function(prop, value){
            return this.findBy(function(c){
                return c[prop] === value;
            });
        },

        /**
         * Find a component under this container at any level by a custom function. If the passed function returns
         * true, the component will be included in the results. The passed function is called with the arguments (component, this container).
         * @param {Function} fn The function to call
         * @param {Object} scope (optional)
         * @return {Array} Array of Ext.Components
         */
        findBy : function(fn, scope){
            var m = [], ct = this;
            this.cascade(function(c){
                if(ct != c && fn.call(scope || c, c, ct) === true){
                    m.push(c);
                }
            });
            return m;
        },

        /**
         * Get a component contained by this container (alias for items.get(key))
         * @param {String/Number} key The index or id of the component
         * @deprecated Should be removed in 4.0, since getComponent does the same thing.
         * @return {Ext.Component} Ext.Component
         */
        get : function(key){
            return this.getComponent(key);
        }
    });

    Ext.Container.LAYOUTS = {};
    Ext.reg('container', Ext.Container);