Question

I wish to create an animation chain, while I'm looping on a set of elements; the next loop step is called when the animations of the first step have been completed. The chain is something like this:

Step 1 (work on element A)
change background color
change font color
(--> fire Step 2)
change background color again
change font color again

Step 2 (work on element B)
change background color
change font color
wait 1 second
change background color again
change font color again
--> fire resolve()

I've written this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>jQuery Deferred</title>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
        <script type="text/javascript">
            $(document).ready(function() {


                function animation() {
                    return $.Deferred(function(dfr) {
                        dfr.pipe(function() {
                            return $.Deferred(function(dfr) {
                                $.when($('#text').animate({
                                    color : '#ff0000',
                                    fontSize : '3em'
                                }, 'slow').delay(3000), $('#text').animate({
                                    color : '#ff0000',
                                    fontSize : '6em'
                                }, 2000)).then(dfr.resolve())
                            }).promise();
                        }).pipe(function() {
                            return $.Deferred(function(dfr) {
                                $.when($('#text').animate({
                                    color : '#c456fa',
                                    fontSize : '1em'
                                }, 'slow')).then(dfr.resolve())
                            }).promise();
                        })
                    }).promise();
                    }
                //}, 1500)

                var a = $.when(
                    animation()).done(function() {
                    console.log('done');
                });
            });

        </script>
    </head>
    <body>
        <p id="text">
            TEXT
        </p>
    </body>
</html>

I wished that the "console.log('done')" was written only at the and of all pipes .. but the animations neither starts!

What is wrong?

(sorry for my awful English, you can understand what I'm trying to code).

Was it helpful?

Solution

The problem is that pipe() is only called to the next link in the chain once its Deferred has been resolved. But you are using pipe() as the very first thing. It's not getting called because it's waiting for this to be resolved before going down the pipe.

I had the same problem trying to understand these things. It seems a bit counterintuitive depending on what way you're approaching this stuff I suppose, but you need to resolve() your dfr before you call pipe. The code then works for me. Here's the change:

            function animation() {
                return $.Deferred(function(dfr) {
                    dfr.resolve();
                    dfr.pipe(function() {
                        ...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top