Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why doesn't this code loop?

Tags:

jquery

var fadeCounter = 0;

function fadeNext() {
  window.fadeCounter++;
  s = '#slide' + window.fadeCounter;
  $(s).fadeIn(1000,fadeNext);
  //forgive typos above, code works, what doesn't:
  if (window.fadeCounter == 8) window.fadeCounter = 0;
  //code will loop up to 8, then stop. why?
}

//initiate loop
fadeNext();

edit:

Demo added, at http://jsfiddle.net/AXRBh/2/ In demo, loop should reset at 20 but halts. Why?

like image 875
Teson Avatar asked Sep 26 '26 03:09

Teson


2 Answers

If fadeCounter is not declared in global scope, it will not work. Make sure you define the variable outside the document.ready handler (or remove window.).

The function does keep calling itself (only one time, see next paragraph) but you don't see the effect. After the first "loop" all the elements are visible so calling a second time fadeIn on them has no effect.

Because they are already visible, the fadeIn callback is fired immediately, making the function act in a weird way: http://jsfiddle.net/fkling/nZ7Mn/
In this case, the next fadeNext passed as callback is executed before the counter is reset:

  // s is already visible, so `fadeNext` is called immediately
  $(s).fadeIn(1000,fadeNext);
  // only after that the timer is reset (too late)
  if (window.fadeCounter == 8) window.fadeCounter = 0;

As there is not element with ID #slide9, calling fadeIn on it has no effect and the recursion stops.

As @Cybernate already noted, reversing the order of these two statements fixes the issue. However, you still won't see the effect as the elements are already visible. You just keep unnecessarily calling the function in a rapid way, which might even crash the browser.

So in order to make it working properly you should hide the elements again. Here is a bit cleaner version:

var max = 4;

function fadeNext(i) {
  i = i % max;
  $('body').append('<div>Current counter: ' + i + '</div>');
   $('#s' + i).fadeIn(1000,function() {
       $(this).fadeOut(1000, function(){fadeNext(i + 1)});
   });                                      
}

//initiate loop
fadeNext(0);

Instead of having the function accessing and changing a global variable (which can lead to some kind of "race condition" as you already experienced), pass the next index as parameter to the function.

DEMO

The big question is: What do you actually want to achieve?

like image 70
Felix Kling Avatar answered Sep 28 '26 15:09

Felix Kling


Move the counter reset right after the slide id.

var fadeCounter = 0;

function fadeNext() {
  window.fadeCounter++;
  s = '#slide' + window.fadeCounter;
  if (window.fadeCounter == 8) window.fadeCounter = 0;
  $(s).fadeIn(1000,fadeNext);
  //forgive typos above, code works, what doesn't:

  //code will loop up to 8, then stop. why?
}

//initiate loop
fadeNext();
like image 42
Chandu Avatar answered Sep 28 '26 16:09

Chandu