Youtube Iframe Player API - Onstatechange Not Firing

YouTube iframe player API - OnStateChange not firing

There was a temporary issue with the iFrame Player API (which was fixed in June 2013) that you can read about here: https://code.google.com/p/gdata-issues/issues/detail?id=4706

Jeff Posnick posted a temporary workaround here:
http://jsfiddle.net/jeffposnick/yhWsG/3/

As a temporary fix, you just need to add the event listener within the onReady event:

function onReady() {
player.addEventListener('onStateChange', function(e) {
console.log('State is:', e.data);
});
}

Make sure to remove the onStateChange event from the YT.PLAYER constructor (see the jsfiddle).

Also, as someone mentioned on the Google Code Issue Thread, you set an interval and poll the player for its current state instead of listening for the onStateChange event. Here is an example code snippet for doing that:

setInterval( function() {
var state = player.getPlayerState();
if ( playerState !== state ) {
onPlayerStateChange( {
data: state
});
}
}, 10);

Firefox and IE Issues

Other people have mentioned that Firefox will not instantiate the YouTube Player if it is placed in a container with the css property display: none. Internet Explorer will also not work with visibility: hidden. If you're finding this to be the issue, try positioning the container off the page with something like left: -150%.

Steve Meisner talks about this here: YouTube API does not appear to load in Firefox, IFrame gets loaded , but the onPlayerReady event never fires?

And another related SO question: YouTube iframe API - onReady and onStateChanged events not firing in IE9

Edit: I've edited this answer to be more thorough because people are still seeing this error after the original bug was fixed in 2013.

YouTube JavaScript API, onStateChange not firing, no autoplay

I was unable to get it to work as I've posted. I had to change the code to use a div rather than an iframe, add a video ID and other parameters in the playerVars. Once I did that, the video played automatically, showed no controls, and fired the state change event.

  function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
playerVars: {
autoplay: 1,
controls: 0,
showinfo: 0,
autohide: 1
},
videoId: '_S_Bg9qfa8o',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}

...

<div id="player"></div>

YouTube iFrame API 'onStateChange' not firing in Firefox

This appears to be an issue with the YouTube flash player. When flash is used (which seems to be the default) the API does not work.

However, when HTML5 mode is requested, the stateChange event does fire.

<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>

<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');

tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
playerVars: {
html5: 1
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}

// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
}

// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
</script>

Here is the OP's jsfiddle, but modified to use the HTML5 player. With the HTML5 player, the video does pause after 6 seconds like it should.

YouTube iframe API - onReady and onStateChanged events not firing

I see several problems in your code, but I'm not sure which one of them is the one that's bothering you.

First of all, you're not supposed to call onYouTubeIframeAPIReady directly.

Instead, you should execute the following and let the browser do it asynchronously:

var scriptElement = document.createElement("script");
scriptElement.src = "http://www.youtube.com/iframe_api";
var firstScriptElement = document.getElementsByTagName("script")[0];
firstScriptElement.parentNode.insertBefore(scriptElement,firstScriptElement);

Second, I believe that you should initialize at least the following player parameters:

playerVars:
{
"enablejsapi":1,
"origin":document.domain,
"rel":0
},
events:
{
"onReady":onPlayerReady,
"onError":onPlayerError,
"onStateChange":onPlayerStateChange
}

Here is the complete relevant piece of code that I have been using:

<body onload="LoadYouTubeIframeAPI()">
<div id="player">Loading Video Player...</div>
<script type="text/javascript">
var player = null;
function LoadYouTubeIframeAPI()
{
var scriptElement = document.createElement("script");
scriptElement.src = "http://www.youtube.com/iframe_api";
var firstScriptElement = document.getElementsByTagName("script")[0];
firstScriptElement.parentNode.insertBefore(scriptElement,firstScriptElement);
}
function onYouTubeIframeAPIReady()
{
var playerParams =
{
playerVars:
{
"enablejsapi":1,
"origin":document.domain,
"rel":0
},
events:
{
"onReady":onPlayerReady,
"onError":onPlayerError,
"onStateChange":onPlayerStateChange
}
};
player = new YT.Player("player",playerParams);
}
function onPlayerReady(event)
{
...
}
function onPlayerError(event)
{
...
}
function onPlayerStateChange(event)
{
...
}
</script>
</body>

YouTube API Change Event Not Firing

@Justin -- in response to your comment, here's some code and a short explanation. There are two things to watch out for ... first of all, I generally load the iFrame API library like this:

<script>
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

This way, it won't load until the page is loaded, which is key to the second step -- when the code loads, it will automatically call the function onYouTubeIframeAPIReady, which you need to define. It's within this function that you can create your bound player object. If you try to do it outside this callback function, you A) run the risk of creating your player object before the iframe API library loads which means it couldn't trigger any player functions, and B) can't bind to elements that already exist on the page as they might not yet be loaded. It looks like this:

var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player("ytplayer", {
events: {
'onStateChange': onPlayerStateChange
}
});
}

function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
alert("now playing ...");
}
}
</script>

This assumes I've given my iframe the id of ytplayer, and that I've appended "?enablejsapi=1" to the URL of the iframe's src attribute.

Here's a working fiddle: http://jsfiddle.net/jlmcdonald/PQy4C/261/

Youtube Embed Iframe - Events Not Firing In Local

It appears that the Youtube iframe API is currently broken, though I've seen no official confirmation yet.

See also:

onReady callback not firing when having the iframe explicitly written inside a template

YouTube API onPlayerReady not firing

Edit: Here is the fix: https://code.google.com/p/gdata-issues/issues/detail?id=5670#c6

Here is a direct quote of the answer at the link above:

A quick fix is to add in the origin=http://www.example.com (replace
with your servers full domain; make sure you use http:// or https://
as appropriate for your site) to the src= attribute of the player's
iframe element. Please make sure that the origin= attribute's value
exactly matches the host domain and URL scheme. E.g.

<iframe
type="text/html"
width="640"
height="480"
src="https://www.youtube.com/embed/VIDEO_ID?enablejsapi=1&origin=https://www.example.com"
frameborder="0">
</iframe>

I'm currently working with the engineering team to figure out whether
origin= is going to be required moving forward or whether this new
requirement can be reverted, but this is the immediate fix. Apologies
for the breakage and lack of advanced communication in the meantime.

If you use the YT.Player() constructor to create the iframe element
for you then this isn't be an issue—it's a bit of an edge case for
developers who are explicitly including the iframe element as part of
their page's HTML.

I implemented the fix above, and it worked for me.



Related Topics



Leave a reply



Submit