TabCloseMenu.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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. mixins: {
  15. observable: 'Ext.util.Observable'
  16. },
  17. /**
  18. * @cfg {String} closeTabText
  19. * The text for closing the current tab. Defaults to <tt>'Close Tab'</tt>.
  20. */
  21. closeTabText: 'Close Tab',
  22. /**
  23. * @cfg {Boolean} showCloseOthers
  24. * Indicates whether to show the 'Close Others' option. Defaults to <tt>true</tt>.
  25. */
  26. showCloseOthers: true,
  27. /**
  28. * @cfg {String} closeOtherTabsText
  29. * The text for closing all tabs except the current one. Defaults to <tt>'Close Other Tabs'</tt>.
  30. */
  31. closeOthersTabsText: 'Close Other Tabs',
  32. /**
  33. * @cfg {Boolean} showCloseAll
  34. * Indicates whether to show the 'Close All' option. Defaults to <tt>true</tt>.
  35. */
  36. showCloseAll: true,
  37. /**
  38. * @cfg {String} closeAllTabsText
  39. * <p>The text for closing all tabs. Defaults to <tt>'Close All Tabs'</tt>.
  40. */
  41. closeAllTabsText: 'Close All Tabs',
  42. /**
  43. * @cfg {Array} extraItemsHead
  44. * An array of additional context menu items to add to the front of the context menu.
  45. */
  46. extraItemsHead: null,
  47. /**
  48. * @cfg {Array} extraItemsTail
  49. * An array of additional context menu items to add to the end of the context menu.
  50. */
  51. extraItemsTail: null,
  52. //public
  53. constructor: function (config) {
  54. this.addEvents(
  55. 'aftermenu',
  56. 'beforemenu');
  57. this.mixins.observable.constructor.call(this, config);
  58. },
  59. init : function(tabpanel){
  60. this.tabPanel = tabpanel;
  61. this.tabBar = tabpanel.down("tabbar");
  62. this.mon(this.tabPanel, {
  63. scope: this,
  64. afterlayout: this.onAfterLayout,
  65. single: true
  66. });
  67. },
  68. onAfterLayout: function() {
  69. this.mon(this.tabBar.el, {
  70. scope: this,
  71. contextmenu: this.onContextMenu,
  72. delegate: 'div.x-tab'
  73. });
  74. },
  75. onBeforeDestroy : function(){
  76. Ext.destroy(this.menu);
  77. this.callParent(arguments);
  78. },
  79. // private
  80. onContextMenu : function(event, target){
  81. var me = this,
  82. menu = me.createMenu(),
  83. disableAll = true,
  84. disableOthers = true,
  85. tab = me.tabBar.getChildByElement(target),
  86. index = me.tabBar.items.indexOf(tab);
  87. me.item = me.tabPanel.getComponent(index);
  88. if(index !== me.tabBar.items.getCount() - 1){
  89. me.tabPanel.setActiveTab(me.item);
  90. menu.child('*[text="' + me.closeTabText + '"]').setDisabled(!me.item.closable);
  91. if (me.showCloseAll || me.showCloseOthers) {
  92. me.tabPanel.items.each(function(item) {
  93. if (item.closable) {
  94. disableAll = false;
  95. if (item != me.item) {
  96. disableOthers = false;
  97. return false;
  98. }
  99. }
  100. return true;
  101. });
  102. if (me.showCloseAll) {
  103. menu.child('*[text="' + me.closeAllTabsText + '"]').setDisabled(disableAll);
  104. }
  105. if (me.showCloseOthers) {
  106. menu.child('*[text="' + me.closeOthersTabsText + '"]').setDisabled(disableOthers);
  107. }
  108. }
  109. event.preventDefault();
  110. me.fireEvent('beforemenu', menu, me.item, me);
  111. menu.showAt(event.getXY());
  112. }
  113. },
  114. createMenu : function() {
  115. var me = this;
  116. if (!me.menu) {
  117. var items = [];
  118. if(me.beforeMenu){
  119. items.push(me.beforeMenu);
  120. items.push('-');
  121. }
  122. items.push({
  123. text: me.closeTabText,
  124. scope: me,
  125. handler: me.onClose
  126. });
  127. //if (me.showCloseAll || me.showCloseOthers) {
  128. // items.push('-');
  129. //}
  130. if (me.showCloseOthers) {
  131. items.push({
  132. text: me.closeOthersTabsText,
  133. scope: me,
  134. handler: me.onCloseOthers
  135. });
  136. }
  137. if (me.showCloseAll) {
  138. items.push({
  139. text: me.closeAllTabsText,
  140. scope: me,
  141. handler: me.onCloseAll
  142. });
  143. }
  144. if (me.extraItemsHead) {
  145. items = me.extraItemsHead.concat(items);
  146. }
  147. if (me.extraItemsTail) {
  148. items = items.concat(me.extraItemsTail);
  149. }
  150. me.menu = Ext.create('Ext.menu.Menu', {
  151. items: items,
  152. width : 157,
  153. listeners: {
  154. hide: me.onHideMenu,
  155. scope: me
  156. }
  157. });
  158. }
  159. return me.menu;
  160. },
  161. onHideMenu: function () {
  162. var me = this;
  163. me.item = null;
  164. me.fireEvent('aftermenu', me.menu, me);
  165. },
  166. onClose : function(){
  167. this.tabPanel.remove(this.item);
  168. },
  169. onCloseOthers : function(){
  170. this.doClose(true);
  171. },
  172. onCloseAll : function(){
  173. this.doClose(false);
  174. },
  175. doClose : function(excludeActive){
  176. var items = [];
  177. this.tabPanel.items.each(function(item){
  178. if(item.closable){
  179. if(!excludeActive || item != this.item){
  180. items.push(item);
  181. }
  182. }
  183. }, this);
  184. Ext.each(items, function(item){
  185. this.tabPanel.remove(item);
  186. }, this);
  187. }
  188. });