Safari:防止在contextmenu事件上设置默认值会触发后续的click事件

时间:2018-12-06 22:02:41

标签: javascript javascript-events safari event-handling

好的,这是一些奇怪的Safari行为。

摘要:

假设我要禁用网页上的上下文菜单。但是,当用户右键单击蓝色正方形时,我要运行openSpecialMenu()。为了匹配此所需的行为,我有:

  1. 文档上的contextmenu事件监听器,调用event.preventDefault()。这样可以防止出现上下文菜单。
  2. 蓝色方块上的contextmenu事件监听器,调用openSpecialMenu()

现在,假设我的特殊菜单会像大多数弹出菜单一样在click事件上自行关闭。

我在以下代码段中重新创建了此场景:

document.addEventListener('contextmenu', function(event) {
  event.preventDefault();
  console.log('document contextmenu prevented');
});

document.getElementById("thing").addEventListener('contextmenu', function(event) {
  console.log('blue square contextmenu');
  
  // This opens my special menu.
  // openSpecialMenu();
});

document.getElementById("thing").addEventListener('click', function(event) {
  console.log('blue square click');
  
  // My special menu closes if this is run.
});

document.getElementById("thing").addEventListener('mouseup', function(event) {
  console.log('blue square mouseup');
  
  // My special menu closes if this is run.
});
#thing {
  height: 100px;
  width: 100px;
  background: blue;
}
<div id="thing"></div>

在Safari上浏览一下。使用CTRL +单击,在控制台打开的情况下,在Codepen输出中的蓝色方块上“右键单击”。请注意,事件是按以下顺序触发的:

blue square contextmenu
document contextmenu prevented
blue square click

这看起来似乎还不错...除了这个blue square click事件。您可能想知道为什么在按住CTRL的情况下在Safari上触发了click事件?contextmenu事件不应该那样吃吗?

现在注释掉event.preventDefault(),然后重试。请注意,这次没有显示blue square click控制台日志。发生什么事了?

我愚蠢的直观理论:

使用contextmenu阻止preventDefault事件会使Safari将事件视为click事件。 AFAIK,这仅是Safari的行为,无法在Chrome,Edge,FF上进行复制。

为什么会出现问题?

如果在这里触发了click个事件,那么我的特殊菜单将在打开后立即关闭。我的函数openSpecialMenu()被正确调用,但是之后立即触发click事件,并且特殊菜单再次关闭。

我的问题:

  1. 这是Safari的已知错误吗?这甚至是错误吗?
  2. 我该如何解决?我可以编写一些骇人听闻的解决方案,在其中检查浏览器并检查click事件之后是否迅速触发了contextmenu事件……但是我正在寻找更强大的工具。

0 个答案:

没有答案