3

from an issue I am experiencing I understand how it works, but I can't find any formal reference that helps me to clarify the behaviour.

<head>
<title>Chapter 7: Example 7</title>
<script type="text/javascript">

    var formWeek = document.form1;
    var weekDays = new Array();
    weekDays = formWeek.theDay.options;
    function btnRemoveWed_onclick()
    {
        console.log("In btnRemoveWed_onclick");

    }
</script>
</head>

<body>
<form action="" name="form1">
    <select name="theDay" size="5">
        <option value="0" selected="selected"></option>

With this code I receive an error on line "weekDays = formWeek.theDay.options;" because "theDay" is not defined. So I believe that while the JS code is executed the browser has not parsed and loaded the DOM (hence it doesn't know about form1).

If I move the variable definition inside the function, everything works fine.

        function btnRemoveWed_onclick()
    {
        console.log("In btnRemoveWed_onclick");
        var formWeek = document.form1;
        var weekDays = new Array();
        weekDays = formWeek.theDay.options;
    }

At function execution the browser knows about form1 (load all the HTML code).

So... from the code the behaviour is clear but still it has not 'clicked' on my mind how it works.

I thought that the link below was a good reference to understand the behaviour.

Where should I put <script> tags in HTML markup?

Can you point me to some good reading that explains HTML-JS loading?

Community
  • 1
  • 1
gxvigo
  • 787
  • 4
  • 10
  • 20
  • 2
    The entire file, script tags and all, are read and parsed from the top down. That means that referencing elements in a script tag that comes later in the DOM doesn't work, as the elements doesn't exist at the time the script tag is parsed. The solution is to move the script tag lower down, or use an event handler that waits for the DOM to load in it's entirety. – adeneo Nov 30 '15 at 22:48
  • 1
    You can place the script tags right before `

    ` if you don't want to use an event listener.

    – Dave Chen Nov 30 '15 at 22:49
  • Possible duplicate of [load and execute order of scripts](http://stackoverflow.com/q/8996852/1529630) – Oriol Nov 30 '15 at 23:19

3 Answers3

5

For what i know, javascript is loaded in line with HTML. So if you have an element <foo> and then a script that uses <foo> after that, it works. Turn them around, and the script is loaded first, after that the foo element. This way your script cannot find the element.

Change your javascript to:

function init()
{
  var formWeek = document.form1;
  var weekDays = new Array();
  weekDays = formWeek.theDay.options;

  function btnRemoveWed_onclick()
  {
    console.log("In btnRemoveWed_onclick");
  }
}

document.addEventListener('DOMContentLoaded', init, false);

this way you make sure the javascript is loaded when the DOM is ready.

Erik Terwan
  • 2,710
  • 19
  • 28
  • 1
    Better use ['DOMContentLoaded'](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded). Of course that is available only from IE9 onwards, but then again, so is `addEventListener`. – GolezTrol Nov 30 '15 at 22:48
1

When you have an inline script tag in HTML, it blocks the parsing of HTML and it is executed immediately. Anything written after it has not been parsed yet.

It's common practice to put script tags at the end of the body tag, because at that point the DOM has been parsed and JS can safely execute.

mrdommyg
  • 101
  • 5
0

As far as the error you pointed out is concerned, you can wait for the browser to finish loading the page by using something like window.onload. Notice lower in the documentation, in the Notes section

The load event fires at the end of the document loading process. At this point, all of the objects in the document are in the DOM, and all the images, scripts, links and sub-frames have finished loading.

This means by the time the code is run, your HTML has been parsed and put into the DOM. Your script tag, then, will be:

<script type="text/javascript">
    window.onload = function() {
        var formWeek = document.form1;
        var weekDays = new Array();
        weekDays = formWeek.theDay.options;
    }
    function btnRemoveWed_onclick()
    {
        console.log("In btnRemoveWed_onclick");

    }
</script>
mejdev
  • 3,509
  • 4
  • 24
  • 38