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 / salary-guide / frontend.js

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

178 lines 8.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 var _typoKeys = {
4 family:'font-family', weight:'font-weight', style:'font-style',
5 decoration:'text-decoration', transform:'text-transform',
6 sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m',
7 lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m',
8 letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m',
9 wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m'
10 };
11 function typoCssVarsForEl(el, obj, prefix) {
12 if (!obj || typeof obj !== 'object') return;
13 Object.keys(_typoKeys).forEach(function (k) {
14 var v = obj[k];
15 if (v === undefined || v === '' || v === null) return;
16 if (k === 'sizeDesktop' || k === 'sizeTablet' || k === 'sizeMobile') v = v + (obj.sizeUnit || 'px');
17 else if (k === 'lineHeightDesktop' || k === 'lineHeightTablet' || k === 'lineHeightMobile') v = v + (obj.lineHeightUnit || '');
18 else if (k === 'letterSpacingDesktop' || k === 'letterSpacingTablet' || k === 'letterSpacingMobile') v = v + (obj.letterSpacingUnit || 'px');
19 else if (k === 'wordSpacingDesktop' || k === 'wordSpacingTablet' || k === 'wordSpacingMobile') v = v + (obj.wordSpacingUnit || 'px');
20 el.style.setProperty(prefix + _typoKeys[k], String(v));
21 });
22 }
23 function mk(tag, cls, styles) { var d = document.createElement(tag); if (cls) d.className = cls; if (styles) Object.keys(styles).forEach(function (k) { d.style[k] = styles[k]; }); return d; }
24 function tx(tag, cls, text, styles) { var d = mk(tag, cls, styles); d.textContent = text; return d; }
25 function ap(p) { Array.prototype.slice.call(arguments, 1).forEach(function (c) { if (c) p.appendChild(c); }); return p; }
26
27 function formatSalary(n, currency) {
28 if (n >= 1000) return currency + Math.round(n / 1000) + 'k';
29 return currency + n;
30 }
31
32 function getGlobalMinMax(roles) {
33 var allVals = [];
34 roles.forEach(function (r) { allVals.push(r.min, r.max); });
35 if (!allVals.length) return { gMin: 0, gMax: 100 };
36 return { gMin: Math.min.apply(null, allVals), gMax: Math.max.apply(null, allVals) };
37 }
38
39 function getCategories(roles) {
40 var cats = [], seen = {};
41 roles.forEach(function (r) { if (!seen[r.category]) { seen[r.category] = 1; cats.push(r.category); } });
42 return cats;
43 }
44
45 function buildBar(role, a, gMin, gMax) {
46 var range = gMax - gMin || 1;
47 var leftPct = ((role.min - gMin) / range) * 100;
48 var widthPct = ((role.max - role.min) / range) * 100;
49 var medPct = ((role.median - gMin) / range) * 100;
50
51 var wrap = mk('div', 'bkbg-sg-bar-wrap');
52 var track = mk('div', 'bkbg-sg-bar-track');
53 track.style.cssText = 'height:' + a.barHeight + 'px;background:' + a.barTrackColor + ';border-radius:' + a.barHeight + 'px;position:relative;overflow:visible';
54
55 var fill = mk('div', 'bkbg-sg-bar-fill');
56 fill.style.cssText = 'position:absolute;left:' + leftPct.toFixed(2) + '%;width:' + widthPct.toFixed(2) + '%;height:100%;background:' + a.barFillColor + ';border-radius:' + a.barHeight + 'px;top:0';
57 ap(track, fill);
58
59 if (a.showMedian) {
60 var med = mk('div', 'bkbg-sg-bar-median');
61 med.style.cssText = 'position:absolute;left:' + medPct.toFixed(2) + '%;top:-3px;width:3px;height:' + (a.barHeight + 6) + 'px;background:' + a.medianColor + ';border-radius:2px;transform:translateX(-50%)';
62 ap(track, med);
63 }
64 ap(wrap, track);
65 return wrap;
66 }
67
68 function buildRow(role, a, gMin, gMax) {
69 var row = mk('div', 'bkbg-sg-row');
70
71 var header = mk('div', 'bkbg-sg-row-header');
72 var info = mk('div', 'bkbg-sg-role-info');
73 var title = tx('span', 'bkbg-sg-role-title', role.title);
74 title.style.color = a.roleTitleColor;
75 ap(info, title);
76 if (a.showLevel) {
77 var lvl = tx('span', 'bkbg-sg-level-badge', role.level);
78 lvl.style.cssText = 'background:' + a.levelBg + ';color:' + a.levelColor;
79 ap(info, lvl);
80 }
81 ap(header, info);
82
83 var labels = mk('div', 'bkbg-sg-range-labels');
84 labels.style.color = a.rangeLabelColor;
85 var minL = tx('span', null, formatSalary(role.min, a.currency));
86 ap(labels, minL);
87 if (a.showMedian) {
88 var medL = tx('span', 'bkbg-sg-median-label', formatSalary(role.median, a.currency) + ' median');
89 medL.style.cssText = 'color:' + a.medianColor + ';font-weight:600';
90 ap(labels, medL);
91 }
92 var maxL = tx('span', null, formatSalary(role.max, a.currency));
93 ap(labels, maxL);
94 ap(header, labels);
95 ap(row, header);
96
97 if (a.showBars) {
98 ap(row, buildBar(role, a, gMin, gMax));
99 }
100 return row;
101 }
102
103 function buildBlock(appEl) {
104 if (appEl.dataset.rendered) return;
105 appEl.dataset.rendered = '1';
106
107 var a = Object.assign({
108 guideTitle: 'Salary Guide', description: '', showDescription: true,
109 currency: '$', period: 'year', location: '', showLocation: true,
110 showBars: true, showMedian: true, showLevel: true, groupByCategory: false,
111 roles: [],
112 fontSize: 14, titleFontSize: 24, lineHeight: 160, borderRadius: 12, barHeight: 10,
113 bgColor: '#ffffff', borderColor: '#e5e7eb',
114 titleColor: '#111827', descColor: '#6b7280',
115 roleTitleColor: '#1f2937', levelBg: '#f3f4f6', levelColor: '#374151',
116 rangeLabelColor: '#6b7280', barTrackColor: '#e5e7eb', barFillColor: '#3b82f6',
117 medianColor: '#0f172a', categoryHeadColor: '#374151', categoryHeadBg: '#f8fafc'
118 }, JSON.parse(appEl.dataset.opts || '{}'));
119
120 var lh = (a.lineHeight / 100).toFixed(2);
121 var mm = getGlobalMinMax(a.roles);
122
123 var wrap = mk('div', 'bkbg-sg-wrap');
124 wrap.style.cssText = 'background:' + a.bgColor + ';border-radius:' + a.borderRadius + 'px;border:1px solid ' + a.borderColor + ';overflow:hidden;font-size:' + a.fontSize + 'px;line-height:' + lh;
125
126 var header = mk('div', 'bkbg-sg-header');
127 header.style.cssText = 'padding:24px 28px;border-bottom:1px solid ' + a.borderColor;
128 var title = tx('h2', 'bkbg-sg-title', a.guideTitle);
129 title.style.cssText = 'color:' + a.titleColor;
130 ap(header, title);
131 var meta = mk('div', 'bkbg-sg-meta');
132 if (a.showDescription && a.description) {
133 var desc = tx('p', null, a.description);
134 desc.style.cssText = 'margin:0;color:' + a.descColor;
135 ap(meta, desc);
136 }
137 if (a.showLocation && a.location) {
138 var loc = tx('span', 'bkbg-sg-location', '📍 ' + a.location + ' · ' + a.currency + ' / ' + a.period);
139 loc.style.cssText = 'color:' + a.descColor + ';font-size:0.88em;margin-top:4px;display:block';
140 ap(meta, loc);
141 }
142 ap(header, meta);
143 ap(wrap, header);
144
145 var body = mk('div', 'bkbg-sg-body');
146 if (a.groupByCategory) {
147 var cats = getCategories(a.roles);
148 cats.forEach(function (cat) {
149 var catRoles = a.roles.filter(function (r) { return r.category === cat; });
150 var catHead = tx('div', 'bkbg-sg-category-head', cat);
151 catHead.style.cssText = 'color:' + a.categoryHeadColor + ';background:' + a.categoryHeadBg + ';border-bottom:1px solid ' + a.borderColor;
152 ap(body, catHead);
153 catRoles.forEach(function (role, i) {
154 var row = buildRow(role, a, mm.gMin, mm.gMax);
155 if (i > 0) { row.style.borderTopColor = a.borderColor; row.style.borderTopWidth = '1px'; row.style.borderTopStyle = 'solid'; }
156 ap(body, row);
157 });
158 });
159 } else {
160 a.roles.forEach(function (role, i) {
161 var row = buildRow(role, a, mm.gMin, mm.gMax);
162 if (i > 0) { row.style.borderTopColor = a.borderColor; row.style.borderTopWidth = '1px'; row.style.borderTopStyle = 'solid'; }
163 ap(body, row);
164 });
165 }
166 ap(wrap, body);
167
168 appEl.innerHTML = '';
169 appEl.appendChild(wrap);
170
171 typoCssVarsForEl(wrap, a.titleTypo, '--bksg-tt-');
172 typoCssVarsForEl(wrap, a.descTypo, '--bksg-dt-');
173 }
174
175 function init() { document.querySelectorAll('.bkbg-salary-guide-app').forEach(buildBlock); }
176 if (document.readyState !== 'loading') { init(); } else { document.addEventListener('DOMContentLoaded', init); }
177 })();
178