PageSourceSearch

https://agustinsanchez.net/user/themes/agustin/js/typed.js?g-bf9b493f

js agustinsanchez.net collected 2026-10-02 02:00:53 UTC 14,324 bytes, 505 lines download raw bytes

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.