Search code examples
javascriptjqueryperformancejquery-animatecode-complexity

JQuery animation and effects apply for several elements with $.when() and then()


I have html element like this,

<div class="row h-100 p-3 justify-content-center align-items-center m-0">
        <h1 class="col-12 text-center position-absolute welcome-line-1 d-none-edited" id="welcome-line-1">TEXT 01</h1>
        <h3 class="col-12 text-center position-absolute welcome-line-2 d-none-edited" id="welcome-line-2">TEXT 02</h3>
        <h2 class="col-12 text-center position-absolute welcome-line-3 d-none-edited" id="welcome-line-3">TEXT 03</h2>
    </div>

and I want to animate these text elements using jQuery.This is my jquery code for one element.

var line_1_anim = function(){
            return $('#welcome-line-1')
                .css('opacity', 0)
                .slideDown('slow')
                .animate(
                    { opacity: 1 },
                    { queue: false, duration: 'slow' }
                )
                .delay(1000)
                .slideUp('slow');
        }

and lets assume I have three elements and i use this kind of approach to animate each element one by one using $.when() and then()

$.when(line_1_anim())
   .then(line_2_anim)

I am trying to reduce the code complexity and achieve this. Already my functions work, but I want to do more. Because if I want to add 10 more elements I have to repeat same code 10 times. So I write something like this.

var line_animation = function(selector,delay){
            return selector
                .css('opacity', 0)
                .slideDown('slow')
                .animate(
                    { opacity: 1 },
                    { queue: false, duration: 'slow' }
                )
                .delay(delay)
                .slideUp('slow');
        }

        $.when(line_animation(line_1,1000))
        .then(line_animation(line_2,2000))
        .then(line_animation(line_3,3000));

I simply planned to change selector and delay and run the same method several time. But this doesn't work like I want. All the functions work at once and not, one after the other.

Any idea what is the wrong with my approach and how can I achieve this.

Hope I have explained my question and everything is clear.


Solution

  • From jQuery promise example you can rewrite all like (i.e.: line_animation should return a promise and not a jQuery object):

    var line_animation = function (selector, delay) {
        var dfd = jQuery.Deferred();
        selector.css('opacity', 0)
                .slideDown('slow')
                .animate({opacity: 1}, {queue: false, duration: 'slow'})
                .delay(delay)
                .slideUp('slow', function () {
                    dfd.resolve("hurray");
                });
        return dfd.promise();  // return a promise....
    }
    
    $.when(line_animation($('#welcome-line-1'), 1000)).then(function () {
        line_animation($('#welcome-line-2'), 2000).then(function () {
            line_animation($('#welcome-line-3'), 3000);
        });
    })
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    
    <div class="row h-100 p-3 justify-content-center align-items-center m-0">
        <h1 class="col-12 text-center position-absolute welcome-line-1 d-none-edited" id="welcome-line-1">TEXT 01</h1>
    
        <h3 class="col-12 text-center position-absolute welcome-line-2 d-none-edited" id="welcome-line-2">TEXT 02</h3>
    
        <h2 class="col-12 text-center position-absolute welcome-line-3 d-none-edited" id="welcome-line-3">TEXT 03</h2>
    </div>