Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / examples / ux / TabCloseMenu.js
index 72a9649..a896450 100644 (file)
-/*!
- * Ext JS Library 3.0.3
- * Copyright(c) 2006-2009 Ext JS, LLC
- * licensing@extjs.com
- * http://www.extjs.com/license
+/**
+ * @class Ext.ux.TabCloseMenu
+ * Plugin (ptype = 'tabclosemenu') for adding a close context menu to tabs. Note that the menu respects
+ * the closable configuration on the tab. As such, commands like remove others and remove all will not
+ * remove items that are not closable.
+ *
+ * @constructor
+ * @param {Object} config The configuration options
+ * @ptype tabclosemenu
  */
-/**\r
- * @class Ext.ux.TabCloseMenu\r
- * @extends Object \r
- * Plugin (ptype = 'tabclosemenu') for adding a close context menu to tabs.\r
- * \r
- * @ptype tabclosemenu\r
- */\r
-Ext.ux.TabCloseMenu = function(){\r
-    var tabs, menu, ctxItem;\r
-    this.init = function(tp){\r
-        tabs = tp;\r
-        tabs.on('contextmenu', onContextMenu);\r
-    };\r
-\r
-    function onContextMenu(ts, item, e){\r
-        if(!menu){ // create context menu on first right click\r
-            menu = new Ext.menu.Menu({            \r
-            items: [{\r
-                id: tabs.id + '-close',\r
-                text: 'Close Tab',\r
-                handler : function(){\r
-                    tabs.remove(ctxItem);\r
-                }\r
-            },{\r
-                id: tabs.id + '-close-others',\r
-                text: 'Close Other Tabs',\r
-                handler : function(){\r
-                    tabs.items.each(function(item){\r
-                        if(item.closable && item != ctxItem){\r
-                            tabs.remove(item);\r
-                        }\r
-                    });\r
-                }\r
-            }]});\r
-        }\r
-        ctxItem = item;\r
-        var items = menu.items;\r
-        items.get(tabs.id + '-close').setDisabled(!item.closable);\r
-        var disableOthers = true;\r
-        tabs.items.each(function(){\r
-            if(this != item && this.closable){\r
-                disableOthers = false;\r
-                return false;\r
-            }\r
-        });\r
-        items.get(tabs.id + '-close-others').setDisabled(disableOthers);\r
-       e.stopEvent();\r
-        menu.showAt(e.getPoint());\r
-    }\r
-};\r
-\r
-Ext.preg('tabclosemenu', Ext.ux.TabCloseMenu);\r
+Ext.define('Ext.tab.TabCloseMenu', {
+    alias: 'plugin.tabclosemenu',
+    alternateClassName: 'Ext.ux.TabCloseMenu',
+
+    mixins: {
+        observable: 'Ext.util.Observable'
+    },
+
+    /**
+     * @cfg {String} closeTabText
+     * The text for closing the current tab. Defaults to <tt>'Close Tab'</tt>.
+     */
+    closeTabText: 'Close Tab',
+
+    /**
+     * @cfg {Boolean} showCloseOthers
+     * Indicates whether to show the 'Close Others' option. Defaults to <tt>true</tt>.
+     */
+    showCloseOthers: true,
+
+    /**
+     * @cfg {String} closeOtherTabsText
+     * The text for closing all tabs except the current one. Defaults to <tt>'Close Other Tabs'</tt>.
+     */
+    closeOthersTabsText: 'Close Other Tabs',
+
+    /**
+     * @cfg {Boolean} showCloseAll
+     * Indicates whether to show the 'Close All' option. Defaults to <tt>true</tt>.
+     */
+    showCloseAll: true,
+
+    /**
+     * @cfg {String} closeAllTabsText
+     * <p>The text for closing all tabs. Defaults to <tt>'Close All Tabs'</tt>.
+     */
+    closeAllTabsText: 'Close All Tabs',
+
+    /**
+     * @cfg {Array} extraItemsHead
+     * An array of additional context menu items to add to the front of the context menu.
+     */
+    extraItemsHead: null,
+
+    /**
+     * @cfg {Array} extraItemsTail
+     * An array of additional context menu items to add to the end of the context menu.
+     */
+    extraItemsTail: null,
+
+    //public
+    constructor: function (config) {
+        this.addEvents(
+            'aftermenu',
+            'beforemenu');
+
+        this.mixins.observable.constructor.call(this, config);
+    },
+
+    init : function(tabpanel){
+        this.tabPanel = tabpanel;
+        this.tabBar = tabpanel.down("tabbar");
+
+        this.mon(this.tabPanel, {
+            scope: this,
+            afterlayout: this.onAfterLayout,
+            single: true
+        });
+    },
+
+    onAfterLayout: function() {
+        this.mon(this.tabBar.el, {
+            scope: this,
+            contextmenu: this.onContextMenu,
+            delegate: 'div.x-tab'
+        });
+    },
+
+    onBeforeDestroy : function(){
+        Ext.destroy(this.menu);
+        this.callParent(arguments);
+    },
+
+    // private
+    onContextMenu : function(event, target){
+        var me = this,
+            menu = me.createMenu(),
+            disableAll = true,
+            disableOthers = true,
+            tab = me.tabBar.getChildByElement(target),
+            index = me.tabBar.items.indexOf(tab);
+
+        me.item = me.tabPanel.getComponent(index);
+        menu.child('*[text="' + me.closeTabText + '"]').setDisabled(!me.item.closable);
+
+        if (me.showCloseAll || me.showCloseOthers) {
+            me.tabPanel.items.each(function(item) {
+                if (item.closable) {
+                    disableAll = false;
+                    if (item != me.item) {
+                        disableOthers = false;
+                        return false;
+                    }
+                }
+                return true;
+            });
+
+            if (me.showCloseAll) {
+                menu.child('*[text="' + me.closeAllTabsText + '"]').setDisabled(disableAll);
+            }
+
+            if (me.showCloseOthers) {
+                menu.child('*[text="' + me.closeOthersTabsText + '"]').setDisabled(disableOthers);
+            }
+        }
+
+        event.preventDefault();
+        me.fireEvent('beforemenu', menu, me.item, me);
+
+        menu.showAt(event.getXY());
+    },
+
+    createMenu : function() {
+        var me = this;
+
+        if (!me.menu) {
+            var items = [{
+                text: me.closeTabText,
+                scope: me,
+                handler: me.onClose
+            }];
+
+            if (me.showCloseAll || me.showCloseOthers) {
+                items.push('-');
+            }
+
+            if (me.showCloseOthers) {
+                items.push({
+                    text: me.closeOthersTabsText,
+                    scope: me,
+                    handler: me.onCloseOthers
+                });
+            }
+
+            if (me.showCloseAll) {
+                items.push({
+                    text: me.closeAllTabsText,
+                    scope: me,
+                    handler: me.onCloseAll
+                });
+            }
+
+            if (me.extraItemsHead) {
+                items = me.extraItemsHead.concat(items);
+            }
+
+            if (me.extraItemsTail) {
+                items = items.concat(me.extraItemsTail);
+            }
+
+            me.menu = Ext.create('Ext.menu.Menu', {
+                items: items,
+                listeners: {
+                    hide: me.onHideMenu,
+                    scope: me
+                }
+            });
+        }
+
+        return me.menu;
+    },
+
+    onHideMenu: function () {
+        var me = this;
+
+        me.item = null;
+        me.fireEvent('aftermenu', me.menu, me);
+    },
+
+    onClose : function(){
+        this.tabPanel.remove(this.item);
+    },
+
+    onCloseOthers : function(){
+        this.doClose(true);
+    },
+
+    onCloseAll : function(){
+        this.doClose(false);
+    },
+
+    doClose : function(excludeActive){
+        var items = [];
+
+        this.tabPanel.items.each(function(item){
+            if(item.closable){
+                if(!excludeActive || item != this.item){
+                    items.push(item);
+                }
+            }
+        }, this);
+
+        Ext.each(items, function(item){
+            this.tabPanel.remove(item);
+        }, this);
+    }
+});