2

I'm fairly new to JavaScript/jQuery, but have made a script to change the background picture.

First Script

The first script version works fine and does the following:

  • creates a setInterval timer that calls function backgroundChange() to run every 7 seconds
  • decides the next picture URL
  • sets the background picture

This works great, but the problem is when the website is live, on a slow connection the background picture doesn't load in time for the next timer change.

New Script

So the new version:

  • creates a setTimeout timer that calls function backgroundChange() to run after 7 seconds

var theTimer = setTimeout(backgroundChange, 7000);

  • clearsTimeout (surely I shouldn't have to run this?)

window.clearTimeout(theTimer);

  • decides the next picture URL
  • waits until the picture is loaded:
  • then sets the background picture
  • then adds a new setTimeout timer

$('#testImage').attr('src', imageText).load(function() {

    $('#backgroundTop').fadeIn(timeIn,function() 
    {
         theTimer = setTimeout(backgroundTimer, 7000);
    });

});

The problem is that the timer now seems to be called double the amount of times whenever the timer runs and exists in the .load function.

I havent purposely not posted my code yet, as I want to make sure my understanding is correct first, rather than someone just fixing my code.

Ta very much.

user1994620
  • 33
  • 1
  • 3
  • You won't have to `clearTimeout(theTimer)` inside `backgroundChange`; the timer has already fired (thats why you're executing `backgroundChange`!) so it's a noop. – Matt Jan 20 '13 at 13:57
  • Please post your code. It is impossible to definitively answer your question otherwise. – Asad Saeeduddin Jan 20 '13 at 14:01

2 Answers2

3

Instead of unbinding, you could use a JavaScript closure for the timer function. This will maintain a single timer that is reset every time it is called.

var slideTimer = (function(){
      var timer = 0;

      // Because the inner function is bound to the slideTimer variable,
      // it will remain in score and will allow the timer variable to be manipulated.

      return function(callback, ms){
           clearTimeout (timer);
           timer = setTimeout(callback, ms);
      };  
})();

Then in your code:

$('#testImage').attr('src', imageText).load(function() {

    $('#backgroundTop').fadeIn(timeIn,function() 
    {
         slideTimer(backgroundTimer, 7000);
    });
});

There should be no need to clear or set the timer anywhere else in your code.

PassKit
  • 12,231
  • 5
  • 57
  • 75
2

You need to unbind the load handler before you add the next one, since they keep piling up as your code stands. With every iteration, you add an extra handler that does the exact same thing. Use unbind to remove the old handler before you reattach:

$('#testImage').unbind('load');
Asad Saeeduddin
  • 46,193
  • 6
  • 90
  • 139