Extjs多标签关闭,支持关闭左侧和右侧标签。
基于官方给出标签关闭方法修改,首先先上效果图。

/*** Plugin 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.*/
Ext.define('Ext.ux.TabCloseMenu', {alias: 'plugin.tabclosemenu',mixins: {observable: 'Ext.util.Observable'},/*** @cfg {String} closeTabText* The text for closing the current tab.*/closeTabText: 'Close Tab',/*** @cfg {Boolean} showCloseOthers* Indicates whether to show the 'Close Others' option.*/showCloseOthers: true,/*** @cfg {String} closeOthersTabsText* The text for closing all tabs except the current one.*/closeOthersTabsText: 'Close Other Tabs',/*** @cfg {Boolean} showCloseAll* Indicates whether to show the 'Close All' option.*/showCloseAll: true,/*** @cfg {String} closeAllTabsText* The text for closing all tabs.*/closeAllTabsText: 'Close All Tabs',/*** 关闭左侧* @type Boolean*/showCloseLeft:true,/*** 关闭左侧* @type String*/closeLeftText:'Close Left Tabs',/*** 关闭右侧* @type Boolean*/showCloseRight:true,/*** 关闭左侧* @type String*/closeRightText:'Close Right 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,//publicconstructor: 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: '.x-tab'});},onBeforeDestroy : function(){Ext.destroy(this.menu);this.callParent(arguments);},// privateonContextMenu : 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);}}if(me.showCloseLeft){var items=new Array();me.tabPanel.items.each(function(item) {items.push(item);});var disableLeft=false;//设置左侧起第一个关闭左侧按钮不可使用if(items[0].getId()==me.item.getId()){disableLeft = true;}if (me.showCloseLeft) {menu.child('*[text="' + me.closeLeftText + '"]').setDisabled(disableLeft);}}if(me.showCloseRight){var items=new Array();me.tabPanel.items.each(function(item) {items.push(item);});var disableRight=false;if(items[items.length-1].getId()==me.item.getId()){disableRight = true;}if (me.showCloseRight) {menu.child('*[text="' + me.closeRightText + '"]').setDisabled(disableRight);}}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|| me.showCloseLeft || me.showCloseRight) {items.push('-');}if (me.showCloseLeft) {items.push({text: me.closeLeftText,scope: me,handler: me.onCloseLeft});}if (me.showCloseRight) {items.push({text: me.closeRightText,scope: me,handler: me.onCloseRight});}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);},onCloseLeft : function(){this.doCloseLeft();},onCloseRight : function(){this.doCloseRight();},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);},doCloseLeft : function(){var items=[];this.tabPanel.items.each(function(item){if(item.closable){if(item != this.item){items.push(item);}if(item == this.item){return false;}}}, this);Ext.each(items, function(item){this.tabPanel.remove(item);}, this);},doCloseRight : function(){var items=[];this.tabPanel.items.each(function(item){items.push(item);}, this);var result= new Array(); var count="";for(var i = 0 ;i <items.length;i++){if(items[i].getId() == this.item.getId()){count=i;}}for(var i = (count+1) ;i <items.length;i++){result.push(items[i]);}Ext.each(result, function(item){this.tabPanel.remove(item);}, this);}
});
调用方法:
plugins: Ext.create('Ext.ux.TabCloseMenu', {closeTabText: '关闭当前',closeOthersTabsText: '关闭其它',closeAllTabsText: '关闭所有',closeLeftText:'关闭左侧',closeRightText:'关闭右侧'})