32

I have $('.element').css("color","yellow") and I need that next event was only after this one, something looks like $('.element').css("color","yellow",function(){ alert(1); }) I need this because:

$('.element').css("color","yellow");
 alert(1);

events are happen at one time almost, and this moment call the bug in animation effect (alert(1) is just here for example, in real module it's animation)

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Stasonix Niculin
  • 547
  • 2
  • 6
  • 12
  • 2
    I'm having a hard time figuring out what you are asking. Could you please edit your post and clarify. – hafichuk Nov 02 '11 at 01:15
  • 2
    The css function is not asynchronous, the color will be changed before the alert even without a callback. – Zack Bloom Nov 02 '11 at 01:16

5 Answers5

23

you can use promise

$('.element').css("color","yellow").promise().done(function(){
    alert( 'color is yellow!' );
});

http://codepen.io/onikiienko/pen/wBJyLP

user2497228
  • 279
  • 2
  • 3
  • This works. But I seldom see people use it this way, is this a good and common practice? – shenkwen Apr 01 '15 at 15:36
  • 1
    This doesn't seem to work for me in Chrome 22/9/2015 – Angelo Sep 22 '15 at 07:08
  • it actually DOES work, even in 2015, even in chrome. but the returned element from done() is not the expected element, but a function. so i got error messages, when i chained other functions behind done(). maybe that is your issue, too.. only option here, is to cache the previous element and proceed inside of done() (i guess).. – honk31 Sep 30 '15 at 18:39
  • matter of fact, the returned element is an object, not a function, but it contains functions and not the selected elements from before. using end() behind done() didn't solve the "issue". – honk31 Sep 30 '15 at 18:47
  • 2
    The codepen linked here doesn't function as expected in Chrome anymore: Version 61.0.3163.100 (Official Build) (64-bit) – mikeschuld Oct 06 '17 at 18:48
21

Callbacks are only necessary for asynchronous functions. The css function will always complete before code execution continues, so a callback is not required. In the code:

$('.element').css('color', 'yellow');
alert(1);

The color will be changed before the alert is fired. You can confirm this by running:

$('.element').css('color', 'yellow');
alert($('.element').css('color'));

In other words, if you wanted to use a callback, just execute it after the css function:

$('.element').css('color', 'yellow');
cb();
Zack Bloom
  • 8,309
  • 2
  • 20
  • 27
  • 5
    Yep, it's a little more complicated. By reading a css property off of the element you are forcing a repaint, making it live. You could also put the subsequent code in a setTimeout with the timeout 0 to defer the execution to the next event loop tick. – Zack Bloom Sep 04 '13 at 22:31
  • @ZackBloom I found that values above 0ms were required when testing using chrome. My guess would be that timeout values of 0 are inlined as an optimization. – Crazometer Jun 13 '16 at 19:11
  • This is true but not referring to the OP question since the op use an animation and javascipt is asynchronous. Let say he want the animation (all ease 1s) to finish, the alert will be fired before. See this http://stackoverflow.com/questions/9255279/callback-when-css3-transition-finishes – Baldráni May 16 '17 at 08:35
4

You can use setTimeout to increase the sleep time between the alert and the css like this:

function afterCss() {
    alert(1);
}

$('.element').css("color","yellow");
setTimeout(afterCss, 1000);

This will make the alert appear 1 second after the css changes were committed.

This answer is outdated, so you might want to use promises from ES6 like the answer above.


$('.element').css("color", "yellow").promise().done(function(){
    // The context here is done() and not $('.element'), 
    // be careful when using the "this" variable
    alert(1);
});
Guilherme David da Costa
  • 2,318
  • 4
  • 32
  • 46
2

There's no callback for jquery css function. However, we can go around, it's not a good practice, but it works.

If you call it right after you make the change

$('.element').css('color','yellow');
alert('DONE');

If you want this function has only been called right after the change, make an interval loop.

$('.element').css('color','yellow');
    var detectChange = setInterval(function(){
    var myColor = $('.element').css('color');
    if (myColor == 'yellow') {
    alert('DONE');
    clearInterval(detectChange); //Stop the loop
}
},10);

To avoid an infinite loop, set a limit

var current = 0;
$('.element').css('color','yellow');
    current++;
    var detectChange = setInterval(function(){
    var myColor = $('.element').css('color');
    if (myColor == 'yellow' || current >= 100) {
      alert('DONE');
      clearInterval(detectChange); //Stop the loop
    }
},10);

Or using settimeout as mentioned above/

singuyen
  • 118
  • 1
  • 5
1

use jquery promise,

$('.element').css("color","yellow").promise().done(function(){alert(1)});
xiaoyifang
  • 919
  • 12
  • 13