Вызов функций работает нормально, проблема в том, что внутри обратного вызова typewrite
setTimeout
(когда вы вспоминаете typewrite
) вы забыли передать обратный вызов и его параметры самому себе, поэтому они определены только во время первой итерации.
Чтобы он заработал, передайте все аргументы самому себе:
var txtElems = document.querySelectorAll("[data-txt]");
txtElems = Array.from(txtElems);
typewriteAll(txtElems, 70);
function typewriteAll(elemArr, delay) {
if (elemArr.length) {
typewrite(
elemArr[0],
elemArr[0].dataset.txt,
delay,
typewriteAll, elemArr.slice(1), delay
);
}
}
function typewrite(Elem, t, delay, func, arg1, arg2) {
let txt = String(t);
if(txt != ""){
Elem.innerHTML += txt[0];
setTimeout(() => {
typewrite(
Elem,
txt.slice(1, txt.length),
delay,
//here:
func,
arg1,
arg2
)
}, delay)
} else {
setTimeout(() => {
Elem.setAttribute("typing", "end");
func(arg1, arg2)
}, 10 * delay)
}
}
<div data-txt="Some text to type"></div>
<div data-txt="Some more text to type..."></div>
И если вы создаете эффекты пишущей машинки, я настоятельно рекомендую вам использовать setInterval
и функции генератора ES6, поскольку они делают код много читается ... и помогает избежать таких ошибок:
function typewrite(element, text, delay){
return new Promise((resolve, reject) => {
const iterator = (function*() {
try{
for(const letter of text){
element.textContent += letter
yield
}
element.setAttribute("typing", "end");
resolve()
}catch(e){
reject(e)
}finally{
clearTimeout(interval)
}
})()
const interval = setInterval(() => iterator.next(), delay);
iterator.next()
})
}
function typewriteAll(elems, delay){
return elems.reduce((acc,elem) => acc.then(() => typewrite(elem, elem.dataset.txt, delay)), Promise.resolve())
}
var txtElems = document.querySelectorAll("[data-txt]");
txtElems = Array.from(txtElems);
typewriteAll(txtElems, 70)
<div data-txt="Some text to type"></div>
<div data-txt="Some more text to type..."></div>