Youtube onYouTubePlayerReady() function not firing - jsp-tags

This question has been asked many times before, however I couldn't solve it even after referring the solutions.
I have an embedded Youtube Player. I am following
https://developers.google.com/youtube/js_api_reference#Examples.
Below is my JS code:
var params = {
scale:'noScale',
salign:'lt',
menu:'false',
allowfullscreen :'true',
wmode :'transparent',
allowScriptAccess: 'always'
};
var atts = { id: "myytplayer" };
swfobject.embedSWF("http://www.youtube.com/v/vPxGBYJ9Wt8?enablejsapi=1&playerapiid=ytplayer&version=3", "ytapiplayer", "560", "315", "8.0.0", null, null, params, atts);
function onYouTubePlayerReady(playerId) {
alert("youtube player ready");
ytplayer = document.getElementById("myytplayer");
ytplayer.addEventListener("onStateChange", "onytplayerStateChange");
}
var count = 0;
function onytplayerStateChange(newState) {
alert("inside");
if (newState == 1){
count = count + 1;
//Trying to count the number of times video is played
}
}
I can watch the video, but I am not able to get any of the alert messages.
It is being served from a Web Server. Also, the JS code is written within a JSP page. What are the things I should check?
Update
I tried the same code in a separate fie and it works just fine.

I solved the problem by putting the window.onYouTubePlayerReady inside $(document).ready(function())

Related

Chrome Plugin Manifest V3 - strange behavior of a promise function in popup.js

I'm trying to create a small plugin to make my day-to-day job easier. I have faced a very strange situation within the popup.js script. The promise function randomly refuses to get executed. I have spent some hours trying to debug or at least understand where the issue could be but without any results.
Here is the skeleton of the code:
document.addEventListener('DOMContentLoaded', function () {
// some initialization
document.getElementById("signinbutton").addEventListener("click", function(event) {
try {
// some more initialization
var user_email = '';
var advertiserId = '';
var checkibm = '';
user_email = $('#emailfield').val().trim();
advertiserId = $('#advertiseridfield').val().trim();
checkibm = $('#checkibm').is(':checked');
if (advertiserId && checkibm) {
_act = 'getTokenIdByAdvId',
_data = advertiserId
}
else if (advertiserId && !checkibm) {
_act = 'getTokenIdByAdvId',
_data = advertiserId
}
else if (user_email && validateEmail(user_email))
{
_act = 'getTokenIdByEmail',
_data = user_email
}
else
{
throw new Error("Valid input has not been provided");
}
sendMessagePromise({
act : 'getTokenIdByAdvId',
data: '16910'//encodeURIComponent(user_email)
})
.then(responseHandler)
.then(responseReplaceTokenHandler)
.then(show_ok('Done'))
.catch(failureCallback);
}
catch (error){
//doing some error catching here
});
});
The code above works perfectly. However, as soon as I fill in the real values in sendMessagePromise e.g
//_act and _data show the proper values when inspected
sendMessagePromise({
act : _act,
data: _data//encodeURIComponent(user_email)
})
the flow skips execution of sendMessagePromise and any other chained function, except the last one ".then(show_ok('Done'))", i.e the only result is the "Done" message on the screen.
I made sure the values are correct. I'm able to debug step-by-step and see the values being properly supplied. I have also put a bunch of console messages inside the chain promise functions to see where the execution gets stuck, but it seems like it doesn't even start executing sendMessagePromise.
As soon as I replace expression back to hardcoded values i.e
sendMessagePromise({
act : 'getTokenIdByAdvId',
data: '16910'//encodeURIComponent(user_email)
})
it starts working again. I'm really stuck and not sure how to debug or which steps to take further.
Please assist

How to play back time-related events

To get familiar with Node.js I'm working on a little project where users can play a piano in their browser and all connected users get to hear the keys played. For this I'm using Express with Socket.io.
So far so good: communication works and sounds are heard by all users. My next challenge is to let a user record him playing the piano and then play it back to all connected users.
The recording itself is rather straightforward:
user.socket.on('keyDown', function (message) {
user.socket.broadcast.emit('keyDownReceived', JSON.stringify(message));
if (user.isRecording) {
var key = message.key;
var time = currentTime() - user.recordingStartTime;
user.recording.timeOffsets.push(time);
user.recording.keys.push(key);
}
});
Every time a key is pressed, I fill two arrays. One with the time offsets for each key since the record button was pressed and one with the key. This later gets saved to MongoDB.
My question is how I would go about playing this back to the user. My initial idea was to do the following:
user.socket.on('playRecording', function () {
user.playRecordingStartTime = currentTime();
var interval = setInterval(function () {
var time = currentTime() - user.playRecordingStartTime;
var index = user.recording.timeOffsets.indexOf(time);
if (index != -1) {
var message = {key: user.recording.keys[index]};
user.socket.broadcast.emit('keyDownReceived', JSON.stringify(message));
}
}, 1);
});
So essentially I'm firing a timer every millisecond and doing a reverse lookup in the array to see if a key has been pressed at that time. As you might imagine, this is not ideal and often times keys are skipped because the execution takes too long.
How should such a problem be tackled in Node.js?
Edit: As suggested by Steven, I could just use setTimeout. How embarrassing
user.socket.on('playRecording', function () {
user.recording.timeOffsets.forEach(function (offset, index) {
setTimeout(function () {
var message = {key: user.recording.keys[index]};
user.socket.emit('playKey', JSON.stringify(message));
user.socket.broadcast.emit('keyDownReceived', JSON.stringify(message));
}, offset);
});
});
In your specific case I would recommend looping over the notearray you are playing and creating a new setTimeOut() with each time interval of the including note.
As an example:
var arrNotes = [{ note: "do", time: 1500 }, { note: "re", time: 2500 }],
length = arrNotes.length,
i = 0;
for (var i = 0; i < length; i++){
(function () {
var t = i;
setTimeout(function () {
playNote(arrNotes[t].note);
}, arrNotes[t].time);
})();
}
function playNote(note) {
console.log(note);
}

handling asynchronous call backs in nodejs

I am newbie to nodejs.It's very hard to handle callbacks at nodejs level. I have code like this,
getItems(request,function(jsonObject){
var itemData={};
var itemDetails=new Array();
for(var i=0;i < jsonObject.length;i++){
getItemDetails(jsonObject[i].value.item_id,function(jsonObject){
itemDetails.push(jsonObject);
});
}
itemData["itemDetails"]=itemDetails;
response.contentType("application/json");
response.send({"data":itemData});
});
while executing the above code, the for loop is continuing with out getting callback from getItemDetails method and response sent to client. My requirement is the loop will wait until getting the call back from the getItemDetails then response should send.
I have tried with process.nextTick(), but i am unable to find where i have to use that process.nextTick().. Please anybody provide suggestions.
Thanks in advance.
You need to send the response only after you get all the items, so modify your code like so:
getItems(request,function(jsonObject) {
var itemData = {},
itemDetails = [],
itemsLeft = len = jsonObject.length,
i;
function sendResponse(itemDetails) {
itemData["itemDetails"] = itemDetails;
response.contentType("application/json");
response.send({ "data": itemData });
}
for (i = 0; i < len; i++) {
getItemDetails(jsonObject[i].value.item_id, function(jsonObject) {
itemDetails.push(jsonObject);
// send response after all callbacks have been executed
if (!--itemsLeft) {
sendResponse(itemDetails);
}
});
}
});
Note: I've used itemLeft here since it's a more generic way to solve these kind of problems, but Ianzz approach is also ok since you can compare the length of the two arrays.
You can't get the loop to wait, but you can modify your code to get the behavior you are expecting:
getItems(request,function(outerJsonObject){
var itemData={};
var itemDetails=new Array();
for(var i=0;i < outerJsonObject.length;i++){
getItemDetails(jsonObject[i].value.item_id,function(innerJsonObject){
itemDetails.push(innerJsonObject);
if (itemDetails.length == outerJsonObject.length) {
// got all item details
itemData["itemDetails"]=itemDetails;
response.contentType("application/json");
response.send({"data":itemData});
}
});
}
});

Using userscript GM_functions inside the page context

I want to "re-link" everything in a specific page through a XMLHTTPRequest to a local network domain. That would lead me to GM_xmlhttpRequest in GreaseMonkey/NinjaKit except that I want to run it when the link is clicked, not when the userscript actually runs...
So I have something like:
links = document.getElementsByTagName('a');
for (i = 0; i < links.length; i++) {
oldhref = links[i].getAttribute('href');
links[i].setAttribute('href', 'javascript:loadLink(' + oldhref + ')');
}
I understand I can either use unsafeWindow or add a script element to document to inject loadLink function.
But how can I use GM_xmlhttpRequest in loadLink?
I've looked at 0.7.20080121.0 Compatibility page but I'm not sure if that is for what I need...
I've also considered adding an iframe to the page and the modified links would load inside the iframe (triggering the userscript again), but I'd prefer a cleaner solution...
You almost never need to use GM functions inside the page context, and from the code posted so far, you don't need unsafeWindow in this case either.
Also, it is not necessary to rewrite the href for what is posted so far.
Something like this will accomplish what you want:
var links = document.getElementsByTagName ('a');
for (var J = 0, len = links.length; J < len; ++J) {
links[J].addEventListener ("click", myLoadLink, false);
}
function myLoadLink (zEvent) {
zEvent.preventDefault();
zEvent.stopPropagation();
var targetHref = zEvent.currentTarget.getAttribute ('href');
GM_xmlhttpRequest ( {
//wtv
} );
return false;
}
Or with jQuery:
$("a").click (myLoadLink);
function myLoadLink () {
var targetHref = $(this).attr ('href');
GM_xmlhttpRequest ( {
//wtv
} );
return false;
}
Ok, so I managed to get that GreaseMonkey official workaround working (dunno what I did wrong the first time) with:
unsafeWindow.loadLink = function(href) {
setTimeout(function(){
GM_xmlhttpRequest({
//wtv
});
},0);
}
But I'd still prefer a solution without using unsafeWindow if there is one... (especially since this one feels so wrong...)

chrome extension connection issues

I have written an extension for google chrome and I have a bug I need a help solving.
what I do is using either a text selection or an input of text search for photos on flickr and then create a results tab.
The extension works most of the times. but sometimes it creates a blank tab with no results and when I repeat the same search it then shows results. I figured that it's something to do with the html files messaging maybe something to do with them communicating. I have to say that I always receive the results from flickr so that the request/responce with flickr works ok. Sometimes the error happens when I play with other tabs or do something on other tabs while waiting for results. can you please help me figure out where's the fault?
the background file:
function searchSelection(info,tab){
var updated;
if(info.selectionText==null){
var value = prompt("Search Flickr", "Type in the value to search");
updated=makeNewString(value);
}
else{
updated=makeNewString(info.selectionText);
}
var resultHtml;
var xhReq = new XMLHttpRequest();
xhReq.open(
"GET",
"http://api.flickr.com/services/rest/?method=flickr.photos.search&text="+updated+
"&api_key=a0a60c4e0ed00af8d70800b0987cae70&content_type=7&sort=relevance&per_page=500",
true);
xhReq.onreadystatechange = function () {
if (xhReq.readyState == 4) {
if (xhReq.status == 200) {
chrome.tabs.executeScript(tab.id, {code:"document.body.style.cursor='auto';"});
var photos = xhReq.responseXML.getElementsByTagName("photo");
if(photos.length==0){
alert("No results found for this selection");
chrome.tabs.executeScript(tab.id, {code:"document.body.style.cursor='auto';"});
return;
}
var myJSPhotos=[];
for(var i=0; i<photos.length; i++){
var data={"id":photos[i].getAttribute("id"),"owner":photos[i].getAttribute("owner"),
"secret":photos[i].getAttribute("secret"),"server":photos[i].getAttribute("server"),
"farm":photos[i].getAttribute("farm"),"title":photos[i].getAttribute("title")};
myJSPhotos[i]=data;
}
chrome.tabs.create({"url":"results.html"},function(thistab){
var port= chrome.tabs.connect(thistab.id);
port.postMessage({photos:myJSPhotos});
});
}
};
};
xhReq.send(null);
chrome.tabs.executeScript(tab.id, {code:"document.body.style.cursor='wait';"});
}
var context="selection";
var id = chrome.contextMenus.create({"title": "search Flickr", "contexts":[context,'page'],"onclick":searchSelection});
results html: has only a reference to the js file res.js
res.js :
chrome.extension.onConnect.addListener(function(port) {
port.onMessage.addListener(function(msg) {
//*****//
var photos=msg.photos;
createPage(photos);
});
});
I have to mention that when the tab is empty if I put alert on the //*****// part it won't
fire.
but when I print out the photos.length at the tab create call back function part it prints out the correct result.
Try to set "run_at":"document_start" option for your res.js in the manifest.
I think callback from chrome.tabs.create is fired right away without waiting for page scripts to be loaded, so you might try something like this instead:
//global vars
var createdTabId = null;
var myJSPhotos = null;
xhReq.onreadystatechange = function () {
//assign myJSPhotos to a global var
chrome.tabs.create({"url":"results.html"},function(thistab){
createdTabId = thistab.id;
});
}
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if(changeInfo.status == "complete" && tab.id == createdTabId) {
createdTabId = null;
//now page is loaded and content scripts injected
var port = chrome.tabs.connect(tab.id);
port.postMessage({photos:myJSPhotos});
}
});

Resources