Javascript: cómo detectar si el documento se ha cargado (IE 7 / Firefox 3)

163

Quiero llamar a una función después de que se cargue un documento, pero el documento puede o no haber terminado de cargarse todavía. Si se cargó, entonces puedo llamar a la función. Si NO se cargó, entonces puedo adjuntar un detector de eventos. No puedo agregar un escucha de eventos después de que ya se haya activado la carga, ya que no se llamará. Entonces, ¿cómo puedo verificar si el documento se ha cargado? Intenté el siguiente código pero no funciona del todo. ¿Algunas ideas?

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);
    }
}
Marcos
fuente
55
"Quiero llamar a una función después de cargar un documento, pero el documento puede o no haber terminado de cargarse aún". Esto no computa.
Richard Simões
77
Creo que quiere decir que no tiene control sobre cuándo se ejecuta inicialmente su bloque de código, pero quiere asegurarse de que DoStuffFunction () no se llame antes de que el documento haya terminado de cargarse.
Ben Blank

Respuestas:

257

No hay necesidad de todo el código mencionado por galambalazs. La forma entre navegadores de hacerlo en JavaScript puro es simplemente probar document.readyState:

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

Así es también como lo hace jQuery.

Dependiendo de dónde se cargue el JavaScript, esto se puede hacer dentro de un intervalo:

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

De hecho, document.readyStatepuede tener tres estados:

Devuelve "cargando" mientras se carga el documento, "interactivo" una vez que finaliza el análisis pero aún cargando recursos secundarios y "completo" una vez que se ha cargado. - document.readyState en la red de desarrolladores de Mozilla

Entonces, si solo necesita que el DOM esté listo, verifique document.readyState === "interactive". Si necesita que toda la página esté lista, incluidas las imágenes, consulte document.readyState === "complete".

Laurent
fuente
3
@costa, si document.readyState == "complete", significa que todo, incluidas las imágenes, se han cargado.
Laurent
Estoy usando la combinación de ambos eventos y document.readyStatepara asegurarme de que la función se inicie después de que se haya analizado DOM, o más tarde, dependiendo de cuándo se haya llamado. ¿Hay algún evento interactivo readyState ?
Tomáš Zato - Restablece a Mónica el
3
Que haría uso /loaded|complete/.test(document.readyState). Algunos navegadores están configurados document.readyStatecomo "cargados" en lugar de "completos". Además, document.readyState NO garantiza que se hayan cargado las fuentes, no hay una buena manera de probarlo sin un complemento.
Ryan Taylor
2
¿Qué hay de document.onreadystatechange? Esto parece más simplificado si los navegadores lo admiten. stackoverflow.com/questions/807878/…
2
Creo que sería mejor verificar document.readyState !== "loading"el estado "DOM listo". Esto evita que surjan problemas si readyStatese verifica tarde por algún motivo (después del estado "interactivo").
rnevius
32

No hay necesidad de una biblioteca. jQuery usó este script por un tiempo, por cierto.

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;
gblazex
fuente
1
Exactamente lo que estaba buscando: la función jQuery.ready sin la biblioteca jQuery. Gracias!
stricjux
3
Perdí totalmente el punto de la pregunta. initno se ejecutará si este código que publicó se incluye después de que la página ya se haya cargado, que es el punto del OP: él / ella no puede controlar cuándo se incluye su script. (tenga en cuenta que solo la setIntervalsucursal funcionará)
Roatin Marth
3
Esto pertenece a una biblioteca. Junto con todas las otras ruedas, la gente suele reinventar.
b01
14

Probablemente quiera usar algo como jQuery, que facilita la programación de JS.

Algo como:

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

Parece que haces lo que buscas.

dan
fuente
2
Y si quiere ver cómo jQuery lo hace de forma portátil, la fuente de jQuery está allí para la inspección :-)
Thomas L Holaday
77
Y en caso de que no esté claro, si ready()se llama después de la carga del documento, la función aprobada se ejecuta inmediatamente.
Ben Blank
2
@Ben Blank: a menos que, por supuesto, jQuery se incluya después de que se haya cargado el documento;)
Roatin Marth
@Roatin Marth: en realidad, eso también funciona bien. (Solo lo probé con jQuery 1.7.1 en FF8 e IE8.)
Ben Blank
35
-1: incluso si la respuesta tiene sentido, el OP nunca mencionó jQuery. Usar todo el proyecto jQuery solo para preparar el documento es exagerado.
marcgg
8
if(document.readyState === 'complete') {
    DoStuffFunction();
} else {
    if (window.addEventListener) {  
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload', DoStuffFunction);
    }
}
Jman
fuente
No parece funcionar en el último Chrome document.loadedsiempre está indefinido
Aniket
esto fue 2010 :). Ahora lo body.readyState === 'loaded'
usaré
6

Si realmente desea que este código se ejecute en la carga , no en domready (es decir, también necesita que se carguen las imágenes), desafortunadamente la función de listo no lo hace por usted. Generalmente solo hago algo como esto:

Incluya en el documento javascript (es decir, siempre se llama antes de que se active la carga):

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

Entonces tu código:

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

(O el equivalente en su marco de preferencia). Utilizo este código para realizar precaching de JavaScript e imágenes para futuras páginas. Como las cosas que recibo no se usan para esta página, no quiero que tenga prioridad sobre la descarga rápida de imágenes.

Puede haber una mejor manera, pero aún no la he encontrado.

Estiramiento Nathan
fuente
4

Mozila Firefox dice que onreadystatechangees una alternativa a DOMContentLoaded.

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

En DOMContentLoadedel documento de Mozila dice:

El evento DOMContentLoaded se desencadena cuando el documento se ha cargado y analizado por completo, sin esperar a que las hojas de estilo, las imágenes y los subtramas terminen de cargarse (el evento de carga se puede utilizar para detectar una página completamente cargada).

Creo que el loadevento debería usarse para un documento completo + carga de recursos.

Mostafa Talebi
fuente
3

El anterior con JQuery es la forma más fácil y más utilizada. Sin embargo, puede usar javascript puro, pero intente definir este script en la cabeza para que se lea al principio. Lo que buscas eswindow.onload evento.

A continuación se muestra un script simple que creé para ejecutar un contador. El contador se detiene después de 10 iteraciones.

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

}
Talha
fuente
2

Prueba esto:

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);
    }
}
smit
fuente
1

Tengo otra solución, mi aplicación debe iniciarse cuando se crea un nuevo objeto de MyApp, por lo que se ve así:

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');

está funcionando en todos los navegadores, eso lo sé.

vitus
fuente