3

I have two questions on placing JS inside HTML. I can't find where these two points were answered here.

Questions are basically

  • Let's say I put Javascript in the head, and say the script tries to get some HTML element by ID, and register a click handler for it. Now since, the HTML has not been loaded yet (because the script is called in head), will this work?
  • On the other hand, if register a function in head which gets called when DOM is loaded, and inside that function I put code which registers handler for click on some button, then as I understand user has chance to click button but the handler will not be called because the whole DOM was not loaded yet (and that is where the button click handler is registered). Am I correct?

What is the solution and best way to put Javascript in HTML considering above two points?

Community
  • 1
  • 1
  • 1
    In a nutshell: yes, this can be an issue, but practically speaking, if there is such a delay between the button being loaded and the rest of the HTML finishing to load, then you need to optimise the size of your HTML and/or how you load more external resources that block the HTML from finishing to load. Someone may want to expand on details on how to do this in a proper answer… – deceze Dec 07 '16 at 08:57
  • @deceze You are referring to my 2nd point? –  Dec 07 '16 at 08:58
  • @user Yes indeed. – deceze Dec 07 '16 at 08:58
  • @deceze "Why not?" Since the DOM isn't loaded yet, the parser is still doing its job, and there's only one thread for parsing _and_ rendering. User can't simply see and click the button before both of these task are done. – Teemu Dec 07 '16 at 09:03
  • 1
    @Teemu You should keep comments in the right thread to preserve context for future readers. FWIW, as far as I am aware, and you'll have to prove me wrong here, the received HTML *is* rendered incrementally, the browser does *not* block until the entire HTML has been loaded. – deceze Dec 07 '16 at 09:09
  • @deceze Sorry for the wrong thread, somehow it look to me like the correct thread was removed, (now I can see it was dimmed only). Afaik, parsing first, then rendering, but not waiting for window.onload ofcourse. I'm going to find some information about this, but that'll take a while. – Teemu Dec 07 '16 at 09:15
  • @deceze would be nice if you could double check existing answer –  Dec 08 '16 at 15:58

1 Answers1

2

Let's say I put Javascript in the head, and say the script tries to get some HTML element by ID, and register a click handler for it. Now since, the HTML has not been loaded yet (because the script is called in head), will this work?

No, this won't work. Whenever <script> tag is seen, javascript is executed right away before going further with DOM building. (if javascript is external, it will wait to fetch it over network and execute it) It will act upon the current snapshot of DOM if the javascript is using DOM APIs like getElementById. When script tries to get the element by id, it tries to get it from DOM, (All DOM APIs acts on DOM) which is being built right now. As the element is not yet added to DOM (we are processing head) it won't be able to get the element. As it cannot get the element it will throw error if you try to access addEventListener or onclick of null.

On the other hand, if register a function in head which gets called when DOM is loaded, and inside that function I put code which registers handler for click on some button, then as I understand user has chance to click button but the handler will not be called because the whole DOM was not loaded yet (and that is where the button click handler is registered). Am I correct?

Yes, you are correct. DOM load generalises the condition that all elements are added to the DOM and is ready for any operation on any element defined by HTML.

Also, window.load will be triggered only after DOM is loaded and all the external resources like images, videos are also loaded. Using it can delay the event attachments further.

What if I want to add event listener immediately?

If you want to immediately bind an event you can do it with inline scripts, just after the element although usually not a requirement and neither a good practice.

<p>whatever</p>
<button id="mybutton">Click me</button>
<script>
     document.getElementById('mybutton').addEventListener(...
</script>
<p>rest of HTML</p>

This also opens another possibility, if you put your scripts at the end of HTML instead of head, it makes sure that all elements are added to the DOM and DOM is practically ready for any operations using DOM APIs. This was used widely when listening to DOM load event was not that easy. Although I can't find the correct reference, this was a recommendation by Doug Crockford.

sabithpocker
  • 15,274
  • 1
  • 42
  • 75
  • what if I write click handler directly inside HTML element? as attribute –  Dec 08 '16 at 15:59