YouTube Javascript API onstateChange event problems - javascript

My javascript:
function onYouTubePlayerReady()
{
playerObj = document.getElementById("player_embed");
playerObj.addEventListener("onStateChange", test);
// Make sure the document is loaded before any DOM-manipulation
$(document).ready(function() {
// Update player information every 500ms
setInterval(updatePlayerInfo, 500);
});
}
function test(newState)
{
alert(newState);
}
My videos are loaded correctly and I can control fine them through my javascript. However the onStateChange event never seems to trigger. It never comes up with an alert when I'm playing/stopping/pausing videos etc. Anyone with a solution/similar problem?

You must pass the function name as a string to addEventListener.
playerObj.addEventListener("onStateChange", "test");

This format is for JQuery but the logic is same, create a function inside onYouTubePlayerReady to pass the playerId
$(document).ready(function() {
onYouTubePlayerReady = function(playerId) {
eventHandler=function(state){onStateChangeID(state,playerId);}
playerObj = document.getElementById("player_embed");
playerObj.addEventListener('onStateChange','eventHandler',false);
}
onStateChangeID=function(newState,playerId) {
console.log("onStateChange: ("+playerId+") " + newState);
}
});

Related

Javascript & Soundcloud Widget: How to load new track into SC Widget iFrame (via URL)

I’ve seen different web apps like Playmoss, Whyd, and Songdrop etc. that, I believe, HAVE to utilize the Soundcloud Embedded Widget in order to produce the functionality of playing multiple tracks, in sucession, not apart of a set/(playlist). Currently I am having issues reproducing this functionality with the following library, so I decided to attempt to write my own:
https://github.com/eric-robinson/SCLPlayer
I am very new to writing javascript, but my below code, will load a first track, and play it once hitting the “ready” bind. Once hitting the “finish” bind, It will then jump to the loadNextTrack() function and load the next tracks URL, into the src of the widget’s iFrame. After that, it doesn’t ever hit the original “ready” bind, which would then begin playback.
So to clear things up, playback doesn’t begin for the second track.
<script type = "text/javascript">
var SCLPlayer = {
isPlayerLoaded : false,
isPlayerFullLoaded : false,
needsFirstTrackSkip : true,
isPaused: true,
scPlayer : function() {
widgetContainer = document.getElementById('sc');
widget = SC.Widget(widgetContainer);
return widget;
},
loadNextTrack : function() {
var ifr = document.getElementById('sc');
ifr.src = 'http://w.soundcloud.com/player/?url=https://api.soundcloud.com/tracks/231758952';
console.log ('Loading Next Track');
SCLPlayer.scPlayer().bind(SC.Widget.Events.READY, function() {
console.log ('Player is Ready, next Track');
SCLPlayer.scPlayer().play();
});
}
};
$( '#sc' ).ready(function() {
SCLPlayer.scPlayer().bind(SC.Widget.Events.READY, function() {
SCLPlayer.isPlayerLoaded = true;
//window.location = 'sclplayer://didLoad';
console.log ('Player is Ready');
SCLPlayer.scPlayer().play();
});
SCLPlayer.scPlayer().bind(SC.Widget.Events.PLAY, function() {
SCLPlayer.isPaused = false;
//window.location = 'sclplayer://didPlay';
console.log ('Player did Play');
});
SCLPlayer.scPlayer().bind(SC.Widget.Events.PAUSE, function() {
SCLPlayer.isPaused = true;
//window.location = 'sclplayer://didPause';
console.log ('Player did Pause');
});
SCLPlayer.scPlayer().bind(SC.Widget.Events.FINISH, function() {
SCLPlayer.isPaused = true;
//window.location = 'sclplayer://didFinish';
console.log ('Player did Finish');
SCLPlayer.loadNextTrack();
});
});
</script>
</head>
<body>
<iframe id = "sc" width="100%" height="100%" scrolling="no" frameborder="no" src="http://w.soundcloud.com/player/?url=https://api.soundcloud.com/tracks/226183306"></iframe>
</body>
The whole point of me writing this Javascript is so that I can then use a Swift to Javascript bridge in my iOS app to then control the loading of tracks into the embedded players. For some reason over a slower connection, the next track doesn't always load into the player, using the "bridge". I hope to provide the nextTrackURL to the javascript side of things before the currentTrack finishes, so that the bridge conveys nothing and the Javascript handles new track loading, solely on its own.
I think you want to use the load function to specify the url for the new track
From the soundcloud Widget API docs:
load(url, options) — reloads the iframe element with a new widget specified by the url. All previously added event listeners will continue working. options is an object which allows you to define all possible widget parameters as well as a callback function which will be executed as soon as new widget is ready. See below for detailed list of widget parameters.
var url = "https://api.soundcloud.com/";
var options = [];
// if a track
url += "tracks/";
// if a playlist
url += "playlists/"
// append the id of the track / playlist to the url
url += id;
// set any options you want for the player
options.show_artwork = false;
options.liking = false;
options.auto_play = true;
widget.load(url, options, OPTIONAL_CALLBACK_FUNCTION);
Edited to show binding...
The bind code is called once, after the widget is initially loaded.
The ready event is only called once, when the widget is initially loaded, it is not called for each subsequent call using load().
try {
widget.bind(SC.Widget.Events.FINISH,
function finishedPlaying() {
// your code / function call
}
);
widget.bind(SC.Widget.Events.PAUSE,
function paused() {
// your code / function call
}
);
widget.bind(SC.Widget.Events.PLAY,
function playing() {
// your code / function call
widget.getCurrentSound(function scCurrentSound(sound) {
// this also binds getCurrent sound which is called
// each time a new sound is loaded
});
}
);
widget.bind(SC.Widget.Events.PLAY_PROGRESS,
function position(pos) {
// your code / function call
}
);
widget.bind(SC.Widget.Events.SEEK,
function seek(pos) {
// your code / function call
}
);
widget.bind(SC.Widget.Events.READY,
function ready() {
// your code / function call
}
);
} catch(e) {
// exception handler code
}

Sequencing two action on a button click

Problem: I have a asp.net button and on click of that I am displaying another window using window.open() at the client side using <script></script>
"I actually, need a popup (alert message) to be displayed on my parent page where my button is located once the user closes the child window."
Couple of things I tried are as follows:
I tried using setTimeOut() to have a time out for some milliseconds. This does not work as the control is not waiting until the time out is complete. It just proceeds to execute next set of code.
I tried using setInterval() but for some reason it is not working for me. Below is the code snippet of that:
$(document).ready(function () {
$('#<%=btnClick.ClientID%>').bind('click', function () {
var newWindow = window.open("http://www.google.com/", "google", 'resizable=1,width=900,height=800,scrollbars=1', '_blank');
newWindow.moveTo(0, 0);
var test = setInterval(function (e) {
if (newWindow.closed) {
alert("HEYY");
clearInterval(test);
__doPostBack("<%= btnClick.UniqueID %>", "");
}
else {
e.preventDefault();
}
}, 5000);
});
});
.
I also tried making an ajax call to open the new window and make it async : false, it again did not help me.
Bring your window and timer variable out of scope of the event handler. You need to do a polling i.e. periodically keep on checking if the windows has been closed. Using setInterval to do a polling will do the job.
var newWin, pollTimer;
$('#btnId').bind('click', function () {
newWin = window.open("...", "...", "");
pollTimer = window.setInterval(function() {
if (newWin.closed) {
window.clearInterval(pollTimer);
callCodeWhenPopupCloses();
}
}, 5000);
});
function callCodeWhenPopupCloses() {
alert("Popup closed.");
...
}

BigVideo.js .on("ended") fires multiple times

I'm using BigVideo.js jQuery plugin to show full screen background videos. I have links that load different background videos on click. At the end of each video (3-5 sec long) I'm loading an animation. Each video has its own animation on top.
Right now I'm fading in the animations with a time out that corresponds to the video length but it's not full proof. What I really need is for #anim03 to fade in when video-03.mp4 ends. But I can't figure out exactly how the BigVideo.js .on("ended") event really works. In the code I have below (simplified):
// init plugin
var BV = new $.BigVideo({useFlashForFirefox:false});
BV.init();
function setupVideo(url) {
if (Modernizr.touch) {
BV.show(url + '.jpg');
} else {
BV.show(url + '.mp4',{
altSource: url + '.webm',
ambient: false
});
}
}
function setupAnimation(num) {
BV.getPlayer().on("ended", function () { // event from video.js API - when video ends playing
$('#anim0' + num).animate({ opacity: 1 });
});
}
$('a').on('click', function(e) {
e.preventDefault();
// we remove .ext cause we got to setup .webm and .jpg versions
var url = $(this).attr('href').replace('.mp4', '');
setupVideo(url);
var current = $(this).parent().index()+1;
setupAnimation(current);
});
The event is triggered but it seems to go through some sort of queue and fire multiple times. If I console.log num like that:
function setupAnimation(num) {
console.log(num);
BV.getPlayer().on("ended", function () {
$('#anim0' + num).animate({ opacity: 1 });
});
}
I get a single expected value. But if I do it like that:
function setupAnimation(num) {
BV.getPlayer().on("ended", function () {
console.log(num);
$('#anim0' + num).animate({ opacity: 1 });
});
}
Then I get multiple values for num and each time I click and this function is called, I get more and more… I'm guessing this .on("ended") loops through some array or something? I can't figure out that part from looking at the plugin's code.
Any help or pointer much appreciated!
When you use the player's "on" function you register a new listener function (This gives you the possibility to trigger multiple functions when something happens).
The reason your on "ended" function fires multiple times, is because each time setupAnimation executed it adds a new instance of the listener-function:
function () {
console.log(num);
$('#anim0' + num).animate({ opacity: 1 });
}
check the API documentation of Video.JS
https://github.com/videojs/video.js/blob/master/docs/api/vjs.Player.md#on-type-fn-
If I get right what you're trying to accomplish, the solution is to run 'setupAnimation' outside the on 'click' function.

JavaScript/HTML - Alert box goes before sound?

The code:
x = new Audio("bar.wav")
x.play()
alert("foo")
Why does the alert box show up first and then then sound is played??
That's because the sound file is loaded asynchronously by JavaScript and then the code continues to execute. The alert fires first because it takes a while to load the sound file.
To fix it, you need to add an event listener on load, like so:
x.addEventListener('load', function() {
x.play();
alert("foo");
});
Or you could add the event listener to the onplay event, like so:
x.onplay = function () { alert("foo"); };
x.play();
You should wait for the playing event. Thats when the sound actually starts playing.
But just an advice that alert boxes pause code execution and could really mess up with sound.
x = new Audio("bar.wav")
x.onplaying = function ()
{
alert("foo");
}
x.play();
EDIT: on this post, a onloadeddata event is used, its more intesting than the example below, but i havent tested it: HTML5 Audio events not triggering on Chrome
--
As you can't assign an onload event, you have to do this:
$(function(){
youraudioelement = new Audio("bar.wav")
var audioReady = function(){
if (youraudioelement.attr('readyState')) {
alert("foo");
} else {
setTimeout(audioReady, 250);
}
}
audioReady();
}
HTML5 Audio onLoad
Just use :
x.onended = function () { alert("foo"); };
x.play();

Make callback after play button is pushed - Youtube embed video

Is it possible to do a javascript action after play button is pushed? I know I will need to use onStateChange function form Youtube's API. But I really don't know where to start? Any help? Thank you.
--
I have also found something here: http://apiblog.youtube.com/2011/01/introducing-javascript-player-api-for.html
Here's a solution that you should be able to extend easily: http://jsbin.com/evagof
Hey here is the answer .
http://jsfiddle.net/masiha/4mEDR/
Enjoy ...let me know if you have more qtns
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
<script type="text/javascript">
google.load("swfobject", "2.1");
</script>
<script type="text/javascript">
// Update a particular HTML element with a new value
function updateHTML(elmId, value) {
document.getElementById(elmId).innerHTML = value;
}
// This function is called when the player changes state
function onPlayerStateChange(newState) {
updateHTML("playerState", newState);
if(newState === 1){
//if the player is now playing
//add your code here
}
}
// This function is automatically called by the player once it loads
function onYouTubePlayerReady(playerId) {
ytplayer = document.getElementById("ytPlayer");
// This causes the updatePlayerInfo function to be called every 250ms to
// get fresh data from the player
setInterval(updatePlayerInfo, 250);
updatePlayerInfo();
ytplayer.addEventListener("onPlayerStateChange");
}
// The "main method" of this sample. Called when someone clicks "Run".
function loadPlayer() {
// The video to load
var videoID = "ylLzyHk54Z0"
// Lets Flash from another domain call JavaScript
var params = { allowScriptAccess: "always" };
// The element id of the Flash embed
var atts = { id: "ytPlayer" };
// All of the magic handled by SWFObject (http://code.google.com/p/swfobject/)
swfobject.embedSWF("http://www.youtube.com/v/" + videoID +
"?version=3&enablejsapi=1&playerapiid=player1",
"videoDiv", "480", "295", "9", null, null, params, atts);
}
function _run() {
loadPlayer();
}
google.setOnLoadCallback(_run);
</script>
<div id="videoDiv">Loading...</div>
<p>Player state: <span id="playerState">--</span></p>
http://code.google.com/apis/ajax/playground/?exp=youtube#polling_the_player
Maybe Youtube made some changes since this question was posted, but most of the answers didn't work. I found that the easiest way was to use the iframe_api (https://developers.google.com/youtube/iframe_api_reference)
Here is an example
https://thimble.webmaker.org/en-US/project/39354/edit

Categories