PDA

View Full Version : Closing a menu (and any number of sub menus) on mouseout



BulletzBill
21 Dec 2011, 12:22 PM
I am using an Ext.Button extension found here (http://www.lustforge.com/2011/07/06/open-extjs-menu-on-mouseover/) (4.0 version is in comments) to allow a button's menu to open on mouseover, and close on mouseout. I attempted to modify the extension to make the button's menu close on mouseout even if a sub menu has been opened (the original extension would not auto-close in this case, you had to click the button again, or click elsewhere on the document). But, after my modifications, the menu(s) will close if you mouseout of the menu or any submenus like I want, but will also close the menus if you mouseover a submenu, then move the cursor back to the parent menu, which I obviously don't want.

Here is my version of the extension. I may just be missing something obvious, or might have gone in the wrong direction altogether:

Test Case: http://jsfiddle.net/2GGYr/


Ext.define('Ext.HoverButton', {
extend: 'Ext.Button',
alias: 'widget.hoverButton',

// hide task properties and helpers
hideTask: null,
isOver: false,
hideTaskMs: 250, // timeout in ms
hideTaskFn: function () {
if (this.isOver) {
if(this.hideTask !== null) { this.hideTask.cancel(); }
return;
}
if (this.hideTask !== null) {
this.hideTask.cancel();
}
this.hideTask = new Ext.util.DelayedTask(this.hideMenu, this);
this.hideTask.delay(this.hideTaskMs);
},

applyListeners : function(menu, cfg) {

Ext.apply(menu, cfg);

Ext.each(menu.items, function(item, idx, allItems){
if(item.menu) {
this.applyListeners(item.menu, cfg);
}
}, this);
},

// extend init props
initComponent: function () {

// add hide/show, if this is a button with menu
var config = {}, menuConfig = {}, me = this;
if (Ext.isDefined(this.initialConfig.menu)) {
config = {
listeners: {
mouseover: {
fn: function (b) {
this.isOver = true;
b.showMenu();
},
scope: me
},
mouseout: {
fn: function (b) {
this.isOver = false;
this.hideTaskFn();
},
scope: me
}
}
};
// add listeners to see if user is over extended menu list
menuConfig = {
listeners: {
// if mousing over menu list, disable timeout
mouseover: {
fn: function (b) {
// cancel hide if they went away and came back
if (this.hideTask !== null) {
this.hideTask.cancel();
this.hideTask = null;
}
},
scope: this
},
// on mousing out of menu list, resume timeout
mouseleave: {
fn: function (b) {
this.hideTaskFn();
},
scope: this
}
}
};

//apply mouseover/leave listeners to all submenus recursively
this.applyListeners(this.menu, menuConfig);
}

// apply config
Ext.apply(this, Ext.apply(this.initialConfig, config));
// call parent
Ext.HoverButton.superclass.initComponent.apply(this, arguments);
}
});