I’ve been working on this problem for hours and can’t figure out what’s going wrong. I’m trying to create multiple YouTube video players that work with click events, but some of them just stop responding.
The Issue:
My code works perfectly for the first two video links, but links 3 and 4 throw an error: Uncaught TypeError: videoInstance.loadVideoById is not a function
. The weird part is that the exact same function works fine for the first two links.
It seems like the YouTube player objects only get created properly for the first two videos. Why would this happen?
What I’m Trying to Do:
I want users to click on text links and have YouTube videos play in a modal popup. Each video should start and stop at specific times that I define in an array.
My Current Code:
// Global variables
var videoPlayers = [];
var isCurrentlyPlaying = false;
videoConfig = [{
buttonID: "btn0",
containerID: "video1",
videoID: "dQw4w9WgXcQ",
startTime: 15,
endTime: 25
}, {
buttonID: "btn1",
containerID: "video2",
videoID: "oHg5SJYRHA0",
startTime: 5,
endTime: 15
}, {
buttonID: "btn2",
containerID: "video3",
videoID: "kJQP7kiw5Fk",
startTime: 45,
endTime: 55
}, {
buttonID: "btn3",
containerID: "video4",
videoID: "9bZkp7q19f0",
startTime: 90,
endTime: 105
}];
// Called when YouTube API is ready
function onYouTubePlayerAPIReady() {
console.log("Total videos to setup: " + videoConfig.length);
for(j = 0; j < videoConfig.length; j++) {
console.log("Setting up video #" + j);
var clickButton = document.getElementById(videoConfig[j].buttonID);
console.log("Button ID: " + clickButton.id);
var currentConfig = videoConfig[j];
console.log("Current video config:");
console.log(currentConfig);
clickButton.addEventListener("click", function() {
selectedID = $(this).attr("id").replace("btn", "");
console.log("Clicked video #" + (parseInt(selectedID) + 1));
var videoCode = videoConfig[selectedID].videoID;
var startPos = videoConfig[selectedID].startTime;
var endPos = videoConfig[selectedID].endTime;
var videoInstance = new YT.Player(videoConfig[selectedID].containerID);
console.log("Video ID: " + videoCode);
console.log("Start: " + startPos + ", End: " + endPos);
$("#videoModal").css({"display": "block"});
$("#videoModal").animate({"opacity": "0.8"}, 800, function() {
console.log("Showing video player");
$(".video-container").show();
console.log("Player object:");
console.log(videoInstance);
videoInstance.loadVideoById({
'videoId': videoCode,
'startSeconds': startPos,
'endSeconds': endPos
});
});
// Monitor player state
setTimeout(function() {
var checkCount = 0;
stateChecker = setInterval(function() {
var currentState = videoInstance.getPlayerState();
var stateDescription;
switch(currentState) {
case -1: stateDescription = "not started"; videoInstance.playVideo(); break;
case 0: stateDescription = "finished"; break;
case 1: stateDescription = "playing"; break;
case 2: stateDescription = "paused"; break;
case 3: stateDescription = "loading"; break;
case 5: stateDescription = "ready"; break;
default: stateDescription = "unknown state";
}
console.log(currentState + ": " + stateDescription);
if(currentState == 1) {
isCurrentlyPlaying = true;
}
// Close modal when video ends
if((isCurrentlyPlaying) && (currentState == 0)) {
setTimeout(function() {
console.log("Closing video modal");
$(".video-container").css({"display": "none"});
$("#videoModal").animate({"opacity": "0"}, 800, function() {
$("#videoModal").css({"display": "none"});
});
isCurrentlyPlaying = false;
}, 300);
clearInterval(stateChecker);
}
// Prevent infinite loop
checkCount++;
if((checkCount > 500) && (currentState != 1) && (currentState != 2) && (currentState != 0)) {
clearInterval(stateChecker);
console.log("State checker stopped to prevent infinite loop");
}
}, 20);
}, 900);
});
}
}
// Load YouTube API
var scriptTag = document.createElement('script');
scriptTag.src = "//www.youtube.com/player_api";
var firstScript = document.getElementsByTagName('script')[0];
firstScript.parentNode.insertBefore(scriptTag, firstScript);
I’ve been debugging this for days and I’m completely stuck. The same exact code works for some videos but not others. Has anyone seen this kind of behavior with the YouTube API before?