YouTube API loadVideoById some times not working? - javascript

I am working on this code. Some times the videos play well but some times it's showing a white screen and I am getting this type of error message:
player.loadVideoById is not a function.
My HTML code:
<i class="fa fa-play-circle-o" id="play_btn" onclick="playyoutubevideo('<?php echo $topic_names1['youtube_video_id']?>');"></i>
This is my javascript code:
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
videoId: $('#video_id').val(),
playerVars: { 'fs':'0' },
events: {
'onStateChange': onPlayerStateChange
}
});
}
// when video ends
function onPlayerStateChange(event) {
if(event.data === 0) {
$('#popup_close').click();
}
}
function playyoutubevideo(video_id)
{
$("body").css("position", "fixed");
if(player)
{
var fn = function(){ player.loadVideoById(video_id); }
setTimeout(fn, 500);
}
$(".pos_popup").removeClass("none1");
$(".pos_popup1").removeClass("none1");
}
If anyone knows the mistake, please help me to solve this issue.

Related

YouTube Player API - Seek and then play

I'm having an issue when trying to use .seekTo() with the YouTube Player API. The first time I set the .seekTo() the video will correctly seek to the value (e.g. 4 seconds) and then play [without me issuing .playVideo()]. The video is stopped when I call .seekTo() the 2nd time and the video plays from the start. I want to be able to start the video again from the seek location.
<!DOCTYPE html>
<html>
<head>
<scriptm src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
</head>
<body>
<div id="player"></div>
<div>
<button id="btnSeek" data-seek="30.7">Seek 30</button>
<button id="btnSeek" data-seek="60">Seek 60</button>
<button id="btnSeek" data-seek="90">Seek 90</button>
<button id="btnSeek" data-seek="180">Seek 180</button>
</div>
<script>
$.getScript('//www.youtube.com/iframe_api');
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: '-HjpL-Ns6_A',
playerVars: { 'start': 159, 'autoplay': 1, 'controls': 1, 'showinfo': 0, 'rel': 0 },
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange,
}
});
}
var done = false;
function onPlayerStateChange(evt)
{
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function onPlayerReady(evt) {
// doesn't work here
// player.seekTo(30);
// lets make ure we have a function
//alert("typeof(player.SeekTo) = " + typeof(player.seekTo));
}
function stopVideo() {
player.stopVideo();
}
$(function() {
$(document).on('click', '#btnSeek', function() {
if(player.getCurrentTime() == player.getDuration())
{
player.playVideo();
}
player.seekTo($(this).data('seek'), true);
});
});
</script>
</body>

Youtube API: Dynamic naming and looping

I apologize in advance, I am not very good with scripting, so I hope this isn't too basic of a request.
I am in a situation where I need to have multiple looping clickable youtube video. I do not want to use the embeddable playlist looping option because it has a few seconds of black where it refreshes the video in the playlist, which in this case would be itself.
I found a few articles on here that show you how to do create multiple videos dynamically using a data attribute, and how to loop specific times within a youtube video, but when I try to combine these, I get an error, which I am assuming is a scope issue but have no idea how to fix. Below is my code, along with the links to each original fiddles.
The error I am receiving is:
"Uncaught ReferenceError: players is not defined"
<div style="position: relative;display:block;width: fit-content;margin:0 auto;">
<a href="#"><div style="width: 100%;height:100%;position:absolute;"></div>
</a>
<div class="video-container">
<div data-id="YE7VzlLtp-4"></div>
</div>
</div>
<script src="https://www.youtube.com/iframe_api"></script>
<script>
function onYouTubeIframeAPIReady() {
var players = document.querySelectorAll('.video-container div')
for (var i = 0; i < players.length; i++) {
new YT.Player(players[i], {
videoId: players[i].dataset.id,
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
},
playerVars: {
'autoplay': 1,
'loop': 1,
'controls': 0,
'showinfo': 0,
'modestbranding': 1}
});
}
}
function onPlayerReady(event) {
loopStart();
players.playVideo();
}
function loopStart() {
players.seekTo(7); // Start at 7 seconds
}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
setTimeout(loopStart, 5000); // After 5 seconds, restart the loop
}
}
</script>
Multiple Videos using Data Attribute Example:
https://jsfiddle.net/nightcoregirl/jyha6xj5/
Looping Example:
http://jsfiddle.net/pbosakov/Lo6gwtff/
Thanks in advance for any isight!
Your specific issue is scope of variable players. players is not visible in onPlayerReady. To retrieve the player from event object, use event.target :
Javascript
function onYouTubePlayerAPIReady() {
players = document.querySelectorAll('.video-container div')
for (var i = 0; i < players.length; i++) {
var player = new YT.Player(players[i], {
videoId: players[i].dataset.id,
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
},
playerVars: {
'autoplay': 1,
'loop': 1,
'controls': 0,
'showinfo': 0,
'modestbranding': 1
}
});
}
}
function onPlayerReady(event) {
loopStart(event.target);
event.target.playVideo();
}
function loopStart(player) {
player.seekTo(7); // Start at 7 seconds
}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
setTimeout(function() {
loopStart(event.target);
}, 5000); // After 5 seconds, restart the loop
}
}
HTML
<script src="https://www.youtube.com/iframe_api"></script>
<div class="video-container">
<div data-id="YE7VzlLtp-4"></div>
</div>
<div class="video-container">
<div data-id="3IXKIVZ9T-U"></div>
</div>
Check this fiddle

Need to refresh the page to see a YouTube live event that has just begun

I’m using YT.player to show live events on the website : http://www.solarimpulse.com/rtw
Since youtube changes the display of live event the countdown on the YT.player is not dynamic anymore. I need to reload the page to see the countdown going down. And worse than that when I start the live event nothing append in the player, I need to reload the page to see the video.
Last year the countdown and the player was working fine, I didn’t change the code since then :
var player = {
playVideo: function (container, videoId) {
if (typeof(YT) == 'undefined' || typeof(YT.Player) == 'undefined') {
window.onYouTubePlayerAPIReady = function () {
player.loadPlayer(container, videoId);
};
$.getScript('//www.youtube.com/player_api');
} else {
player.loadPlayer(container, videoId);
}
},
loadPlayer: function (container, videoId) {
youtubePlayerSatcom = new YT.Player(container, {
playerVars: {
controls: 1,
rel: 0,
autoplay: 1,
playsinline: 1,
modestbranding: 1, // disable watch on youtube
fs: 1, // fullscreen
cc_load_policy: 0,
iv_load_policy: 3, // annotations
showinfo: 0 // don't show loading
},
height: '100%',
width: '100%',
videoId: videoId,
events: {
'onStateChange': function (event) {
if (event.data === 0) {
youtubePlayerSatcom.loadVideoById(videoId, 0);
}
}
}
});
}
};
player.playVideo('satcom-player', videoId);
How can I fix that ?
Thank you for your help.
I made a small fix to reload the video if it hasn't started yet. It's not very clean as the player get black and load again but it works. The countdown get dynamic like that.
$.doTimeout('youtube_notplaying', 20*1000, function () {
if (typeof youtubePlayerSatcom != 'undefined') {
if (youtubePlayerSatcom.getPlayerState() == -1) {
if (debug_interface) console.log('load '+videoId);
youtubePlayerSatcom.loadVideoById(videoId);
} else if (youtubePlayerSatcom.getPlayerState() != -1) {
return false; // stop timeout
}
}
return true; // repeat
}, true);

Lose context of this when youtube constructor method is called

I have created a youtube player using the youtube iframe api, I am listening for the ENDED event but I've realised that I lose the reference to this which becomes the window but I'm really unsure how to resolve this. I've tried binding this to the contsructor etc but with no joy whatesoever so could really do with you guys help.
JS
startPlayer: function (videoId) {
var instance = this;
console.log('startPlayer', instance);
if( instance.flags.isPlaying ) {
instance.selectors.playerCtn.empty();
instance.flags.isPlaying = false;
}
instance.selectors.playerCtn.append('<div id="player"></div>');
instance.player = new YT.Player('player', {
height: '390',
width: '640',
videoId: videoId,
events: {
'onReady': this.onPlayerReady,
'onStateChange': this.onPlayerStateChange
}
});
instance.flags.isPlaying = true;
},
onPlayerStateChange: function (event) {
console.log('onPlayerStateChange');
var instance = this;
console.log(instance); //undefined??
if (event.data == YT.PlayerState.PLAYING) {
console.log('PLAYING...');
}
if (event.data == YT.PlayerState.PAUSED) {
console.log('PAUSED...');
}
if (event.data == YT.PlayerState.ENDED) {
console.log('what is this', instance);
// if instance.counter === instance.playlist
if (instance.counter === instance.playlist) {
console.log('you\'ve come to the end of your playlist');
// Display message or go back to first?
return;
}
// Increase the counter
instance.counter++
// Set the new current element
instance.current = instance.selectors.listItems[instance.counter];
console.log(instance.counter);
console.log(instance.current);
// Get the new current element data-id
var videoId = instance.current.attr('data-id');
// Start the player
startPlayer(videoId);
}
if (event.data == YT.PlayerState.BUFFERING) {
console.log('BUFFERING...');
}
}
Test page http://go.shr.lc/1lh2dmu
events: {
'onReady': this.onPlayerReady.bind(this),
'onStateChange': this.onPlayerStateChange.bind(this)
}
Besides, why var instance = this;? this is quite shorter to type and you aren't using instance in any closure.

Using an array in Jquery

I'm not so experienced with Javascript and I have been struggling with this one pretty much all day.
I'm using Jquery to create and array of the ids of embedded youtube videos:
$(function() {
$('li').on("click",function(){
alert($(this).attr('data-pile'));
var pilename = $(this).attr('data-pile');
var videoIDs = [];
$("li[data-pile='"+pilename+"']").each(function(index){
videoIDs.push($(this).attr('id'));
});
$.each(videoIDs,function(){
});
});
});
And I need to use the array in this JS:
<script src="//www.youtube.com/iframe_api"></script>
<script>
/**
* Put your video IDs in this array
*/
var videoIDs = [
//my array of Ids here
];
var player, currentVideoId = 0;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '350',
width: '425',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(event) {
event.target.loadVideoById(videoIDs[currentVideoId]);
}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.ENDED) {
currentVideoId++;
if (currentVideoId < videoIDs.length) {
player.loadVideoById(videoIDs[currentVideoId]);
}
}
}
</script>
In each div where embedded videos are I'm applying an id with same id as video.
How should I make the two scripts work?
I'll really appreciate if someone can point me in the right direction.
You're declaring your videoIDs array twice, once in your click events and again in your second
script.
The one inside your click events is local to that function whereas the other one is global. Javascript has function scope, so that click event one gets discarded once that function ends.
If you remove the one inside your click events, I believe it should work. You should also remove the $.each... as I don't think it's going to help (you're trying to make a playlist, right?).
It should be noted that it's considered bad practice to pollute the global namespace by using global variables. If this is all the code you have on your page, it's probably not an issue.
Try doing it this way: add a custom listener after "click" event. Didn't check your array forming section, tested with a custom array, hope you won't have issues with it.
<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);
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '350',
width: '425',
});
}
$(function(){
$(document.body).on("click",".play", function(){
player.stopVideo();
var pilename = $(this).attr('data-pile');
var videoIDs = [];
$("li[data-pile='"+pilename+"']").each(function(index){
videoIDs.push($(this).attr('id'));
});
if(videoIDs.length > 0){
currentVideoId = 0;
player.loadVideoById(videoIDs[0]);
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.ENDED) {
currentVideoId++;
if (currentVideoId < videoIDs.length) {
player.loadVideoById(videoIDs[currentVideoId]);
}
}
}
player.addEventListener("onStateChange", onPlayerStateChange)
player.playVideo();
}
});
});
</script>

Categories

Resources