85 votes

Comment vérifier si DOM est prêt sans framework ?

La question ressemble à des millions d'autres ici et sur le web - Comment vérifier si le DOM a été chargé en Javascript ? Mais voici le hic :

  • Sans utiliser un framework comme jQuery etc ;
  • Sans savoir si votre script a été chargé via un fichier statiquement placé <script> ou via un autre Javascript, bien plus tard, après que le DOM ait déjà été chargé.

Peut-on le faire de manière plus ou moins fiable et en assurant la compatibilité entre les navigateurs ?

Ajouté : Laissez-moi clarifier : j'écris un fichier .JS autonome qui peut être inclus dans des pages Web arbitraires. Je veux exécuter du code APRÈS le DOM a été chargé. Mais je ne sais pas COMMENT mon script sera inclus. Cela pourrait être en plaçant un <script> (dans ce cas, la traditionnelle balise onload ou les solutions de préparation du DOM fonctionneront) ; ou il pourrait être chargé via AJAX ou d'autres moyens, bien plus tard après que le DOM est déjà chargé (donc les solutions mentionnées précédemment ne fonctionneront jamais).

3 votes

El document.readyState peut être utilisée, bien que je ne sois pas sûr de la compatibilité avec les navigateurs...

1 votes

Pas très bon, j'en ai peur. :(

5 votes

100voto

Digital Plane Points 11741

El document.readyState peut être utilisée pour vérifier si le document est prêt. De MDN :

Valeurs

Le readyState d'un document peut être l'un des suivants :

  • chargement - Le document est toujours en cours de chargement.
  • interactive - Le chargement du document est terminé et le document a été analysé mais les sous-ressources telles que les images, les feuilles de style et les cadres sont toujours en cours de chargement.
  • complet - Le chargement du document et de toutes les sous-ressources est terminé. L'état indique que le charge est sur le point de se déclencher.

Exemple de code :

if(document.readyState === "complete") {
    // Fully loaded!
}
else if(document.readyState === "interactive") {
    // DOM ready! Images, frames, and other subresources are still downloading.
}
else {
    // Loading still in progress.
    // To wait for it to complete, add "DOMContentLoaded" or "load" listeners.

    window.addEventListener("DOMContentLoaded", () => {
        // DOM ready! Images, frames, and other subresources are still downloading.
    });

    window.addEventListener("load", () => {
        // Fully loaded!
    });
}

4 votes

Gardez à l'esprit que addEventListener() a été ajouté avec IE9, qui n'est pas disponible pour Windows XP

1 votes

Bien sûr. Cela va de pair avec les autres solutions pour une simulation d'événement DOMReady.

7 votes

D'une part, cela ne fonctionne pas avec tous les navigateurs. D'autre part, cela attend également le chargement des images. Cela agit comme window.onload.

10voto

jfriend00 Points 152127

Firefox, Opera et les navigateurs basés sur Webkit ont un événement au niveau du document. DOMContentLoaded que vous pouvez écouter avec document.addEventListener("DOMContentLoaded", fn, false) .

C'est plus compliqué dans IE. Ce que fait jQuery dans IE, c'est regarder onreadystatechange sur l'objet document pour un état de lecture particulier avec une sauvegarde de l'événement document.onload. document.onload se déclenche plus tard que le DOM est prêt (seulement quand toutes les images ont fini de se charger) donc il est seulement utilisé comme un filet de sécurité au cas où les événements précédents ne fonctionnent pas pour une raison quelconque.

Si vous passez un peu de temps sur Google, vous trouverez du code pour faire cela. Je pense que le code le plus éprouvé pour ce faire se trouve dans les grands frameworks comme jQuery et YUI. Ainsi, même si je n'utilise pas ce framework, je cherche des techniques dans son code source.

Voici la partie principale de la source de jQuery 1.6.2 pour 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();
        }
    }
},

1 votes

Encore une fois, cela ne fonctionnera pas si j'attache mon gestionnaire d'événement après que le DOM ait déjà été chargé.

4 votes

Regardez dans la source de jQuery que j'ai incluse. C'est pourquoi ils ont la ligne qui commence par if ( document.readyState === "complete" ) { afin qu'ils gèrent le cas où le document est déjà prêt. Si vous créez votre propre mini-framework, vous devrez intégrer vous-même ce type de fonctionnalité.

9voto

Christoph Points 64389

Si vous vous appuyez sur document.readyState est ok, une solution rapide avec sondage :

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

0 votes

document.readyState est la réponse à mes problèmes. Comme je l'ai dit à plusieurs reprises, le fait de s'attacher à un événement de type "DOMReady" n'est pas un problème. Le problème est lorsque le readyState==complete, donc l'événement DOMReady ne sera jamais déclenché.

0 votes

@Vilx- : mon point de vue est que si vous comptez sur document.readyState (c'est-à-dire que vous ne voulez pas prendre en charge les anciens navigateurs non IE), il n'est pas nécessaire d'utiliser un code spécifique au navigateur ( DOMContentLoaded vs. onload vs. onreadystatechange , addEventListener vs attachEvent ) - la solution ci-dessus fonctionne partout

0 votes

Pour autant que je sache, le seul navigateur que je ne prendrai pas en charge est FireFox en dessous de la version 3.6. Et, pour être honnête, c'est un cas limite (la plupart du temps, le script sera inclus de manière traditionnelle), donc si je le rate pour une combinaison très rare, ce ne sera pas si grave :P

9voto

John Foley Points 179

Cette méthode fonctionne pour tous les navigateurs et est courte et concise :

var execute = function () {
  alert("executing code");  
};

if ( !!(window.addEventListener) )
  window.addEventListener("DOMContentLoaded", execute)
else // MSIE
  window.attachEvent("onload", execute)

3voto

John Hartsock Points 36565

Voici un moyen en exécutant script en bas de la page. De plus en utilisant le window.onload vous pouvez attendre que toutes les images/script soient chargés. Ou vous pouvez simplement placer du code en bas de la page sans attendre le chargement des images.

<html>
<head>
</head>
<body>
</body>
<script language="text/javascript">
  window.onload = (function (oldOnLoad) {
    return function () {
      if (oldOnLoad) { 
        olOnLoad();  //fire old Onload event that was attached if any.
      }
      // your code to run after images/scripts are loaded
    }
  })(window.onload);

  // your code to run after DOM is loaded
</script>
</html>

Edited : for Vilx's Comment

De nombreuses liaisons de type onload, dont voici un exemple. http://jsfiddle.net/uTF2N/3/

0 votes

+1. Vous pourriez ajouter une explication sur la façon dont cela fonctionne pour les personnes qui font des recherches ultérieures et trouvent ceci sans avoir beaucoup d'expérience, cependant.

1 votes

Je pense que vous violez : "Sans savoir si votre script a été chargé via une balise <script placée statiquement ou via un autre Javascript beaucoup plus tard après que le DOM ait déjà été chargé".

0 votes

Je suis désolé, je n'avais pas dit que je parlais d'un script autonome. J'ai clarifié.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X