Container2.html
10.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>The source code</title>
<link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
<script type="text/javascript" src="../resources/prettify/prettify.js"></script>
<style type="text/css">
.highlight { display: block; background-color: #ddd; }
</style>
<script type="text/javascript">
function highlight() {
document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
}
</script>
</head>
<body onload="prettyPrint(); highlight();">
<pre class="prettyprint lang-js"><span id='Ext-container-Container'>/**
</span> * Base class for any 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 Ext.panel.Panel, Ext.window.Window and
* 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.
*
* The code below illustrates how to explicitly create a Container:
*
* @example
* // 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 #cfg-items}` of a Container, or dynamically {@link #method-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 {@link 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
* Ext.layout.container.Card, Ext.layout.container.Anchor, Ext.layout.container.VBox,
* Ext.layout.container.HBox, and Ext.layout.container.Table. For example:
*
* // Create the GridPanel.
* var myNewGrid = Ext.create('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.
*/
Ext.define('Ext.container.Container', {
extend: 'Ext.container.AbstractContainer',
alias: 'widget.container',
alternateClassName: 'Ext.Container',
/*
* For more information on the following methods, see the note for the
* hierarchyEventSource observer defined in the class' callback
*/
fireHierarchyEvent: function (ename) {
this.hierarchyEventSource.fireEvent(ename, this);
},
// note that the collapse and expand events are fired explicitly from Panel.js
afterHide: function() {
this.callParent(arguments);
this.fireHierarchyEvent('hide');
},
afterShow: function(){
this.callParent(arguments);
this.fireHierarchyEvent('show');
},
onAdded: function() {
this.callParent(arguments);
if (this.hierarchyEventSource.hasListeners.added) {
this.fireHierarchyEvent('added');
}
},
<span id='Ext-container-Container-method-getChildByElement'> /**
</span> * Return the immediate child Component in which the passed element is located.
* @param {Ext.Element/HTMLElement/String} el The element to test (or ID of element).
* @param {Boolean} deep If `true`, returns the deepest descendant Component which contains the passed element.
* @return {Ext.Component} The child item which contains the passed element.
*/
getChildByElement: function(el, deep) {
var item,
itemEl,
i = 0,
it = this.getRefItems(),
ln = it.length;
el = Ext.getDom(el);
for (; i < ln; i++) {
item = it[i];
itemEl = item.getEl();
if (itemEl && ((itemEl.dom === el) || itemEl.contains(el))) {
return (deep && item.getChildByElement) ? item.getChildByElement(el, deep) : item;
}
}
return null;
}
}, function () {
/*
* The observer below is used to be able to detect showing/hiding at various levels
* in the hierarchy. While it's not particularly expensive to bubble an event up,
* cascading an event down can be quite costly.
*
* The main usage for this is to do with floating components. For example, the load mask
* is a floating component. The component it is masking may be inside several containers.
* As such, we need to know when component is hidden, either directly, or via a parent
* container being hidden. We can subscribe to these events and filter out the appropriate
* container.
*/
this.hierarchyEventSource = this.prototype.hierarchyEventSource = new Ext.util.Observable({ events: {
hide: true,
show: true,
collapse: true,
expand: true,
added: true
}});
});
</pre>
</body>
</html>