只能通过unsafeWindow从TamperMonkey脚本触发鼠标悬停事件 - 为什么?

时间:2014-02-08 14:20:13

标签: jquery mouseover tampermonkey

在现有的网页上,通过TamperMonkey脚本,我想自动将鼠标悬停在图像上,等待“弹出”(实际上是< DIV>)出现,然后单击该弹出窗口上的按钮

现在,从控制台开始,此代码会触发鼠标悬停事件,并且会出现“弹出窗口”。

$('div.photo.mpHover img').eq(0).mouseover()

在我的TM脚本中,除非我引用unsafeWindow ..

,否则此代码不会触发事件
unsafeWindow.$('div.photo.mpHover img').eq(0).mouseover()

为什么会这样?我很困惑,因为例如从TM脚本模拟'click'事件按预期工作而不访问unsafeWindow ..

$('div.photo.mpHover img').eq(0).click()

1 个答案:

答案 0 :(得分:1)

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

  

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

  

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


这在实践中意味着:

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

  2. .trigger()通常仅在相同范围相同范围中调用时才有效。
    除非您注入代码或使用unsafeWindow跳转范围,否则用户脚本在不同的范围内运行。

  3. 但是,如果目标元素具有匹配的本机方法,例如click,则jQuery将默认尝试调用此方法。
    许多元素都使用原生click方法,但很少(¿none?)具有原生mouseover方法。

    这就是为什么即使没有使用注入,jQuery .click() 有时会从用户脚本工作的原因。但是,这是不可靠的,并且由于尝试访问JS代码跨沙箱的安全限制而经常会失败。


  4. 最强大的解决方案是发送实际鼠标事件(更新代码):

    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"