Search code examples
javascriptinputplaceholder

Animate placeholder text so it types MULTIPLE phrases


I'm using this code from jsfiddle to animate the placeholder text in my search bar. The end result is it looks like it is being typed. Right now it only types one phrase and I would like to get it to type one phrase and then replace with another and so on. Any help wold be appreciated.

// your custom placeholder goes here!
var ph = "Search Website e.g. \"Dancing Cats\"",
    searchBar = $('#search'),
    // placeholder loop counter
    phCount = 0;

// function to return random number between
// with min/max range
function randDelay(min, max) {
    return Math.floor(Math.random() * (max-min+1)+min);
}

// function to print placeholder text in a 
// 'typing' effect
function printLetter(string, el) {
    // split string into character seperated array
    var arr = string.split(''),
        input = el,
        // store full placeholder
        origString = string,
        // get current placeholder value
        curPlace = $(input).attr("placeholder"),
        // append next letter to current placeholder
        placeholder = curPlace + arr[phCount];

    setTimeout(function(){
        // print placeholder text
        $(input).attr("placeholder", placeholder);
        // increase loop count
        phCount++;
        // run loop until placeholder is fully printed
        if (phCount < arr.length) {
            printLetter(origString, input);
        }
    // use random speed to simulate
    // 'human' typing
    }, randDelay(50, 90));
}  

// function to init animation
function placeholder() {
    $(searchBar).attr("placeholder", "");
    printLetter(ph, searchBar);
}

placeholder();
$('.submit').click(function(e){
    phCount = 0;
    e.preventDefault();
    placeholder();
});

Solution

  • Check out my ES6 Promise based solution. Hope this helps.

    // Add something to given element placeholder
    function addToPlaceholder(toAdd, el) {
        el.attr('placeholder', el.attr('placeholder') + toAdd);
        // Delay between symbols "typing" 
        return new Promise(resolve => setTimeout(resolve, 100));
    }
    
    // Cleare placeholder attribute in given element
    function clearPlaceholder(el) {
        el.attr("placeholder", "");
    }
    
    // Print one phrase
    function printPhrase(phrase, el) {
        return new Promise(resolve => {
            // Clear placeholder before typing next phrase
            clearPlaceholder(el);
            let letters = phrase.split('');
            // For each letter in phrase
            letters.reduce(
                (promise, letter, index) => promise.then(_ => {
                    // Resolve promise when all letters are typed
                    if (index === letters.length - 1) {
                        // Delay before start next phrase "typing"
                        setTimeout(resolve, 1000);
                    }
                    return addToPlaceholder(letter, el);
                }),
                Promise.resolve()
            );
        });
    } 
    
    // Print given phrases to element
    function printPhrases(phrases, el) {
        // For each phrase
        // wait for phrase to be typed
        // before start typing next
        phrases.reduce(
            (promise, phrase) => promise.then(_ => printPhrase(phrase, el)), 
            Promise.resolve()
        );
    }
    
    // Start typing
    function run() {
        let phrases = [
            "Search Website e.g. \"Dancing Cats\"",
            "Lorem ipsum dolor sit amet",
            "Consectetur adipiscing elit",
            "JS is so strange :)"
        ];
    
        printPhrases(phrases, $('#search'));
    }
    
    run();
    .searchbar {
        width: 300px;
        padding: 10px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width">
        <title>Bin</title>
    </head>
    <body>
        <input type='text' id="search" class="searchbar" />
    </body>
    </html>