PDA

View Full Version : Using the DOM before window.onload [solution]


brothercake
05-11-2005, 05:39 PM
This is the result of a thread in DOM programming - http://www.codingforums.com/showthread.php?t=56369 - and offers the final result as a useable script.

Here's the library code:

//DOM-ready watcher
function domFunction(f, a)
{
//initialise the counter
var n = 0;

//start the timer
var t = setInterval(function()
{
//continue flag indicates whether to continue to the next iteration
//assume that we are going unless specified otherwise
var c = true;

//increase the counter
n++;

//if DOM methods are supported, and the body element exists
//(using a double-check including document.body, for the benefit of older moz builds [eg ns7.1]
//in which getElementsByTagName('body')[0] is undefined, unless this script is in the body section)
if(typeof document.getElementsByTagName != 'undefined' && (document.getElementsByTagName('body')[0] != null || document.body != null))
{
//set the continue flag to false
//because other things being equal, we're not going to continue
c = false;

//but ... if the arguments object is there
if(typeof a == 'object')
{
//iterate through the object
for(var i in a)
{
//if its value is "id" and the element with the given ID doesn't exist
//or its value is "tag" and the specified collection has no members
if
(
(a[i] == 'id' && document.getElementById(i) == null)
||
(a[i] == 'tag' && document.getElementsByTagName(i).length < 1)
)
{
//set the continue flag back to true
//because a specific element or collection doesn't exist
c = true;

//no need to finish this loop
break;
}
}
}

//if we're not continuing
//we can call the argument function and clear the timer
if(!c) { f(); clearInterval(t); }
}

//if the timer has reached 60 (so timeout after 15 seconds)
//in practise, I've never seen this take longer than 7 iterations [in kde 3
//in second place was IE6, which takes 2 or 3 iterations roughly 5% of the time]
if(n >= 60)
{
//clear the timer
clearInterval(t);
}

}, 250);
};

Put that in an external JS and add it to your page - it can go anywhere, but if it's going to call other functions it must come after them in the source code:

<script type="text/javascript" src="domFunction.js"></script>

Then use the object constructor to define individual functions. You can either call a named function:

var foobar = new domFunction(myFunction);

Or write an anonymous function directly inside the constructor:

var foobar = new domFunction(function()
{
//code ...

});

The function will be called once the DOM is ready (determined by the existence of the getElementsByTagName method and the presence of the <body> element; this is the point at which you can safely use DOM methods, including creating and appending new elements to the <body>).

You can treat it essentially the same as a regular onload function except that - if you're going to manipulate (eg, read from or append to) any existing HTML elements other than the body, you must also test for those elements before calling your script.

And for this purpose the constructor takes an optional second argument - an object-literal which defines the elements or collections that the script should test before trying to call the function:

var foobar = new domFunction(function()
{
//code ...

}, { 'poster' : 'id', 'h1' : 'tag' });

Each name/value pair should be either:

- the ID of an element, followed by the value "id", to test whether that element exists; or
- the tag name of an element, followed by the value "tag", to test whether that collection has any members.