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 / flip-countdown / frontend.js

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

255 lines 10.3 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 /* ── Typography CSS-var helper ──────────────────────────────── */
5 var defined = function (v) { return v !== undefined && v !== null && v !== ''; };
6 function typoCssVarsForEl(typo, prefix, el) {
7 if (!typo || typeof typo !== 'object') return;
8 var m = {
9 family: 'font-family',
10 weight: 'font-weight',
11 style: 'font-style',
12 decoration: 'text-decoration',
13 transform: 'text-transform',
14 sizeDesktop: 'font-size-d',
15 sizeTablet: 'font-size-t',
16 sizeMobile: 'font-size-m',
17 lineHeightDesktop: 'line-height-d',
18 lineHeightTablet: 'line-height-t',
19 lineHeightMobile: 'line-height-m',
20 letterSpacingDesktop:'letter-spacing-d',
21 letterSpacingTablet: 'letter-spacing-t',
22 letterSpacingMobile: 'letter-spacing-m',
23 wordSpacingDesktop: 'word-spacing-d',
24 wordSpacingTablet: 'word-spacing-t',
25 wordSpacingMobile: 'word-spacing-m'
26 };
27 var needsPx = { sizeDesktop:1,sizeTablet:1,sizeMobile:1,letterSpacingDesktop:1,letterSpacingTablet:1,letterSpacingMobile:1,wordSpacingDesktop:1,wordSpacingTablet:1,wordSpacingMobile:1 };
28 Object.keys(m).forEach(function (k) {
29 if (defined(typo[k])) {
30 var v = typo[k];
31 if (needsPx[k] && typeof v === 'number') v = v + (typo[k.replace(/Desktop|Tablet|Mobile/, 'Unit')] || 'px');
32 el.style.setProperty(prefix + m[k], '' + v);
33 }
34 });
35 if (defined(typo.family)) el.style.setProperty(prefix + 'font-family', typo.family + ', sans-serif');
36 }
37
38 function initBlock(root) {
39 var optsRaw = root.getAttribute('data-opts');
40 var opts;
41 try { opts = JSON.parse(optsRaw); } catch (e) { opts = {}; }
42
43 var targetDate = opts.targetDate || '';
44 var showDays = opts.showDays !== false;
45 var showHours = opts.showHours !== false;
46 var showMinutes = opts.showMinutes !== false;
47 var showSeconds = opts.showSeconds !== false;
48 var showLabels = opts.showLabels !== false;
49 var showSeps = opts.showSeparators !== false;
50 var endMessage = opts.endMessage || '🎉 The wait is over!';
51 var endAction = opts.endAction || 'message';
52 var cardRadius = opts.cardRadius || 8;
53 var cardGap = opts.cardGap || 16;
54 var digitSize = opts.digitSize || 56;
55 var labelFontSize = opts.labelFontSize || 12;
56 var flipBg = opts.flipBg || '#1e1b4b';
57 var flipColor = opts.flipColor || '#ffffff';
58 var flipHingeBg = opts.flipHingeBg || '#0f0e17';
59 var labelColor = opts.labelColor || '#64748b';
60 var sepColor = opts.separatorColor || '#6366f1';
61 var sectionBg = opts.sectionBg || '#f8fafc';
62 var titleColor = opts.titleColor || '#1e1b4b';
63
64 if (sectionBg) root.style.background = sectionBg;
65
66 typoCssVarsForEl(opts.typoTitle, '--bkbg-fcd-tt-', root);
67 typoCssVarsForEl(opts.typoSubtitle, '--bkbg-fcd-ts-', root);
68 typoCssVarsForEl(opts.typoDigit, '--bkbg-fcd-td-', root);
69 typoCssVarsForEl(opts.typoLabel, '--bkbg-fcd-tl-', root);
70
71 var titleEl = root.querySelector('.bkbg-fc-title');
72 if (titleEl) { titleEl.style.color = titleColor; }
73 var subEl = root.querySelector('.bkbg-fc-subtitle');
74 if (subEl) { subEl.style.color = titleColor; }
75
76 var target = targetDate ? new Date(targetDate).getTime() : null;
77 if (!target || isNaN(target)) { target = Date.now() + 7 * 24 * 60 * 60 * 1000; } // demo: 7 days
78
79 // ---- Build digit cards ----
80 var units = [];
81 if (showDays) units.push({ key: 'd', label: 'Days', max: 999 });
82 if (showHours) units.push({ key: 'h', label: 'Hours', max: 23 });
83 if (showMinutes) units.push({ key: 'm', label: 'Minutes', max: 59 });
84 if (showSeconds) units.push({ key: 's', label: 'Seconds', max: 59 });
85
86 var row = document.createElement('div');
87 row.className = 'bkbg-fc-row';
88 row.style.gap = cardGap + 'px';
89 root.appendChild(row);
90
91 // Map from key to array [card0, card1] (for 2-digit display)
92 var cards = {};
93
94 function makeDigitCard(digit) {
95 var card = document.createElement('div');
96 card.className = 'bkbg-fc-card';
97 card.style.cssText = 'background:' + flipBg + ';border-radius:' + cardRadius + 'px;color:' + flipColor + ';';
98
99 var upper = document.createElement('div');
100 upper.className = 'bkbg-fc-upper';
101 upper.textContent = digit;
102
103 var lower = document.createElement('div');
104 lower.className = 'bkbg-fc-lower';
105 lower.textContent = digit;
106
107 var hinge = document.createElement('div');
108 hinge.className = 'bkbg-fc-hinge';
109 hinge.style.background = flipHingeBg;
110
111 card.appendChild(upper);
112 card.appendChild(lower);
113 card.appendChild(hinge);
114 return card;
115 }
116
117 function flipDigitCard(card, oldD, newD) {
118 if (oldD === newD) return;
119 var upper = card.querySelector('.bkbg-fc-upper');
120 var lower = card.querySelector('.bkbg-fc-lower');
121
122 // Remove old flap elements
123 var old = card.querySelectorAll('.bkbg-fc-flap-upper, .bkbg-fc-flap-lower');
124 old.forEach(function (el) { el.remove(); });
125
126 // Flap upper: shows oldD, flips away
127 var flapUpper = document.createElement('div');
128 flapUpper.className = 'bkbg-fc-flap-upper';
129 flapUpper.textContent = oldD;
130 flapUpper.style.cssText = 'color:' + flipColor + ';';
131
132 // Flap lower: shows newD, flips in
133 var flapLower = document.createElement('div');
134 flapLower.className = 'bkbg-fc-flap-lower';
135 flapLower.textContent = newD;
136 flapLower.style.cssText = 'color:' + flipColor + ';background:' + flipBg + ';';
137
138 // Update static halves immediately for lower, update upper after animation
139 lower.textContent = newD;
140
141 card.appendChild(flapUpper);
142 card.appendChild(flapLower);
143
144 flapUpper.addEventListener('animationend', function () {
145 upper.textContent = newD;
146 flapUpper.remove();
147 });
148 flapLower.addEventListener('animationend', function () {
149 flapLower.remove();
150 });
151 }
152
153 units.forEach(function (u, i) {
154 if (i > 0 && showSeps) {
155 var sep = document.createElement('div');
156 sep.className = 'bkbg-fc-sep';
157 sep.textContent = ':';
158 sep.style.cssText = 'color:' + sepColor + ';';
159 row.appendChild(sep);
160 }
161
162 var unit_ = document.createElement('div');
163 unit_.className = 'bkbg-fc-unit';
164
165 var pair = document.createElement('div');
166 pair.className = 'bkbg-fc-pair';
167
168 var c0 = makeDigitCard('0');
169 var c1 = makeDigitCard('0');
170 pair.appendChild(c0);
171 pair.appendChild(c1);
172 unit_.appendChild(pair);
173
174 if (showLabels) {
175 var lbl = document.createElement('div');
176 lbl.className = 'bkbg-fc-label';
177 lbl.textContent = u.label;
178 lbl.style.cssText = 'color:' + labelColor + ';';
179 unit_.appendChild(lbl);
180 }
181
182 row.appendChild(unit_);
183 cards[u.key] = [c0, c1];
184 });
185
186 // ---- Prev values cache ----
187 var prev = { d: -1, h: -1, m: -1, s: -1 };
188
189 function updateCards(key, val) {
190 var str = String(Math.max(0, val)).padStart(2, '0');
191 var d0 = str[0];
192 var d1 = str[1];
193 var prevStr = String(Math.max(0, prev[key])).padStart(2, '0');
194
195 if (prev[key] < 0) {
196 // First render — no animation
197 if (cards[key]) {
198 cards[key][0].querySelector('.bkbg-fc-upper').textContent = d0;
199 cards[key][0].querySelector('.bkbg-fc-lower').textContent = d0;
200 cards[key][1].querySelector('.bkbg-fc-upper').textContent = d1;
201 cards[key][1].querySelector('.bkbg-fc-lower').textContent = d1;
202 }
203 } else {
204 if (d0 !== prevStr[0] && cards[key]) flipDigitCard(cards[key][0], prevStr[0], d0);
205 if (d1 !== prevStr[1] && cards[key]) flipDigitCard(cards[key][1], prevStr[1], d1);
206 }
207 prev[key] = val;
208 }
209
210 var finished = false;
211
212 function tick() {
213 if (finished) return;
214 var now = Date.now();
215 var diff = Math.max(0, target - now);
216
217 if (diff <= 0) {
218 finished = true;
219 if (endAction === 'hide') {
220 root.style.display = 'none';
221 } else if (endAction === 'message') {
222 row.style.display = 'none';
223 var msg = document.createElement('div');
224 msg.className = 'bkbg-fc-end';
225 msg.textContent = endMessage;
226 msg.style.color = titleColor;
227 root.appendChild(msg);
228 }
229 return; // stop ticking
230 }
231
232 var totalSec = Math.floor(diff / 1000);
233 var s = totalSec % 60;
234 var totalMin = Math.floor(totalSec / 60);
235 var m = totalMin % 60;
236 var totalHour = Math.floor(totalMin / 60);
237 var h = totalHour % 24;
238 var d = Math.floor(totalHour / 24);
239
240 if (showDays) updateCards('d', d);
241 if (showHours) updateCards('h', h);
242 if (showMinutes) updateCards('m', m);
243 if (showSeconds) updateCards('s', s);
244
245 setTimeout(tick, 1000);
246 }
247
248 tick();
249 }
250
251 document.querySelectorAll('.bkbg-fc-app').forEach(function (root) {
252 initBlock(root);
253 });
254 })();
255