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
Related
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>
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.
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);
I'm trying to get youtube videos to start on hover. It will pause (not stop) when the user hovers over another video...
I am stuck on the hover command. Can someone help me work it out please?
The page has 16 videos, this is the working code from the jsfiddle that contains 3 videos as an example.
http://jsfiddle.net/sebwhite/gpJN4/
VIDEO:
<iframe id="player" width="385" height="230" src="http://www.youtube.com/embed/erDxb4IkgjM?rel=0&wmode=Opaque&enablejsapi=1;showinfo=0;controls=0" frameborder="0" allowfullscreen></iframe>
JAVASCRIPT:
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
events: {
'onStateChange': onPlayerStateChange
}
});
onYouTubeIframeAPIReady();
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING) {
player1.pauseVideo();
player2.pauseVideo();
}
UPDATED FIDDLE
Try this:
var $$ = function(tagname) { return document.getElementsByTagName(tagname); }
function onYouTubeIframeAPIReady() {
var videos = $$('iframe'), // the iframes elements
players = [], // an array where we stock each videos youtube instances class
playingID = null; // stock the current playing video
for (var i = 0; i < videos.length; i++) // for each iframes
{
var currentIframeID = videos[i].id; // we get the iframe ID
players[currentIframeID] = new YT.Player(currentIframeID); // we stock in the array the instance
// note, the key of each array element will be the iframe ID
videos[i].onmouseover = function(e) { // assigning a callback for this event
if (playingID !== currentHoveredElement.id) {
players[playingID].stopVideo();
}
var currentHoveredElement = e.target;
if (playingID) // if a video is currently played
{
players[playingID].pauseVideo();
}
players[currentHoveredElement.id].playVideo();
playingID = currentHoveredElement.id;
};
}
}
onYouTubeIframeAPIReady();
Fiddle:
http://jsfiddle.net/gpJN4/3/
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>