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 / time-duration-calculator / frontend.js

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

167 lines 8.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 function pad2(n) { return String(Math.abs(Math.floor(n))).padStart(2,'0'); }
5
6 function fmtHMS(totalSec) {
7 var neg = totalSec < 0;
8 var s = Math.abs(totalSec);
9 var h = Math.floor(s / 3600); s -= h * 3600;
10 var m = Math.floor(s / 60); s -= m * 60;
11 return (neg ? '' : '') + pad2(h) + ':' + pad2(m) + ':' + pad2(s);
12 }
13
14 function toSec(h, m, s) {
15 return (parseInt(h) || 0) * 3600 + (parseInt(m) || 0) * 60 + (parseInt(s) || 0);
16 }
17
18 function initBlock(app) {
19 var opts = {};
20 try { opts = JSON.parse(app.getAttribute('data-opts') || '{}'); } catch(e) {}
21
22 var accent = opts.accentColor || '#6c3fb5';
23 var resultBg = opts.resultBg || accent;
24 var resultColor = opts.resultColor || '#fff';
25 var statBg = opts.statBg || '#f3f4f6';
26 var statBorder = opts.statBorder || '#e5e7eb';
27 var statValue = opts.statValue || '#111827';
28 var statLabel = opts.statLabel || '#6b7280';
29 var opActiveBg = opts.opActiveBg || accent;
30 var opActiveClr = opts.opActiveColor || '#fff';
31 var opInactiveBg = opts.opInactiveBg || '#f3f4f6';
32 var opInactiveClr= opts.opInactiveColor|| '#374151';
33 var inputBorder = opts.inputBorder || '#e5e7eb';
34 var labelColor = opts.labelColor || '#374151';
35 var cardRadius = (opts.cardRadius !== undefined ? opts.cardRadius : 16) + 'px';
36 var inputRadius = (opts.inputRadius !== undefined ? opts.inputRadius : 8) + 'px';
37 var showSec = opts.showSeconds !== false;
38 var showTotalSec = opts.showTotalSec !== false;
39 var showDays = opts.showDaysBreakdown !== false;
40
41 var state = { op: opts.defaultOp || 'add' };
42
43 var wrap = document.createElement('div');
44 wrap.className = 'bkbg-tdc-wrap';
45 wrap.style.borderRadius = cardRadius;
46 if (opts.cardBg) wrap.style.background = opts.cardBg;
47 app.appendChild(wrap);
48
49 // Header
50 if (opts.showTitle || opts.showSubtitle) {
51 var hdr = document.createElement('div'); hdr.className = 'bkbg-tdc-header';
52 if (opts.showTitle && opts.title) {
53 var ti = document.createElement('div'); ti.className = 'bkbg-tdc-title';
54 if (opts.titleColor) ti.style.color = opts.titleColor;
55 ti.textContent = opts.title; hdr.appendChild(ti);
56 }
57 if (opts.showSubtitle && opts.subtitle) {
58 var su = document.createElement('div'); su.className = 'bkbg-tdc-subtitle';
59 if (opts.subtitleColor) su.style.color = opts.subtitleColor;
60 su.textContent = opts.subtitle; hdr.appendChild(su);
61 }
62 wrap.appendChild(hdr);
63 }
64
65 // Op buttons
66 var opsRow = document.createElement('div'); opsRow.className = 'bkbg-tdc-ops';
67 var btnAdd = document.createElement('button'); btnAdd.className = 'bkbg-tdc-op'; btnAdd.type = 'button'; btnAdd.textContent = '+ Add';
68 var btnSub = document.createElement('button'); btnSub.className = 'bkbg-tdc-op'; btnSub.type = 'button'; btnSub.textContent = '− Subtract';
69 opsRow.appendChild(btnAdd); opsRow.appendChild(btnSub); wrap.appendChild(opsRow);
70
71 function styleOp() {
72 [btnAdd, btnSub].forEach(function(btn, i) {
73 var active = (i === 0 && state.op === 'add') || (i === 1 && state.op === 'sub');
74 btn.style.background = active ? opActiveBg : opInactiveBg;
75 btn.style.color = active ? opActiveClr : opInactiveClr;
76 btn.classList.toggle('active', active);
77 });
78 opSymEl.textContent = state.op === 'add' ? '+' : '';
79 resultLabelEl.textContent = state.op === 'add' ? 'Total Duration' : 'Difference';
80 calc();
81 }
82
83 btnAdd.addEventListener('click', function(){ state.op = 'add'; styleOp(); });
84 btnSub.addEventListener('click', function(){ state.op = 'sub'; styleOp(); });
85
86 // Duration builder helper
87 function makeDurBlock(label, defH, defM, defS) {
88 var block = document.createElement('div'); block.className = 'bkbg-tdc-dur-block';
89 var lbl = document.createElement('div'); lbl.className = 'bkbg-tdc-dur-lbl'; lbl.style.color = labelColor; lbl.textContent = label;
90 var grid = document.createElement('div'); grid.className = 'bkbg-tdc-dur-grid' + (showSec ? '' : ' no-sec');
91 block.appendChild(lbl); block.appendChild(grid);
92
93 var inputs = {};
94 [['h', 'Hours', defH], ['m', 'Minutes', defM], showSec && ['s', 'Seconds', defS]].forEach(function(f) {
95 if (!f) return;
96 var cell = document.createElement('div');
97 var fl = document.createElement('label'); fl.className = 'bkbg-tdc-field-label'; fl.style.color = labelColor; fl.textContent = f[1];
98 var fi = document.createElement('input'); fi.type = 'number'; fi.className = 'bkbg-tdc-input'; fi.min = 0; fi.value = f[2];
99 fi.style.borderColor = inputBorder; fi.style.borderRadius = inputRadius;
100 fi.addEventListener('input', calc);
101 cell.appendChild(fl); cell.appendChild(fi); grid.appendChild(cell);
102 inputs[f[0]] = fi;
103 });
104 if (!showSec) inputs['s'] = { value: '0' };
105 return { block: block, inputs: inputs };
106 }
107
108 var dur1 = makeDurBlock('Duration A', opts.defaultH1 || 1, opts.defaultM1 || 30, opts.defaultS1 || 0);
109 wrap.appendChild(dur1.block);
110
111 var opSymEl = document.createElement('div'); opSymEl.className = 'bkbg-tdc-operator'; opSymEl.style.color = accent; opSymEl.textContent = '+';
112 wrap.appendChild(opSymEl);
113
114 var dur2 = makeDurBlock('Duration B', opts.defaultH2 || 0, opts.defaultM2 || 45, opts.defaultS2 || 0);
115 wrap.appendChild(dur2.block);
116
117 // Spacer
118 var spacer = document.createElement('div'); spacer.style.height = '16px'; wrap.appendChild(spacer);
119
120 // Result card
121 var resultCard = document.createElement('div'); resultCard.className = 'bkbg-tdc-result';
122 resultCard.style.background = resultBg; resultCard.style.color = resultColor; resultCard.style.borderRadius = '12px';
123 var resultLabelEl = document.createElement('div'); resultLabelEl.className = 'bkbg-tdc-result-label'; resultLabelEl.textContent = 'Total Duration';
124 var resultTimeEl = document.createElement('div'); resultTimeEl.className = 'bkbg-tdc-result-time';
125 resultCard.appendChild(resultLabelEl); resultCard.appendChild(resultTimeEl); wrap.appendChild(resultCard);
126
127 // Stats
128 var statsRow = document.createElement('div'); statsRow.className = 'bkbg-tdc-stats'; wrap.appendChild(statsRow);
129 var statEls = {};
130 function makeStat(key, label) {
131 var s = document.createElement('div'); s.className = 'bkbg-tdc-stat'; s.style.background = statBg; s.style.borderColor = statBorder;
132 var v = document.createElement('div'); v.className = 'bkbg-tdc-stat-val'; v.style.color = statValue;
133 var l = document.createElement('div'); l.className = 'bkbg-tdc-stat-lbl'; l.style.color = statLabel; l.textContent = label;
134 s.appendChild(v); s.appendChild(l); statsRow.appendChild(s);
135 statEls[key] = v;
136 return s;
137 }
138 var daysStat = showDays ? makeStat('days','Days') : null;
139 makeStat('hours','Hours'); makeStat('mins','Minutes');
140 var secsStat = showSec ? makeStat('secs','Seconds') : null;
141 var totalSecSt = showTotalSec ? makeStat('tsec','Total Seconds') : null;
142
143 function calc() {
144 var t1 = toSec(dur1.inputs.h.value, dur1.inputs.m.value, dur1.inputs.s.value);
145 var t2 = toSec(dur2.inputs.h.value, dur2.inputs.m.value, dur2.inputs.s.value);
146 var total = state.op === 'add' ? t1 + t2 : t1 - t2;
147 var abs = Math.abs(total);
148 var days = Math.floor(abs / 86400);
149 var hours = Math.floor((abs % 86400) / 3600);
150 var mins = Math.floor((abs % 3600) / 60);
151 var secs = abs % 60;
152
153 resultTimeEl.textContent = fmtHMS(total);
154 if (statEls.days) statEls.days.textContent = days;
155 if (statEls.hours) statEls.hours.textContent = hours;
156 if (statEls.mins) statEls.mins.textContent = mins;
157 if (statEls.secs) statEls.secs.textContent = secs;
158 if (statEls.tsec) statEls.tsec.textContent = abs.toLocaleString();
159 }
160
161 styleOp();
162 }
163
164 function init() { document.querySelectorAll('.bkbg-tdc-app').forEach(initBlock); }
165 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); }
166 })();
167