Reputation: 2706
Here's a fiddle with my problem:
I have three buttons:
<button>Button A</button>
<button>Button B</button>
<button>Button C</button>
Each button triggers some AJAX to pull data, and reacts according to the response.
If no data is returned, an error alert is displayed with a delayed fade, like so:
if ( no_data )
{
$error.show().delay(6000).fadeoutOut("slow");
}
else
{
// we have data, do some stuff
}
So if Button B returns no data and shows the alert, and I quickly click on Button C, which does have data, the error alert remains until the delay completes, which is not intended.
I tried adding a hide function to the else block:
if ( no_data )
{
$error.show().delay(6000).fadeOut("slow");
}
else
{
$error.hide(); // we don't want the alert to keep showing
// we have data, do some stuff
}
Great, so now a successful query removes the alert if it's displayed. However, if (as explained above) I click Button B, get an error (alert is triggered), then click Button C and the alert is removed ... and then I click on Button B again (quickly), the previous delay is still in the animation queue and removes the alert almost immediately.
Is there a way such that:
if ( no_data )
{
$error.show().delay(6000).fadeOut("slow");
}
else
{
// kill the previous fadeOut, then...
$error.hide();
// do other stuff
}
I've tried adding the stop function:
$error.stop(true, true).hide();
But it's still doesn't appear to work. I assume this is because there is no animation in the queue due to the delay, so the stop function never actually removes anything.
What am I doing wrong?
Upvotes: 2
Views: 80
Reputation: 471
setTimeout() and clearTimeout() can fix this:
var $a = $('#btn-a');
var $b = $('#btn-b');
var $c = $('#btn-c');
var $x = $('#alert');
var timerHandle;
$a.on('click', function (e) {
$x.show();
timerHandle = setTimeout(function () {
$x.fadeOut("slow");;
}, 6000);
});
$b.on('click', function (e) {
$x.show();
timerHandle = setTimeout(function () {
$x.fadeOut("slow");;
}, 6000);
});
$c.on('click', function (e) {
$x.hide();
clearTimeout(timerHandle);
});
Upvotes: 2
Reputation: 351
Have you tried using dequeue() to break the delay() function?
You could try something like this:
if ( no_data ){
$error.show().delay(6000).fadeOut("slow");
}else{
// kill the previous fadeOut, then...
$error.dequeue();
// do other stuff
}
In your code, it would look like this:
$c.on('click', function(e) {
$x.hide();
$x.dequeue();
});
That said, I believe it would probably be better to have a state machine where you keep track of the state of the error being displayed and only enable the buttons A, B and C when the error fadeout event has completed. You could enable the buttons when no error is shown, but when an error is detected, you disable the buttons for the 6000ms time with a setTimeout function.
Upvotes: 1