只能通过 unsafeWindow 从 TamperMonkey 脚本触发鼠标悬停事件 - 为啥?
Posted
技术标签:
【中文标题】只能通过 unsafeWindow 从 TamperMonkey 脚本触发鼠标悬停事件 - 为啥?【英文标题】:Can only trigger mouseover event from TamperMonkey script via unsafeWindow - Why?只能通过 unsafeWindow 从 TamperMonkey 脚本触发鼠标悬停事件 - 为什么? 【发布时间】:2014-02-08 14:20:13 【问题描述】:在现有网页上,通过 TamperMonkey 脚本,我想自动将鼠标悬停在图像上,等待“弹出窗口”(实际上是 )出现,然后单击该弹出窗口上的按钮。
现在,该代码从控制台触发了我所期望的鼠标悬停事件,并出现了一个“弹出窗口”。
$('div.photo.mpHover img').eq(0).mouseover()
在我的 TM 脚本中,此代码不会触发事件,除非我引用 unsafeWindow..
unsafeWindow.$('div.photo.mpHover img').eq(0).mouseover()
为什么会这样?我很困惑,因为例如从 TM 脚本模拟“点击”事件可以按预期工作而无需访问 unsafeWindow..
$('div.photo.mpHover img').eq(0).click()
【问题讨论】:
【参考方案1】:jQuery 的 .click()
和 .mouseover()
只是 .trigger()
的快捷方式。
来自the docs:
任何事件处理程序附加
.on()
或其快捷方法之一在相应事件发生时触发。但是,可以使用.trigger()
方法手动触发它们。
还有:
注意:对于普通对象和除 window 以外的 DOM 对象,如果触发的事件名称与对象上的属性名称匹配,jQuery 将尝试调用该属性作为方法,如果没有事件处理程序调用 event.preventDefault()。
这在实践中意味着:
.trigger()
,或者它的一种快捷方法,只能可靠地作用于由 jQuery 设置的事件处理程序,而不是其他 javascript。
.trigger()
通常只有在 相同的 jQuery 实例,在相同的范围中调用时才会起作用。
用户脚本在不同的范围内运行,除非您注入其代码或使用 unsafeWindow
跳转范围。
但是,如果目标元素有匹配的本地方法,例如click
,jQuery 将默认尝试调用它。
许多元素都有原生的click
方法,但很少(¿none?)有原生的mouseover
方法。
这就是为什么 jQuery .click()
有时会在用户脚本中工作,即使不使用注入也是如此。但是,这并不可靠,并且由于尝试跨沙箱访问 JS 代码的安全限制,经常会失败。
最强大的解决方案是发送实际的鼠标事件(更新代码):
triggerMouseEvent ( $('div.photo.mpHover img').eq(0), "mouseover");
function triggerMouseEvent (jNode, eventType)
if (jNode && jNode.length)
var clickEvent = new MouseEvent (
eventType, canBubble: true, cancelable: true
);
jNode[0].dispatchEvent (clickEvent);
旧方法:仍然有效,但has been deprecated。
triggerMouseEvent ( $('div.photo.mpHover img').eq(0), "mouseover");
function triggerMouseEvent (jNode, eventType)
if (jNode && jNode.length)
var clickEvent = document.createEvent('MouseEvents');
clickEvent.initEvent (eventType, true, true);
jNode[0].dispatchEvent (clickEvent);
这在几乎所有情况下都有效,通常无需注入或unsafeWindow
。
有关更复杂的场景,请参阅"Choosing and activating the right controls on an AJAX-driven site"。
【讨论】:
看来 document.createEvent 已被弃用,因此我将重新编写您的代码示例以使用事件构造函数,不过感谢您花时间提供高质量的答案 Brock。 不客气。感谢您让我知道已弃用的代码。 @richardPlester 已修复。编辑已提交。以上是关于只能通过 unsafeWindow 从 TamperMonkey 脚本触发鼠标悬停事件 - 为啥?的主要内容,如果未能解决你的问题,请参考以下文章
为啥用户脚本中的窗口(和 unsafeWindow)与 <script> 标记中的不同?