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