是否存在浏览器上下文菜单的关闭事件

时间:2012-10-09 14:06:39

标签: javascript jquery javascript-events contextmenu

我正在使用jQuery捕获contextmenu事件:

$(document.body).on("contextmenu", function(e){
    //do stuff here
});

到目前为止,这么好。现在我想在关闭时执行一些代码,但我似乎无法为此找到正确的解决方案。

使用类似下面的内容会捕获一些案例,但几乎不是全部:

$(document.body).on("contextmenu click", function(e){});

在以下情况下不会执行:

  • 浏览器失去焦点
  • 选择了contextmenu中的选项
  • 用户点击浏览器中不在页面上的任何位置

注意:我没有使用jQuery上下文菜单,我只是用它来捕捉事件。

2 个答案:

答案 0 :(得分:6)

以下代码可能会对您有所帮助。 jsfiddle

var isIntextMenuOpen ;
$(document).on("contextmenu", function(e){

    isIntextMenuOpen = true;
});
function hideContextmenu(e){
       if(isIntextMenuOpen ){
            console.log("contextmenu closed ");
       }

     isIntextMenuOpen = false;
}
$(window).blur(hideContextmenu);

$(document).click(hideContextmenu);

答案 1 :(得分:1)

我需要检测上下文菜单何时关闭,因此我想出了一个解决方案。

提琴:https://jsfiddle.net/kexp0nmd/1/

var premenuelem;

var TempContextMenuCloseHandler = function(e) {
console.log('closed!');
//console.log(e);
	window.removeEventListener('keyup', TempContextMenuCloseHandler, true);
	window.removeEventListener('mousedown', TempContextMenuCloseHandler, true);
	window.removeEventListener('focus', TempContextMenuCloseHandler, true);

	var focuselem = document.getElementById('tempfocus');
	if (focuselem === document.activeElement)  premenuelem.focus();
	focuselem.style.display = 'none';
};

var TempContextMenuHandler = function(e) {
console.log('open!');
//console.log(e);
	premenuelem = document.activeElement;

	var focuselem = document.getElementById('tempfocus');
	focuselem.style.display = 'block';
	focuselem.focus();

	window.addEventListener('keyup', TempContextMenuCloseHandler, true);
	window.addEventListener('mousedown', TempContextMenuCloseHandler, true);
	window.addEventListener('focus', TempContextMenuCloseHandler, true);
};

window.addEventListener('contextmenu', TempContextMenuHandler, true);
html, body { min-height: 100%; }
<textarea></textarea>

<div id="tempfocus" tabIndex="-1" style="left: 0; bottom: 0; height: 50px; width: 100%; background-color: #CCCCCC; display: none; position: fixed; outline: none;"></div>

截至2020年5月,经过测试和验证,可以在Edge,Firefox 76和Chrome 80上同时使用鼠标和键盘。移动/触摸支持未知。

此解决方案的关键方面是使用元素上带有tabIndex的元素。通过在上下文菜单出现之前显示焦点并将焦点移动到该元素(窃取焦点),将导致Edge和Chrome在用户稍后关闭上下文菜单时发送焦点更改事件。我将div的背景设为灰色,以便可以看到它-在生产中,将其设为透明背景,然后根据需要对其进行样式设置。

keyup处理程序在键盘关闭上下文菜单时捕获Escape / Enter键的释放。 mousedown处理程序仅在Firefox中捕获鼠标按下事件。

据我所知,无法确定用户选择了哪个选项,或者即使他们确实选择了选项,也无法确定。至少,它允许在所有主要浏览器中一致地检测上下文菜单的打开/关闭。

示例中的textarea只是为了给焦点处理提供其他玩法。

尽管此解决方案涉及临时的焦点窃取,但它是最干净的跨浏览器解决方案,直到浏览器供应商和W3C向DOM添加“ exitcontextmenu”事件或类似事件为止。

我遇到的一个小错误:显示上下文菜单并切换到另一个应用程序会关闭上下文菜单,但不会立即触发已关闭的事件。但是,切换回Web浏览器后,将触发事件并运行close处理程序。在窗口中添加“模糊”捕获可能会解决该问题,但随后我必须重新测试所有内容,并且可能会破坏某些内容(例如,打开上下文菜单时出现火灾模糊)。在极少数情况下可能不值得修复,并且处理程序仍会开火-明显地延迟了。