PageSourceSearch

https://mobstep.com/assets/js/typing-placeholder.js?v=0a13cc05

js mobstep.com collected 2026-10-02 01:36:08 UTC 3,274 bytes, 92 lines download raw bytes

1class TypingPlaceholder {
2    constructor(element) {
3        // Handle both selector string and element object
4        this.input = typeof element === 'string' ? document.querySelector(element) : element;
5        if (!this.input) return;
6        
7        this.phrases = this.input.getAttribute('data-typing')?.split('|') || [];
8        this.typingSpeed = parseInt(this.input.getAttribute('data-typing-speed')) || 50;
9        this.backspaceSpeed = parseInt(this.input.getAttribute('data-typing-backspace-speed')) || 30;
10        this.pauseDuration = parseInt(this.input.getAttribute('data-typing-pause')) || 2000;
11        
12        this.currentPhraseIndex = 0;
13        this.currentCharIndex = 0;
14        this.isTyping = true;
15        this.isPaused = false;
16        
17        this.originalPlaceholder = this.input.getAttribute('placeholder');
18        this.init();
19    }
20    
21    init() {
22        // Start typing animation
23        this.type();
24        
25        // Handle focus/blur events
26        this.input.addEventListener('focus', () => {
27            this.input.setAttribute('placeholder', this.originalPlaceholder);
28        });
29        
30        this.input.addEventListener('blur', () => {
31            if (!this.input.value) {
32                this.animate();
33            }
34        });
35        
36        // Start animation if input is empty
37        if (!this.input.value) {
38            this.animate();
39        }
40    }
41    
42    animate() {
43        this.currentPhraseIndex = 0;
44        this.currentCharIndex = 0;
45        this.isTyping = true;
46        this.isPaused = false;
47        this.type();
48    }
49    
50    type() {
51        if (this.isPaused) return;
52        
53        const currentPhrase = this.phrases[this.currentPhraseIndex];
54        
55        if (this.isTyping) {
56            // Typing characters
57            if (this.currentCharIndex < currentPhrase.length) {
58                this.input.setAttribute('placeholder', currentPhrase.substring(0, this.currentCharIndex + 1));
59                this.currentCharIndex++;
60                setTimeout(() => this.type(), this.typingSpeed);
61            } else {
62                // Finished typing, pause before backspace
63                this.isTyping = false;
64                this.isPaused = true;
65                setTimeout(() => {
66                    this.isPaused = false;
67                    this.type();
68                }, this.pauseDuration);
69            }
70        } else {
71            // Backspacing characters
72            if (this.currentCharIndex > 0) {
73                this.input.setAttribute('placeholder', currentPhrase.substring(0, this.currentCharIndex - 1));
74                this.currentCharIndex--;
75                setTimeout(() => this.type(), this.backspaceSpeed);
76            } else {
77                // Move to next phrase
78                this.currentPhraseIndex = (this.currentPhraseIndex + 1) % this.phrases.length;
79                this.isTyping = true;
80                setTimeout(() => this.type(), 500); // Brief pause before next phrase
81            }
82        }
83    }
84}
85
86// Initialize typing placeholders
87document.addEventListener('DOMContentLoaded', () => {
88    const typingInputs = document.querySelectorAll('[data-typing]');
89    typingInputs.forEach(input => {
90        new TypingPlaceholder(input);
91    });
92});

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.