views:

272

answers:

3

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>
+3  A: 

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
Is this the standard practice or just in this case?
JMSA
Standard practice is that you start execution from the time the page loads.
Jacob Relkin
It is standard practice to run scripts only after the DOM tree has been built.
Paul Lammertsma
So it should be safe to put all scripts at the bottom always. No?
JMSA
No, the tree is only ready when the page is completely loaded. Since the `<script>` tags are part of the document, your suggestion won't suffice either. I would either take a look at a JavaScript package, or if that's overkill for your implementation, take a look at this: http://www.javascriptkit.com/dhtmltutors/domready.shtml
Paul Lammertsma
@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
+8  A: 

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
Or consider using Prototype, JQuery or some other package to handle the DOM ready event.
Paul Lammertsma
I don't think he needs to import a whole library just for the DOM ready event. ;)
Jacob Relkin
@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
+1  A: 

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
window.onload doesn't fire until the whole document has been parsed and all files downloaded
jaywon