最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin1浏览0评论

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 video time.
But, the key part must run in the target-page scope -- where Greasemonkey's GM_ functions are not available.

I want to use GM_setValue() to record the video time. How do I call GM_setValue() from my button's click handler?

Here is the relevant part of the plete script (right-click to save):

... ...

//-- 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);
}

function activateTimeButton () {
    var timeBtn = document.getElementById ("gmTimeBtn");
    if (timeBtn) {
        timeBtn.addEventListener ('click',
            function () {
                var ytplayer = document.getElementById ("movie_player");
                //-- IMPORTANT:  GM_functions will not work here.

                console.log ("getCurrentTime(): ", ytplayer.getCurrentTime() );
                alert (ytplayer.getCurrentTime() );
            },
            false
        );
    }
    else {
        alert ("Time button not found!");
    }
}

... ...


Thank you :-)

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 video time.
But, the key part must run in the target-page scope -- where Greasemonkey's GM_ functions are not available.

I want to use GM_setValue() to record the video time. How do I call GM_setValue() from my button's click handler?

Here is the relevant part of the plete script (right-click to save):

... ...

//-- 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);
}

function activateTimeButton () {
    var timeBtn = document.getElementById ("gmTimeBtn");
    if (timeBtn) {
        timeBtn.addEventListener ('click',
            function () {
                var ytplayer = document.getElementById ("movie_player");
                //-- IMPORTANT:  GM_functions will not work here.

                console.log ("getCurrentTime(): ", ytplayer.getCurrentTime() );
                alert (ytplayer.getCurrentTime() );
            },
            false
        );
    }
    else {
        alert ("Time button not found!");
    }
}

... ...


Thank you :-)

Share Improve this question edited May 23, 2017 at 10:27 CommunityBot 11 silver badge asked Jan 9, 2013 at 6:32 RomaricRomaric 651 silver badge5 bronze badges 4
  • I know I told you to ask this question, but Stack Overflow is not (normally) a code writing service. You need to phrase the question in a way that others might find useful for their problems. You should also show what you have tried, not just spit the last answer back at us and ask for additional features. ... This question is in danger of being closed as "too localized" (by others, not me). Please edit the question with that in mind. I'll answer tomorrow, if nobody beats me to it. – Brock Adams Commented Jan 9, 2013 at 6:43
  • 1 I understand, but I know very little JavaScript. And being French and speaking very little English and bad, it is very difficult to express myself. – Romaric Commented Jan 9, 2013 at 7:07
  • Refactored the question for, hopefully, more general applicability. – Brock Adams Commented Jan 10, 2013 at 10:35
  • It's okay, it works! And thank you for refactoring, it is much better that way. :) – Romaric Commented Jan 10, 2013 at 19:14
Add a ment  | 

1 Answer 1

Reset to default 9

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 bees:

... ...

//-- 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)

  1. 暂无评论