Javascript - Comment détecter si le document est chargé (IE 7 / Firefox 3)

163

Je souhaite appeler une fonction après le chargement d'un document, mais le chargement du document peut ou non encore être terminé. S'il s'est chargé, je peux simplement appeler la fonction. S'il ne s'est pas chargé, je peux attacher un écouteur d'événements. Je ne peux pas ajouter d'écouteur d'événement après que onload a déjà été déclenché car il ne sera pas appelé. Alors, comment puis-je vérifier si le document est chargé? J'ai essayé le code ci-dessous mais cela ne fonctionne pas entièrement. Des idées?

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
la source
5
"Je souhaite appeler une fonction après le chargement d'un document, mais le chargement du document peut ou non encore être terminé." Cela ne calcule pas.
Richard Simões
7
Je crois qu'il veut dire qu'il n'a pas le contrôle sur le moment où son bloc de code est initialement exécuté, mais veut s'assurer que DoStuffFunction () n'est pas appelé avant que le document ait fini de charger.
Ben Blank

Réponses:

257

Il n'y a pas besoin de tout le code mentionné par les galambalazs. La manière multi-navigateurs de le faire en JavaScript pur est simplement de tester document.readyState:

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

C'est également ainsi que jQuery le fait.

Selon l'endroit où le JavaScript est chargé, cela peut être fait dans un intervalle:

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

En fait, document.readyStatepeut avoir trois états:

Renvoie «chargement» pendant le chargement du document, «interactif» une fois qu'il a terminé l'analyse mais toujours en train de charger les sous-ressources, et «terminé» une fois qu'il est chargé. - document.readyState chez Mozilla Developer Network

Donc, si vous n'avez besoin que du DOM pour être prêt, vérifiez document.readyState === "interactive". Si vous avez besoin que toute la page soit prête, y compris les images, vérifiez document.readyState === "complete".

Laurent
la source
3
@costa, si document.readyState == "complete"cela signifie que tout, y compris les images, a été chargé.
laurent
J'utilise une combinaison des deux événements et document.readyStatepour m'assurer que la fonction démarre après l'analyse du DOM, ou plus tard, selon le moment où elle a été appelée. Y a-t-il un événement interactif readyState ?
Tomáš Zato - Réintégrer Monica
3
J'utiliserais /loaded|complete/.test(document.readyState). Certains navigateurs sont définis document.readyStatesur "chargé" au lieu de "complet". De plus, document.readyState ne garantit PAS que les polices ont été chargées, il n'y a pas vraiment de bon moyen de tester cela sans plugin.
Ryan Taylor
2
Et quoi document.onreadystatechange? Cela semble plus simple si les navigateurs le prennent en charge. stackoverflow.com/questions/807878/…
2
Je pense qu'il serait préférable de vérifier document.readyState !== "loading"l'état "DOM ready". Cela évite que des problèmes surgissent si le readyStateest vérifié tard pour une raison quelconque (après l'état "interactif").
rnevius
32

Pas besoin de bibliothèque. jQuery a utilisé ce script pendant un certain temps, btw.

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
la source
1
Exactement ce que je cherchais - fonction jQuery.ready sans la bibliothèque jQuery. Merci!
stricjux le
3
Totalement manqué le point de la question. initne fonctionnera pas si ce code que vous avez posté est inclus après le chargement de la page, ce qui est le point de l'OP: il / elle ne peut pas contrôler quand son script est inclus. (notez que seule la setIntervalbranche fonctionnera)
Roatin Marth
3
Cela appartient à une bibliothèque. Avec toutes les autres roues, les gens réinventent couramment.
b01
14

Vous voudrez probablement utiliser quelque chose comme jQuery, qui facilite la programmation JS.

Quelque chose comme:

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

Semblerait faire ce que vous recherchez.

dan
la source
2
Et s'il veut voir comment jQuery le fait de manière portable, la source de jQuery est là pour l'inspection :-)
Thomas L Holaday
7
Et si ce n'est pas clair, si ready()est appelé après le chargement du document, la fonction passée est exécutée immédiatement.
Ben Blank du
2
@Ben Blank: à moins bien sûr que jQuery lui-même ne soit inclus après le chargement du document;)
Roatin Marth
@Roatin Marth - En fait, cela fonctionne bien aussi. (Je viens de l'essayer avec jQuery 1.7.1 sur FF8 et IE8.)
Ben Blank
35
-1: même si la réponse a du sens, l'OP n'a jamais mentionné jQuery. Utiliser tout le projet jQuery juste pour préparer le document est bien excessif.
marcgg
8
if(document.readyState === 'complete') {
    DoStuffFunction();
} else {
    if (window.addEventListener) {  
        window.addEventListener('load', DoStuffFunction, false);
    } else {
        window.attachEvent('onload', DoStuffFunction);
    }
}
Jman
la source
Ne semble pas fonctionner dans la dernière version de Chrome document.loadedest toujours indéfini
Aniket
c'était 2010 :). Maintenant, je vais utiliserbody.readyState === 'loaded'
Jman
6

Si vous voulez réellement que ce code s'exécute au chargement , pas chez domready (c'est-à-dire que vous avez également besoin des images à charger), alors malheureusement, la fonction ready ne le fait pas pour vous. Je fais généralement quelque chose comme ça:

Inclure dans le document javascript (c'est-à-dire toujours appelé avant le lancement du chargement):

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

Puis votre code:

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

(Ou l'équivalent dans votre cadre de préférence.) J'utilise ce code pour faire du précaching de javascript et d'images pour les pages futures. Étant donné que le contenu que je reçois n'est pas du tout utilisé pour cette page, je ne veux pas qu'il prenne le pas sur le téléchargement rapide des images.

Il y a peut-être un meilleur moyen, mais je ne l'ai pas encore trouvé.

Nathan Stretch
la source
4

Mozila Firefox dit que onreadystatechangec'est une alternative à DOMContentLoaded.

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

Dans DOMContentLoadedle doc de Mozila dit:

L'événement DOMContentLoaded est déclenché lorsque le document a été complètement chargé et analysé, sans attendre la fin du chargement des feuilles de style, des images et des sous-cadres (l'événement load peut être utilisé pour détecter une page entièrement chargée).

Je pense que l' loadévénement devrait être utilisé pour un document complet + le chargement des ressources.

Mostafa Talebi
la source
3

Celui ci-dessus avec JQuery est le moyen le plus simple et le plus utilisé. Cependant, vous pouvez utiliser du javascript pur mais essayez de définir ce script dans la tête pour qu'il soit lu au début. Ce que vous recherchez estwindow.onload événement.

Vous trouverez ci-dessous un script simple que j'ai créé pour exécuter un compteur. Le compteur s'arrête ensuite après 10 itérations

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

}
Talha
la source
2

Essaye ça:

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);
    }
}
frapper
la source
1

J'ai une autre solution, mon application doit être démarrée quand un nouvel objet de MyApp est créé, il ressemble donc à:

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

cela fonctionne sur tous les navigateurs, que je connais.

vitus
la source