typingEffect()
iterates through an array of strings that type out on the screen like a chatbot. I originally put typedMessage.textContent = "";
inside typingFunction()
to simplify things, but it was really hard to time the clearing text feature with how long some of the strings are.
I tried to change the timing around, but because the loop function can only be set to one set time(I think), I couldn't make it work.
Is there a better way to write this so it's more repeatable, while being able to manipulate the timing of the typedMessage.textContent = "";
. Any help is greatly appreciated!
const body = document.querySelector("body");
const typedMessage = document.querySelector("div");
const messageArray = ["Welcome to your new chatBuddy!", "I want to ask you a few questions...",
"Some of them might be kind of weird..", "But, hey... we're pals, right?!",
"After all, my name is ChatBuddy, so...let's do this!", "Would you rather have no arms or no legs?"];
/**
* function typingEffect()
* iterates through messageArray[] to type out messages
* setTimeout feature to iterate through characters/clear text
* @param {string} message
* @param {string} item
* @param {integer} i
* @returns
*/
const typingEffect = (message, item, i = 0) => {
message.textContent += item[i];
if (i === item.length - 1) {
return;
}
setTimeout(() => {
typingEffect(message, item, i + 1)
}, 30);
}
typingEffect(typedMessage, messageArray[0]);
setTimeout(() => {
typedMessage.textContent = "";
}, 3000)
setTimeout(() => {
typingEffect(typedMessage, messageArray[1]);
}, 3100)
setTimeout(() => {
typedMessage.textContent = "";
}, 7000)
setTimeout(() => {
typingEffect(typedMessage, messageArray[2]);
}, 7100)
setTimeout(() => {
typedMessage.textContent = "";
}, 11000)
setTimeout(() => {
typingEffect(typedMessage, messageArray[3]);
}, 11100)
setTimeout(() => {
typedMessage.textContent = "";
}, 15000)
For a start, create two functions, one that types messages and the other that accepts an Array and passes each message to the first one after a timeout of 2sec:
const typingText = (elem, txt, done = () => {}) => {
let i = 0;
elem.textContent = ""; // Clear before typing!
const next = () => {
elem.textContent += txt[i];
if (i === txt.length - 1) return done();
i += 1;
setTimeout(next, 30);
};
next(); // Start!
};
const typingArray = (elem, arr, done = () => {}) => {
let i = 0;
const next = () => {
typingText(elem, arr[i], () => {
if (i === arr.length - 1) return done();
i += 1;
setTimeout(next, 2000);
});
};
next(); // Start!
};
const elDiv = document.querySelector("div");
const messages = [
"Welcome to your new chatBuddy!",
"I want to ask you a question...",
"Can you combine the two functions into one?"
];
typingArray(elDiv, messages, () => { console.log("All done!"); });
<div></div>
Both function have a done
function that calls on completion, text typed for the first one, and after all the array is typed - for the second function.
For homework (since the two functions are pretty similar) you can try to convert them into a single blueprint function that accepts either a String or an Array of Strings; and use accordingly.