我们有自定义上下文菜单,可以在右键单击时替换浏览器菜单。我们希望能够以与浏览器隐藏默认上下文菜单相同的方式中止(隐藏)上下文菜单 - 单击菜单外的任何位置未注册为单击。该解决方案应该适用于绑定事件和默认浏览器操作,但不会妨碍其他事件的能力,即。 hover
来自解雇。
示例:
在Firefox中,右键单击此页面以打开上下文菜单。将鼠标悬停在
上Questions-Tags-Users-Badges-Unanswered
位于此页面顶部。即使上下文菜单已打开,仍会出现突出显示。现在,单击此页面上的文本区域,如顶部的搜索框。上下文菜单将隐藏,但光标不会聚焦文本框(除非您在关闭菜单时再次单击它)。
我们如何在JavaScript中模拟此行为?
我们考虑的拒绝选项:
在整个页面上使用透明div。问题:这可以捕获任何地方的点击次数,但会中断悬停事件并悬停css。
在每个点击处理程序中检查上下文菜单打开变量,并为所有链接分配处理程序,并输入元素以检测上下文菜单打开状态,这将关闭上下文菜单,取消设置打开状态并防止处理程序默认。问题:非常草率的代码和维护噩梦。
答案 0 :(得分:1)
考虑被拒绝的选项#2的变体,其中文档上有一个事件监听器。
document.addEventListener('click', function (e) {
if (contextMenuOpen) {
e.preventDefault();
e.stopPropagation();
}
}, true);
有关true
的更多信息,请查看useCapture
和event flow。
答案 1 :(得分:0)
Guest
在事件捕获的正确轨道上,但解决方案有一些小问题。这是一个更强大的解决方案,可以解决以下问题:
为此,您需要两个捕获事件处理程序:
document.addEventListener('focus', function(e){eDocumentFocusCapture(e)}, true);
document.addEventListener('click', function(e){eDocumentClickCapture(e)}, true);
// If the context menu is open, ignore the focus event.
eDocumentFocusCapture = function(e){
if(RowContextMenuIsOpen){
console.log('focus event sees the menu open: cancel focus, but leave menu be. Click will take care of closing it.');
e.stopImmediatePropagation();
e.preventDefault();
e.target.blur(); // tell the clicked element it is not focused, otherwise you can't focus it until you click elsewhere first!
}
}
eDocumentClickCapture = function(e){
// A right click fires immediatly after context menu is fired,
// we prevent the menu from closing immediately by skipping one right click event
if(RowContextMenuWasJustOpened===true && e.button===2){
console.log('right click self bypass');
RowContextMenuWasJustOpened=false;
return;
}
if(this.protected.RowContextMenuIsOpen){
console.log('click event sees menu open, I will close it.');
this.HideRowContextMenu();
e.stopImmediatePropagation();
e.preventDefault();
}
}