$ (Document). Jj équivalent sans jQuery

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

Comment puis-je mettre en œuvre ma propre fonctionnalité $(document).ready sans utiliser jQuery? Je sais que l'utilisation de window.onload ne sera pas la même, que window.onload fires après que toutes les images, les images, etc. aient été chargés.

Il existe un remplacement basé sur les normes, DOMContentLoaded qui est pris 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 ); } 

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

 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 suis pas sûr de la fonctionnalité de ce code, mais cela a bien fonctionné avec mes tests superficiels. Cela a pris un certain temps, alors j'espère que vous et d'autres pourront en bénéficier.

PS: je suggère de le compiler .

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

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

Ou la fonction native si vous devez seulement supporter les nouveaux navigateurs

 document.addEventListener('DOMContentLoaded',function(){/*fun code to run*/}) 

Trois options:

  1. Si le script est la dernière étiquette du corps, le DOM serait prêt avant l'exécution du script.
  2. Lorsque le DOM est prêt, "readyState" changera en "complete"
  3. Placez tout sous l'écouteur d'événements "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 d'âge de pierre: passez au code source jQuery et utilisez la fonction ready . Dans ce cas, vous n'êtes pas analyser + exécuter toute la bibliothèque que vous ne faites qu'une très petite partie de celle-ci.

Placez votre <script>/*JavaScript code*/</script> juste avant la </body> fermeture .

Certes, cela pourrait ne pas convenir à tous les besoins car il faut changer le fichier HTML plutôt que de faire quelque chose dans le fichier JavaScript à la document.ready , mais toujours …

La solution de l'homme pauvre:

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

Voir Fiddle

J'ai ajouté celui-ci, un peu mieux, je suppose, sa 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

J'utilise ceci:

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

Remarque: Cela ne fonctionne probablement qu'avec des navigateurs plus récents, en particulier ceux-ci: http://caniuse.com/#feat=domcontentloaded

Vraiment, si vous vous souciez d' Internet Explorer 9+ uniquement, 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(); } } }, 

Je l'utilisais récemment pour un site mobile. C'est la version simplifiée de John Resig à partir de "Pro JavaScript Techniques". Cela dépend d'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; })(); 

La réponse jQuery m'a été très utile. Avec un peu de refactory il a bien ajusté mes besoins. J'espère que cela aidera 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 ) } 

Cette question a été posée il y a très longtemps. Pour tout le monde qui vient de voir cette question, il existe maintenant un site appelé «vous pourriez ne pas avoir besoin de jquery» qui décompose – par niveau de support IE requis – toutes les fonctionnalités de jquery et fournit des bibliothèques alternatives et plus petites.

Le script IE5 de document prêt 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(); }); } 

Voici le plus petit extrait de code pour tester le prêt DOM 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 .

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

 var docLoaded = setInterval(function () { if(document.readyState !== "complete") return; clearInterval(docLoaded); /* Your code goes here ie init() */ }, 30); 

Affichage de l'alerte dans jsfiddle

Ajoutez simplement ceci au bas de votre page HTML …

 <script> Your_Function(); </script> 

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

Ce code de navigateur croisé appellera une fonction une fois que le DOM est prêt:

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

Voici comment cela fonctionne:

  1. La première ligne de domReady appelle la méthode toString de la fonction pour obtenir une représentation 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 domReady crée un élément de script avec l'expression et l'ajoute au body du document.
  3. Le navigateur exécute des tags de script ajoutés au body après que le DOM est prêt.

Par exemple, si vous faites ceci: domReady(function(){alert();}); , Le suivant sera ajouté à l'élément du body :

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

Notez que cela ne fonctionne que pour les fonctions définies par l'utilisateur. Ce qui suit ne fonctionnera pas: domReady(alert);

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

Voici le code au cas où le site tomberait

 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");}); 

Qu'en est-il de 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(); }; 

Nous avons trouvé une implémentation de navigateur croisée rapide et sale de notre part 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); }; 

Il est toujours bon d'utiliser des équivalents JavaScript par rapport à jQuery. L'une des raisons pour lesquelles une bibliothèque est moins dépendante et sont beaucoup plus rapides que les équivalents jQuery.

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

En ce qui concerne votre question, j'ai pris le code ci-dessous à partir du lien ci-dessus 🙂 La seule mise en garde est que cela fonctionne uniquement avec Internet Explorer 9 et versions ultérieures.

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

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

Le problème se manifeste 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) qui résout 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 sa mise en œuvre.

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 «chargé», mais «interactif» ou «complet»)
  • Si le DOM est encore en cours de chargement, il configure un auditeur d'événement lorsque le DOM est disponible (interactif).

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

Si vous souhaitez attendre que tous les éléments soient chargés, toutes les images affichées, etc., utilisent window.onload à la place.

Pour IE9 +:

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

La fonction prête dans jQuery fait un certain nombre de choses. Franchement, je ne vois pas le point de le remplacer, sauf si vous avez une sortie étonnamment faible de votre site Web. JQuery est une bibliothèque assez petite, et elle gère toutes sortes de choses croisées entre les navigateurs dont vous aurez besoin plus tard.

Quoi qu'il en soit, il y a peu de chose à poster ici, ouvrez simplement jQuery et regardez la méthode bindReady.

Il commence par appeler document.addEventListener ("DOMContentLoaded") ou document.attachEvent ('onreadystatechange') selon le modèle d'événement, et se déroule à partir de là.

Si vous chargez jQuery près du bas de BODY, mais avez 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 de document prêt, elle tient simplement sur les fonctions jusqu'à ce que jQuery soit disponible puis procède avec jQuery comme prévu. Le point de déplacer jQuery vers le bas du corps est d'accélérer le chargement de la page, et vous pouvez toujours l'accomplir en indiquant jqShim.min.js dans la tête de votre modèle.

J'ai fini par écrire ce code pour faire passer tous les scripts dans WordPress au pied de page, et juste ce code de caisse est maintenant directement dans l'en-tête.

Cette approche est la façon la plus courante dont je peux penser.

La solution basée sur l'événement DOMContentLoaded ne fonctionne que si le script est chargé avant le document, alors que le contrôle paresseux suggéré ici garantit que le code soit toujours exécuté, même dans les scripts chargés dynamiquement plus tard, exactement comme le document de JQuery est prêt.

Ce code est compatible avec tous les navigateurs (y compris certains hérités, vers IE6 et Safari pour Windows).

 (function ready() { if (!document.body) {setTimeout(ready, 50); return;} // Document is ready here })(); 
 function onDocReady(fn){ (function c(){document.readyState!=="loading"?fn():setTimeout(c,9)})(); } function onDocLoad(fn){ (function c(){document.readyState==="complete"?fn():setTimeout(c,30)})(); } 

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

OnDocLoad fournit un rappel lorsque tout a été chargé (images, etc.)

  • Ces fonctions peuvent être appelées lorsque vous le souhaitez.
  • Prise en charge de multiples "auditeurs".
  • Fonctionnera dans n'importe quel navigateur.

C'était une bonne solution https://stackoverflow.com/a/11810957/185565 pauvre homme. Un commentaire a été considéré comme un compteur de renflouement en cas d'urgence. C'est ma modification.

 function doTheMagic(counter) { alert("It worked on " + counter); } // wait for document ready then call handler function var checkLoad = function(counter) { counter++; if (document.readyState != "complete" && counter<1000) { var fn = function() { checkLoad(counter); }; setTimeout(fn,10); } else doTheMagic(counter); }; checkLoad(0); 

Modifier l'édition de @duskwuff pour prendre en charge Internet Explorer 8 aussi. La différence est un nouvel appel au test de fonction du regex et au setTimeout avec une fonction anonyme.

En outre, j'ai mis le délai d'attente à 99.

 function ready(f){/in/.test(document.readyState)?setTimeout(function(){ready(f);},99):f();} 

En bref, au lieu de $ (document) .ready () utilisé dans jQuery, nous pouvons utiliser une méthode JavaScript:

 <script> document.addEventListener("DOMContentLoaded", function_name, false); function function_name(){ statements; } </script> 

Thus, when the page is ready ie DOMContentLoaded only then the function function_name() will be invoked.

If you want to support Internet Explorer 7+ (no quirks, compatibility and other pain), last Chrome , last Safari , last Firefox and no iframes – this will be enough:

 is_loaded = false callbacks = [] loaded = -> is_loaded = true for i in [0...callbacks.length] callbacks[i].call document callbacks = [] content_loaded = -> document.removeEventListener "DOMContentLoaded", content_loaded, true loaded() state_changed = -> if document.readyState is "complete" document.detachEvent "onreadystatechange", state_changed loaded() if !!document.addEventListener document.addEventListener "DOMContentLoaded", content_loaded, true else document.attachEvent "onreadystatechange", state_changed dom_ready = (callback) -> if is_loaded callback.call document else callbacks.push callback