Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / examples / ux / TabCloseMenu.js
1 /**
2  * @class Ext.ux.TabCloseMenu
3  * Plugin (ptype = 'tabclosemenu') for adding a close context menu to tabs. Note that the menu respects
4  * the closable configuration on the tab. As such, commands like remove others and remove all will not
5  * remove items that are not closable.
6  *
7  * @constructor
8  * @param {Object} config The configuration options
9  * @ptype tabclosemenu
10  */
11 Ext.define('Ext.tab.TabCloseMenu', {
12     alias: 'plugin.tabclosemenu',
13     alternateClassName: 'Ext.ux.TabCloseMenu',
14
15     mixins: {
16         observable: 'Ext.util.Observable'
17     },
18
19     /**
20      * @cfg {String} closeTabText
21      * The text for closing the current tab. Defaults to <tt>'Close Tab'</tt>.
22      */
23     closeTabText: 'Close Tab',
24
25     /**
26      * @cfg {Boolean} showCloseOthers
27      * Indicates whether to show the 'Close Others' option. Defaults to <tt>true</tt>.
28      */
29     showCloseOthers: true,
30
31     /**
32      * @cfg {String} closeOtherTabsText
33      * The text for closing all tabs except the current one. Defaults to <tt>'Close Other Tabs'</tt>.
34      */
35     closeOthersTabsText: 'Close Other Tabs',
36
37     /**
38      * @cfg {Boolean} showCloseAll
39      * Indicates whether to show the 'Close All' option. Defaults to <tt>true</tt>.
40      */
41     showCloseAll: true,
42
43     /**
44      * @cfg {String} closeAllTabsText
45      * <p>The text for closing all tabs. Defaults to <tt>'Close All Tabs'</tt>.
46      */
47     closeAllTabsText: 'Close All Tabs',
48
49     /**
50      * @cfg {Array} extraItemsHead
51      * An array of additional context menu items to add to the front of the context menu.
52      */
53     extraItemsHead: null,
54
55     /**
56      * @cfg {Array} extraItemsTail
57      * An array of additional context menu items to add to the end of the context menu.
58      */
59     extraItemsTail: null,
60
61     //public
62     constructor: function (config) {
63         this.addEvents(
64             'aftermenu',
65             'beforemenu');
66
67         this.mixins.observable.constructor.call(this, config);
68     },
69
70     init : function(tabpanel){
71         this.tabPanel = tabpanel;
72         this.tabBar = tabpanel.down("tabbar");
73
74         this.mon(this.tabPanel, {
75             scope: this,
76             afterlayout: this.onAfterLayout,
77             single: true
78         });
79     },
80
81     onAfterLayout: function() {
82         this.mon(this.tabBar.el, {
83             scope: this,
84             contextmenu: this.onContextMenu,
85             delegate: 'div.x-tab'
86         });
87     },
88
89     onBeforeDestroy : function(){
90         Ext.destroy(this.menu);
91         this.callParent(arguments);
92     },
93
94     // private
95     onContextMenu : function(event, target){
96         var me = this,
97             menu = me.createMenu(),
98             disableAll = true,
99             disableOthers = true,
100             tab = me.tabBar.getChildByElement(target),
101             index = me.tabBar.items.indexOf(tab);
102
103         me.item = me.tabPanel.getComponent(index);
104         menu.child('*[text="' + me.closeTabText + '"]').setDisabled(!me.item.closable);
105
106         if (me.showCloseAll || me.showCloseOthers) {
107             me.tabPanel.items.each(function(item) {
108                 if (item.closable) {
109                     disableAll = false;
110                     if (item != me.item) {
111                         disableOthers = false;
112                         return false;
113                     }
114                 }
115                 return true;
116             });
117
118             if (me.showCloseAll) {
119                 menu.child('*[text="' + me.closeAllTabsText + '"]').setDisabled(disableAll);
120             }
121
122             if (me.showCloseOthers) {
123                 menu.child('*[text="' + me.closeOthersTabsText + '"]').setDisabled(disableOthers);
124             }
125         }
126
127         event.preventDefault();
128         me.fireEvent('beforemenu', menu, me.item, me);
129
130         menu.showAt(event.getXY());
131     },
132
133     createMenu : function() {
134         var me = this;
135
136         if (!me.menu) {
137             var items = [{
138                 text: me.closeTabText,
139                 scope: me,
140                 handler: me.onClose
141             }];
142
143             if (me.showCloseAll || me.showCloseOthers) {
144                 items.push('-');
145             }
146
147             if (me.showCloseOthers) {
148                 items.push({
149                     text: me.closeOthersTabsText,
150                     scope: me,
151                     handler: me.onCloseOthers
152                 });
153             }
154
155             if (me.showCloseAll) {
156                 items.push({
157                     text: me.closeAllTabsText,
158                     scope: me,
159                     handler: me.onCloseAll
160                 });
161             }
162
163             if (me.extraItemsHead) {
164                 items = me.extraItemsHead.concat(items);
165             }
166
167             if (me.extraItemsTail) {
168                 items = items.concat(me.extraItemsTail);
169             }
170
171             me.menu = Ext.create('Ext.menu.Menu', {
172                 items: items,
173                 listeners: {
174                     hide: me.onHideMenu,
175                     scope: me
176                 }
177             });
178         }
179
180         return me.menu;
181     },
182
183     onHideMenu: function () {
184         var me = this;
185
186         me.item = null;
187         me.fireEvent('aftermenu', me.menu, me);
188     },
189
190     onClose : function(){
191         this.tabPanel.remove(this.item);
192     },
193
194     onCloseOthers : function(){
195         this.doClose(true);
196     },
197
198     onCloseAll : function(){
199         this.doClose(false);
200     },
201
202     doClose : function(excludeActive){
203         var items = [];
204
205         this.tabPanel.items.each(function(item){
206             if(item.closable){
207                 if(!excludeActive || item != this.item){
208                     items.push(item);
209                 }
210             }
211         }, this);
212
213         Ext.each(items, function(item){
214             this.tabPanel.remove(item);
215         }, this);
216     }
217 });