Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / container / Container.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * Base class for any Ext.Component that may contain other Components. Containers handle the basic behavior of
17  * containing items, namely adding, inserting and removing items.
18  *
19  * The most commonly used Container classes are Ext.panel.Panel, Ext.window.Window and
20  * Ext.tab.Panel. If you do not need the capabilities offered by the aforementioned classes you can create a
21  * lightweight Container to be encapsulated by an HTML element to your specifications by using the
22  * {@link Ext.Component#autoEl autoEl} config option.
23  *
24  * The code below illustrates how to explicitly create a Container:
25  *
26  *     @example
27  *     // Explicitly create a Container
28  *     Ext.create('Ext.container.Container', {
29  *         layout: {
30  *             type: 'hbox'
31  *         },
32  *         width: 400,
33  *         renderTo: Ext.getBody(),
34  *         border: 1,
35  *         style: {borderColor:'#000000', borderStyle:'solid', borderWidth:'1px'},
36  *         defaults: {
37  *             labelWidth: 80,
38  *             // implicitly create Container by specifying xtype
39  *             xtype: 'datefield',
40  *             flex: 1,
41  *             style: {
42  *                 padding: '10px'
43  *             }
44  *         },
45  *         items: [{
46  *             xtype: 'datefield',
47  *             name: 'startDate',
48  *             fieldLabel: 'Start date'
49  *         },{
50  *             xtype: 'datefield',
51  *             name: 'endDate',
52  *             fieldLabel: 'End date'
53  *         }]
54  *     });
55  *
56  * ## Layout
57  *
58  * Container classes delegate the rendering of child Components to a layout manager class which must be configured into
59  * the Container using the `{@link #layout}` configuration property.
60  *
61  * When either specifying child `{@link #items}` of a Container, or dynamically {@link #add adding} Components to a
62  * Container, remember to consider how you wish the Container to arrange those child elements, and whether those child
63  * elements need to be sized using one of Ext's built-in `{@link #layout}` schemes. By default, Containers use the
64  * {@link Ext.layout.container.Auto Auto} scheme which only renders child components, appending them one after the other
65  * inside the Container, and **does not apply any sizing** at all.
66  *
67  * A common mistake is when a developer neglects to specify a `{@link #layout}` (e.g. widgets like GridPanels or
68  * TreePanels are added to Containers for which no `{@link #layout}` has been specified). If a Container is left to
69  * use the default {@link Ext.layout.container.Auto Auto} scheme, none of its child components will be resized, or changed in
70  * any way when the Container is resized.
71  *
72  * Certain layout managers allow dynamic addition of child components. Those that do include
73  * Ext.layout.container.Card, Ext.layout.container.Anchor, Ext.layout.container.VBox,
74  * Ext.layout.container.HBox, and Ext.layout.container.Table. For example:
75  *
76  *     //  Create the GridPanel.
77  *     var myNewGrid = new Ext.grid.Panel({
78  *         store: myStore,
79  *         headers: myHeaders,
80  *         title: 'Results', // the title becomes the title of the tab
81  *     });
82  *
83  *     myTabPanel.add(myNewGrid); // {@link Ext.tab.Panel} implicitly uses {@link Ext.layout.container.Card Card}
84  *     myTabPanel.{@link Ext.tab.Panel#setActiveTab setActiveTab}(myNewGrid);
85  *
86  * The example above adds a newly created GridPanel to a TabPanel. Note that a TabPanel uses {@link
87  * Ext.layout.container.Card} as its layout manager which means all its child items are sized to {@link
88  * Ext.layout.container.Fit fit} exactly into its client area.
89  *
90  * **_Overnesting is a common problem_**. An example of overnesting occurs when a GridPanel is added to a TabPanel by
91  * wrapping the GridPanel _inside_ a wrapping Panel (that has no `{@link #layout}` specified) and then add that
92  * wrapping Panel to the TabPanel. The point to realize is that a GridPanel **is** a Component which can be added
93  * directly to a Container. If the wrapping Panel has no `{@link #layout}` configuration, then the overnested
94  * GridPanel will not be sized as expected.
95  *
96  * ## Adding via remote configuration
97  *
98  * A server side script can be used to add Components which are generated dynamically on the server. An example of
99  * adding a GridPanel to a TabPanel where the GridPanel is generated by the server based on certain parameters:
100  *
101  *     // execute an Ajax request to invoke server side script:
102  *     Ext.Ajax.request({
103  *         url: 'gen-invoice-grid.php',
104  *         // send additional parameters to instruct server script
105  *         params: {
106  *             startDate: Ext.getCmp('start-date').getValue(),
107  *             endDate: Ext.getCmp('end-date').getValue()
108  *         },
109  *         // process the response object to add it to the TabPanel:
110  *         success: function(xhr) {
111  *             var newComponent = eval(xhr.responseText); // see discussion below
112  *             myTabPanel.add(newComponent); // add the component to the TabPanel
113  *             myTabPanel.setActiveTab(newComponent);
114  *         },
115  *         failure: function() {
116  *             Ext.Msg.alert("Grid create failed", "Server communication failure");
117  *         }
118  *     });
119  *
120  * The server script needs to return a JSON representation of a configuration object, which, when decoded will return a
121  * config object with an {@link Ext.Component#xtype xtype}. The server might return the following JSON:
122  *
123  *     {
124  *         "xtype": 'grid',
125  *         "title": 'Invoice Report',
126  *         "store": {
127  *             "model": 'Invoice',
128  *             "proxy": {
129  *                 "type": 'ajax',
130  *                 "url": 'get-invoice-data.php',
131  *                 "reader": {
132  *                     "type": 'json'
133  *                     "record": 'transaction',
134  *                     "idProperty": 'id',
135  *                     "totalRecords": 'total'
136  *                 })
137  *             },
138  *             "autoLoad": {
139  *                 "params": {
140  *                     "startDate": '01/01/2008',
141  *                     "endDate": '01/31/2008'
142  *                 }
143  *             }
144  *         },
145  *         "headers": [
146  *             {"header": "Customer", "width": 250, "dataIndex": 'customer', "sortable": true},
147  *             {"header": "Invoice Number", "width": 120, "dataIndex": 'invNo', "sortable": true},
148  *             {"header": "Invoice Date", "width": 100, "dataIndex": 'date', "renderer": Ext.util.Format.dateRenderer('M d, y'), "sortable": true},
149  *             {"header": "Value", "width": 120, "dataIndex": 'value', "renderer": 'usMoney', "sortable": true}
150  *         ]
151  *     }
152  *
153  * When the above code fragment is passed through the `eval` function in the success handler of the Ajax request, the
154  * result will be a config object which, when added to a Container, will cause instantiation of a GridPanel. **Be sure
155  * that the Container is configured with a layout which sizes and positions the child items to your requirements.**
156  *
157  * **Note:** since the code above is _generated_ by a server script, the `autoLoad` params for the Store, the user's
158  * preferred date format, the metadata to allow generation of the Model layout, and the ColumnModel can all be generated
159  * into the code since these are all known on the server.
160  */
161 Ext.define('Ext.container.Container', {
162     extend: 'Ext.container.AbstractContainer',
163     alias: 'widget.container',
164     alternateClassName: 'Ext.Container',
165
166     /**
167      * Return the immediate child Component in which the passed element is located.
168      * @param {Ext.Element/HTMLElement/String} el The element to test (or ID of element).
169      * @return {Ext.Component} The child item which contains the passed element.
170      */
171     getChildByElement: function(el) {
172         var item,
173             itemEl,
174             i = 0,
175             it = this.items.items,
176             ln = it.length;
177
178         el = Ext.getDom(el);
179         for (; i < ln; i++) {
180             item = it[i];
181             itemEl = item.getEl();
182             if ((itemEl.dom === el) || itemEl.contains(el)) {
183                 return item;
184             }
185         }
186         return null;
187     }
188 });
189