javascripthtmlcssvideovimeo

Play / pause Vimeo Video when watcher switches browser tab or minimize browser window


I'm using Vimeo Pro to upload video courses on a Wordpress Website and then, I use H5P to add interactions to the video.

In order to insert these vimeo videos in H5P Interactive Videos I need to use the .mp4 distribution of Vimeo Pro (and not the Vimeo Iframe). This is an example:

https://player.vimeo.com/external/376040732.sd.mp4?s=a88abddb83ad31962643b6c4dd8270323d80874e&profile_id=165


ON THE WEBSITE

If I inspect my website, this is the code:

<div class="h5p-video-wrapper h5p-video hardware-accelerated">

<video src="https://player.vimeo.com/external/376040732.sd.mp4?s=a88abddb83ad31962643b6c4dd8270323d80874e&amp;profile_id=165" webkit-playsinline="" playsinline="" preload="metadata" disableremoteplayback="" class="h5p-video" style="display: block;">
</video>
<div class="h5p-overlay h5p-ie-transparent-background"></div>

</div>

MY REQUEST

Which is the simplest method to pause the video when students switches the browser tab or minimize browser window? Thanks for your help!

EDIT - SOLUTION

Both Matt Oestreich's and Oliver Tacke's scripts works if you insert only one H5P Interactive Video in a webpage.

NB: If you need to insert more than one H5P Interactive Video in a webpage, use the Matt Oestreich's script.


Solution



  • ANSWER:

    I had to clear out a lot of the previous updates, due to character limits in these answers.

    I managed to get it working with multiple iframes..

    The only issue with this is if someone plays 2 different videos, then clicks on a different tab (pauses all videos) and they come back, it will play all videos... I can try to figure something out to resolve that, but for now this should do.

    Make sure to check out the updated demo site above as well..

    Just put this script on any page that has a video you wish to pause/play using Page Visible API and the rest should take care of itself.

    You will need to use the following:

    const THE_IFRAME_SELECTOR = 'iframe[id^="h5p-iframe-"]'; // matches all iframes with an id that starts with h5p-iframe-
    const THE_VIDEO_SELECTOR = 'video.h5p-video'; // since all videos appear to have the same class you don't need to change this
    

    Therefore, the new script should look like this:

    // ====================================================================================================================
    // ~~~ SECOND SCRIPT ~~~ 
    // THIS WAITS FOR THE IFRAME AND THE VIDEO INSIDE OF THE IFRAME TO BE CREATED BEFORE INITIALIZING THE PAGE VISIBLE API
    // ====================================================================================================================
    // "Global" variables.
    const THE_IFRAME_SELECTOR = 'iframe[id^="h5p-iframe-"]'; // matches all iframes with an id that starts with h5p-iframe-
    const THE_VIDEO_SELECTOR = 'video.h5p-video'; // since all videos appear to have the same class you don't need to change this
    
    waitForMultipleElements(document, THE_IFRAME_SELECTOR, () => {
      let ALL_IFRAMES = document.querySelectorAll(THE_IFRAME_SELECTOR);
      ALL_IFRAMES.forEach(FOUND_IFRAME => {
        let FOUND_IFRAME_SELECTOR = `#${FOUND_IFRAME.id}`;
        console.log("FOUND_IFRAME_SELECTOR:", FOUND_IFRAME_SELECTOR)
        waitForElement(document, FOUND_IFRAME_SELECTOR, () => {
          waitForVideoElement(FOUND_IFRAME_SELECTOR, THE_VIDEO_SELECTOR, () => {
            initPageVisibleApi(FOUND_IFRAME_SELECTOR, THE_VIDEO_SELECTOR);
          });
        });
      });
    });
    
    function waitForMultipleElements(parentEl, selector, callback) {
      let theInterval = setInterval(() => {
        console.log('still waiting for all elements: ' + selector);
        let elements = parentEl.querySelectorAll(selector);
        if (elements.length) {
          console.log("elements: " + selector + " exist!");
          clearInterval(theInterval);
          callback();
        }
      }, 1000);
    }
    
    function waitForVideoElement(iframeSelector, videoElementSelector, callback) {
      let theIframeElement = document.querySelector(iframeSelector);
      let iframeEl = theIframeElement.contentWindow.document;
      waitForElement(iframeEl, videoElementSelector, () => {
        callback()
      });
    }
    
    function waitForElement(parentEl, selectorOfElementToWaitFor, callback) {
      let theInterval = setInterval(() => {
        console.log("still waiting for " + selectorOfElementToWaitFor);
        let element = parentEl.querySelector(selectorOfElementToWaitFor);
        if (element) {
          console.log(selectorOfElementToWaitFor + " exists!");
          clearInterval(theInterval);
          callback();
        }
      }, 100);
    }
    
    function initPageVisibleApi(iframeSelector, videoSelector) {
      // This is the same code that builds out the Page Visible API
      // event listeners. 
      // The only difference is I wrapped it in a function and added 
      // parameters to make it flexible.
      const iframe = document.querySelector(iframeSelector);
      const innerDoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;
      const videoElement = innerDoc.querySelector(videoSelector);
      // Set the name of the hidden property and the change event for visibility
      var hidden, visibilityChange;
      if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support 
        hidden = "hidden";
        visibilityChange = "visibilitychange";
      } else if (typeof document.msHidden !== "undefined") {
        hidden = "msHidden";
        visibilityChange = "msvisibilitychange";
      } else if (typeof document.webkitHidden !== "undefined") {
        hidden = "webkitHidden";
        visibilityChange = "webkitvisibilitychange";
      }
    
      // To tell if video has been played yet or not
      let VIDEO_HAS_BEEN_PLAYED = false;
      // If the page is hidden, pause the video;
      // if the page is shown, play the video
      function handleVisibilityChange() {
        if (VIDEO_HAS_BEEN_PLAYED) {
          if (document[hidden]) {
            videoElement.pause();
          } else {
            videoElement.play();
          }
        }
      }
      // Warn if the browser doesn't support addEventListener or the Page Visibility API
      if (typeof document.addEventListener === "undefined" || hidden === undefined) {
        alert("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
      } else {
        // Handle page visibility change   
        document.addEventListener(visibilityChange, handleVisibilityChange, false);
    
        // When the video pauses, set the title.
        // This shows the paused
        const defaultTitle = document.title;
        videoElement.addEventListener("pause", function () {
          document.title = 'Paused - ' + defaultTitle;
        }, false);
        // When the video plays, set the title.
        videoElement.addEventListener("play", function () {
          VIDEO_HAS_BEEN_PLAYED = true;
          document.title = 'Playing - ' + defaultTitle;
        }, false);
      }
    }
    // ====================================================================================================================
    // ---------- END SECOND SCRIPT ------------
    // ====================================================================================================================