Search code examples
javascriptwistia

How to remove the overlay image on only the selected lazyloaded video?


In the script below, I'm lazyloading two videos. My script is designed to remove the overlay image from the selected video when clicked. However, it's also removing the overlay image from the second video and placing it above it. Another click removes the duplicate image, and a third click plays the video.

How do I remove only the image for the selected video in a way that doesn't affect a second video on the page?

const getVideoId = (wistia_vid) => {
  const classes = Array.from(wistia_vid.querySelector(".wistia_embed").classList);
  const idClass = classes.find((cls) => cls.startsWith("wistia_async_"));
  const id = idClass.replace("wistia_async_", "");

  return id;
};

const removeElems = (wistia_vid) => {
  const toRemove = Array.from(
    wistia_vid.querySelectorAll(".wistia__overlay, .embed-youtube__play, .embed-video__play")
  );

  toRemove.forEach((node) => node.remove());
};

Array.from(document.querySelectorAll(".wistia")).forEach((node) => {
  node.addEventListener("click", () => {
    const videoId = getVideoId(node);
    let wistiaSupportScripts = [
      //adds jsonp file to provide security over requests
      `https://fast.wistia.com/embed/medias/${videoId}.jsonp`
    ];

    removeElems(node);
    
    //Checks if above scripts are already loaded, and if they are... they won't be loaded again
    const id = 'script-ev1';
    if (!document.getElementById(id)) {
      // const id = 'script-ev1';
      var script = document.createElement('script');
      script.id = id;
      script.onload = () => {
        console.log('Ev-1.js loaded and ready to go!');
      };
      script.src = `https://fast.wistia.com/assets/external/E-v1.js` ;
      document.getElementsByTagName('head')[0].appendChild(script);
    } else {
      console.log(`Ev-1.js script with id: ${videoId} already loaded.`);
    }     
    
    //loads supporting scripts into head
    for (var i = 0; i < wistiaSupportScripts.length; i++) {
      let wistiaSupportScript = document.createElement("script");
      wistiaSupportScript.src = wistiaSupportScripts[i];
      let complete = false;
      if (
        !complete &&
        (!this.readyState ||
          this.readyState == "loaded" ||
          this.readyState == "complete")
      ) {
        complete = true;
        console.log(`JSONP script was added.`);
      }

      let wistiaContainers = document.querySelector(".wistia");

      wistiaContainers ? document.getElementsByTagName("head")[0].appendChild(wistiaSupportScript) : console.log("No Wistia videos here.");
    }     

    window._wq = window._wq || [];
    _wq.push({
      //globally scoped
      id: videoId,
      options: {
        autoPlay: true,
        volume: 0.5
      },

      onReady: function (video) {
        playedOnce = true;
        video.popover.show();
        video.play();
      }
    });
  });
});
.wistia {
  position: relative;
  display: block;
  width: 100%;
  max-width: 500px;
  padding: 0;
  overflow: hidden;
  cursor: pointer;
}
.wistia__overlay {
  width: 100%;
  height: auto;
}
.wistia::before {
  display: block;
  content: "";
}
.wistia button.embed-youtube__play {
  background: url("https://nextiva.com/assets/svg/play-button.svg") no-repeat center center, rgba(33, 33, 33, 0.8);
  background-size: 40%;
  background-position: 55%;
  border: 0;
  border-radius: 50%;
  position: absolute;
  transition: all 0.2s ease;
  -webkit-transition: background 0.2s;
  width: 10%;
  aspect-ratio: 1/1;
  max-height: 15%;    
  cursor: pointer;
  z-index: 10;
  display: flex;
  justify-content: center;
  align-items: center;
  top: 50%;
  left: 50%;
  transform: translate3d(-50%, -50%, 0);
}
.wistia:hover button.embed-youtube__play,
.wistia button.embed-youtube__play:focus-visible,
.wistia button.embed-youtube__play:focus {
  background: url("https://nextiva.com/assets/svg/play-button.svg") no-repeat center center, #005fec;
  background-size: 40%;
  background-position: 55%;
}
.wistia_embed,
.wistia embed,
.wistia iframe {
  width: 100%;
  max-height: 100%;
}
<div class="wistia">
  <picture>
    <source srcset="https://embedwistia-a.akamaihd.net/deliveries/48f1d62d1ceddb4284ad9cf67c916235.jpg?auto=format&w=640" media="(min-width: 1200px)">
    <source srcset="https://embedwistia-a.akamaihd.net/deliveries/48f1d62d1ceddb4284ad9cf67c916235.jpg?auto=format&w=310" media="(min-width: 768px)">
    <img src="https://embedwistia-a.akamaihd.net/deliveries/48f1d62d1ceddb4284ad9cf67c916235.jpg?auto=format&w=310" alt="some text" class="wistia__overlay lazy" loading="lazy">
  </picture>
  <div class="wistia_embed wistia_async_vhkqhqhzyq videoFoam=true"></div>
  <button class="embed-youtube__play"></button>
</div>

<div class="wistia">
  <picture>
    <source srcset="https://embed-fastly.wistia.com/deliveries/2eab84ad71cf5acd9c7572d36667d255.jpg?auto=format&w=640" media="(min-width: 1200px)">
    <source srcset="https://embed-fastly.wistia.com/deliveries/2eab84ad71cf5acd9c7572d36667d255.jpg?auto=format&w=310" media="(min-width: 768px)">
    <img src="https://embed-fastly.wistia.com/deliveries/2eab84ad71cf5acd9c7572d36667d255.jpg?auto=format&w=310" alt="Some text" class="wistia__overlay lazy" loading="lazy">
  </picture>
  <div class="wistia_embed wistia_async_8ei13wuby7 videoFoam=true"></div>
  <button class="embed-youtube__play"></button>
</div>


Solution

  • Put this in your CSS:

    .wistia_embed {
        display: none;
    }
    
    .wistia.shown .wistia_embed {
        display: block;
    }
    

    Then, put this in your JS:

    if (!node.classList.contains("shown")) {
        node.classList.add("shown");
    } else {
        return;
    }
    

    Right in the beginning of the event listener function.

    Explanation

    The E-v1.js script shows all the videos at once, when you load this script by the first click with this piece of code:

    const id = 'script-ev1';
    if (!document.getElementById(id)) {
        // const id = 'script-ev1';
        var script = document.createElement('script');
        script.id = id;
        script.onload = () => {
            console.log('Ev-1.js loaded and ready to go!');
        };
        script.src = `https://fast.wistia.com/assets/external/E-v1.js`;
        document.getElementsByTagName('head')[0].appendChild(script);
    } else {
        console.log(`Ev-1.js script with id: ${videoId} already loaded.`);
    }
    

    Before you load this script, there are no videos as is, just the <source> elements. You never indicate with you CSS that videos should be invisible; henceforth, they are visible by default, once the E-v1.js script loads them.

    Now, when you add this CSS snippet above, you indicate that .wistia_embed elements, which are basically the loaded videos, have to be invisible from the beginning.

    With this single line of JS code, only one video will be revealed on click (setting .shown class, which contains display: block; attribute for the .wistia_embed).

    Undefined video.popover

    enter image description here

    I don't know Wistia API that much, but the browser tells that there is no video.popover.show() function. Remove this from your code as well, otherwise the second video won't auto-play by clicking on it.

    onReady: function (video) {
        playedOnce = true;
        video.popover.show(); // remove
        video.play();
    }
    

    Full working code

    const getVideoId = (wistia_vid) => {
        const classes = Array.from(wistia_vid.querySelector(".wistia_embed").classList);
        const idClass = classes.find((cls) => cls.startsWith("wistia_async_"));
        const id = idClass.replace("wistia_async_", "");
    
        return id;
    };
    
    const removeElems = (wistia_vid) => {
        const toRemove = Array.from(
            wistia_vid.querySelectorAll(".wistia__overlay, .embed-youtube__play, .embed-video__play")
        );
    
        toRemove.forEach((node) => node.remove());
    };
    
    Array.from(document.querySelectorAll(".wistia")).forEach((node) => {
        node.addEventListener("click", () => {
            if (!node.classList.contains("shown")) {
                node.classList.add("shown");
            } else {
                return;
            }
    
            const videoId = getVideoId(node);
            let wistiaSupportScripts = [
                //adds jsonp file to provide security over requests
                `https://fast.wistia.com/embed/medias/${videoId}.jsonp`
            ];
    
            removeElems(node);
    
            //Checks if above scripts are already loaded, and if they are... they won't be loaded again
            const id = 'script-ev1';
            if (!document.getElementById(id)) {
                // const id = 'script-ev1';
                var script = document.createElement('script');
                script.id = id;
                script.onload = () => {
                    console.log('Ev-1.js loaded and ready to go!');
                };
                script.src = `https://fast.wistia.com/assets/external/E-v1.js`;
                document.getElementsByTagName('head')[0].appendChild(script);
            } else {
                console.log(`Ev-1.js script with id: ${videoId} already loaded.`);
            }
    
            //loads supporting scripts into head
            for (var i = 0; i < wistiaSupportScripts.length; i++) {
                let wistiaSupportScript = document.createElement("script");
                wistiaSupportScript.src = wistiaSupportScripts[i];
                let complete = false;
                if (
                    !complete &&
                    (!this.readyState ||
                        this.readyState == "loaded" ||
                        this.readyState == "complete")
                ) {
                    complete = true;
                    console.log(`JSONP script was added.`);
                }
    
                let wistiaContainers = document.querySelector(".wistia");
    
                wistiaContainers ? document.getElementsByTagName("head")[0].appendChild(wistiaSupportScript) : console.log("No Wistia videos here.");
            }
    
            window._wq = window._wq || [];
            _wq.push({
                //globally scoped
                id: videoId,
                options: {
                    autoPlay: true,
                    volume: 0.5
                },
    
                onReady: function (video) {
                    playedOnce = true;
                    video.play();
                }
            });
        });
    });
    .wistia {
        position: relative;
        display: block;
        width: 100%;
        max-width: 500px;
        padding: 0;
        overflow: hidden;
        cursor: pointer;
    }
    
    .wistia__overlay {
        width: 100%;
        height: auto;
    }
    
    .wistia::before {
        display: block;
        content: "";
    }
    
    .wistia button.embed-youtube__play {
        background: url("https://nextiva.com/assets/svg/play-button.svg") no-repeat center center, rgba(33, 33, 33, 0.8);
        background-size: 40%;
        background-position: 55%;
        border: 0;
        border-radius: 50%;
        position: absolute;
        transition: all 0.2s ease;
        -webkit-transition: background 0.2s;
        width: 10%;
        aspect-ratio: 1/1;
        max-height: 15%;
        cursor: pointer;
        z-index: 10;
        display: flex;
        justify-content: center;
        align-items: center;
        top: 50%;
        left: 50%;
        transform: translate3d(-50%, -50%, 0);
    }
    
    .wistia:hover button.embed-youtube__play,
    .wistia button.embed-youtube__play:focus-visible,
    .wistia button.embed-youtube__play:focus {
        background: url("https://nextiva.com/assets/svg/play-button.svg") no-repeat center center, #005fec;
        background-size: 40%;
        background-position: 55%;
    }
    
    .wistia_embed,
    .wistia embed,
    .wistia iframe {
        width: 100%;
        max-height: 100%;
    }
    
    .wistia_embed {
        display: none;
    }
    
    .wistia.shown .wistia_embed {
        display: block;
    }
    <div class="wistia">
        <picture>
            <source
                srcset="https://embedwistia-a.akamaihd.net/deliveries/48f1d62d1ceddb4284ad9cf67c916235.jpg?auto=format&w=640"
                media="(min-width: 1200px)">
            <source
                srcset="https://embedwistia-a.akamaihd.net/deliveries/48f1d62d1ceddb4284ad9cf67c916235.jpg?auto=format&w=310"
                media="(min-width: 768px)">
            <img src="https://embedwistia-a.akamaihd.net/deliveries/48f1d62d1ceddb4284ad9cf67c916235.jpg?auto=format&w=310"
                alt="some text" class="wistia__overlay lazy" loading="lazy">
        </picture>
        <div class="wistia_embed wistia_async_vhkqhqhzyq videoFoam=true"></div>
        <button class="embed-youtube__play"></button>
    </div>
    
    <div class="wistia">
        <picture>
            <source
                srcset="https://embed-fastly.wistia.com/deliveries/2eab84ad71cf5acd9c7572d36667d255.jpg?auto=format&w=640"
                media="(min-width: 1200px)">
            <source
                srcset="https://embed-fastly.wistia.com/deliveries/2eab84ad71cf5acd9c7572d36667d255.jpg?auto=format&w=310"
                media="(min-width: 768px)">
            <img src="https://embed-fastly.wistia.com/deliveries/2eab84ad71cf5acd9c7572d36667d255.jpg?auto=format&w=310"
                alt="Some text" class="wistia__overlay lazy" loading="lazy">
        </picture>
        <div class="wistia_embed wistia_async_8ei13wuby7 videoFoam=true"></div>
        <button class="embed-youtube__play"></button>
    </div>