1

I am creating a utility method which helps fading the elements sequentially with jQuery. As you can see in the below code I am adding an extra class as alreadyFadedIn a flag. At the end of the method call sequentiallyFadeIn(...) I would like to perform the cleanUp where I want to remove the flag class which I added in the selected elements inside the sequentiallyFadeIn(...) method.

<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
$(document).ready(function() {

    function sequentialFadeIn(selectorText, speed, display, callBack) {

        display = typeof display !== 'undefined' ? display : "block";

        function helper() {
            nextElementToFadeIn = $(selectorText).not(".alreadyFadedIn").first();
            nextElementToFadeIn.fadeIn(speed, function() {
                $(this).addClass("alreadyFadedIn");
                helper();
            }).css("display", display);
        }
        helper();

        callBack(selectorText);      
    }
    sequentialFadeIn(".toBeFaddedIn", "slow", "inline-block",function cleanUp(selectorText1){
            $(selectorText1).removeClass("alreadyFadedIn");
            console.log("Clean up has been performed.");
                    console.log("Selector Text: " +selectorText1);

        } );

});

</script>

</head>
<body><style media="screen" type="text/css">
.hello {
    background-color: blue;
    height:50px;
    width: 50px;
    display: none;

}
</style>

<div class="hello toBeFaddedIn"></div>
<div class="hello toBeFaddedIn"></div>
<div class="hello toBeFaddedIn"></div>
<div class="hello toBeFaddedIn"></div>
<div class="hello toBeFaddedIn"></div>

</body></html>

While looking at the inspect element I notice that class alreadyFadedIn is not getting removed. The cause seems to me is the cleanUp method gets executed asynchronously along with main logic of the sequentiallyFadeIn method which is in helper(). You can also notice the log message "Clean up has been performed." getting printed even before the divs have completed fading in.

How can I make the cleanUp call getting executed after the completion of main logic in the sequentiallyFadedIn method? Any suggestions?

Code on jsfiddle: http://jsfiddle.net/BztLx/11/

7
  • 1
    Looks like you have to run the callback inside the helper function once nextElementToFadeIn does not contain any element anymore. Commented Nov 24, 2012 at 17:22
  • You need to call the callBack function in the completion function of fadeIn. Commented Nov 24, 2012 at 17:22
  • Your code executes helper (which removes the class alreadyFadedIn) immediately, and the anonymous function which adds the class alreadyFadedIn is executed later, when the fadeIn animation is complete. That seems wrong. But you have the ingredients there to fix the logic. You can execute code immediately or on animation end. Commented Nov 24, 2012 at 17:24
  • This looks overly complicated. Why not chain fade-in using next(), without the need for adding a class? Commented Nov 24, 2012 at 17:25
  • @FelixKling your solution worked ! : ) Here is the updated code on jsfiddle: jsfiddle.net/BztLx/14 Commented Nov 24, 2012 at 17:31

3 Answers 3

4

You need to check whether any elements remain to be faded in. If no elements remain, call the cleanup callback. Here is how I implemented it:

    if ($(selectorText).is(":not(.alreadyFadedIn)")) {

        //Your main logic
        nextElementToFadeIn = $(selectorText).not(".alreadyFadedIn").first();
        nextElementToFadeIn.fadeIn(speed, function() {
            $(this).addClass("alreadyFadedIn");
            helper();
        }).css("display", display);

    } else {

        //No elements remain, cleanup time
        callBack(selectorText);
    }

In the outer condition I check whether there is at least one element that is not faded in, otherwise I invoke the callback.

Demonstration: http://jsfiddle.net/BztLx/12/

Sign up to request clarification or add additional context in comments.

1 Comment

I also came up with something similar based on @FelixKing's suggestion in the comments under the question. Demo: jsfiddle.net/BztLx/14
3

Easier, cleaner and faster if you just rewrite your code something like this...

$(document).ready(function() {

    function sequentialFadeIn(selectorText, speed, display, callBack) {

        display = display || "block";

        var els = $(selectorText),
              i = 0;

        (function helper() {
            els.eq(i++).fadeIn(speed, helper).css("display", display);
            if (callback && i === els.length)
                callback(selectorText); // Not really needed any more
        })();
    }

    sequentialFadeIn(".toBeFaddedIn", "slow", "inline-block", function cleanUp(selectorText1){
        // not really needed any more
       //  $(selectorText1).removeClass("alreadyFadedIn");
    });
});

DEMO: http://jsfiddle.net/BztLx/15/

You were doing way more DOM selection than needed.

1 Comment

Aah ! Beautiful : ) When we have the .eq() as looper, who needs the extra flags! Thanks for pointing out this way.
2

To expand on my comment, here is a simplified version that doesn't use an additional class:

function fadeThenNext(element){
    element.fadeIn("fast", function() {
        element=element.next(".toBeFaddedIn");
        if (element.length) fadeThenNext(element);
    });
}
fadeThenNext($(".toBeFaddedIn").first());

demo: http://jsfiddle.net/BztLx/17/

[Update] A more generic version if the elements are not siblings:

function fadeSequence(elements){
    elements.first().fadeIn("fast", function() {
        fadeSequence(elements.slice(1));
    });
}
fadeSequence($(".toBeFaddedIn"));

​fiddle: http://jsfiddle.net/BztLx/22/

2 Comments

It requires the elements selected to be siblings of each other, it may not be the case sometimes. But applicable to some scenarios where this effect needs to be applied say on a list of elements.
right, for a more generic code you'll need to iterate through the selector as in @user1689607 's sample. The point is that you don't need the extra class!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.