TypeError: player.b is undefined. How do I fix that?

I thought that was being removed.

I added it back in here.

Good. Now you know what happens with playerVars just before the events object. Now throw away the code that you’ve damaged, go back to the code that you started with, and make the recommended changes correctly this time.

Like this?

Am I close?

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

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

   const playerVars = {
      autoplay: 1,
      controls: 1,
      showinfo: 1,
      rel: 0,
      iv_load_policy: 3,
      cc_load_policy: 0,
      fs: 0,
      disablekb: 1,
      loop: true,
      start: 200,
      end: 204
   };

   function onPlayerStateChange(event) {
      if (playerVars.loop && event.data === YT.PlayerState.ENDED) {
         player.seekTo(playerVars.start);

      }

      new YT.Player(video, {
         width: 606,
         height: 344,
         videoId: video.dataset.id,
         host: "https://www.youtube-nocookie.com",
         // playerVars: {
         //   ...
         // },
         playerVars,

         events: {
            "onReady": onPlayerReady,
            "onStateChange": onPlayerStateChange
         }
      });
   }


   function init(opts) {
      load.js("https://www.youtube.com/player_api").then(function () {
         YT.ready(function () {
            addVideo(opts.video);
         });
      });
   }
   return {
      init
   };
}());

(function iife() {
   "use strict";

   function show(el) {
      el.classList.remove("hide");
   }

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

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

   const cover = document.querySelector(".jacketc");
   cover.addEventListener("click", coverClickHandler);
}());

It doesn’t look like you started from the working code in https://jsfiddle.net/29u5oa1j/1/, because other things are broken in what you posted above.

I tried here. Updated

Here is a visual presentation of the difference between those two sets of codes.
https://www.diffchecker.com/KbnjZvKQ (only live for 24 hours)

Line 53 on the original code shows that there used to be an addVideo function line, that you have since destroyed. Fix that.

1 Like

There should be no errors.

ReferenceError: YT is not defined

Working code has no errors.

That works for me in Chrome. I’ll attempt it too in Firefox. It works there too.

The code in https://jsfiddle.net/7jf2gr34/1/ seems to have no errors.

1 Like

Although, it looks like you’ve placed that addVideo function line in the wrong place. It should be just above the YT.Player line instead.

And, I would move the onPlayerReady function down so that it is just above the onPlayerStateChange function.

1 Like

Fixed

Nice one. That only took about 20 posts, when it normally only takes 1 post to achieve.

Would I be able to do that same thing with this?

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

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

    let hasShuffled = false;

    function onPlayerStateChange(event) {
        const player = event.target;
        if (!hasShuffled) {
            player.setShuffle(true);
            player.playVideoAt(0);
            hasShuffled = true;
        }
        if (event.data === YT.PlayerState.PLAYING) {
            for (let i = 0; i < players.length; i++) {
                if (players[i] !== event.target) players[i].pauseVideo();
            }
        }

        const playerVars = player.b.b.playerVars;
        if (playerVars.loop && event.data === YT.PlayerState.ENDED) {
            player.seekTo(playerVars.start);
        }
    }

    function addVideo(video, settings) {
        players.push(new YT.Player(video, Object.assign({
            videoId: video.dataset.id,
            host: "https://www.youtube-nocookie.com",
            events: {
                "onReady": onPlayerReady,
                "onStateChange": onPlayerStateChange
            }
        }, settings)));
    }

    function init(video, settings) {
        load.js("https://www.youtube.com/player_api").then(function () {
            YT.ready(function () {
                addVideo(video, settings);
            });
        });
    }
    return {
        init
    };
}());

function loadPlayer(opts) {
    "use strict";

    function show(el) {
        el.classList.remove("hide");
    }

    function initPlayer(wrapper) {
        const video = wrapper.querySelector(".video");
        opts.width = opts.width || 198;
        opts.height = opts.height || 198;
        opts.autoplay = 1;
        opts.controls = 1;
        opts.rel = 0;
        opts.iv_load_policy = 3;
        opts.fs = 0;
        opts.disablekb = 1;

        function paramInOpts(settings, param) {
            if (opts[param] !== undefined) {
                settings[param] = opts[param];
            }
            return settings;
        }
        const settingsParams = ["width", "height", "videoid", "host"];
        const settings = settingsParams.reduce(paramInOpts, {});
        const playerVarsParams = ["autoplay", "cc_load_policy",
            "controls", "disablekb", "end", "fs", "iv_load_policy",
            "list", "listType", "loop", "playlist", "rel", "start"
        ];
        settings.playerVars = playerVarsParams.reduce(paramInOpts, {});
        videoPlayer.init(video, settings);
    }

    function coverClickHandler(evt) {
        const wrapper = evt.currentTarget.nextElementSibling;
        show(wrapper);
        initPlayer(wrapper);
    }
    const cover = document.querySelector(opts.target);
    cover.addEventListener("click", coverClickHandler);
}
const playlist = "0dgNc5S8cLI,mnfmQe8Mv1g,-Xgi_way56U,CHahce95B1g";

loadPlayer({
    target: ".jacket-left",
    width: 277,
    height: 207
});

loadPlayer({
    target: ".jacket-middle",
    width: 277,
    height: 207,
    start: 4
});
loadPlayer({
    target: ".jacket-right",
    width: 277,
    height: 207
});

loadPlayer({
    target: ".jacketc",
    width: 600,
    height: 338,
    loop: true,
    playlist
});
loadPlayer({
    target: ".alpha",
    start: 0,
    end: 280,
    loop: true
});
loadPlayer({
    target: ".beta",
    start: 0,
    end: 240,
    loop: true
});
loadPlayer({
    target: ".gamma",
    start: 0,
    end: 265,
    loop: true
});
loadPlayer({
    target: ".delta",
    start: 4,
    end: 254,
    loop: true
});
loadPlayer({
    target: ".epsilon",
    start: 0,
    end: 242,
    loop: true
});
loadPlayer({
    target: ".zeta",
    start: 0,
    end: 285,
    loop: true
});
loadPlayer({
    target: ".eta",
    start: 23,
    end: 312,
    loop: true
});
loadPlayer({
    target: ".theta",
    start: 2
});
loadPlayer({
    target: ".iota"
});

That is something that I cannot help you with now… You’ve already exhausted all of the help that I can give to this place today. Nobody else gets to be helped now.

It’s possible to do is what you are saying.

It’s not impossible.

Another time then.

I just cleaned up the code here so everything is easy to get to.

Me looking at it, it doesn’t seem possible to do because there is so much going on in the code,

At the top of the makeVideoPlayer function we can add a playerVars object:

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

That playerVars object can be updated from elsewhere, such as from the addVideo function, and accessed by anything inside of the makeVideoPlayer function.

The addVideo function can update the playerVars object, and use that when creating the new video.

    function addVideo(video, settings) {
        playerVars = Object.assign({
            videoId: video.dataset.id,
            host: "https://www.youtube-nocookie.com",
            events: {
                "onReady": onPlayerReady,
                "onStateChange": onPlayerStateChange
            }
        }, settings);
        players.push(new YT.Player(video, playerVars));
    }

And because playerVars contains meaningful information, we can replace the undocumented and brittle way of accessing playerVars, with using that playerVars object that we created instead.

        // const playerVars = player.b.b.playerVars;
        if (playerVars.loop && event.data === YT.PlayerState.ENDED) {

After testing, the players look to work well, so the commented line can now be removed.

        if (playerVars.loop && event.data === YT.PlayerState.ENDED) {
1 Like

Thank you.

Fixed and Updated


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

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

   let hasShuffled = false;

   function onPlayerStateChange(event) {
      const player = event.target;
      if (!hasShuffled) {
         player.setShuffle(true);
         player.playVideoAt(0);
         hasShuffled = true;
      }
      if (event.data === YT.PlayerState.PLAYING) {
         for (let i = 0; i < players.length; i++) {
            if (players[i] !== event.target) players[i].pauseVideo();
         }
      }

      if (playerVars.loop && event.data === YT.PlayerState.ENDED) {
         player.seekTo(playerVars.start);
      }
   }

   function addVideo(video, settings) {
      playerVars = Object.assign({
         videoId: video.dataset.id,
         host: "https://www.youtube-nocookie.com",
         events: {
            "onReady": onPlayerReady,
            "onStateChange": onPlayerStateChange
         }
      }, settings);
      players.push(new YT.Player(video, playerVars));
   }

   function init(video, settings) {
      load.js("https://www.youtube.com/player_api").then(function () {
         YT.ready(function () {
            addVideo(video, settings);
         });
      });
   }
   return {
      init
   };
}());

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