Playing YouTube videos from an array

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.

1 Like