views:

406

answers:

5

Hello. I want a string to appear character-for-character with the following code:

function initText()
{
    var textScroller = document.getElementById('textScroller');
    var text = 'Hello how are you?';

    for(c = 0; c < text.length; c++)
    {
     setTimeout('textScroller.innerHTML += text[c]', 1000);
    }
}

window.onload = initText;

It's not working.. what am I doing wrong?

A: 

Try this:

function initText()
{
    var textScroller = document.getElementById('textScroller');
    var text = 'Hello how are you?';

for(c = 0; c < text.length; c++)
{
    setTimeout("textScroller.innerHTML += '" + text[c] + "'", 1000 + c*200);
}
}

window.onload = initText;
Josh Pearce
Edited to remove test variable and append text[c] as a string in single quotes.
Josh Pearce
Would fail if text has `'`, `\` or newline characters. Best to avoid creating and executing code in strings like timeout-with-string-argument does.
bobince
A: 

Your for loop is setting a timeout for every character at once, so they will not appear in sequence, but all at once. Your setTimeout should include code to another setTimeout that will include the next character to display.

So something like this (didn't test this)

function initText()
{
    var textScroller = document.getElementById('textScroller');
    var text = 'Hello how are you?';    
    setTimeout('nextChar(text)', 1000);
}
function nextChar(text){
    if(text.length > 0){
        textScroller.innerHTML += text[0]; 
        setTimeout('nextChar(text.substring(1))', 1000);
    }
}
jarrett
+2  A: 

Try something like this:

function initText()
{
    var textScroller = document.getElementById('textScroller');
    var text = 'Hello how are you?';

    var c = 0;
        var interval = setInterval(
      function() { 
       textScroller.innerHTML += text[c]; 
       c++; 
       if( c >= text.length) clearInterval(interval);
      } , 1000);

}

Note I added clearInterval to stop it when it's needed.

Soufiane Hassou
You are right that setInterval is a better idea, didn't think about it
jarrett
I see, thanks! In this case, no (standard) loop is defined. So in this case the function acts as a loop? That's new but interesting to me :)
richard
What's looping is `setInterval`. It just like looping over a `setTimeout` as you were doing :)
Soufiane Hassou
+1  A: 

Try using a closure:

function init() {
    var textScroller = document.getElementById('textScroller');
    var text = 'Hello how are you?';
    var c = 0;
    function run() {
        textScroller.innerHTML += text[c++];
        if (c<text.length)
            setTimeout(run, 1000);
    }
    setTimeout(run, 1000);
}
init()

The problem in your code is that the code you put in the string will run in the global context, where textScroller is not defined (it is defined inside your function).

idrosid
+2  A: 

Currently, you are defining 18 timeouts and all will be executed ~ at once. Second problem is, you pass instructions to execute as a String. In that case, the code won't have access to all variables defined in initText, because evaluated code will be executed in global scope.

IMO, this should do the job

function initText(){
    var textScroller = document.getElementById('textScroller');
    var text = 'Hello how are you?';

    var c = 0;

    (function(){
     textScroller.innerHTML += text.charAt(c++);
     if(text.length > c){
      setTimeout(arguments.callee, 1000);
     }
    })();
}
Rafael