There’s a lot happening with that code. Simplifying what happens is a good way to make it easier to understand what’s going on.
Simplify onYouTubeIframeAPIReady
For example, that onYouTubeIframeAPIReady function shouldn’t be out on its lonesome where it is. It should be in the videoPlayer function with the other youtube-related code. But, we don’t want the loadPlayer code to also go in the videoPlayer code.
Instead, we can have the onYouTubeIframeAPIReady function run a videoPlayer function, that we name onIframeReady. That way we can add that function from the end of the code with the loadPlayer stuff, and the onYouTubeIframeAPIReady can then invoke that function when the iframe is ready to go.
How do we do that in a simple way? We rename the onYouTubeIframeAPIReady line so that it adds a function to videoPlayer instead.
videoPlayer.onIframeReady = function loadPlayers() {
loadPlayer({
height: 207,
target: ".jacket-left",
width: 277
});
Then in the videoPlayer, we can have onYouTubeIframeAPIReady invoke that videoPlayer.onIframeReady code.
const tag = document.createElement("script");
tag.src = "https://www.youtube.com/player_api";
const firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
window.onYouTubeIframeAPIReady = onYouTubeIframeAPIReady;
That is a simplification that JSLint is okay with us doing, and helps to ensure that the configuration is down at the end of the code. https://jsfiddle.net/143bq6zw/
More configuration can be moved to the end of the code too. When all configuration is moved to the end of the code, it then becomes easier to understand what the code is configured to do, which makes it easier for us to update that configuration to achieve our needs.
The videoPlayer code currently automatically runs code to load the iframe script. It’s a better practice to put that into an init function, and use that to initialize the videoPlayer code afterwards.
Simplify videoPlayer.onIframeReady
Continuing on with the simplifying, the videoPlayer.onIframeReady calls the loadPlayer function many times with different parameters. Those different parameters should all be put into a single array, so that we successfully separate the config from what is done with it.
const playerConfig = [
{
height: 207,
target: ".jacket-left",
width: 277
},
{
height: 207,
start: 4,
target: ".jacket-middle",
width: 277
},
{
height: 207,
target: ".jacket-right",
width: 277
},
{
height: 338,
loop: true,
playlist: "0dgNc5S8cLI,mnfmQe8Mv1g,-Xgi_way56U,CHahce95B1g",
target: ".jacketc",
width: 600
},
{
end: 280,
loop: true,
start: 0,
target: ".alpha"
},
{
end: 240,
loop: true,
start: 0,
target: ".beta"
},
{
end: 265,
loop: true,
start: 0,
target: ".gamma"
},
{
end: 254,
loop: true,
start: 4,
target: ".delta"
},
{
end: 242,
loop: true,
start: 0,
target: ".epsilon"
},
{
end: 285,
loop: true,
start: 0,
target: ".zeta"
},
{
end: 312,
loop: true,
start: 23,
target: ".eta"
},
{
start: 2,
target: ".theta"
},
{
target: ".iota"
}
];
That way when we are trying to understand what the code does, we only have the following small part after it to worry about:
videoPlayer.onIframeReady = function loadPlayers() {
playerConfig.forEach(function (config) {
loadPlayer(config);
});
};
The updated code is found at: https://jsfiddle.net/143bq6zw/1/
Simplify videoPlayer
The videoPlayer function has code that is automatically run when the page loads. That is a complication that is best avoided by moving the code into an init function so that the videoPlayer can be initialized using that init function.
We can move that code down to an init function at the end of the videoPlayer code, so that we can call the init later on at the end of everything.
function init() {
const tag = document.createElement("script");
tag.src = "https://www.youtube.com/player_api";
const firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
window.onYouTubeIframeAPIReady = onYouTubeIframeAPIReady;
}
return {
addPlayer,
init,
play
};
That way, after setting up the videoPlayer.onIframeReady function, we init the videoPlayer too.
videoPlayer.onIframeReady = function loadPlayers() {
...
};
videoPlayer.init();
The updated code is at: https://jsfiddle.net/143bq6zw/2/
Simplify manageCover
There are several manageCover functions that the same init thing can be done with, moving initialization code into an init function, so that we can separately init the code.
We might also find a major simplification comes from that too.
With manageCovere we assign it to a constant, so that we can call it later with the init command.
const manageCovere = (function makeManageCovere() {
We move the code that automatically runs into an init function, so that we can init it later on.
function init() {
const cover = document.querySelector(".jacketd");
cover.addEventListener("click", coverClickHandler);
}
return {
init
};
}());
manageCovere.init();
And this is where the magic happens, we invoke the init method with a selector for cover
as the argument.
function init(coverSelector) {
const cover = document.querySelector(coverSelector);
cover.addEventListener("click", coverClickHandler);
}
return {
init
};
}());
manageCovere.init(".jacketd");
I could remove most of those manageCover functions now, but surprizes can occur so I’ll make those same updates to the manageCovera, manageCoverb, manageCoverc, and manageCoverd functions too.
You had five sets of duplication there with the manageCover functions. Normally three sets of smaller duplication, or in this case two sets of larger duplication, is the signal to remove that duplication.
Those manageCover init statements can now all be grouped together and moved to the end of the code:
manageCovera.init(".jacket-left");
manageCoverb.init(".jacket-middle");
manageCoverc.init(".jacket-right");
manageCoverd.init(".jacketc");
manageCovere.init(".jacketd");
Those manageCover functions are all nearly identical. It’s only the last one with show functions that’s different. We can update that last manageCovere function so that it checks if the element exists before showing it, and we can then remove all of the other manageCover functions.
const manageCovere = (function makeManageCovere() {
...
const thewrap = cover.parentElement.querySelector(".wraph");
if (thewrap) {
show(thewrap);
}
I’ll start by using manageCovere for the other init methods:
manageCovere.init(".jacket-left");
manageCovere.init(".jacket-middle");
manageCovere.init(".jacket-right");
manageCovere.init(".jacketc");
manageCovere.init(".jacketd");
Everything still works fine, so the other manageCover functions can be removed, and mamageCovere gets renamed to only manageCover.
const manageCover = (function makeManageCover() {
As a reminder, the make
prefix tells us that the manageCover variable is not a function, but is an object with methods instead, in this case the init method.
We end up with the following configuration at the end of the code, from which we can now start investigating about getting videos to play when they are clicked on.
manageCover.init(".jacket-left");
manageCover.init(".jacket-middle");
manageCover.init(".jacket-right");
manageCover.init(".jacketc");
manageCover.init(".jacketd");
videoPlayer.onIframeReady = function loadPlayers() {
playerConfig.forEach(function (config) {
loadPlayer(config);
});
};
videoPlayer.init();
The updated code is at: https://jsfiddle.net/143bq6zw/3/
Next up is to investigate the video play issue.