1

我正在尝试使用 Greasemonkey 观看视频的时间来显示警报。

我的脚本

// ==UserScript==
// @name        Time YouTube
// @description Does not work ! Help !
// @namespace   time_youtube
// @include     *youtube.com/watch*
// @grant       GM_setValue
// @icon        http://aux3.iconpedia.net/uploads/520882026785186105.png
// @version     1.3
// ==/UserScript==

ytplayer        = document.getElementById ("movie_player");
var time        = document.createElement ('a');
time.innerHTML  = '<a style="position: fixed; top: 200px; left: 3px; color:black;">Time</a>';

//time.addEventListener ('click', function(){GM_setValue('url_time',(document.location.href) + '&t=' + (ytplayer.getCurrentTime()));}, false);
time.addEventListener ('click',
    function () {
        alert (ytplayer.getCurrentTime() );
    },
    false
);

document.body.appendChild (time);


但这不起作用。

你能帮助我吗?谢谢!

4

1 回答 1

2

由于各种安全和范围问题,您不能ytplayer.getCurrentTime()从 Greasemonkey 脚本范围运行。

同样,click事件处理程序必须在目标页面的范围内运行才能访问该函数。尝试不这样做会产生undefined和的组合Error: Bad NPObject as private data!

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

  1. Youtube 和大多数 Google 网站都广泛使用<iframe>s。为避免多次执行脚本时出现问题,请使用检查window.top === window.self以确保脚本仅在框架中运行或包含您所定位的页面。
  2. 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()在单击该按钮时最终使用等。这需要跨范围的消息传递。 当您到达该部分时,请参阅此答案或打开一个新问题。

于 2013-01-08T23:38:22.657 回答