X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/0494b8d9b9bb03ab6c22b34dae81261e3cd7e3e6..7a654f8d43fdb43d78b63d90528bed6e86b608cc:/src/container/Container.js?ds=inline diff --git a/src/container/Container.js b/src/container/Container.js new file mode 100644 index 00000000..9713718e --- /dev/null +++ b/src/container/Container.js @@ -0,0 +1,184 @@ +/** + * @class Ext.container.Container + * @extends Ext.container.AbstractContainer + *

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.

+ * + *

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 + * {@link Ext.Component#autoEl autoEl} config option.

+ * + * {@img Ext.Container/Ext.Container.png Ext.Container component} + *

The code below illustrates how to explicitly create a Container:


+// 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'
+    }]
+});
+

+ * + *

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.container.Auto Auto} 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 + * {Ext.layout.container.Auto Auto} 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.container.Card}, + * {@link Ext.layout.container.Anchor}, {@link Ext.layout.container.VBox}, {@link Ext.layout.container.HBox}, and + * {@link Ext.layout.container.Table}. For example:


+//  Create the GridPanel.
+var myNewGrid = new Ext.grid.Panel({
+    store: myStore,
+    headers: myHeaders,
+    title: 'Results', // the title becomes the title of the tab
+});
+
+myTabPanel.add(myNewGrid); // {@link Ext.tab.Panel} implicitly uses {@link Ext.layout.container.Card Card}
+myTabPanel.{@link Ext.tab.Panel#setActiveTab setActiveTab}(myNewGrid);
+ * 

+ *

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. + *

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 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:


+{
+    "xtype": 'grid',
+    "title": 'Invoice Report',
+    "store": {
+        "model": 'Invoice',
+        "proxy": {
+            "type": 'ajax',
+            "url": 'get-invoice-data.php',
+            "reader": {
+                "type": 'json'
+                "record": 'transaction',
+                "idProperty": 'id',
+                "totalRecords": 'total'
+            })
+        },
+        "autoLoad": {
+            "params": {
+                "startDate": '01/01/2008',
+                "endDate": '01/31/2008'
+            }
+        }
+    },
+    "headers": [
+        {"header": "Customer", "width": 250, "dataIndex": 'customer', "sortable": true},
+        {"header": "Invoice Number", "width": 120, "dataIndex": 'invNo', "sortable": true},
+        {"header": "Invoice Date", "width": 100, "dataIndex": 'date', "renderer": Ext.util.Format.dateRenderer('M d, y'), "sortable": true},
+        {"header": "Value", "width": 120, "dataIndex": 'value', "renderer": 'usMoney', "sortable": true}
+    ]
+}
+
+ *

When the above code fragment is passed through the eval 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. Be sure that the Container is configured with a layout which sizes and positions the child items to your requirements.

+ *

Note: since the code above is generated by a server script, the autoLoad 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.

+ * + * @xtype container + */ +Ext.define('Ext.container.Container', { + extend: 'Ext.container.AbstractContainer', + alias: 'widget.container', + alternateClassName: 'Ext.Container', + + /** + * Return the immediate child Component in which the passed element is located. + * @param el The element to test. + * @return {Component} The child item which contains the passed element. + */ + getChildByElement: function(el) { + var item, + itemEl, + i = 0, + it = this.items.items, + ln = it.length; + + el = Ext.getDom(el); + for (; i < ln; i++) { + item = it[i]; + itemEl = item.getEl(); + if ((itemEl.dom === el) || itemEl.contains(el)) { + return item; + } + } + return null; + } +});