PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.14
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.14
2.0.14 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 / body-fat-calculator / frontend.js

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

263 lines 15.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 calcBodyFat(gender, height, waist, neck, hip) {
5 var h = parseFloat(height) || 0;
6 var w = parseFloat(waist) || 0;
7 var n = parseFloat(neck) || 0;
8 var hi= parseFloat(hip) || 0;
9 if (h <= 0 || w <= 0 || n <= 0) return null;
10 var bf;
11 if (gender === 'male') {
12 bf = 495 / (1.0324 - 0.19077 * Math.log10(w - n) + 0.15456 * Math.log10(h)) - 450;
13 } else {
14 if (hi <= 0) return null;
15 bf = 495 / (1.29579 - 0.35004 * Math.log10(w + hi - n) + 0.22100 * Math.log10(h)) - 450;
16 }
17 return Math.max(0, Math.min(70, +bf.toFixed(1)));
18 }
19
20 function getCategory(bf, gender) {
21 if (gender === 'male') {
22 if (bf < 6) return { label: 'Essential Fat', color: '#3b82f6' };
23 if (bf < 14) return { label: 'Athletes', color: '#10b981' };
24 if (bf < 18) return { label: 'Fitness', color: '#6c3fb5' };
25 if (bf < 25) return { label: 'Average', color: '#f59e0b' };
26 return { label: 'Obese', color: '#ef4444' };
27 } else {
28 if (bf < 14) return { label: 'Essential Fat', color: '#3b82f6' };
29 if (bf < 21) return { label: 'Athletes', color: '#10b981' };
30 if (bf < 25) return { label: 'Fitness', color: '#6c3fb5' };
31 if (bf < 32) return { label: 'Average', color: '#f59e0b' };
32 return { label: 'Obese', color: '#ef4444' };
33 }
34 }
35
36 function maleRanges() { return [[0,6,'Essential','#3b82f6'],[6,14,'Athletes','#10b981'],[14,18,'Fitness','#6c3fb5'],[18,25,'Average','#f59e0b'],[25,50,'Obese','#ef4444']]; }
37 function femaleRanges() { return [[0,14,'Essential','#3b82f6'],[14,21,'Athletes','#10b981'],[21,25,'Fitness','#6c3fb5'],[25,32,'Average','#f59e0b'],[32,50,'Obese','#ef4444']]; }
38
39 function typoCssVarsForEl(typo, prefix, el) {
40 if (!typo) return;
41 if (typo.family) el.style.setProperty(prefix + 'font-family', "'" + typo.family + "', sans-serif");
42 if (typo.weight) el.style.setProperty(prefix + 'font-weight', typo.weight);
43 if (typo.transform) el.style.setProperty(prefix + 'text-transform', typo.transform);
44 if (typo.style) el.style.setProperty(prefix + 'font-style', typo.style);
45 if (typo.decoration) el.style.setProperty(prefix + 'text-decoration', typo.decoration);
46 var su = typo.sizeUnit || 'px';
47 if (typo.sizeDesktop !== '' && typo.sizeDesktop != null) el.style.setProperty(prefix + 'font-size-d', typo.sizeDesktop + su);
48 if (typo.sizeTablet !== '' && typo.sizeTablet != null) el.style.setProperty(prefix + 'font-size-t', typo.sizeTablet + su);
49 if (typo.sizeMobile !== '' && typo.sizeMobile != null) el.style.setProperty(prefix + 'font-size-m', typo.sizeMobile + su);
50 var lhu = typo.lineHeightUnit || '';
51 if (typo.lineHeightDesktop !== '' && typo.lineHeightDesktop != null) el.style.setProperty(prefix + 'line-height-d', typo.lineHeightDesktop + lhu);
52 if (typo.lineHeightTablet !== '' && typo.lineHeightTablet != null) el.style.setProperty(prefix + 'line-height-t', typo.lineHeightTablet + lhu);
53 if (typo.lineHeightMobile !== '' && typo.lineHeightMobile != null) el.style.setProperty(prefix + 'line-height-m', typo.lineHeightMobile + lhu);
54 var lsu = typo.letterSpacingUnit || 'px';
55 if (typo.letterSpacingDesktop !== '' && typo.letterSpacingDesktop != null) el.style.setProperty(prefix + 'letter-spacing-d', typo.letterSpacingDesktop + lsu);
56 if (typo.letterSpacingTablet !== '' && typo.letterSpacingTablet != null) el.style.setProperty(prefix + 'letter-spacing-t', typo.letterSpacingTablet + lsu);
57 if (typo.letterSpacingMobile !== '' && typo.letterSpacingMobile != null) el.style.setProperty(prefix + 'letter-spacing-m', typo.letterSpacingMobile + lsu);
58 var wsu = typo.wordSpacingUnit || 'px';
59 if (typo.wordSpacingDesktop !== '' && typo.wordSpacingDesktop != null) el.style.setProperty(prefix + 'word-spacing-d', typo.wordSpacingDesktop + wsu);
60 if (typo.wordSpacingTablet !== '' && typo.wordSpacingTablet != null) el.style.setProperty(prefix + 'word-spacing-t', typo.wordSpacingTablet + wsu);
61 if (typo.wordSpacingMobile !== '' && typo.wordSpacingMobile != null) el.style.setProperty(prefix + 'word-spacing-m', typo.wordSpacingMobile + wsu);
62 }
63
64 function buildApp(app) {
65 var opts = {};
66 try { opts = JSON.parse(app.getAttribute('data-opts') || '{}'); } catch(e) {}
67 var o = opts;
68 var accent = o.accentColor || '#6c3fb5';
69 var labelC = o.labelColor || '#374151';
70 var radius = (o.cardRadius || 16) + 'px';
71 var inpRad = (o.inputRadius || 8) + 'px';
72 var resultBg= o.resultBg || '#f5f3ff';
73 var resultBr= o.resultBorder || '#ede9fe';
74
75 app.innerHTML = '';
76 app.style.fontFamily = 'inherit';
77
78 var section = document.createElement('div');
79 section.style.cssText = 'padding-top:' + (o.paddingTop||60) + 'px;padding-bottom:' + (o.paddingBottom||60) + 'px;background:' + (o.sectionBg||'') + ';';
80 app.appendChild(section);
81
82 var card = document.createElement('div');
83 card.style.cssText = 'background:' + (o.cardBg||'#fff') + ';border-radius:' + radius + ';padding:36px 32px;max-width:' + (o.maxWidth||560) + 'px;margin:0 auto;box-shadow:0 4px 24px rgba(0,0,0,.09);box-sizing:border-box;';
84 section.appendChild(card);
85
86 // Title/subtitle
87 if (o.showTitle || o.showSubtitle) {
88 var hdr = document.createElement('div');
89 hdr.style.marginBottom = '20px';
90 if (o.showTitle) { var t=document.createElement('div'); t.className='bkbg-bfc-title'; t.textContent=o.title||'Body Fat Calculator'; t.style.cssText='color:'+(o.titleColor||'#1e1b4b')+';margin-bottom:6px;'; hdr.appendChild(t); }
91 if (o.showSubtitle && o.subtitle) { var s=document.createElement('div'); s.textContent=o.subtitle; s.style.cssText='font-size:15px;color:'+(o.subtitleColor||'#6b7280')+';'; hdr.appendChild(s); }
92 card.appendChild(hdr);
93 }
94
95 var gender = o.defaultGender || 'male';
96 var unit = o.defaultUnit || 'metric';
97 var unitLbl = unit === 'metric' ? 'cm' : 'in';
98
99 // Helper: convert to cm
100 function toCm(v) { return unit === 'imperial' ? v * 2.54 : v; }
101
102 // Gender tabs
103 var genderRow = document.createElement('div');
104 genderRow.style.cssText = 'display:flex;gap:10px;margin-bottom:20px;';
105 var gBtns = {};
106 ['male','female'].forEach(function(g) {
107 var btn = document.createElement('button');
108 btn.type = 'button';
109 btn.textContent = g === 'male' ? '♂ Male' : '♀ Female';
110 btn.style.cssText = 'flex:1;padding:9px 16px;border-radius:8px;cursor:pointer;font-family:inherit;font-size:14px;font-weight:700;transition:all .15s;';
111 btn.addEventListener('click', function() { gender = g; refreshGender(); update(); });
112 gBtns[g] = btn;
113 genderRow.appendChild(btn);
114 });
115 card.appendChild(genderRow);
116
117 // Unit tabs
118 var unitRow = document.createElement('div');
119 unitRow.style.cssText = 'display:flex;gap:10px;margin-bottom:24px;';
120 var uBtns = {};
121 [['metric','Metric (cm)'],['imperial','Imperial (in)']].forEach(function(pair) {
122 var btn = document.createElement('button');
123 btn.type = 'button'; btn.textContent = pair[1];
124 btn.style.cssText = 'flex:1;padding:9px 16px;border-radius:8px;cursor:pointer;font-family:inherit;font-size:14px;font-weight:700;transition:all .15s;';
125 btn.addEventListener('click', function() { unit = pair[0]; unitLbl = unit==='metric'?'cm':'in'; refreshUnit(); });
126 uBtns[pair[0]] = btn;
127 unitRow.appendChild(btn);
128 });
129 card.appendChild(unitRow);
130
131 function styleTab(btn, active) {
132 btn.style.border = '2px solid ' + (active ? accent : '#e5e7eb');
133 btn.style.background = active ? accent : 'transparent';
134 btn.style.color = active ? '#fff' : accent;
135 }
136 function refreshGender() { ['male','female'].forEach(function(g){ styleTab(gBtns[g], g===gender); }); buildHipRow(); }
137 function refreshUnit() {
138 ['metric','imperial'].forEach(function(u){ styleTab(uBtns[u], u===unit); });
139 unitLbl = unit === 'metric' ? 'cm' : 'in';
140 ['height','waist','neck','hip'].forEach(function(f) {
141 var lEl = document.getElementById('bkbg-bfc-lbl-'+f);
142 if (lEl) lEl.textContent = unitLbl;
143 });
144 update();
145 }
146 refreshGender(); refreshUnit();
147
148 // Input grid
149 var grid = document.createElement('div');
150 grid.className = 'bkbg-bfc-input-grid';
151 grid.style.cssText = 'display:grid;grid-template-columns:1fr 1fr;gap:0 20px;margin-bottom:20px;';
152 card.appendChild(grid);
153
154 var inputs = {};
155 var defaults = { metric: { height:170, waist:85, neck:37, hip:95 }, imperial: { height:67, waist:33, neck:15, hip:37 } };
156
157 function makeInputRow(field, label, container) {
158 var row = document.createElement('div');
159 row.className = 'bkbg-bfc-input-row';
160 row.setAttribute('data-field', field);
161 row.style.marginBottom = '14px';
162 var lbl = document.createElement('label');
163 lbl.style.cssText = 'display:flex;justify-content:space-between;font-size:13px;font-weight:600;color:'+labelC+';margin-bottom:5px;';
164 var nm = document.createElement('span'); nm.textContent = label;
165 var su = document.createElement('span'); su.id = 'bkbg-bfc-lbl-'+field; su.textContent = unitLbl; su.style.cssText = 'font-weight:400;color:#9ca3af;';
166 lbl.appendChild(nm); lbl.appendChild(su);
167 row.appendChild(lbl);
168 var inp = document.createElement('input');
169 inp.type = 'number'; inp.min = '0'; inp.step = '0.1';
170 inp.value = (defaults[unit] || defaults.metric)[field];
171 inp.style.cssText = 'width:100%;padding:9px 12px;border-radius:'+inpRad+';border:1.5px solid #e5e7eb;font-size:16px;outline:none;box-sizing:border-box;';
172 inp.addEventListener('focus', function(){ inp.style.borderColor=accent; inp.style.boxShadow='0 0 0 3px rgba(108,63,181,.15)'; });
173 inp.addEventListener('blur', function(){ inp.style.borderColor='#e5e7eb'; inp.style.boxShadow=''; });
174 inp.addEventListener('input', update);
175 row.appendChild(inp);
176 inputs[field] = inp;
177 container.appendChild(row);
178 }
179
180 makeInputRow('height', 'Height', grid);
181 makeInputRow('waist', 'Waist (at navel)', grid);
182 makeInputRow('neck', 'Neck', grid);
183
184 var hipRow;
185 function buildHipRow() {
186 if (gender === 'female') {
187 if (!hipRow) {
188 hipRow = document.createElement('div');
189 hipRow.className = 'bkbg-bfc-input-row';
190 hipRow.style.marginBottom = '14px';
191 var lbl = document.createElement('label');
192 lbl.style.cssText = 'display:flex;justify-content:space-between;font-size:13px;font-weight:600;color:'+labelC+';margin-bottom:5px;';
193 var nm = document.createElement('span'); nm.textContent = 'Hips';
194 var su = document.createElement('span'); su.id = 'bkbg-bfc-lbl-hip'; su.textContent = unitLbl; su.style.cssText = 'font-weight:400;color:#9ca3af;';
195 lbl.appendChild(nm); lbl.appendChild(su);
196 hipRow.appendChild(lbl);
197 var inp = document.createElement('input'); inp.type = 'number'; inp.min = '0'; inp.step = '0.1'; inp.value = (defaults[unit]||defaults.metric).hip;
198 inp.style.cssText = 'width:100%;padding:9px 12px;border-radius:'+inpRad+';border:1.5px solid #e5e7eb;font-size:16px;outline:none;box-sizing:border-box;';
199 inp.addEventListener('focus',function(){ inp.style.borderColor=accent; inp.style.boxShadow='0 0 0 3px rgba(108,63,181,.15)'; });
200 inp.addEventListener('blur', function(){ inp.style.borderColor='#e5e7eb'; inp.style.boxShadow=''; });
201 inp.addEventListener('input', update);
202 hipRow.appendChild(inp);
203 inputs.hip = inp;
204 }
205 grid.appendChild(hipRow);
206 } else if (hipRow && hipRow.parentNode) {
207 hipRow.parentNode.removeChild(hipRow);
208 }
209 }
210
211 // Result
212 var resultBox = document.createElement('div');
213 resultBox.style.cssText = 'background:'+resultBg+';border:2px solid '+resultBr+';border-radius:'+radius+';padding:24px 28px;text-align:center;margin-bottom:16px;';
214 card.appendChild(resultBox);
215
216 // Category bar
217 var catSection = document.createElement('div');
218 if (o.showChart) card.appendChild(catSection);
219
220 function update() {
221 var h = toCm(parseFloat(inputs.height.value)||0);
222 var w = toCm(parseFloat(inputs.waist.value)||0);
223 var n = toCm(parseFloat(inputs.neck.value)||0);
224 var hi= gender==='female' && inputs.hip ? toCm(parseFloat(inputs.hip.value)||0) : 0;
225 var bf = calcBodyFat(gender, h, w, n, hi);
226 var cat = bf !== null ? getCategory(bf, gender) : null;
227
228 resultBox.innerHTML = '';
229 if (bf !== null && cat) {
230 var valEl = document.createElement('div'); valEl.className='bkbg-bfc-bf-value'; valEl.textContent = bf+'%'; valEl.style.cssText = 'color:'+cat.color+';';
231 var catEl = document.createElement('div'); catEl.textContent = cat.label; catEl.style.cssText = 'margin-top:6px;font-weight:700;font-size:16px;color:'+cat.color+';';
232 var lblEl = document.createElement('div'); lblEl.textContent = 'Body Fat Percentage'; lblEl.style.cssText = 'margin-top:4px;font-size:13px;color:'+labelC+';';
233 resultBox.appendChild(valEl); resultBox.appendChild(catEl); resultBox.appendChild(lblEl);
234 } else {
235 var ph = document.createElement('div'); ph.textContent = 'Enter measurements above'; ph.style.cssText = 'color:'+labelC+';font-size:15px;';
236 resultBox.appendChild(ph);
237 }
238
239 if (o.showChart) {
240 catSection.innerHTML = '';
241 var ranges = gender === 'male' ? maleRanges() : femaleRanges();
242 var track = document.createElement('div'); track.style.cssText = 'display:flex;height:14px;border-radius:100px;overflow:hidden;margin-bottom:8px;';
243 ranges.forEach(function(r) { var seg=document.createElement('div'); seg.style.cssText='flex:'+(r[1]-r[0])+';background:'+r[3]+';'; track.appendChild(seg); });
244 catSection.appendChild(track);
245 if (o.showCategories) {
246 var leg = document.createElement('div'); leg.style.cssText = 'display:flex;flex-wrap:wrap;gap:6px;';
247 ranges.forEach(function(r) {
248 var chip=document.createElement('span'); chip.textContent=r[2]+' ('+r[0]+(r[1]<50?'-'+r[1]:'+')+' %)'; chip.style.cssText='font-size:11px;font-weight:700;background:'+r[3]+'22;color:'+r[3]+';padding:2px 8px;border-radius:100px;';
249 leg.appendChild(chip);
250 });
251 catSection.appendChild(leg);
252 }
253 }
254 }
255
256 update();
257 typoCssVarsForEl(o.typoTitle, '--bkbg-bfc-title-', app);
258 typoCssVarsForEl(o.typoResult, '--bkbg-bfc-result-', app);
259 }
260
261 document.querySelectorAll('.bkbg-bfc-app').forEach(buildApp);
262 })();
263