Javascript 如何从Greasemonkey调用此YouTube函数?

Javascript 如何从Greasemonkey调用此YouTube函数?,javascript,youtube,youtube-api,greasemonkey,Javascript,Youtube,Youtube Api,Greasemonkey,我正试图用Greasemonkey显示视频观看时间的警报 : /==UserScript== //@name-Time-YouTube //@description不起作用!救命啊! //@namespace time\u youtube //@include*youtube.com/watch* //@grant GM_setValue //@图标http://aux3.iconpedia.net/uploads/520882026785186105.png //@version 1.3 //

我正试图用Greasemonkey显示视频观看时间的警报

:

/==UserScript==
//@name-Time-YouTube
//@description不起作用!救命啊!
//@namespace time\u youtube
//@include*youtube.com/watch*
//@grant GM_setValue
//@图标http://aux3.iconpedia.net/uploads/520882026785186105.png
//@version 1.3
//==/UserScript==
ytplayer=document.getElementById(“电影播放器”);
var time=document.createElement('a');
time.innerHTML='time';
//time.addEventListener('click',function(){GM_setValue('url_time',(document.location.href)+'&t='+(ytplayer.getCurrentTime());},false);
time.addEventListener('单击',
函数(){
警报(ytplayer.getCurrentTime());
},
假的
);
document.body.appendChild(时间);

但这是行不通的


你能帮我吗?谢谢大家!

由于各种安全性和作用域问题,您无法从Greasemonkey脚本作用域运行
ytplayer.getCurrentTime()

同样地,
单击
事件处理程序必须在目标页面的作用域中运行才能访问该函数。否则,将产生
未定义
错误的组合:错误的NPObject作为私有数据

这意味着您必须“注入”时间按钮的
单击处理程序。
但首先,还有几个问题需要考虑:

  • Youtube和大多数谷歌网站都广泛使用
    s。要避免多次执行脚本时出现问题,请使用诸如
    window.top==window.self
    之类的检查,以确保脚本仅在您目标的帧或包含页面中运行
  • 尽量避免使用
    innerHTML
    和内联样式。这将使代码更易于维护,在许多情况下速度更快,并且不太可能触发意外的副作用
  • 综上所述,下面是您的完整脚本重构:

    // ==UserScript==
    // @name        Time YouTube
    // @description Does not work ! Help !
    // @namespace   time_youtube
    // @include     *youtube.com/watch*
    // @icon        http://aux3.iconpedia.net/uploads/520882026785186105.png
    // @grant       GM_setValue
    // @grant       GM_addStyle
    // @version     1.3
    // ==/UserScript==
    
    //-- 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!");
        }
    }
    
    //-- Style and position our button the CSS way.
    GM_addStyle ( "                 \
        #gmTimeBtn {                \
            position:   fixed;      \
            top:        200px;      \
            left:       3px;        \
            color:      black;      \
            margin:     0;          \
            padding:    0;          \
        }                           \
    " );
    
    //-- This is a standard-ish utility function...
    function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
        var D                                   = document;
        var scriptNode                          = D.createElement ('script');
        if (runOnLoad) {
            scriptNode.addEventListener ("load", runOnLoad, false);
        }
        scriptNode.type                         = "text/javascript";
        if (text)       scriptNode.textContent  = text;
        if (s_URL)      scriptNode.src          = s_URL;
        if (funcToRun)  scriptNode.textContent  = '(' + funcToRun.toString() + ')()';
    
        var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
        targ.appendChild (scriptNode);
    }
    


    最后,从您的脚本来看,您似乎希望在单击该按钮时最终使用
    GM_setValue()
    ,等等。这需要跨作用域传递消息请参见或在进入该部分时打开一个新问题。

    非常感谢您的回答和解释。实际上,我会使用
    GM\u setValue()
    。所以我必须提出一个新问题?再次感谢:-)
    // ==UserScript==
    // @name        Time YouTube
    // @description Does not work ! Help !
    // @namespace   time_youtube
    // @include     *youtube.com/watch*
    // @icon        http://aux3.iconpedia.net/uploads/520882026785186105.png
    // @grant       GM_setValue
    // @grant       GM_addStyle
    // @version     1.3
    // ==/UserScript==
    
    //-- 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!");
        }
    }
    
    //-- Style and position our button the CSS way.
    GM_addStyle ( "                 \
        #gmTimeBtn {                \
            position:   fixed;      \
            top:        200px;      \
            left:       3px;        \
            color:      black;      \
            margin:     0;          \
            padding:    0;          \
        }                           \
    " );
    
    //-- This is a standard-ish utility function...
    function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
        var D                                   = document;
        var scriptNode                          = D.createElement ('script');
        if (runOnLoad) {
            scriptNode.addEventListener ("load", runOnLoad, false);
        }
        scriptNode.type                         = "text/javascript";
        if (text)       scriptNode.textContent  = text;
        if (s_URL)      scriptNode.src          = s_URL;
        if (funcToRun)  scriptNode.textContent  = '(' + funcToRun.toString() + ')()';
    
        var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
        targ.appendChild (scriptNode);
    }