1

Please take a look at this function:

var msgdiv, i=0;
msgdiv=$("#message");
messages=["Welcome!","Добро пожаловать!"];
function fadeMessages(messages, div){
    while(i<messages.length){
        div.fadeOut(1000).html('').append(messages[i]).fadeIn(1000);
        i=i+1;
    }  
}
 fadeMessages(messages,msgdiv);

What I want to do is, to show one by one elements of array. But, function above shows only last element of array messages.length time. Where I did wrong?

Live example: http://jsfiddle.net/QQy6X/

4 Answers 4

4

The while executes much much faster than the fadeOut/fadeIn calls, so you only see the last result. You need to make each animation wait for the previous ones to finish.

I like to solve these problems recursively. Note, it does alter the messages array, but it's not too hard to convert this to use a counter instead (like your original version). Here you go:

var $msgdiv = $('#message'),
    messages = ['Xoş gəlmişsiniz!', 'Welcome!', 'Добро пожаловать!'];

function showNext() {
    var msg = messages.shift();
    if (msg) {
        $msgdiv.fadeOut(1000, function () {
            $(this).text(msg).fadeIn(1000, showNext);
        });
    }
}

showNext();

Demo: http://jsfiddle.net/mattball/Exj95/


Here's a version that leaves messages intact:

var $msgdiv = $('#message'),
    messages = ['Xoş gəlmişsiniz!', 'Welcome!', 'Добро пожаловать!'],
    i = 0;

function showNext() {
    if (i < messages.length) {
        var msg = messages[i];
        $msgdiv.fadeOut(1000, function () {
            i++;
            $(this).text(msg).fadeIn(1000, showNext);
        });
    }
}

showNext();

Demo: http://jsfiddle.net/mattball/wALfP/

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

5 Comments

I can't figure out how to " make each animation wait for the previous ones "
You need to refresh the page, my friend ;-)
and how to get it work with delay between fadein() and fadeout()?
Learn to search the jQuery API docs, man. I'll give you a hint: .delay().
1

Your while loop finishes executing before the div has had a chance to fade out. Use an if statement and recursion:

var msgdiv = $("#message"); 
var i = 0; 
var messages = ["Welcome!", "Добро пожаловать!"]; 
(function fadeMessages() { 
    if (i in messages) { 
        msgdiv.fadeOut(1000, function() {
            $(this).html('').append(messages[i++]).fadeIn(1000, fadeMessages);
        });
    } 
})(); 

http://jsfiddle.net/QQy6X/6/

Comments

0

Your while loop finishes very quickly; instead you should wait for the animation to finish before starting the next one. This is easy to do by adding a callback function to fadeIn. I would use this:

+function(){
    var $msgdiv = $("#message");
    var i = -1;
    var messages = ["Xoş gəlmişsiniz!","Welcome!","Добро пожаловать!"];

    +function fadeNext(){
        $msgdiv.fadeOut(1000, function(){
            $msgdiv.text(messages[i = (i + 1) % messages.length]);
            $msgdiv.fadeIn(1000, fadeNext);
        });        
    }();
}();

http://jsfiddle.net/Paulpro/QQy6X/7/

2 Comments

and how to get it work with delay between fadein() and fadeout()?
@TuralTeyyuboglu Add .delay(1000); after the fadeIn, like this: jsfiddle.net/Paulpro/QQy6X/8
0

In jQuery, you can't intertwine animations and non-animations in the way you are doing and expect them to run in the right order. The animations will go into the animation queue and get sequenced one after another there, but the non-animations will all run immediately. Thus, things won't happen in the right order.

To do something like you want to do, you can use code like this.

messages=["Welcome!","Добро пожаловать!"];

function fadeMessages(msgs, div) {
    var i = 0;
    function next() {
        if (i < msgs.length) {
            div.fadeOut(1000, function() {
                div.html(msgs[i++]).fadeIn(1000, next);
            });
        }
    }
    next();
}

fadeMesssages(messages, div);

This uses the completion functions of both fadeIn() and fadeOut() to carry out the next steps. Here's how it works:

  1. It fades out the div.
  2. In the completion function of the fadeOut, it sets the next message and then starts the fadeIn.
  3. It advances the message counter.
  4. In the completion function from the fadeIn, it calls the function to start the next iteration.

If you want a delay before the fadeOut (to make sure a given message displays for a certain amount of time), you can add that with this .delay(2000) added in the right place:

messages=["Welcome!","Добро пожаловать!"];

function fadeMessages(msgs, div) {
    var i = 0;
    function next() {
        if (i < msgs.length) {
            div.delay(2000).fadeOut(1000, function() {
                div.html(msgs[i++]).fadeIn(1000, next);
            });
        }
    }
    next();
}

fadeMesssages(messages, div);

If you want a delay before the next iteration starts, you can do that like this with a setTimeout:

messages=["Welcome!","Добро пожаловать!"];

function fadeMessages(msgs, div) {
    var i = 0;
    function next() {
        if (i < msgs.length) {
            div.fadeOut(1000, function() {
                div.html(msgs[i++]).fadeIn(1000, function() {
                    setTimeout(next, 2000);
                });
            });
        }
    }
    next();
}

fadeMesssages(messages, div);

2 Comments

and how to set delay before next()?
Your original code had no delay between each iteration other than the fadeIn, fadeOut times, but I've added two new versions to my answer that have a 2 second delay. The first is before the fadeOut at the start of each iteration. The second is before the next iteration starts. The former is easier because you can just use .delay(). The second uses setTimeout().

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.