ExtJS的4.1“HoverButton”延长问题(ExtJS 4.1 “HoverButton”

2019-07-29 08:11发布

我的工作Ext.Button的延伸,使按钮的鼠标悬停/鼠标移出菜单的显示/隐藏。 这是可以正常使用的按钮的直接子菜单,但是我遇到了一个问题,与有它正确的行为对于任何二级/三级/ ECT菜单。

现在,当用户在移动时项目中包含一个菜单顶部的菜单,它会打开菜单,用户可以将光标移动到它,没有任何问题,一切都将保持开放。 然后,如果用户将光标移动了二级菜单进入空地,所有菜单将关闭这是正确的为好。 但有时如果用户移动到二级菜单,然后返回到其上级菜单,所有的菜单将关闭,这是不应该发生的事情,起码光标已经结束应该保持开放,该父菜单。

从我最初的调试它看起来是与事件是如何激发一个问题,他们的时间。 看来,从孩子的菜单搬回父菜单时父菜单MouseEnter事件不火。 其次,它看起来对我来说,在菜单鼠标悬停不会触发事件足够可靠或经常足以使它儿童菜单上mouseLeave事件后取消延迟隐藏任务已经解雇。

问题的演示: http://qs1724.pair.com/users/autod1nx/EMPLOYEE/BDAMI/hoverbutton/index.html

而这里的代码,做任何事情根本性的错误脱颖而出?

Ext.define('Ext.HoverButton', {    
    extend: 'Ext.Button',
    alias: 'widget.hoverButton',
    isOver: false,
    hideDelay: 250,
    showDelay: 200,

    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);
    },

    initComponent: function() {
        var config = {}, 
            menuConfig = {}, 
            me = this;

        me.delayedShowMenu = new Ext.util.DelayedTask(function() {
            if(!me.isOver) return;
            me.showMenu();
        }, this);

        me.delayedHideMenu = new Ext.util.DelayedTask(function() {
            if(me.isOver) return;
            me.hideMenu();
        });

        if(Ext.isDefined(this.initialConfig.menu)) {
            config = {
                listeners: {
                    mouseover: {
                        scope: me,
                        fn: function(b) {
                            me.isOver = true;
                            me.delayedShowMenu.delay(me.showDelay);
                        }
                    },
                    mouseout: {
                        scope: me,
                        fn: function(b) {
                            me.isOver = false;
                            me.delayedHideMenu.delay(me.hideDelay);
                        }
                    }
                }
            };

            menuConfig = {
                listeners: {
                    mouseover: {
                        scope: me,
                        fn: function(menu, item, e) {
                            me.delayedHideMenu.cancel();
                        }
                    },
                    mouseenter: {
                        scope: me,
                        fn: function(menu, e) {
                            me.delayedHideMenu.cancel();
                        }
                    },
                    mouseleave: {
                        scope: me,
                        fn: function(menu, e) {
                            me.delayedHideMenu.delay(me.hideDelay);
                        }
                    }
                }
            };


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

        Ext.apply(me, Ext.apply(me.initialConfig, config));
        Ext.HoverButton.superclass.initComponent.apply(me, arguments);
    }
});

Answer 1:

我一直在做的东西有点类似,我已经采取了偷看后解决了问题http://www.quirksmode.org/dom/events/mouseover.html

看来,DOM的事件顺序应该是鼠标悬停 - >的mouseenter - >鼠标移开 - >鼠标离开这意味着有时取消()延迟之前将被称为()设置。 为了解决我把最后一个变量输入问题:

mouseenter: {
 scope: me,
 fn: function(menu, e) {
  presentlyInside = menu; /* << */
  me.delayedHideMenu.cancel();
 }
},
mouseleave: {
 scope: me,
 fn: function(menu, e) {
  if(presentlyInside==menu) /* << */
    me.delayedHideMenu.delay(me.hideDelay);
 }
}

希望能帮助到你!



Answer 2:

我发现这一个工程,也更简单。

Ext.define('Ext.HoverButton', {
extend    : 'Ext.Button',
alias     : 'widget.hoverButton',
listeners : {
        mouseover : function() {
            this.showMenu();
        },
        menushow : function() {
            this.mouseLeaveMonitor = this.menu.el.monitorMouseLeave(100, this.hideMenu, this);
        },
        destroy : function(combo) {
            combo.menu.el.un(combo.mouseLeaveMonitor);
        }
    }
});


文章来源: ExtJS 4.1 “HoverButton” extension issue