Pure JavaScript equivalent of jQuery's $.ready() - how to call a function when the page/DOM is ready for it -
this question has answer here:
- $(document).ready equivalent without jquery 31 answers
okay, might silly question, though i'm sure there plenty of other people asking same question time time. me, want make 100% sure either way. jquery know wonderful
$('document').ready(function(){});
however, let's want run function written in standard javascript no library backing it, , want launch function page ready handle it. what's proper way approach this?
i know can do:
window.onload="myfunction()";
...or can use body
tag:
<body onload="myfunction()">
...or can try @ bottom of page after everything, end body
or html
tag like:
<script type="text/javascript"> myfunction(); </script>
what cross-browser(old/new)-compliant method of issuing 1 or more functions in manner jquery's $.ready()
?
the simplest thing in absence of framework cross-browser compatibility put call code @ end of body. faster execute onload
handler because waits dom ready, not images load. and, works in every browser.
<html> <head> </head> <body> html here <script> // self executing function here (function() { // page initialization code here // dom available here })(); </script> </body> </html>
if don't want way , need cross browser compatibility , don't want wait window.onload
, should go @ how framework jquery implements it's $(document).ready()
method. it's involved depending upon capabilities of browser.
to give little idea jquery (which work wherever script tag placed).
if supported, tries standard:
document.addeventlistener('domcontentloaded', fn, false);
with fallback to:
window.addeventlistener('load', fn, false )
or older versions of ie, uses:
document.attachevent("onreadystatechange", fn);
with fallback to:
window.attachevent("onload", fn);
and, there work-arounds in ie code path don't quite follow, looks has frames.
here full substitute jquery's .ready()
written in plain javascript:
(function(funcname, baseobj) { // public function name defaults window.docready // can pass in own object , own function name , used // if want put them in different namespace funcname = funcname || "docready"; baseobj = baseobj || window; var readylist = []; var readyfired = false; var readyeventhandlersinstalled = false; // call when document ready // function protects against being called more once function ready() { if (!readyfired) { // must set true before start calling callbacks readyfired = true; (var = 0; < readylist.length; i++) { // if callback here happens add new ready handlers, // docready() function see fired // , schedule callback run right after // event loop finishes handlers still execute // in order , no new ones added readylist // while processing list readylist[i].fn.call(window, readylist[i].ctx); } // allow closures held these functions free readylist = []; } } function readystatechange() { if ( document.readystate === "complete" ) { ready(); } } // 1 public interface // docready(fn, context); // context argument optional - if present, passed // argument callback baseobj[funcname] = function(callback, context) { if (typeof callback !== "function") { throw new typeerror("callback docready(fn) must function"); } // if ready has fired, schedule callback // fire asynchronously, right away if (readyfired) { settimeout(function() {callback(context);}, 1); return; } else { // add function , context list readylist.push({fn: callback, ctx: context}); } // if document ready go, schedule ready function run if (document.readystate === "complete") { settimeout(ready, 1); } else if (!readyeventhandlersinstalled) { // otherwise if don't have event handlers installed, install them if (document.addeventlistener) { // first choice domcontentloaded event document.addeventlistener("domcontentloaded", ready, false); // backup window load event window.addeventlistener("load", ready, false); } else { // must ie document.attachevent("onreadystatechange", readystatechange); window.attachevent("onload", ready); } readyeventhandlersinstalled = true; } } })("docready", window);
the latest version of code shared publicly on github @ https://github.com/jfriend00/docready
usage:
// pass function reference docready(fn); // use anonymous function docready(function() { // code here }); // pass function reference , context // context passed function first argument docready(fn, context); // use anonymous function context docready(function(context) { // code here can use context argument passed docready }, ctx);
this has been tested in:
ie6 , firefox 3.6 , chrome 14 , safari 5.1 , opera 11.6 , multiple ios devices multiple android devices
working implementation , test bed: http://jsfiddle.net/jfriend00/yfd3c/
here's summary of how works:
- create iife (immediately invoked function expression) can have non-public state variables.
- declare public function
docready(fn, context)
- when
docready(fn, context)
called, check if ready handler has fired. if so, schedule newly added callback fire right after thread of js finishessettimeout(fn, 1)
. - if ready handler has not fired, add new callback list of callbacks called later.
- check if document ready. if so, execute ready handlers.
- if haven't installed event listeners yet know when document becomes ready, install them now.
- if
document.addeventlistener
exists, install event handlers using.addeventlistener()
both"domcontentloaded"
,"load"
events. "load" backup event safety , should not needed. - if
document.addeventlistener
doesn't exist, install event handlers using.attachevent()
"onreadystatechange"
,"onload"
events. - in
onreadystatechange
event, check see ifdocument.readystate === "complete"
, if so, call function fire ready handlers. - in other event handlers, call function fire ready handlers.
- in function call ready handlers, check state variable see if we've fired. if have, nothing. if haven't yet been called, loop through array of ready functions , call each 1 in order added. set flag indicate these have been called never executed more once.
- clear function array closures might using can freed.
handlers registered docready()
guaranteed fired in order registered.
if call docready(fn)
after document ready, callback scheduled execute current thread of execution completes using settimeout(fn, 1)
. allows calling code assume async callbacks called later, if later current thread of js finishes , preserves calling order.