Search code examples
javascripthtmldelaypreloader

Need to Tweak Pre-loader script to not load on a page that loads in under 1 second


php guy here not a javascript guy. support a site with the below code, need to adjust the preloader to wait and see if the page loaded within a second, if not, then to display the image. Am pretty clueless and have search for examples, the ones I found extend the preloader time, which isnt what i want, here is the code:

<script>
    document.onreadystatechange = function () {
        var state = document.readyState
        if (state == 'interactive') {
            document.getElementById('contents').style.visibility="hidden";
        } else if (state == 'complete') {
            setTimeout(function(){
                document.getElementById('interactive');
                document.getElementById('load').style.visibility="hidden";
                document.getElementById('contents').style.visibility="visible";
            },1);
        }
    }
</script>
<div id="load"></div>

Solution

  • There is some irony in trying to do some DOM manipulation (like your code does) before the document is ready. Usually, you want to avoid DOM manipulation until after the document is ready. I recommend a slightly different and simpler approach. Control the visibility of your loading image via CSS.

    Currently, your #load image is visible by default. To make it hidden by default, add visibility: hidden; to your #load style rule. Next, add a rule for .loading #load that overrides the visibility to make it visible. This means that #load will only be visible when one of its a parent elements has a class of loading, thus activating the rule that overrides visibility.

    #load {
        width:100%;
        height:100%;
        position:fixed;
        z-index:9999;
        background:url("../images/loading.gif") no-repeat fixed center rgba(255,255,255,1);
        visibility: hidden;
    }
    
    .loading #load {
        visibility: visible;
    }
    

    With your CSS in place, the JavaScript is fairly straightforward. We are going use setTimeout to set a delay of 1 second (1000 ms) and then run a function. That function checks to see if the document is ready, and if not, adds the loading class to the root HTML element, thus allowing the #load image to be visible 1 second after the script tag was parsed.

    We also add an event listener on the document for the load event (which happens immediately after document.readyState is set to complete). When that event fires, it removes the loading class from the root element. If this happens to run before 1 second, that's ok. It doesn't matter that the root element doesn't have the loading class yet. It never will, in that case, because it only gets added if the readyState is not yet complete.

    setTimeout(function() {
        if (document.readyState != "complete") {
            document.documentElement.classList.add("loading");
        }
    }, 1000);
    document.addEventListener("load", function() {
        document.documentElement.classList.remove("loading");
    });
    

    You should familiarize yourself with all of the possible values of document.readyState. It's possible that you want to hide your loading image as soon as the document is interactive. In this state, not every image has been downloaded, but the document has been fully parsed and is ready for DOM manipulation. In that case, you would listen for the readystatechange event instead of the load event:

    setTimeout(function() {
        if (document.readyState == "loading") {
            document.documentElement.classList.add("loading");
        }
    }, 1000);
    document.addEventListener("readystatechange", function() {
        if (document.readyState != "loading") { // either interactive or complete
            document.documentElement.classList.remove("loading");
        }
    });