Search code examples
flaskiframewindowjinja2loading

Removing loading screen and spinner after all contents of the window have loaded but before iframes have finished loading


I am using a loading screen with a spinner that is displayed before all contents in the window have loaded. It works well on all pages and the window loads very fast on webpages with less content but on one of my pages, I am loading many iframes that embed youtube videos. $(window).on('load', function(){}); doesn't trigger until all contents have loaded, including iframes. That means that loading takes a long time and the loading screen with the spinner is shown long after the browser has finished loading the HTML, CSS, JS, and all images. I want to use skeleton loading for the iframes after the HTML, CSS, JS, and all images have loaded to cut down on perceived load time. Is there a way to tell that the rest of the window has fully loaded but the iframes are still loading? This is what I am currently doing to remove the loading screen with the spinner:

<html>
<head>
</head>
<div class="spinner-wrapper">
  <div class="spinner">
    <div class="rect1"></div>
    <div class="rect2"></div>
    <div class="rect3"></div>
    <div class="rect4"></div>
    <div class="rect5"></div>
  </div>
</div>
<body>
 {% for video in range(videos|length) %}
   <iframe class="yvideo" src="{{ "https://www.youtube.com/embed/%s" + videos[video]}.get("url") }}"></iframe>
 {% endfor %}
 <script type=module src="{{ url_for('static', filename='js/video.js') }}"></script>
</body>
</html>

videos.js:

$(window).on('load', function() {
    preloaderFadeOutTime = 300;
    function hidePreloader() {
    var preloader = $('.spinner-wrapper');
        preloader.fadeOut(preloaderFadeOutTime);
    }
    hidePreloader();
});

Solution

  • There can be multiple ways to solve this issue:

    One simple approach can be to keep source of iframes empty initially and dynamically set source of iframes upon window.load.

    Here sample code:

     <script>
        $(window).on('load', function() {
    
            document.getElementById('myIframe').src = "your URL";
            document.getElementById('myIframe2').src = "your URL";
    
           preloaderFadeOutTime = 300;
           function hidePreloader() {
             var preloader = $('.spinner-wrapper');
             preloader.fadeOut(preloaderFadeOutTime);
           }
           hidePreloader();
        });
      </script>
    
      <iframe id="myIframe"  src="" ></iframe>
      <iframe id="myIframe2"  src="" ></iframe>
    

    EDIT:
    If you cannot change the video.js file but can create your own js files which can interact with html on the page then do below in your custom js file:

    //your external js
    // first get collection of your iframes by class
     var listOfIframes = document.getElementsByClassName("yvideo");
     for (let item of listOfIframes) {
                item.src = "";  // set them to empty.
            }
     window.addEventListener("load", function() { 
    
    //once page is loaded then populate the source with your json file. 
    
    
     for (let item of listOfIframes) {
                item.src = "URLs from JSON";  
            }
    
     });
    
    
    

    Second approach:

    Instead of calling hidePreloader() only at window.load. You can also check for the rest of the items in your page that if they are loaded or not. Once they are loaded, then you can use call hidePreloader()