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

It’s in 2 spots in here.

How is that fixed in the code? https://jsfiddle.net/2gpu38sx/

(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
    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);
    });
  }
})();

Like this? https://jsfiddle.net/s53tcua1/

(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;

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

    // 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",
        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);
    };
  }
})();

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