$ (document) .équivalent déjà sans jQuery

2017

J'ai un script qui utilise $(document).ready, mais il n'utilise rien d'autre de jQuery. Je voudrais l'éclaircir en supprimant la dépendance jQuery.

Comment puis-je implémenter ma propre $(document).readyfonctionnalité sans utiliser jQuery? Je sais que l'utilisation window.onloadne sera pas la même chose, car les window.onloadincendies après le chargement de toutes les images, cadres, etc.

FlySwat
la source
296
... et certainement pas la même fonctionnalité.
Joel Mueller
40
Comme l'indique cette réponse , si tout ce que vous voulez de jQuery est $(document).ready, vous pouvez résoudre ce problème facilement en exécutant votre code tout en bas de la page plutôt qu'en haut. HTML5Boilerplate utilise cette approche exacte.
Blazemonger
3
Pourquoi ne pas simplement utiliser le DOMContentLoaded? C'est IE9 + caniuse.com/domcontentloaded developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded
Brock
J'ai enfin passé mon appel de document et cela résout mon problème. Lorsque la fonction est appelée, tout est chargé.
IgniteCoders

Réponses:

1440

Il existe un remplacement basé sur des normes, DOMContentLoadedpris en charge par plus de 98% des navigateurs , mais pas IE8:

document.addEventListener("DOMContentLoaded", function(event) { 
  //do work
});

La fonction native de jQuery est beaucoup plus compliquée que simplement window.onload, comme illustré ci-dessous.

function bindReady(){
    if ( readyBound ) return;
    readyBound = true;

    // Mozilla, Opera and webkit nightlies currently support this event
    if ( document.addEventListener ) {
        // Use the handy event callback
        document.addEventListener( "DOMContentLoaded", function(){
            document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
            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", function(){
            if ( document.readyState === "complete" ) {
                document.detachEvent( "onreadystatechange", arguments.callee );
                jQuery.ready();
            }
        });

        // If IE and not an iframe
        // continually check to see if the document is ready
        if ( document.documentElement.doScroll && window == window.top ) (function(){
            if ( jQuery.isReady ) return;

            try {
                // If IE is used, use the trick by Diego Perini
                // http://javascript.nwbox.com/IEContentLoaded/
                document.documentElement.doScroll("left");
            } catch( error ) {
                setTimeout( arguments.callee, 0 );
                return;
            }

            // and execute any waiting functions
            jQuery.ready();
        })();
    }

    // A fallback to window.onload, that will always work
    jQuery.event.add( window, "load", jQuery.ready );
}
Chad Grant
la source
19
Une implémentation javascript simple et efficace ici si quelqu'un veut du code, il peut simplement le déposer: stackoverflow.com/questions/9899372/…
jfriend00
4
Le code jQuery DOM ready semble être simplifié: github.com/jquery/jquery/blob/master/src/core/ready.js
Jose Nobile
2
@JoseNobile car ils ont abandonné la prise en charge des anciens navigateurs
huysentruitw
16
Je pense que nous sommes tous prêts à passer d'IE8 ...;). Merci pour le lien, @JoseNobile.
Con Antonakos
13
DOMContentLoaded ne fonctionnera pas si le script est chargé par la suite. Le document JQuery prêt s'exécute toujours.
Jared Insel
343

Éditer:

Voici un remplacement viable pour jQuery ready

function ready(callback){
    // in case the document is already rendered
    if (document.readyState!='loading') callback();
    // modern browsers
    else if (document.addEventListener) document.addEventListener('DOMContentLoaded', callback);
    // IE <= 8
    else document.attachEvent('onreadystatechange', function(){
        if (document.readyState=='complete') callback();
    });
}

ready(function(){
    // do something
});

Tiré de https://plainjs.com/javascript/events/running-code-when-the-document-is-ready-15/

Une autre bonne fonction domReady ici tirée de https://stackoverflow.com/a/9899701/175071


Comme la réponse acceptée était très loin d'être complète, j'ai assemblé une fonction "prête" comme jQuery.ready()basée sur la source jQuery 1.6.2:

var ready = (function(){

    var readyList,
        DOMContentLoaded,
        class2type = {};
        class2type["[object Boolean]"] = "boolean";
        class2type["[object Number]"] = "number";
        class2type["[object String]"] = "string";
        class2type["[object Function]"] = "function";
        class2type["[object Array]"] = "array";
        class2type["[object Date]"] = "date";
        class2type["[object RegExp]"] = "regexp";
        class2type["[object Object]"] = "object";

    var ReadyObj = {
        // Is the DOM ready to be used? Set to true once it occurs.
        isReady: false,
        // A counter to track how many items to wait for before
        // the ready event fires. See #6781
        readyWait: 1,
        // Hold (or release) the ready event
        holdReady: function( hold ) {
            if ( hold ) {
                ReadyObj.readyWait++;
            } else {
                ReadyObj.ready( true );
            }
        },
        // Handle when the DOM is ready
        ready: function( wait ) {
            // Either a released hold or an DOMready/load event and not yet ready
            if ( (wait === true && !--ReadyObj.readyWait) || (wait !== true && !ReadyObj.isReady) ) {
                // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
                if ( !document.body ) {
                    return setTimeout( ReadyObj.ready, 1 );
                }

                // Remember that the DOM is ready
                ReadyObj.isReady = true;
                // If a normal DOM Ready event fired, decrement, and wait if need be
                if ( wait !== true && --ReadyObj.readyWait > 0 ) {
                    return;
                }
                // If there are functions bound, to execute
                readyList.resolveWith( document, [ ReadyObj ] );

                // Trigger any bound ready events
                //if ( ReadyObj.fn.trigger ) {
                //    ReadyObj( document ).trigger( "ready" ).unbind( "ready" );
                //}
            }
        },
        bindReady: function() {
            if ( readyList ) {
                return;
            }
            readyList = ReadyObj._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( ReadyObj.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", ReadyObj.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", ReadyObj.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();
                }
            }
        },
        _Deferred: function() {
            var // callbacks list
                callbacks = [],
                // stored [ context , args ]
                fired,
                // to avoid firing when already doing so
                firing,
                // flag to know if the deferred has been cancelled
                cancelled,
                // the deferred itself
                deferred  = {

                    // done( f1, f2, ...)
                    done: function() {
                        if ( !cancelled ) {
                            var args = arguments,
                                i,
                                length,
                                elem,
                                type,
                                _fired;
                            if ( fired ) {
                                _fired = fired;
                                fired = 0;
                            }
                            for ( i = 0, length = args.length; i < length; i++ ) {
                                elem = args[ i ];
                                type = ReadyObj.type( elem );
                                if ( type === "array" ) {
                                    deferred.done.apply( deferred, elem );
                                } else if ( type === "function" ) {
                                    callbacks.push( elem );
                                }
                            }
                            if ( _fired ) {
                                deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
                            }
                        }
                        return this;
                    },

                    // resolve with given context and args
                    resolveWith: function( context, args ) {
                        if ( !cancelled && !fired && !firing ) {
                            // make sure args are available (#8421)
                            args = args || [];
                            firing = 1;
                            try {
                                while( callbacks[ 0 ] ) {
                                    callbacks.shift().apply( context, args );//shifts a callback, and applies it to document
                                }
                            }
                            finally {
                                fired = [ context, args ];
                                firing = 0;
                            }
                        }
                        return this;
                    },

                    // resolve with this as context and given arguments
                    resolve: function() {
                        deferred.resolveWith( this, arguments );
                        return this;
                    },

                    // Has this deferred been resolved?
                    isResolved: function() {
                        return !!( firing || fired );
                    },

                    // Cancel
                    cancel: function() {
                        cancelled = 1;
                        callbacks = [];
                        return this;
                    }
                };

            return deferred;
        },
        type: function( obj ) {
            return obj == null ?
                String( obj ) :
                class2type[ Object.prototype.toString.call(obj) ] || "object";
        }
    }
    // The DOM ready check for Internet Explorer
    function doScrollCheck() {
        if ( ReadyObj.isReady ) {
            return;
        }

        try {
            // If IE is used, use the trick by Diego Perini
            // http://javascript.nwbox.com/IEContentLoaded/
            document.documentElement.doScroll("left");
        } catch(e) {
            setTimeout( doScrollCheck, 1 );
            return;
        }

        // and execute any waiting functions
        ReadyObj.ready();
    }
    // Cleanup functions for the document ready method
    if ( document.addEventListener ) {
        DOMContentLoaded = function() {
            document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
            ReadyObj.ready();
        };

    } else if ( document.attachEvent ) {
        DOMContentLoaded = function() {
            // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
            if ( document.readyState === "complete" ) {
                document.detachEvent( "onreadystatechange", DOMContentLoaded );
                ReadyObj.ready();
            }
        };
    }
    function ready( fn ) {
        // Attach the listeners
        ReadyObj.bindReady();

        var type = ReadyObj.type( fn );

        // Add the callback
        readyList.done( fn );//readyList is result of _Deferred()
    }
    return ready;
})();

Comment utiliser:

<script>
    ready(function(){
        alert('It works!');
    });
    ready(function(){
        alert('Also works!');
    });
</script>

Je ne sais pas à quel point ce code est fonctionnel, mais cela a bien fonctionné avec mes tests superficiels. Cela a pris un certain temps, alors j'espère que vous et les autres en bénéficierez.

PS: je suggère de le compiler .

Ou vous pouvez utiliser http://dustindiaz.com/smallest-domready-ever :

function r(f){/in/.test(document.readyState)?setTimeout(r,9,f):f()}
r(function(){/*code to run*/});

ou la fonction native si vous avez seulement besoin de prendre en charge les nouveaux navigateurs (contrairement à jQuery ready, cela ne fonctionnera pas si vous l'ajoutez après le chargement de la page)

document.addEventListener('DOMContentLoaded',function(){/*fun code to run*/})
Timo Huovinen
la source
14
@TimoHuovinen Alternatives: Zepto.js (9,1 ko), Snack.js (8,1 ko), $ dom (2,3 ko) et 140 Medley (0,5 ko). Edit: Vous pouvez également jeter un œil à Ender.
Frederik Krautwald,
2
@FrederikKrautwald $ dom ressemble à ce que je voudrais, mais je ne sais pas si cela correspond à la facture. Zepto semble également très prometteur, merci du partage!
Timo Huovinen
@TimoHuovinen Si vous n'avez pas regardé Ender, vous devriez certainement y jeter un œil, enderjs.com .
Frederik Krautwald
2
@Timo Huovinen: Votre question est vraiment, vraiment large! Lorsque jQuery a été créé, il répondait à de nombreux problèmes de navigateurs croisés générés par des navigateurs qui sont aujourd'hui moins importants. Aujourd'hui, "javascript uniquement" est plus facile qu'il ne l'était. A cette époque, créer un "gros 20kb compressé, qui contient tout" était sûrement une bonne idée pour tant de raisons que je préfère ne pas les lister toutes.
dotpush
1
Je n'aime pas ça. Si les gens préfèrent cette réponse, demandez-vous pourquoi vous souhaitez supprimer jQuery en premier lieu. C'est un peu inutile si vous allez simplement extraire exactement la même fonctionnalité avec tout ce repli du navigateur dans votre bundle. N'est-ce pas là tout l'intérêt d'éviter jQuery en premier lieu?
Phil
208

Trois options:

  1. Si scriptest la dernière balise du corps, le DOM serait prêt avant l'exécution de la balise de script
  2. Lorsque le DOM est prêt, "readyState" devient "complete"
  3. Mettez tout sous l'écouteur d'événement «DOMContentLoaded»

onreadystatechange

  document.onreadystatechange = function () {
     if (document.readyState == "complete") {
     // document is ready. Do your stuff here
   }
 }

Source: MDN

DOMContentLoaded

document.addEventListener('DOMContentLoaded', function() {
   console.log('document is ready. I can sleep now');
});

Préoccupé par les navigateurs de l'âge de pierre: accédez au code source jQuery et utilisez lareadyfonction. Dans ce cas, vous n'êtes pas en train d'analyser + d'exécuter toute la bibliothèque, vous n'en faites qu'une très petite partie.

Jhankar Mahbub
la source
3
Ce deuxième exemple est beaucoup plus élégant et succinct que les réponses marquées. Pourquoi celui-ci n'a-t-il pas été marqué comme étant le bon?
0112
2
Toujours +1 pour le truc DOMContentLoaded, il a fait exactement ce que je voulais.
tripleee
1
onreadystatechange a fait l'affaire pour moi ... nécessaire pour exécuter un script après le chargement de jquery asynchrone.
Abram
2
Tout comme un FYI, # 1 n'est pas entièrement vrai. Il est tout à fait possible qu'un script à la fin de la page se charge avant que le DOM ne soit terminé. C'est pourquoi les auditeurs sont supérieurs. Ils écoutent quand le navigateur est terminé. Le mettre à la fin, c'est croiser les doigts, le chargement du script a été plus lent que le navigateur ne peut le rendre.
Machavity
1
cette variante fonctionnera également lorsque le chargement du document est déjà terminé, veuillez mettre à jour votre (meilleure imo) réponse si vous le pouvez: if (document.readyState == 'complete') {init (); } else {document.onreadystatechange = function () {if (document.readyState == 'complete') {init (); }}}
ZPiDER
87

Placez votre <script>/*JavaScript code*/</script>droite avant la </body> balise de fermeture .

Certes, cela pourrait ne pas convenir à tout le monde car cela nécessite de changer le fichier HTML plutôt que de simplement faire quelque chose dans le fichier JavaScript à la la document.ready, mais quand même ...

Rob
la source
Il me semble qu'il y avait des problèmes de compatibilité, comme, comme la page n'est pas encore prête, vous ne pouvez pas faire ceci ou cela dans ces navigateurs. Malheureusement, je ne me souviens pas plus clairement. Néanmoins +1 pour une méthode suffisamment proche dans 99% des cas (et suggérée par Yahoo!).
Boldewyn
7
En fait, mettre un élément de script au bas de la page est une solution presque parfaite. Il fonctionne sur plusieurs navigateurs et simule un document déjà parfait. Le seul inconvénient est que c'est (un peu) plus intrusif que d'utiliser du code intelligent, vous devrez demander à l'utilisateur du script que vous créez d'ajouter un fragment de script supplémentaire pour appeler votre fonction ready ou init.
Stijn de Witt
@StijndeWitt - Que voulez-vous dire par le fait d'appeler une fonction init? Un script qui utilise document.ready n'a pas besoin d'autre code client pour l'appeler, il est autonome, et l'équivalent de celui où le code est inclus à la fin du corps peut également être autonome et ne le fait pas exiger un autre code pour l'appeler non plus.
nnnnnn
1
Pourquoi ne pas mettre le script après la balise de fermeture et avant la </html>balise de fermeture ?
Charles Holbrow
1
@CharlesHolbrow Bien que tous les navigateurs l'interprètent correctement, si vous voulez qu'il soit en html valide, la htmlbalise ne doit contenir que headet body.
Alvaro Montoro
66

Solution du pauvre:

var checkLoad = function() {   
    document.readyState !== "complete" ? setTimeout(checkLoad, 11) : alert("loaded!");   
};  

checkLoad();  

Voir Fiddle

Ajout de celui-ci, un peu mieux je suppose, propre portée et non récursif

(function(){
    var tId = setInterval(function() {
        if (document.readyState == "complete") onComplete()
    }, 11);
    function onComplete(){
        clearInterval(tId);    
        alert("loaded!");    
    };
})()

Voir Fiddle

Jakob Sternberg
la source
8
@PhilipLangford Ou mettez-le simplement dans un setIntervalet supprimez complètement la récursivité.
Alex W
1
@Raveren, hmm tu as raison, je suis presque sûr de l'avoir testé quand je l'ai posté. de toute façon, c'est devenu encore plus simple, maintenant la fonction vient d'être appelée, pas d'habillage.
Jakob Sternberg
24
Ce n'est pas sexy. Non désolé. Utiliser des minuteries / intervalles pour détecter des trucs peut "fonctionner" mais si vous continuez à programmer comme ça, n'importe quel projet plus gros qui en vaut la peine va plonger. Ne piratez pas des trucs comme ça. Fais-le bien. S'il vous plaît. Ce type de code nuit à l'écosystème de développement car il existe une meilleure solution et vous le SAVEZ.
dudewad
1
Je pense que cette réponse est beaucoup plus proche de dustindiaz.com/smallest-domready-ever J'ai donc amélioré le script: jsfiddle.net/iegik/PT7x9
iegik
1
@ReidBlomquist Oui, et c'est une "mauvaise" façon, et c'est ce que je signale (quoique un peu catégoriquement, je sais). On pourrait dire qu'en agissant mal, cela "aide" en quelque sorte l'écosystème, mais le problème est qu'avec la quantité de mauvais code que les gens prennent pour un "bon" code parce qu'ils n'ont pas l'expérience pour mieux connaître n'aide pas l'écosystème, car alors ils vont prendre ce mauvais code et l'implémenter dans une solution architecturale de production réelle. Donc, je suppose que nous devrons simplement différer d'opinion sur cette "erreur".
dudewad
34

J'utilise ceci:

document.addEventListener("DOMContentLoaded", function(event) { 
    //Do work
});

Remarque: Cela ne fonctionne probablement qu'avec les nouveaux navigateurs, en particulier ceux-ci: http://caniuse.com/#feat=domcontentloaded

Dustin Davis
la source
13
IE9 et supérieur en fait
Pascalius
Cela fonctionne également très bien dans les scripts de contenu de l'extension Chrome si vous accrochiez un événement document_start ou document_idle.
Volomike
21

Vraiment, si vous vous souciez uniquement d' Internet Explorer 9+ , ce code suffirait à remplacer jQuery.ready:

    document.addEventListener("DOMContentLoaded", callback);

Si vous vous inquiétez d' Internet Explorer 6 et de certains navigateurs vraiment étranges et rares, cela fonctionnera:

domReady: function (callback) {
    // Mozilla, Opera and WebKit
    if (document.addEventListener) {
        document.addEventListener("DOMContentLoaded", callback, false);
        // If Internet Explorer, the event model is used
    } else if (document.attachEvent) {
        document.attachEvent("onreadystatechange", function() {
            if (document.readyState === "complete" ) {
                callback();
            }
        });
        // A fallback to window.onload, that will always work
    } else {
        var oldOnload = window.onload;
        window.onload = function () {
            oldOnload && oldOnload();
            callback();
        }
    }
},
Dan
la source
18

Cette question a été posée il y a longtemps. Pour tous ceux qui viennent de voir cette question, il existe maintenant un site appelé "vous n'aurez peut-être pas besoin de jquery" qui décompose - par niveau de support IE requis - toutes les fonctionnalités de jquery et fournit des bibliothèques alternatives plus petites.

Le script prêt pour le document IE8 selon vous pourrait ne pas avoir besoin de jquery

function ready(fn) {
    if (document.readyState != 'loading')
        fn();
    else if (document.addEventListener)
        document.addEventListener('DOMContentLoaded', fn);
    else
        document.attachEvent('onreadystatechange', function() {
            if (document.readyState != 'loading')
                fn();
        });
}
chugadie
la source
Je me demande pourquoi 'onreadystatechange'c'est nécessaire plutôt quedocument.attachEvent('onload', fn);
Luke
13

J'utilisais récemment ceci pour un site mobile. Ceci est la version simplifiée de John Resig de "Pro JavaScript Techniques". Cela dépend de addEvent.

var ready = ( function () {
  function ready( f ) {
    if( ready.done ) return f();

    if( ready.timer ) {
      ready.ready.push(f);
    } else {
      addEvent( window, "load", isDOMReady );
      ready.ready = [ f ];
      ready.timer = setInterval(isDOMReady, 13);
    }
  };

  function isDOMReady() {
    if( ready.done ) return false;

    if( document && document.getElementsByTagName && document.getElementById && document.body ) {
      clearInterval( ready.timer );
      ready.timer = null;
      for( var i = 0; i < ready.ready.length; i++ ) {
        ready.ready[i]();
      }
      ready.ready = null;
      ready.done = true;
    }
  }

  return ready;
})();
James
la source
13
Soyez prudent avec ce code. Ce n'est PAS équivalent à $ (document) .ready. Ce code déclenche le rappel lorsque document.body est prêt, ce qui ne garantit pas que le DOM est entièrement chargé.
Karolis
12

Cross-browser (anciens navigateurs aussi) et une solution simple:

var docLoaded = setInterval(function () {
    if(document.readyState !== "complete") return;
    clearInterval(docLoaded);

    /*
        Your code goes here i.e. init()
    */
}, 30);

Affichage d'alerte dans jsfiddle

Pawel
la source
Sauf s'il faut plus de 30 ms pour charger le DOM, votre code ne s'exécutera pas.
Quelklef
1
@Quelklef c'est setInterval pas setTimeout
Pawel
11

La réponse jQuery m'a été très utile. Avec un peu de réfractaire ça correspondait bien à mes besoins. J'espère que cela aide quelqu'un d'autre.

function onReady ( callback ){
    var addListener = document.addEventListener || document.attachEvent,
        removeListener =  document.removeEventListener || document.detachEvent
        eventName = document.addEventListener ? "DOMContentLoaded" : "onreadystatechange"

    addListener.call(document, eventName, function(){
        removeListener( eventName, arguments.callee, false )
        callback()
    }, false )
}
Miere
la source
sur certains navigateurs, le removeListenerdevra être appelé avec le document comme contexte, ie. removeListener.call(document, ...
Ron
9

Voici le plus petit extrait de code pour tester DOM ready qui fonctionne sur tous les navigateurs (même IE 8):

r(function(){
    alert('DOM Ready!');
});
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}

Voir cette réponse .

Antara Roy
la source
6

Ajoutez simplement ceci au bas de votre page HTML ...

<script>
    Your_Function();
</script>

Parce que les documents HTML sont analysés de haut en bas.

davefrassoni
la source
7
Comment savez-vous que DOM est construit lorsque ce code est exécuté? Y compris le CSS chargé et analysé? L'API du navigateur DOMContentLoaded est conçue pour cela.
Dan
Cela dépend vraiment de ce qu'il veut faire avec js. S'il a vraiment besoin d'exécuter quelque chose lorsque la page est terminée ou non.
davefrassoni
5

Cela vaut la peine de regarder dans Rock Solid addEvent () et http://www.braksator.com/how-to-make-your-own-jquery .

Voici le code en cas de panne du site

function addEvent(obj, type, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(type, fn, false);
        EventCache.add(obj, type, fn);
    }
    else if (obj.attachEvent) {
        obj["e"+type+fn] = fn;
        obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
        obj.attachEvent( "on"+type, obj[type+fn] );
        EventCache.add(obj, type, fn);
    }
    else {
        obj["on"+type] = obj["e"+type+fn];
    }
}

var EventCache = function(){
    var listEvents = [];
    return {
        listEvents : listEvents,
        add : function(node, sEventName, fHandler){
            listEvents.push(arguments);
        },
        flush : function(){
            var i, item;
            for(i = listEvents.length - 1; i >= 0; i = i - 1){
                item = listEvents[i];
                if(item[0].removeEventListener){
                    item[0].removeEventListener(item[1], item[2], item[3]);
                };
                if(item[1].substring(0, 2) != "on"){
                    item[1] = "on" + item[1];
                };
                if(item[0].detachEvent){
                    item[0].detachEvent(item[1], item[2]);
                };
                item[0][item[1]] = null;
            };
        }
    };
}();

// Usage
addEvent(window, 'unload', EventCache.flush);
addEvent(window, 'load', function(){alert("I'm ready");});
Ben
la source
Le deuxième lien est rompu.
Peter Mortensen
4

Ce code inter-navigateur appellera une fonction une fois le DOM prêt:

var domReady=function(func){
    var scriptText='('+func+')();';
    var scriptElement=document.createElement('script');
    scriptElement.innerText=scriptText;
    document.body.appendChild(scriptElement);
};

Voici comment ça fonctionne:

  1. La première ligne domReadyappelle la toStringméthode de la fonction pour obtenir une représentation sous forme de chaîne de la fonction que vous passez et l'enveloppe dans une expression qui appelle immédiatement la fonction.
  2. Le reste de domReadycrée un élément de script avec l'expression et l'ajoute au bodydocument.
  3. Le navigateur exécute des balises de script ajoutées bodyaprès que le DOM est prêt.

Par exemple, si vous procédez domReady(function(){alert();});comme suit:, ce qui suit sera ajouté à l' bodyélément:

 <script>(function (){alert();})();</script>

Notez que cela ne fonctionne que pour les fonctions définies par l'utilisateur. Les éléments suivants ne fonctionneront pas:domReady(alert);

Max Heiber
la source
4

C'est l'année 2020 et la <script>balise a un deferattribut.

par exemple:

<script src="demo_defer.js" defer></script>

il spécifie que le script est exécuté lorsque la page a terminé l'analyse.

https://www.w3schools.com/tags/att_script_defer.asp

Mikser
la source
3

Et cette solution?

// other onload attached earlier
window.onload=function() {
   alert('test');
};

tmpPreviousFunction=window.onload ? window.onload : null;

// our onload function
window.onload=function() {
   alert('another message');

   // execute previous one
   if (tmpPreviousFunction) tmpPreviousFunction();
};
Mike
la source
3
Vous pouvez utiliser addEventListener sur la fenêtre avec "charger". Les écouteurs sont exécutés un par un et n'ont pas besoin d'être enchaînés manuellement.
Zaffy
1
Mais la charge est différente de celle prête. Le «chargement» se produit même avant que le document ne soit «prêt». Un document prêt a son DOM chargé, une fenêtre chargée n'a pas nécessairement le DOM prêt. Bonne réponse cependant
Mzn
1
@Mzn: Je pense que c'est à l'envers. Je pense que le document prêt se produit avant l'événement de chargement de la fenêtre. "En général, il n'est pas nécessaire d'attendre que toutes les images soient entièrement chargées. Si le code peut être exécuté plus tôt, il est généralement préférable de le placer dans un gestionnaire envoyé à la méthode .ready ()." ( api.jquery.com/load-event )
Tyler Rick
cela remplacera le reste des événements window.onload sur la page et entraînerait des problèmes. il doit ajouter un événement en plus de celui existant.
Teoman shipahi
L'événement de chargement peut se produire trop tard. Il est pénible de l'utiliser quand il dépend de js / images externes tiers ... Un serveur non réactif que vous ne contrôlez pas et tout échoue. L'utilisation de DOMContentLoaded n'est pas seulement une optimisation, c'est aussi plus sûr!
dotpush
3

Il est toujours bon d'utiliser des équivalents JavaScript par rapport à jQuery. Une des raisons est qu'il faut compter sur une bibliothèque de moins et elles sont beaucoup plus rapides que les équivalents jQuery.

Une référence fantastique pour les équivalents jQuery est http://youmightnotneedjquery.com/ .

En ce qui concerne votre question, j'ai pris le code ci-dessous à partir du lien ci-dessus :) Seul bémol, cela ne fonctionne qu'avec Internet Explorer 9 et versions ultérieures.

function ready(fn) {
    if (document.readyState != 'loading') {
        fn();
    }
    else {
        document.addEventListener('DOMContentLoaded', fn);
    }
}
Vatsal
la source
3

Le plus minimal et 100% fonctionnel

J'ai choisi la réponse de PlainJS et ça marche bien pour moi. Il s'étend DOMContentLoadedpour pouvoir être accepté sur tous les navigateurs.


Cette fonction est l'équivalent de la $(document).ready()méthode de jQuery :

document.addEventListener('DOMContentLoaded', function(){
    // do something
});

Cependant, contrairement à jQuery, ce code ne fonctionnera correctement que dans les navigateurs modernes (IE> 8) et il ne le sera pas si le document est déjà rendu au moment où ce script est inséré (par exemple via Ajax). Par conséquent, nous devons étendre un peu ceci:

function run() {
    // do something
}

// in case the document is already rendered
if (document.readyState!='loading') run();
// modern browsers
else if (document.addEventListener) 
document.addEventListener('DOMContentLoaded', run);
// IE <= 8
else document.attachEvent('onreadystatechange', function(){
    if (document.readyState=='complete') run();
});

Cela couvre essentiellement toutes les possibilités et constitue un remplacement viable de l'aide jQuery.

Shivam Sharma
la source
2

Nous avons trouvé une implémentation de navigateur croisée rapide et sale qui peut faire l'affaire pour la plupart des cas simples avec une implémentation minimale:

window.onReady = function onReady(fn){
    document.body ? fn() : setTimeout(function(){ onReady(fn);},50);
};
malko
la source
quoi doc.body!?
Nabi KAZ
2

Les solutions setTimeout / setInterval présentées ici ne fonctionneront que dans des circonstances spécifiques.

Le problème apparaît surtout dans les anciennes versions d'Internet Explorer jusqu'à 8.

Les variables affectant le succès de ces solutions setTimeout / setInterval sont:

1) dynamic or static HTML
2) cached or non cached requests
3) size of the complete HTML document
4) chunked or non chunked transfer encoding

le code original (Javascript natif) résolvant ce problème spécifique est ici:

https://github.com/dperini/ContentLoaded
http://javascript.nwbox.com/ContentLoaded (test)

c'est le code à partir duquel l'équipe jQuery a construit leur implémentation.

Diego Perini
la source
1

Voici ce que j'utilise, c'est rapide et couvre toutes les bases je pense; fonctionne pour tout sauf IE <9.

(() => { function fn() {
    // "On document ready" commands:
    console.log(document.readyState);
};  
  if (document.readyState != 'loading') {fn()}
  else {document.addEventListener('DOMContentLoaded', fn)}
})();

Cela semble attraper tous les cas:

  • se déclenche immédiatement si le DOM est déjà prêt (si le DOM n'est pas en "chargement", mais "interactif" ou "complet")
  • si le DOM est toujours en cours de chargement, il configure un écouteur d'événements lorsque le DOM est disponible (interactif).

L'événement DOMContentLoaded est disponible dans IE9 et tout le reste, donc je pense personnellement que c'est OK pour l'utiliser. Réécrivez la déclaration de la fonction flèche dans une fonction anonyme régulière si vous ne transpilez pas votre code d'ES2015 vers ES5.

Si vous voulez attendre que toutes les ressources soient chargées, toutes les images affichées, etc., utilisez plutôt window.onload.

Olemak
la source
1

Si vous n'avez pas à prendre en charge de très anciens navigateurs, voici un moyen de le faire même lorsque votre script externe est chargé avec l' attribut async :

HTMLDocument.prototype.ready = new Promise(function(resolve) {
   if(document.readyState != "loading")
      resolve();
   else
      document.addEventListener("DOMContentLoaded", function() {
         resolve();
      });
});

document.ready.then(function() {
   console.log("document.ready");
});
user4617883
la source
0

Pour IE9 +:

function ready(fn) {
  if (document.readyState != 'loading'){
    fn();
  } else {
    document.addEventListener('DOMContentLoaded', fn);
  }
}
Joaquinglezsantos
la source
0

Si vous chargez jQuery près du bas de BODY, mais que vous rencontrez des problèmes avec le code qui écrit jQuery (<func>) ou jQuery (document) .ready (<func>), consultez jqShim sur Github.

Plutôt que de recréer sa propre fonction prête pour le document, il conserve simplement les fonctions jusqu'à ce que jQuery soit disponible, puis continue avec jQuery comme prévu. Le point de déplacer jQuery vers le bas du corps est d'accélérer le chargement des pages, et vous pouvez toujours l'accomplir en insérant le jqShim.min.js dans la tête de votre modèle.

J'ai fini par écrire ce code pour déplacer tous les scripts de WordPress dans le pied de page, et ce code shim se trouve maintenant directement dans l'en-tête.

Matt Pileggi
la source
0

Essaye ça:

function ready(callback){
    if(typeof callback === "function"){
        document.addEventListener("DOMContentLoaded", callback);
        window.addEventListener("load", callback);
    }else{
        throw new Error("Sorry, I can not run this!");
    }
}
ready(function(){
    console.log("It worked!");
});

la source
Lol, tu vas exécuter le rappel deux fois
Andrew
0
function onDocReady(fn){ 
    $d.readyState!=="loading" ? fn():document.addEventListener('DOMContentLoaded',fn);
}

function onWinLoad(fn){
    $d.readyState==="complete") ? fn(): window.addEventListener('load',fn);
} 

onDocReady fournit un rappel lorsque le dom HTML est prêt à accéder / analyser / manipuler complètement.

onWinLoad fournit un rappel lorsque tout est chargé (images, etc.)

  • Ces fonctions peuvent être appelées à tout moment.
  • Prend en charge plusieurs "écouteurs".
  • Fonctionnera dans n'importe quel navigateur.
Jakob Sternberg
la source
0
(function(f){
  if(document.readyState != "loading") f();
  else document.addEventListener("DOMContentLoaded", f);
})(function(){
  console.log("The Document is ready");
});
Dustin Poissant
la source
Qu'est-ce que cela ajoute que les autres réponses ne font pas?
dwjohnston
Il utilise une fermeture autonome (ne remplit pas la portée globale de la "fenêtre"), il fonctionne sur tous les navigateurs et est très compact. Je ne vois pas d'autres réponses comme ça.
Dustin Poissant
Il fonctionne également même après le chargement du DOM (comme le fait jQuery.ready), ce que la plupart de ces réponses ne parviennent pas à faire.
Dustin Poissant
0

La plupart des fonctions vanilla JS Ready ne prennent PAS en compte le scénario dans lequel le DOMContentLoadedgestionnaire est défini une fois le document déjà chargé - ce qui signifie que la fonction ne s'exécutera jamais . Cela peut se produire si vous recherchez DOMContentLoadeddans un asyncscript externe ( <script async src="file.js"></script>).

Le code ci-dessous ne vérifie DOMContentLoadedque si le document readyStaten'est pas déjà interactiveou complete.

var DOMReady = function(callback) {
  document.readyState === "interactive" || document.readyState === "complete" ? callback() : document.addEventListener("DOMContentLoaded", callback());
};
DOMReady(function() {
  //DOM ready!
});

Si vous souhaitez également prendre en charge IE:

var DOMReady = function(callback) {
    if (document.readyState === "interactive" || document.readyState === "complete") {
        callback();
    } else if (document.addEventListener) {
        document.addEventListener('DOMContentLoaded', callback());
    } else if (document.attachEvent) {
        document.attachEvent('onreadystatechange', function() {
            if (document.readyState != 'loading') {
                callback();
            }
        });
    }
};

DOMReady(function() {
  // DOM ready!
});
Nul
la source
0

J'utilise simplement:

setTimeout(function(){
    //reference/manipulate DOM here
});

Et contrairement document.addEventListener("DOMContentLoaded" //etcà la toute première réponse, cela fonctionne aussi loin que IE9 - http://caniuse.com/#search=DOMContentLoaded indique seulement aussi récemment que IE11.

Fait intéressant, je suis tombé sur cette setTimeoutsolution en 2009: la vérification de l'état de préparation du DOM est-elle excessive? , qui aurait probablement pu être formulé un peu mieux, car je voulais dire "est-ce exagéré d'utiliser des approches plus complexes de divers cadres pour vérifier la disponibilité du DOM".

Ma meilleure explication de la raison pour laquelle cette technique fonctionne est que, lorsque le script avec un tel setTimeout a été atteint, le DOM est en train d'être analysé, donc l'exécution du code dans le setTimeout est différée jusqu'à la fin de cette opération.

Dexygen
la source