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