Playing YouTube videos from an array

How this works is, you click on the cover and it plays one video after another from an array.

https://jsfiddle.net/3aj02byv/

There’s duplication in the code which I think can be removed.

(function init() {
    const videos = [
        "0dgNc5S8cLI",
        "mnfmQe8Mv1g",
        "CHahce95B1g",
        "2VwsvrPFr9w"           
    ];

    let videoList = [];

    const mvideos = videos[Math.floor(Math.random() * videos.length)];
    document.querySelector(".video").setAttribute("data-id", mvideos);
}());

const videoPlayer = (function makeVideoPlayer() {

    const videos = [
        "0dgNc5S8cLI",
        "mnfmQe8Mv1g",
        "CHahce95B1g",
        "2VwsvrPFr9w"     
    ];

    let videoList = [];

    function onStateChange(evt) {
        if (evt.data)

        {
            return;
        }

        if (!videoList.length) {
            videoList = videos.filter(function (a) {
                return a !== player.getVideoData().video_id;
            });
        }

        const id = videoList.splice(Math.floor(Math.random() * videoList.length), 1)[0];
        player.loadVideoById(id);
    }
2 Likes

Why on earth would you do that when the youtube player already supports playlists?

I was trying to come up with different ways YouTube could play a video. So I tried to get it working the same way but with an array instead. It’s a different way of setting it up which I have never tried before.

This top part I think can be removed, and I don’t think it is necessary.

(function init() {
    const videos = [
        "0dgNc5S8cLI",
        "mnfmQe8Mv1g",
        "CHahce95B1g",
        "2VwsvrPFr9w"           
    ];

    let videoList = [];

    const mvideos = videos[Math.floor(Math.random() * videos.length)];
    document.querySelector(".video").setAttribute("data-id", mvideos);
}());

You’re making more work for yourself that’s not needed. Just go with a playlist and use the youtube API to shuffle it.

Maybe a similar idea will come to me that may be easier to set up, easier to understand how it would work.

Instead of doing all that, what about doing an array where it would pick just one video and load it.

Would that be easier to do? That would probably be better to do.

    const videos = [
        "0dgNc5S8cLI",
        "mnfmQe8Mv1g",
        "CHahce95B1g",
        "2VwsvrPFr9w"           
    ];
1 Like

Picking one item from an array means that you can just use that for the videoid of the player. You can do that by setting the videoid parameter of the playerOptions.

2 Likes

I like that idea. Let’s try that way.

I’ll get a code set up ready to work on it.

Here’s a code to work on.

https://jsfiddle.net/aso4n8hx/5/

How would this be done?

const videoPlayer = (function makeVideoPlayer() {

  let player = null;

  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 onPlayerReady(event) {
    player = event.target;
    player.setVolume(100); // percent
  }

  function addPlayer(video) {

  const videos = [ "0dgNc5S8cLI","mnfmQe8Mv1g","CHahce95B1g","2VwsvrPFr9w"];

    const config = {
      height: 360,
      host: "https://www.youtube-nocookie.com",
      videoId: video.dataset.id,
      width: 640
    };
    config.playerVars = {
      autoplay: 0,
      cc_load_policy: 0,
      controls: 1,
      disablekb: 1,
      fs: 0,
      iv_load_policy: 3,
      rel: 0
    };
    config.events = {
      "onReady": onPlayerReady
    };
    player = new YT.Player(video, config);

  }

  function play() {
    player.playVideo();
  }
  return {
    addPlayer,
    play
  };
}());

Is this what you mean, or would it be written differently?

Did I do it right?
https://jsfiddle.net/op7u1ta9/

const videoPlayer = (function makeVideoPlayer() {

    let player = null;

    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 onPlayerReady(event) {
        player = event.target;
        player.setVolume(100); // percent
    }

    function singleYT() {
        const videos = [
            "0dgNc5S8cLI",
            "mnfmQe8Mv1g",
            "CHahce95B1g",
            "2VwsvrPFr9w"
        ];

        const index = Math.floor(Math.random() * videos.length);
        return videos[index];
    }

    function addPlayer(video) {
        const videoID = singleYT();
        const config = {
            height: 360,
            host: "https://www.youtube-nocookie.com",
            videoId: videoID,
            width: 640
        };
        config.playerVars = {
            autoplay: 0,
            cc_load_policy: 0,
            controls: 1,
            disablekb: 1,
            fs: 0,
            iv_load_policy: 3,
            rel: 0
        };
        config.events = {
            "onReady": onPlayerReady
        };
        player = new YT.Player(video, config);

    }

    function play() {
        player.playVideo();
    }
    return {
        addPlayer,
        play
    };
}());

Yes, that seems to work.

1 Like

I have a question.

Is it better to use double tilde (~~) instead of Math.floor?

I was reading about it and it’s supposed to be faster, that’s what I read.

I don’t really notice a difference though.

Math.floor is a lot easier to understand that double tilde.

1 Like

Same with regular functions as opposed to arrow functions.

I prefer regular.

Easier to find the errors.

About the only good time for arrow functions is when it’s a single line statement. It’s difficult to justify any other use for them.

1 Like

Would I be able to take this code I managed to do.
https://jsfiddle.net/op7u1ta9/

function singleYT() {
        const videos = [
            "0dgNc5S8cLI",
            "mnfmQe8Mv1g",
            "CHahce95B1g",
            "2VwsvrPFr9w"
        ];

        const index = Math.floor(Math.random() * videos.length);
        return videos[index];
    }

    function addPlayer(video) {
        const videoID = singleYT();
        const config = {
            height: 360,
            host: "https://www.youtube-nocookie.com",
            videoId: videoID,
            width: 640
        };

and have it be able to work with this one?

It seems easier said than done.

I tried merging the codes together, but I was not able to get it, either because, I am doing it wrong, or, both codes are not meant to work with each other.

https://jsfiddle.net/3aj02byv/

function onStateChange(evt) {
        if (evt.data)

        {
            return;
        }

        if (!videoList.length) {
            videoList = videos.filter(function (a) {
                return a !== player.getVideoData().video_id;
            });
        }


        const id = videoList.splice(Math.floor(Math.random() * videoList.length), 1)[0];
        player.loadVideoById(id);
    }

First I add onStateChange and the code still works:
https://jsfiddle.net/9rnby6jc/1/

 function singleYT() {
        const videos = [
            "0dgNc5S8cLI",
            "mnfmQe8Mv1g",
            "CHahce95B1g",
            "2VwsvrPFr9w"
        ];

        const index = Math.floor(Math.random() * videos.length);
        return videos[index];
    }
    
    function onStateChange(evt) {
        if (evt.data)

        {
            return;
        }

        if (!videoList.length) {
            videoList = videos.filter(function (a) {
                return a !== player.getVideoData().video_id;
            });
        }
    
    }

    function addPlayer(video) {
        const videoID = singleYT();
        const config = {
            height: 360,
            host: "https://www.youtube-nocookie.com",
            videoId: videoID,
            width: 640
        };

Doing any of that in the stateChange event is the wrong things to do.

1 Like

Maybe that was why I was not able to get it.

Would it be done in a different spot?

or, a different way?

I thought I would be able to just put one code with the other, turns out, no.

This seems hard to do.


In the working code I did where it picks one song and plays it.

https://jsfiddle.net/op7u1ta9/

To have it to play through the whole array, how would that be done?

That’s what I was trying to figure out.

I found this, would this help in figuring it out?

In the fiddle it plays one video after another.
https://jsfiddle.net/y1qkLwg8/

 function onPlayerReady(event) {
        event.target.loadVideoById(videoIDs[currentVideoId]);
    }

    function onPlayerStateChange(event) {
        if (event.data == YT.PlayerState.ENDED) {
            currentVideoId++;
            if (currentVideoId < videoIDs.length) {
                player.loadVideoById(videoIDs[currentVideoId]);
            }
        }
    }

This works:

How would I be able to have the ids play out of order?

https://jsfiddle.net/m6bz5d9r/3/

    let player = null;
    let currentVideoId = 0;

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

    const videoID = [
        "0dgNc5S8cLI",
        "mnfmQe8Mv1g",
        "CHahce95B1g",
        "2VwsvrPFr9w"
    ];

    function onPlayerReady(event) {
        event.target.loadVideoById(videoID[currentVideoId]);
        player.setVolume(100); // percent

    }

    function onStateChange(event) {
        if (event.data == YT.PlayerState.ENDED) {
            currentVideoId++;
            if (currentVideoId < videoID.length) {
                player.loadVideoById(videoID[currentVideoId]);
            }
        }
    }


    function addPlayer(video) {

        const config = {
            height: 360,
            host: "https://www.youtube-nocookie.com",
            width: 640
        };
        config.playerVars = {
            autoplay: 0,
            cc_load_policy: 0,
            controls: 1,
            disablekb: 1,
            fs: 0,
            iv_load_policy: 3,
            rel: 0
        };
        config.events = {
            "onReady": onPlayerReady,
            "onStateChange": onStateChange
        };
        player = new YT.Player(video, config);

    }

Just give the youtube player a list of them as a playlist, and have youtube shuffle the list.