How to call Greasemonkey's GM_ functions from code that must run in the target page scope?

后端 未结 1 985
Happy的楠姐
Happy的楠姐 2020-11-27 22:07

I asked a question and got an answer here: How to call this YouTube function from Greasemonkey?

That code works and adds a button to the page, which captures the vid

相关标签:
1条回答
  • 2020-11-27 22:30

    To use Greasemonkey's GM_ functions from code that must run in the page scope (Such as your timeBtn click handler), do the following:

    1. Have the page-scope code use postMessage to send the data in string format.
    2. Have the Greasemonkey script listen for the appropriate messages and call the desired GM_ function(s) with the message data.
    3. Use JSON to safely package data in strings.

    Adding window.postMessage () and window.addEventListener ("message"... to your code, it becomes:

    ... ...
    
    //-- Only run in the top page, not the various iframes.
    if (window.top === window.self) {
        var timeBtn         = document.createElement ('a');
        timeBtn.id          = "gmTimeBtn";
        timeBtn.textContent = "Time";
        //-- Button is styled using CSS, in GM_addStyle, below.
    
        document.body.appendChild (timeBtn);
    
        addJS_Node (null, null, activateTimeButton);
    
        window.addEventListener ("message", receiveTimeMessage, false);
    }
    
    function activateTimeButton () {
        var timeBtn = document.getElementById ("gmTimeBtn");
        if (timeBtn) {
            timeBtn.addEventListener ('click',
                function () {
                    var ytplayer = document.getElementById ("movie_player");
                    /*-- GM_functions will not work here, so send the data
                        back to the GM script scope.
                    */
                    //-- Tag the message, we may not be the only ones sending.
                    var messageTxt  = JSON.stringify (
                        {currentVidTime: ytplayer.getCurrentTime ()}
                    );
                    window.postMessage (messageTxt, "*");
                },
                false
            );
        }
        else {
            alert ("Time button not found!");
        }
    }
    
    function receiveTimeMessage (event) {
        var messageJSON;
        try {
            messageJSON     = JSON.parse (event.data);
        }
        catch (zError) {
            // Do nothing
        }
    
        if ( ! messageJSON  ||  ! messageJSON.currentVidTime)
            return; //-- Message is not for us.
    
        /*--- We have a time value, set it with GM_setValue ()
            But, WARNING: First make sure that the stored value is
            a safe string.  GM_setValue() crashes on just about anything else.
        */
        var safeValue       = JSON.stringify (messageJSON.currentVidTime);
        GM_setValue ("videoMarkedTime", safeValue);
        console.log ("Video time recorded with GM_setValue ().");
    }
    
    ... ...
    


    You can see the stored value by opening about:config and searching for videoMarkedTime.

    0 讨论(0)
提交回复
热议问题