1var Typer = function(element) { 2 this.element = element; 3 var delim = element.dataset.delim || ","; 4 var words = element.dataset.words || "override these,sample typing"; 5 this.words = words.split(delim).filter((v) => v); // non empty words 6 this.delay = element.dataset.delay || 200; 7 this.loop = element.dataset.loop || "true"; 8 if (this.loop === "false" ) { this.loop = 1 } 9 this.deleteDelay = element.dataset.deletedelay || element.dataset.deleteDelay || 800; 10 11 this.progress = { word: 0, char: 0, building: true, looped: 0 }; 12 this.typing = true; 13 14 var colors = element.dataset.colors || "black"; 15 this.colors = colors.split(","); 16 this.element.style.color = this.colors[0]; 17 this.colorIndex = 0; 18 19 this.doTyping(); 20}; 21 22Typer.prototype.start = function() { 23 if (!this.typing) { 24 this.typing = true; 25 this.doTyping(); 26 } 27}; 28Typer.prototype.stop = function() { 29 this.typing = false; 30}; 31Typer.prototype.doTyping = function() { 32 var e = this.element; 33 var p = this.progress; 34 var w = p.word; 35 var c = p.char; 36 var currentDisplay = [...this.words[w]].slice(0, c).join(""); 37 var atWordEnd; 38 if (this.cursor) { 39 this.cursor.element.style.opacity = "1"; 40 this.cursor.on = true; 41 clearInterval(this.cursor.interval); 42 this.cursor.interval = setInterval(() => this.cursor.updateBlinkState(), 400); 43 } 44 45 e.innerHTML = currentDisplay; 46 47 if (p.building) { 48 atWordEnd = p.char === this.words[w].length; 49 if (atWordEnd) { 50 p.building = false; 51 } else { 52 p.char += 1; 53 } 54 } else { 55 if (p.char === 0) { 56 p.building = true; 57 p.word = (p.word + 1) % this.words.length; 58 this.colorIndex = (this.colorIndex + 1) % this.colors.length; 59 this.element.style.color = this.colors[this.colorIndex]; 60 } else { 61 p.char -= 1; 62 } 63 } 64 65 if (p.word === this.words.length - 1) { 66 p.looped += 1; 67 } 68 69 if (!p.building && this.loop <= p.looped){ 70 this.typing = false; 71 } 72 73 setTimeout(() => { 74 if (this.typing) { this.doTyping() }; 75 }, atWordEnd ? this.deleteDelay : this.delay); 76}; 77 78var Cursor = function(element) { 79 this.element = element; 80 this.cursorDisplay = element.dataset.cursordisplay || element.dataset.cursorDisplay || "_"; 81 element.innerHTML = this.cursorDisplay; 82 this.on = true; 83 element.style.transition = "all 0.1s"; 84 this.interval = setInterval(() => this.updateBlinkState(), 400); 85} 86Cursor.prototype.updateBlinkState = function() { 87 if (this.on) { 88 this.element.style.opacity = "0"; 89 this.on = false; 90 } else { 91 this.element.style.opacity = "1"; 92 this.on = true; 93 } 94} 95 96function TyperSetup() { 97 var typers = {}; 98 for (let e of document.getElementsByClassName("typer")) { 99 typers[e.id] = new Typer(e); 100 } 101 for (let e of document.getElementsByClassName("typer-stop")) { 102 let owner = typers[e.dataset.owner]; 103 e.onclick = () => owner.stop(); 104 } 105 for (let e of document.getElementsByClassName("typer-start")) { 106 let owner = typers[e.dataset.owner]; 107 e.onclick = () => owner.start(); 108 } 109 for (let e of document.getElementsByClassName("cursor")) { 110 let t = new Cursor(e); 111 t.owner = typers[e.dataset.owner]; 112 t.owner.cursor = t; 113 } 114} 115 116TyperSetup();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.