Search code examples
javascripthtmljqueryvideowistia

How to get Javascript to run after a video has fully loaded in the DOM


How do I ensure my Javascript always loads after an embedded Wistia video loads?

I have a page that has a Wistia video embedded on it, and some Javascript that is trying to do the following:

  1. Detect the play button of the video (and full screen button)
  2. Listen for when the play button is clicked (or clicked again, aka paused)
  3. Start a timer when the play button is clicked
  4. Pause the timer when the video is paused
  5. After enough time passes, reveal some hidden content

I had this working during testing, but later I realized it was failing on most occasions because my Javascript was running before the Wistia video was loaded, therefore, it wasn't finding the video elements I need to add eventlisteners to.

I tried to look up solutions to defer javascript or wait for the whole page to load, but it isn't working. Any help you could provide to get this timer working 100% of the time would be appreciated!!

Please view my code below, or look at the JSFiddle right here: https://jsfiddle.net/skuq16t3/

HTML

<div id="video">
  <script src="https://fast.wistia.com/embed/medias/wd2eroj8k3.jsonp" async></script><script src="https://fast.wistia.com/assets/external/E-v1.js" async></script>
  <div class="wistia_responsive_padding" style="padding: 56.25% 0 0 0; position: relative;">
    <div class="wistia_responsive_wrapper" style="height: 100%; left: 0; position: absolute; top: 0; width: 100%;">
      <div class="wistia_embed wistia_async_wd2eroj8k3 videoFoam=true" style="height: 100%; position: relative; width: 100%;">
        <div class="wistia_swatch" style="height: 100%; left: 0; opacity: 0; overflow: hidden; position: absolute; top: 0; transition: opacity 200ms; width: 100%;">
          <img style="filter: blur(5px); height: 100%; object-fit: contain; width: 100%;" src="https://fast.wistia.com/embed/medias/wd2eroj8k3/swatch" alt="" aria-hidden="true" />
        </div>
      </div>
    </div>
  </div>
</div>
<div id="countdowntimer">
  <p class="left normaltext countdowntext">Your exclusive invitation will be unlocked in <span class="countdowntimerspan"><span id="minutesleft">16</span>:<span id="secondsleft">50</span></span></p>
  <p class="stopwatchscreen"><span id="minutes">00</span>:<span id="seconds">00</span>:<span id="tens">00</span></p>
</div>
<div id="hiddencontentunlockedbytimer">
  <p>Hidden content here</p>
</div>

CSS

#video {
  max-width: 400px;
}
#countdowntimer {
    background: #fafafa;
    padding: 20px;
    text-align: center;
    border: 3px solid #b81937;
    border-radius: 5px;
    margin: 40px 20px;
    font-size: 24px;
    box-shadow: 5px 5px 10px #aaa;
}
#hiddencontentunlockedbytimer {
    display: none;
}

Javascript

jQuery(document).ready(function() {
    console.log('The page is now loaded');
    var Interval;
    var minutes = 0; 
    var seconds = 0; 
    var tens = 0; 
    var appendTens = document.getElementById('tens');
    var appendSeconds = document.getElementById('seconds');
    var appendMinutes = document.getElementById('minutes');
    // make variables for how much time needs to pass before the video is finished
    var minutesUntilFinished = 16; // change this
    var secondsUntilFinished = 50; // change this
    // make variables for the countdown timer
    var appendSecondsCD = document.getElementById('secondsleft');
    var appendMinutesCD = document.getElementById('minutesleft');
    
    // This is the full screen button. Do nothing when this is clicked
    var wistiaFullScreenButton = document.querySelector('#wistia_grid_29_main button.w-vulcan-v2-button.w-css-reset.w-css-reset-tree.w-css-reset-button-important');

    // find the things that will start and pause the Wistia video
    var wistiaBigPlayButton = document.querySelector('#wistia_grid_29_main button.w-big-play-button.w-css-reset-button-important.w-vulcan-v2-button');
    var wistiaVideoArea = document.querySelector('#wistia_grid_29_main .w-vulcan--background.w-css-reset');
    
    // test if different parts of the Wistia video were found and then clicked  
    if(wistiaFullScreenButton) {
        console.log('The full screen button was found');
        document.querySelector('#wistia_grid_29_main button.w-vulcan-v2-button.w-css-reset.w-css-reset-tree.w-css-reset-button-important').addEventListener('click', function() {
            console.log('The Wistia full screen button was clicked');
        });
    } else {
        console.log('The full screen button was NOT found');
    }
    if(wistiaBigPlayButton) {
        console.log('The big Wistia play button was found');
        document.querySelector('#wistia_grid_29_main button.w-big-play-button.w-css-reset-button-important.w-vulcan-v2-button').addEventListener('click', function() {
            console.log('The big Wistia play button was clicked');
        });
    } else {
        console.log('The big Wistia play button was NOT found');
    }
    if(wistiaVideoArea) {
        console.log('The Wistia video area was found');
        document.querySelector('#wistia_grid_29_main .w-vulcan--background.w-css-reset').addEventListener('click', function() {
            console.log('The Wistia video area was clicked');
        });
    } else {
        console.log('The Wistia video area was NOT found');
    }
    
    // figure out if a number is even or odd (for pausing the timer)
    function isOdd(num) { 
        return num % 2;
    }
    
    // start the timer after the big button is pressed the first time
    jQuery(wistiaBigPlayButton).one('click', function() {
        
        console.log('The Big Wistia play button was clicked for the first time');
        
        var BigPlayClickCount = 1;
        
        // start the timer
        clearInterval(Interval);
        Interval = setInterval(startTimer, 10);
        
        // pause the timer if the video is paused
        wistiaBigPlayButton.onclick = function() {
            
            // increase the click count by 1
            BigPlayClickCount++;
            
            console.log(BigPlayClickCount);
            
            // if its an even number, start the timer
            if(isOdd(BigPlayClickCount) == 1) {
                clearInterval(Interval);
                Interval = setInterval(startTimer, 10);
            }
            // if its an odd number, pause the timer
            if(isOdd(BigPlayClickCount) == 0) {
                clearInterval(Interval);
            }
        }
        // pause the timer if the video is paused
        wistiaVideoArea.onclick = function() {
            
            // increase the click count by 1
            BigPlayClickCount++;
            
            console.log(BigPlayClickCount);
            
            // if its an even number, start the timer
            if(isOdd(BigPlayClickCount) == 1) {
                clearInterval(Interval);
                Interval = setInterval(startTimer, 10);
            }
            // if its an odd number, pause the timer
            if(isOdd(BigPlayClickCount) == 0) {
                clearInterval(Interval);
            }
        }
    });
    
    // also start the timer if they click on the video but not the big red button (both work)
    jQuery(wistiaVideoArea).one('click', function() {
        
        console.log("The Wistia video area was clicked for the first time");
        
        var BigPlayClickCount = 1;
        console.log(BigPlayClickCount);
        
        // start the timer
        clearInterval(Interval);
        Interval = setInterval(startTimer, 10);
        
        // pause the timer if the video is paused
        wistiaBigPlayButton.onclick = function() {
            
            // increase the click count by 1
            BigPlayClickCount++;
            
            console.log(BigPlayClickCount);
            
            // if its an even number, start the timer
            if(isOdd(BigPlayClickCount) == 1) {
                clearInterval(Interval);
                Interval = setInterval(startTimer, 10);
            }
            // if its an odd number, pause the timer
            if(isOdd(BigPlayClickCount) == 0) {
                clearInterval(Interval);
            }
        }
        // pause the timer if the video is paused
        wistiaVideoArea.onclick = function() {
            
            // increase the click count by 1
            BigPlayClickCount++;
                            
            // if its an even number, start the timer
            if(isOdd(BigPlayClickCount) == 1) {
                clearInterval(Interval);
                Interval = setInterval(startTimer, 10);
            }
            // if its an odd number, pause the timer
            if(isOdd(BigPlayClickCount) == 0) {
                clearInterval(Interval);
            }
        }
    });
    
    function startTimer () {
        tens++;
        // add a 0 at the beginning if less than 9
        if(tens <= 9) {
            appendTens.innerHTML = "0" + tens;
        }
        if (tens > 9) {
            appendTens.innerHTML = tens;
        } 
        if (tens > 99) {
            seconds++;
            
            // subtract time from the seconds left
            secondsUntilFinished--;
                            
            if (secondsUntilFinished > 9) {
                document.getElementById("secondsleft").innerHTML = secondsUntilFinished;
            }
            if (secondsUntilFinished < 10) {
                document.getElementById("secondsleft").innerHTML = "0" + secondsUntilFinished;
            }
            
            // once the seconds left reaches 0, start back over at 59
            if (secondsUntilFinished < 1) {
                secondsUntilFinished = 60;
            }
            if (secondsUntilFinished == 59) {
                // subtract time from the minutes left counter
                minutesUntilFinished--;

                document.getElementById("minutesleft").innerHTML = minutesUntilFinished;

            }
            
            appendSeconds.innerHTML = "0" + seconds;
            tens = 0;
            appendTens.innerHTML = "0" + 0;
        }
        if (minutesUntilFinished <= 0) {
            minutesUntilFinished = 0;
        }
        if (seconds > 9) {
            appendSeconds.innerHTML = seconds;
        }
        if (seconds > 59) {
            minutes++;
            
            appendMinutes.innerHTML = "0" + minutes;
            seconds = 0;
            appendSeconds.innerHTML = "0" + 0;
            appendTens.innerHTML = "0" + 0;
        }
        // after 1 minute show the countdown timer
        if (minutes > 0) {
            
            var countdowncheck = document.getElementById('countdowntimer');

            if(countdowncheck) {
                document.getElementById('countdowntimer').style.display = 'block';
            }
        }
        // after a certain amount of time passes, show the  hidden content
        if (minutes > 1) {
            
            // after 2 minutes show the hidden content
            var hiddencontentcheck = document.getElementById('hiddencontentunlockedbytimer');
            if(hiddencontentcheck) {
                document.getElementById('hiddencontentunlockedbytimer').style.display = 'block';
            }
        }
    }
});

Solution

  • Lots of code here. Probably could have shrunk this down a bit, but I found the answer. Here in the Wistia docs (https://wistia.com/support/developers/player-api) they have this code sample:

    <script src="//fast.wistia.com/assets/external/E-v1.js" async></script>
    <div class="wistia_embed wistia_async_abcde12345" style="width:640px;height:360px;"></div>
    <script>
    window._wq = window._wq || [];
    _wq.push({ id: 'abcde12345', onReady: function(video) {
      console.log("I got a handle to the video!", video);
    }});
    </script>
    

    Basically, you put in the ID of your specific video and anything inside that function will only load after that video is loaded. Just remove the jquery bit at the beginning and replace it with that. Your updated code would look like this:

    <script>
    window._wq = window._wq || [];
    _wq.push({ id: 'wd2eroj8k3', onReady: function(video) {
    
        // All your code goes here
    
    }});
    </script>
    

    Here is an updated Fiddle, just for reference: https://jsfiddle.net/8z41cLtj/