views:

44

answers:

1

I'd like to have a DIV fade in after fading another out. Because the one DIV is inside of the other, I need the parent DIV to fade out completely (clearing any other content that might be showing) before the child DIV then fades in. I tried using the jQuery callback function in my code below to no avail.

$('#viewer a').click(function(e) {
    e.preventDefault();
    $('#content > *').fadeOut(500, function(){
        $('#kiosk').fadeIn(250);
    });
});

The DIVs are jumpy, and it's obvious that the script is not waiting for the animation to complete before beginning the fading in of the other DIV. Why is this?

Nota bene: I know I could probably chain a .delay() or something of the sort, but I'd rather not tack on half of a second when the callback function is there for this exact purpose!

+1  A: 

I'm guessing that part of the choppiness is from the fact that you are fading elements whose ancestors are currently being faded.

When you fade something, it automatically fades its descendants as well, so you should probably do this instead.

$('#content').children().fadeOut(500, function(){
    $('#kiosk').fadeIn(250);
});

Now keep in mind that the callback with the .fadeIn() will be called once for each element that is faded out. This could be an issue as well.

Since (presumably) #kiosk is a direct descendant of #content, you could just directly chain the fadeIn() on the end. No .delay() is needed.

Try it out: http://jsfiddle.net/rrM28/

$('#content').children().fadeOut(500).filter('#kiosk').fadeIn(250);

EDIT: From your updated example in the comment, the fadeIn() is running immediately because the #kiosk is initially hidden, therefore the animation is immediately complete for that one, and the chain continues.

A solution is to place the .fadeIn() in an animation .queue() so that it will run only after the fadeOut() is complete.

Try it out: http://jsfiddle.net/rrM28/4

$('#viewer a').click(function(e) {
    e.preventDefault();
           // Don't fadeOut the #kiosk
    $('#content').children(':not(#kiosk)').fadeOut(500)
           // Place the fadeIn of #kiosk in the next step of the animation queue
        .queue(function() {
            $(this).siblings('#kiosk').fadeIn(250).dequeue();
        });
});
patrick dw
@Patrick, thanks for the answer, and for the bit of code. I updated your fiddle to include a selector inside the #kiosk DIV which is faded in after it is loaded (on my site, a large img, in this code, a span).I still see the content being loaded before the previous content had fully faded out, let me know what you think: http://jsfiddle.net/rrM28/3/
BenjiBee
@BenjiBee - I see. The issue is that because `#kiosk` is initially hidden, it must see the animation (for that element) as being immediately complete, so it continues with the chained `.filter().fadeIn()`. Hiding and fading the nested `<span>` doesn't help you. I'm trying to figure out the simplest solution. I'll hopefully post something in a few minutes.
patrick dw
@Patrick - Thanks for the reply, I appreciate the explanation and code. I think for this project, and my others, it'd be benificial to read up on .queue(), but I'm not sure if it's exactly what I'm looking for. I guess I'm really hung-up on the idea of the function of a callback. As far as I know, the method proceeding the callback should be exectuted completely before the callback is even performed. So, as I see it, if you have a .fadeIn(500) there should be 500ms where the fadeIn is performed before the callback, I don't understand how it could overlap!
BenjiBee
@BenjiBee - Remember that when you call `$('#content').children().fadeOut...` You are calling the `fadeOut()` on *several* elements. If one of those elements (`#kiosk` in this case) is already "faded out", then I'm guessing jQuery sees the `fadeOut()` as being complete for that one, and fires the callback even though the others are still fading. Here's another version that should work. http://jsfiddle.net/rrM28/5/ It is similar to the one that uses `queue()`. It excludes `#kiosk` from the `fadeOut()`, then does a callback. Now the callback works because the `#kiosk` isn't ending early.
patrick dw
...keep in mind one more thing though. Because the callback in the new example is firing once for *each* element, you may see some unexpected behavior since the `fadeIn()` is being triggered several times. If that happens, you may need to set a flag so that the `fadeIn()` only triggers once. Think of a variable called `fadeInCalled` set to `false`. When the callback runs, it checks that flag. If it is `false`, it does the `fadeIn()` and sets the flag to `true` so that the subsequent times the callback runs, the `fadeIn()` won't be triggered. Don't worry about it unless it is an issue though.
patrick dw
@Patrick - This is wonderful thank you. I just was having a bit of a hard time wrapping my head around it, your explanation helped a lot. The .fadeIn() and .fadeOut() looks much better without the .delay() and the whole site feels better. Many thanks! (if you feel up for it, I have another more general question I think you'd know a good answer to here: http://stackoverflow.com/questions/3425599/dynamic-image-gallery-generation-using-php-and-jquery)
BenjiBee
@BenjiBee - You're welcome. :o) With regard to your other question, I'm afraid I won't be much help. I'm really only beginning to explore server-side possibilities for myself. I haven't rolled too many sites out, so I can't give too much of a "big picture" perspective. With regard to the client side, there are lots of great libraries. jQuery is nice because there are so many users. You'll get lots of good support. Maybe with the others too. I just don't know. One interesting server-side project I've looked at is CouchDB. It is from the Apache Foundation, and just had its 1.0 release...
patrick dw
...It is a schema-less DBMS written in Erlang. You can interact with it directly via HTTP, and instead of SQL, you use javascript to find/reduce records. There are ups and downs, but I'd include it among the other tires you're kicking. :o) http://couchdb.apache.org/ http://www.couch.io/
patrick dw