0

Here is a JSFiddle example of the problem.

When I click the button everything fades as expected and returns in 3 seconds or until cliked. However, if I do not wait the 3 seconds but click it early and then quickly click the button it returns in less than 3 seconds.

EDIT: a better explanation of the problem: In the JSFiddle, click the green button, click the open space to stop the fade, and then click the green button again (this all has to be done quickly). The elements fade back in way too quickly.

Thanks Katana314

var waiting;

function startNext() {
  $(document).off('click');
  window.clearTimeout(waiting);
  $('#correctT, #correctP').fadeOut('fast', function() {
    $('#button1, #button2, #button3, #button4, #title, #image, #ame').fadeIn('slow');


  })

}
$('#button1, #button2, #button3, #button4').click(function(e) {


  $('#button1, #button2, #button3, #button4, #title, #image, #ame').fadeOut('fast', function() {


    $('#button1, #button2, #button3, #button4, #title, #image, #ame').hide();
    $('#correctT, #correctP').fadeIn('fast');

    $(document).click(startNext);

    waiting = setTimeout(startNext, 2500);
  });
});
  • Please, be more especific!, The code looks good – Fabian Sierra Aug 26 '16 at 20:45
  • 4
    don't delete and re-ask questions... that's really annoying(and will get you closer to a question ban quicker). you still haven't clarified the question. – Kevin B Aug 26 '16 at 20:46
  • 1
    tldr if you click the button more than once before it has chance to fade, you're going to start two intervals, one of which can't be stopped, which is going to cause weirdness. – Kevin B Aug 26 '16 at 20:49
  • @KevinB Is it a problem if I can understand it? In the JSFiddle, click the green button, click the open space to stop the fade, and then click the green button again (this all has to be done quickly). The elements fade back in way too quickly, and on a quick glance I do not know why. – Katana314 Aug 26 '16 at 20:49
  • question made sense to me and i was able to duplicate it... – Robert Parham Aug 26 '16 at 20:50
  • Sorry, please do this @FabianSierra click one of the buttons, then quickly click the page so that the buttons re appear, then quickly click one of the buttons again and then wait. You will see that the animation takes place after waiting less than 3 seconds. – Rache Riveto Aug 26 '16 at 20:50
  • right, if you do *anything* before the fadeout completes, it's not going to work correctly because you're relying on the fade out to complete before starting the timeout, so there's no timeout for it to clear.. – Kevin B Aug 26 '16 at 20:51

2 Answers2

2

The root of your problem is here:

$('#button1, #button2, #button3, #button4, #title, #image, #ame').fadeOut('fast', function() {


    $('#button1, #button2, #button3, #button4, #title, #image, #ame').hide();
    $('#correctT, #correctP').fadeIn('fast');

    $(document).click(startNext);

    waiting = setTimeout(startNext, 2500);
    console.log("started timer:" + waiting );
});

If you run this and look at your console what do you see? You see that you are starting not one, but 7 timers. Your fadeOut handler will be called for each of your elements. So you start 7 timers, but waiting only has the id of the last timer started. So the other 6 are still running. Robert's answer above avoids that problem by not starting another timer if one is already set and that works. A cleaner solution would be to wait for all the animations to be done. For example, see here:

jQuery wait till all page animations are done

So something like this ought to work:

$('#button1, #button2, #button3, #button4, #title, #image, #ame').fadeOut('fast').promise().done(function() {


    $('#button1, #button2, #button3, #button4, #title, #image, #ame').hide();
    $('#correctT, #correctP').fadeIn('fast');

    $(document).click(startNext);

    waiting = setTimeout(startNext, 2500);
    console.log("started timer:" + waiting);
});
Community
  • 1
  • 1
Matt Burland
  • 44,552
  • 18
  • 99
  • 171
  • +1 good catch... i didn't care to investigate further.. made an assumption and tested it. I wil update my answer with a more appropriate fix.. – Robert Parham Aug 26 '16 at 21:08
-1

https://jsfiddle.net/1dmjvon3/3/

take care of your timeout ids...

if(waiting!==null){
    window.clearTimeout(waiting);
    waiting = null;
}

also

if(waiting===null) waiting = setTimeout(startNext, 2500);

A more appropriate solution is to assign a class name to each of the elements in your selector and use the classname as the selector so the function doesn't fire seven times.

Here's another fiddle: https://jsfiddle.net/1dmjvon3/

Robert Parham
  • 704
  • 3
  • 10
  • 2
    this is not necessary. – Kevin B Aug 26 '16 at 20:53
  • 1
    yes it is. it fixes the problem. somehow the settimeout is being called more than once. this will cause it to ignore subsequent calls. why dont you try it before you downvote.. go ahead, i'll wait... – Robert Parham Aug 26 '16 at 20:55
  • I honestly didn't think this was a necessary fix when I saw it, but I pasted it into the JSFiddle and it fixed the problem perfectly. The votes currently being thrown around are making the reality of this question and answer very difficult to see correctly; this really is the solution. – Katana314 Aug 26 '16 at 20:56
  • @Katana314 yes, i know :) if this helped please hit the little check mark for me. godspeed :) – Robert Parham Aug 26 '16 at 20:57
  • 1
    Clearing an already cleared (or otherwise invalid) timer id will have no effect whatsoever, so the first check shouldn't be necessary at all. The second piece however is a good idea. It's always good to check if a timeout is still running before starting another one. – Matt Burland Aug 26 '16 at 20:59
  • @MattBurland I would agree about the effects of the second check being good, but when I did my test, I only clicked three times total, so I don't think that this was a case of accepting extra clicks during a fade. As I already said, I don't totally follow the logic of this answer but based on actual testing it DOES work. The hypothesis should follow the results, not the other way around. – Katana314 Aug 26 '16 at 21:01
  • you may have forgotten to click "Save" in jsfiddle. but even so, using a class still results in multiple elements being selected, [thus still causing multiple callbacks](http://stackoverflow.com/questions/8790752/callback-of-animate-gets-called-twice-jquery/8791175#8791175). – Kevin B Aug 26 '16 at 21:17