Search code examples
javascriptjquerylazy-loadingvimeo

lazy loading vimeo only works on last in array


I have four Vimeo videos on my homepage which slows down the page. I would like to lazy load them. I'm trying to get them to find the video thumbnail, and only load the full video when the thumbnail is clicked on.

So far I can get this to work when there is only one video on the page. However when there are several the last one gets all the thumbnails and only this one will load the video when clicked on.

I think it has to do with my use of a global variable, but I'm unsure how to get it to work without due to the scope of the ajax call to the vimeo servers.

$(document).on('turbolinks:load', function() {
  var video = document.querySelectorAll(".lazy-video");
  // var currentVid;

  for (var i = 0; i < video.length; i++) {
    // set current video global
    currentVid = video[i]

    // get and add image thumbnail
    $.ajax({
      type: 'get',
      url: 'https://vimeo.com/api/v2/video/' + currentVid.dataset.embed + '.json',
      dataType: 'json',
      success: function(data) {
        var image = new Image();
        image.src = data[0]["thumbnail_large"];
        debugger;
        currentVid.appendChild(image);
      }
    })

    // listen for click
    currentVid.addEventListener("click", function() {
      var iframe = document.createElement("iframe");
      iframe.setAttribute("frameborder", "0");
      iframe.setAttribute("allowfullscreen", "");
      iframe.setAttribute("src", "https://player.vimeo.com/video/" + this.dataset.embed + "?autoplay=1&color=0083B2&portrait=0");
      this.innerHTML = "";
      this.appendChild(iframe);
    });
  };
});

Solution

  • You're right, the issue is to do with scope. As you've not used the var keyword on the variable definition it's within global scope and so its value changes in each iteration. Hence only the final video is affected as the loop has long ended when the AJAX calls complete.

    The simple fix to this is to declare the variable using the let keyword in order for it to retain scope within the loop:

    let currentVid = video[i];