I'm receiving a "script error"

JSLint is pretty harsh, but helps to ensure good coding practices.

Often latter messages are fixed by dealing with earlier issues, so we should deal with the issues one at a time from the top, then check again.

Here is the first issue:

Redefinition of ‘cover’ from line 1.

const cover = evt.currentTarget;

We already have a variable called cover defined, right at the top of the code. But that’s a different cover from the one that the event handler was assigned to.

The manageCurtain code doesn’t only have one cover, it’s actually multiple covers. We should rename the variable to show that.

  // const cover = document.querySelectorAll(".jacketa");
  // cover.forEach(function(el) {
  const covers = document.querySelectorAll(".jacketa");
  covers.forEach(function(el) {

That only leaves the split-wrap cover variable at the top which has no relevance to the manageCover code, and can be moved down to where it’s used, both in the onYouTubeIframeAPIReady function, and with the click handler at the bottom of the code.

// const cover = document.querySelector(".split-wrap");
...
function onYouTubeIframeAPIReady() {
  const cover = document.querySelector(".split-wrap");
  const wrapper = cover.parentElement;
  ...
}
...
  const cover = document.querySelector(".split-wrap");
  cover.addEventListener("click", coverClickHandler);
}());

The next issue is:

Redefinition of ‘player’ from line 28.

const player = event.target;

Here is where the player is being defined and redefined.

  const player = null;
  ...
  function onPlayerReady(event) {
    const player = event.target;

That player = null should have been your first clue that it is not to be defined using const.

Further down there is a play function that needs access to that player variable. We want that player to be redefined. The solution? Use let to allow the player to be redefined.

  // const player = null;
  let player = null;
  ...
  function onPlayerReady(event) {
    // const player = event.target;
    player = event.target;

The same issue is solved in the onPlayerStateChange function:

  function onPlayerStateChange(event) {
    // const player = event.target;
    player = event.target;

and is solved in the addPlayer code:

  function addPlayer(video) {
    const playlist = "M7lc1UVf-VE";
    // const player = new YT.Player(video, {
    player = new YT.Player(video, {

The next issue is:

Undeclared ‘YT’.

player = new YT.Player(video, {

We just need to tell JSLint that YT is expected as a global variable, for which a JSLint directive is used. It’s only a comment, but it gives useful information to JSLint.

/*global YT */
(function manageCurtain() {

The next issue is:

Expected property ‘height’ to be ordered before property ‘width’.

height: 360,

Object properties should be defined in alphabetical order.

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

That doesn’t work for us though because width and height are separated a long way from each other.

Because I want to maintain some logical order to the properties, we can define them separately in the config object.

    const playlist = "M7lc1UVf-VE";
    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,
      loop: 1,
      playlist,
      rel: 0
    };
    config.events = {
      "onReady": onPlayerReady,
      "onStateChange": onPlayerStateChange
    };
    player = new YT.Player(video, config);

That keeps us happy and it keeps the linter ordering requirement happy too.

The next issue is:

Expected ‘use strict’ at column 5, not column 3.

“use strict”;

JSLint expects there to be 4 spaces of indenting on lines, which is designed to inform you about when you have too much nested indenting taking place.

With JSFiddle you can go to Settings and set the indent to 4 spaces. When you then use Tidy on the code, the 4 space indent then properly occurs.

Or at least, that works on my desktop computer. For some reason it doesn’t work in JSFiddle on my laptop so we can also use beautifier.io to appropriately indent the code.

The next issue is:

Expected one space between ‘function’ and ‘(’.

covers.forEach(function(el) {

It is possible to solve that just by adding a space, but it’s a good indication about the function itself. Functions are more informative when they are named.

    // covers.forEach(function(el) {
    covers.forEach(function addHandler(el) {

And that solves all of the warnings from JSLint, helping to tidy up issues in the code.

2 Likes