Youtube API not loading in firefox - javascript

I have this test slider http://jsfiddle.net/dUyLY/2/
In Chrome it works nice, but in firefox and safari it bugs out when the animation is done.
In the scripts file I check after each animation if the current visible element is the youtube player, if so play the video. And when leaving the slide pause it.
I get this error in console player.pauseVideo is not a function
Anyone has a solution to this?

You're deferring the definition of onYouTubePlayerAPIReady. For this reason, it's likely that the YouTube API finishes before onYouTubePlayerAPIReady is defined. In that case, your code will fail.
To solve the problem, check whether the API is ready at run-time.
window.onYouTubePlayerAPIReady = function () {
player = new YT.Player('player', {
height: '315',
width: '560',
videoId: 'bpOR_HuHRNs',
});
};
if (window.YT) {
// Apparently, the API was ready before this script was executed.
// Manually invoke the function
onYouTubePlayerAPIReady();
}
Note. For simple one-way functions, such as player.playVideo() and player.pauseVideo(), I recommend to use this simple function, which is not as bloated as the documented YouTube API. See this answer.
Here's a the updated part of your page, using the callPlayer function from my other answer instead of the YouTube API: http://jsfiddle.net/ryyCZ/
<div id="player">
<iframe width="560" height="315" frameborder="0" src="http://www.youtube.com/embed/bpOR_HuHRNs?enablejsapi=1"></iframe>
</div>
if ($(".slides_control > div:visible #player").length == 1) {
callPlayer("player","playVideo");
} else {
callPlayer("player", "pauseVideo");
}

Related

auto-advance to next page when iframe video ends in Qualtrics

I am trying to embed a vimeo video using iframe in my Qualtrics survey. When this video ends, I want to automatically advance to the next page (i.e., automatically press the "next button"). Before using vimeo, my videos were stored on dropbox and I used the following code for this (the url is not the real one):
<video autoplay="" id="video1" height="580" width="740"><source src="https://dl.dropboxusercontent.com/u/6339921/att/fam.mp4" type="video/mp4"></video>
Qualtrics.SurveyEngine.addOnload(function() {
that = this;
document.getElementById('video1').addEventListener('ended',myHandler,false);
function myHandler(e) {
if(!e) {
e = window.event;
}
that.clickNextButton();
}
});
However, it seems that I have to use iframe with vimeo, but I am unable to make the auto-advance work (the video will play but the page will not advance). Maybe it is because I am assigning the "ID" the wrong way. Here is the code:
<iframe id="player1" src="https://player.vimeo.com/video/20708824?autoplay=1api=1&player_id=player1&title=0&byline=0&portrait=0&background=1&mute=0&loop=0" width="600" height="400" frameborder="0"></iframe>
Qualtrics.SurveyEngine.addOnload(function() {
that = this;
var idPlayer = new Vimeo.Player('player1');
document.getElementByID('player1').addEventListener('ended',myHandler,false);
function myHandler(e) {
if(!e) { e = window.event; }
that.clickNextButton();
}
});
I am looking for a) an option to fix the iframe code, or b) an option to embed a vimeo video using the old code that I had used with dropbox videos.
Thanks so much and I apologize if this all sounds naive, I am not a programmer :-(
You can't add an event listener to an iframe from a different domain. It is called cross-domain scripting and for security reasons isn't allowed by the browser.
You have to use postMessage. There is a JavaScript class already written, but you would have figure out how to integrate it into Qualtrics:
https://github.com/vimeo/player.js

YouTube onStateChange event is suddenly not working

I had everything working fine until about two weeks ago. I haven't changed any code.
function loadYtVideo(video, advert, advert_link, splash, splash_link){
var params = { allowScriptAccess: "always", wmode: "transparent" };
var atts = { id: "eda-player", wmode: "transparent" };
var swfobject;
adv.orig = video;
swfobject.embedSWF("https://www.youtube.com/v/"+adv.orig+"?rel=0&enablejsapi=1&playerapiid=ytplayer","ytapiplayer", "719", "404", "8", null, null, params, atts);
}
function onYouTubePlayerReady(playerId) {
//It's fired
edaplayer = document.getElementById('eda-player');
edaplayer.addEventListener("onStateChange", "playerState");
}
function playerState(state) {
//it's not fired
console.log(state);
}
<div class="adv-video">
<div id="ytapiplayer">
<script>
$(document).ready(function(){
loadYtVideo($.getUrlVar('ytVideo'), 'eM2ja9LE0YE', 'http://wilmax.ru/', '', '');
});
</script>
</div>
</div>
I found posts with similar problem, but solutions in those posts are not working in this case.
Any help would be greatly appreciated.
I would suggest you move to YouTube IFrame Player API:
The IFrame player API lets you embed a YouTube video player on your website and control the player using JavaScript. Unlike the Flash and JavaScript player APIs, which both involve embedding a Flash object on your web page, the IFrame API posts content to an <iframe> tag on your page. This approach provides more flexibility than the previously available APIs since it allows YouTube to serve an HTML5 player rather than a Flash player for mobile devices that do not support Flash.
Flash API and JS API has already been deprecated. I'm not sure if it still work with the current API that is why I suggest you to use Iframe API
Here are some sources that may help you:
JS Fiddle Demo
embedding Flash
Related SO question
Hope this helps!

Get video play of youtube player

I'm creating this webpage on wordpress which have videos from youtube in some of it's posts, for tagging purposes I need to capture everytime a person clicks play on each of the videos. I've looked through the web, but all I could find is that, since this videos are on iframes from outside the main domain, it's impossible to catch something from the inside of it, like clicks.
Is there any way that I can catch this clicks on the play button without changing anything on the site? Just from JS.
Regards and thanks in advance.
You could capture some events within the iframe using youtube's js API
This is what you have to do:
1). Load the Player API in your page
<script src="http://www.youtube.com/player_api"></script>
2). Enable jsapi in your iframe as a trailing parameter (enablejsapi) like
<iframe id="myIframe" src="http://www.youtube.com/embed/opj24KnzrWo?enablejsapi=1&autoplay=0" width="420" height="280" frameborder="0"></iframe>
... also notice we added an ID to the iframe.
3). Create 3 functions :
a). onPlayerReady :
Here is where you can detect when the video has loaded and is ready to play. Here you can actually start the video, etc.
function onPlayerReady(event) {
// video is ready, do something
event.target.playVideo();
}
b). onPlayerStateChange :
Here is where you can detect what events are triggered:
function onPlayerStateChange(event) {
console.log(event.data); // event triggered
// e.g. end of video
if (event.data === 0) {
// end of video: do something here
}
}
When you click play or pause, an event is triggered. Then you can decide what action you want do, including pushing a tracking event, etc.
This is a list of the returned values of each event :
-1 – unstarted
0 – ended
1 – playing
2 – paused
3 – buffering
5 – video cued
Refer to the documentation to learn more about those events
c). onYouTubePlayerAPIReady :
This is where you actually initialize the API and bind the events to the other functions :
function onYouTubePlayerAPIReady() {
var id = document.getElementById("myIframe").getAttribute("id");
var player = new YT.Player(id, {
events: {
onReady: onPlayerReady,
onStateChange: onPlayerStateChange
}
});
} // youtube API ready
See JSFIDDLE

YouTube iFrame API behavior is inconsistent/nondeterministic

I was having trouble isolating a bug in my JavaScript code for controlling Youtube videos via the iframe/HTML5 API.
I went back to the demo code on the main documentation page:
https://developers.google.com/youtube/iframe_api_reference
...and to my surprise, I see the same inconsistent behavior even when I use the demo code from there and don't change anything.
The behavior is that some of the time, when I load this page, the player autoplays (which is the intent of the code), and other times it doesn't. It always does succeed in loading. Also, the player never seems to stop after 6 seconds, in contrary to what the comments say.
Breakpoints verify that part of the issue at least is that onPlayerReady() is not always being called. When I set a breakpoint in onPlayerReady(), it usually is not reached, and is only reached the times that the player goes on to succeed in autoplaying.
Of course, this behavior may be dependent on the speed and reliability of my internet connection, which is wired and otherwise seems decently fast. I just tested it -- 24 Mbps, and it seems pretty consistent.
If I make superficial changes to the html, that seems to sometimes prompt the page on loading to autoplay, but not always. Sometimes I will reload every few seconds 5 times in a row with no autoplay or onPlayerReady breakpoint being hit, then do it a 6th time and that time it will autoplay fine.
I'm using Chrome v30.0.1599.101 on Mac OS 10.8.4.
I know that code is in beta and in flux, and isn't supposed to be production level yet, but I was hoping there was something i can try.
Here is the code I'm using, FYI, in case the code posted on the api reference page above changes. Again, I'm not altering a single character.
<!DOCTYPE html>
<html>
<body>
<!-- 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',
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>
</body>
</html>
I was opening the page locally, which makes for different behavior in all sorts of little ways from how it works when delivered from a server. The browser client itself handles things like cacheing differently when content is local. When I put the same page on a server, it started to work every time.
In addition, FYI, for my bigger issue that led me down this rabbithole, I found that I needed to follow this advice: https://stackoverflow.com/a/14952334/2308190 ...in order to get my YouTube callback functions to be called with jQuery loaded.
I had a situation where my first YouTube iframe would load correctly, and subsequent ones would not.
The issue was caused by creating a new YT.Player before its <div> had been added to the DOM. This issue didn't occur the first time I created a YT.Player, because the YouTube API had to be loaded first. This caused a microsecond delay which allowed the rest of my code to execute, so the <div> was added to the DOM before the YouTube API finished loading.

Auto-play youtube and soundcloud embeds after one another

I have a music blog that contains a series of youtube and soundcloud embeds.
I would like to automatically play all of the embedded content on the page one after another. In other words after a youtube embed that I've played ends, I would like the next embed to start playing whether it be from soundcloud or youtube and vice versa.
The rendered HTML looks like this:
<span class="soundcloud_embed" id="soundcloud_post_308">
<iframe id="ui-id-1" width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F103518792&show_artwork=true&secret_token=s-LnOTK"></iframe>
</span>
<span class="youtube_embed" id="youtube_post_309">
<iframe id="ui-id-2" width="528" height="190" src="//www.youtube.com/embed/Y3CYKXBEtf0" frameborder="0" allowfullscreen></iframe>
</span>
<span class="youtube_embed" id="youtube_post_310">
<iframe id="ui-id-3" width="528" height="190" src="//www.youtube.com/embed/yMx1FnkrhYc" frameborder="0" allowfullscreen></iframe>
</span>
Building off help I received from this source: Pause Youtube embed when playing Soundcloud embed
To keep track of which players are on the page, which api's they belong to, and which of them is currently playing:
var playerCurrentlyPlaying = {"api":null,"frameID":null};
var players = {"yt":{},"sc":{}};
I need to define a generic playNext function that is called in the event that playerCurrentlyPlaying comes to an end. Depending on the api of the next embed, the playNext function has to execute the proper play command. In order to find which embed is next, the function can perhaps increment the ID of the currentlyPlaying iframe by 1. Such that if id="ui-id-2" has just ended then id="ui-id-3" should play.
Sometimes these youtube videos crash and say things like "video no longer exists" or "uploader has made this unavailable in your country". In these cases, how can I check for a crash and skip to the next incremented ID (e.g. id="ui-id-4") ?
This video no longer exists:
<span class="youtube_embed" id="youtube_post_311">
<iframe id="ui-id-4" width="528" height="190" src="//www.youtube.com/embed/Ym3DgqNTzyc" frameborder="0" allowfullscreen></iframe>
</span>
You've got two questions in one, here. I'll try to address them both.
In terms of making the next player auto-play, there are two small steps you'll need to take. The first is to bind your player objects to their API's respective event signaling that the media is done playing. For YouTube, your event listener would look something like this:
onYTPlayerStateChange = function (event) {
if (event.data == YT.PlayerState.PLAYING) {
onYTPlay(event.target.a.id);
}
else if (event.data == YT.PlayerState.ENDED) {
playNextPlayer();
}
};
Where playNextPlayer() is this generic function you mention you need to define. For your Soundcloud embeds, your event bindings would look something like this, now:
(function () {
$(".soundcloud_embed iframe").each(function () {
var frameid = $(this).attr('id');
players["sc"][frameid] = {};
players["sc"][frameid] = {
"widget": SC.Widget(document.getElementById(frameid)),
"firstplay": true
};
players["sc"][frameid]["widget"].bind(SC.Widget.Events.READY, function () {
players["sc"][frameid]["widget"].bind(SC.Widget.Events.PLAY, function () {
onSCPlay(frameid, SC.Widget.Events.PLAY);
});
players["sc"][frameid]["widget"].bind(SC.Widget.Events.PLAY_PROGRESS, function () {
onSCPlay(frameid, SC.Widget.Events.PLAY_PROGRESS);
});
players["sc"][frameid]["widget"].bind(SC.Widget.Events.FINISH, function () {
playNextPlayer();
});
});
});
}());
Once you've got those bindings in place, the playNextPlayer function will need to determine what the next player is, what API it comes from, and then execute that API's play call. Something like this:
playNextPlayer = function() {
var nextIdNum=parseInt(playerCurrentlyPlaying["frameID"].split("-").pop())+1;
nextFrameId="ui-id-"+nextIdNum;
switch($("#"+nextFrameId).parent().attr('class')) {
case "youtube_embed":
api="yt";
players[api][nextFrameId].playVideo();
break;
case "soundcloud_embed":
api="sc";
players[api][nextFrameId]["widget"].play();
break;
}
playerCurrentlyPlaying["api"]=api;
playerCurrentlyPlaying["frameID"]=nextFrameId;
};
Keep in mind that there's no error handling built in to this sample code; you'll have to write some to handle cases where the IDs aren't sequential, for example, or what to do when its out of iframes to play.
As to your second question -- to determine whether or not a video is playable, you'll have to set up some error event listeners as well as the playback event listeners.
function onYouTubeIframeAPIReady() {
$(".youtube_embed iframe").each(function () {
players["yt"][$(this).attr('id')] = new YT.Player($(this).attr('id'), {
events: {
'onError': seeError,
'onStateChange': onYTPlayerStateChange
}
});
});
}
The seeError function can then be defined in such a way that it determines what player threw the error (using the event.target.a.id parameter in way similar to how it's being done with the state change event listeners), and then leverages the same generic playNextPlayer function. Keep in mind that if a Youtube video doesn't exist in that way, it will NOT generate a "PLAYING" event, so you'll have to set the proper playerCurrentlyPlaying values in your error listener as well, just to make sure the system then properly advances.
The YouTube player is supposed to throw different types of errors based on whether the video doesn't exist, whether it isn't playable in a particular country, etc. See here: https://developers.google.com/youtube/js_api_reference#Events under the "onError" section to see what these different codes are supposed to be. I say 'supposed to' because it looks like, right now, it's just throwing code 0 for all "can't play" errors.
Here's a working fiddle which does all of the above (you can switch the ids of the soundcloud and youtube iframes to verify that the advancement works both directions). This fiddle also instantiates an onError listener but doesn't define what it will do. Shouldn't be hard for you to get that to work, though.
http://jsfiddle.net/jlmcdonald/NqRqm/8/

Categories