我正在尝试模拟用户对我无法控制的代码的网站的点击。我试图与充当按钮的 div 互动的元素。
<div role="button" class="c-T-S a-b a-b-B a-b-Ma oU v2" aria-disabled="false" style="-webkit-user-select: none;" tabindex="0">
Generate
</div>
与元素关联的事件监听器(根据 Chrome 的检查器)是:
我只是尝试使用以下方法点击按钮:
var button = $('.c-T-S.a-b.a-b-B.a-b-Ma.oU.v2')
button.click()
...但是没有任何反应。选择器有效,经验证:
alert($('.c-T-S.a-b.a-b-B.a-b-Ma.oU.v2').length); // alerts "1"
我已经尝试了所有事件处理程序的排列
button.trigger('click');
button.mouseover().mousedown().mouseup()
button.trigger('mouseover', function() { button.trigger('mousedown', function() { button.trigger('mouseup'); }); });
...但仍然没有。我怎样才能模拟点击这个 div?
如果不清楚,我尝试模拟点击这个div并触发原始功能,而不是在元素上定义新的点击功能。
更新
这些答案中的许多确实确实点击了按钮,但不会产生与手动点击按钮相同的结果。所以看起来问题不一定是点击按钮本身,而是模拟真实点击。
最佳答案
我做了一个FIDDLE模拟您的“不可点击”按钮。那里的蓝色 div 附加了与您在问题中显示的相同的 eventListeners。玩弄最终得到以下结果:
1) 让我们先获取 DOM 元素:
var button = document.getElementsByClassName('.c-T-S.a-b.a-b-B.a-b-Ma.oU.v2')[0];
2) 该页面不包含 jQuery。所以那里的所有 eventListeners 都附加了 native .addEventListener()
.如果使用 jQuery 触发事件,它只会触发 jQuery 附加的事件,而不会触发 native 附加事件。这意味着:
$(button).trigger('mousedown'); // this doesn't work
button.dispatchEvent(new Event('mousedown')); // this should work
3) 正如 Scimonster 所指出的,没有附加 click-eventListener。这意味着:
$(button).trigger('click'); // doesn't work anyway, see 2)
// next works, but has no visible result on the page,
// because there is no click-handler to do anything:
button.dispatchEvent(new Event('click'));
4) 当鼠标按钮上升时触发点击事件。当 mouseup
-event 被用来代替它看起来像点击。在 fiddle 中,mouseup 使红色 div 可见。您可以尝试通过将此行添加到代码中来触发 mouseup 事件:
button.dispatchEvent(new Event('mouseup')); // "works", but has no visible result
mouseup-handler 被mouseover
“隐藏”了- 和 mouseout
-events,第一个附加它,后者删除它。这样 mouseup 只有在鼠标悬停在按钮上时才会产生结果。我假设您的 google-page 做了类似的事情来覆盖点击事件。
5) 你应该尝试什么:
先以原生方式触发一些单一的事件:
button.dispatchEvent(new Event('eventName'));
如果没有给出可用的结果,请使用一些合理的事件组合:
button.dispatchEvent(new Event('mouseover'));
button.dispatchEvent(new Event('mousedown'));
// or:
button.dispatchEvent(new Event('mousedown'));
button.dispatchEvent(new Event('mouseup')); // or: .....
有很多方法可以组合事件,因此单个事件不会做任何事情,但只有正确的组合才有效。
编辑 根据您的调查来源邀请,我发现了两种方法:
1) 按钮本身没有附加 eventListeners。该按钮包裹在 <a>
中-标签。此标记是按钮及其属性 jsaction
的父级的值表明 <a>
有 click
的监听器, focus
, 和 mousedown
.直接定位它有效:
button.parentElement.dispatchEvent(new Event('click'));
2) 如果您想要单击按钮本身,您必须触发一个事件使 DOM 向上冒泡以到达具有单击处理程序的元素。但是在使用 new Event('name')
创建事件时, 它的 bubbles
-属性默认为 false
. 我没有想到这一点是我的错。。因此,以下内容直接作用于按钮:
button.dispatchEvent(new Event('click', {bubbles: true}));
EDIT 2 深入挖掘该页面上发生的事情产生了可用的结果:
已经发现页面会处理鼠标指针的位置和事件的正确顺序,可能会区分是人类还是机器人/脚本触发了事件。因此,此解决方案使用 MouseEvent
- 包含 clientX
的对象和 clientY
属性,保存事件触发时指针的坐标。
元素上的自然“点击”总是按给定顺序触发四个事件:mouseover
, mousedown
, mouseup
, 和 click
.模拟自然行为mousedown
和 mouseup
被延迟。为了方便起见,所有步骤都包含在一个函数中
模拟 1) 在它的左上角输入元素,2) 稍后在元素中心单击。详情见评论。
function simulateClick(elem) {
var rect = elem.getBoundingClientRect(), // holds all position- and size-properties of element
topEnter = rect.top,
leftEnter = rect.left, // coordinates of elements topLeft corner
topMid = topEnter + rect.height / 2,
leftMid = topEnter + rect.width / 2, // coordinates of elements center
ddelay = (rect.height + rect.width) * 2, // delay depends on elements size
ducInit = {bubbles: true, clientX: leftMid, clientY: topMid}, // create init object
// set up the four events, the first with enter-coordinates,
mover = new MouseEvent('mouseover', {bubbles: true, clientX: leftEnter, clientY: topEnter}),
// the other with center-coordinates
mdown = new MouseEvent('mousedown', ducInit),
mup = new MouseEvent('mouseup', ducInit),
mclick = new MouseEvent('click', ducInit);
// trigger mouseover = enter element at toLeft corner
elem.dispatchEvent(mover);
// trigger mousedown with delay to simulate move-time to center
window.setTimeout(function() {elem.dispatchEvent(mdown)}, ddelay);
// trigger mouseup and click with a bit longer delay
// to simulate time between pressing/releasing the button
window.setTimeout(function() {
elem.dispatchEvent(mup); elem.dispatchEvent(mclick);
}, ddelay * 1.2);
}
// now it does the trick:
simulateClick(document.querySelector(".c-T-S.a-b.a-b-B.a-b-Ma.oU.v2"));
该函数不会模拟给定任务不需要的真实鼠标移动。
关于javascript - div 按钮上的 JQuery click() 不会触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26126663/