1// The MIT License (MIT) 2 3// Typed.js | Copyright (c) 2016 Matt Boldt | www.mattboldt.com 4 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to deal 7// in the Software without restriction, including without limitation the rights 8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9// copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21// THE SOFTWARE. 22 23 24 25 26! function(window, document, $) { 27 28 "use strict"; 29 30 var Typed = function(el, options) { 31 var self = this; 32 33 // chosen element to manipulate text 34 this.el = el; 35 36 // options 37 this.options = {}; 38 Object.keys(defaults).forEach(function(key) { 39 self.options[key] = defaults[key]; 40 }); 41 Object.keys(options).forEach(function(key) { 42 self.options[key] = options[key]; 43 }); 44 45 // attribute to type into 46 this.isInput = this.el.tagName.toLowerCase() === 'input'; 47 this.attr = this.options.attr; 48 49 // show cursor 50 this.showCursor = this.isInput ? false : this.options.showCursor; 51 52 // text content of element 53 this.elContent = this.attr ? this.el.getAttribute(this.attr) : this.el.textContent; 54 55 // html or plain text 56 this.contentType = this.options.contentType; 57 58 // typing speed 59 this.typeSpeed = this.options.typeSpeed; 60 61 // add a delay before typing starts 62 this.startDelay = this.options.startDelay; 63 64 // backspacing speed 65 this.backSpeed = this.options.backSpeed; 66 67 // amount of time to wait before backspacing 68 this.backDelay = this.options.backDelay; 69 70 // Fade out instead of backspace 71 this.fadeOut = this.options.fadeOut; 72 this.fadeOutClass = this.options.fadeOutClass; 73 this.fadeOutDelay = this.options.fadeOutDelay; 74
75 // div containing strings 76 if($ && this.options.stringsElement instanceof $) { 77 this.stringsElement = this.options.stringsElement[0] 78 } else { 79 this.stringsElement = this.options.stringsElement; 80 } 81 82 // input strings of text 83 this.strings = this.options.strings; 84 85 // character number position of current string 86 this.strPos = 0; 87 88 // current array position 89 this.arrayPos = 0; 90 91 // number to stop backspacing on. 92 // default 0, can change depending on how many chars 93 // you want to remove at the time 94 this.stopNum = 0; 95 96 // Looping logic 97 this.loop = this.options.loop; 98 this.loopCount = this.options.loopCount; 99 this.curLoop = 0; 100 101 // for stopping 102 this.stop = false; 103 104 // custom cursor 105 this.cursorChar = this.options.cursorChar; 106 107 // shuffle the strings 108 this.shuffle = this.options.shuffle; 109 // the order of strings 110 this.sequence = []; 111 112 // All systems go! 113 this.build(); 114 }; 115 116 Typed.prototype = { 117 118 constructor: Typed, 119 120 init: function() { 121 // begin the loop w/ first current string (global self.strings) 122 // current string will be passed as an argument each time after this 123 var self = this; 124 self.timeout = setTimeout(function() { 125 for (var i=0;i<self.strings.length;++i) self.sequence[i]=i; 126 127 // shuffle the array if true 128 if(self.shuffle) self.sequence = self.shuffleArray(self.sequence); 129 130 // Start typing 131 self.typewrite(self.strings[self.sequence[self.arrayPos]], self.strPos); 132 }, self.startDelay); 133 }, 134 135 build: function() { 136 var self = this; 137 // Insert cursor 138 if (this.showCursor === true) { 139 this.cursor = document.createElement('span'); 140 this.cursor.className = 'typed-cursor'; 141 this.cursor.innerHTML = this.cursorChar; 142 this.el.parentNode && this.el.parentNode.insertBefore(this.cursor, this.el.nextSibling); 143 } 144 if (this.stringsElement) { 145 this.strings = []; 146 this.stringsElement.style.display = 'none'; 147 var strings = Array.prototype.slice.apply(this.stringsElement.children); 148 strings.forEach(function(stringElement){ 149 self.strings.push(stringElement.innerHTML); 150 }); 151 } 152 this.init(); 153 }, 154 155 // pass current string state to each function, types 1 char per call 156 typewrite: function(curString, curStrPos) { 157 // exit when stopped 158 if (this.stop === true) { 159 return; 160 } 161 162 if (this.fadeOut && this.el.classList.contains(this.fadeOutClass)) { 163 this.el.classList.remove(this.fadeOutClass); 164 this.cursor.classList.remove(this.fadeOutClass); 165 } 166 167 // varying values for setTimeout during typing 168 // can't be global since number changes each time loop is executed 169 var humanize = Math.round(Math.random() * (100 - 30)) + this.typeSpeed; 170 var self = this; 171 172 // ------------- optional ------------- // 173 // backpaces a certain string faster 174 // ------------------------------------ // 175 // if (self.arrayPos == 1){ 176 // self.backDelay = 50; 177 // } 178 // else{ self.backDelay = 500; } 179 180 // contain typing function in a timeout humanize'd delay 181 self.timeout = setTimeout(function() { 182 // check for an escape character before a pause value 183 // format: \^\d+ .. eg: ^1000 .. should be able to print the ^ too using ^^ 184 // single ^ are removed from string 185 var charPause = 0; 186 var substr = curString.substr(curStrPos); 187 if (substr.charAt(0) === '^') { 188 var skip = 1; // skip atleast 1 189 if (/^\^\d+/.test(substr)) { 190 substr = /\d+/.exec(substr)[0]; 191 skip += substr.length; 192 charPause = parseInt(substr); 193 } 194 195 // strip out the escape character and pause value so they're not printed 196 curString = curString.substring(0, curStrPos) + curString.substring(curStrPos + skip); 197 } 198 199 if (self.contentType === 'html') { 200 // skip over html tags while typing 201 var curChar = curString.substr(curStrPos).charAt(0); 202 if (curChar === '<' || curChar === '&') { 203 var tag = ''; 204 var endTag = ''; 205 if (curChar === '<') { 206 endTag = '>' 207 } 208 else { 209 endTag = ';' 210 } 211 while (curString.substr(curStrPos + 1).charAt(0) !== endTag) { 212 tag += curString.substr(curStrPos).charAt(0); 213 curStrPos++; 214 if (curStrPos + 1 > curString.length) { break; } 215 } 216 curStrPos++; 217 tag += endTag; 218 } 219 } 220 221 // timeout for any pause after a character 222 self.timeout = setTimeout(function() { 223 if (curStrPos === curString.length) { 224 // fires callback function 225 self.options.onStringTyped(self.arrayPos); 226 227 // is this the final string 228 if (self.arrayPos === self.strings.length - 1) { 229 // animation that occurs on the last typed string 230 self.options.callback(); 231 232 self.curLoop++; 233 234 // quit if we wont loop back 235 if (self.loop === false || self.curLoop === self.loopCount) 236 return; 237 } 238 239 self.timeout = setTimeout(function() { 240 self.backspace(curString, curStrPos); 241 }, self.backDelay); 242 243 } else { 244 245 /* call before functions if applicable */ 246 if (curStrPos === 0) { 247 self.options.preStringTyped(self.arrayPos); 248 } 249
250 // start typing each new char into existing string 251 // curString: arg, self.el.html: original text inside element 252 var nextString = curString.substr(0, curStrPos + 1); 253 if (self.attr) { 254 self.el.setAttribute(self.attr, nextString); 255 } else { 256 if (self.isInput) { 257 self.el.value = nextString; 258 } else if (self.contentType === 'html') { 259 self.el.innerHTML = nextString; 260 } else { 261 self.el.textContent = nextString; 262 } 263 } 264 265 // add characters one by one 266 curStrPos++; 267 // loop the function 268 self.typewrite(curString, curStrPos); 269 } 270 // end of character pause 271 }, charPause); 272 273 // humanized value for typing 274 }, humanize); 275 276 }, 277 278 backspace: function(curString, curStrPos) { 279 var self = this; 280 // exit when stopped 281 if (this.stop === true) { 282 return; 283 } 284 285 if (this.fadeOut){ 286 this.initFadeOut(); 287 return; 288 } 289 290 // varying values for setTimeout during typing 291 // can't be global since number changes each time loop is executed 292 var humanize = Math.round(Math.random() * (100 - 30)) + this.backSpeed; 293 294 self.timeout = setTimeout(function() { 295 296 // ----- this part is optional ----- // 297 // check string array position 298 // on the first string, only delete one word 299 // the stopNum actually represents the amount of chars to 300 // keep in the current string. In my case it's 14. 301 // if (self.arrayPos == 1){ 302 // self.stopNum = 14; 303 // } 304 //every other time, delete the whole typed string 305 // else{ 306 // self.stopNum = 0; 307 // } 308 309 if (self.contentType === 'html') { 310 // skip over html tags while backspacing 311 if (curString.substr(curStrPos).charAt(0) === '>') { 312 var tag = ''; 313 while (curString.substr(curStrPos - 1).charAt(0) !== '<') { 314 tag -= curString.substr(curStrPos).charAt(0); 315 curStrPos--; 316 if (curStrPos < 0) { break; } 317 } 318 curStrPos--; 319 tag += '<'; 320 } 321 } 322 323 // ----- continue important stuff ----- // 324 // replace text with base text + typed characters 325 var nextString = curString.substr(0, curStrPos); 326 self.replaceText(nextString); 327 328 // if the number (id of character in current string) is 329 // less than the stop number, keep going 330 if (curStrPos > self.stopNum) { 331 // subtract characters one by one 332 curStrPos--; 333 // loop the function 334 self.backspace(curString, curStrPos); 335 } 336 // if the stop number has been reached, increase 337 // array position to next string 338 else if (curStrPos <= self.stopNum) { 339 self.arrayPos++; 340 341 if (self.arrayPos === self.strings.length) { 342 self.arrayPos = 0; 343 344 // Shuffle sequence again 345 if(self.shuffle) self.sequence = self.shuffleArray(self.sequence); 346 347 self.init(); 348 } else 349 self.typewrite(self.strings[self.sequence[self.arrayPos]], curStrPos); 350 } 351 352 // humanized value for typing 353 }, humanize); 354 355 }, 356 357 // Adds a CSS class to fade out current string 358 initFadeOut: function(){ 359 self = this; 360 this.el.className += ' ' + this.fadeOutClass; 361 this.cursor.className += ' ' + this.fadeOutClass; 362 return setTimeout(function() { 363 self.arrayPos++; 364 self.replaceText(''); 365 366 // Resets current string if end of loop reached 367 if(self.strings.length > self.arrayPos) { 368 self.typewrite(self.strings[self.sequence[self.arrayPos]], 0); 369 } else { 370 self.typewrite(self.strings[0], 0); 371 self.arrayPos = 0; 372 } 373 }, self.fadeOutDelay); 374 }, 375 376 // Replaces current text in the HTML element 377 replaceText: function(str) { 378 if (this.attr) { 379 this.el.setAttribute(this.attr, str); 380 } else { 381 if (this.isInput) { 382 this.el.value = str; 383 } else if (this.contentType === 'html') { 384 this.el.innerHTML = str; 385 } else { 386 this.el.textContent = str; 387 } 388 } 389 }, 390 391 // Shuffles the numbers in the given array. 392 shuffleArray: function(array) { 393 var tmp, current, top = array.length; 394 if(top) while(--top) { 395 current = Math.floor(Math.random() * (top + 1)); 396 tmp = array[current]; 397 array[current] = array[top]; 398 array[top] = tmp; 399 } 400 return array; 401 }, 402 403 // Start & Stop currently not working 404 405 // , stop: function() { 406 // var self = this; 407 408 // self.stop = true; 409 // clearInterval(self.timeout); 410 // } 411 412 // , start: function() { 413 // var self = this; 414 // if(self.stop === false) 415 // return; 416 417 // this.stop = false;
418 // this.init(); 419 // } 420 421 // Reset and rebuild the element 422 reset: function() { 423 var self = this; 424 clearInterval(self.timeout); 425 var id = this.el.getAttribute('id'); 426 this.el.textContent = ''; 427 if (typeof this.cursor !== 'undefined' && typeof this.cursor.parentNode !== 'undefined') { 428 this.cursor.parentNode.removeChild(this.cursor); 429 } 430 this.strPos = 0; 431 this.arrayPos = 0; 432 this.curLoop = 0; 433 // Send the callback 434 this.options.resetCallback(); 435 } 436 437 }; 438 439 Typed.new = function(selector, option) { 440 var elements = Array.prototype.slice.apply(document.querySelectorAll(selector)); 441 elements.forEach(function(element) { 442 var instance = element._typed, 443 options = typeof option == 'object' && option; 444 if (instance) { instance.reset(); } 445 element._typed = instance = new Typed(element, options); 446 if (typeof option == 'string') instance[option](); 447 }); 448 }; 449 450 if ($) { 451 $.fn.typed = function(option) { 452 return this.each(function() { 453 var $this = $(this), 454 data = $this.data('typed'), 455 options = typeof option == 'object' && option; 456 if (data) { data.reset(); } 457 $this.data('typed', (data = new Typed(this, options))); 458 if (typeof option == 'string') data[option](); 459 }); 460 }; 461 } 462 463 window.Typed = Typed; 464 465 var defaults = { 466 strings: ["These are the default values...", "You know what you should do?", "Use your own!", "Have a great day!"], 467 stringsElement: null, 468 // typing speed 469 typeSpeed: 0, 470 // time before typing starts 471 startDelay: 0, 472 // backspacing speed 473 backSpeed: 0, 474 // shuffle the strings 475 shuffle: false, 476 // time before backspacing 477 backDelay: 500, 478 // Fade out instead of backspace 479 fadeOut: false, 480 fadeOutClass: 'typed-fade-out', 481 fadeOutDelay: 500, // milliseconds 482 // loop 483 loop: false, 484 // false = infinite 485 loopCount: false, 486 // show cursor 487 showCursor: true, 488 // character for cursor 489 cursorChar: "|", 490 // attribute to type (null == text) 491 attr: null, 492 // either html or text 493 contentType: 'html', 494 // call when done callback function 495 callback: function() {}, 496 // starting callback function before each string 497 preStringTyped: function() {}, 498 //callback for every typed string 499 onStringTyped: function() {}, 500 // callback for reset 501 resetCallback: function() {} 502 }; 503 504 505}(window, document, window.jQuery);
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.