Javascript - Come rilevare se il documento è stato caricato (IE 7 / Firefox 3)


163

Voglio chiamare una funzione dopo che un documento è stato caricato, ma il documento potrebbe non essere stato ancora caricato. Se è stato caricato, posso semplicemente chiamare la funzione. Se NON è stato caricato, posso collegare un listener di eventi. Non riesco ad aggiungere un listener di eventi dopo che onload è già stato attivato poiché non verrà chiamato. Quindi, come posso verificare se il documento è stato caricato? Ho provato il codice qui sotto ma non funziona del tutto. Qualche idea?

var body = document.getElementsByTagName('BODY')[0];
// CONDITION DOES NOT WORK
if (body && body.readyState == 'loaded') {
    DoStuffFunction();
} else {
    // CODE BELOW WORKS
    if (window.addEventListener) {  
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload', DoStuffFunction);
    }
}

5
"Voglio chiamare una funzione dopo che un documento è stato caricato, ma il documento potrebbe non essere ancora terminato." Questo non calcola.
Richard Simões,

7
Credo che significhi che non ha il controllo su quando il suo blocco di codice viene inizialmente eseguito, ma vuole assicurarsi che DoStuffFunction () non venga chiamato prima che il documento abbia terminato il caricamento.
Ben Blank,

Risposte:


257

Non è necessario per tutto il codice menzionato dai galambalaz. Il modo cross-browser per farlo in puro JavaScript è semplicemente testare document.readyState:

if (document.readyState === "complete") { init(); }

Questo è anche il modo in cui jQuery lo fa.

A seconda di dove viene caricato JavaScript, questo può essere fatto all'interno di un intervallo:

var readyStateCheckInterval = setInterval(function() {
    if (document.readyState === "complete") {
        clearInterval(readyStateCheckInterval);
        init();
    }
}, 10);

In effetti, document.readyStatepossono avere tre stati:

Restituisce "caricamento" durante il caricamento del documento, "interattivo" al termine dell'analisi ma continua a caricare risorse secondarie e "completamento" dopo il caricamento. - document.readyState su Mozilla Developer Network

Quindi, se hai solo bisogno che il DOM sia pronto, controlla document.readyState === "interactive". Se hai bisogno che l'intera pagina sia pronta, comprese le immagini, controlla document.readyState === "complete".


3
@costa, se document.readyState == "complete", significa che è stato caricato tutto, comprese le immagini.
laurent

Sto usando la combinazione di entrambi gli eventi e document.readyStateper assicurarmi che la funzione inizi dopo che il DOM è stato analizzato, o successivamente, a seconda di quando è stato chiamato. C'è un evento per interattivo readyState ?
Tomáš Zato - Ripristina Monica

3
Vorrei usare /loaded|complete/.test(document.readyState). Alcuni browser sono impostati document.readyStatesu "caricato" anziché "completo". Inoltre, document.readyState NON garantisce che i caratteri siano stati caricati, non c'è davvero un buon modo per testarlo senza un plugin.
Ryan Taylor,

2
Che dire document.onreadystatechange? Questo sembra più snello se i browser lo supportano. stackoverflow.com/questions/807878/...

2
Penso che sarebbe meglio controllare document.readyState !== "loading", per lo stato "DOM ready". Questo evita che readyStatesi verifichino problemi se viene spuntato tardi per qualche motivo (dopo lo stato "interattivo").
rnevius,

32

Non c'è bisogno di una biblioteca. jQuery ha usato questo script per un po ', a proposito.

http://dean.edwards.name/weblog/2006/06/again/

// Dean Edwards/Matthias Miller/John Resig

function init() {
  // quit if this function has already been called
  if (arguments.callee.done) return;

  // flag this function so we don't do the same thing twice
  arguments.callee.done = true;

  // kill the timer
  if (_timer) clearInterval(_timer);

  // do stuff
};

/* for Mozilla/Opera9 */
if (document.addEventListener) {
  document.addEventListener("DOMContentLoaded", init, false);
}

/* for Internet Explorer */
/*@cc_on @*/
/*@if (@_win32)
  document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
  var script = document.getElementById("__ie_onload");
  script.onreadystatechange = function() {
    if (this.readyState == "complete") {
      init(); // call the onload handler
    }
  };
/*@end @*/

/* for Safari */
if (/WebKit/i.test(navigator.userAgent)) { // sniff
  var _timer = setInterval(function() {
    if (/loaded|complete/.test(document.readyState)) {
      init(); // call the onload handler
    }
  }, 10);
}

/* for other browsers */
window.onload = init;

1
Esattamente quello che stavo cercando: jQuery.ready funziona senza la libreria jQuery. Grazie!
Stricjux,

3
Totalmente perso il punto della domanda. initnon funzionerà se questo codice che hai pubblicato è incluso dopo che la pagina è già stata caricata, che è il punto dell'OP: non può controllare quando il suo script è incluso. (nota che funzionerà solo la setIntervalfiliale)
Roatin Marth,

3
Questo appartiene a una biblioteca. Insieme a tutte le altre ruote, le persone comunemente reinventano.
n.

14

Probabilmente vuoi usare qualcosa come jQuery, che semplifica la programmazione JS.

Qualcosa di simile a:

$(document).ready(function(){
   // Your code here
});

Sembrerebbe fare quello che stai cercando.


2
E se vuole vedere come jQuery lo fa in modo portatile, la fonte di jQuery è lì per l'ispezione :-)
Thomas L Holaday,

7
E nel caso in cui non sia chiaro, se ready()viene chiamato dopo il caricamento del documento, la funzione passata viene eseguita immediatamente.
Ben Blank,

2
@Ben Blank: a meno che ovviamente non sia incluso jQuery dopo che il documento è stato caricato;)
Roatin Marth,

@Roatin Marth - In realtà, funziona anche bene. (Ho appena provato con jQuery 1.7.1 su FF8 e IE8.)
Ben Blank

35
-1: anche se la risposta ha senso, l'OP non ha mai menzionato jQuery. Usare l'intero progetto jQuery solo per preparare il documento è eccessivo.
marcgg,

8
if(document.readyState === 'complete') {
    DoStuffFunction();
} else {
    if (window.addEventListener) {  
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload', DoStuffFunction);
    }
}

Non sembra funzionare nell'ultima versione di Chrome non document.loadedè sempre definito
Aniket

questo era il 2010 :). Ora useròbody.readyState === 'loaded'
Jman

6

Se vuoi davvero che questo codice venga eseguito al caricamento , non su domready (cioè devi anche caricare le immagini), purtroppo la funzione ready non lo fa per te. In genere faccio semplicemente una cosa del genere:

Includi nel documento javascript (ovvero sempre chiamato prima dell'onload attivato):

var pageisloaded=0;
window.addEvent('load',function(){
 pageisloaded=1;
});

Quindi il tuo codice:

if (pageisloaded) {
 DoStuffFunction();
} else {
 window.addEvent('load',DoStuffFunction);
}

(O l'equivalente nel tuo quadro di preferenze.) Uso questo codice per eseguire il precaching di javascript e immagini per le pagine future. Dato che le cose che sto ricevendo non sono affatto utilizzate per questa pagina, non voglio che abbia la precedenza sul rapido download di immagini.

Potrebbe esserci un modo migliore, ma devo ancora trovarlo.


4

Mozila Firefox afferma che onreadystatechangeè un'alternativa a DOMContentLoaded.

// alternative to DOMContentLoaded
document.onreadystatechange = function () {
    if (document.readyState == "complete") {
        initApplication();
    }
}

Nel DOMContentLoadeddocumento di Mozila dice:

L'evento DOMContentLoaded viene generato quando il documento è stato completamente caricato e analizzato, senza attendere il completamento del caricamento di fogli di stile, immagini e sottoframe (l'evento di caricamento può essere utilizzato per rilevare una pagina completamente caricata).

Penso che l' loadevento dovrebbe essere usato per un documento completo + caricamento delle risorse.


3

Quello sopra con JQuery è il modo più semplice e più usato. Tuttavia puoi usare javascript puro ma prova a definire questo script in testa in modo che venga letto all'inizio. Quello che stai cercando è un window.onloadevento.

Di seguito è riportato un semplice script che ho creato per eseguire un contatore. Il contatore si arresta quindi dopo 10 iterazioni

window.onload=function()
{
    var counter = 0;
    var interval1 = setInterval(function()
    { 
        document.getElementById("div1").textContent=counter;
        counter++; 
        if(counter==10)
        {
            clearInterval(interval1);
        }
    },1000);

}

2

Prova questo:

var body = document.getElementsByTagName('BODY')[0];
// CONDITION DOES NOT WORK
if ((body && body.readyState == 'loaded') || (body &&  body.readyState == 'complete') ) {
    DoStuffFunction();
} else {
    // CODE BELOW WORKS
    if (window.addEventListener) {
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload',DoStuffFunction);
    }
}

1

Ho un'altra soluzione, la mia applicazione deve essere avviata quando viene creato un nuovo oggetto di MyApp, quindi sembra:

function MyApp(objId){
     this.init=function(){
        //.........
     }
     this.run=function(){
          if(!document || !document.body || !window[objId]){
              window.setTimeout(objId+".run();",100);
              return;
          }
          this.init();
     };
     this.run();
}
//and i am starting it 
var app=new MyApp('app');

funziona su tutti i browser, lo so.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.