-1

There are these 2 warnings coming up in the javascript, how do I get rid of them?

Can someone provide an answer to show me how to remove the warning?

https://jsfiddle.net/qjp7hfya/

It says this for both of them.

Functions declared within loops referencing an outer scoped variable may lead to confusing semantics

enter image description here

(function() {
  let YouTubeContainers = document.querySelectorAll(".embed-youtube");

  // Iterate over every YouTube container you may have
  for (let i = 0; i < YouTubeContainers.length; i++) {
    let container = YouTubeContainers[i];
    let imageSource = "https://img.youtube.com/vi/" + container.dataset.videoId + "/sddefault.jpg";

    // Load the Thumbnail Image asynchronously
    let image = new Image();
    image.src = imageSource;
    image.addEventListener("load", function() {
      container.appendChild(image);
    });

    // When the user clicks on the container, load the embedded YouTube video

    const addImageToContainer = function(container, image) {
      container.appendChild(image);
    };

    container.querySelector("button").addEventListener("click", function() {
      let iframe = document.createElement("iframe");

      iframe.setAttribute("frameborder", "0");
      iframe.setAttribute("allowfullscreen", "");
      iframe.setAttribute("allow", "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture");
      // Important: add the autoplay GET parameter, otherwise the user would need to click over the YouTube video again to play it 
      iframe.setAttribute("src", "https://www.youtube.com/embed/" + container.dataset.videoId + "?rel=0&showinfo=0&autoplay=1&fs=0");

      // Clear Thumbnail and load the YouTube iframe
      container.innerHTML = "";
      container.appendChild(iframe);
    });
  }
})();
Eve Ninnall
  • 1
  • 3
  • 20
  • It is a warning but because you are using let it will work just fine. If you were using var, the variable will most likely be alwasy the last one. https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example – Agustin Pazos Oct 31 '22 at 01:44
  • 1
    How do I get rid of the warning, can you show me? – Eve Ninnall Oct 31 '22 at 01:47
  • 1
    Can someone provide an answer to show me how to remove the warning? – Eve Ninnall Oct 31 '22 at 01:49
  • An easy way is to select Babel+JSX as your language in jsFiddle – Agustin Pazos Oct 31 '22 at 01:58
  • I don't understand those languages. – Eve Ninnall Oct 31 '22 at 02:01
  • Is a javascript transpiler, so you can set it as your language and type pure js code with no problem. But as it is already set to understand ES6 it wont show the warning. – Agustin Pazos Oct 31 '22 at 02:04
  • 1
    How would I get rid of the warning manually? Can an answer be provided? – Eve Ninnall Oct 31 '22 at 02:06
  • Here's a SO discussion on the topic of the warning: [Functions declared within loops referencing an outer scoped variable may lead to confusing semantics.](https://stackoverflow.com/questions/46027262/functions-declared-within-loops-referencing-an-outer-scoped-variable-may-lead-to) – bloodyKnuckles Oct 31 '22 at 13:34

1 Answers1

0

Functions declared within loops referencing an outer scoped variable may lead to confusing semantics. (container, image)

Simply a warning, so doesn't break code, but points to a way to avoid the warning—pass the variables through function parameters. This is not directly possible with the flagged function here: ...addEventListener("click", function()..., because it's an event handler and it utilizes predetermined parameters—so wrap the addEventListener in an anonymous, immediately invoked function expression (IIFE), and pass the offending variables as parameters. This creates a function scope that both separates the outer variables from the inner scope and still makes them available to the inner scope.

Replace:

image.addEventListener("load", function() {
  container.appendChild(image);
});

...with:

(function (container, image) { // <-- instantiate function variables
  image.addEventListener("load", function() {
    container.appendChild(image);
  });
}(container, image)); // <-- pass the outer variables to the function

There are two of the same warnings presented. The same method can be used, or...

Another method to pass additional variables to an event handler is to write a function that returns a function. Passing the variables to the outer function creates a function scope that, again, both separates the outer variables from the inner scope and still makes them available to the inner scope. To pass the return'ed function to the event execute the outer function in place, i.e., in the addEventListener() parameters where the handler function normally goes:

Replace:

  container.querySelector("button").addEventListener("click", function() {
    let iframe = document.createElement("iframe");

    iframe.setAttribute("frameborder", "0");
    iframe.setAttribute("allowfullscreen", "");
    iframe.setAttribute("allow", "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture");
    // Important: add the autoplay GET parameter, otherwise the user would need to click over the YouTube video again to play it 
    iframe.setAttribute("src", "https://www.youtube.com/embed/" + container.dataset.videoId + "?rel=0&showinfo=0&autoplay=1&fs=0");

    // Clear Thumbnail and load the YouTube iframe
    container.innerHTML = "";
    container.appendChild(iframe);
  });

} // end of YouTubeContainers for loop

...with:

  container.querySelector("button")
    .addEventListener(
      "click", 
      containerBtnHandler(document, container) // <-- execute the function that returns the handler function
                                               // ...and pass the outer variables to it
    );

} // end of YouTubeContainers for loop

// PUT the function that returns the handler OUTSIDE the for loop...

function containerBtnHandler (document, container) {
  return function () { // return the original event handler
    let iframe = document.createElement("iframe");

    iframe.setAttribute("frameborder", "0");
    iframe.setAttribute("allowfullscreen", "");
    iframe.setAttribute("allow", "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture");
    // Important: add the autoplay GET parameter, otherwise the user would need to click over the YouTube video again to play it 
    iframe.setAttribute("src", "https://www.youtube.com/embed/" + container.dataset.videoId + "?rel=0&showinfo=0&autoplay=1&fs=0");

    // Clear Thumbnail and load the YouTube iframe
    container.innerHTML = "";
    container.appendChild(iframe);
  };
}

Warning: This only avoids the warning, but doesn't necessarily remove the possibility of "lead[ing] to confusing semantics." Mastery of a craft means one knows when and how they can break the "rules" with impunity.

Here's a SO discussion on the topic of the warning: Functions declared within loops referencing an outer scoped variable may lead to confusing semantics.

bloodyKnuckles
  • 11,551
  • 3
  • 29
  • 37
  • 1
    But now the code doesn't work, Seen Here: https://jsfiddle.net/uo8p51wb/ How do I add the other stuff back into the code so that it is fully working like it was before? Seen Here: https://jsfiddle.net/qjp7hfya/ It would help me to be able to see the code working fully. – Eve Ninnall Oct 31 '22 at 08:00
  • 1
    Can you edit your answer please to include the whole code? – Eve Ninnall Oct 31 '22 at 10:52
  • 1
    Can you edit the jsfiddle with the code working? https://jsfiddle.net/qjp7hfya/ – Eve Ninnall Oct 31 '22 at 11:35
  • 1
    Can you attach both those examples with jsfiddle links please? – Eve Ninnall Oct 31 '22 at 13:43
  • Please explain, why are you not able to copy the examples into your jsfiddle link? I'm happy to teach and help people in need—just let me know! – bloodyKnuckles Oct 31 '22 at 14:11
  • 1
    I am, I am just not understanding your instructions on what to do, that is all. Seeing it in a jsfiddle would help. – Eve Ninnall Oct 31 '22 at 15:15
  • @EricaLevine I'm happy to walk you through it—join me here with your questions: https://chat.stackoverflow.com/rooms/249201/how-to-remove-two-warnings-from-the-javascript However SO is not the place to find people to do your work for you. – bloodyKnuckles Oct 31 '22 at 15:34