1 | /* |
---|
2 | * Ext JS Library 2.2.1 |
---|
3 | * Copyright(c) 2006-2009, Ext JS, LLC. |
---|
4 | * licensing@extjs.com |
---|
5 | * |
---|
6 | * http://extjs.com/license |
---|
7 | */ |
---|
8 | |
---|
9 | /** |
---|
10 | * @class Ext.Container |
---|
11 | * @extends Ext.BoxComponent |
---|
12 | * <p>Base class for any {@link Ext.BoxComponent} that can contain other components. The most commonly |
---|
13 | * used Container classes are {@link Ext.Panel}, {@link Ext.Window} and {@link Ext.TabPanel}, but you can |
---|
14 | * create a lightweight Container to encapsulate an HTML element that is created to your |
---|
15 | * specifications at render time by using the {@link Ext.Component#autoEl autoEl} config option |
---|
16 | * which takes the form of a {@link Ext.DomHelper DomHelper} specification. If you do not need |
---|
17 | * the capabilities offered by the above mentioned classes, for instance embedded |
---|
18 | * {@link Ext.layout.ColumnLayout column} layouts inside FormPanels, then this is a useful technique.</p> |
---|
19 | * <p>The code below illustrates both how to explicitly <i>create</i> a Container, and how to implicitly |
---|
20 | * create one using the <b><tt>'container'</tt></b> xtype:<pre><code> |
---|
21 | var embeddedColumns = new Ext.Container({ |
---|
22 | autoEl: {}, |
---|
23 | layout: 'column', |
---|
24 | defaults: { |
---|
25 | xtype: 'container', |
---|
26 | autoEl: {}, |
---|
27 | layout: 'form', |
---|
28 | columnWidth: 0.5, |
---|
29 | style: { |
---|
30 | padding: '10px' |
---|
31 | } |
---|
32 | }, |
---|
33 | items: [{ |
---|
34 | items: { |
---|
35 | xtype: 'datefield', |
---|
36 | name: 'startDate', |
---|
37 | fieldLabel: 'Start date' |
---|
38 | } |
---|
39 | }, { |
---|
40 | items: { |
---|
41 | xtype: 'datefield', |
---|
42 | name: 'endDate', |
---|
43 | fieldLabel: 'End date' |
---|
44 | } |
---|
45 | }] |
---|
46 | });</code></pre></p> |
---|
47 | * Containers handle the basic behavior of containing items, namely adding, inserting and removing them. |
---|
48 | * The specific layout logic required to visually render contained items is delegated to any one of the different |
---|
49 | * {@link #layout} classes available.</p> |
---|
50 | * <p>When either specifying child {@link #items} of a Container, or dynamically adding components to a Container, |
---|
51 | * remember to consider how you wish the Container to arrange those child elements, and whether those child elements |
---|
52 | * need to be sized using one of Ext's built-in layout schemes.</p> |
---|
53 | * <p>By default, Containers use the {@link Ext.layout.ContainerLayout ContainerLayout} scheme. This simply renders |
---|
54 | * child components, appending them one after the other inside the Container, and does not apply any sizing at all. |
---|
55 | * This is a common source of confusion when widgets like GridPanels or TreePanels are added to Containers for |
---|
56 | * which no layout has been specified. If a Container is left to use the ContainerLayout scheme, none of its child |
---|
57 | * components will be resized, or changed in any way when the Container is resized.</p> |
---|
58 | * <p>A very common example of this is where a developer will attempt to add a GridPanel to a TabPanel by wrapping |
---|
59 | * the GridPanel <i>inside</i> a wrapping Panel and add that wrapping Panel to the TabPanel. This misses the point that |
---|
60 | * Ext's inheritance means that a GridPanel <b>is</b> a Component which can be added unadorned into a Container. If |
---|
61 | * that wrapping Panel has no layout configuration, then the GridPanel will not be sized as expected.<p> |
---|
62 | * <p>Below is an example of adding a newly created GridPanel to a TabPanel. A TabPanel uses {@link Ext.layout.CardLayout} |
---|
63 | * as its layout manager which means all its child items are sized to fit exactly into its client area. The following |
---|
64 | * code requires prior knowledge of how to create GridPanels. See {@link Ext.grid.GridPanel}, {@link Ext.data.Store} |
---|
65 | * and {@link Ext.data.JsonReader} as well as the grid examples in the Ext installation's <tt>examples/grid</tt> |
---|
66 | * directory.</p><pre><code> |
---|
67 | // Create the GridPanel. |
---|
68 | myGrid = new Ext.grid.GridPanel({ |
---|
69 | store: myStore, |
---|
70 | columns: myColumnModel, |
---|
71 | title: 'Results', |
---|
72 | }); |
---|
73 | |
---|
74 | myTabPanel.add(myGrid); |
---|
75 | myTabPanel.setActiveTab(myGrid); |
---|
76 | </code></pre> |
---|
77 | */ |
---|
78 | Ext.Container = Ext.extend(Ext.BoxComponent, { |
---|
79 | /** @cfg {Boolean} monitorResize |
---|
80 | * True to automatically monitor window resize events to handle anything that is sensitive to the current size |
---|
81 | * of the viewport. This value is typically managed by the chosen {@link #layout} and should not need to be set manually. |
---|
82 | */ |
---|
83 | /** |
---|
84 | * @cfg {String} layout |
---|
85 | * The layout type to be used in this container. If not specified, a default {@link Ext.layout.ContainerLayout} |
---|
86 | * will be created and used. Specific config values for the chosen layout type can be specified using |
---|
87 | * {@link #layoutConfig}. Valid values are:<ul class="mdetail-params"> |
---|
88 | * <li>absolute</li> |
---|
89 | * <li>accordion</li> |
---|
90 | * <li>anchor</li> |
---|
91 | * <li>border</li> |
---|
92 | * <li>card</li> |
---|
93 | * <li>column</li> |
---|
94 | * <li>fit</li> |
---|
95 | * <li>form</li> |
---|
96 | * <li>table</li></ul> |
---|
97 | */ |
---|
98 | /** |
---|
99 | * @cfg {Object} layoutConfig |
---|
100 | * This is a config object containing properties specific to the chosen layout (to be used in conjunction with |
---|
101 | * the {@link #layout} config value). For complete details regarding the valid config options for each layout |
---|
102 | * type, see the layout class corresponding to the type specified:<ul class="mdetail-params"> |
---|
103 | * <li>{@link Ext.layout.Absolute}</li> |
---|
104 | * <li>{@link Ext.layout.Accordion}</li> |
---|
105 | * <li>{@link Ext.layout.AnchorLayout}</li> |
---|
106 | * <li>{@link Ext.layout.BorderLayout}</li> |
---|
107 | * <li>{@link Ext.layout.CardLayout}</li> |
---|
108 | * <li>{@link Ext.layout.ColumnLayout}</li> |
---|
109 | * <li>{@link Ext.layout.FitLayout}</li> |
---|
110 | * <li>{@link Ext.layout.FormLayout}</li> |
---|
111 | * <li>{@link Ext.layout.TableLayout}</li></ul> |
---|
112 | */ |
---|
113 | /** |
---|
114 | * @cfg {Boolean/Number} bufferResize |
---|
115 | * When set to true (100 milliseconds) or a number of milliseconds, the layout assigned for this container will buffer |
---|
116 | * the frequency it calculates and does a re-layout of components. This is useful for heavy containers or containers |
---|
117 | * with a large quantity of sub-components for which frequent layout calls would be expensive. |
---|
118 | */ |
---|
119 | /** |
---|
120 | * @cfg {String/Number} activeItem |
---|
121 | * A string component id or the numeric index of the component that should be initially activated within the |
---|
122 | * container's layout on render. For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first |
---|
123 | * item in the container's collection). activeItem only applies to layout styles that can display |
---|
124 | * items one at a time (like {@link Ext.layout.Accordion}, {@link Ext.layout.CardLayout} and |
---|
125 | * {@link Ext.layout.FitLayout}). Related to {@link Ext.layout.ContainerLayout#activeItem}. |
---|
126 | */ |
---|
127 | /** |
---|
128 | * @cfg {Mixed} items |
---|
129 | * A single item, or an array of child Components to be added to this container. |
---|
130 | * Each item can be any type of object based on {@link Ext.Component}.<br><br> |
---|
131 | * Component config objects may also be specified in order to avoid the overhead |
---|
132 | * of constructing a real Component object if lazy rendering might mean that the |
---|
133 | * added Component will not be rendered immediately. To take advantage of this |
---|
134 | * "lazy instantiation", set the {@link Ext.Component#xtype} config property to |
---|
135 | * the registered type of the Component wanted.<br><br> |
---|
136 | * For a list of all available xtypes, see {@link Ext.Component}. |
---|
137 | * If a single item is being passed, it should be passed directly as an object |
---|
138 | * reference (e.g., items: {...}). Multiple items should be passed as an array |
---|
139 | * of objects (e.g., items: [{...}, {...}]). |
---|
140 | */ |
---|
141 | /** |
---|
142 | * @cfg {Object} defaults |
---|
143 | * A config object that will be applied to all components added to this container either via the {@link #items} |
---|
144 | * config or via the {@link #add} or {@link #insert} methods. The defaults config can contain any number of |
---|
145 | * name/value property pairs to be added to each item, and should be valid for the types of items |
---|
146 | * being added to the container. For example, to automatically apply padding to the body of each of a set of |
---|
147 | * contained {@link Ext.Panel} items, you could pass: defaults: {bodyStyle:'padding:15px'}. |
---|
148 | */ |
---|
149 | |
---|
150 | /** @cfg {Boolean} autoDestroy |
---|
151 | * If true the container will automatically destroy any contained component that is removed from it, else |
---|
152 | * destruction must be handled manually (defaults to true). |
---|
153 | */ |
---|
154 | autoDestroy: true, |
---|
155 | /** @cfg {Boolean} hideBorders |
---|
156 | * True to hide the borders of each contained component, false to defer to the component's existing |
---|
157 | * border settings (defaults to false). |
---|
158 | */ |
---|
159 | /** @cfg {String} defaultType |
---|
160 | * <p>The default {@link Ext.Component xtype} of child Components to create in this Container when |
---|
161 | * a child item is specified as a raw configuration object, rather than as an instantiated Component.</p> |
---|
162 | * <p>Defaults to 'panel'.</p> |
---|
163 | */ |
---|
164 | defaultType: 'panel', |
---|
165 | |
---|
166 | // private |
---|
167 | initComponent : function(){ |
---|
168 | Ext.Container.superclass.initComponent.call(this); |
---|
169 | |
---|
170 | this.addEvents( |
---|
171 | /** |
---|
172 | * @event afterlayout |
---|
173 | * Fires when the components in this container are arranged by the associated layout manager. |
---|
174 | * @param {Ext.Container} this |
---|
175 | * @param {ContainerLayout} layout The ContainerLayout implementation for this container |
---|
176 | */ |
---|
177 | 'afterlayout', |
---|
178 | /** |
---|
179 | * @event beforeadd |
---|
180 | * Fires before any {@link Ext.Component} is added or inserted into the container. |
---|
181 | * A handler can return false to cancel the add. |
---|
182 | * @param {Ext.Container} this |
---|
183 | * @param {Ext.Component} component The component being added |
---|
184 | * @param {Number} index The index at which the component will be added to the container's items collection |
---|
185 | */ |
---|
186 | 'beforeadd', |
---|
187 | /** |
---|
188 | * @event beforeremove |
---|
189 | * Fires before any {@link Ext.Component} is removed from the container. A handler can return |
---|
190 | * false to cancel the remove. |
---|
191 | * @param {Ext.Container} this |
---|
192 | * @param {Ext.Component} component The component being removed |
---|
193 | */ |
---|
194 | 'beforeremove', |
---|
195 | /** |
---|
196 | * @event add |
---|
197 | * Fires after any {@link Ext.Component} is added or inserted into the container. |
---|
198 | * @param {Ext.Container} this |
---|
199 | * @param {Ext.Component} component The component that was added |
---|
200 | * @param {Number} index The index at which the component was added to the container's items collection |
---|
201 | */ |
---|
202 | 'add', |
---|
203 | /** |
---|
204 | * @event remove |
---|
205 | * Fires after any {@link Ext.Component} is removed from the container. |
---|
206 | * @param {Ext.Container} this |
---|
207 | * @param {Ext.Component} component The component that was removed |
---|
208 | */ |
---|
209 | 'remove' |
---|
210 | ); |
---|
211 | |
---|
212 | /** |
---|
213 | * The collection of components in this container as a {@link Ext.util.MixedCollection} |
---|
214 | * @type MixedCollection |
---|
215 | * @property items |
---|
216 | */ |
---|
217 | var items = this.items; |
---|
218 | if(items){ |
---|
219 | delete this.items; |
---|
220 | if(Ext.isArray(items) && items.length > 0){ |
---|
221 | this.add.apply(this, items); |
---|
222 | }else{ |
---|
223 | this.add(items); |
---|
224 | } |
---|
225 | } |
---|
226 | }, |
---|
227 | |
---|
228 | // private |
---|
229 | initItems : function(){ |
---|
230 | if(!this.items){ |
---|
231 | this.items = new Ext.util.MixedCollection(false, this.getComponentId); |
---|
232 | this.getLayout(); // initialize the layout |
---|
233 | } |
---|
234 | }, |
---|
235 | |
---|
236 | // private |
---|
237 | setLayout : function(layout){ |
---|
238 | if(this.layout && this.layout != layout){ |
---|
239 | this.layout.setContainer(null); |
---|
240 | } |
---|
241 | this.initItems(); |
---|
242 | this.layout = layout; |
---|
243 | layout.setContainer(this); |
---|
244 | }, |
---|
245 | |
---|
246 | // private |
---|
247 | render : function(){ |
---|
248 | Ext.Container.superclass.render.apply(this, arguments); |
---|
249 | if(this.layout){ |
---|
250 | if(typeof this.layout == 'string'){ |
---|
251 | this.layout = new Ext.Container.LAYOUTS[this.layout.toLowerCase()](this.layoutConfig); |
---|
252 | } |
---|
253 | this.setLayout(this.layout); |
---|
254 | |
---|
255 | if(this.activeItem !== undefined){ |
---|
256 | var item = this.activeItem; |
---|
257 | delete this.activeItem; |
---|
258 | this.layout.setActiveItem(item); |
---|
259 | return; |
---|
260 | } |
---|
261 | } |
---|
262 | if(!this.ownerCt){ |
---|
263 | this.doLayout(); |
---|
264 | } |
---|
265 | if(this.monitorResize === true){ |
---|
266 | Ext.EventManager.onWindowResize(this.doLayout, this, [false]); |
---|
267 | } |
---|
268 | }, |
---|
269 | |
---|
270 | /** |
---|
271 | * <p>Returns the Element to be used to contain the child Components of this Container.</p> |
---|
272 | * <p>An implementation is provided which returns the Container's {@link #getEl Element}, but |
---|
273 | * if there is a more complex structure to a Container, this may be overridden to return |
---|
274 | * the element into which the {@link #layout layout} renders child Components.</p> |
---|
275 | * @return {Ext.Element} The Element to render child Components into. |
---|
276 | */ |
---|
277 | getLayoutTarget : function(){ |
---|
278 | return this.el; |
---|
279 | }, |
---|
280 | |
---|
281 | // private - used as the key lookup function for the items collection |
---|
282 | getComponentId : function(comp){ |
---|
283 | return comp.itemId || comp.id; |
---|
284 | }, |
---|
285 | |
---|
286 | /** |
---|
287 | * <p>Adds a {@link Ext.Component Component} to this Container. Fires the {@link #beforeadd} event before |
---|
288 | * adding, then fires the {@link #add} event after the component has been added.</p> |
---|
289 | * <p>You will never call the render method of a child Component when using a Container. |
---|
290 | * Child Components are rendered by this Container's {@link #layout} manager when |
---|
291 | * this Container is first rendered.</p> |
---|
292 | * <p>Certain layout managers allow dynamic addition of child components. Those that do |
---|
293 | * include {@link Ext.layout.CardLayout}, {@link Ext.layout.AnchorLayout}, |
---|
294 | * {@link Ext.layout.FormLayout}, {@link Ext.layout.TableLayout}.</p> |
---|
295 | * <p>If the Container is already rendered when add is called, you may need to call |
---|
296 | * {@link #doLayout} to refresh the view which causes any unrendered child Components |
---|
297 | * to be rendered. This is required so that you can add multiple child components if needed |
---|
298 | * while only refreshing the layout once.</p> |
---|
299 | * <p>When creating complex UIs, it is important to remember that sizing and positioning |
---|
300 | * of child items is the responsibility of the Container's {@link #layout} manager. If |
---|
301 | * you expect child items to be sized in response to user interactions, you must |
---|
302 | * specify a layout manager which creates and manages the type of layout you have in mind.</p> |
---|
303 | * <p><b>Omitting the {@link #layout} config means that a basic layout manager is |
---|
304 | * used which does nothnig but render child components sequentially into the Container. |
---|
305 | * No sizing or positioning will be performed in this situation.</b></p> |
---|
306 | * @param {Ext.Component/Object} component The Component to add.<br><br> |
---|
307 | * Ext uses lazy rendering, and will only render the added Component should |
---|
308 | * it become necessary, that is: when the Container is layed out either on first render |
---|
309 | * or in response to a {@link #doLayout} call.<br><br> |
---|
310 | * A Component config object may be passed instead of an instantiated Component object. |
---|
311 | * The type of Component created from a config object is determined by the {@link Ext.Component#xtype xtype} |
---|
312 | * config property. If no xtype is configured, the Container's {@link #defaultType} |
---|
313 | * is used.<br><br> |
---|
314 | * For a list of all available xtypes, see {@link Ext.Component}. |
---|
315 | * @return {Ext.Component} component The Component (or config object) that was |
---|
316 | * added with the Container's default config values applied. |
---|
317 | * <p>example:</p><pre><code> |
---|
318 | var myNewGrid = new Ext.grid.GridPanel({ |
---|
319 | store: myStore, |
---|
320 | colModel: myColModel |
---|
321 | }); |
---|
322 | myTabPanel.add(myNewGrid); |
---|
323 | myTabPanel.setActiveTab(myNewGrid); |
---|
324 | </code></pre> |
---|
325 | */ |
---|
326 | add : function(comp){ |
---|
327 | if(!this.items){ |
---|
328 | this.initItems(); |
---|
329 | } |
---|
330 | var a = arguments, len = a.length; |
---|
331 | if(len > 1){ |
---|
332 | for(var i = 0; i < len; i++) { |
---|
333 | this.add(a[i]); |
---|
334 | } |
---|
335 | return; |
---|
336 | } |
---|
337 | var c = this.lookupComponent(this.applyDefaults(comp)); |
---|
338 | var pos = this.items.length; |
---|
339 | if(this.fireEvent('beforeadd', this, c, pos) !== false && this.onBeforeAdd(c) !== false){ |
---|
340 | this.items.add(c); |
---|
341 | c.ownerCt = this; |
---|
342 | this.fireEvent('add', this, c, pos); |
---|
343 | } |
---|
344 | return c; |
---|
345 | }, |
---|
346 | |
---|
347 | /** |
---|
348 | * Inserts a Component into this Container at a specified index. Fires the |
---|
349 | * {@link #beforeadd} event before inserting, then fires the {@link #add} event after the |
---|
350 | * Component has been inserted. |
---|
351 | * @param {Number} index The index at which the Component will be inserted |
---|
352 | * into the Container's items collection |
---|
353 | * @param {Ext.Component} component The child Component to insert.<br><br> |
---|
354 | * Ext uses lazy rendering, and will only render the inserted Component should |
---|
355 | * it become necessary.<br><br> |
---|
356 | * A Component config object may be passed in order to avoid the overhead of |
---|
357 | * constructing a real Component object if lazy rendering might mean that the |
---|
358 | * inserted Component will not be rendered immediately. To take advantage of |
---|
359 | * this "lazy instantiation", set the {@link Ext.Component#xtype} config |
---|
360 | * property to the registered type of the Component wanted.<br><br> |
---|
361 | * For a list of all available xtypes, see {@link Ext.Component}. |
---|
362 | * @return {Ext.Component} component The Component (or config object) that was |
---|
363 | * inserted with the Container's default config values applied. |
---|
364 | */ |
---|
365 | insert : function(index, comp){ |
---|
366 | if(!this.items){ |
---|
367 | this.initItems(); |
---|
368 | } |
---|
369 | var a = arguments, len = a.length; |
---|
370 | if(len > 2){ |
---|
371 | for(var i = len-1; i >= 1; --i) { |
---|
372 | this.insert(index, a[i]); |
---|
373 | } |
---|
374 | return; |
---|
375 | } |
---|
376 | var c = this.lookupComponent(this.applyDefaults(comp)); |
---|
377 | |
---|
378 | if(c.ownerCt == this && this.items.indexOf(c) < index){ |
---|
379 | --index; |
---|
380 | } |
---|
381 | |
---|
382 | if(this.fireEvent('beforeadd', this, c, index) !== false && this.onBeforeAdd(c) !== false){ |
---|
383 | this.items.insert(index, c); |
---|
384 | c.ownerCt = this; |
---|
385 | this.fireEvent('add', this, c, index); |
---|
386 | } |
---|
387 | return c; |
---|
388 | }, |
---|
389 | |
---|
390 | // private |
---|
391 | applyDefaults : function(c){ |
---|
392 | if(this.defaults){ |
---|
393 | if(typeof c == 'string'){ |
---|
394 | c = Ext.ComponentMgr.get(c); |
---|
395 | Ext.apply(c, this.defaults); |
---|
396 | }else if(!c.events){ |
---|
397 | Ext.applyIf(c, this.defaults); |
---|
398 | }else{ |
---|
399 | Ext.apply(c, this.defaults); |
---|
400 | } |
---|
401 | } |
---|
402 | return c; |
---|
403 | }, |
---|
404 | |
---|
405 | // private |
---|
406 | onBeforeAdd : function(item){ |
---|
407 | if(item.ownerCt){ |
---|
408 | item.ownerCt.remove(item, false); |
---|
409 | } |
---|
410 | if(this.hideBorders === true){ |
---|
411 | item.border = (item.border === true); |
---|
412 | } |
---|
413 | }, |
---|
414 | |
---|
415 | /** |
---|
416 | * Removes a component from this container. Fires the {@link #beforeremove} event before removing, then fires |
---|
417 | * the {@link #remove} event after the component has been removed. |
---|
418 | * @param {Component/String} component The component reference or id to remove. |
---|
419 | * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function. |
---|
420 | * Defaults to the value of this Container's {@link #autoDestroy} config. |
---|
421 | * @return {Ext.Component} component The Component that was removed. |
---|
422 | */ |
---|
423 | remove : function(comp, autoDestroy){ |
---|
424 | var c = this.getComponent(comp); |
---|
425 | if(c && this.fireEvent('beforeremove', this, c) !== false){ |
---|
426 | this.items.remove(c); |
---|
427 | delete c.ownerCt; |
---|
428 | if(autoDestroy === true || (autoDestroy !== false && this.autoDestroy)){ |
---|
429 | c.destroy(); |
---|
430 | } |
---|
431 | if(this.layout && this.layout.activeItem == c){ |
---|
432 | delete this.layout.activeItem; |
---|
433 | } |
---|
434 | this.fireEvent('remove', this, c); |
---|
435 | } |
---|
436 | return c; |
---|
437 | }, |
---|
438 | |
---|
439 | /** |
---|
440 | * Removes all components from this container. |
---|
441 | * @param {Boolean} autoDestroy (optional) True to automatically invoke the removed Component's {@link Ext.Component#destroy} function. |
---|
442 | * Defaults to the value of this Container's {@link #autoDestroy} config. |
---|
443 | * @return {Array} Array of the destroyed components |
---|
444 | */ |
---|
445 | removeAll: function(autoDestroy){ |
---|
446 | var item, items = []; |
---|
447 | while((item = this.items.last())){ |
---|
448 | items.unshift(this.remove(item, autoDestroy)); |
---|
449 | } |
---|
450 | return items; |
---|
451 | }, |
---|
452 | |
---|
453 | /** |
---|
454 | * Gets a direct child Component by id, or by index. |
---|
455 | * @param {String/Number} id or index of child Component to return. |
---|
456 | * @return Ext.Component |
---|
457 | */ |
---|
458 | getComponent : function(comp){ |
---|
459 | if(typeof comp == 'object'){ |
---|
460 | return comp; |
---|
461 | } |
---|
462 | return this.items.get(comp); |
---|
463 | }, |
---|
464 | |
---|
465 | // private |
---|
466 | lookupComponent : function(comp){ |
---|
467 | if(typeof comp == 'string'){ |
---|
468 | return Ext.ComponentMgr.get(comp); |
---|
469 | }else if(!comp.events){ |
---|
470 | return this.createComponent(comp); |
---|
471 | } |
---|
472 | return comp; |
---|
473 | }, |
---|
474 | |
---|
475 | // private |
---|
476 | createComponent : function(config){ |
---|
477 | return Ext.ComponentMgr.create(config, this.defaultType); |
---|
478 | }, |
---|
479 | |
---|
480 | /** |
---|
481 | * Force this container's layout to be recalculated. A call to this function is required after adding a new component |
---|
482 | * to an already rendered container, or possibly after changing sizing/position properties of child components. |
---|
483 | * @param {Boolean} shallow (optional) True to only calc the layout of this component, and let child components auto |
---|
484 | * calc layouts as required (defaults to false, which calls doLayout recursively for each subcontainer) |
---|
485 | */ |
---|
486 | doLayout : function(shallow){ |
---|
487 | if(this.rendered && this.layout){ |
---|
488 | this.layout.layout(); |
---|
489 | } |
---|
490 | if(shallow !== false && this.items){ |
---|
491 | var cs = this.items.items; |
---|
492 | for(var i = 0, len = cs.length; i < len; i++) { |
---|
493 | var c = cs[i]; |
---|
494 | if(c.doLayout){ |
---|
495 | c.doLayout(); |
---|
496 | } |
---|
497 | } |
---|
498 | } |
---|
499 | }, |
---|
500 | |
---|
501 | /** |
---|
502 | * Returns the layout currently in use by the container. If the container does not currently have a layout |
---|
503 | * set, a default {@link Ext.layout.ContainerLayout} will be created and set as the container's layout. |
---|
504 | * @return {ContainerLayout} layout The container's layout |
---|
505 | */ |
---|
506 | getLayout : function(){ |
---|
507 | if(!this.layout){ |
---|
508 | var layout = new Ext.layout.ContainerLayout(this.layoutConfig); |
---|
509 | this.setLayout(layout); |
---|
510 | } |
---|
511 | return this.layout; |
---|
512 | }, |
---|
513 | |
---|
514 | // private |
---|
515 | beforeDestroy : function(){ |
---|
516 | if(this.items){ |
---|
517 | Ext.destroy.apply(Ext, this.items.items); |
---|
518 | } |
---|
519 | if(this.monitorResize){ |
---|
520 | Ext.EventManager.removeResizeListener(this.doLayout, this); |
---|
521 | } |
---|
522 | if (this.layout && this.layout.destroy) { |
---|
523 | this.layout.destroy(); |
---|
524 | } |
---|
525 | Ext.Container.superclass.beforeDestroy.call(this); |
---|
526 | }, |
---|
527 | |
---|
528 | /** |
---|
529 | * Bubbles up the component/container heirarchy, calling the specified function with each component. The scope (<i>this</i>) of |
---|
530 | * function call will be the scope provided or the current component. The arguments to the function |
---|
531 | * will be the args provided or the current component. If the function returns false at any point, |
---|
532 | * the bubble is stopped. |
---|
533 | * @param {Function} fn The function to call |
---|
534 | * @param {Object} scope (optional) The scope of the function (defaults to current node) |
---|
535 | * @param {Array} args (optional) The args to call the function with (default to passing the current component) |
---|
536 | */ |
---|
537 | bubble : function(fn, scope, args){ |
---|
538 | var p = this; |
---|
539 | while(p){ |
---|
540 | if(fn.apply(scope || p, args || [p]) === false){ |
---|
541 | break; |
---|
542 | } |
---|
543 | p = p.ownerCt; |
---|
544 | } |
---|
545 | }, |
---|
546 | |
---|
547 | /** |
---|
548 | * Cascades down the component/container heirarchy from this component (called first), calling the specified function with |
---|
549 | * each component. The scope (<i>this</i>) of |
---|
550 | * function call will be the scope provided or the current component. The arguments to the function |
---|
551 | * will be the args provided or the current component. If the function returns false at any point, |
---|
552 | * the cascade is stopped on that branch. |
---|
553 | * @param {Function} fn The function to call |
---|
554 | * @param {Object} scope (optional) The scope of the function (defaults to current component) |
---|
555 | * @param {Array} args (optional) The args to call the function with (defaults to passing the current component) |
---|
556 | */ |
---|
557 | cascade : function(fn, scope, args){ |
---|
558 | if(fn.apply(scope || this, args || [this]) !== false){ |
---|
559 | if(this.items){ |
---|
560 | var cs = this.items.items; |
---|
561 | for(var i = 0, len = cs.length; i < len; i++){ |
---|
562 | if(cs[i].cascade){ |
---|
563 | cs[i].cascade(fn, scope, args); |
---|
564 | }else{ |
---|
565 | fn.apply(scope || cs[i], args || [cs[i]]); |
---|
566 | } |
---|
567 | } |
---|
568 | } |
---|
569 | } |
---|
570 | }, |
---|
571 | |
---|
572 | /** |
---|
573 | * Find a component under this container at any level by id |
---|
574 | * @param {String} id |
---|
575 | * @return Ext.Component |
---|
576 | */ |
---|
577 | findById : function(id){ |
---|
578 | var m, ct = this; |
---|
579 | this.cascade(function(c){ |
---|
580 | if(ct != c && c.id === id){ |
---|
581 | m = c; |
---|
582 | return false; |
---|
583 | } |
---|
584 | }); |
---|
585 | return m || null; |
---|
586 | }, |
---|
587 | |
---|
588 | /** |
---|
589 | * Find a component under this container at any level by xtype or class |
---|
590 | * @param {String/Class} xtype The xtype string for a component, or the class of the component directly |
---|
591 | * @param {Boolean} shallow (optional) False to check whether this Component is descended from the xtype (this is |
---|
592 | * the default), or true to check whether this Component is directly of the specified xtype. |
---|
593 | * @return {Array} Array of Ext.Components |
---|
594 | */ |
---|
595 | findByType : function(xtype, shallow){ |
---|
596 | return this.findBy(function(c){ |
---|
597 | return c.isXType(xtype, shallow); |
---|
598 | }); |
---|
599 | }, |
---|
600 | |
---|
601 | /** |
---|
602 | * Find a component under this container at any level by property |
---|
603 | * @param {String} prop |
---|
604 | * @param {String} value |
---|
605 | * @return {Array} Array of Ext.Components |
---|
606 | */ |
---|
607 | find : function(prop, value){ |
---|
608 | return this.findBy(function(c){ |
---|
609 | return c[prop] === value; |
---|
610 | }); |
---|
611 | }, |
---|
612 | |
---|
613 | /** |
---|
614 | * Find a component under this container at any level by a custom function. If the passed function returns |
---|
615 | * true, the component will be included in the results. The passed function is called with the arguments (component, this container). |
---|
616 | * @param {Function} fcn |
---|
617 | * @param {Object} scope (optional) |
---|
618 | * @return {Array} Array of Ext.Components |
---|
619 | */ |
---|
620 | findBy : function(fn, scope){ |
---|
621 | var m = [], ct = this; |
---|
622 | this.cascade(function(c){ |
---|
623 | if(ct != c && fn.call(scope || c, c, ct) === true){ |
---|
624 | m.push(c); |
---|
625 | } |
---|
626 | }); |
---|
627 | return m; |
---|
628 | } |
---|
629 | }); |
---|
630 | |
---|
631 | Ext.Container.LAYOUTS = {}; |
---|
632 | Ext.reg('container', Ext.Container); |
---|