如何监听上下文菜单项上的事件?

问题描述 投票:0回答:2

我正在尝试监听浏览器默认上下文菜单(不是自定义上下文菜单)上的“在新选项卡中打开链接”上下文菜单项的单击。我想在页面在新选项卡中打开之前执行一些 JavaScript。或者甚至停止默认行为,执行我的 javascript,然后自己 window.open() 链接。

我已经看到如何监听这样的上下文菜单...

document.addEventListener('contextmenu', e => {});

但这不允许我确定是否单击了特定项目。

javascript onclick contextmenu addeventlistener
2个回答
0
投票

那是不可能的。您无法监听每个用户交互,但您可以猜测一些。如果您必须在打开新窗口之前执行操作,请使用自定义上下文菜单。

您可以采取某种解决方法,例如在打开上下文菜单后监听

window.onblur
和/或
window.mousemove
。我遇到过几种情况,我不得不处理与你类似的挑战,但并不是所有的事情都能被捕获。

例如,鼠标移动不会触发,而上下文菜单已打开,但

document.hasFocus()
为 true。一旦用户在上下文菜单中单击,并且鼠标仍在当前文档上方,鼠标移动就会在同一位置触发两次。如果与单击事件结合使用,用户可以通过左键单击 DOM 来关闭上下文菜单。如果用户使用 ESC 关闭上下文菜单,则会触发 keyup,但如果用户使用键盘选择某些内容则不会触发。

/*
 auxclick can be any mouse key except primary
 contextmenu may also trigger, if you use the contextmenu key on the keyboard
 but it fires a MouseEvent with values from a KeyboardEvent
 */
["contextmenu", /*"mousemove", */ "click", "auxclick", "keydown", "keyup"].forEach(name => {
  document.addEventListener(name, function(e) {
    if (document.visibilityState != "hidden") {
      console.log(name, document.hasFocus(), document.activeElement, e.key || e.screenX, e.key || e.screenY);
    }
  });
});

document.addEventListener("visibilitychange", function(e) {
  console.log("visibilitychange", document.hasFocus(), document.visibilityState, window.screenX, window.screenY);
  if (window.screenX == window.screenY && window.screenX == -32000 && document.visibilityState == 'visible') {
    console.log("restored");
  }
});

/*
  this won't trigger if the user switches from outside 
  the window directly into an iframe or between multiple
  iframes see https://crbug.com/967430
  monitor document.hasFocus() changes and fire a custom focus/blur event on change.
 */
window.addEventListener("focus", function(e) {
  console.log("focus", document.hasFocus());
});

window.addEventListener("blur", function(e) {
  console.log("blur", document.hasFocus(), document.visibilityState, window.screenX, window.screenY);
  setTimeout(() => {
    if (document.visibilityState == "hidden") {
      if (window.screenX == window.screenY && window.screenX == -32000) {
        console.log("minimized");
      } else {
        console.log("maybe new or other tab with focus or view source?");
      }

    } else if (!document.hasFocus()) {
      if (window == window.top) {
        console.log("maybe new window or dev tools");
      } else {
        console.log("maybe new window, dev tools or I'm an iframe and my parent got selected");
      }
    } else if (document.hasFocus()) {
      console.log("Maybe entered an iframe or canvas?", document.activeElement);
    }
  }, 1);
});

setInterval(() => console.log("interval", document.hasFocus(), document.activeElement), 2000);

0
投票

您需要创建自定义上下文菜单:

原生js:在此处输入链接描述

反应示例:在此处输入链接描述

© www.soinside.com 2019 - 2024. All rights reserved.