41

Why does refButton get null in the following JavaScript code?

<html>
<head>
    <title></title>
    <script type="text/javascript">
        var refButton = document.getElementById("btnButton");

        refButton.onclick = function() {
            alert('I am clicked!');
        };
    </script>
</head>
<body>
    <form id="form1">
    <div>
        <input id="btnButton" type="button" value="Click me"/>
    </div>
    </form>
</body>
</html>
user366312
  • 16,949
  • 65
  • 235
  • 452

3 Answers3

84

At the point you are calling your function, the rest of the page has not rendered and so the element is not in existence at that point. Try calling your function on window.onload maybe. Something like this:

<html>
<head>
    <title></title>
    <script type="text/javascript">
        window.onload = function(){
           var refButton = document.getElementById("btnButton");

            refButton.onclick = function() {
                alert('I am clicked!');
            }
        };
    </script>
</head>
<body>
    <form id="form1">
    <div>
        <input id="btnButton" type="button" value="Click me"/>
    </div>
    </form>
</body>
</html>
jaywon
  • 8,164
  • 10
  • 39
  • 47
  • 3
    Or consider using Prototype, JQuery or some other package to handle the DOM ready event. – Paul Lammertsma Dec 02 '09 at 00:29
  • 5
    I don't think he needs to import a whole library just for the DOM ready event. ;) – Jacob Relkin Dec 02 '09 at 00:33
  • 1
    @Paul - good point. @JMSA the DOM ready event actually fires BEFORE all images are downloaded and AFTER all scripts and the page has been downloaded. Therefore, the DOM ready event fires before the window.onload event. :) – jaywon Dec 02 '09 at 00:34
16

You need to put the JavaScript at the end of the body tag.

It doesn't find it because it's not in the DOM yet!

You can also wrap it in the onload event handler like this:

window.onload = function() {
var refButton = document.getElementById( 'btnButton' );
refButton.onclick = function() {
   alert( 'I am clicked!' );
}
}
Jacob Relkin
  • 161,348
  • 33
  • 346
  • 320
  • Is this the standard practice or just in this case? – user366312 Dec 02 '09 at 00:30
  • Standard practice is that you start execution from the time the page loads. – Jacob Relkin Dec 02 '09 at 00:32
  • It is standard practice to run scripts only after the DOM tree has been built. – Paul Lammertsma Dec 02 '09 at 00:32
  • So it should be safe to put all scripts at the bottom always. No? – user366312 Dec 02 '09 at 00:33
  • 1
    No, the tree is only ready when the page is completely loaded. Since the ` – Paul Lammertsma Dec 02 '09 at 00:38
  • 1
    @JMSA - Not necessarily. It all depends on what you need it to do, and how far along in the entire rendering process the page is. attaching to the window.onload event will assure that all files included in the page(CSS, JS, images) have been downloaded. if you know you only need the HTML rendered above your script tags that certainly works, but probably better to attach to events and know what those events mean. – jaywon Dec 02 '09 at 00:41
5

Because when the script executes the browser has not yet parsed the <body>, so it does not know that there is an element with the specified id.

Try this instead:

<html>
<head>
    <title></title>
    <script type="text/javascript">
        window.onload = (function () {
            var refButton = document.getElementById("btnButton");

            refButton.onclick = function() {
                alert('Dhoor shala!');
            };
        });
    </script>
    </head>
<body>
    <form id="form1">
    <div>
        <input id="btnButton" type="button" value="Click me"/>
    </div>
</form>
</body>
</html>

Note that you may as well use addEventListener instead of window.onload = ... to make that function only execute after the whole document has been parsed.

Bruno Reis
  • 37,201
  • 11
  • 119
  • 156
  • 2
    window.onload doesn't fire until the whole document has been parsed and all files downloaded – jaywon Dec 02 '09 at 00:36