【问题标题】: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()

【问题讨论】:

    标签: jquery mouseover tampermonkey


    【解决方案1】:

    jQuery 的 .click().mouseover() 只是 .trigger() 的快捷方式。
    来自the docs

    任何事件处理程序附加.on() 或其快捷方法之一在相应事件发生时触发。但是,可以使用 .trigger() 方法手动触发它们。

    还有:

    注意:对于普通对象和除 window 以外的 DOM 对象,如果触发的事件名称与对象上的属性名称匹配,jQuery 将尝试调用该属性作为方法,如果没有事件处理程序调用 event.preventDefault()。


    这在实践中意味着:

    1. .trigger(),或者它的一种快捷方法,只能可靠地作用于由 jQuery 设置的事件处理程序,而不是其他 javascript。

    2. .trigger() 通常只有在 相同的 jQuery 实例,在相同的范围中调用时才会起作用。
      用户脚本在不同的范围内运行,除非您注入其代码或使用 unsafeWindow 跳转范围。

    3. 但是,如果目标元素有匹配的本地方法,例如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 已修复。编辑已提交。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-30
    • 1970-01-01
    • 2014-01-14
    • 1970-01-01
    • 2012-04-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多