Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Code inside DOMContentLoaded event not working

I have used

<!DOCTYPE html> <html> <head>   <meta charset="utf-8" /> </head> <body>   <button type="button" id="button">Click</button>   <pre id="output">Not Loading...</pre>    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.17.0/babel.min.js"></script>   <script type="text/babel">     document.addEventListener('DOMContentLoaded', function () {       const button = document.getElementById('button');       const output = document.getElementById('output');        output.textContent = 'Loading...';        addEventListener('click', function () {         output.textContent = 'Done';       });      });   </script> </body> </html> 

but it seems the code inside document.addEventListener('DOMContentLoaded', function () {}); is not loading.

If I remove this from my code, it suddenly works.

I have made a JS Bin here.

like image 201
Jamgreen Avatar asked Oct 12 '16 08:10

Jamgreen


People also ask

Does DOMContentLoaded wait for scripts?

DOMContentLoaded and styles External style sheets don't affect DOM, so DOMContentLoaded does not wait for them. The reason for this is that the script may want to get coordinates and other style-dependent properties of elements, like in the example above.

What triggers DOMContentLoaded?

The DOMContentLoaded event fires when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.

Does DOMContentLoaded wait for CSS?

DOMContentLoaded doesn't wait for stylesheets to load provided that no scripts are placed after the stylesheet reference, <link rel="stylesheet"> . This is valid for all browsers supporting DOMContentLoaded.

What does DOMContentLoaded get executed?

DOMContentLoaded event gets executed once the basic HTML document is loaded and its parsing has taken place. This event doesn't wait for the completion of the loading of add-ons such as stylesheets, sub-frames and images/pictures.


2 Answers

It's most likely because the DOMContentLoaded event was already fired at this point. The best practice in general is to check for document.readyState to determine whether or not you need to listen for that event at all.

if( document.readyState !== 'loading' ) {     console.log( 'document is already ready, just execute code here' );     myInitCode(); } else {     document.addEventListener('DOMContentLoaded', function () {         console.log( 'document was not ready, place code here' );         myInitCode();     }); }  function myInitCode() {} 
like image 191
jAndy Avatar answered Sep 28 '22 05:09

jAndy


The event has already fired by the time that code hooks it. The way Babel standalone works is by responding to DOMContentLoaded by finding and executing all of the type="text/babel" scripts on the page. You can see this in the index.js file:

// Listen for load event if we're in a browser and then kick off finding and // running of scripts with "text/babel" type. const transformScriptTags = () => runScripts(transform); if (typeof window !== 'undefined' && window && window.addEventListener) {   window.addEventListener('DOMContentLoaded', transformScriptTags, false); } 

Just run the code directly, without waiting for the event, since you know Babel standalone will wait for it for you.

Also note that if you put you script at the end of the body, just before the closing </body> tag, there's no need to wait for DOMContentLoaded even if you don't use Babel. All of the elements defined above the script will exist and be available to your script.


In a comment you've asked:

But I am using Babel standalone in development, but I will pre-compile it when I go into production. Should I add it back on when I go into production?

Just ensure that your script tag is at the end of body as described above, and there's no need to use the event.

If it's important to you to use it anyway, you can check to see whether the event has already run by checking document.readyState (after following the link, scroll up a bit):

function onReady() {     // ...your code here... } if (document.readyState !== "loading") {     onReady(); // Or setTimeout(onReady, 0); if you want it consistently async } else {     document.addEventListener("DOMContentLoaded", onReady); } 

document.readyState goes through these stages (scroll up slightly from the link above):

Returns "loading" while the Document is loading, "interactive" once it is finished parsing but still loading sub-resources, and "complete" once it has loaded.

like image 24
T.J. Crowder Avatar answered Sep 28 '22 04:09

T.J. Crowder