Come verificare se DOM è pronto senza un framework?

La domanda è così simile a un milione di altri qui e sul web – Come verificare se DOM è stato caricato in Javascript? Ma ecco il trucco:

  • Senza usare un framework come jQuery etc;
  • Senza sapere se il tuo script è stato caricato tramite un tag posizionato staticamente o tramite qualche altro Javascript molto più tardi dopo che il DOM è già stato caricato.

Questo può essere fatto più o meno in modo affidabile e con compatibilità cross-browser?

Aggiunto: Vorrei chiarire: Sto scrivendo un file .JS autonomo che può essere incluso in pagine web arbitrarie. Voglio eseguire il codice dopo che il DOM è stato caricato. Ma non so come verrà inclusa la mia sceneggiatura. Potrebbe essere posizionando un tag (nel qual caso funzioneranno le tradizionali soluzioni on- onload o DOM-readiness); oppure potrebbe essere caricato tramite AJAX o altri mezzi, molto più tardi dopo che il DOM è già caricato (quindi le soluzioni menzionate in precedenza non verranno mai triggerste).

La proprietà document.readyState può essere utilizzata per verificare se il documento è pronto:

 if(document.readyState === "complete") { //Already loaded! } else { //Add onload or DOMContentLoaded event listeners here: for example, window.addEventListener("onload", function () {/* your code here */}, false); //or //document.addEventListener("DOMContentLoaded", function () {/* code */}, false); } 

I browser Firefox, Opera e Webkit hanno un evento a livello di documento DOMContentLoaded che puoi ascoltare con document.addEventListener("DOMContentLoaded", fn, false) .

È più complicato in IE. Quello che jQuery fa in IE è guardare onreadystatechange del documento per un readystate particolare con un backup dell’evento document.onload. document.onload scatta dopo che il DOM è pronto (solo quando tutte le immagini hanno terminato il caricamento), quindi viene utilizzato solo come protezione nel caso in cui gli eventi precedenti non funzionino per qualche motivo.

Se passi un po ‘di tempo su Google, troverai il codice per farlo. Immagino che il codice più controllato per farlo sia nei framework di grandi dimensioni come jQuery e YUI, quindi, anche se non sto usando quel framework, cerco nel loro codice sorgente le tecniche.

Ecco la parte principale del sorgente jQuery 1.6.2 per document.ready() :

 bindReady: function() { if ( readyList ) { return; } readyList = jQuery._Deferred(); // Catch cases where $(document).ready() is called after the // browser event has already occurred. if ( document.readyState === "complete" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready return setTimeout( jQuery.ready, 1 ); } // Mozilla, Opera and webkit nightlies currently support this event if ( document.addEventListener ) { // Use the handy event callback document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", jQuery.ready, false ); // If IE event model is used } else if ( document.attachEvent ) { // ensure firing before onload, // maybe late but safe also for iframes document.attachEvent( "onreadystatechange", DOMContentLoaded ); // A fallback to window.onload, that will always work window.attachEvent( "onload", jQuery.ready ); // If IE and not a frame // continually check to see if the document is ready var toplevel = false; try { toplevel = window.frameElement == null; } catch(e) {} if ( document.documentElement.doScroll && toplevel ) { doScrollCheck(); } } }, 

Questo funziona per tutti i browser ed è breve e conciso:

 var execute = function () { alert("executing code"); }; if ( !!(window.addEventListener) ) window.addEventListener("DOMContentLoaded", execute) else // MSIE window.attachEvent("onload", execute) 

Se fare affidamento su document.readyState è ok, soluzione rapida e sporca con il polling:

 (function() { var state = document.readyState; if(state === 'interactive' || state === 'complete') { // do stuff } else setTimeout(arguments.callee, 100); })(); 

L’evento DOMContentLoaded viene DOMContentLoaded quando il documento HTML iniziale è stato caricato e analizzato completamente, senza attendere che i fogli di stile, le immagini e i sottoframe terminino il caricamento. La buona cosa è chrome, firefox, IE9, opera e safari lo supporta allo stesso modo

 document.addEventListener("DOMContentLoaded", function(event) { console.log("DOM fully loaded and parsed"); } 

NOTA: Internet Explorer 8 supporta l’evento readystatechange, che può essere utilizzato per rilevare quando il DOM è pronto.

Ecco un modo eseguendo script in fondo alla pagina. Inoltre, utilizzando window.onload è ansible attendere il caricamento di tutte le immagini / script. Oppure potresti semplicemente inserire il codice in fondo in attesa di caricare le immagini.

        

Modificato: per il commento di Vilx

Molti collegamenti onload qui sono un esempio http://jsfiddle.net/uTF2N/3/