1592

With jQuery, we all know the wonderful .ready() function:

$('document').ready(function(){});

However, let's say I want to run a function that is written in standard JavaScript with no library backing it, and that I want to launch a function as soon as the page is ready to handle it. What's the proper way to approach this?

I know I can do:

window.onload="myFunction()";

Or I can use the body tag:

<body onload="myFunction()">

Or I can even try at the bottom of the page after everything, but the end body or html tag like:

<script type="text/javascript">
    myFunction();
</script>

What is a cross-browser(old/new)-compliant method of issuing one or more functions in a manner like jQuery's $.ready()?

Aryan Beezadhur
  • 2,647
  • 1
  • 12
  • 31
chris
  • 31,824
  • 49
  • 132
  • 238
  • 1
    support for older browsers is nice, but with as fast as tech is moving forward and people seem to be catching up quicker these days its not 100% needed but a nice bonus if possible. Overall I am trying to figure what if any of these is the standard across browsers. Do they all work? Does it matter which I choose? If they all work what would be suggested as the best vs the rest? – chris Mar 28 '12 at 00:00
  • 9
    See this: http://stackoverflow.com/questions/799981/document-ready-equivalent-without-jquery – Dan A. Mar 28 '12 at 00:00
  • @clexmond putting script at the bottom vs top is something I've always understood for a variety of reasons. I tend to place it at the bottom, external files or on the page itself. But last couple years I've been spoiled by jQuery and other libraires. However I am now on a crusade of sorts trying to get a better understanding of javascript by itself with no lib backing it. So despite knowing what I know of javascript this simple little thing throws me off a bit as I want to make sure any script I do follows a compliant cross browser methodology. – chris Mar 28 '12 at 00:04
  • 4
    You could check out the source of jQuery to see how they implement the document ready function and work from there. – joshuahealy Mar 28 '12 at 00:04
  • @DanA. Nice. I think that sums the answer to this question up some. So JavaScript alone, there's no absolute way of easily finding a ready state, a means of sorts has to be created to support it across the various browsers. Thank you for finding that and clarifying it better for me. – chris Mar 28 '12 at 00:10
  • @chris, right. I'm unfamiliar with the document.ondoncontentready function that maxhud mentioned, but if that becomes standardized, I guess that's the equivalent of what jQuery has now. – Dan A. Mar 28 '12 at 00:13
  • @DanA.: I don't see how that post answers the question of cross-browser compatibility of the `onload` event of `body`, or of placing the script at the bottom of the page. I'm not aware of any actual cross browser issues. Are you? –  Mar 28 '12 at 00:16
  • @amnotiam No, I think onload is pretty standard, if you only need the DOM structure loaded. That would be the most straight-forward way to do it. – Dan A. Mar 28 '12 at 00:19
  • @DanA. that answers the question towards what I was looking for more so than less seeing how jQuery handles it all around tells me despite onload being a semi-straight forward/standard method in sorts it doesn't mean it will work in every situation with every browser, ultimately pending the need of the function I want to build and call upon. Overall I am looking just for when the DOM is fully loaded which onload seems to cover but, at the same time I wanted to see which of the above was a more compliant way of approaching it as well. – chris Mar 28 '12 at 00:30

10 Answers10

2257

The simplest thing to do in the absence of a framework that does all the cross-browser compatibility for you is to just put a call to your code at the end of the body. This is faster to execute than an onload handler because this waits only for the DOM to be ready, not for all images to load. And, this works in every browser.

<!doctype html>
<html>
<head>
</head>
<body>
Your HTML here

<script>
// self executing function here
(function() {
   // your page initialization code here
   // the DOM will be available here

})();
</script>
</body>
</html>

For modern browsers (anything from IE9 and newer and any version of Chrome, Firefox or Safari), if you want to be able to implement a jQuery like $(document).ready() method that you can call from anywhere (without worrying about where the calling script is positioned), you can just use something like this:

function docReady(fn) {
    // see if DOM is already available
    if (document.readyState === "complete" || document.readyState === "interactive") {
        // call on next available tick
        setTimeout(fn, 1);
    } else {
        document.addEventListener("DOMContentLoaded", fn);
    }
}    

Usage:

docReady(function() {
    // DOM is loaded and ready for manipulation here
});

If you need full cross browser compatibility (including old versions of IE) and you don't want to wait for window.onload, then you probably should go look at how a framework like jQuery implements its $(document).ready() method. It's fairly involved depending upon the capabilities of the browser.

To give you a little idea what jQuery does (which will work wherever the script tag is placed).

If supported, it tries the standard:

document.addEventListener('DOMContentLoaded', fn, false);

with a fallback to:

window.addEventListener('load', fn, false )

or for older versions of IE, it uses:

document.attachEvent("onreadystatechange", fn);

with a fallback to:

window.attachEvent("onload", fn);

And, there are some work-arounds in the IE code path that I don't quite follow, but it looks like it has something to do with frames.


Here is a full substitute for jQuery's .ready() written in plain javascript:

(function(funcName, baseObj) {
    // The public function name defaults to window.docReady
    // but you can pass in your own object and own function name and those will be used
    // if you want to put them in a different namespace
    funcName = funcName || "docReady";
    baseObj = baseObj || window;
    var readyList = [];
    var readyFired = false;
    var readyEventHandlersInstalled = false;

    // call this when the document is ready
    // this function protects itself against being called more than once
    function ready() {
        if (!readyFired) {
            // this must be set to true before we start calling callbacks
            readyFired = true;
            for (var i = 0; i < readyList.length; i++) {
                // if a callback here happens to add new ready handlers,
                // the docReady() function will see that it already fired
                // and will schedule the callback to run right after
                // this event loop finishes so all handlers will still execute
                // in order and no new ones will be added to the readyList
                // while we are processing the list
                readyList[i].fn.call(window, readyList[i].ctx);
            }
            // allow any closures held by these functions to free
            readyList = [];
        }
    }

    function readyStateChange() {
        if ( document.readyState === "complete" ) {
            ready();
        }
    }

    // This is the one public interface
    // docReady(fn, context);
    // the context argument is optional - if present, it will be passed
    // as an argument to the callback
    baseObj[funcName] = function(callback, context) {
        if (typeof callback !== "function") {
            throw new TypeError("callback for docReady(fn) must be a function");
        }
        // if ready has already fired, then just schedule the callback
        // to fire asynchronously, but right away
        if (readyFired) {
            setTimeout(function() {callback(context);}, 1);
            return;
        } else {
            // add the function and context to the list
            readyList.push({fn: callback, ctx: context});
        }
        // if document already ready to go, schedule the ready function to run
        if (document.readyState === "complete") {
            setTimeout(ready, 1);
        } else if (!readyEventHandlersInstalled) {
            // otherwise if we don't have event handlers installed, install them
            if (document.addEventListener) {
                // first choice is DOMContentLoaded event
                document.addEventListener("DOMContentLoaded", ready, false);
                // backup is window load event
                window.addEventListener("load", ready, false);
            } else {
                // must be IE
                document.attachEvent("onreadystatechange", readyStateChange);
                window.attachEvent("onload", ready);
            }
            readyEventHandlersInstalled = true;
        }
    }
})("docReady", window);

The latest version of the code is shared publicly on GitHub at https://github.com/jfriend00/docReady

Usage:

// pass a function reference
docReady(fn);

// use an anonymous function
docReady(function() {
    // code here
});

// pass a function reference and a context
// the context will be passed to the function as the first argument
docReady(fn, context);

// use an anonymous function with a context
docReady(function(context) {
    // code here that can use the context argument that was passed to docReady
}, ctx);

This has been tested in:

IE6 and up
Firefox 3.6 and up
Chrome 14 and up
Safari 5.1 and up
Opera 11.6 and up
Multiple iOS devices
Multiple Android devices

Working implementation and test bed: http://jsfiddle.net/jfriend00/YfD3C/


Here's a summary of how it works:

  1. Create an IIFE (immediately invoked function expression) so we can have non-public state variables.
  2. Declare a public function docReady(fn, context)
  3. When docReady(fn, context) is called, check if the ready handler has already fired. If so, just schedule the newly added callback to fire right after this thread of JS finishes with setTimeout(fn, 1).
  4. If the ready handler has not already fired, then add this new callback to the list of callbacks to be called later.
  5. Check if the document is already ready. If so, execute all ready handlers.
  6. If we haven't installed event listeners yet to know when the document becomes ready, then install them now.
  7. If document.addEventListener exists, then install event handlers using .addEventListener() for both "DOMContentLoaded" and "load" events. The "load" is a backup event for safety and should not be needed.
  8. If document.addEventListener doesn't exist, then install event handlers using .attachEvent() for "onreadystatechange" and "onload" events.
  9. In the onreadystatechange event, check to see if the document.readyState === "complete" and if so, call a function to fire all the ready handlers.
  10. In all the other event handlers, call a function to fire all the ready handlers.
  11. In the function to call all the ready handlers, check a state variable to see if we've already fired. If we have, do nothing. If we haven't yet been called, then loop through the array of ready functions and call each one in the order they were added. Set a flag to indicate these have all been called so they are never executed more than once.
  12. Clear the function array so any closures they might be using can be freed.

Handlers registered with docReady() are guaranteed to be fired in the order they were registered.

If you call docReady(fn) after the document is already ready, the callback will be scheduled to execute as soon as the current thread of execution completes using setTimeout(fn, 1). This allows the calling code to always assume they are async callbacks that will be called later, even if later is as soon as the current thread of JS finishes and it preserves calling order.

Jan Kyu Peblik
  • 1,140
  • 11
  • 17
jfriend00
  • 580,699
  • 78
  • 809
  • 825
  • Didn't think of that one. Will older browsers support this as well? Or is this more of a modern approach? – chris Mar 28 '12 at 00:49
  • 3
    Putting the page initialization code after the body content works everywhere even very old browsers. Because of the possibility of using `document.write()` in your javascript and the simplicity that it leads to in coding/implementation, all javascript that isn't explicitly marked as defer or async is loaded sequentially as it is encountered in the page and everything that is before it in the file has already executed or been parsed. – jfriend00 Mar 28 '12 at 00:59
  • 1
    Added a full implementation of a plain javascript function called `docReady()`. – jfriend00 Mar 26 '14 at 05:05
  • 2
    All that the tail script needs to be is a call to the initialisation code, so can be a single call to say `init()`, where functions to be called when the DOM is ready are added to *init*. – RobG Jun 06 '14 at 06:24
  • may i know why u give the ability pass context to the docReady? – slier Feb 17 '15 at 20:05
  • Can you give some instructions on how to namespace the library? https://github.com/jfriend00/docReady/issues/4 – RavenHursT May 19 '15 at 21:24
  • 2
    Why do you call set timeout instead of callback(context) directly ? – Ced May 11 '16 at 11:34
  • 5
    @Ced - It calls `setTimeout()` so that registering a new callback always has the same asynchronous behavior whether the document is already loaded or whether the document is not yet loaded. This avoids some subtle timing bugs in the calling code. The callback will never be called until after the current thread of jS finishes executing. Promises do the same thing with installing a new `.then()` handler for the same reason. – jfriend00 May 11 '16 at 15:12
  • Added type checking for callback to make sure it is a function. – jfriend00 Feb 03 '17 at 21:17
  • This may not work when you use external java script. – kta Dec 14 '17 at 10:22
  • 1
    @kta - What do you mean precisely? If you are manually loading your own scripts, then of course the `DOMContentLoaded` or window `load` event do not apply to them because you can manually load a script any time so you have to track when they are loaded yourself. Other than that, this should work fine with any external script in a regular ` – jfriend00 Dec 14 '17 at 13:32
  • 1
    Why needed to use `(function() { })();`? Does as you said use the code in end of the body is not enough? – Nabi K.A.Z. Jun 28 '18 at 21:53
  • 6
    @NabiK.A.Z. - It's called an IIFE (immediately invoked function expression). It provides a private function scope so your symbols (variables and functions) inside that don't conflict with the global namespace and can't be mussed with by other code. It's a very common way of isolating or protecting code in Javascript. It serves the same purpose as just putting all the code in a function and then calling that function, but this way, no global function name symbol gets defined. – jfriend00 Jun 28 '18 at 22:05
  • This is the most complete answer i have ever saw. – EPurpl3 Apr 19 '19 at 11:47
  • According to https://caniuse.com/#feat=domcontentloaded, `DOMContentLoaded` will work on all modern browsers, including IE starting from version 9. So unless you need to support IE 8 and older, you can just go with the simple `document.addEventListener('DOMContentLoaded', (event) => {});` – ling Jun 07 '19 at 06:15
  • 1
    @ling - That would not fully simulate `jQuery.ready()` in a couple of ways which was the question here. If you also notice the date of this question and answer, this code was provided at a time when `DOMConentLoaded` was not as widely supported. – jfriend00 Jun 07 '19 at 13:55
  • Thank you very much!! This is excellent stuff! – Jens Jan 23 '20 at 00:19
  • @jfriend00 - why you calling `reslove` function in `ready` with `call` method and set it's `this` to `window`? why not just calling it like `readyList[i].fn()` – Ahmadreza_HK Dec 20 '20 at 10:07
  • 1
    @Ahmadreza_HK - I don't recall why I did it that way (that was 8+ years ago). If you don't care if the `this` value is set in your callback to `window` in strict mode, then you can do it as `readyList[i].fn()` just fine. – jfriend00 Dec 20 '20 at 15:39
  • self executing functions do not have access to the fully loaded DOM – Aurovrata Jan 23 '21 at 03:36
  • @Aurovrata - Not sure what you mean by that. They do have access to the fully loaded DOM when they wait for the DOM to be loaded (which is what this code does). – jfriend00 Jan 23 '21 at 03:38
  • no, tried it, `document.querySelector('#my-div')` returns null. Only `DOMContentLoaded` bounded functions work. Self executing functions are run immediately on page load, not on document ready! – Aurovrata Jan 23 '21 at 03:48
  • @Aurovrata - I don't think you understand what this does. `docReady(fn)` registers `fn` as a callback to be called when the DOM has been loaded. Yes, the self-executing function here is executed immediately and it initializes itself and registers a `DOMContentLoaded` handler that it uses to call the other callbacks that `docReady(fn)` loads when the DOM has been loaded. In addition, it keeps track of the loaded state so if you call `docReady(fn)` after the page is already loaded, it will still work properly. – jfriend00 Jan 23 '21 at 03:57
  • sure I do, but your preamble is misleading. – Aurovrata Jan 23 '21 at 04:36
  • @Aurovrata - What is your objection to the simple first version? At the point that code executes all the DOM elements that in the original HTML are available - they've all been parsed and are in the DOM. Images may not yet be loaded, but the `` tag is there. So, what exactly do you think is the issue? – jfriend00 Jan 23 '21 at 05:15
  • Any reason to use `setTimeout(fn, 1)` instead of `setTimeout(fn, 0)`? – Artur Mar 23 '21 at 14:09
  • 1
    @Artur - No reason. Not sure why it was written that way 9 years ago. – jfriend00 Mar 23 '21 at 19:37
215

If you are doing VANILLA plain JavaScript without jQuery, then you must use (Internet Explorer 9 or later):

document.addEventListener("DOMContentLoaded", function(event) {
    // Your code to run since DOM is loaded and ready
});

Above is the equivalent of jQuery .ready:

$(document).ready(function() {
    console.log("Ready!");
});

Which ALSO could be written SHORTHAND like this, which jQuery will run after the ready even occurs.

$(function() {
    console.log("ready!");
});

NOT TO BE CONFUSED with BELOW (which is not meant to be DOM ready):

DO NOT use an IIFE like this that is self executing:

 Example:

(function() {
   // Your page initialization code here  - WRONG
   // The DOM will be available here   - WRONG
})();

This IIFE will NOT wait for your DOM to load. (I'm even talking about latest version of Chrome browser!)

Tom Stickel
  • 16,699
  • 6
  • 102
  • 108
  • 2
    If the latter is in a script tag at the very bottom of your webpage then it will occur after all the dom elements above it have been loaded. – csga5000 Nov 14 '15 at 06:48
  • 4
    TRUE , but OP question was "pure JavaScript equivalent to jQuery's $.ready() how to call a function when the page/dom is ready for it" – Tom Stickel Nov 15 '15 at 02:23
  • 7
    For me this should be the accepted answer. What a fabulously simple solution and I agree on the IIFE not being a correct solution. You sometimes don't have control over when you can inject your script which makes the prerequisite requirement of an IIFE being loaded last as useless if for you want to use jQuery functions before the library has been loaded into the page. – Jonathan Mar 03 '16 at 13:47
  • There is a big difference between jQuery and vanilla javascript. you can multiple times $(document).ready but not the addEventListener version because every time you call that an extra addEventListener is added to the list. – Herman Van Der Blom Apr 21 '21 at 15:01
180

I would like to mention some of the possible ways here together with a pure javascript trick which works across all browsers:

// with jQuery 
$(document).ready(function(){ /* ... */ });

// shorter jQuery version 
$(function(){ /* ... */ });

// without jQuery (doesn't work in older IEs)
document.addEventListener('DOMContentLoaded', function(){ 
    // your code goes here
}, false);

// and here's the trick (works everywhere)
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}
// use like
r(function(){
    alert('DOM Ready!');
});

The trick here, as explained by the original author, is that we are checking the document.readyState property. If it contains the string in (as in uninitialized and loading, the first two DOM ready states out of 5) we set a timeout and check again. Otherwise, we execute the passed function.

And here's the jsFiddle for the trick which works across all browsers.

Thanks to Tutorialzine for including this in their book.

Ram Patra
  • 14,608
  • 12
  • 60
  • 69
  • 42
    Very bad approach, using a timeout loop with an arbitrary 9ms interval, and using eval. Also checking for just /in/ doesn't make much sense. – Vitim.us Nov 22 '15 at 14:51
  • @Ramswaroop I just did http://stackoverflow.com/a/33885930/938822 – Vitim.us Nov 25 '15 at 02:34
  • 2
    @Vitim.us Well, supporting all browsers is what I was talking about. Please give a better solution which would work on all browsers. – Ram Patra Nov 25 '15 at 06:02
  • 1
    @Vitim.us I see that it works only in ie9+. this works in ie8 – Claudiu Creanga Feb 18 '16 at 20:01
  • @Claudiu I just don't agree that this is elegant, nor robust. If you could at least explain why 9ms? or why check for just 'in' and not 'Loading', what if the readyState property is undefined? you would have a infinity loop, no fallback, no nothing. Ok I can see this being used if everything else fails like last resort, but just this? it would be better fallback to the good old onload than use that in my opinion. – Vitim.us Feb 24 '16 at 10:58
  • @Vitim.us Please go through the code properly, it will never go into an infinite loop. It is only `in` because it is checking for the two initial states `uninitialized` and `loading`. Both of these have `in` in between them. See the 5 DOM ready states here: http://www.w3schools.com/jsref/prop_doc_readystate.asp – Ram Patra Feb 25 '16 at 10:45
  • 3
    @Vitim.us And `readyState` is never `undefined`, it has any one of the 5 values listed here: http://www.w3schools.com/jsref/prop_doc_readystate.asp – Ram Patra Feb 25 '16 at 14:56
  • 1
    I found out that neither DOMContentLoaded nor onreadystatechange are working in iOS webviews. So I used the trick but replaced the setTimeout by `setTimeout(function(){r(f)},9)` to just avoid the evaluated string. – Guillaume Gendre Feb 20 '17 at 16:03
  • 6
    @GuillaumeGendre, you can just do `setTimeout(r,9,f)` -- any parameters after the 2nd to setTimeout are passed to the first argument if it's a function. – cuniculus Aug 29 '17 at 20:23
  • 1
    Testing against `/in/` seems VERY hacky. Why not be explicit so there is no question or confused? `/(?:uninitialized|loading)/` – Marie Feb 25 '19 at 20:31
  • 2
    @Marie yes, you could that as well. – Ram Patra Aug 06 '19 at 09:55
80

Tested in IE9, and latest Firefox and Chrome and also supported in IE8.

document.onreadystatechange = function () {
  var state = document.readyState;
  if (state == 'interactive') {
      init();
  } else if (state == 'complete') {
      initOnCompleteLoad();
  }
}​;

Example: http://jsfiddle.net/electricvisions/Jacck/

UPDATE - reusable version

I have just developed the following. It's a rather simplistic equivalent to jQuery or Dom ready without backwards compatibility. It probably needs further refinement. Tested in latest versions of Chrome, Firefox and IE (10/11) and should work in older browsers as commented on. I'll update if I find any issues.

window.readyHandlers = [];
window.ready = function ready(handler) {
  window.readyHandlers.push(handler);
  handleState();
};

window.handleState = function handleState () {
  if (['interactive', 'complete'].indexOf(document.readyState) > -1) {
    while(window.readyHandlers.length > 0) {
      (window.readyHandlers.shift())();
    }
  }
};

document.onreadystatechange = window.handleState;

Usage:

ready(function () {
  // your code here
});

It's written to handle async loading of JS but you might want to sync load this script first unless you're minifying. I've found it useful in development.

Modern browsers also support async loading of scripts which further enhances the experience. Support for async means multiple scripts can be downloaded simultaneously all while still rendering the page. Just watch out when depending on other scripts loaded asynchronously or use a minifier or something like browserify to handle dependencies.

sam
  • 811
  • 2
  • 10
  • 25
PhilT
  • 3,507
  • 1
  • 31
  • 25
  • 1
    This also works in IE8. Won't work in lower versions or any IE in compatibility mode. Thanks. – monzonj Jan 06 '14 at 09:25
  • 1
    Do you mean `addEventListener` @rogerdpack? `attachEvent` is no longer supported in any browser but I get your point. I'll update. – PhilT Nov 01 '16 at 20:07
24

The good folks at HubSpot have a resource where you can find pure Javascript methodologies for achieving a lot of jQuery goodness - including ready

http://youmightnotneedjquery.com/#ready

function ready(fn) {
  if (document.readyState != 'loading'){
    fn();
  } else if (document.addEventListener) {
    document.addEventListener('DOMContentLoaded', fn);
  } else {
    document.attachEvent('onreadystatechange', function() {
      if (document.readyState != 'loading')
        fn();
    });
  }
}

example inline usage:

ready(function() { alert('hello'); });
rogerdpack
  • 50,731
  • 31
  • 212
  • 332
Lorcan O'Neill
  • 3,093
  • 1
  • 20
  • 22
  • 1
    I tested this on IE8 and it worked, though their current one on the link is different and looks to only support IE9, odd... – rogerdpack Oct 28 '16 at 17:39
  • @rogerdpack: there's a switcher at the top of the page that enables you to go back to IE8+ support. They're doing their bit for simplicity by defaulting to a less-messy but less-backwards-compatible version. – Tao Apr 10 '20 at 11:42
14

I'm not quite sure what you're asking, but maybe this can help:

window.onload = function(){
    // Code. . .

}

Or:

window.onload = main;

function main(){
    // Code. . .

}
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Zak The Hat
  • 207
  • 5
  • 14
9

Your method (placing script before the closing body tag)

<script>
   myFunction()
</script>
</body>
</html>

is a reliable way to support old and new browsers.

rogerdpack
  • 50,731
  • 31
  • 212
  • 332
Kernel James
  • 2,830
  • 18
  • 17
  • 1
    I said it is the "only reliable way", not the "only way". I said "only reliable way" because it was the only way to do it in Netscape 2.0. – Kernel James Dec 09 '16 at 05:58
  • 3
    According to your revision history, you actually said "is the _only_ (one of the) reliable(s) way to support old and new browsers.". Such language is easily misconstrued to be interpreted as the only way. I ain't taking back what I said, sorry. – Jonathan Dec 20 '16 at 20:16
6

Ready

function ready(fn){var d=document;(d.readyState=='loading')?d.addEventListener('DOMContentLoaded',fn):fn();}

Use like

ready(function(){
    //some code
});

For self invoking code

(function(fn){var d=document;(d.readyState=='loading')?d.addEventListener('DOMContentLoaded',fn):fn();})(function(){

    //Some Code here
    //DOM is avaliable
    //var h1s = document.querySelector("h1");

});

Support: IE9+

Vitim.us
  • 16,145
  • 12
  • 81
  • 96
  • 1
    This answer is redundant, it's already been mentioned here: http://stackoverflow.com/a/30757781/1385441 – Ram Patra Feb 26 '16 at 16:47
4

Here's a cleaned-up, non-eval-using version of Ram-swaroop's "works in all browsers" variety--works in all browsers!

function onReady(yourMethod) {
  var readyStateCheckInterval = setInterval(function() {
    if (document && document.readyState === 'complete') { // Or 'interactive'
      clearInterval(readyStateCheckInterval);
      yourMethod();
    }
  }, 10);
}
// use like
onReady(function() { alert('hello'); } );

It does wait an extra 10 ms to run, however, so here's a more complicated way that shouldn't:

function onReady(yourMethod) {
  if (document.readyState === 'complete') { // Or also compare to 'interactive'
    setTimeout(yourMethod, 1); // Schedule to run immediately
  }
  else {
    readyStateCheckInterval = setInterval(function() {
      if (document.readyState === 'complete') { // Or also compare to 'interactive'
        clearInterval(readyStateCheckInterval);
        yourMethod();
      }
    }, 10);
  }
}

// Use like
onReady(function() { alert('hello'); } );

// Or
onReady(functionName);

See also How to check if DOM is ready without a framework?.

rogerdpack
  • 50,731
  • 31
  • 212
  • 332
3

document.ondomcontentready=function(){} should do the trick, but it doesn't have full browser compatibility.

Seems like you should just use jQuery min

Nakilon
  • 32,203
  • 13
  • 95
  • 132
maxhud
  • 9,261
  • 13
  • 52
  • 99
  • Oh I couldn't agree with you more. I am a big fan of jQuery use it in almost anything I do javascript related. However I'm just trying to learn JavaScript from the core so I can be even better with applications I develop including what I would do with jQuery backing it. – chris Mar 28 '12 at 00:09
  • then you can use that or window.onload, but there isn't a good cross browser solution. Here is a reading on how jQuery does it if you're interested: http://docs.jquery.com/How_jQuery_Works#Launching_Code_on_Document_Ready – maxhud Mar 28 '12 at 00:13
  • It seems like you could get it to work in theory by adding onload events to images and to window which should include every element. – maxhud Mar 28 '12 at 00:15
  • @maxhud: Are you aware of any browser where `onload` actually doesn't work? Or where placing the script at the bottom of the page doesn't work? –  Mar 28 '12 at 00:28
  • Nope. They should both always work. – maxhud Mar 28 '12 at 00:42