3

I am trying to rotate an image using javascript and I was trying some code I found on adobes website that does what I was looking for. When I run it it gives me the error: Uncaught TypeError: Cannot set property 'src' of null

It keeps repeating every 5 second interval which is the amount of time between each image

Here is the javascript:

 (function () {
        var rotator = document.getElementById('rotator');  // change to match image ID
        var imageDir = 'images/';                          // change to match images folder
        var delayInSeconds = 5;                            // set number of seconds delay
        // list image names
        var images = ['image2.jpg', 'image3.jpg', 'image4.jpg', 'image1.jpg'];

        // don't change below this line
        var num = 0;
        var changeImage = function () {
            var len = images.length;
            rotator.src = imageDir + images[num++];
            if (num == len) {
                num = 0;
            }
        };
        setInterval(changeImage, delayInSeconds * 1000);
    })();

and here is the html for the image:

<img src="images/image1.jpg" alt="rotating image" width="400" height="300" id="rotator" />

It shows the image1.jpg, but does not rotate it. Is there something blatantly obvious that I am not seeing? Wouldn't surprise me!

Thanks to anyone that can offer advice.

Joe W
  • 1,567
  • 6
  • 23
  • 36
  • 1
    Where's the script? You may be encountering this if it is in the `head`. – acdcjunior Jun 21 '13 at 13:58
  • Try passing rotator in your private function in changeImage. – SenorAmor Jun 21 '13 at 13:58
  • it is in the head in the tags – Joe W Jun 21 '13 at 13:59
  • 4
    You need to wait for the DOM to be ready before you try and access elements. So, since your code's in the head, and is executed immediately, it tries to look for the `#rotator` element (in the body), which hasn't even been rendered yet, so the result of `document.getElementById("rotator")` is `null`, so of course you can't set the `src` property of `null` – Ian Jun 21 '13 at 14:01
  • 2
    Its trying to find an element with id `rotator` but it doesn't exist yet. Wrap it in a document ready event or run it after it has rendered – DickieBoy Jun 21 '13 at 14:01
  • Is the DOM ready/loaded when this code runs? – Elias Van Ootegem Jun 21 '13 at 14:02
  • @JoeW at that point the img object doesn't exist yet. Maybe you can move the script as the last element just before the – HMR Jun 21 '13 at 14:02

4 Answers4

7

When in the head (look at the console):

http://jsfiddle.net/m2wce/

This happens because you are declaring the closure and executing right away. When you execute it in the head, the DOM is not ready (in other words, the HTML below still hasn't been "mounted" by the browser, as it processes the page sequencially, from top to botto) and at the time of the execution the img tag does not yet exist (because it is down below in the HTML page).

When in the body, after the referenced img, it works:

http://jsfiddle.net/m2wce/1/

acdcjunior
  • 132,397
  • 37
  • 331
  • 304
  • 1
    It may be clearer here, **look at the console**: (1) Code in `head` - before the `img` - not working: http://jsbin.com/ificir/2/edit and (2) code after the `img` - working: http://jsbin.com/ovuhet/2/edit . – acdcjunior Jun 21 '13 at 14:29
  • 2
    Your answer saved me from 3 days of agony. Mentioning that 'DOM must be ready' was very vital in this answer. This is something I was not even aware of. and struggled with for 3 days. Thank you for this good answer. – Joseph Apr 12 '19 at 09:08
2

You need to place this code after your dom gets ready. i.e inside $(document).ready() or on window.onload. as:

window.onload=function(){
(function () {
    var rotator = document.getElementById('rotator');  // change to match image ID
    var imageDir = 'images/';                          // change to match images folder
    var delayInSeconds = 5;                            // set number of seconds delay
    // list image names
    var images = ['image2.jpg', 'image3.jpg', 'image4.jpg', 'image1.jpg'];

    // don't change below this line
    var num = 0;
    var changeImage = function () {
        var len = images.length;
        rotator.src = imageDir + images[num++];
        if (num == len) {
            num = 0;
        }
    };
    setInterval(changeImage, delayInSeconds * 1000);
})();

If you place that code inside anynomous function inside head (as you did), then it will not be able to load that image element from Dom because Dom would not be fully loaded at that time.

Sanjeev Rai
  • 6,721
  • 4
  • 23
  • 33
1

Your script is loaded before the body of your page, so the rotator element is not found. Remove the var rotator = ... line and put it inside the changeImage function instead:

(function () {
    var rotator;
    var rotatedImageId = 'rotator';           // change to match your HTML
    var imageDir = 'images/';
    var delayInSeconds = 5;
    // list image names
    var images = ['image2.jpg', 'image3.jpg', 'image4.jpg', 'image1.jpg'];

    // don't change below this line
    var num = 0;
    var changeImage = function () {
        if (!rotator)
            rotator = document.getElementById(rotatedImageId);
        if (!rotator)
            return;

        var len = images.length;
        rotator.src = imageDir + images[num++];
        if (num == len) {
            num = 0;
        }
    };
    setInterval(changeImage, delayInSeconds * 1000);
})();
bdesham
  • 15,430
  • 13
  • 79
  • 123
  • if you're going to do it like that, would be better as `var rotator; .... if (!rotator) { rotator = document.getElementById('rotator'); if (!rotator) { return; } }` type-thing. – AD7six Jun 21 '13 at 14:05
  • @AD7six Great suggestion, thank you. I've added that piece to my answer. – bdesham Jun 21 '13 at 14:09
-1

I met this problems too.You can make document.getElementById(rotatedImageId) before you use that function. Another word,you can define rotator to gobal. This is how i solved this problem.

Liam
  • 27,717
  • 28
  • 128
  • 190
GoodBoyth
  • 1
  • 1