ExtJS 4.1“悬停按钮"延期问题 [英] ExtJS 4.1 "HoverButton" extension issue

查看:12
本文介绍了ExtJS 4.1“悬停按钮"延期问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发 Ext.Button 的扩展,它可以在鼠标悬停/鼠标移出时显示/隐藏按钮的菜单.它对于按钮的直接子菜单非常有效,但是我遇到了一个问题,让它在任何二级/三级/等菜单中都能正常运行.

I am working on an extension of Ext.Button that enables the showing/hiding of a button's menu on mouseover/mouseout. It is working perfectly for the button's immediate child menu, however I am running into an issue with having it behave properly for any secondary/tertiary/ect menus.

现在,当用户移动到包含菜单的顶部菜单中的项目时,它将打开菜单,用户可以毫无问题地将光标移入其中,一切都将保持打开状态.如果用户随后将光标移出二级菜单进入开放空间,则所有菜单都将关闭,这也是正确的.但是,有时如果用户移动到二级菜单,然后返回其父菜单,所有菜单都会关闭,这不是应该发生的情况,至少光标现在所在的父菜单应该保持打开状态.

Right now, when the user moves over am item in the top menu that contains a menu, it will open the menu and the user can move the cursor into it with no problems, everything will stay open. If the user then moves the cursor out of the secondary menu into open space, all menus will close which is correct as well. BUT, sometimes if a user moves into a secondary menu, and then back into its parent menu, all the menus will close, which isn't what should happen, at the very least that parent menu that the cursor is now over should remain open.

从我最初的调试来看,事件的触发方式及其时间似乎是一个问题.从子菜单移回父菜单时,父菜单的 mouseenter 事件似乎不会触发.其次,在我看来,菜单鼠标悬停事件的触发不够可靠或不够频繁,无法在子菜单上的 mouseleave 事件触发后取消延迟隐藏任务.

From my initial debugging it looks to be an issue with how the events are firing, and their timing. It appears that the mouseenter event for a parent menu does not fire when moving from a child menu back into the parent menu. And secondly it looks to me like the the menu mouseover event does not fire reliably enough or often enough for it to cancel the delayed hide task after a mouseleave event on a child menu has fired.

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

这是代码,它有什么根本性的错误吗?

And here's the code, does anything fundamentally wrong with it stand out?

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

推荐答案

我一直在做一些类似的事情,并在查看了 http://www.quirksmode.org/dom/events/mouseover.html

I've been doing something a bit similar and I've solved the problem after taking a peek at http://www.quirksmode.org/dom/events/mouseover.html

似乎 DOM 的事件顺序应该是 mouseover -> mouseenter -> mouseout -> mouseleave 这意味着有时会在设置 delay() 之前调用 cancel().为了解决这个问题,我将最后输入的内容保留在变量中:

It seems that DOM's event order should be mouseover -> mouseenter -> mouseout -> mouseleave which means that sometimes the cancel() will be called before the delay() is set. To solve the problem I keep the last entered in a variable:

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

希望能帮到你!

这篇关于ExtJS 4.1“悬停按钮"延期问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆