2013-01-08 77 views
1

我試圖用Greasemonkey觀看視頻的時間顯示警報。如何從Greasemonkey調用此YouTube功能?

My script

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


但是,這是行不通的。

你能幫我嗎?謝謝!

回答

2

由於各種安全問題和範圍界定問題,您無法從Greasemonkey腳本作用域運行ytplayer.getCurrentTime()

同樣,click事件處理程序必須在目標頁面的作用域中運行以訪問該函數。嘗試這樣做會產生undefinedError: Bad NPObject as private data!的組合。

這意味着您必須爲您的時間按鈕「注入」click處理程序。
但首先,這裏有幾個問題需要考慮:

  1. YouTube和谷歌大部分的網站,大量運用秒。爲避免多次執行腳本時出現問題,請使用像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()等,當點擊那個按鈕。這需要跨範圍進行消息傳遞。 請參閱this answer或打開一個新的問題,當你到那個部分。

+0

非常感謝您的回覆和解釋。 的確我會用'GM_setValue()'。 所以我必須開一個新的問題? 再一次,謝謝你:-) – Romaric

+0

不客氣。樂意效勞。 –