Search code examples
javascriptarraysanimationtext

animation of text array stops after a few entries


I've got a script displaying multiple words stored in a text array in some sort of typewriter style. However, the script stops after a few entries and does not run through all the words in the array as supposed to. Maybe I can't see the obvious issue, but please, can I get a hint?

Here's a pen of it: https://codepen.io/jackennils/pen/KKeVEbJ

document.addEventListener('DOMContentLoaded', function(event) {
    // array with texts to type in typewriter
    var dataText = ["Holz", "Schiefer", "Jeans", "Edelstahl", "Spiegel", "Acryl", "Leder", "Kork", "Fliesen", "Stein"];

    // type one text in the typwriter
    // keeps calling itself until the text is finished
    function typeWriter(text, i, fnCallback) {
        // check if text isn't finished yet
        if (i < (text.length)) {
            // add next character to span
            document.querySelector("span.mats").innerHTML = text.substring(0, i + 1) + '<span class="mats-inner" aria-hidden="true"></span>';

            // wait for a while and call this function again for next character
            setTimeout(function() {
                typeWriter(text, i + 1, fnCallback)
            }, 100);
        }
        // text finished, call callback if there is a callback function
        else if (typeof fnCallback == 'function') {
            // call callback after timeout
            setTimeout(fnCallback, 1000);
        }
    }
    // start a typewriter animation for a text in the dataText array
    function StartTextAnimation(i) {
        if (typeof dataText[i] == 'undefined') {
            setTimeout(function() {
                StartTextAnimation(0);
            }, 0);
        }
        // check if dataText[i] exists
        if (i < dataText[i].length) {
            // text exists! start typewriter animation
            typeWriter(dataText[i], 0, function() {
                // after callback (and whole text has been animated), start next text
                StartTextAnimation(i + 1);
            });
        }
    }
    // start the text animation
    StartTextAnimation(0);
});
body {
    background-color: #362871;
    height: 100%;
    font-family: 'Raleway', sans-serif;
}

p {
    font-size: 5em;
    color: white;
    text-transform: uppercase;
}

span.mats-inner {
    border-right: 20px solid;
    margin-left: 10px;
    animation: caret 1s steps(1) infinite;
}

@keyframes caret {
    50% {
        border-color: transparent;
    }
}
<p>Wir veredeln <span class="mats">mit Licht</span></p>


Solution

  • It was really small logical mistake at the condition of the if statement.

    if (i < dataText[i].length)
    

    Here you are comparing i to the string length of the word but it has nothing to with string length. Instead, compare it with array length because it is fixed.

    document.addEventListener('DOMContentLoaded', function(event) {
        // array with texts to type in typewriter
        var dataText = ["Holz", "Schiefer", "Jeans", "Edelstahl", "Acryl", "Leder", "Kork", "Fliesen", "Stein"];
    
        // type one text in the typwriter
        // keeps calling itself until the text is finished
        function typeWriter(text, i, fnCallback) {
            // check if text isn't finished yet
            if (i < (text.length)) {
                // add next character to span
                document.querySelector("span.mats").innerHTML = text.substring(0, i + 1) + '<span class="mats-inner" aria-hidden="true"></span>';
    
                // wait for a while and call this function again for next character
                setTimeout(function() {
                    typeWriter(text, i + 1, fnCallback)
                }, 100);
            }
            // text finished, call callback if there is a callback function
            else if (typeof fnCallback == 'function') {
                // call callback after timeout
                setTimeout(fnCallback, 1000);
            }
        }
        // start a typewriter animation for a text in the dataText array
        function StartTextAnimation(i) {
            console.log(i)
            if (typeof dataText[i] == 'undefined') {
                setTimeout(function() {
                    StartTextAnimation(0);
                }, 0);
            }
            // check if dataText[i] exists
            if (i < dataText.length) {
                // text exists! start typewriter animation
                typeWriter(dataText[i], 0, function() {
                    // after callback (and whole text has been animated), start next text
                    StartTextAnimation(i + 1);
                });
            }
        }
        // start the text animation
        StartTextAnimation(0);
    });
    body {
        background-color: #362871;
        height: 100%;
        font-family: 'Raleway', sans-serif;
    }
    
    p {
        font-size: 5em;
        color: white;
        text-transform: uppercase;
    }
    
    span.mats-inner {
        border-right: 20px solid;
        margin-left: 10px;
        animation: caret 1s steps(1) infinite;
    }
    
    @keyframes caret {
        50% {
            border-color: transparent;
        }
    }
    <p>Wir veredeln <span class="mats">mit Licht</span></p>