Playing YouTube videos from an array

https://jsfiddle.net/cp104j5L/4/

  function addPlayer(video, settings, videoIds = video.dataset.id) {
    const videoId = !Array.isArray(videoIds) && videoIds;
    const playlist = Array.isArray(videoIds) && videoIds;
    const defaults = {
      playerOptions: {
        events: {
          "onReady": onPlayerReady
        },
        host: "https://www.youtube-nocookie.com",
        playerVars: {
          playlist,
        },
        videoId
      }
    };

The way this one is set up, events is at the bottom, and host is at the top, we don’t want this?

I thought it looked more organized.

const config = {
      host: "https://www.youtube-nocookie.com",
    };
    config.playerVars = {
      playlist,
    };
    config.events = {
      "onReady": onPlayerReady,
      "onStateChange": onPlayerStateChange
    };

https://jsfiddle.net/htus95vm/

  1. Unused ‘paramInOptions’.
    function paramInOptions(opts, param) {

121: 152. Unused ‘optionParams’.
const optionParams = [“width”, “height”, “playlist”, “host”, “videoid”];

function addPlayer(video, settings, videoIds = video.dataset.id) {
    const videoId = !Array.isArray(videoIds) && videoIds;
    const playlist = Array.isArray(videoIds) && videoIds;
    const defaults = {
      playerOptions: {
        events: {
          "onReady": onPlayerReady
        },
        host: "https://www.youtube-nocookie.com",
        playerVars: {
          playlist,
        },
        videoId
      }
    };
    const defaultOptions = defaults.playerOptions;
    const playerOptions = Object.assign({}, defaultOptions, settings);
    players.push(new YT.Player(video, playerOptions));
  }

  return {
    addPlayer
  };
}());

const managePlayer = (function makeManagePlayer() {
  const defaults = {
    playerOptions: {
      height: 600,
      playerVars: {
        autoplay: 0,
        controls: 1,
        disablekb: 1,
        enablejsapi: 1,
        fs: 0,
        iv_load_policy: 3,
        rel: 0
      },
      width: 360
    }
  };

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

  function createPlayerOptions(settings) {
    function paramInOptions(opts, param) {
      if (settings[param] !== undefined) {
        opts[param] = settings[param];
        delete settings[param];
      }
      return opts;
    }

    const optionParams = ["width", "height", "playlist", "host", "videoid"];
    const defaultOptions = defaults.playerOptions;
    const defaultVars = defaultOptions.playerVars;
    const playerVars = settings.playerVars;
    const playerOptions = Object.assign({}, defaultOptions, settings);
    playerOptions.playerVars = Object.assign({}, defaultVars, playerVars);
    return playerOptions;
  }

Continuing from Code 2 I would then do this?
https://jsfiddle.net/eL79x6mr/1/

const managePlayer = (function makeManagePlayer() {
  const config = {
    width: 360,
    height: 600
  };
  config.playerVars = {
    autoplay: 0,
    controls: 1,
    disablekb: 1,
    enablejsapi: 1,
    fs: 0,
    iv_load_policy: 3,
    rel: 0
  };

After that, stuff would need to be renamed in here.

const optionParams = ["width", "height", "playlist", "host", "videoid"];
    const defaultOptions = config.playerOptions;
    const defaultVars = defaultOptions.playerVars;
    const playerVars = settings.playerVars;
    const playerOptions = Object.assign({}, defaultOptions, settings);
    playerOptions.playerVars = Object.assign({}, defaultVars, playerVars);
    return playerOptions;
  }

  function createPlayer(videoWrapper, settings = {}, videoIds = "") {
    const video = videoWrapper.querySelector(".video");
    if (!videoIds) {
      videoIds = video.dataset.id;
    }
    const playerOptions = createPlayerOptions(settings);
    return videoPlayer.addPlayer(video, playerOptions, videoIds);
  }

  function createCoverClickHandler(playerSettings, videoIds) {
    return function coverClickHandler(evt) {
      const cover = evt.currentTarget;
      const wrapper = cover.nextElementSibling;
      show(wrapper);
      const player = createPlayer(wrapper, playerSettings, videoIds);
      wrapper.player = player;
    };
  }

  function addPlayer(coverSelector, playerSettings, videoIds) {
    const clickHandler = createCoverClickHandler(playerSettings, videoIds);
    manageCover.addCoverHandler(coverSelector, clickHandler);
  }


  function addPlayerRandomVideo(coverSelector, playerSettings, videoIds) {
    const index = Math.floor(Math.random() * videoIds.length);
    const videoId = videoIds[index];
    const clickHandler = createCoverClickHandler(playerSettings, videoId);
    manageCover.addCoverHandler(coverSelector, clickHandler);
  }


  function init(playerOptions) {
    Object.assign(config.playerOptions, playerOptions);
  }

  return {
    add: addPlayer,
    addRandom: addPlayerRandomVideo,
    init
  };
}());

This is what you wanted me to do:
https://jsfiddle.net/htus95vm/

I thought setting it up this way would be better.

Can the code be able to work this way?
It looks neater and more organized.

Can further progress be made from here?

Uncaught TypeError: Cannot convert undefined or null to object"

https://jsfiddle.net/jw9mp2fg/

function addPlayer(video, settings, videoIds = video.dataset.id) {
    const videoId = !Array.isArray(videoIds) && videoIds;
    const playlist = Array.isArray(videoIds) && videoIds;
    const config = {
      host: "https://www.youtube-nocookie.com",
      videoId
    };
    config.playerVars = {
      playlist
    };

    config.events = {
      "onReady": onPlayerReady
    };
    const defaultOptions = config;
    const playerOptions = Object.assign({}, defaultOptions, settings);
    players.push(new YT.Player(video, playerOptions));
  }

  return {
    addPlayer
  };
}());

const managePlayer = (function makeManagePlayer() {
  const config = {
    width: 360,
    height: 600
  };
  config.playerVars = {
    autoplay: 0,
    controls: 1,
    disablekb: 1,
    enablejsapi: 1,
    fs: 0,
    iv_load_policy: 3,
    rel: 0
  };

Code works like this up to this point:
https://jsfiddle.net/tLry9hon/1/

  function addPlayer(video, settings, videoIds = video.dataset.id) {
    const videoId = !Array.isArray(videoIds) && videoIds;
    const playlist = Array.isArray(videoIds) && videoIds;
    const config = {
      host: "https://www.youtube-nocookie.com",
      videoId
    };
    config.playerVars = {
      playlist
    };

    config.events = {
      "onReady": onPlayerReady
    };
    const defaultOptions = config;
    const playerOptions = Object.assign({}, defaultOptions, settings);
    players.push(new YT.Player(video, playerOptions));
  }

  return {
    addPlayer
  };
}());

const managePlayer = (function makeManagePlayer() {
  const defaults = {
    playerOptions: {
      height: 600,
      playerVars: {
        autoplay: 0,
        controls: 1,
        disablekb: 1,
        enablejsapi: 1,
        fs: 0,
        iv_load_policy: 3,
        rel: 0
      },
      width: 360
    }
  };

Adding this in: When it stops working
https://jsfiddle.net/tLry9hon/3/

const managePlayer = (function makeManagePlayer() {
  const config = {
    width: 360,
    height: 600
  };
  config.playerVars = {
    autoplay: 0,
    controls: 1,
    disablekb: 1,
    enablejsapi: 1,
    fs: 0,
    iv_load_policy: 3,
    rel: 0
  };

After adding that piece in, stuff in here I think would need to be changed:

const defaultOptions = defaults.playerOptions;
    const defaultVars = defaultOptions.playerVars;
    const playerVars = settings.playerVars;
    const playerOptions = Object.assign({}, defaultOptions, settings);
    playerOptions.playerVars = Object.assign({}, defaultVars, playerVars);
    return playerOptions;
  }

  function createPlayer(videoWrapper, settings = {}, videoIds = "") {
    const video = videoWrapper.querySelector(".video");
    if (!videoIds) {
      videoIds = video.dataset.id;
    }
    const playerOptions = createPlayerOptions(settings);
    return videoPlayer.addPlayer(video, playerOptions, videoIds);
  }

  function createCoverClickHandler(playerSettings, videoIds) {
    return function coverClickHandler(evt) {
      const cover = evt.currentTarget;
      const wrapper = cover.nextElementSibling;
      show(wrapper);
      const player = createPlayer(wrapper, playerSettings, videoIds);
      wrapper.player = player;
    };
  }

  function addPlayer(coverSelector, playerSettings, videoIds) {
    const clickHandler = createCoverClickHandler(playerSettings, videoIds);
    manageCover.addCoverHandler(coverSelector, clickHandler);
  }


  function addPlayerRandomVideo(coverSelector, playerSettings, videoIds) {
    const index = Math.floor(Math.random() * videoIds.length);
    const videoId = videoIds[index];
    const clickHandler = createCoverClickHandler(playerSettings, videoId);
    manageCover.addCoverHandler(coverSelector, clickHandler);
  }


  function init(playerOptions) {
    Object.assign(defaults.playerOptions, playerOptions);
  }

I got it working here:
https://jsfiddle.net/fLshnr9j/

function addPlayer(video, settings, videoIds = video.dataset.id) {
    const videoId = !Array.isArray(videoIds) && videoIds;
    const playlist = Array.isArray(videoIds) && videoIds;
    const config = {
      host: "https://www.youtube-nocookie.com",
      videoId
    };
    config.playerVars = {
      playlist
    };

    config.events = {
      "onReady": onPlayerReady
    };
    const defaultOptions = config;
    const playerOptions = Object.assign({}, defaultOptions, settings);
    players.push(new YT.Player(video, playerOptions));
  }

  return {
    addPlayer
  };
}());


const managePlayer = (function makeManagePlayer() {
  const config = {
    width: 360,
    height: 600
  };
  config.playerVars = {
    autoplay: 0,
    controls: 1,
    disablekb: 1,
    enablejsapi: 1,
    fs: 0,
    iv_load_policy: 3,
    rel: 0
  };

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

  function createPlayerOptions(settings) {
    function paramInOptions(opts, param) {
      if (settings[param] !== undefined) {
        opts[param] = settings[param];
        delete settings[param];
      }
      return opts;
    }

    const optionParams = ["width", "height", "playlist", "host", "videoid"];
    const defaultOptions = config;
    const defaultVars = defaultOptions.playerVars;
    const playerVars = settings.playerVars;
    const playerOptions = Object.assign({}, defaultOptions, settings);
    playerOptions.playerVars = Object.assign({}, defaultVars, playerVars);
    return playerOptions;
  }

  function createPlayer(videoWrapper, settings = {}, videoIds = "") {
    const video = videoWrapper.querySelector(".video");
    if (!videoIds) {
      videoIds = video.dataset.id;
    }
    const playerOptions = createPlayerOptions(settings);
    return videoPlayer.addPlayer(video, playerOptions, videoIds);
  }

  function createCoverClickHandler(playerSettings, videoIds) {
    return function coverClickHandler(evt) {
      const cover = evt.currentTarget;
      const wrapper = cover.nextElementSibling;
      show(wrapper);
      const player = createPlayer(wrapper, playerSettings, videoIds);
      wrapper.player = player;
    };
  }

  function addPlayer(coverSelector, playerSettings, videoIds) {
    const clickHandler = createCoverClickHandler(playerSettings, videoIds);
    manageCover.addCoverHandler(coverSelector, clickHandler);
  }


  function addPlayerRandomVideo(coverSelector, playerSettings, videoIds) {
    const index = Math.floor(Math.random() * videoIds.length);
    const videoId = videoIds[index];
    const clickHandler = createCoverClickHandler(playerSettings, videoId);
    manageCover.addCoverHandler(coverSelector, clickHandler);
  }

  function init(playerOptions) {
    Object.assign(config, playerOptions);
  }

Last working Version
https://jsfiddle.net/ksLecgxy/1/

Remaining jslint errors

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

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


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

    function addPlayer(video, settings, videoIds = video.dataset.id) {
        const videoId = !Array.isArray(videoIds) && videoIds;
        const playlist = Array.isArray(videoIds) && videoIds;
        const config = {
            host: "https://www.youtube-nocookie.com",
            videoId
        };
        config.playerVars = {
            playlist
        };

        config.events = {
            "onReady": onPlayerReady
        };
        const defaultOptions = config;
        const playerOptions = Object.assign({}, defaultOptions, settings);
        players.push(new YT.Player(video, playerOptions));
    }

    return {
        addPlayer
    };
}());


const managePlayer = (function makeManagePlayer() {
    const config = {
        height: 600,
        width: 360
    };
    config.playerVars = {
        autoplay: 0,
        controls: 1,
        disablekb: 1,
        enablejsapi: 1,
        fs: 0,
        iv_load_policy: 3,
        rel: 0
    };

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

    function createPlayerOptions(settings) {
        function paramInOptions(opts, param) {
            if (settings[param] !== undefined) {
                opts[param] = settings[param];
                delete settings[param];
            }
            return opts;
        }

        const optionParams = ["width", "height", "playlist", "host", "videoid"];
        const defaultOptions = config;
        const defaultVars = defaultOptions.playerVars;
        const playerVars = settings.playerVars;
        const playerOptions = Object.assign({}, defaultOptions, settings);
        playerOptions.playerVars = Object.assign({}, defaultVars, playerVars);
        return playerOptions;
    }

    function createPlayer(videoWrapper, settings = {}, videoIds = "") {
        const video = videoWrapper.querySelector(".video");
        if (!videoIds) {
            videoIds = video.dataset.id;
        }
        const playerOptions = createPlayerOptions(settings);
        return videoPlayer.addPlayer(video, playerOptions, videoIds);
    }

    function createCoverClickHandler(playerSettings, videoIds) {
        return function coverClickHandler(evt) {
            const cover = evt.currentTarget;
            const wrapper = cover.nextElementSibling;
            show(wrapper);
            const player = createPlayer(wrapper, playerSettings, videoIds);
            wrapper.player = player;
        };
    }

    function addPlayer(coverSelector, playerSettings, videoIds) {
        const clickHandler = createCoverClickHandler(playerSettings, videoIds);
        manageCover.addCoverHandler(coverSelector, clickHandler);
    }


    function addPlayerRandomVideo(coverSelector, playerSettings, videoIds) {
        const index = Math.floor(Math.random() * videoIds.length);
        const videoId = videoIds[index];
        const clickHandler = createCoverClickHandler(playerSettings, videoId);
        manageCover.addCoverHandler(coverSelector, clickHandler);
    }


    function init(playerOptions) {
        Object.assign(config, playerOptions);
    }

    return {
        add: addPlayer,
        addRandom: addPlayerRandomVideo,
        init
    };
}());

With that paramInOptions error, it looks like some things have been removed from the createPlayerOptions function that needed to be there.

A working version of that function is found at https://jsitor.com/OX7GlFnem
You can copy the createPlayerOptions function from there to fix the problem.

It’s not helping because both codes are set up differently,

I can’t just replace one whole section with another whole section.

I have to know what I am looking for to remove, replace, or add in.

https://jsfiddle.net/ksLecgxy/1/

This whole thing is different:

I have it using this, your code is not set up like this.

const managePlayer = (function makeManagePlayer() {
    const config = {
        height: 600,
        width: 360
    };
    config.playerVars = {
        autoplay: 0,
        controls: 1,
        disablekb: 1,
        enablejsapi: 1,
        fs: 0,
        iv_load_policy: 3,
        rel: 0
    };

I added this:
playlist: playlist || undefined

But that didn’t make a difference:
https://jsfiddle.net/0e73rgy1/2/

Code 1 From this:
https://jsfiddle.net/0e73rgy1/3/

        const optionParams = ["width", "height", "playlist", "host", "videoid"];
        const defaultOptions = config;
        const defaultVars = config.playerVars;
        const playerVars = settings.playerVars;
        const playerOptions = Object.assign({}, defaultOptions, settings);
        config.playerVars = Object.assign({}, defaultVars, playerVars);
        return playerOptions;
    }

Code 2
To This: no jslint errors, but that doesn’t mean anything.

Because the settings are still not working in the code:
start: 100,

The playerVars are not working either.

   config.playerVars = {
        autoplay: 0,
        controls: 0,

I don’t think either of these were ever working in the code.

Things were being added and removed from the code so I thought everything would be working at the end.

I thought fixing all the jslint errors would fix and resolve those issues.

https://jsfiddle.net/0e73rgy1/4/

       const optionParams = ["width", "height", "playlist", "host", "videoid"];
        const defaultOptions = config;
        const preferred = optionParams.reduce(paramInOptions, {});
        const playerOptions = Object.assign({}, defaultOptions, preferred);
        // settings should now only consist of playerVars
        const defaultVars = config.playerVars;
        const playerVars = settings.playerVars;
        config.playerVars = Object.assign({}, defaultVars, playerVars);
        return playerOptions;
    }

Settings & playerVars are working in here if you want to compare it to a working code.
https://jsfiddle.net/m8hvqjdp/

I hope I didn’t make a lot of mistakes.

Let’s work on the first error that you have from JSLint. Which error is that?

There are 0 errors in here:

Code 2
https://jsfiddle.net/0e73rgy1/4/

According to jslint, these errors were in Code 1

And in Code 2, I did something that fixed those errors.

Settings & playerVars are working in here: which can be used to figure out what is wrong with the other code.
https://jsfiddle.net/m8hvqjdp/

It’s important to understand that just because there are zero errors, doesn’t mean that the code will do what you want.

Okay, let’s work with that then. Code 1 is at https://jsfiddle.net/0e73rgy1/3/

The paramInOptions function is used to separate out from the settings, the valid playerOption settings.

You are missing the line that starts with const preferred from the https://jsitor.com/OX7GlFnem code.
That line from the jsitor code, needs to be put into your code before the const playerOptions line.

Which of these should be used?

const defaultVars = config;
or
const defaultPlayerVars = config;

In here?
https://jsfiddle.net/Lskw3zte/2/

     const optionParams = ["width", "height", "playlist", "host", "videoid"];
        const defaultOptions = config;
        const preferred = optionParams.reduce(paramInOptions, {});
        const playerOptions = Object.assign({}, defaultOptions, settings);
         // settings should now only consist of playerVars

        const defaultVars = config;
        const defaultPlayerVars = config;
        
        const playerVars = Object.assign({}, config, settings);
        config.playerVars = Object.assign({}, config, playerVars);
        return config;
    }

None of those.

The preferred variable contains a subset of the settings, that are suitable for being Player options.

What you should do next is, just below the preferred line, replace settings with the word preferred.

I did that here:
If that looks good to you we can move on to Playlist
https://jsfiddle.net/cenubwrm/1/

        const optionParams = ["width", "height", "playlist", "host", "videoid"];
        const defaultOptions = config;
        const preferred = optionParams.reduce(paramInOptions, {});
        const playerOptions = Object.assign({}, defaultOptions, preferred);
         // settings should now only consist of playerVars
        const playerVars = Object.assign({}, config, settings);
        config.playerVars = Object.assign({}, config, playerVars);
        return config;
    }

As I understand it:

This is for a random video from list

   managePlayer.addRandom(".playa", {
        height: 207,
        start: 45,
        width: 277
    }, [
        "0dgNc5S8cLI",
        "mnfmQe8Mv1g",
        "-Xgi_way56U",
        "CHahce95B1g"
    ]);

and this is to do a playlist:

    managePlayer.add(".playb", {
        height: 207,
        playlist: "0dgNc5S8cLI,mnfmQe8Mv1g,-Xgi_way56U,CHahce95B1g",
        width: 277
    });

Playlist is not working in the code:
https://jsfiddle.net/cenubwrm/2/

With managePlayer.add, the playlist is the third parameter that you use.

function addPlayer(coverSelector, playerSettings, videoIds) {

The first parameter is the video selector
The second parameter is the player options and player vars
The third parameter is either a string for one video, or an array of strings for multiple videos.

This is for a random song from a string,

managePlayer.addRandom(".playa", {
        height: 207,
        start: 45,
        width: 277
    }, [
        "0dgNc5S8cLI",
        "mnfmQe8Mv1g",
        "-Xgi_way56U",
        "CHahce95B1g"
    ]);

I wouldn’t be doing this for a playlist, I would be doing something else?

playlist: "0dgNc5S8cLI,mnfmQe8Mv1g,-Xgi_way56U,CHahce95B1g",

addRandom is working, playlist is not working.
https://jsfiddle.net/uvd48syr/

  managePlayer.addRandom(".playa", {
        height: 207,
        start: 45,
        width: 277
    }, [
        "0dgNc5S8cLI",
        "mnfmQe8Mv1g",
        "-Xgi_way56U",
        "CHahce95B1g"
    ]);
    managePlayer.add(".playb", {
        height: 207,
        playlist: "0dgNc5S8cLI,mnfmQe8Mv1g,-Xgi_way56U,CHahce95B1g",
        width: 277
    });