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 に答える