Questions about the YouTube player_api code


#1

Question 1.)

On the single player code, all that’s needed is this line:
addVideo(opts.video);
https://jsfiddle.net/hzyrfkwb/320/

And not all this, right?
Because there’s no PlayerVars in the ‘videoPlayer.init’
https://jsfiddle.net/hzyrfkwb/319/
addVideo(opts.video, opts.playerVars || {});

Question 2.)

Can these be removed from the code?
Are they needed or necessary?
|| {}

addVideo(opts.video, opts.playerVars || {});`
https://jsfiddle.net/hzyrfkwb/318/

Written this way instead?
addVideo(opts.video, opts.playerVars);
https://jsfiddle.net/hzyrfkwb/317/

addVideo(opts.video);
https://jsfiddle.net/hzyrfkwb/320/

These are in reference to this thread:
Preventing YouTube caching in browser


#2

That’s right.

Because of Question 1, they don’t exist.


#3

Then this is good:
addVideo(opts.video, opts.playerVars);

And this is good:
addVideo(opts.video);


#4

I was trying to figure out something before, and that was this.

How would this have worked with the code if it was used?

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

I wasn’t able to figure it out though.
https://jsfiddle.net/hzyrfkwb/327/

I think this would’ve been needed to change to something else:
YT.ready

Maybe: this
YT.apiIsReady

But I don’t think that’s it.

  let apiIsReady = false;
  window.onYouTubePlayerAPIReady = function() {
    apiIsReady = true;
  };
  
  function init(opts) {
    addVideo(opts.video);
  }
  return {
    init
  };
}());
(function iife() {
  "use strict";
  const show = (el) => el.classList.remove("hide");

  function coverClickHandler(evt) {
    const wrapper = evt.currentTarget.nextElementSibling;
    show(wrapper);
    load.js("https://www.youtube.com/player_api").then(function() {
      YT.ready(function() {
        videoPlayer.init({
          video: wrapper.querySelector(".video")
        });
      });
    });
  }

#5

Because YT.ready already waits until the api is ready, there’s no benefit gained from the apiIsReady code anymore.


#6

However, that doesn’t mean that improvements can’t occur.

Currently the clickhandler code uses YT.ready, but that clickhandler code shouldn’t need to know such details about using the youtube api.

    load.js("https://www.youtube.com/player_api").then(function() {
      YT.ready(function() {
        videoPlayer.init({
          video: wrapper.querySelector(".video"),
          playerVars
        });
      });
    });

Instead of having YT.ready in the click handler, we can place it inside of the videoPlayer init function instead. That’s a much better place for the YT.ready to occur.

  function init(opts) {
    // addVideo(opts.video, opts.playerVars);
    YT.ready(function () {
      addVideo(opts.video, opts.playerVars);
    });
  }

We can now remove YT.ready from the clickhandler code.

    load.js("https://www.youtube.com/player_api").then(function() {
      // YT.ready(function() {
        videoPlayer.init({
          video: wrapper.querySelector(".video"),
          playerVars
        });
      // });
    });

And that also means that other clickhandler code that used if/else, doesn’t need to do that anymore either.


#7

I didn’t know that could be improved anymore, I thought that was final.

I guess things can always improve.

Thanks.


#8

That load statement shouldn’t be in the clickhandler code either, so a similar technique can be used to move it into the videoPlayer init code instead.

That leaves the clickhandler code as being just:

      videoPlayer.init({
        video: wrapper.querySelector(".video"),
        playerVars
      });

Which is much more preferable.


#9

This would go:
load.js

In here?

      videoPlayer.init({
        video: wrapper.querySelector(".video"),
        playerVars
      });

#10

If I can have a jsfiddle to explore with, I’ll find an appropriate way to achieve it.


#11

This one is 2 players:
https://jsfiddle.net/hzyrfkwb/330/

This one is one player:
https://jsfiddle.net/hzyrfkwb/331/


#12

Good one. This is the existing click handler code.

        if (!window.YT) {
            load.js("https://www.youtube.com/player_api").then(function() {
                YT.ready(function() {
                    initPlayer(wrapper);
                });
            });
        } else {
            initPlayer(wrapper);
        }

We can copy that if/else structure into the init code:

    function init(opts) {
        if (!window.YT) {
            load.js("https://www.youtube.com/player_api").then(function() {
                YT.ready(function() {
                    // initPlayer(wrapper);
                    addVideo(opts.video, opts.playerVars || {});
                });
            });
        } else {
            // initPlayer(wrapper);
            addVideo(opts.video, opts.playerVars || {});
        }
    }

Which lets us remove the if statements and load code from the clickhandler, leaving us with just the following in there:

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        initPlayer(wrapper);
    }

We can now clean up the init function, because doubling up on opts.playerVars || {} prompts me to improve that, using a separate variable instead.

    function init(opts) {
        var playerVars = opts.playerVars || {};
        if (!window.YT) {
            load.js("https://www.youtube.com/player_api").then(function() {
                YT.ready(function() {
                    addVideo(opts.video, playerVars);
                });
            });
        } else {
            addVideo(opts.video, playerVars);
        }
    }

There. Much better.


#13

How come you didn’t remove YT.ready in your code, like was done here?

    load.js("https://www.youtube.com/player_api").then(function() {
      // YT.ready(function() {
        videoPlayer.init({
          video: wrapper.querySelector(".video"),
          playerVars
        });
      // });
    });

#14

I haven’t tested much yet to learn if removing YT.ready results in significant problems.
When loading the api it takes some time before it’s ready to use, so it’s best to use YT.ready as that’s designed to wait if needed.


#15

How come the grid videos aren’t working now?
https://jsfiddle.net/hzyrfkwb/334/


#16

That would be because you destroyed the clickhandler, and replaced it with the init function that’s not supposed to be there. That init function needs to replace the videoPlayer init function instead.


#17

This gets deleted?

    function initPlayer(wrapper) {
        videoPlayer.init({
            video: wrapper.querySelector(".video"),
            playerVars
        });
    }

#18

No, that doesn’t get touched.


#19

Like this?
https://jsfiddle.net/hzyrfkwb/336/


    function init(opts) {
        var playerVars = opts.playerVars || {};
        if (!window.YT) {
            load.js("https://www.youtube.com/player_api").then(function() {
                YT.ready(function() {
                    addVideo(opts.video, playerVars);
                });
            });
        } else {
            addVideo(opts.video, playerVars);
        }
    }

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        initPlayer(wrapper);
    }
    const cover = document.querySelector(containerSelector);
    cover.addEventListener("click", coverClickHandler);
}

#20

No.

The videoPlayer init function is the one that gets replaced by the updated init function.