views:

34

answers:

0

I am developing a script to avoid Flashes Of Un-styled Content by hiding the body element until its contents have fully loaded.

This is designed as a plugin for pages rich in disparate and often weighty resources that gradually populate the page, make DOM manipulations etc, leaving the user with a page that is displayed before it is finished and goes through an unseemly narrative of radical, disorienting visual changes before it is properly presentable or even usable.

My original code was inserted just below the title element, before any external resource calls, as follows:

<script>
/*<![CDATA[*/
    (function(){
        function a(b){document.documentElement.setAttribute('class',b);}
        a('scripted loading');
        this.load = a('scripted');
    }());
/*]]>*/
</script>

'scripted' is necessary to call styles exclusively necessary for the Javascript-enabled page render; the 'loading' is used in a short style tag immediately after the script which hides the child body by means of visibility:hidden (display:none won't load associated internal resources in certain browsers), and puts a loading gif as a centered background image for the html element.

So the mechanism ran as follows: in an anonymous function, immediately give the html element a class of 'scripted loading', and on window.load, get rid of the 'loading' class to reveal the loaded page. Execute the anonymous function immediately after parsing.

In practice, on a sample large site landing page (2.6 MB), I was still getting FOUC — even when all the resources were called directly from my file system — in particular a large Flash object would flick in later (dramatically changing the layout), and styles relating to dynamically hidden content would be briefly visible after the body had been revealed.

So I tried delaying the execution of the function removing the 'loading' class:

<script>
/*<![CDATA[*/
    var a = document.documentElement,
        b = function(c){a.setAttribute('class',c);};
    b('scripted loading');
    a.onload = this.setTimeout('b(\'scripted\')',500);
/*]]>*/
</script>

Again, still with everything on my local filesystem and loaded from cache, the FOUC remained. When I delayed the final function execution to 1 second after document load (already fumbling for what may be a better indicator of full load), the page was revealed as it should be: however by this point I've forced all users to see the loading gif for an arbitrary full second. It's hardly ideal.

What I'm after is a better indicator of the page having fully loaded and processed. Do I have to set listeners for every external resource's having loaded and assume necessary processing and rendering time thereafter to trigger an accurate 'user-ready' event?

All answers welcome…