PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / animated-text / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/animated-text/frontend.js

131 lines 4.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 'use strict';
3
4 var reducedMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
5
6 function initAnimatedText(el) {
7 var rawWords = el.getAttribute('data-words');
8 var words;
9 try { words = JSON.parse(rawWords); } catch (e) { return; }
10
11 if (!words || words.length < 1) return;
12
13 var effect = el.getAttribute('data-effect') || 'typewriter';
14 var typingSpeed = parseInt(el.getAttribute('data-typing-speed'), 10) || 80;
15 var deletingSpeed = parseInt(el.getAttribute('data-deleting-speed'), 10) || 40;
16 var pause = parseInt(el.getAttribute('data-pause'), 10) || 2000;
17 var loop = el.getAttribute('data-loop') !== '0';
18 var showCursor = el.getAttribute('data-cursor') !== '0';
19 var cursorChar = el.getAttribute('data-cursor-char') || '|';
20
21 var wordText = el.querySelector('.bkbg-at-word-text');
22 var cursorEl = el.querySelector('.bkbg-at-cursor');
23
24 if (!wordText) return;
25
26 // If reduced motion — just show first word statically
27 if (reducedMotion) {
28 wordText.textContent = words[0] || '';
29 if (cursorEl) cursorEl.remove();
30 return;
31 }
32
33 var currentIndex = 0;
34
35 if (effect === 'typewriter') {
36 // ── Typewriter engine ─────────────────────────────────────────────
37 var currentText = '';
38 var isDeleting = false;
39 var isPaused = false;
40
41 function tick() {
42 var word = words[currentIndex] || '';
43 if (isDeleting) {
44 currentText = word.substring(0, currentText.length - 1);
45 } else {
46 currentText = word.substring(0, currentText.length + 1);
47 }
48
49 wordText.textContent = currentText;
50
51 var nextDelay;
52
53 if (!isDeleting && currentText === word) {
54 // Finished typing — pause then delete
55 if (!loop && currentIndex === words.length - 1) return; // stop at last word
56 nextDelay = pause;
57 isDeleting = true;
58 } else if (isDeleting && currentText === '') {
59 // Finished deleting — move to next word
60 isDeleting = false;
61 currentIndex = (currentIndex + 1) % words.length;
62 nextDelay = 200;
63 } else {
64 nextDelay = isDeleting ? deletingSpeed : typingSpeed;
65 // Natural randomness
66 nextDelay += Math.floor(Math.random() * 30) - 15;
67 if (nextDelay < 5) nextDelay = 5;
68 }
69
70 setTimeout(tick, nextDelay);
71 }
72
73 // Start after a brief initial delay
74 setTimeout(tick, 600);
75
76 } else {
77 // ── CSS animation cycling ─────────────────────────────────────────
78 var animDuration = 350; // ms — matches CSS animation durations
79
80 function showWord(index) {
81 wordText.textContent = words[index];
82 el.classList.remove('is-leaving');
83 el.classList.add('is-entering');
84
85 // Remove entering class after animation
86 setTimeout(function () {
87 el.classList.remove('is-entering');
88 }, animDuration);
89 }
90
91 function nextWord() {
92 // Trigger leave animation
93 el.classList.add('is-leaving');
94
95 setTimeout(function () {
96 // Advance index
97 if (!loop && currentIndex === words.length - 1) {
98 el.classList.remove('is-leaving');
99 return; // stop
100 }
101 currentIndex = (currentIndex + 1) % words.length;
102 showWord(currentIndex);
103 }, animDuration);
104 }
105
106 // Show first word (no animation on first)
107 showWord(0);
108
109 // Start cycling
110 if (words.length > 1) {
111 setInterval(nextWord, pause + animDuration * 2);
112 }
113 }
114 }
115
116 function init() {
117 var elements = Array.prototype.slice.call(document.querySelectorAll('.bkbg-at-animated-word'));
118 elements.forEach(function (el) {
119 if (el.getAttribute('data-words')) {
120 initAnimatedText(el);
121 }
122 });
123 }
124
125 if (document.readyState === 'loading') {
126 document.addEventListener('DOMContentLoaded', init);
127 } else {
128 init();
129 }
130 })();
131