Abdalla Abdalmunim
Abdalla Abdalmunim

Reputation: 101

multiple elements with type effect JavaScript

I have two elements with typing effect using javascript, every element has its own function to make the typing effect, the problem is the two texts get displayed incompletely, but when I comment out one of the two functions all of the characters get displayed. And here is my index.js:

const h1Txt = 'this is h1';
const headerP = 'this is paragraph!';
let i = 0;

window.addEventListener('load', function() {
  console.log('typing');

  executeAsynchronously([typeWriter, typeWriter2], 100);

});

function executeAsynchronously(functions, timeout) {
  for (var i = 0; i < functions.length; i++) {
    setTimeout(functions[i], timeout);
  }
}
// The typewriter method for h1
function typeWriter() {
  if (i < h1Txt.length) {
    document.getElementById('h1-text').innerHTML += h1Txt.charAt(i);
    i++;
    setTimeout(typeWriter, 100);

  }
}



// The typewriter method for p
function typeWriter2() {
  if (i < headerP.length) {
    document.getElementById('p-text').innerHTML += headerP.charAt(i);
    i++;
    setTimeout(typeWriter2, 100);
  }

}
<h1 class="text-floating" id="h1-text"></h1>
<p id="p-text"></p>

Upvotes: 1

Views: 361

Answers (3)

lissettdm
lissettdm

Reputation: 13078

Having the same i global variable for both functions causes i takes unexpected values. You can create one function to control the typing, and i will be in the type function's scope:

const h1Txt = "this is h1";
const headerP = "this is paragraph!";

window.addEventListener("load", function() {
  executeAsynchronously([
    [h1Txt, "h1-text", 100],
    [headerP, "p-text", 100]
  ]);
});

function executeAsynchronously(texts) {
  texts.forEach(args => type(...args));
}

function type(text, id, delay) {
  const node = document.getElementById(id);
  for (let i = 0; i < text.length; i++) {
    setTimeout(() => {
      node.textContent += text.charAt(i);
    }, i * delay);
  }
}
<h1 class="text-floating" id="h1-text"></h1>
<p id="p-text"></p>

Upvotes: 1

ksankar
ksankar

Reputation: 485

You are using the same 'i' for both, the characters are gets missed out because of that. I've simplified the code a bit, here'a working sample in codepen:

window.addEventListener('load', function() {
  console.log('typing');

  executeAsynchronously([
    typeText('h1-text', 'this is h1'),
    typeText('p-text', 'this is paragraph!'),
  ], 100);
});

function executeAsynchronously(functions, timeout) {
  for (var i = 0; i < functions.length; i++) {
    setTimeout(functions[i], timeout);
  }
}

function typeText(elementId, text) {
  let idx = 0;
  const element = document.getElementById(elementId);
  let interval;
  interval = setInterval(() => {
    element.innerHTML += text.charAt(idx);
    idx++;
    if (idx == text.length) {
      clearInterval(interval);
    }
  }, 100);
}
<h1 class="text-floating" id="h1-text"></h1>
<p id="p-text"></p>

Upvotes: 0

Nithish
Nithish

Reputation: 5999

The issue in your code is that, you are referring to the same variable i which is declared at the global level in both of your typeWriter functions.

By the time one of the typeWriter function gets executed, i value will be incremented and since both the typeWriter functions are referring to the same one of the character is not getting displayed in the output.

For eg.,

  • typeWriter1 gets executed first at the end of the function execution i will be 1. And in the output it'll print t in the h1Txt text.
  • Now consider typeWriter2 gets its turn and getting executed, now this function is also referring to same i whose value is 1. So, it'll not print t in headerP text.

So, the output is not getting displayed as expected.

Below is one of the ways you can fix this issue i.e., by using two different variables which will be referred in typeWriter functions.

const h1Txt = 'this is h1';
const headerP = 'this is paragraph!';
let i = 0;
let j = 0;

window.addEventListener('load', function() {
  console.log('typing');

  executeAsynchronously([typeWriter, typeWriter2], 100);

});

function executeAsynchronously(functions, timeout) {
  for (var i = 0; i < functions.length; i++) {
    setTimeout(functions[i], timeout);
  }
}
// The typewriter method for h1
function typeWriter() {
  if (i < h1Txt.length) {
    document.getElementById('h1-text').innerHTML += h1Txt.charAt(i);
    i++;
    setTimeout(typeWriter, 100);

  }
}

// The typewriter method for p
function typeWriter2() {
  if (j < headerP.length) {
    document.getElementById('p-text').innerHTML += headerP.charAt(j);
    j++;
    setTimeout(typeWriter2, 100);
  }

}
<h1 class="text-floating" id="h1-text"></h1>
<p id="p-text"></p>

Upvotes: 2

Related Questions