Explain Codes LogoExplain Codes Logo

$(document).ready equivalent without jQuery

javascript
dom-readiness
vanilla-js
javascript-optimizations
Anton ShumikhinbyAnton Shumikhin·Oct 5, 2024
TLDR

For directly replacing $(document).ready, use the native JavaScript document.addEventListener('DOMContentLoaded', callback). This bit of code runs as soon as the DOM is fully parsed:

document.addEventListener('DOMContentLoaded', function() { // Code to be executed after the DOM is ready });

Pro tip: Use this at the start of your script to ensure the DOM is fully loaded before you start manipulating it — just like you would with jQuery’s ready() method.

When DOMContentLoaded fires too early

Let's discuss an interesting edge-case. When async or defer attributes are used, your script can load after DOMContentLoaded fires. For such cases, check document.readyState.

if (document.readyState === "loading") { // If HTML is still loading document.addEventListener('DOMContentLoaded', function() { // Let's get coding! }); } else { // `DOMContentLoaded` has already occurred // Time to Boogie on! }

When it comes to scripts, timing is everything — ensure you don't miss the party!

Covering all your bases: Browser Compatibility

Cursed by the ghost of IE? No worries, document.attachEvent with onreadystatechange has your back for IE 8 and older browsers. Also, say document.readyState === 'complete' three times in front of the mirror, it acts as a charm to check if document is fully loaded.

(function ready() { if (document.readyState != 'loading'){ // Time to play DOM-tetris! } else if (document.addEventListener) { document.addEventListener('DOMContentLoaded', function() { // Fire the DOM lasers! Pew Pew! }); } else { document.attachEvent('onreadystatechange', function() { if (document.readyState == 'complete') { // DOM's ready. Challenge Accepted! } }); } })();

IEgoistic IE may not have addEventListener, but it's never too old for some IE-special tricks.

DOM loading optimizations

Script placement matters! If scripts are at the end of the body, chances are that the DOM would be ready by the time they execute, bypassing the need for a DOM readiness check:

<body> <!-- HTML content --> <script> // The DOM is my playground, let's get swingin! </script> </body>

More powerful DOM readiness checks

While DOMContentLoaded is our usual suspect, some sneaky scenarios demand a fancier approach:

  • How about a fallback for Stone Age browsers (looking at you IE6/7)? We can marry setInterval (our recurring readiness checks) to clearInterval (stop-check flag) for a primitive cave-painting approach.

  • Working in wonderland of deferred function patterns? Queue the callbacks for DOM readiness, and make it rain when the DOM is prepped.

  • Sometimes in our wildest dreams, we not only need the DOM but also images, CSS, and other external resources to load. Alas, window.onload is the call you've been waiting for.

window.onload = function() { // All aboard and loaded? Full speed ahead! };
  • Before summoning jQuery or other large libraries, consider dabbling into magical lands of vanilla JS alternatives. Trust me, places like http://youmightnotneedjquery.com/ and https://plainjs.com/ make unicorns seem ordinary.

  • Isolation and encapsulation: Running a magical school (read large applications) or shipping your spells (reusable code)? Immediately-invoked function expressions (IIFEs) keep the global namespace as clean as a new-broomstick!

  • Conjuring custom DOM ready functions? A friendly house-elf in the form of a closure compiler can compress/minify your JS for the final shiny performance broomstick.

Making magic work with dynamically loaded content

In the realm of dynamic content or single-page applications, the DOM's ready state might need a consult from a Time-Turner on content load. Here, directly charmed event listeners or a MutationObserver can reroute magic upon DOM changes.

References