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

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

233 lines 11.6 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 map = {
7 family: 'font-family', weight: 'font-weight', style: 'font-style',
8 decoration: 'text-decoration', transform: 'text-transform',
9 sizeDesktop: 'font-size-d', sizeTablet: 'font-size-t', sizeMobile: 'font-size-m',
10 lineHeightDesktop: 'line-height-d', lineHeightTablet: 'line-height-t', lineHeightMobile: 'line-height-m',
11 letterSpacingDesktop: 'letter-spacing-d', letterSpacingTablet: 'letter-spacing-t', letterSpacingMobile: 'letter-spacing-m',
12 wordSpacingDesktop: 'word-spacing-d', wordSpacingTablet: 'word-spacing-t', wordSpacingMobile: 'word-spacing-m'
13 };
14 Object.keys(map).forEach(function (k) {
15 if (typo[k] !== undefined && typo[k] !== '') {
16 var v = typo[k];
17 if (['sizeDesktop','sizeTablet','sizeMobile'].indexOf(k) !== -1) {
18 v = v + (typo.sizeUnit || 'px');
19 } else if (['lineHeightDesktop','lineHeightTablet','lineHeightMobile'].indexOf(k) !== -1) {
20 v = v + (typo.lineHeightUnit || '');
21 } else if (['letterSpacingDesktop','letterSpacingTablet','letterSpacingMobile'].indexOf(k) !== -1) {
22 v = v + (typo.letterSpacingUnit || 'px');
23 } else if (['wordSpacingDesktop','wordSpacingTablet','wordSpacingMobile'].indexOf(k) !== -1) {
24 v = v + (typo.wordSpacingUnit || 'px');
25 }
26 el.style.setProperty(prefix + map[k], String(v));
27 }
28 });
29 }
30
31 var UNITS = {
32 mpg: { distLabel: 'Distance', effLabel: 'Fuel Economy', priceLabel: 'Fuel Price', volUnit: 'gal', effUnit: 'mpg', distUnit: 'mi' },
33 lper100:{ distLabel: 'Distance', effLabel: 'Fuel Economy', priceLabel: 'Fuel Price', volUnit: 'L', effUnit: 'L/100km', distUnit: 'km' },
34 kmpl: { distLabel: 'Distance', effLabel: 'Fuel Economy', priceLabel: 'Fuel Price', volUnit: 'L', effUnit: 'km/L', distUnit: 'km' }
35 };
36
37 function calcFuel(dist, eff, price, unit) {
38 if (unit === 'mpg') {
39 var gallons = eff > 0 ? dist / eff : 0;
40 return { cost: gallons * price, litres: gallons * 3.78541, gallons: gallons };
41 } else if (unit === 'lper100') {
42 var l = eff > 0 ? (dist / 100) * eff : 0;
43 return { cost: l * price, litres: l, gallons: l / 3.78541 };
44 } else {
45 var l2 = eff > 0 ? dist / eff : 0;
46 return { cost: l2 * price, litres: l2, gallons: l2 / 3.78541 };
47 }
48 }
49
50 function co2Kg(litres) { return litres * 2.31; }
51
52 function esc(s) { return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;'); }
53
54 function buildApp(app) {
55 var opts;
56 try { opts = JSON.parse(app.getAttribute('data-opts') || '{}'); } catch (e) { return; }
57 var o = opts;
58 var accent = o.accentColor || '#6c3fb5';
59 var cur = o.currency || '$';
60
61 app.style.paddingTop = (o.paddingTop || 60) + 'px';
62 app.style.paddingBottom = (o.paddingBottom || 60) + 'px';
63 if (o.sectionBg) app.style.background = o.sectionBg;
64
65 typoCssVarsForEl(o.typoTitle, '--bkbg-fuel-tt-', app);
66 typoCssVarsForEl(o.typoSubtitle, '--bkbg-fuel-st-', app);
67 typoCssVarsForEl(o.typoResult, '--bkbg-fuel-rs-', app);
68
69 var maxW = (o.maxWidth || 620) + 'px';
70
71 /* Header */
72 if (o.showTitle || o.showSubtitle) {
73 var hdr = document.createElement('div');
74 hdr.style.cssText = 'text-align:center;margin-bottom:32px;max-width:' + maxW + ';margin-left:auto;margin-right:auto';
75 if (o.showTitle && o.title) {
76 var ht = document.createElement('h3');
77 ht.className = 'bkbg-fuel-title';
78 ht.textContent = o.title;
79 ht.style.cssText = 'color:' + (o.titleColor || '#1e1b4b') + ';margin:0 0 8px';
80 hdr.appendChild(ht);
81 }
82 if (o.showSubtitle && o.subtitle) {
83 var hs = document.createElement('p');
84 hs.className = 'bkbg-fuel-subtitle';
85 hs.textContent = o.subtitle;
86 hs.style.cssText = 'color:' + (o.subtitleColor || '#6b7280') + ';margin:0';
87 hdr.appendChild(hs);
88 }
89 app.appendChild(hdr);
90 }
91
92 /* Card */
93 var card = document.createElement('div');
94 card.style.cssText = 'background:' + (o.cardBg || '#fff') + ';border-radius:' + (o.cardRadius || 16) + 'px;padding:32px;max-width:' + maxW + ';margin:0 auto;box-shadow:0 4px 24px rgba(0,0,0,0.06)';
95 app.appendChild(card);
96
97 /* State */
98 var unitKey = o.unit || 'mpg';
99 var dist = o.defaultDist || 300;
100 var eff = o.defaultEff || 30;
101 var price = o.defaultPrice || 3.50;
102 var pax = o.defaultPassengers || 2;
103
104 /* Unit toggle */
105 var unitRow = document.createElement('div');
106 unitRow.style.cssText = 'display:flex;gap:8px;margin-bottom:24px';
107 var unitBtns = {};
108 ['mpg','lper100','kmpl'].forEach(function (k) {
109 var btn = document.createElement('button');
110 btn.textContent = k === 'lper100' ? 'L/100km' : k.toUpperCase();
111 btn.className = 'bkbg-fuel-unit-btn';
112 btn.style.cssText = 'flex:1;padding:8px;border:none;border-radius:' + (o.inputRadius || 8) + 'px;font-weight:600;font-size:13px;cursor:pointer;transition:background 0.15s';
113 btn.addEventListener('click', function () { unitKey = k; refreshUnitBtns(); buildInputSection(); update(); });
114 unitBtns[k] = btn;
115 unitRow.appendChild(btn);
116 });
117 card.appendChild(unitRow);
118
119 function refreshUnitBtns() {
120 Object.keys(unitBtns).forEach(function (k) {
121 unitBtns[k].style.background = k === unitKey ? accent : (o.statCardBg || '#f9fafb');
122 unitBtns[k].style.color = k === unitKey ? '#fff' : (o.labelColor || '#374151');
123 });
124 }
125 refreshUnitBtns();
126
127 /* Input section */
128 var inputSection = document.createElement('div');
129 card.appendChild(inputSection);
130
131 var distInput, effInput, priceInput, paxInput;
132
133 function makeRow(labelText, suffix) {
134 var row = document.createElement('div');
135 row.className = 'bkbg-fuel-input-row';
136 var lbl = document.createElement('label');
137 lbl.textContent = labelText;
138 lbl.style.color = o.labelColor || '#374151';
139 var right = document.createElement('div');
140 right.style.cssText = 'display:flex;align-items:center;gap:6px';
141 var inp = document.createElement('input');
142 inp.type = 'number'; inp.min = '0'; inp.step = '0.01';
143 inp.style.cssText = 'width:90px;text-align:right;border:1px solid #d1d5db;border-radius:' + (o.inputRadius || 8) + 'px;padding:5px 8px;font-size:14px;box-sizing:border-box';
144 var sfx = document.createElement('span');
145 sfx.textContent = suffix;
146 sfx.style.cssText = 'color:' + (o.subtitleColor || '#6b7280') + ';font-size:13px;min-width:56px';
147 right.appendChild(inp);
148 right.appendChild(sfx);
149 row.appendChild(lbl);
150 row.appendChild(right);
151 return { row: row, input: inp, suffix: sfx };
152 }
153
154 function buildInputSection() {
155 inputSection.innerHTML = '';
156 var u = UNITS[unitKey];
157 var dr = makeRow(u.distLabel + ' (' + u.distUnit + ')', u.distUnit);
158 dr.input.value = dist;
159 dr.input.addEventListener('input', function () { dist = parseFloat(dr.input.value) || 0; update(); });
160 distInput = dr.input;
161
162 var er = makeRow(u.effLabel, u.effUnit);
163 er.input.value = eff;
164 er.input.addEventListener('input', function () { eff = parseFloat(er.input.value) || 0; update(); });
165 effInput = er.input;
166
167 var pr = makeRow(u.priceLabel + ' (' + cur + '/' + u.volUnit + ')', cur + '/' + u.volUnit);
168 pr.input.value = price;
169 pr.input.step = '0.01';
170 pr.input.addEventListener('input', function () { price = parseFloat(pr.input.value) || 0; update(); });
171 priceInput = pr.input;
172
173 if (o.showPerPerson !== false) {
174 var par = makeRow('Passengers', 'people');
175 par.input.value = pax;
176 par.input.min = '1';
177 par.input.step = '1';
178 par.input.addEventListener('input', function () { pax = parseInt(par.input.value) || 1; update(); });
179 paxInput = par.input;
180 inputSection.appendChild(dr.row);
181 inputSection.appendChild(er.row);
182 inputSection.appendChild(pr.row);
183 inputSection.appendChild(par.row);
184 } else {
185 inputSection.appendChild(dr.row);
186 inputSection.appendChild(er.row);
187 inputSection.appendChild(pr.row);
188 }
189 }
190 buildInputSection();
191
192 /* Result area */
193 var resultArea = document.createElement('div');
194 resultArea.style.cssText = 'background:' + (o.resultBg || '#f5f3ff') + ';border:2px solid ' + (o.resultBorder || '#ede9fe') + ';border-radius:' + (o.cardRadius || 16) + 'px;padding:24px;text-align:center;margin:24px 0';
195 card.appendChild(resultArea);
196
197 /* Stat cards */
198 var statRow = document.createElement('div');
199 statRow.className = 'bkbg-fuel-stat-cards';
200 card.appendChild(statRow);
201
202 function update() {
203 var res = calcFuel(dist, eff, price, unitKey);
204 var totalCost = res.cost;
205 var perPerson = pax > 0 ? totalCost / pax : totalCost;
206 var co2 = co2Kg(res.litres);
207
208 resultArea.innerHTML =
209 '<div style="font-size:13px;color:' + (o.subtitleColor || '#6b7280') + ';margin-bottom:4px">Total Fuel Cost</div>' +
210 '<div class="bkbg-fuel-result-value" style="color:' + (o.totalColor || accent) + '">' + esc(cur + totalCost.toFixed(2)) + '</div>' +
211 (o.showRoundTrip !== false ? '<div style="font-size:12px;color:' + (o.subtitleColor || '#6b7280') + ';margin-top:6px">one way · ' + esc(cur + (totalCost * 2).toFixed(2)) + ' round trip</div>' : '');
212
213 statRow.innerHTML = '';
214 var stats = [];
215 if (o.showLitres !== false) stats.push({ val: res.litres.toFixed(1) + 'L / ' + res.gallons.toFixed(1) + 'gal', lbl: 'Fuel Used', color: o.labelColor || '#374151' });
216 if (o.showPerPerson !== false) stats.push({ val: cur + perPerson.toFixed(2), lbl: 'Per Person', color: accent });
217 if (o.showCO2 !== false) stats.push({ val: co2.toFixed(1) + ' kg', lbl: 'CO₂ Emitted', color: o.co2Color || '#10b981' });
218
219 stats.forEach(function (st) {
220 var sc = document.createElement('div');
221 sc.className = 'bkbg-fuel-stat-card';
222 sc.style.cssText = 'background:' + (o.statCardBg || '#f9fafb') + ';border-radius:12px;padding:16px;text-align:center;flex:1;min-width:100px';
223 sc.innerHTML = '<div class="bkbg-fuel-stat-val" style="color:' + st.color + '">' + esc(st.val) + '</div><div class="bkbg-fuel-stat-lbl" style="color:' + (o.subtitleColor || '#6b7280') + '">' + esc(st.lbl) + '</div>';
224 statRow.appendChild(sc);
225 });
226 }
227
228 update();
229 }
230
231 document.querySelectorAll('.bkbg-fuel-app').forEach(buildApp);
232 })();
233