【问题标题】:Emulating middle click on element with an "onclick" event使用“onclick”事件模拟元素的中间点击
【发布时间】:2021-03-26 04:06:22
【问题描述】:

问题

对于站点测试,我正在尝试使用基于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 标记保留在元素上。

【问题讨论】:

  • 尝试删除 onclick="window.open('google.com/…); return false;"它应该适用于中间按钮
  • 不幸的是,我无法摆脱 onclick 标记(或者根本无法修改 DOM)。在原帖中澄清了。
  • 我将您的示例代码移到了 Stack Overflow sn-p 中,并重组了您的介绍性文本。如果编辑后的版本不能正确反映您的意图,请随时重新编辑(或恢复到您的原始版本)。
  • 我最终将它从 stackoverflow sn-p 中取出,因为它没有按预期工作并且不想混淆,但保留了您的一些其他编辑!谢谢你:)

标签: javascript onclick mouseevent ui-automation popupwindow


【解决方案1】:

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

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

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

注意:第三种选择是创建一个自定义事件,该事件具有与内置 click 事件相同的核心行为,但实际上不是点击事件,其想法是欺骗 onclick 处理程序通过事件。我不确定重建这个特定轮子需要做多少工作才能做得足够好。也许不会太糟糕?


在此脚本中,打开新选项卡的功能由按钮单击触发,但这当然只是出于演示目的,您可能会在页面加载时触发它们或作为其他操作的回调。为了节省空间,sn-p 中的锚元素也略有改变

.

(因为直接调用 window.open 在 Stack Overflow sn-p 中似乎无法正常工作,所以我按照您的指示粘贴了代码 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>

【讨论】:

  • 感谢您的精彩回答。 l 主要是想避免更改 DOM,以使测试尽可能接近本机功能。但是,我真的很喜欢 emulateMiddleClick 恢复 onclick 的方式;我认为这可能是提供的 JS 的最佳方法。如果测试不是为了模仿手动行为,我肯定会使用类似 followLink
猜你喜欢
  • 2017-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-07
  • 1970-01-01
  • 2017-05-18
  • 2020-12-10
相关资源
最近更新 更多