0

Possible Duplicate:
Javascript closure inside loops - simple practical example

How can I make this work?

// Phrases

var phrases = new Array();
phrases[0] = 'Phrase 1';
phrases[1] = 'Phrase 2';
phrases[2] = 'Phrase 3';

for (var i = 0; i < phrases.length; i++) {  
   var content = phrases[i];        
   $('#phrase').html(content).slideDown('slow').delay(1000).fadeOut('slow');    
};

Here's the HTML:

<p id="phrase"></p>

Passing the content variable into the html() function I noticed that content is always equal to the last phrase in the array, and the loop runs the slide / delay / fade functions 3 times.

I know that this is something to do with closures inside a for loop and I've looked at countless examples, but I just can't get my head around it. Can someone solve and explain this one to me please?

EDIT: Apologies for being unclear before, I have edited this question to include the HTML and the array in question.

Functionality: Different phrases are held in the phrases[] array, I would like to insert the phrase into the <p> element, then slide that element down, leave it on screen for a second, then fade it out. Then I would like to move on to the next phrase in the phrases[] array and perform the same functions.

Community
  • 1
  • 1
FrediDoo
  • 43
  • 1
  • 4
  • what the loop is really doing is selecting the element with that id and writing to it every iteration of the loop, so it is overwriting it every time until the final iteration. Explain what it is you are wanting to do – CrayonViolent Mar 24 '11 at 02:54
  • Thanks Crayon, I have updated the question to reflect what I am trying to do. – FrediDoo Mar 24 '11 at 03:18
  • Doesn't delay(1000) actually return control NOW and insert a task to occur 1 second from now, or 1000 seconds from now (prototype takes seconds)? If so, the loop will execute very quickly, and then after 1 second all the queued up screen changes will occur very quickly. Also, I'm not sure the line with delay() is syntactically valid, at least when used with prototype.js. I haven't tried it, though. – Paul Mar 24 '11 at 04:32

1 Answers1

1

You don't actually have an issue with closures, it is just setting the innerHTML to content on every iteration, which doesn't take into account the effects which need to be completed first.

var showPhrase = function(phrases, start) {
    start = start || 0;
    var showNext = function() {
        $('#phrase')
         .html(phrases[start])
         .slideDown('slow')
         .delay(1000)
         .fadeOut('slow', function() {
            start++;
            if (start < phrases.length) {
                showNext();
            }
        });
    }
    showNext();
}

showPhrase(['a', 'b', 'c']);

jsFiddle.

alex
  • 479,566
  • 201
  • 878
  • 984
  • Hi Alex, thanks for your response. This works of course, but I was hoping to display the phrases which are held in the phrases array as apposed to the letters a, b, and c. – FrediDoo Mar 24 '11 at 03:21
  • Sorry keyboard issue there - how could I amend your script so that it would read the phrases from the array itself? – FrediDoo Mar 24 '11 at 03:22
  • @FrediDoo: check out **[this](http://jsfiddle.net/G9RvQ/2/)** – qwertymk Mar 24 '11 at 03:37
  • @FrediDoo Sorry, I was out to lunch. It is trivial to replace my example array with your own. – alex Mar 24 '11 at 04:08
  • Alrighty, cheers Alex. I'm really not great with Javascript at all so definitely wouldn't have got it on my own. Take it easy :) – FrediDoo Mar 24 '11 at 04:17
  • @FrediDoo Feel free to give me the big green tick to say *thanks* :) – alex Mar 24 '11 at 04:18
  • @qwertymk I don't know why I didn't do that originally. I edited my question, thanks. – alex Mar 24 '11 at 04:18