2

This is the code that I have and I want to make it so that the letters (sentence parameter) type themselves one by one. Not all at a time. I keep trying with setTimeout() but I can't do it so that it keeps it's progress. Please help.

var letters = [];

function typeOut(sentence, code) {
    $('body').append('<p id=' + code + '></p>');


    for (i = 0; i < sentence.length; i++) {
        letters[i] = sentence[i];
        $('#' + code).append(letters[i]);
    }
}

typeOut("Hello World", 1);

Thanks in advance!

Surak
  • 23
  • 5

5 Answers5

3

setTimeout seems perfect. I guess you are using it incorrectly.

function typeOut(sentence) {
  var txt = document.body
    .appendChild(document.createElement('p'))
    .appendChild(document.createTextNode(''));
  var i = 0;
  (function typeLetter() {
    if(i < sentence.length) {
      txt.nodeValue += sentence[i];
      ++i;
      setTimeout(typeLetter, 100);
    }
  })();
}
typeOut("Hello World");
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • Thank you very much. I can't believe you made it work. I'm not very good at it I guess... Thanks!! – Surak Aug 06 '16 at 18:32
1

I had fun with this question....
I may have done a little more than you asked.
But I think you will like it.

See in this CodePen.

My version of your typeOut function:

function typeOut(sentence, code) {
    $('body').append('<p id=' + code + '></p>');

    var i=0;
    var letterDelay = setInterval(function(){
        $('#' + code).append(sentence[i]);
        i++;
    }, $("#speed").val() );
}
Louys Patrice Bessette
  • 33,375
  • 6
  • 36
  • 64
0

There is many way to make this work could this solution for you work to

 var letters = [];

function typeOut(sentence, code) {
    $('body').append('<p id=' + code + '></p>');
    self = this;
    self.currentIndex = 0;
    self.sentence = sentence;
    
   var write =  function (){
     if(self.currentIndex < sentence.length) {
          letter = sentence[self.currentIndex];
          $('#' + code).append(letter);
           self.currentIndex+=1;
     }else {
          clearInterval(self.writeHandler);
        }
    }
    
    self.writeHandler = setInterval(write, 500)
}

typeOut("Hello World", "div1");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<p id="div1"></p>

here on jsbin check this

0

There really aren't that many options, the only thing suitable for this is timers, either setTimout or setInterval.

You could always use jQuery's delay() method, but internally it also uses setTimeout

function typeOut(sentence, speed) {
    var p = $('<p />'), i = 0;
    $('body').append(p);
    
    (function go() {
        p.dequeue().append(sentence[i++]).delay(speed).queue(go);
    })();
}

typeOut("Hello World", 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
adeneo
  • 312,895
  • 29
  • 395
  • 388
0

Why nobody remember that setTimeout accepts more than two arguments? It is very convenient feature. This is my version of typeOut.

function typeOut(text) {
    var out = document.getElementById('out');
    out.innerHTML = '';
    setTimeout(function typeNext(i) { //internal function can be named
        out.innerHTML += text[i++];
        if (i < text.length)
            setTimeout(typeNext, 100, i);
    }, 100, 0); //3rd arg goes to the function
}
<p id="out"></p>
<button type="button" onclick="typeOut('Hello World');">Type Out</button>
Alex Kudryashev
  • 9,120
  • 3
  • 27
  • 36
  • Because IE 9 and below didn't support the additional parameters to `setTimeout`, so we have the two parameter version locked in our heads. Whenever possible, I like to stick to a 'universal subset' that works everywhere rather than remember environment specific differences. – Jeremy J Starcher Aug 07 '16 at 03:58
  • IE 9 is almost gone and will go away finally. We cannot stick to deprecated stuff forever. – Alex Kudryashev Aug 08 '16 at 14:49