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 / decision-matrix / frontend.js

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

280 lines 13.7 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 typoCssVarsForEl(typo, prefix, el) {
5 if (!typo || typeof typo !== 'object') return;
6 var m = { family:'font-family', weight:'font-weight', transform:'text-transform', style:'font-style', decoration:'text-decoration',
7 sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m',
8 lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m',
9 letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m',
10 wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m' };
11 Object.keys(m).forEach(function (k) {
12 if (typo[k] !== undefined && typo[k] !== '') {
13 var v = typo[k], u = typo[k + 'Unit'] || '';
14 if (/Desktop|Tablet|Mobile/.test(k) && typeof v === 'number') v = v + (u || 'px');
15 el.style.setProperty(prefix + m[k], '' + v);
16 }
17 });
18 }
19
20 function mk(tag, cls, styles) {
21 var d = document.createElement(tag);
22 if (cls) d.className = cls;
23 if (styles) Object.keys(styles).forEach(function (k) { d.style[k] = styles[k]; });
24 return d;
25 }
26 function mkText(tag, cls, text, styles) {
27 var d = mk(tag, cls, styles);
28 d.textContent = text;
29 return d;
30 }
31 function mkTh(content, styles) {
32 var th = (typeof content === 'string') ? mkText('th', '', content, styles) : mk('th', '', styles);
33 if (typeof content !== 'string' && content) th.appendChild(content);
34 return th;
35 }
36 function mkTd(content, styles) {
37 var td = (typeof content === 'string') ? mkText('td', '', content, styles) : mk('td', '', styles);
38 if (typeof content !== 'string' && content) td.appendChild(content);
39 return td;
40 }
41
42 function calcTotals(options, criteria) {
43 return options.map(function (opt) {
44 var total = 0;
45 criteria.forEach(function (crit, ci) {
46 total += (opt.scores[ci] || 0) * (crit.weight || 1);
47 });
48 return total;
49 });
50 }
51
52 function winnerIdx(totals) {
53 var maxVal = -1, maxIdx = -1;
54 totals.forEach(function (t, i) { if (t > maxVal) { maxVal = t; maxIdx = i; } });
55 return maxIdx;
56 }
57
58 function init() {
59 document.querySelectorAll('.bkbg-decision-matrix-app').forEach(function (appEl) {
60 if (appEl.dataset.rendered) return;
61 appEl.dataset.rendered = '1';
62
63 var opts; try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; }
64
65 var o = {
66 blockTitle: opts.blockTitle || 'Decision Matrix',
67 showTitle: opts.showTitle !== false,
68 blockSubtitle: opts.blockSubtitle || '',
69 showSubtitle: opts.showSubtitle !== false,
70 options: opts.options || [],
71 criteria: opts.criteria || [],
72 showWeights: opts.showWeights !== false,
73 showRawScores: opts.showRawScores !== false,
74 showWinner: opts.showWinner !== false,
75 showProgressBars: opts.showProgressBars || false,
76 fontSize: opts.fontSize !== undefined ? opts.fontSize : 14,
77 titleFontSize: opts.titleFontSize !== undefined ? opts.titleFontSize : 24,
78 borderRadius: opts.borderRadius !== undefined ? opts.borderRadius : 10,
79 bgColor: opts.bgColor || '',
80 headerBg: opts.headerBg || '#1e293b',
81 headerColor: opts.headerColor || '#ffffff',
82 criteriaLabelBg: opts.criteriaLabelBg || '#f1f5f9',
83 criteriaLabelColor: opts.criteriaLabelColor|| '#475569',
84 cellBg: opts.cellBg || '#ffffff',
85 cellColor: opts.cellColor || '#374151',
86 borderColor: opts.borderColor || '#e2e8f0',
87 winnerBg: opts.winnerBg || '#eff6ff',
88 winnerColor: opts.winnerColor || '#1d4ed8',
89 winnerBorderColor: opts.winnerBorderColor || '#3b82f6',
90 totalRowBg: opts.totalRowBg || '#f8fafc',
91 totalRowColor: opts.totalRowColor || '#0f172a',
92 accentColor: opts.accentColor || '#3b82f6',
93 titleColor: opts.titleColor || '#0f172a',
94 subtitleColor: opts.subtitleColor || '#64748b'
95 };
96
97 if (!o.options.length || !o.criteria.length) return;
98
99 var totals = calcTotals(o.options, o.criteria);
100 var winner = o.showWinner ? winnerIdx(totals) : -1;
101 var maxTotal = Math.max.apply(null, totals);
102
103 /* ── Outer block ─────────────────────────────────── */
104 var block = mk('div', 'bkbg-dm-block');
105 if (o.bgColor) block.style.background = o.bgColor;
106 block.style.setProperty('--bkbg-dm-border', o.borderColor);
107 /* Typography CSS vars */
108 block.style.setProperty('--bkbg-dm-ttl-fs', o.titleFontSize + 'px');
109 block.style.setProperty('--bkbg-dm-sub-fs', (opts.subtitleFontSize || 14) + 'px');
110 block.style.setProperty('--bkbg-dm-cel-fs', o.fontSize + 'px');
111 if (opts.typoTitle) typoCssVarsForEl(opts.typoTitle, '--bkbg-dm-ttl-', block);
112 if (opts.typoSubtitle) typoCssVarsForEl(opts.typoSubtitle, '--bkbg-dm-sub-', block);
113 if (opts.typoCell) typoCssVarsForEl(opts.typoCell, '--bkbg-dm-cel-', block);
114 /* ── Header ──────────────────────────────────────── */
115 if ((o.showTitle && o.blockTitle) || (o.showSubtitle && o.blockSubtitle)) {
116 var header = mk('div', 'bkbg-dm-header', { marginBottom: '20px' });
117 if (o.showTitle && o.blockTitle) {
118 header.appendChild(mkText('h3', 'bkbg-dm-title', o.blockTitle, {
119 color: o.titleColor, margin: '0 0 6px'
120 }));
121 }
122 if (o.showSubtitle && o.blockSubtitle) {
123 header.appendChild(mkText('p', 'bkbg-dm-subtitle', o.blockSubtitle, {
124 color: o.subtitleColor, margin: '0'
125 }));
126 }
127 block.appendChild(header);
128 }
129
130 /* ── Winner banner ───────────────────────────────── */
131 if (o.showWinner && winner >= 0) {
132 var banner = mk('div', 'bkbg-dm-winner-banner', {
133 background: o.winnerBg, border: '1px solid ' + o.winnerBorderColor,
134 borderRadius: o.borderRadius + 'px', marginBottom: '16px'
135 });
136 banner.appendChild(mkText('span', '', '🏆', { fontSize: '20px' }));
137 banner.appendChild(mkText('span', '', o.options[winner].name + ' wins with ' + totals[winner] + ' points', {
138 fontWeight: '700', color: o.winnerColor, fontSize: '15px'
139 }));
140 block.appendChild(banner);
141 }
142
143 /* ── Table ───────────────────────────────────────── */
144 var tableWrap = mk('div', 'bkbg-dm-table-wrap', { overflowX: 'auto' });
145 var table = mk('table', 'bkbg-dm-table', {
146 width: '100%', borderCollapse: 'collapse',
147 border: '1px solid ' + o.borderColor, borderRadius: o.borderRadius + 'px', overflow: 'hidden'
148 });
149
150 /* Head */
151 var thead = mk('thead', '');
152 var headRow = mk('tr', '');
153
154 // Criterion header
155 var thCrit = mkText('th', '', 'Criterion', {
156 background: o.headerBg, color: o.headerColor,
157 padding: '12px 16px', textAlign: 'left', fontWeight: '700',
158 border: '1px solid rgba(255,255,255,.1)'
159 });
160 headRow.appendChild(thCrit);
161
162 // Weight header
163 if (o.showWeights) {
164 headRow.appendChild(mkText('th', '', 'Weight', {
165 background: o.headerBg, color: o.headerColor,
166 padding: '12px 10px', textAlign: 'center', fontWeight: '600', fontSize: '12px',
167 border: '1px solid rgba(255,255,255,.1)'
168 }));
169 }
170
171 // Option headers
172 o.options.forEach(function (opt, oi) {
173 var isWin = oi === winner;
174 var thOpt = mk('th', isWin ? 'is-winner' : '', {
175 background: isWin ? o.winnerBorderColor : o.headerBg,
176 color: o.headerColor, padding: '12px 16px', textAlign: 'center', fontWeight: '700',
177 border: '1px solid rgba(255,255,255,.1)'
178 });
179 thOpt.textContent = opt.name + (isWin ? ' 🏆' : '');
180 headRow.appendChild(thOpt);
181 });
182
183 thead.appendChild(headRow);
184 table.appendChild(thead);
185
186 /* Body */
187 var tbody = mk('tbody', '');
188
189 o.criteria.forEach(function (crit, ci) {
190 var row = mk('tr', '');
191
192 row.appendChild(mkText('td', '', crit.label, {
193 background: o.criteriaLabelBg, color: o.criteriaLabelColor,
194 padding: '10px 16px', fontWeight: '600',
195 border: '1px solid ' + o.borderColor
196 }));
197
198 if (o.showWeights) {
199 row.appendChild(mkText('td', '', '×' + (crit.weight || 1), {
200 background: o.criteriaLabelBg, color: o.accentColor,
201 padding: '10px', textAlign: 'center', fontWeight: '700', fontSize: '13px',
202 border: '1px solid ' + o.borderColor
203 }));
204 }
205
206 o.options.forEach(function (opt, oi) {
207 var isWin = oi === winner;
208 var raw = opt.scores[ci] || 0;
209 var weighted = raw * (crit.weight || 1);
210
211 var td = mk('td', isWin ? 'is-winner' : '', {
212 background: isWin ? o.winnerBg : o.cellBg,
213 color: o.cellColor, padding: '10px 16px', textAlign: 'center',
214 border: '1px solid ' + o.borderColor
215 });
216
217 var cellContent = mk('div', '', { lineHeight: '1' });
218 var scoreSpan = mkText('span', 'bkbg-dm-score', String(raw), { fontWeight: '600' });
219 cellContent.appendChild(scoreSpan);
220
221 if (o.showRawScores) {
222 cellContent.appendChild(mkText('span', 'bkbg-dm-weighted', '(' + weighted + ')', {
223 fontSize: '11px', color: o.accentColor, marginLeft: '4px', opacity: '.85'
224 }));
225 }
226
227 if (o.showProgressBars) {
228 var barWrap = mk('div', 'bkbg-dm-bar-wrap');
229 var barFill = mk('div', 'bkbg-dm-bar-fill', {
230 width: (raw / 10 * 100) + '%',
231 background: isWin ? o.winnerBorderColor : o.accentColor
232 });
233 barWrap.appendChild(barFill);
234 cellContent.appendChild(barWrap);
235 }
236
237 td.appendChild(cellContent);
238 row.appendChild(td);
239 });
240
241 tbody.appendChild(row);
242 });
243
244 /* Total row */
245 var totalRow = mk('tr', 'bkbg-dm-total-row');
246 var labelTdColspan = o.showWeights ? 2 : 1;
247 var labelTd = mk('td', '', {
248 padding: '12px 16px', fontWeight: '700', fontSize: '13px',
249 color: o.totalRowColor, textTransform: 'uppercase', letterSpacing: '.05em',
250 background: o.totalRowBg, border: '1px solid ' + o.borderColor
251 });
252 labelTd.colSpan = labelTdColspan;
253 labelTd.textContent = '🏁 Weighted Total';
254 totalRow.appendChild(labelTd);
255
256 totals.forEach(function (t, i) {
257 var isWin = i === winner;
258 totalRow.appendChild(mkText('td', isWin ? 'is-winner' : '', String(t), {
259 padding: '12px 16px', textAlign: 'center', fontWeight: '800', fontSize: '16px',
260 color: isWin ? o.winnerColor : o.totalRowColor,
261 background: isWin ? o.winnerBg : o.totalRowBg,
262 border: '1px solid ' + o.borderColor
263 }));
264 });
265 tbody.appendChild(totalRow);
266
267 table.appendChild(tbody);
268 tableWrap.appendChild(table);
269 block.appendChild(tableWrap);
270
271 /* ── Insert ──────────────────────────────────────── */
272 appEl.parentNode.insertBefore(block, appEl);
273 appEl.style.display = 'none';
274 });
275 }
276
277 if (document.readyState !== 'loading') { init(); }
278 else { document.addEventListener('DOMContentLoaded', init); }
279 })();
280