Removing setInterval

Clicking on all 9 is 380 + requests.

Maybe making a grid of 9 videos wasn’t such a smart idea.

Api is removed, what would be next?

Starting from this point.

1st Half:

    var waitting_inits=[];
    function load_all_waitting_inits()
    {
    	for(var opts of waitting_inits)
      {
      	init(opts);
      }
    }

2nd Half:

        }
    }));
}

  load_all_waitting_inits()

function init(opts) {
  	loadPlayer();

      addVideo(opts.video, opts.playerVars || {});
      
      waitting_inits.push(opts)
    
}
return {
    init
};

I deleted This:

    let apiIsReady = false;
    let timer;
    window.onYouTubePlayerAPIReady = function() {
      apiIsReady = true;

    };

this would become:
for(var opts of waitting_inits)

This?
waitting_inits.forEach(init);

What would I do next?

This would be because I removed ‘apiIsReady’ from the bottom.
YT is not defined

Like this then:

  const players = [];
  const waitting_inits = [];

  function load_all_waitting_inits() {
    waitting_inits.forEach(init);
  }

Like this?

What comes next?

 window.onYouTubePlayerAPIReady = function() {

    load_all_waitting_inits()
  };

  function init(opts) {
    loadPlayer();
    if (YT.Player) {
      addVideo(opts.video, opts.playerVars || {});
    } else {
      waitting_inits.push(opts)
    }
  }
  return {
    init
  };
}());

That’s going to fail when YT doesn’t exist. Don’t do it that way. Just check for YT instead.

I just put the letters YT in there?
if (YT) {

It still says:
ReferenceError: YT is not defined


  function init(opts) {
    loadPlayer();
    if (YT) {
      addVideo(opts.video, opts.playerVars || {});
    } else {
      waitting_inits.push(opts)
    }
  }
  return {
    init
  };
}());

If I do this I get:
TypeError: opts is undefined

  function init(YT, opts) {
    loadPlayer();
    if (YT) {

Ahh yes, that’s a handy warning because at that stage, it really is undefined, and won’t be defined until the youtube api has taken its time to load up.

What JavaScript does is to check if YT is in the local scope, then it goes up through parent scopes until it reaches the window object. If YT still isn’t defined, that’s when the error occurs.

What we can do, is to check for window.YT instead, which lets us check if YT exists, and avoids the error from happening.

That gets the if statement working.

For the sake of consistency the existing uses of YT should also be renamed to window.YT, just to make it clear where they’re coming from, but that’s not a necessity.

I thought this would no-longer be needed or necessary.

or am I deleting this?

  window.onYouTubePlayerAPIReady = function() {
  };

I got this:

TypeError: window.YT is not a constructor

But I don’t understand how I would get it working.

I added “window.YT” like you said to, right?

    const playerVars = Object.assign(defaultPlayerVars, desiredPlayerVars);
    players.push(new window.YT(video, {

  function init(opts) {
    loadPlayer();
    if (window.YT) {
      addVideo(opts.video, opts.playerVars || {});
    } else {
      waitting_inits.push(opts)
    }
  }
  return {
    init
  };

If I’m using this:
<script type="text/javascript" src="https://www.youtube.com/player_api"></script>

Then this:

    function loadPlayer() {
        const tag = document.createElement("script");
        tag.src = "https://www.youtube.com/player_api";
        const firstScriptTag = document.getElementsByTagName("script")[0];
        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    }

And This:

loadPlayer();

Can be deleted / removed from the code

Am I right?

Those are no-longer needed or necessary.

All that would be needed is this.

Right?

Code

<script type="text/javascript" src="https://www.youtube.com/player_api"></script>

const videoPlayer = (function makeVideoPlayer() {
    "use strict";
    const players = [];

    function onPlayerReady(event) {
        const player = event.target;
        player.setVolume(50); // percent
    }

    function onPlayerStateChange(event) {
        const player = event.target;
        if (event.data === YT.PlayerState.PLAYING) {
            const otherVideos = (video) => video !== player;
            const pauseVideo = (video) => video.pauseVideo();
            players.filter(otherVideos).forEach(pauseVideo);
        }
        const playerVars = player.b.b.playerVars;
        if (playerVars.loop && event.data === YT.PlayerState.ENDED) {
            player.seekTo(playerVars.start);
        }
    }

    function addVideo(video, desiredPlayerVars) {
        const videoId = video.getAttribute("data-id");
        const defaultPlayerVars = {
            autoplay: 1,
            controls: 1,
            showinfo: 1,
            rel: 0,
            iv_load_policy: 3,
            cc_load_policy: 0,
            fs: 0,
            disablekb: 1
        };
        const playerVars = Object.assign(defaultPlayerVars, desiredPlayerVars);
        players.push(new YT.Player(video, {
            width: 200,
            height: 200,
            videoId: videoId,
            playerVars,
            events: {
                "onReady": onPlayerReady,
                "onStateChange": onPlayerStateChange
            }
        }));
    }

    function init(opts) {
     addVideo(opts.video, opts.playerVars || {});
        
    }
    return {
        init
    };
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 900,
                end: 1200
            }
        });
    }
    const cover = document.querySelector(".playa");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playb");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playc");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playd");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playe");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playf");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playg");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playh");
    cover.addEventListener("click", coverClickHandler);
}());
(function iife() {
    "use strict";
    const show = (el) => el.classList.remove("hide");

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars: {
                start: 30,
                end: 50
            }
        });
    }
    const cover = document.querySelector(".playi");
    cover.addEventListener("click", coverClickHandler);
}());

It’s become clear that checking for YT is not a good solution. Using apiIsReady is a better solution instead.

1 Like

Then this is a good one then:

Top:

const players = [];
  const waitting_inits = [];

  function load_all_waitting_inits() {
    waitting_inits.forEach(init);
  }

Bottom:

 let apiIsReady = false;
  window.onYouTubePlayerAPIReady = function() {
    apiIsReady = true;
    load_all_waitting_inits()
  };

  function init(opts) {
    loadPlayer();
    if (apiIsReady) {
      addVideo(opts.video, opts.playerVars || {});
    } else if (!waitting_inits.includes(opts)) // if array doesn't include opts then push
    {
      waitting_inits.push(opts)
    }
  }
  return {
    init
  };
}());

Well, apart from the spelling. There’s only one “t” in waiting, and underscore notation is a habit that comes from other languages. With JavaScript we prefer to use camelCase instead.

Like this then:

Top:

  const players = [];
  const waitingInits = [];

  function loadallWaitingInits() {
    waitingInits.forEach(init);
  }

Bottom:

 let apiIsReady = false;
  window.onYouTubePlayerAPIReady = function() {
    apiIsReady = true;
    loadallWaitingInits()
  };

  function init(opts) {
    loadPlayer();
    if (apiIsReady) {
      addVideo(opts.video, opts.playerVars || {});
    } else if (!waitingInits.includes(opts)) // if array doesn't include opts then push
    {
      waitingInits.push(opts)
    }
  }

Close, it’s better to have “all” with initial caps too, as in loadAllWaitingInits, or go without it completely, as in loadWaitingInits

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.