I am making an application which uses the YouTube API to gather a grid of videos from a search string. When a thumbnail is clicked, player.loadVideoByID should run, opening it in a previously defined iFrame. I'm using the player object instead of iframe directly, as I need the timestamps for future functionality (note-taking).
However, I get the error "Uncaught TypeError: player is undefined". Why is that? Function scope?
Here is the relevant HTML:
<!DOCTYPE html><html><head><title>YouTube API</title><link rel="stylesheet" href="style.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap/dist/css/bootstrap.min.css"><script type = "text/javascript"> function showNote() { document.getElementById('note-container').style.display = "block"; }</script></head><body><div class="header"><br><h1>YouTube API Search</h1><div class="search-bar"><input type="text" id="search" placeholder="Search for videos"><input type = "image" src = "search.png" id = "search-button"></button></div><div id="keywordPopup" class="popup" style="display: none;"><br><input type="text" id="customKeyword" placeholder="Enter custom keyword"><button id="submitKeyword">Submit</button><button id="cancelKeyword">Cancel</button></div><div class = "addKeyword"><button id="addKeywordButton" class="add-button">+</button></div><div class="category-buttons"><button class="category-button" data-category="Software Quality Assurance">Software Quality Assurance</button><button class="category-button" data-category="Computing">Computing</button></div></div><div class = "content"><br><div class="row"><div class="col-md-12"><div id="videos"></div></div></div></div><div id="loading" style="display: none"><p>Loading...</p></div><div id="error" style="display:none"><p>An error occurred while fetching videos.</p></div><div id="videoScreen" class="screen"><div class="screen-content"><span class="close" onclick="closeVideo()">×</span><iframe id="videoFrame" width="560" height="315" src="" frameborder="0" allowfullscreen></iframe><p><a download="info.txt" id="downloadlink"><img src="save.png" alt="Download" width="60px" height="60px"></a></p><input type = "image" style="width:60px;height:60px;" src = "note.png" onclick = "showNote()" id = "note-opener"></button></div><!--<div id="note-container" style = "display:none;"><h2>Video Notes</h2><ul id="notes-list"></ul><div style="background-color: #fff"><input type="text" id="note-text" placeholder="Add note" /><button id="add-note">Add Note</button></div><div style="background-color: #fff"><select id="video-selector"></select><button id="load-video">Load Video</button></div></div>*--></div><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script><script src="https://www.youtube.com/iframe_api"></script><script src="ytsearch.js"></script></body></html>Here is the relevant JS script (excluding note-taking):
$(document).ready(function(){ var API_KEY = "AIzaSyAYUJirQE2io-hjqAce9IJCQw9D-F6aFNk"; var selectedCategories = []; $(".category-button").click(function () { $(this).toggleClass("selected"); var categoryKeyword = $(this).data("category"); var $searchInput = $("#search"); if ($(this).hasClass("selected")) { selectedCategories.push(categoryKeyword); } else { selectedCategories = selectedCategories.filter(item => item !== categoryKeyword); } var combinedCategories = selectedCategories.join(" "); if (combinedCategories !== "") { $searchInput.val(combinedCategories); } else { $searchInput.val(""); } }); $("#search-button").click(function () { var search = $("#search").val(); var videoDuration = "short"; videoSearch(API_KEY, search, 12, videoDuration); }); function videoSearch(key, search, maxResults, videoDuration) { var player; function onYouTubeIframeAPIReady() { player = new YT.Player('videoFrame', { playerVars: {'playsinline': 1 }, events: {'onReady': onPlayerReady, } }); } function onPlayerReady(event){ event.target.playVideo(); } $("#videos").empty(); $.get("https://www.googleapis.com/youtube/v3/search?key=" + key+"&type=video&part=snippet&maxResults=" + maxResults +"&q=" + search +"&videoDuration=" + videoDuration, function(data){ //populateVideoSelector(data.items); var videosContainer = $("<div class='row'></div>"); console.log(data); data.items.forEach(function (item, index) { var videoColumn = $("<div class='col-md-4'></div>"); var videoContainer = $("<div class='video-container'></div>"); // Create an image or link to represent the video thumbnail and trigger the pop-up var thumbnail = $("<img src='" + item.snippet.thumbnails.medium.url +"' alt='Video Thumbnail'>"); thumbnail.on("click", function () { player.loadVideoById(item.id.videoId) //openVideo("https://www.youtube.com/embed/" + item.id.videoId +"?enablejsapi=1"); (function () { var textFile = null, makeTextFile = function (text) { var data = new Blob([text], {type: 'text/plain'}); // If we are replacing a previously generated file we need to // manually revoke the object URL to avoid memory leaks. if (textFile !== null) { window.URL.revokeObjectURL(textFile); } textFile = window.URL.createObjectURL(data); return textFile; }; var link = document.getElementById("downloadlink"); link.href = makeTextFile("https://www.youtube.com/embed/" + item.id.videoId)})() }); var videoTitle = $("<p class='video-title'></p>"); videoTitle.text(item.snippet.title); videoContainer.append(thumbnail); videoContainer.append(videoTitle); videoColumn.append(videoContainer); videosContainer.append(videoColumn); if ((index + 1) % 3 === 0) { $("#videos").append(videosContainer); videosContainer = $("<div class='row'></div>"); } }); window.videoData = data; if (videosContainer.children().length > 0){ $("#videos").append(videosContainer); } }) } var videoScreen = document.getElementById("videoScreen"); var videoFrame = document.getElementById("videoFrame"); function openVideo(videoUrl) { videoFrame.src = videoUrl; videoScreen.style.display = "block"; } function closeVideo() { videoFrame.src = ""; videoScreen.style.display = "none"; } var closeBtn = document.querySelector(".close"); closeBtn.addEventListener("click", closeVideo); window.onclick = function(event) { if (event.target === videoScreen) { closeVideo(); } } $("#addKeywordButton").click(function (){ $("#keywordPopup").css("display", "block"); }); $("#cancelKeyword").click(function (){ $("#keywordPopup").css("display", "none"); }); $("#submitKeyword").click(function () { var customKeyword = $("#customKeyword").val(); if (customKeyword.trim() !== "") { var newCategoryButton = $("<button class='category-button' data-category='" + customKeyword +"'>" + customKeyword +"</button>"); newCategoryButton.click(function () { $(this).toggleClass("selected"); var $searchInput = $("#search"); if ($(this).hasClass("selected")) { $searchInput.val(customKeyword); } else { $searchInput.val(""); } }); $(".category-buttons").append(newCategoryButton); $("#customKeyword").val(""); $("#keywordPopup").css("display", "none"); } })});Thank you.