3

I'm trying to fade in one word at a time from a div. The below code works fine for one div but when I have multiple divs, it does not do it sequentially.

Here is the fiddle : http://jsfiddle.net/zlud/6czap/110/

Can anyone see an obvious problem? Any suggestions to print one line after the other would be greatly appreciated. (So the text in the second div will be printed after the first div is done.)

<html>
<div class="example">These are some words that </br> should be faded in one after the other.</div>
<div class="example"> No way some words that </br> should be faded in one after the other.</div>
</html>

JavaScript

var $el = $('.example').map(function () {
return this;
}).get();

$el.forEach(function (eachdiv){
        
var  text = $(eachdiv).text(),
words = text.split(" ");
var html = "";

for (var i = 0; i < words.length; i++) {
    html += "<span>" + words[i] + " </span>";

        $(eachdiv).html(html).children().hide().each(function(i){
           return $(this).delay(i*500).fadeIn(700);``
        });        
    }
});
robyaw
  • 2,274
  • 2
  • 22
  • 29
user2599381
  • 727
  • 1
  • 8
  • 16

3 Answers3

2

How about this?

I am assuming you dont need a delay in animation, instead you need them to appear one after the other.

var words, $el;
var arrEl = [];

// loop through each div and populate the array with the container (div) element and its text content split
$('.example').each(function(){
    var $this = $(this);
    arrEl.push({el:$this,words : $.trim($this.text()).split(" ")});
    $this.empty();
});

//This will the startup function  
function fadeIn(){
    var len = arrEl.length,  obj = arrEl.shift() || {}; //get the top item from array and remove it from the array using array.shift
    $el = obj.el; //get the container from the item
    words = obj.words; //get the array of words
    //if there are any items in the array start the animation process for this item.
    if(len)  window.setTimeout(transitionElement, 0); 
}

function transitionElement(){

    var wlen = words.length,
    span = $('<span/>', {'class':'hide'}).append(" " + words.shift()); //remove and get the top text string from the word array wrap it in span with a class "hide" which will hide it by default

    window.setTimeout(function(){
        if(wlen)  //if words are available anymore then call show word
           showWord(span);
        else //else call fadeIn to process the next container in the arrEl array of items
            fadeIn();
    },0);
}

function showWord(span){
     span.appendTo($el).fadeIn(500, transitionElement); // append the span to the container with an animation duration of 500ms and in the complete callback of this invoke transitionElement to process the next word or next item. Here there is no delay required since this will invoked only when the transition of first word is completed
}
//Start animation process
fadeIn();

Fiddle

PSL
  • 123,204
  • 21
  • 253
  • 243
  • Thank you very muach. this is exactly what I was trying to do. – user2599381 Sep 11 '13 at 15:04
  • could you be kind enought to put few comments on?? I know I'm been a pain now but could not understand some of the code, cheers in advance. – user2599381 Sep 11 '13 at 15:10
  • @user2599381 You are welcome.. added some explanation. let me know for any more quesitons... – PSL Sep 11 '13 at 15:31
  • sorry To distrub you again but I was trying still having a stab at my problem to solve it imoprove my knowldge on callbacks, [Link] (http://jsfiddle.net/zlud/6czap/185/) this fiddle is my latest try, but the fade in seems to happen instently any ideas? Thanks in advance – user2599381 Sep 13 '13 at 09:48
  • @user2599381 it is because you need to perform the transition if next item only when the first one completes, that is what you achieve using the callback on fadeIin See the showWord function in my answer.. – PSL Sep 13 '13 at 17:29
1

Jquerys animation functions have a callback in the parameter list. This callback will be executed after the animation completes. Or maybe it's that i is passed by reference.

undefined
  • 2,051
  • 3
  • 26
  • 47
  • Thank you. How would I use that here should I look for the next div in the callback? Thanks again. – user2599381 Sep 11 '13 at 14:13
  • See [here](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) about referencing values in loops. – undefined Sep 11 '13 at 14:16
  • And [here](http://stackoverflow.com/questions/10032453/jquery-animation-chaining-each-and-animate-or-fadein-and-fadeout) for some tips about animation chaining. – undefined Sep 11 '13 at 14:22
0

You should pick on div at a time to work on and continue to the next one ones the first is done. Now you attach the delay and fade-in to each word in each div at the same time. Initiate the animation of the second div by a trigger when the first one is done or something like that?

inquam
  • 12,664
  • 15
  • 61
  • 101
  • Thanks for the quick reply. I thought the .map will put each div to an array element, and then I'm passing a single div through the foreach loop? Sorry my javascript knowledge is not very good. – user2599381 Sep 11 '13 at 14:09
  • I think this kind of happens, but the animations are "attached" and then it moves on. It doesn't wait for the animations to complete. You can have a callback function to catch that. So since this happens so fast the animations are attached to both div's (well, their words) almost at the same time and that is why the animate together. – inquam Sep 11 '13 at 14:11
  • Also, you don't need to "return" *$(this).delay(i*500).fadeIn(700);*. You can call that on one line and return on the line after. And you don't have to have the part where you traverse the spans of the div and attaches the animations in the for loop. That causes you to do it multiple times for each div. – inquam Sep 11 '13 at 14:13
  • Thanks again. I tried debugging it, as you said the first foreach loop keeps sending in DIVs before the animation on words can complete, How can I kindda "make it sequential" so the out foreach loop waits till the animation completes, my knoweldge of callbacks are appualing, just like my spelling :) – user2599381 Sep 11 '13 at 14:21