简体   繁体   中英

Javascript function shows only last element of array

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/

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/

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/

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);

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/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM