Ilan Biala
Ilan Biala

Reputation: 3417

Uncaught TypeError cannot set property 'src' of null

So on my new website in google chrome, I am trying to make the images switch every 5 seconds using a setInterval function. This seems to work, however I have the problem cannot set property src of null.

var images = new Array();
images[0] = "/images/grilled-chicken-large.png";
images[1] = "/images/sizzly-steak.png";
var img = document.getElementById("img");

function changeImage() {
     for (var i = 0; i < 3; i++) {
        img.src = images[i];
        if (i == 2){i = i - 2;};
     }
}

window.onload=setInterval("changeImage()", 5000);

I know the problem is that I am trying to get the element with an id of img before the page is done loading, but I've already got a window.onload, so i don't know what to do. Also, if i make an init() function containing the setInterval and the img variable, the page freezes.

Any ideas?

Upvotes: 1

Views: 22195

Answers (4)

Yogu
Yogu

Reputation: 9445

The problem is that you access element 2 of an array with only two elements (0 and 1).

But there is also a logical error in your script: Where do you store the index of the currently visible image? You need a global variable which holds that index.

var currentIndex = 0;
function changeImage() {
    // Switch currentIndex in a loop
    currentIndex++;
    if (currentIndex >= images.length)
        currentIndex = 0;

    var img = document.getElementById("img");
    img.src = images[currentIndex];
}

document.onload = function() {
    setInterval(changeImage, 5000);
}

I've moved the img variable into the function so that it is assigned after five seconds when the document has loaded.

Just to clear things up: JavaScript is an event-based programming language. That means that the slideshow-change code is executed every time the interval fires, does some work (switch to the next slide) and then is done, so that the browser can render the page. If you iterate through the slides in a loop, there is no way for the browser to show the new slide because the script is still executing between the slides. The solution is what I've posted: Define a global variable that replaces the loop variable, and increment it every time the next slide is to be shown.

Upvotes: 3

spaceman12
spaceman12

Reputation: 1109

function changeImage() 
{
    for (var i = 0; i < 2; i++) 
    {
        img.src = images[i];
     }
}


window.onload=function()
{
    setInterval(changeImage,5000);
}

Your last line in the for loop is completely useless and just complicate things, Also, Your way of setting a window onload event is not standard!

EDIT: the src property is null because , obviously, your array size is only 2!!

Upvotes: 0

Nicolas Stamm
Nicolas Stamm

Reputation: 123

Your for loop looks odd. Try that loop:

function changeImage(){
  if(!img.attributes["index"]){img.attributes["index"]=0;return;};
  img.attributes["index"]++;
  img.src=images[img.attributes["index"]];
}
window.onload=function(){
  window.img=document.getElementById("img");
  setInterval("changeImage()",5000)
}

Should work.
You'll notice that I store the image index in an attribute of the image, as opposed to a global variable. I think the global is slightly faster, but storing it in the image means you can easily expand this to multiple images if needed. Also, the problem with your browser freezing was that the following code:

for(var i=0;i<3;i++){
  //Some more stuff
  if(i==2){i-=2};
}

This loop is infinite, because whenever i reaches 2, i==2 becomes true, which means that iteration will reset i to 0 and start it all over again. The only way to prevent that would be a break; somewhere, which I don't see anywhere. Tip: It is generally a bad idea to tamper with the index variable in for loops.

Upvotes: 0

Šime Vidas
Šime Vidas

Reputation: 185893

Here:

window.onload = function () {

    var images = [
        'http://placekitten.com/100/200',
        'http://placekitten.com/200/100',
    ];

    var img = document.getElementById( 'img' );

    setInterval(function () {
        img.src = img.src === images[0] ? images[1] : images[0];
    }, 1000 );

};

Live demo: http://jsfiddle.net/wkqpr/


If you have more than two images, you can do this:

window.onload = function () {

    var images = [
        'http://placekitten.com/100/200',
        'http://placekitten.com/200/100',
        'http://placekitten.com/200/150',
        'http://placekitten.com/150/300'
    ];

    images.current = 0;

    var img = document.getElementById( 'img' );

    setInterval(function () {
        img.src = images[ images.current++ ];
        if ( images.current === images.length ) images.current = 0;       
    }, 1000 );

};

Live demo: http://jsfiddle.net/wkqpr/1/

Upvotes: 1

Related Questions