是否有可能让其他javascript事件监听器等待异步事件?

时间:2016-02-15 18:44:10

标签: javascript ajax events greasemonkey tampermonkey

我想劫持一个网页(使用Tampermonkey),该网页有一个带有一些事件监听器的按钮,最后是一个重定向。

有没有办法将自己的click事件处理程序添加到按钮,这会产生一个AJAX请求,并在继续使用其他事件侦听器之前等待它完成,所以我的AJAX请求肯定在重定向之前完成了? / p>

我知道stopImmediatePropagation但不知道如何延迟"异步传播。

1 个答案:

答案 0 :(得分:2)

不,你不能让其他事件处理程序等待。您有时可以覆盖/劫持现有函数,但这通常不可能使用Tampermonkey并且在可能的情况下会变得混乱(例如在Firefox + Greasemonkey中)。

对于像按钮这样的可点击元素,一种解决方法是覆盖按钮,在其上设置侦听器,然后让它们在时间到来时触发原始按钮上的所需事件。

例如,请考虑以下代码段:

  1. #mainButton及其代码代表原始页面。
  2. "劫持"按钮模拟您的Tampermonkey脚本的运行。
  3. "脚本"创建一个与按钮大小相同的div,并将其放在按钮上。因此,任何点击都会被div捕获,而不是按钮。
  4. 拦截代码执行一些异步操作,然后触发对原始按钮的单击。
  5. 
    
    //--------------------------
    //--- The page's code:
    //--------------------------
    $("#mainButton").click ( function () {
        logline ("The button was clicked.");
    } );
    
    //------------------------------
    //--- The script setup and code:
    //------------------------------
    $("#tmIntercept").click ( function () {
        logline ("==> Main button is now intercepted.");
        //this.disabled = true;
        $(this).attr ( {"disabled": true} );
    
        var targBtn     = $("#mainButton");
        var overlayDiv  = $('<div id="tmBtnOverlay">').css ( {
            'width':        targBtn.outerWidth (),
            'height':       targBtn.outerHeight (),
            'position':     'absolute',
            'top':          targBtn.offset ().top,
            'left':         targBtn.offset ().left,
            'z-index':      8888,
            'background':   "lime",
            'opacity':      "0.2"
        } )
        .appendTo ("body");
    
        overlayDiv.click ( function (zEvent) {
            //-- Guard against more global handlers.
            zEvent.stopImmediatePropagation ();
    
            logline ("Doing some AJAXy thing... <span>&nbsp;</span>");
    
            //-- Simulated AJAX call:
            setTimeout (doSomeAjaxyThing, 1111);
        } );
    } );
    
    function doSomeAjaxyThing () {
        $("#eventLog > p > span").first ().text ('Done.');
    
        //-- Now send required events to the original button:
        var clickEvent = document.createEvent ('MouseEvents');
        clickEvent.initEvent ("click", true, true);
        $("#mainButton")[0].dispatchEvent (clickEvent);
    }
    
    function logline (str) {
        this.lineNumber = this.lineNumber + 1  ||  1;
        var lineDisplay = (1e15 + this.lineNumber + "").slice (-3);  //-- zero pad 3 places
    
        $("#eventLog").prepend ('<p>' + lineDisplay + ' &nbsp; ' + str + '</p>');
    }
    &#13;
    #mainButton {
        font-size: 2em;
        padding: 0.3ex 2ex;
    }
    #eventLog {
        max-height: 50vh;
        overflow-y: auto;
        overflow-x: hidden;
    }
    #eventLog > p {
        margin: 0.3ex 2ex;
    }
    &#13;
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
    
    <p><button id="mainButton">The Button</button></p>
    
    <p><button id="tmIntercept" autocomplete="off">Hijack the button</button></p>
    
    <fieldset>
        <legend>Event Log:</legend>
        <div id="eventLog"></div>
    </fieldset>
    &#13;
    &#13;
    &#13;

    备注:

    1. 在某些情况下,您可能会想直接调用该网页的代码。但它通常更简单,更健壮,更安全地触发事件。
    2. 这只是叠加过程的演示。在实践中,简单的绝对定位可能需要调整。 (通常将目标节点包裹在相对定位的div中并调整偏移量。)这超出了这个问题的范围。