Ahh okay. The first step is to put the script loading code into a function.
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);
}
That code was running immediately on running the videoPlayer code. We want to delay that, so we can use an init method.
const videoPlayer = (function makeVideoPlayer() {
...
function init() {
loadIframeScript();
}
return {
addPlayer,
play,
init
};
}());
We can now use videoPlayer.init() at any time to load the script, and get things going.
(function iife() {
"use strict";
function coverClickHandler(evt) {
videoPlayer.init();
videoPlayer.play(); // problem
}
But there’s a problem. Because init takes time to do its thing, that play cannot work. We need a way to inform videoPlayer about what we want to do after things are inited. Even though the code has an onPlayerReady function, it’s really bad to make changes to that function, as it causes your code to be extremely brittle and easy to break when you use it in other places.
Instead, we can add a different onPlayerReady method to the videoPlayer code. That way we can check if anything is there and run that, which helps to ensure that nothing else breaks.
Here is that play being put into an onPlayerReady method:
function coverClickHandler(evt) {
videoPlayer.init();
videoPlayer.onReady = function playVideo(videoPlayer) {
videoPlayer.play();
};
}
We just now need the videoPlayer code to check if anything is there, and run it.
function onPlayerReady(event) {
...
if (videoPlayer.onReady) {
videoPlayer.onReady(videoPlayer);
}
}
Having the code check that onReady exists is a good safety procedure to ensure that the code still runs correctly when it doesn’t exist either.
That is the more appropriate way to do things.
And after a few tweaks to keep JSLint happy, we have https://jsfiddle.net/963jh4wv/1/