8

I have the following code, which basically toggles through a bunch of images.

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript">
            var num = 1;
            img = document.getElementsByTagName("img")[0];
            hbutton = document.getElementsByTagName("h1")[0];
            hbutton.onclick = function() {
                num += 1;
                img.src = num + ".jpg";
            }
        </script>
    </head>
    <body>
        <h1>Press Here!</h1>
        <img src = "1.jpg"></img>
    </body>
</html>

For some reason, when I run it, nothing happens, because of the following error as displayed by my Firebug console.

    hbutton is undefined    
---
    hbutton.onclick = function() {

When I run just the JS after the page has loaded however, it works perfectly fine!!! Why is this?

Bobby Tables
  • 1,104
  • 4
  • 15
  • 23
  • It's not odd, it's expected... I have updated the title with real symptoms. Look for questions relating to `getElementById` and `undefined`. It's the same idea. –  May 29 '12 at 21:52
  • Whoops, it's slightly different with `getElementById` (look for ["getElementById null"](http://stackoverflow.com/search?q=getelementbyid+null)). In this case there is undefined because `getElementsByTagName` returns an empty array[-like] object so `emptyArray[0]` results in `undefined`. In any case, see other question. –  May 29 '12 at 21:58
  • possible duplicate of [getElementById() returns null even though the element exists](http://stackoverflow.com/questions/5371047/getelementbyid-returns-null-even-though-the-element-exists) –  May 29 '12 at 21:58
  • Possible duplicate of [Why does jQuery or a DOM method such as getElementById not find the element?](http://stackoverflow.com/questions/14028959/why-does-jquery-or-a-dom-method-such-as-getelementbyid-not-find-the-element) – Michał Perłakowski Jan 20 '16 at 09:49

5 Answers5

16

Your code is executing before the h1 tag is defined. You must run it in an onload handler or put it just before /body

Julian
  • 2,729
  • 19
  • 30
  • 1
    To be more specific, `document.getElementsByTagName("h1")[0]` is returning `undefined` because as @Julian said, the tag doesn't exist when the code is run. The error comes when you try to set `onclick` on `undefined`. – Aren May 29 '12 at 21:51
2

JavaScript is interpreted top-to-bottom. So at the place where your <script> executes, no h1 tags are known yet.

Try putting the <script>-Tag to the bottom of your page. Otherwise, if you need the script at the beginning of the page, an onLoad-Handler might help:

<script type="text/javascript">
    function onLoadHandler() {
         // your original javascript code here...
    }
</script> 
<body onload="onloadHandler()">
<!-- HTML Code here-->
Lukx
  • 1,243
  • 2
  • 11
  • 20
1

When you put it in the header, your h1 is not loaded yet. hbutton becomes undefined, not an object. Then when you try to set .onclick, it breaks because you cant set properties of something undefined. When you put the code in the body, your h1 is already loaded, so the code works as you expected it to.

You can fix this by leaving your code at the top, but only calling it after an onload event.

Joel
  • 1,072
  • 1
  • 9
  • 15
1

The head gets executed before the dom is loaded. Put it on the button of the page or put an onload function in the body tag.

It cannot find document.getElementsByTagName("img") when the Document isnt ready yet, because it is simply not there yet.

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript">
          function onDocumentReady(){
            var num = 1;
            img = document.getElementsByTagName("img")[0];
            hbutton = document.getElementsByTagName("h1")[0];
            hbutton.onclick = function() {
                num += 1;
                img.src = num + ".jpg";
            }
          }  
        </script>
    </head>
    <body onload="onDocumentReady()">
        <h1>Press Here!</h1>
        <img src = "1.jpg"></img>
    </body>
</html>

or simply do this:

<!DOCTYPE html>
<html>
    <head></head>
    <body>
        <h1>Press Here!</h1>
        <img src = "1.jpg"></img>
        <script type="text/javascript">
            var num = 1;
            img = document.getElementsByTagName("img")[0];
            hbutton = document.getElementsByTagName("h1")[0];
            hbutton.onclick = function() {
                num += 1;
                img.src = num + ".jpg";
            }
        </script>
    </body>
</html>
Michael Koper
  • 8,866
  • 6
  • 40
  • 56
0

The problem is that the script is being executed immediately it is encountered during page load.

Since it's at the top of the page, in the header, this means that it is executed before the page has loaded the <h1> element (or any of the rest of the body).

Therefore, when it asks for getElementsByTagName('h1'), there aren't any matching elements at that moment in time.

You need to either: * move the code to the end of the script. * or wrap it in a function, and trigger the function to execute when the page has finished loading -- ie use the onload method.

Spudley
  • 157,081
  • 38
  • 222
  • 293