【问题标题】:How to detect which option from hyperlink's right-clicked contextmenu was clicked?如何检测单击了超链接右键单击上下文菜单中的哪个选项?
【发布时间】:2019-02-08 18:35:25
【问题描述】:

假设我正在使用默认浏览器的上下文菜单。

  • 例如,我怎样才能找出用户从右键单击上下文菜单中选择了“复制链接位置”?
  • 如何在“复制链接位置”操作后覆盖默认行为? (例如,替换链接,但如果用户选择“在新选项卡中打开”,它仍然是原始链接)。

已编辑:在关闭链接的上下文菜单后立即替换剪贴板中的链接(即使用户选择了与“复制链接位置”不同的选项)也是可接受的解决方案。

【问题讨论】:

  • 为什么要更改用户复制到剪贴板的内容?
  • 客户项目的要求。
  • 这里不问问题会破坏 NDA 吗?有充分的理由,如果没有用户的操作,您所要求的内容是不可能的。善意和合乎道德地建议客户。
  • 你为什么要叫名字?您本质上要问的是如何在未经用户许可的情况下颠覆和破坏用户的系统。除非我误认为要求是在用户不知情或未经许可的情况下更改用户剪贴板的内容。
  • 你错了。

标签: javascript html browser hyperlink contextmenu


【解决方案1】:

很遗憾,出于安全原因,不可能检测到在默认浏览器的上下文菜单中选择的内容。

出于安全原因,也不可能覆盖覆盖默认浏览器上下文菜单上的默认功能/操作。

你可以做什么:

  1. 使用浏览器扩展程序(最终用户应首先安装您的扩展程序),您可以将您自己的自定义选项与您的图标和功能添加到默认浏览器的上下文菜单中。

  2. 您可以覆盖鼠标右键单击时的默认行为。例如,右键单击后,您可以使用自己的功能显示自己的自定义上下文菜单。


编辑:我对 OP(原始海报)第一条评论的回答:

右键单击和oncotextmenu 事件后的链接替换与您想要在您的问题中实现的目标无关!我上面已经写过了

您可以在鼠标右键单击时覆盖默认行为

这也意味着您可以在右键单击后替换链接,但在您的问题中,您想在 default 上下文中单击 特定菜单选项 后替换链接菜单。出于安全原因,这是不可能

你必须阅读oncontextmenu event:

在窗口上单击鼠标右键时通常会触发 contextmenu 事件。除非阻止默认行为,否则浏览器上下文菜单将激活。

【讨论】:

  • 哦,不幸的是这不是真的。我已经找到了一种在右键单击操作中更改 url 的通用方法:stackoverflow.com/a/54421841/2166188。但是现在,我只想更改“复制链接位置”网址
  • Michal,你想错了。 oncontextmenu 事件和链接替换与您的问题无关。我在上面的答案中为你写了答案。
  • 我正在寻找解决方案。如果oncontextmenu 不是一个正确的地方,那么有哪些选择?关闭contextmenu 后立即替换剪贴板中的链接?如果有,怎么做?
  • Michal,“从 contextmenu 关闭后替换剪贴板中的链接”只有在用户的一些许可下才可能,并且只能在从 contextmenu 打开之前,因为我们没有关闭此菜单的某些事件。但是像这个事件这样的错误代码你可能有像 here 这样的错误代码。但是,如果您想在所有情况下都替换链接,那么为什么要等到从上下文菜单关闭?您可以在打开的上下文菜单中替换 HTML 中的链接,就像上面链接中的代码一样。但我个人永远不会这样做。
  • 我不想替换 H​​TML 中的链接,因为如果用户单击“在新选项卡中打开”或“在新窗口中打开”,我会使用原始链接。当用户从上下文菜单中选择“复制链接到剪贴板”时,我只对替换链接感兴趣
【解决方案2】:

已编辑:在关闭链接后立即替换剪贴板中的链接 contextmenu(即使用户选择了与“复制链接”不同的选项 location") 也是可以接受的解决方案。

如果用户授予适当的permissions,您可以使用contextmenu 事件、focusoutcontextmenu 事件处理程序和Async Clipboard API 中附加到windowAsync Clipboard API

<body>
  <a id="a" href="#">click</a>
  <script>
    a.addEventListener('contextmenu', e => {
      console.log(e);
      window.addEventListener("focusout", e => {
        console.log(e);
        navigator.clipboard.writeText(a.href)
          .then(() => {
            console.log('Text copied to clipboard');
          })
          .catch(err => {
            // This can happen if the user denies clipboard permissions:
            console.error('Could not copy text: ', err);
          });
        navigator.clipboard.readText()
          .then(text => {
            console.log('Pasted content: ', text);
          })
          .catch(err => {
            console.error('Failed to read clipboard contents: ', err);
          });
      }, {
        once: true
      });
    });
  </script>
</body>

plnkr

【讨论】:

  • 有趣!小提示:我根本不需要navigator.clipboard.readText() 部分。此外,我发现了focusout 的一个问题:它只有在用户在浏览器窗口内再次单击时才有效。如果用户单击其他任何地方(例如,在浏览器面板上或最小化浏览器窗口并将链接粘贴到不同的应用程序) - 它不起作用。在这种情况下哪个事件会更通用并被触发?
  • @Michal_Szulc focusout 事件在 POC 中用作示例。您可以尝试focussetTimeout 或其他方式来估计何时访问剪贴板的内容。鉴于此答案适用于答案中问题的块引用部分,因此在访问设置的剪贴板数据时不需要任何明显的延迟。包含.readText() 以证明内容已设置。相应地调整代码以满足特定要求。
  • 那么在用户关闭上下文菜单后,哪个事件适合使用以确保它会被执行? (即使通过点击例如alt-tab触发了关闭conetextmenu操作?)
  • @Michal_Szulc 只尝试过focusoutfocusblur。和setTimeout。您尝试了哪些事件或其他方法来完成您想要实现的目标?
  • 似乎问题出在标签焦点上,导致focusoutblur 内的console.log 打印到控制台:developers.google.com/web/updates/2018/03/clipboardapi To help prevent abuse, clipboard access is only allowed when a page is the active tab. Pages in active tabs can write to the clipboard without requesting permission, but reading from the clipboard always requires permission.
【解决方案3】:

contextmenu 用于识别right click 例如:

$('{IdOrClass}').on('click contextmenu', "a", function(event) {
   alert("Right clicked"); // do whatever you want on right click
}); 

【讨论】:

  • 我们正在尝试在right click 菜单打开后从上下文菜单中识别所选选项,而不是打开上下文菜单本身。
猜你喜欢
  • 1970-01-01
  • 2016-03-09
  • 1970-01-01
  • 2010-09-21
  • 1970-01-01
  • 1970-01-01
  • 2016-02-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多