Issue
I have a function that takes a list of strings, loops over them and prints each one to a new line. I have added in some CSS animations that take a few seconds to have the string fully displayed.
The issue I am facing is that I can't figure out a way to wait for the previous string to be fully displayed before beginning the animation of the next string. I've added a snippet below - sorry if I'm not explaining it well.
Intended Outcome
For each string in the array that we pass into the newComputerMessage(messages) function, it should print a new line but only after the previous line has completely been displayed.
let userInputs = [];
const textBox = document.querySelector(".textBox");
const userInput = document.querySelector(".userInput");
const letters = /^[A-Za-z] $/;
let user = {
name: "",
timeInterval: -1,
halt: false,
quit: false
};
function captureUserInput() {
let text = userInput.value;
userInput.value = "";
return text;
}
function nameEntered() {
enteredName = captureUserInput();
if (!enteredName.match(letters)) {
newComputerMessage(">>Please only use Letters");
} else {
user.name = enteredName;
newComputerMessage([">>Hello there " user.name, ">>Second message"]);
}
}
function newComputerMessage(messages) {
for (let index = 0; index < messages.length; index ) {
const newPElement = document.createElement("p");
newPElement.innerHTML = messages[index];
newPElement.setAttribute("class", "computerText");
textBox.appendChild(newPElement);
}
}
.textBox {
width: max-content;
}
.computerText {
color: black;
font-family: monospace;
overflow: hidden;
border-right: 0.15em solid orange;
white-space: nowrap;
margin: 0 auto 0 0;
letter-spacing: 0.15em;
animation: typing 3.5s steps(30, end), blink-caret 0.5s step-end infinite;
width: max-content;
}
/* The typing effect */
@keyframes typing {
from {
width: 0;
}
to {
width: 100%;
}
}
/* The typewriter cursor effect */
@keyframes blink-caret {
from,
to {
border-color: transparent;
}
50% {
border-color: orange;
}
}
<body>
<div >
<div >
<p >>>Hello, please enter your name below</p>
</div>
</div>
<div >
<input class='userInput' type="text" name="fname"><br>
<input onclick="nameEntered()" type="submit" value="Submit">
</div>
</div>
</body>
CodePudding user response:
You can use setTimeout as shown below. First snippet is a working example. Second snippet is how it would look in your code:
I have taken 3500
miliseconds because I noticed 3.5s
as the time for your animation in your CSS. You can vary that as per your needs.
function newComputerMessage() {
for (let index = 0; index < 3; index ) {
setTimeout(() => console.log('appending element'), 3500 * index);
}
}
newComputerMessage();
So in terms of your code it will be:
function newComputerMessage(messages) {
for (let index = 0; index < messages.length; index ) {
const newPElement = document.createElement("p");
newPElement.innerHTML = messages[index];
newPElement.setAttribute("class", "computerText");
setTimeout(() => textBox.appendChild(newPElement), 3500 * index);
}
}