PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.11
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.11
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 / analog-clock / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.11, at blocks/analog-clock/frontend.js

267 lines 10.5 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 function getTimeInZone(timezone) {
5 if (!timezone || timezone === 'local') {
6 var d = new Date();
7 return { h: d.getHours(), m: d.getMinutes(), s: d.getSeconds() };
8 }
9 try {
10 var parts = new Intl.DateTimeFormat('en-US', {
11 timeZone: timezone,
12 hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: false
13 }).formatToParts(new Date());
14 var vals = {};
15 parts.forEach(function (p) { vals[p.type] = parseInt(p.value, 10); });
16 return { h: vals.hour % 24, m: vals.minute, s: vals.second };
17 } catch (e) {
18 var d2 = new Date();
19 return { h: d2.getHours(), m: d2.getMinutes(), s: d2.getSeconds() };
20 }
21 }
22
23 function getDateInZone(timezone) {
24 if (!timezone || timezone === 'local') {
25 return new Date().toLocaleDateString(undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
26 }
27 try {
28 return new Intl.DateTimeFormat(undefined, {
29 timeZone: timezone, weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'
30 }).format(new Date());
31 } catch (e) {
32 return new Date().toLocaleDateString(undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
33 }
34 }
35
36 function getDigitalInZone(timezone) {
37 if (!timezone || timezone === 'local') {
38 return new Date().toLocaleTimeString();
39 }
40 try {
41 return new Intl.DateTimeFormat(undefined, { timeZone: timezone, hour: '2-digit', minute: '2-digit', second: '2-digit' }).format(new Date());
42 } catch (e) {
43 return new Date().toLocaleTimeString();
44 }
45 }
46
47 function toRad(deg) { return (deg - 90) * Math.PI / 180; }
48
49 var ns = 'http://www.w3.org/2000/svg';
50
51 function createEl(tag, attrs, children) {
52 var el = document.createElementNS(ns, tag);
53 if (attrs) {
54 Object.keys(attrs).forEach(function (k) {
55 el.setAttribute(k, attrs[k]);
56 });
57 }
58 if (children) {
59 children.forEach(function (c) { if (c) el.appendChild(c); });
60 }
61 return el;
62 }
63
64 function buildClock(opts) {
65 var sz = opts.clockSize || 240;
66 var r = 46;
67 var cx = 50, cy = 50;
68 var bw = opts.clockStyle === 'minimal' ? 2 : opts.clockStyle === 'bold' ? 9 : 4;
69
70 var svg = createEl('svg', {
71 viewBox: '0 0 100 100',
72 width: sz, height: sz,
73 'class': 'bkbg-clk-svg',
74 'aria-label': 'Analog clock'
75 });
76
77 // Border circle
78 svg.appendChild(createEl('circle', { cx: cx, cy: cy, r: 49, fill: opts.clockBorder || '#1e1b4b' }));
79 // Face
80 svg.appendChild(createEl('circle', { cx: cx, cy: cy, r: 49 - bw, fill: opts.clockFace || '#ffffff' }));
81
82 // Ticks
83 if (opts.showTicks !== false) {
84 for (var i = 0; i < 60; i++) {
85 var isBig = i % 5 === 0;
86 var ang = (i * 6 - 90) * Math.PI / 180;
87 var innerR = isBig ? r - 7 : r - 4;
88 svg.appendChild(createEl('line', {
89 x1: cx + innerR * Math.cos(ang), y1: cy + innerR * Math.sin(ang),
90 x2: cx + r * Math.cos(ang), y2: cy + r * Math.sin(ang),
91 stroke: opts.tickColor || '#374151',
92 'stroke-width': isBig ? 1.8 : 0.8,
93 'stroke-linecap': 'round'
94 }));
95 }
96 }
97
98 // Numbers
99 if (opts.showNumbers !== false) {
100 for (var j = 1; j <= 12; j++) {
101 var nAng = (j * 30 - 90) * Math.PI / 180;
102 var txt = createEl('text', {
103 x: cx + (r - 14) * Math.cos(nAng),
104 y: cy + (r - 14) * Math.sin(nAng),
105 'text-anchor': 'middle',
106 'dominant-baseline': 'middle',
107 'font-size': 7, 'font-weight': 700,
108 fill: opts.numberColor || '#1e1b4b',
109 'font-family': 'system-ui, sans-serif'
110 });
111 txt.textContent = j;
112 svg.appendChild(txt);
113 }
114 }
115
116 // Hands (created and stored for updates)
117 var hourHand = createEl('line', {
118 x1: cx, y1: cy, x2: cx, y2: cy - 28,
119 stroke: opts.hourHandColor || '#1e1b4b',
120 'stroke-width': 3.5, 'stroke-linecap': 'round'
121 });
122
123 var minuteHand = createEl('line', {
124 x1: cx, y1: cy, x2: cx, y2: cy - 38,
125 stroke: opts.minuteHandColor || '#374151',
126 'stroke-width': 2.5, 'stroke-linecap': 'round'
127 });
128
129 var secondHand = null, secondTail = null;
130 if (opts.showSecondHand !== false) {
131 secondHand = createEl('line', {
132 x1: cx, y1: cy, x2: cx, y2: cy - 40,
133 stroke: opts.secondHandColor || '#ef4444',
134 'stroke-width': 1.5, 'stroke-linecap': 'round',
135 'class': 'bkbg-clk-second-hand'
136 });
137 secondTail = createEl('line', {
138 x1: cx, y1: cy, x2: cx, y2: cy + 10,
139 stroke: opts.secondHandColor || '#ef4444',
140 'stroke-width': 1.5, 'stroke-linecap': 'round'
141 });
142 }
143
144 svg.appendChild(hourHand);
145 svg.appendChild(minuteHand);
146 if (secondHand) svg.appendChild(secondHand);
147 if (secondTail) svg.appendChild(secondTail);
148
149 // Center dot
150 svg.appendChild(createEl('circle', { cx: cx, cy: cy, r: 3.5, fill: opts.centerDotColor || '#ef4444' }));
151 svg.appendChild(createEl('circle', { cx: cx, cy: cy, r: 1.5, fill: '#fff' }));
152
153 function updateHands(t) {
154 var h12 = t.h % 12;
155 var hDeg = h12 * 30 + t.m * 0.5;
156 var mDeg = t.m * 6 + t.s * 0.1;
157 var sDeg = t.s * 6;
158
159 function rotate(hand, angle, len) {
160 var rad = toRad(angle);
161 hand.setAttribute('x2', cx + len * Math.cos(rad));
162 hand.setAttribute('y2', cy + len * Math.sin(rad));
163 }
164
165 rotate(hourHand, hDeg, 28);
166 rotate(minuteHand, mDeg, 38);
167
168 if (secondHand) {
169 rotate(secondHand, sDeg, 40);
170 var tailRad = toRad(sDeg + 180);
171 secondTail.setAttribute('x2', cx + 10 * Math.cos(tailRad));
172 secondTail.setAttribute('y2', cy + 10 * Math.sin(tailRad));
173 }
174 }
175
176 return { svg: svg, updateHands: updateHands };
177 }
178
179 function typoCssVarsForEl(typo, prefix, el) {
180 if (!typo || typeof typo !== 'object') return;
181 var map = {
182 family:'font-family', weight:'font-weight', style:'font-style',
183 decoration:'text-decoration', transform:'text-transform',
184 sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m',
185 lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m',
186 letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m',
187 wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m'
188 };
189 Object.keys(map).forEach(function(k) {
190 if (typo[k] !== undefined && typo[k] !== '') {
191 var v = typo[k];
192 if (['sizeDesktop','sizeTablet','sizeMobile'].indexOf(k) !== -1) v = v + (typo.sizeUnit || 'px');
193 else if (['lineHeightDesktop','lineHeightTablet','lineHeightMobile'].indexOf(k) !== -1) v = v + (typo.lineHeightUnit || '');
194 else if (['letterSpacingDesktop','letterSpacingTablet','letterSpacingMobile'].indexOf(k) !== -1) v = v + (typo.letterSpacingUnit || 'px');
195 else if (['wordSpacingDesktop','wordSpacingTablet','wordSpacingMobile'].indexOf(k) !== -1) v = v + (typo.wordSpacingUnit || 'px');
196 el.style.setProperty(prefix + map[k], String(v));
197 }
198 });
199 }
200
201 function initBlock(root) {
202 var optsRaw = root.getAttribute('data-opts');
203 var opts;
204 try { opts = JSON.parse(optsRaw); } catch (e) { opts = {}; }
205
206 // Apply background
207 if (opts.sectionBg) root.style.background = opts.sectionBg;
208
209 // Typography CSS vars
210 typoCssVarsForEl(opts.titleTypo, '--bkbg-clk-title-', root);
211 typoCssVarsForEl(opts.subtitleTypo, '--bkbg-clk-subtitle-', root);
212 if (opts.fontSize && opts.fontSize !== 22) root.style.setProperty('--bkbg-clk-title-sz', opts.fontSize + 'px');
213 if (opts.subtitleSize && opts.subtitleSize !== 14) root.style.setProperty('--bkbg-clk-subtitle-sz', opts.subtitleSize + 'px');
214
215 // Apply title styles
216 var titleEl = root.querySelector('.bkbg-clk-title');
217 if (titleEl) {
218 titleEl.style.color = opts.titleColor || '#1e1b4b';
219 }
220 var subtitleEl = root.querySelector('.bkbg-clk-subtitle');
221 if (subtitleEl) {
222 subtitleEl.style.color = opts.titleColor || '#1e1b4b';
223 }
224
225 // Build clock wrap
226 var wrap = document.createElement('div');
227 wrap.className = 'bkbg-clk-clock-wrap';
228 root.appendChild(wrap);
229
230 // Build and insert SVG clock
231 var clock = buildClock(opts);
232 wrap.appendChild(clock.svg);
233
234 // Date element
235 var dateEl = null;
236 if (opts.showDate) {
237 dateEl = document.createElement('div');
238 dateEl.className = 'bkbg-clk-date';
239 dateEl.style.color = opts.titleColor || '#1e1b4b';
240 wrap.appendChild(dateEl);
241 }
242
243 // Digital time element
244 var digitalEl = null;
245 if (opts.showDigitalTime) {
246 digitalEl = document.createElement('div');
247 digitalEl.className = 'bkbg-clk-digital';
248 digitalEl.style.color = opts.titleColor || '#1e1b4b';
249 wrap.appendChild(digitalEl);
250 }
251
252 function tick() {
253 var t = getTimeInZone(opts.timezone);
254 clock.updateHands(t);
255 if (dateEl) dateEl.textContent = getDateInZone(opts.timezone);
256 if (digitalEl) digitalEl.textContent = getDigitalInZone(opts.timezone);
257 }
258
259 tick(); // initial render
260 setInterval(tick, 1000);
261 }
262
263 document.querySelectorAll('.bkbg-clk-app').forEach(function (root) {
264 initBlock(root);
265 });
266 })();
267