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

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

205 lines 10.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 fmtMoney(val, currency, pos) {
5 var s = Math.abs(val).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
6 return pos === 'after' ? s + currency : currency + s;
7 }
8
9 function buildApp(app) {
10 var opts = {};
11 try { opts = JSON.parse(app.dataset.opts || '{}'); } catch (e) {}
12
13 var bill = opts.defaultBill || 50;
14 var tipPct = opts.defaultTip || 15;
15 var customTip = '';
16 var people = opts.defaultPeople || 2;
17 var currency = opts.currency || '$';
18 var pos = opts.currencyPos || 'before';
19 var quickTips = opts.quickTips && opts.quickTips.length ? opts.quickTips : [10, 15, 18, 20, 25];
20
21 var accent = opts.accentColor || '#6c3fb5';
22 var actBg = opts.activeBtnBg || accent;
23 var actCol = opts.activeBtnColor || '#ffffff';
24 var inBg = opts.quickBtnBg || '#f3f4f6';
25 var inCol = opts.quickBtnColor || '#374151';
26 var cardBg = opts.cardBg || '#ffffff';
27 var resultBg = opts.resultBg || '#f5f3ff';
28 var resultBdr = opts.resultBorder || '#ede9fe';
29 var resultCol = opts.resultNumColor || accent;
30 var labelColor = opts.labelColor || '#374151';
31 var titleColor = opts.titleColor || '#1e1b4b';
32 var subColor = opts.subtitleColor || '#6b7280';
33 var cRadius = (opts.cardRadius || 16) + 'px';
34 var btnR = (opts.btnRadius || 8) + 'px';
35 var maxW = (opts.maxWidth || 520) + 'px';
36 var ptop = (opts.paddingTop || 60) + 'px';
37 var pbot = (opts.paddingBottom || 60) + 'px';
38
39
40 /* Build card */
41 app.innerHTML = '';
42 var card = document.createElement('div');
43 card.className = 'bkbg-tc-card';
44 card.style.cssText = 'background:' + cardBg + ';border-radius:' + cRadius + ';padding:32px;box-shadow:0 4px 24px rgba(0,0,0,0.08);max-width:' + maxW + ';margin:0 auto;padding-top:' + ptop + ';padding-bottom:' + pbot + ';box-sizing:border-box;';
45 app.appendChild(card);
46
47 if (opts.showTitle !== false && opts.title) {
48 var titleEl = document.createElement('h2');
49 titleEl.className = 'bkbg-tc-title';
50 titleEl.textContent = opts.title;
51 titleEl.style.cssText = 'color:' + titleColor + ';';
52 card.appendChild(titleEl);
53 }
54 if (opts.showSubtitle !== false && opts.subtitle) {
55 var subEl = document.createElement('p');
56 subEl.className = 'bkbg-tc-subtitle';
57 subEl.textContent = opts.subtitle;
58 subEl.style.color = subColor;
59 card.appendChild(subEl);
60 }
61
62 /* Bill input */
63 var billField = document.createElement('div'); billField.className = 'bkbg-tc-field';
64 var billLabel = document.createElement('label'); billLabel.className = 'bkbg-tc-label'; billLabel.textContent = 'Bill Amount'; billLabel.style.color = labelColor;
65 var billWrap = document.createElement('div'); billWrap.className = 'bkbg-tc-input-wrap';
66 var billPrefix = document.createElement('span'); billPrefix.className = 'bkbg-tc-prefix'; billPrefix.textContent = pos === 'before' ? currency : '';
67 var billInp = document.createElement('input');
68 billInp.type = 'number'; billInp.className = 'bkbg-tc-input' + (pos === 'before' ? ' with-prefix' : ''); billInp.value = bill; billInp.min = 0; billInp.step = '0.01';
69 billInp.style.accentColor = accent;
70 billWrap.appendChild(billPrefix); billWrap.appendChild(billInp);
71 billField.appendChild(billLabel); billField.appendChild(billWrap);
72 card.appendChild(billField);
73
74 /* Quick tip buttons */
75 var tipField = document.createElement('div'); tipField.className = 'bkbg-tc-field';
76 var tipLabel = document.createElement('label'); tipLabel.className = 'bkbg-tc-label'; tipLabel.textContent = 'Tip Percentage'; tipLabel.style.color = labelColor;
77 var tipsRow = document.createElement('div'); tipsRow.className = 'bkbg-tc-tips';
78
79 var tipBtns = [];
80 quickTips.forEach(function(pct) {
81 var btn = document.createElement('button');
82 btn.className = 'bkbg-tc-tip-btn';
83 btn.textContent = pct + '%';
84 btn.dataset.pct = pct;
85 btn.style.borderRadius = btnR;
86 tipsRow.appendChild(btn);
87 tipBtns.push(btn);
88 });
89
90 var customInp = null;
91 if (opts.allowCustomTip !== false) {
92 customInp = document.createElement('input');
93 customInp.type = 'number'; customInp.className = 'bkbg-tc-custom-tip';
94 customInp.placeholder = 'Custom %'; customInp.min = 0; customInp.max = 100;
95 customInp.style.borderRadius = btnR;
96 tipsRow.appendChild(customInp);
97 }
98
99 tipField.appendChild(tipLabel); tipField.appendChild(tipsRow);
100 card.appendChild(tipField);
101
102 function updateTipBtns() {
103 tipBtns.forEach(function(btn) {
104 var isActive = customTip === '' && parseInt(btn.dataset.pct) === tipPct;
105 btn.style.background = isActive ? actBg : inBg;
106 btn.style.color = isActive ? actCol: inCol;
107 });
108 if (customInp) {
109 customInp.style.borderColor = customTip !== '' ? accent : '#e5e7eb';
110 }
111 }
112 updateTipBtns();
113
114 /* People splitter */
115 var peopleField = null;
116 var peopleNum = null;
117 if (opts.showSplitter !== false) {
118 peopleField = document.createElement('div'); peopleField.className = 'bkbg-tc-field';
119 var pLabel = document.createElement('label'); pLabel.className = 'bkbg-tc-label'; pLabel.textContent = 'Number of People'; pLabel.style.color = labelColor;
120 var pRow = document.createElement('div'); pRow.className = 'bkbg-tc-people-row';
121 var minusBtn = document.createElement('button'); minusBtn.className = 'bkbg-tc-count-btn'; minusBtn.textContent = ''; minusBtn.style.cssText = 'color:' + accent + ';border-color:' + accent + ';';
122 peopleNum = document.createElement('span'); peopleNum.className = 'bkbg-tc-count-num'; peopleNum.textContent = people; peopleNum.style.color = titleColor;
123 var plusBtn = document.createElement('button'); plusBtn.className = 'bkbg-tc-count-btn plus'; plusBtn.textContent = '+'; plusBtn.style.cssText = 'color:#fff;background:' + accent + ';border-color:' + accent + ';';
124 pRow.appendChild(minusBtn); pRow.appendChild(peopleNum); pRow.appendChild(plusBtn);
125 peopleField.appendChild(pLabel); peopleField.appendChild(pRow);
126 card.appendChild(peopleField);
127
128 minusBtn.addEventListener('click', function() { people = Math.max(1, people - 1); peopleNum.textContent = people; update(); });
129 plusBtn.addEventListener('click', function() { people++; peopleNum.textContent = people; update(); });
130 }
131
132 /* Results */
133 var cols = 0;
134 if (opts.showTipAmount !== false) cols++;
135 if (opts.showTotal !== false) cols++;
136 var resultsBox = document.createElement('div');
137 resultsBox.className = 'bkbg-tc-results';
138 resultsBox.style.cssText = 'background:' + resultBg + ';border:1.5px solid ' + resultBdr + ';border-radius:' + cRadius + ';grid-template-columns:' + (cols > 1 ? '1fr 1fr' : '1fr') + ';';
139 card.appendChild(resultsBox);
140
141 var tipAmtEl = null, totalEl = null, perPersonEl = null;
142
143 if (opts.showTipAmount !== false) {
144 var tipAmtBox = document.createElement('div'); tipAmtBox.className = 'bkbg-tc-result-item';
145 var tipAmtLbl = document.createElement('div'); tipAmtLbl.className = 'bkbg-tc-result-label'; tipAmtLbl.textContent = 'Tip Amount';
146 tipAmtEl = document.createElement('div'); tipAmtEl.className = 'bkbg-tc-result-value'; tipAmtEl.style.cssText = 'font-size:28px;color:' + accent + ';';
147 tipAmtBox.appendChild(tipAmtLbl); tipAmtBox.appendChild(tipAmtEl);
148 resultsBox.appendChild(tipAmtBox);
149 }
150
151 if (opts.showTotal !== false) {
152 var totalBox = document.createElement('div'); totalBox.className = 'bkbg-tc-result-item';
153 var totalLbl = document.createElement('div'); totalLbl.className = 'bkbg-tc-result-label'; totalLbl.textContent = 'Total';
154 totalEl = document.createElement('div'); totalEl.className = 'bkbg-tc-result-value'; totalEl.style.cssText = 'font-size:28px;color:' + titleColor + ';';
155 totalBox.appendChild(totalLbl); totalBox.appendChild(totalEl);
156 resultsBox.appendChild(totalBox);
157 }
158
159 if (opts.showSplitter !== false && opts.showPerPerson !== false) {
160 var ppBox = document.createElement('div'); ppBox.className = 'bkbg-tc-result-item bkbg-tc-per-person';
161 ppBox.style.borderTopColor = resultBdr;
162 var ppLbl = document.createElement('div'); ppLbl.className = 'bkbg-tc-result-label'; ppLbl.textContent = 'Per Person';
163 perPersonEl = document.createElement('div'); perPersonEl.className = 'bkbg-tc-result-value bkbg-tc-per-person-value'; perPersonEl.style.cssText = 'color:' + resultCol + ';';
164 ppBox.appendChild(ppLbl); ppBox.appendChild(perPersonEl);
165 resultsBox.appendChild(ppBox);
166 }
167
168 /* Compute & update */
169 function update() {
170 var eff = customTip !== '' ? parseFloat(customTip) : tipPct;
171 if (isNaN(eff)) eff = 0;
172 var tipAmt = bill * eff / 100;
173 var total = bill + tipAmt;
174 var perPerson = people > 0 ? total / people : total;
175 if (tipAmtEl) tipAmtEl.textContent = fmtMoney(tipAmt, currency, pos);
176 if (totalEl) totalEl.textContent = fmtMoney(total, currency, pos);
177 if (perPersonEl) perPersonEl.textContent = fmtMoney(perPerson, currency, pos);
178 }
179 update();
180
181 /* Events */
182 billInp.addEventListener('input', function() { bill = parseFloat(this.value) || 0; update(); });
183
184 tipsRow.addEventListener('click', function(e) {
185 var btn = e.target.closest('.bkbg-tc-tip-btn');
186 if (!btn) return;
187 tipPct = parseInt(btn.dataset.pct);
188 customTip = '';
189 if (customInp) customInp.value = '';
190 updateTipBtns();
191 update();
192 });
193
194 if (customInp) {
195 customInp.addEventListener('input', function() {
196 customTip = this.value;
197 updateTipBtns();
198 update();
199 });
200 }
201 }
202
203 document.querySelectorAll('.bkbg-tc-app').forEach(buildApp);
204 })();
205