使用“onclick”事件模拟元素的中间点击

问题描述

问题

对于站点测试,我尝试使用基于 some other answers on here 的 JS 模拟如下元素上的中间点击(或滚轮点击)。

HTML:

<a 
  id="example-link" href="https://www.google.com/" 
  target="_blank" 
  onclick="window.open('https://www.google.com/','','width=500,height=500,resizable=1,scrollbars=1');
     return false;">
  <span>Middle Click Me</span>
</a>

JS(希望在这里改变一些东西):

var middleClick = new MouseEvent( "click",{ "button": 1,"which": 2 });
jQuery("#example-link")[0].dispatchEvent( middleClick );

The issue is shown in this jsfiddle

  1. 请注意,常规点击通常会发送一个弹出窗口。 jsfiddle 正在捕获弹出窗口并在新选项卡中打开它。
  2. 使用 jsfiddle 而不是 stackoverflow fiddle 以避免混淆,因为堆栈溢出 fiddle 无法正确处理 window.open()

将 1) 手动中间点击与 2) 运行代码模拟点击进行比较。

问题是,当我以编程方式触发中间点击时,它同时触发打开新窗口的 onclick 方法,以及在新选项卡中打开链接(创建弹出窗口和选项卡,而不仅仅是一个选项卡)。如果手动点击此链接,则不会触发弹出窗口。

问题

是否有更好的模拟中间点击的方法(最好是跨浏览器兼容的)?它的编写方式,我真的无法让 MouseEvent 脚本准确模拟手动中间点击。

编辑:不幸的是,为了测试完整性,我无法更改 HTML 对象或修改 DOM,因此我希望 onclick 标记保留在元素上。

解决方法

据我所知,只要该内联点击处理程序存在,它就会在该元素上的每个点击事件上触发,但这里有两个我想出的解决方法。

  1. 如果你真的不能瞬间修改 DOM,那么第一个选项将无法使用。它通过更改 DOM 然后恢复它来作弊,希望在任何人注意到之前。

  2. 第二个选项通过读取链接的属性并使用它们打开新选项卡,而无需触发新的点击事件,从而完全避免点击链接。 (这依赖于对链接元素标记有基本了解的脚本。具体来说,我在这里编写的代码只是假设“链接”元素在其 href 属性中有一个有效的 url -- 但如果有必要,您可以做出其他更复杂的假设,并根据“链接”元素在运行时具有的属性有条件地采取行动。)

注意:第三种选择是创建一个自定义事件,它具有与内置 click 事件完全相同的核心行为,但实际上不是点击事件,其想法是欺骗 onclick 处理程序进入睡眠状态通过事件。我不知道需要多少工作才能很好地重建这个特殊的轮子。也许不会太糟糕?


在这个脚本中,打开新选项卡的函数是由按钮点击触发的,当然这只是为了演示目的,你可能会在页面加载时触发它们或作为对其他一些操作的回调。出于节省空间的原因,代码段中的锚元素也略有更改

.

(因为在 Stack Overflow 代码段中直接调用 window.open 似乎无法正常工作,所以我按照您的指示粘贴了代码 into a fiddle,因此可以看到它在所有名义上运行荣耀。)

const
  // Identifies some DOM elements
  cheatButton = document.getElementById("cheat-button"),mimicButton = document.getElementById("mimic-button"),exampleLink = document.getElementById("example-link"),// Defines an event to be dispatched programmatically
  middleClick = new MouseEvent("click",{button: 1,which: 2});

// Demonstrates calling the functions
cheatButton.addEventListener("click",emulateMiddleClick); // Option 1
mimicButton.addEventListener("click",followLink); // Option 2

// Defines the functions
function emulateMiddleClick(){
  const onclickHandler = exampleLink.onclick; // Remembers onclick handler
  exampleLink.onclick = ""; // Supresses onclick handler
  exampleLink.dispatchEvent(middleClick); // Dispatches middle click
  exampleLink.onclick = onclickHandler; // Restores onclick handler
}

function followLink(){
  if(!exampleLink.href){ return; } // In case href attribute is not set
  const {href,target} = exampleLink; // Gets props by using "destructuring"

  // This doesn't seem to work in the Stack Overflow snippet...
  window.open(href,(target || "_blank")); // In case target attribute is not set

  // ...But we can at least log our intention to open a new tab
  console.log(`opening: "${href}" (in "${target}")`);
}
div{ margin: 1em; }
button{ padding: 0.3em; border-radius: 0.5em; }
span{ margin: 1.3em; }
<div>
  <button id="cheat-button">Fake Click,and Suppress Handler</button>
</div>
<div>
  <button id="mimic-button">Follow Link without Clicking</button>
</div>
  <a id="example-link"
     href="https://www.google.com/"
     target="_blank"
     onclick="window.open('https://www.google.com/','','width=50,height=50');">
    <span>Middle Click Me</span>
  </a>