[thelist] Reliable end-of-queue onload event

Barney Carroll barney at clickwork.net
Tue Aug 11 08:08:19 CDT 2009


Hello list,

For a while I've enhanced my sites with variations of a script that hides
the page while it loads, and presents the user with the finished and
fully-functional thing as and when it's ready. I'm now trying to refine this
script into a reliably portable form so that it can be dropped in at the end
of any page's head element and prevent semi-functional half-rendered pages
from imposing themselves upon you too early.

Script below:

<script type="text/javascript">
	// Barney's graceful page load script v0.9
	// Hide the body contents and display a loading image until the
entire page has loaded

	
	// Write a style tag to hide body's children and use a loading image
as the body's background
	
	document.write('<style id="bodyHider"
type="text/css">body{visibility:hidden;}
html{background-color:#dbe7f3;background-image:url(data:image/gif;base64,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);background-position:50%
50%;background-repeat:no-repeat;cursor:progress;height:100%;overflow:hidden}</style>');

	// Function to remove the style tag
	
	function revealBody(){
		document.getElementsByTagName('head')[0].removeChild(document.getElementById('bodyHider'));
	}
	
	// Run the remove style tag when the body has loaded, or after any
other scripts waiting for the body load event if they exist

	
	var onloadEvent = window.onload;
	if(typeof window.onload != 'function'){
		window.onload = revealBody;
	} else{
		window.onload = function(){
			onloadEvent();
			revealBody();
		}
	}

</script>


As you can see, the mechanism is stupidly simple — document.write a style
tag that hides the body and base-64 include a background image of a
'loading...' animated gif, then when the page has loaded, delete the style
tag to leave the page as the authors intended.

I found a page which loads over 500kb of Javascript, much of it called from
within the body tag, including Google Maps, Prototype, and several
stand-alone DOM-manipulation plugins, and suffers a significant pause
halfway through rendering the body while the scripts go back over what's
there, edit, adjust, etc — basically a page that could really use this
script. However when I insert the code above, my window.onload event never
fires (I assume this was one of the other scripts commandeering the
window.onload event) so I tried editing the script to associate the function
call with an attachEvent/eventListener for the window (or document,
whichever the browser could use) load event, but this fired way too early —
before most of the content had rendered — and it was only after this event
that I got prompts such as 'Google Maps API key incorrect' etc.

So using the first method, my event never fires, and using the second it
fires too early to be of any use. I want the function's trigger to execute
at the end of the queue of any other scripts waiting for a full page load
(or as close as possible). Is there a more reliable way of associating my
function with the load event?


Regards,
Barney Carroll

barney.carroll at gmail.com
07594 506 381



More information about the thelist mailing list