Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / docs / source / Panel4.html
1 <!DOCTYPE html><html><head><title>Sencha Documentation Project</title><link rel="stylesheet" href="../reset.css" type="text/css"><link rel="stylesheet" href="../prettify.css" type="text/css"><link rel="stylesheet" href="../prettify_sa.css" type="text/css"><script type="text/javascript" src="../prettify.js"></script></head><body onload="prettyPrint()"><pre class="prettyprint"><pre><span id='Ext-tab.Panel-method-constructor'><span id='Ext-tab.Panel'>/**
2 </span></span> * @author Ed Spencer, Tommy Maintz, Brian Moeskau
3  * @class Ext.tab.Panel
4  * @extends Ext.panel.Panel
5
6 A basic tab container. TabPanels can be used exactly like a standard {@link Ext.panel.Panel} for layout purposes, but also 
7 have special support for containing child Components (`{@link Ext.container.Container#items items}`) that are managed 
8 using a {@link Ext.layout.container.Card CardLayout layout manager}, and displayed as separate tabs.
9
10 __Note:__
11
12 By default, a tab's close tool _destroys_ the child tab Component and all its descendants. This makes the child tab 
13 Component, and all its descendants __unusable__. To enable re-use of a tab, configure the TabPanel with `{@link #autoDestroy autoDestroy: false}`.
14
15 __TabPanel's layout:__
16
17 TabPanels use a Dock layout to position the {@link Ext.tab.Bar TabBar} at the top of the widget. Panels added to the TabPanel will have their 
18 header hidden by default because the Tab will automatically take the Panel's configured title and icon.
19
20 TabPanels use their {@link Ext.panel.Panel#header header} or {@link Ext.panel.Panel#footer footer} element (depending on the {@link #tabPosition} 
21 configuration) to accommodate the tab selector buttons. This means that a TabPanel will not display any configured title, and will not display any 
22 configured header {@link Ext.panel.Panel#tools tools}.
23
24 To display a header, embed the TabPanel in a {@link Ext.panel.Panel Panel} which uses `{@link Ext.container.Container#layout layout:'fit'}`.
25
26 __Examples:__
27
28 Here is a basic TabPanel rendered to the body. This also shows the useful configuration {@link #activeTab}, which allows you to set the active tab on render. 
29 If you do not set an {@link #activeTab}, no tabs will be active by default.
30 {@img Ext.tab.Panel/Ext.tab.Panel1.png TabPanel component}
31 Example usage:
32
33     Ext.create('Ext.tab.Panel', {
34         width: 300,
35         height: 200,
36         activeTab: 0,
37         items: [
38             {
39                 title: 'Tab 1',
40                 bodyPadding: 10,
41                 html : 'A simple tab'
42             },
43             {
44                 title: 'Tab 2',
45                 html : 'Another one'
46             }
47         ],
48         renderTo : Ext.getBody()
49     }); 
50     
51 It is easy to control the visibility of items in the tab bar. Specify hidden: true to have the
52 tab button hidden initially. Items can be subsequently hidden and show by accessing the
53 tab property on the child item.
54
55 Example usage:
56     
57     var tabs = Ext.create('Ext.tab.Panel', {
58         width: 400,
59         height: 400,
60         renderTo: document.body,
61         items: [{
62             title: 'Home',
63             html: 'Home',
64             itemId: 'home'
65         }, {
66             title: 'Users',
67             html: 'Users',
68             itemId: 'users',
69             hidden: true
70         }, {
71             title: 'Tickets',
72             html: 'Tickets',
73             itemId: 'tickets'
74         }]    
75     });
76     
77     setTimeout(function(){
78         tabs.child('#home').tab.hide();
79         var users = tabs.child('#users');
80         users.tab.show();
81         tabs.setActiveTab(users);
82     }, 1000);
83
84 You can remove the background of the TabBar by setting the {@link #plain} property to `false`.
85
86 Example usage:
87
88     Ext.create('Ext.tab.Panel', {
89         width: 300,
90         height: 200,
91         activeTab: 0,
92         plain: true,
93         items: [
94             {
95                 title: 'Tab 1',
96                 bodyPadding: 10,
97                 html : 'A simple tab'
98             },
99             {
100                 title: 'Tab 2',
101                 html : 'Another one'
102             }
103         ],
104         renderTo : Ext.getBody()
105     }); 
106
107 Another useful configuration of TabPanel is {@link #tabPosition}. This allows you to change the position where the tabs are displayed. The available 
108 options for this are `'top'` (default) and `'bottom'`.
109 {@img Ext.tab.Panel/Ext.tab.Panel2.png TabPanel component}
110 Example usage:
111
112     Ext.create('Ext.tab.Panel', {
113         width: 300,
114         height: 200,
115         activeTab: 0,
116         bodyPadding: 10,        
117         tabPosition: 'bottom',
118         items: [
119             {
120                 title: 'Tab 1',
121                 html : 'A simple tab'
122             },
123             {
124                 title: 'Tab 2',
125                 html : 'Another one'
126             }
127         ],
128         renderTo : Ext.getBody()
129     }); 
130
131 The {@link #setActiveTab} is a very useful method in TabPanel which will allow you to change the current active tab. You can either give it an index or 
132 an instance of a tab.
133
134 Example usage:
135
136     var tabs = Ext.create('Ext.tab.Panel', {
137         items: [
138             {
139                 id   : 'my-tab',
140                 title: 'Tab 1',
141                 html : 'A simple tab'
142             },
143             {
144                 title: 'Tab 2',
145                 html : 'Another one'
146             }
147         ],
148         renderTo : Ext.getBody()
149     });
150     
151     var tab = Ext.getCmp('my-tab');
152     
153     Ext.create('Ext.button.Button', {
154         renderTo: Ext.getBody(),
155         text    : 'Select the first tab',
156         scope   : this,
157         handler : function() {
158             tabs.setActiveTab(tab);
159         }
160     });
161     
162     Ext.create('Ext.button.Button', {
163         text    : 'Select the second tab',
164         scope   : this,
165         handler : function() {
166             tabs.setActiveTab(1);
167         },
168         renderTo : Ext.getBody()        
169     });
170
171 The {@link #getActiveTab} is a another useful method in TabPanel which will return the current active tab.
172
173 Example usage:
174
175     var tabs = Ext.create('Ext.tab.Panel', {
176         items: [
177             {
178                 title: 'Tab 1',
179                 html : 'A simple tab'
180             },
181             {
182                 title: 'Tab 2',
183                 html : 'Another one'
184             }
185         ],
186         renderTo : Ext.getBody()        
187     });
188     
189     Ext.create('Ext.button.Button', {
190         text    : 'Get active tab',
191         scope   : this,
192         handler : function() {
193             var tab = tabs.getActiveTab();
194             alert('Current tab: ' + tab.title);
195         },
196         renderTo : Ext.getBody()        
197     });
198
199 Adding a new tab is very simple with a TabPanel. You simple call the {@link #add} method with an config object for a panel.
200
201 Example usage:
202
203     var tabs = Ext.Create('Ext.tab.Panel', {
204         items: [
205             {
206                 title: 'Tab 1',
207                 html : 'A simple tab'
208             },
209             {
210                 title: 'Tab 2',
211                 html : 'Another one'
212             }
213         ],
214         renderTo : Ext.getBody()        
215     });
216     
217     Ext.create('Ext.button.Button', {
218         text    : 'New tab',
219         scope   : this,
220         handler : function() {
221             var tab = tabs.add({
222                 title: 'Tab ' + (tabs.items.length + 1), //we use the tabs.items property to get the length of current items/tabs
223                 html : 'Another one'
224             });
225             
226             tabs.setActiveTab(tab);
227         },
228         renderTo : Ext.getBody()
229     });
230
231 Additionally, removing a tab is very also simple with a TabPanel. You simple call the {@link #remove} method with an config object for a panel.
232
233 Example usage:
234
235     var tabs = Ext.Create('Ext.tab.Panel', {        
236         items: [
237             {
238                 title: 'Tab 1',
239                 html : 'A simple tab'
240             },
241             {
242                 id   : 'remove-this-tab',
243                 title: 'Tab 2',
244                 html : 'Another one'
245             }
246         ],
247         renderTo : Ext.getBody()
248     });
249     
250     Ext.Create('Ext.button.Button', {
251         text    : 'Remove tab',
252         scope   : this,
253         handler : function() {
254             var tab = Ext.getCmp('remove-this-tab');
255             tabs.remove(tab);
256         },
257         renderTo : Ext.getBody()
258     });
259
260  * @extends Ext.Panel
261  * @constructor
262  * @param {Object} config The configuration options
263  * @xtype tabpanel
264  * @markdown
265  */
266 Ext.define('Ext.tab.Panel', {
267     extend: 'Ext.panel.Panel',
268     alias: 'widget.tabpanel',
269     alternateClassName: ['Ext.TabPanel'],
270
271     requires: ['Ext.layout.container.Card', 'Ext.tab.Bar'],
272
273 <span id='Ext-tab.Panel-cfg-tabPosition'>    /**
274 </span>     * @cfg {String} tabPosition The position where the tab strip should be rendered (defaults to &lt;code&gt;'top'&lt;/code&gt;).
275      * In 4.0, The only other supported value is &lt;code&gt;'bottom'&lt;/code&gt;.
276      */
277     tabPosition : 'top',
278     
279 <span id='Ext-tab.Panel-cfg-tabBar'>    /**
280 </span>     * @cfg {Object} tabBar Optional configuration object for the internal {@link Ext.tab.Bar}. If present, this is 
281      * passed straight through to the TabBar's constructor
282      */
283
284 <span id='Ext-tab.Panel-cfg-layout'>    /**
285 </span>     * @cfg {Object} layout Optional configuration object for the internal {@link Ext.layout.container.Card card layout}.
286      * If present, this is passed straight through to the layout's constructor
287      */
288
289 <span id='Ext-tab.Panel-cfg-removePanelHeader'>    /**
290 </span>     * @cfg {Boolean} removePanelHeader True to instruct each Panel added to the TabContainer to not render its header 
291      * element. This is to ensure that the title of the panel does not appear twice. Defaults to true.
292      */
293     removePanelHeader: true,
294
295 <span id='Ext-tab.Panel-cfg-Boolean'>    /**
296 </span>     * @cfg Boolean plain
297      * True to not show the full background on the TabBar
298      */
299     plain: false,
300
301 <span id='Ext-tab.Panel-cfg-itemCls'>    /**
302 </span>     * @cfg {String} itemCls The class added to each child item of this TabPanel. Defaults to 'x-tabpanel-child'.
303      */
304     itemCls: 'x-tabpanel-child',
305
306 <span id='Ext-tab.Panel-cfg-minTabWidth'>    /**
307 </span>     * @cfg {Number} minTabWidth The minimum width for a tab in the {@link #tabBar}. Defaults to &lt;code&gt;30&lt;/code&gt;.
308      */
309
310 <span id='Ext-tab.Panel-cfg-deferredRender'>    /**
311 </span>     * @cfg {Boolean} deferredRender
312      * &lt;p&gt;&lt;tt&gt;true&lt;/tt&gt; by default to defer the rendering of child &lt;tt&gt;{@link Ext.container.Container#items items}&lt;/tt&gt;
313      * to the browsers DOM until a tab is activated. &lt;tt&gt;false&lt;/tt&gt; will render all contained
314      * &lt;tt&gt;{@link Ext.container.Container#items items}&lt;/tt&gt; as soon as the {@link Ext.layout.container.Card layout}
315      * is rendered. If there is a significant amount of content or a lot of heavy controls being
316      * rendered into panels that are not displayed by default, setting this to &lt;tt&gt;true&lt;/tt&gt; might
317      * improve performance.&lt;/p&gt;
318      * &lt;br&gt;&lt;p&gt;The &lt;tt&gt;deferredRender&lt;/tt&gt; property is internally passed to the layout manager for
319      * TabPanels ({@link Ext.layout.container.Card}) as its {@link Ext.layout.container.Card#deferredRender}
320      * configuration value.&lt;/p&gt;
321      * &lt;br&gt;&lt;p&gt;&lt;b&gt;Note&lt;/b&gt;: leaving &lt;tt&gt;deferredRender&lt;/tt&gt; as &lt;tt&gt;true&lt;/tt&gt; means that the content
322      * within an unactivated tab will not be available&lt;/p&gt;
323      */
324     deferredRender : true,
325
326     //inherit docs
327     initComponent: function() {
328         var me = this,
329             dockedItems = me.dockedItems || [],
330             activeTab = me.activeTab || 0;
331
332         me.layout = Ext.create('Ext.layout.container.Card', Ext.apply({
333             owner: me,
334             deferredRender: me.deferredRender,
335             itemCls: me.itemCls
336         }, me.layout));
337
338 <span id='Ext-tab.Panel-property-tabBar'>        /**
339 </span>         * @property tabBar
340          * @type Ext.TabBar
341          * Internal reference to the docked TabBar
342          */
343         me.tabBar = Ext.create('Ext.tab.Bar', Ext.apply({}, me.tabBar, {
344             dock: me.tabPosition,
345             plain: me.plain,
346             border: me.border,
347             cardLayout: me.layout,
348             tabPanel: me
349         }));
350
351         if (dockedItems &amp;&amp; !Ext.isArray(dockedItems)) {
352             dockedItems = [dockedItems];
353         }
354
355         dockedItems.push(me.tabBar);
356         me.dockedItems = dockedItems;
357
358         me.addEvents(
359 <span id='Ext-tab.Panel-event-beforetabchange'>            /**
360 </span>             * @event beforetabchange
361              * Fires before a tab change (activated by {@link #setActiveTab}). Return false in any listener to cancel
362              * the tabchange
363              * @param {Ext.tab.Panel} tabPanel The TabPanel
364              * @param {Ext.Component} newCard The card that is about to be activated
365              * @param {Ext.Component} oldCard The card that is currently active
366              */
367             'beforetabchange',
368
369 <span id='Ext-tab.Panel-event-tabchange'>            /**
370 </span>             * @event tabchange
371              * Fires when a new tab has been activated (activated by {@link #setActiveTab}).
372              * @param {Ext.tab.Panel} tabPanel The TabPanel
373              * @param {Ext.Component} newCard The newly activated item
374              * @param {Ext.Component} oldCard The previously active item
375              */
376             'tabchange'
377         );
378         me.callParent(arguments);
379
380         //set the active tab
381         me.setActiveTab(activeTab);
382         //set the active tab after initial layout
383         me.on('afterlayout', me.afterInitialLayout, me, {single: true});
384     },
385
386 <span id='Ext-tab.Panel-method-afterInitialLayout'>    /**
387 </span>     * @private
388      * We have to wait until after the initial layout to visually activate the activeTab (if set).
389      * The active tab has different margins than normal tabs, so if the initial layout happens with
390      * a tab active, its layout will be offset improperly due to the active margin style. Waiting
391      * until after the initial layout avoids this issue.
392      */
393     afterInitialLayout: function() {
394         var me = this,
395             card = me.getComponent(me.activeTab);
396             
397         if (card) {
398             me.layout.setActiveItem(card);
399         }
400     },
401
402 <span id='Ext-tab.Panel-method-setActiveTab'>    /**
403 </span>     * Makes the given card active (makes it the visible card in the TabPanel's CardLayout and highlights the Tab)
404      * @param {Ext.Component} card The card to make active
405      */
406     setActiveTab: function(card) {
407         var me = this,
408             previous;
409
410         card = me.getComponent(card);
411         if (card) {
412             previous = me.getActiveTab();
413             
414             if (previous &amp;&amp; previous !== card &amp;&amp; me.fireEvent('beforetabchange', me, card, previous) === false) {
415                 return false;
416             }
417             
418             me.tabBar.setActiveTab(card.tab);
419             me.activeTab = card;
420             if (me.rendered) {
421                 me.layout.setActiveItem(card);
422             }
423             
424             if (previous &amp;&amp; previous !== card) {
425                 me.fireEvent('tabchange', me, card, previous);
426             }
427         }
428     },
429
430 <span id='Ext-tab.Panel-method-getActiveTab'>    /**
431 </span>     * Returns the item that is currently active inside this TabPanel. Note that before the TabPanel first activates a
432      * child component this will return whatever was configured in the {@link #activeTab} config option 
433      * @return {Ext.Component/Integer} The currently active item
434      */
435     getActiveTab: function() {
436         return this.activeTab;
437     },
438
439 <span id='Ext-tab.Panel-method-getTabBar'>    /**
440 </span>     * Returns the {@link Ext.tab.Bar} currently used in this TabPanel
441      * @return {Ext.TabBar} The TabBar
442      */
443     getTabBar: function() {
444         return this.tabBar;
445     },
446
447 <span id='Ext-tab.Panel-method-onAdd'>    /**
448 </span>     * @ignore
449      * Makes sure we have a Tab for each item added to the TabPanel
450      */
451     onAdd: function(item, index) {
452         var me = this;
453
454         item.tab = me.tabBar.insert(index, {
455             xtype: 'tab',
456             card: item,
457             disabled: item.disabled,
458             closable: item.closable,
459             hidden: item.hidden,
460             tabBar: me.tabBar
461         });
462         
463         item.on({
464             scope : me,
465             enable: me.onItemEnable,
466             disable: me.onItemDisable,
467             beforeshow: me.onItemBeforeShow,
468             iconchange: me.onItemIconChange,
469             titlechange: me.onItemTitleChange
470         });
471
472         if (item.isPanel) {
473             if (me.removePanelHeader) {
474                 item.preventHeader = true;
475                 if (item.rendered) {
476                     item.updateHeader();
477                 }
478             }
479             if (item.isPanel &amp;&amp; me.border) {
480                 item.setBorder(false);
481             }
482         }
483
484         // ensure that there is at least one active tab
485         if (this.rendered &amp;&amp; me.items.getCount() === 1) {
486             me.setActiveTab(0);
487         }
488     },
489     
490 <span id='Ext-tab.Panel-method-onItemEnable'>    /**
491 </span>     * @private
492      * Enable corresponding tab when item is enabled.
493      */
494     onItemEnable: function(item){
495         item.tab.enable();
496     },
497
498 <span id='Ext-tab.Panel-method-onItemDisable'>    /**
499 </span>     * @private
500      * Disable corresponding tab when item is enabled.
501      */    
502     onItemDisable: function(item){
503         item.tab.disable();
504     },
505     
506 <span id='Ext-tab.Panel-method-onItemBeforeShow'>    /**
507 </span>     * @private
508      * Sets activeTab before item is shown.
509      */
510     onItemBeforeShow: function(item) {
511         if (item !== this.activeTab) {
512             this.setActiveTab(item);
513             return false;
514         }    
515     },
516     
517 <span id='Ext-tab.Panel-method-onItemIconChange'>    /**
518 </span>     * @private
519      * Update the tab iconCls when panel iconCls has been set or changed.
520      */
521     onItemIconChange: function(item, newIconCls) {
522         item.tab.setIconCls(newIconCls);
523         this.getTabBar().doLayout();
524     },
525     
526 <span id='Ext-tab.Panel-method-onItemTitleChange'>    /**
527 </span>     * @private
528      * Update the tab title when panel title has been set or changed.
529      */
530     onItemTitleChange: function(item, newTitle) {
531         item.tab.setText(newTitle);
532         this.getTabBar().doLayout();
533     },
534
535
536 <span id='Ext-tab.Panel-method-doRemove'>    /**
537 </span>     * @ignore
538      * If we're removing the currently active tab, activate the nearest one. The item is removed when we call super,
539      * so we can do preprocessing before then to find the card's index
540      */
541     doRemove: function(item, autoDestroy) {
542         var me = this,
543             items = me.items,
544 <span id='Ext-tab.Panel-property-hasItemsLeft'>            /**
545 </span>             * At this point the item hasn't been removed from the items collection.
546              * As such, if we want to check if there are no more tabs left, we have to
547              * check for one, as opposed to 0.
548              */
549             hasItemsLeft = items.getCount() &gt; 1;
550
551         if (me.destroying || !hasItemsLeft) {
552             me.activeTab = null;
553         } else if (item === me.activeTab) {
554              me.setActiveTab(item.next() || items.getAt(0)); 
555         }
556         me.callParent(arguments);
557
558         // Remove the two references
559         delete item.tab.card;
560         delete item.tab;
561     },
562
563 <span id='Ext-tab.Panel-method-onRemove'>    /**
564 </span>     * @ignore
565      * Makes sure we remove the corresponding Tab when an item is removed
566      */
567     onRemove: function(item, autoDestroy) {
568         var me = this;
569         
570         item.un({
571             scope : me,
572             enable: me.onItemEnable,
573             disable: me.onItemDisable,
574             beforeshow: me.onItemBeforeShow
575         });
576         if (!me.destroying &amp;&amp; item.tab.ownerCt == me.tabBar) {
577             me.tabBar.remove(item.tab);
578         }
579     }
580 });
581 </pre></pre></body></html>