There’s a lot to be done here because we are returning some fundamentals back to the code, such as init methods.
To help ensure that timing works right, we’ll use a videoPlayer init method to load the scripts and setup the onYouTubeIframeAPIReady handler.
function loadIframeScript() {
const tag = document.createElement("script");
tag.src = "https://www.youtube.com/iframe_api";
const firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
}
function onYouTubeIframeAPIReady() {
const cover = document.querySelector(".jacket");
const wrapper = cover.parentElement;
const frameContainer = wrapper.querySelector(".video");
videoPlayer.addPlayer(frameContainer);
}
...
function init() {
loadIframeScript();
window.onYouTubeIframeAPIReady = onYouTubeIframeAPIReady;
}
return {
addPlayer,
init,
play
};
...
videoPlayer.init();
The manageCover code at the top needs an init method, so that it can be delayed until after the player is ready.
const manageCover = (function makeManageCover() {
const events = {};
...
function coverClickHandler(evt) {
const cover = evt.currentTarget;
...
cover.dispatchEvent(events.afterClickCover);
}
function init(callback) {
const cover = document.querySelector(".jacket");
cover.addEventListener("click", coverClickHandler);
events.afterClickCover = new Event("afterClickCover");
cover.addEventListener("afterClickCover", callback);
}
return {
init
};
}());
In fact, that init method can accept a callback function, so that we can run that callback function when initialising the code.
(function manageCover() {
...
function coverClickHandler(evt) {
...
callback(cover);
}
...
function init(callback) {
const cover = document.querySelector(".jacket");
cover.addEventListener("click", coverClickHandler);
}
...
videoPlayer.init();
manageCover.init(function playVideo() {
videoPlayer.play();
});
And, the videoPlayer function can take an eventHandlers object, so that we can delay that manageCover code until after the player is ready.
const videoPlayer = (function makeVideoPlayer() {
const events = {};
const eventHandlers = {};
...
function addEvents(handlers) {
eventHandlers.afterPlayerReady = handlers.afterPlayerReady;
events.afterPlayerReady = new Event("afterPlayerReady");
}
...
function init(initEventHandlers) {
addEvents(initEventHandlers);
Then we just need to add that afterPlayerReady event to an element, such as the iframe, and dispatch the event when after the onPlayerReady function.
function onPlayerReady(event) {
...
const iframe = player.h;
iframe.dispatchEvent("afterPlayerReady");
}
...
player = new YT.Player(video, config);
const iframe = player.h;
const eventHandler = eventHandlers.afterPlayerReady;
iframe.addEventListener("afterPlayerReady", eventHandler);
The code at https://jsitor.com/SEWXsfQOf7 has been updated, and clicking on the cover now doesn’t trigger it until after the player is ready to go.