Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does jQuery fadeIn() not work when used after an interrupting fadeOut()?

Tags:

jquery

I have something I want to fade in when the user does something. I want to fade it out when an event occurs. If the user does something, I want to fade it back in again (and again, fade it out when an event occurs).

Take a look at my jsFiddle for an example. In this scenario, I want to fade in the "fadeP" tag when the user clicks "Click Me". I have a setTimeout to fade it out again (instead of my event listener). The timeout will fire before the fadeIn completes. It will stop the fadeIn (also clearing the animation queue) and fadeOut. If a user clicks "Click Me" again (potentially before the fadeOut completes), I want to fade the "fadeP" tag back in.

Click "Click Me" several times (either allowing time for the element to appear and dissapear or not, it doesn't seem to make a difference). Each time, the fadeIn fades the element in slightly less. I want it to fade the element in just as much each time the user clicks.

It's something to do with the stop(). It seems to remember that at the point the fadeIn was stopped, it had a certain opacity, and considers this opacity to be the completely faded in opacity. When you come to fadeIn again, it fades to the "remembered" opacity, but doesn't get there, because it is stoped, which causes it to remember that opacity as the completely faded in opacity and so on.

I need it to stop fadeIn when an event fires and fadeOut. I need it to stop fadeOut when an event fires and fadeIn. I need fadeIn to attempt to fade to the same opacity each time. Any ideas?

like image 402
Spycho Avatar asked Jun 15 '11 09:06

Spycho


1 Answers

You are right. You can track this in firebug. At the end of fade out, he sets the opacity back to the value he started from and also display: none. You can workaround this with setting opacity back to 1 or even better to '' (for IE) when fadeOut is completed.

fadeP = $('#fadeP');
clickMe = $('#clickMe');

clickMe.click(function(){
    fadeP.stop(true).fadeIn(1000);
    setTimeout(function(){
        fadeP.stop(true).fadeOut('300', function() {
            $(this).css('opacity', '');
        });
    }, 500);
});

Updated fiddle

EDIT

I've modified the code to work with your comment. You could animate the opacity by yourself to start from the current value.

fadeP = $('#fadeP');
clickMe = $('#clickMe');

clickMe.click(function(){
    var currentOpacity = fadeP.css('opacity');
    fadeP.stop(true).show().css('opacity', (currentOpacity  < 1) ? currentOpacity  : 0 ).animate({opacity: 1});
    setTimeout(function(){
        fadeP.stop(true).fadeOut(5000, function() {
            $(this).css('opacity', '');
        });
    }, 500);
});

fiddle

EDIT 2

The final solution in collaboration with the OP ;-)

clickMe.click(function(){
    if(fadeP.css('display') == 'none') fadeP.css('opacity', '0');
    fadeP.stop(true).show().animate({opacity: 1}, 1000, function () { $(this).css('opacity', ''); } );
    setTimeout(function(){
        fadeP.stop(true).fadeOut(1000);
    }, 500);
});

fiddle

like image 102
DanielB Avatar answered Nov 14 '22 21:11

DanielB