views:

559

answers:

3

Hi all,

I'm trying to prevent clicks on a list item while an animation is occurring. So at the top of my click handler, I want to do something like this:

if(!$(this).is(:animated)) {
    // handle click code here
}

Note the 'bang' (!) in the if statement above. I haven't tested, but I assume this will work. What I'm not sure of is whether '.is(:animated)' will return true when run against an element that is being animated via fadeIn() and fadeOut(). I know that jQuery has a .animate() function, and I assume :animated certainly works against elements animated using that function, but will it work with those using fadeIn() and fadeOut()? Thanks.

UPDATE: After some dramatic mis-posts, all seems well, and thanks to the reponders for all the great follow-ups and edits. In the end, I have found that, yes, :animated matches those elements animated using fadeIn() and fadeOut() because the jQuery source uses .animate() to achieve these effects. My final check was as originally posted:

if(!$(this).is(:animated)) {
    // handle click code here
}

..rather than using .not() as has been proposed in some instances (though I believe these will work as currently posted). Thanks again.

+2  A: 

:animate will match elements which have had fadeOut called.

If you look in the jQuery source, you'll see that fadeOut simply calls animate.
It's defined like this:

// Generate shortcuts for custom animations
jQuery.each({
    slideDown: genFx("show", 1),
    slideUp: genFx("hide", 1),
    slideToggle: genFx("toggle", 1),
    fadeIn: { opacity: "show" },
    fadeOut: { opacity: "hide" }
}, function( name, props ){
    jQuery.fn[ name ] = function( speed, callback ){
     return this.animate( props, speed, callback );
    };
});
SLaks
Did not know that fadeIn and fadeOut used animate(). Thanks for the info.
Mega Matt
A: 

Yes, :animated will return true for any sort of animation that jQuery creates. It will also do it for any plugins that animate provided they use the jQuery animate function.

However, you can write your code just a pinch differently to make use of jQuery:

Edit The not function is not the opposite of is. It filters out nodes, but still returns a jQuery object which evaluates to true. To use the not function as I originally suggested, you would have to add .length to the test:

if( $(this).not(':animated').length ) {
    // Handle click code here
}

Otherwise, use the function as the OP originally posted:

if( !$(this).is(':animated')) {
    // Handle click code here
}
Doug Neiner
Ah, good to know. Was not aware of the 'not' function. Thanks for the response.
Mega Matt
you can also do if (!$(this).is(':not(:animated)')) { //handle click code }
PetersenDidIt
@petersendidit So your code says: "If not `this` is not animated". So... if it _is_ animated ;) Think you left an extra `!` in there, but I get your point. Very good to know.
Doug Neiner
@dcneiner, @petersendidit Just logged on to report that the 'not' is not the opposite of 'is' as dcneiner had posted, but I see you all already beat me to :) Wish I would have logged on a little sooner because I had a *hell* of a time not understanding what was going on for a while. But as stated, !$(this).is(':animated'); works best for my purposes, so that's the way I left it. And it works fine with the fadeIn() and fadeOut(). Beats the hell out of killing and reconnecting live click events, which is what I was doing. Thanks again for the responses.
Mega Matt
@Mega Matt, I felt horrible already.. now I feel worse! :) I wish there was a SO instant message system.
Doug Neiner
Process Improvement? :) Moderators?! I'm down.
Mega Matt
A: 

You don't need to have the if statement in there at all. You can chain the .not(':animated') before your 'click code'.

As an example, these fades would only work if the div wasn't in the process of being animated, therefore getting rid of the nasty queue problem.

$('a#show_me').toggle(function() {
    $('div#the_money').not(':animated').fadeIn();
}, function() {
    $('div#the_money').not(':animated').fadeOut();
});

It would work the same for the .click() as well.

Erik