class Typer { constructor(options){ this.options = Object.assign(this.defaults, options || {}) this.elem = document.querySelector(this.options.elementSelector); this.stringsElem = document.querySelectorAll(this.options.stringsSelector); this._initStrings(this.stringsElem); this.strings = this.options.strings; this._addCursor(); this.currentStringIndex = 0; this.rotateStrings(); } rotateStrings(index){ index = index || 0; this.type(this.strings[this.currentStringIndex]); } type(string, charPos){ charPos = charPos || 0; this.elem.innerHTML = string.substring(0, charPos); if(string.length > charPos){ setTimeout(()=>{ this.type(string, ++charPos); }, 200) } else { this.backspace(); } } backspace(){ let string = this.elem.innerHTML; if(string.length > 0){ setTimeout(()=>{ this.elem.innerHTML = string.substr(0, string.length-1); this.backspace(); }, 100); } else { if(this.currentStringIndex < this.strings.length-1){ this.currentStringIndex++; } else { this.currentStringIndex = 0; } this.rotateStrings() } } defaults = { strings: [], elementSelector: null, stringsSelector: null, } _initStrings(stringsElem){ stringsElem[0].parentElement.style.display = 'none'; this.options.strings = Array.from(stringsElem).map((elem)=>{ return elem.innerHTML; }) } _addCursor(){ let cursorHtml= `<span class=\'typer-cursor\'>_<\span>`; this.elem.insertAdjacentHTML('afterend', cursorHtml); } } var typer = new Typer({ elementSelector: '.typer', stringsSelector: '.typer-items li' });
<div> <span>I am a </span><span class="typer"></span> <ul class='typer-items'> <li>software engineer</li> <li>motorcyclist</li> <li>mongolian speaker</li> <li>vim enthuiast</li> <li>command line evangelist</li> </ul> </div>
.typer-cursor { opacity: 1; -webkit-animation: blink 0.7s infinite; -moz-animation: blink 0.7s infinite; animation: blink 0.7s infinite; } @keyframes blink { 0% { opacity: 1; } 50% { opacity: 0; } 100% { opacity: 1; } }