2013-01-08 46 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

不客气。乐意效劳。 –