I asked a question and got an answer here: How to call this YouTube function from Greasemonkey?
That code works and adds a button to the page, which captures the video time.
But, the key part must run in the target-page scope -- where Greasemonkey's GM_
functions are not available.
I want to use GM_setValue()
to record the video time. How do I call GM_setValue()
from my button's click
handler?
Here is the relevant part of the plete script (right-click to save):
... ...
//-- 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!");
}
}
... ...
Thank you :-)
I asked a question and got an answer here: How to call this YouTube function from Greasemonkey?
That code works and adds a button to the page, which captures the video time.
But, the key part must run in the target-page scope -- where Greasemonkey's GM_
functions are not available.
I want to use GM_setValue()
to record the video time. How do I call GM_setValue()
from my button's click
handler?
Here is the relevant part of the plete script (right-click to save):
... ...
//-- 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!");
}
}
... ...
Thank you :-)
- I know I told you to ask this question, but Stack Overflow is not (normally) a code writing service. You need to phrase the question in a way that others might find useful for their problems. You should also show what you have tried, not just spit the last answer back at us and ask for additional features. ... This question is in danger of being closed as "too localized" (by others, not me). Please edit the question with that in mind. I'll answer tomorrow, if nobody beats me to it. – Brock Adams Commented Jan 9, 2013 at 6:43
- 1 I understand, but I know very little JavaScript. And being French and speaking very little English and bad, it is very difficult to express myself. – Romaric Commented Jan 9, 2013 at 7:07
- Refactored the question for, hopefully, more general applicability. – Brock Adams Commented Jan 10, 2013 at 10:35
- It's okay, it works! And thank you for refactoring, it is much better that way. :) – Romaric Commented Jan 10, 2013 at 19:14
1 Answer
Reset to default 9To use Greasemonkey's GM_
functions from code that must run in the page scope (Such as your timeBtn
click handler), do the following:
- Have the page-scope code use
postMessage
to send the data in string format. - Have the Greasemonkey script listen for the appropriate messages and call the desired
GM_
function(s) with the message data. - Use JSON to safely package data in strings.
Adding window.postMessage ()
and window.addEventListener ("message"...
to your code, it bees:
... ...
//-- 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);
window.addEventListener ("message", receiveTimeMessage, false);
}
function activateTimeButton () {
var timeBtn = document.getElementById ("gmTimeBtn");
if (timeBtn) {
timeBtn.addEventListener ('click',
function () {
var ytplayer = document.getElementById ("movie_player");
/*-- GM_functions will not work here, so send the data
back to the GM script scope.
*/
//-- Tag the message, we may not be the only ones sending.
var messageTxt = JSON.stringify (
{currentVidTime: ytplayer.getCurrentTime ()}
);
window.postMessage (messageTxt, "*");
},
false
);
}
else {
alert ("Time button not found!");
}
}
function receiveTimeMessage (event) {
var messageJSON;
try {
messageJSON = JSON.parse (event.data);
}
catch (zError) {
// Do nothing
}
if ( ! messageJSON || ! messageJSON.currentVidTime)
return; //-- Message is not for us.
/*--- We have a time value, set it with GM_setValue ()
But, WARNING: First make sure that the stored value is
a safe string. GM_setValue() crashes on just about anything else.
*/
var safeValue = JSON.stringify (messageJSON.currentVidTime);
GM_setValue ("videoMarkedTime", safeValue);
console.log ("Video time recorded with GM_setValue ().");
}
... ...
You can see the stored value by opening about:config
and searching for videoMarkedTime
.