jQuery: Can I call delay() between addClass() and such?
Asked Answered
T

11

193

Something as simple as:

$("#div").addClass("error").delay(1000).removeClass("error");

doesn't seem to work. What would be the easiest alternative?

Timms answered 24/3, 2010 at 17:46 Comment(1)
wanted to do exactly the same thing. It would be cool to call $("#div").addClassTemporarily("error",1000)Iover
W
391

You can create a new queue item to do your removing of the class:

$("#div").addClass("error").delay(1000).queue(function(next){
    $(this).removeClass("error");
    next();
});

Or using the dequeue method:

$("#div").addClass("error").delay(1000).queue(function(){
    $(this).removeClass("error").dequeue();
});

The reason you need to call next or dequeue is to let jQuery know that you are done with this queued item and that it should move on to the next one.

Wilkie answered 24/3, 2010 at 18:5 Comment(3)
I like this option because it makes it easy to pass a reference to the jquery object thats used in the queued function, so it can be used in a more generic context (without hard coded names).Champerty
Why do we need "next"? Can we do $("#div").addClass("error").delay(1000).queue(function(){ $(this).removeClass("error"); }); Seems more elegant?Humiliation
@Humiliation You don't need to pass a 'next' queue item. You may choose to use the dequeue() method instead: api.jquery.com/dequeueCleat
O
53

AFAIK the delay method only works for numeric CSS modifications.

For other purposes JavaScript comes with a setTimeout method:

window.setTimeout(function(){$("#div").removeClass("error");}, 1000);
Olivaolivaceous answered 24/3, 2010 at 17:52 Comment(4)
+1: Don't use Jquery for Jquery's sake. There are simple javascript solutions to many problems.Congruent
+1: Just the same as first comment. Simple JS also works fine some times.Centrifugate
+1 for simplicity, but also +1'ed the accepted answer - as it pointed me out that the .queue() actually passes continuation object that must be called manually (the 'next()'). I've spent half of hour wondering why my chain of parameterless callbacks execute only the first one -- many examples on other sites use a single delay in chain and a parameterless callback, which is a bit misleading oversimplification of that mechanismKingsly
Just a pedant note: setTimeout comes from the browser's window object (BOM). JavaScript (understood as ECMA Script) doesn't have that method.Grose
I
11

I know this this is a very old post but I've combined a few of the answers into a jQuery wrapper function that supports chaining. Hope it benefits someone:

$.fn.queueAddClass = function(className) {
    this.queue('fx', function(next) {
        $(this).addClass(className);
        next();
    });
    return this;
};

And here's a removeClass wrapper:

$.fn.queueRemoveClass = function(className) {
    this.queue('fx', function(next) {
        $(this).removeClass(className);
        next();
    });
    return this;
};

Now you can do stuff like this - wait 1sec, add .error, wait 3secs, remove .error:

$('#div').delay(1000).queueAddClass('error').delay(2000).queueRemoveClass('error');

Irruption answered 17/8, 2016 at 1:31 Comment(1)
Very helpful! Thank you!Raquelraquela
T
6

jQuery's CSS manipulation isn't queued, but you can make it executed inside the 'fx' queue by doing:

$('#div').delay(1000).queue('fx', function() { $(this).removeClass('error'); });

Quite same thing as calling setTimeout but uses jQuery's queue mecanism instead.

Tinct answered 23/12, 2014 at 15:23 Comment(1)
This works for me better then accepted answer (calls not repeats if there is a transition transformation in class).Polemic
C
6

Of course it would be more simple if you extend jQuery like this:

$.fn.addClassDelay = function(className,delay) {
    var $addClassDelayElement = $(this), $addClassName = className;
    $addClassDelayElement.addClass($addClassName);
    setTimeout(function(){
        $addClassDelayElement.removeClass($addClassName);
    },delay);
};

after that you can use this function like addClass:

$('div').addClassDelay('clicked',1000);
Crist answered 11/5, 2016 at 21:20 Comment(1)
and if you want to add chaining support, read te basics about plugin creation, or simply add return this to the function...Crist
A
2

Delay operates on a queue. and as far as i know css manipulation (other than through animate) is not queued.

Alt answered 24/3, 2010 at 17:50 Comment(0)
H
2

delay does not work on none queue functions, so we should use setTimeout().

And you don't need to separate things. All you need to do is including everything in a setTimeOut method:

setTimeout(function () {
    $("#div").addClass("error").delay(1000).removeClass("error");
}, 1000);
Hag answered 30/5, 2018 at 5:19 Comment(3)
You don't have to use delay() with setTimeout().Jaguarundi
@Jaguarundi I don't think you get the idea. If you dont use setTimeout, then that delay wont workHag
The solution doesn't need both to work together. Either use delay() with queue() in jQuery or simply use setTimeout() can solve the problem. I am not saying your answer is wrong.Jaguarundi
D
0

Try this:

function removeClassDelayed(jqObj, c, to) {    
    setTimeout(function() { jqObj.removeClass(c); }, to);
}
removeClassDelayed($("#div"), "error", 1000);
Dragnet answered 3/1, 2011 at 9:29 Comment(0)
C
0

Try this simple arrow funtion:

setTimeout( () => { $("#div").addClass("error") }, 900 );

Camelot answered 18/9, 2019 at 7:37 Comment(0)
A
0

Another way...

$("#div").addClass("error"); 
setTimeout(function () { $("#div").removeClass("error"); }, 1000);
Adipose answered 16/3, 2022 at 16:27 Comment(0)
F
-1
$("#div").addClass("error").show(0).delay(1000).removeClass("error");

Thanks me later.

Flammable answered 26/3, 2021 at 6:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.