3

I want to figure out how to get the typewriter to loop infinitely with a subtle delay. Currently, it only triggers on page load.

<!DOCTYPE html>
<html>
<body>

<h1>Typewriter</h1>


<p id="demo"></p>

<script>
var i = 0;
var txt = 'Lorem ipsum dummy text blabla.';
var speed = 50;

function typeWriter() {
  if (i < txt.length) {
    document.getElementById("demo").innerHTML += txt.charAt(i);
    i++;
    setTimeout(typeWriter, speed);
  }
}
  window.onload = typeWriter;
</script>

</body>
</html>
Brian
  • 87
  • 1
  • 5
  • 1
    once you reach your limit, reset `i`to `0` – Daniel A. White May 25 '22 at 18:07
  • 1
    you may want to consider using setInterval() instead of setTimeout(), since setInterval() it runs at a given interval instead of waiting an amount of time to run – Charlie Ciampa May 25 '22 at 18:10
  • Does this answer your question? https://stackoverflow.com/questions/48958413/i-need-help-understanding-setinterval-this-bit-of-code-doesnt-behave-like/48958437#48958437 – Scott Marcus May 25 '22 at 18:16

1 Answers1

1

Using setTimeout: reset the paragraph back to "" at the begging. When the length of the text is reached inside the loop, reset i to 0. To add a delay simply use a different speed if it's the last character.

But, it's better to use setInterval in your case instead, here is an example:

<h1>Typewriter</h1>

<p id="demo"></p>

<script>
var txt = 'Lorem ipsum dummy text blabla.';
var speed = 50;

var elem = document.getElementById('demo');

function typeWriter() {
  var i = 0;
  elem.textContent = "";

  var interval = setInterval(function(){
    elem.textContent += txt[i];
    i++;

    if (i === txt.length) {
      clearInterval(interval);
      setTimeout(typeWriter, 3000);
    }
  }, speed)
}

window.onload = typeWriter;
</script>

As @Scott Marcus suggested in the comments, use textContent instead of innerHTML when you're only changing the text.

Idrizi.A
  • 9,819
  • 11
  • 47
  • 88
  • `setInterval()` is perfect for this. The loop is uncessary. – Scott Marcus May 25 '22 at 18:23
  • 1
    I'm not going to rewrite the entire code, but rather just added the necessary parts to the OP's code. You're very welcome to answer with your better solution. – Idrizi.A May 25 '22 at 18:26
  • I did in the comments. But, if the OP is going about this the wrong way, it doesn't make sense to build out a solution based on it. – Scott Marcus May 25 '22 at 18:26
  • *`var p`*... Unless you're code-golfing, try always to name your variables with at least 3 characters. – Roko C. Buljan May 25 '22 at 18:42
  • I have added a `setInterval` example. Feel free to edit the code if you think it needs improving. – Idrizi.A May 25 '22 at 18:43
  • 2
    Poor answers are always a reason to downvote. Remember that you aren't just answering for the OP. Stack Overflow is a knowledge base and your answers will be what others see in the future. Since you've improved your answer, I've retracted my downvote. – Scott Marcus May 25 '22 at 18:43
  • I would now suggest though that you not use `.innerHTML` as there are security and performance implications to its use. Rather, use `.textContent`, which doesn't have those issues. Since you aren't working with any HTML in the string, `.innerHTML` is not warranted. – Scott Marcus May 25 '22 at 18:44
  • thanks for all of the commentary, I tried both using an external js file and for the second solution (that contains clearInterval) I had to use $(document).ready(function(){ }); in order for the code to work – Brian May 25 '22 at 18:58
  • @Brian If you place your `script` element at the end of the document, just prior to the closing `body` tag, you won't need the `document.ready` coade. – Scott Marcus May 25 '22 at 19:02
  • I'd say @Enve has redeemed himself with the second response. But I would delete that coding horror of an original answer. Iterating a string to time event triggering? This abstraction is like using atomic numbers to weigh a coin. – radarbob May 25 '22 at 19:03
  • I have updated the answer. Thank you for all your suggestions. – Idrizi.A May 25 '22 at 19:25