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 / multi-step-form / frontend.js

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

200 lines 8.8 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 document.querySelectorAll('.bkbg-msf-wrapper').forEach(function (wrapper) {
5 var form = wrapper.querySelector('.bkbg-msf-form');
6 if (!form) return;
7
8 var total = parseInt(form.getAttribute('data-total-steps'), 10) || 1;
9 var panels = form.querySelectorAll('.bkbg-msf-step-panel');
10 var success = form.querySelector('.bkbg-msf-success');
11 var indicator = wrapper.querySelector('.bkbg-msf-indicator');
12 var current = 0;
13
14 /* ── Build indicator ──────────────────────────────────────────── */
15 var progStyle = (indicator && indicator.getAttribute('data-progress')) || 'steps';
16
17 function buildIndicator() {
18 if (!indicator) return;
19 indicator.innerHTML = '';
20
21 if (progStyle === 'bar') {
22 var track = document.createElement('div');
23 track.className = 'bkbg-msf-progress-track';
24 var fill = document.createElement('div');
25 fill.className = 'bkbg-msf-progress-fill';
26 fill.style.width = '0%';
27 track.appendChild(fill);
28 indicator.appendChild(track);
29 return;
30 }
31
32 if (progStyle === 'dots') {
33 for (var di = 0; di < total; di++) {
34 var dot = document.createElement('button');
35 dot.type = 'button';
36 dot.className = 'bkbg-msf-dot' + (di === 0 ? ' is-active' : ' is-pending');
37 dot.setAttribute('aria-label', 'Step ' + (di + 1));
38 (function (idx) {
39 dot.addEventListener('click', function () { goTo(idx); });
40 })(di);
41 indicator.appendChild(dot);
42 }
43 return;
44 }
45
46 /* Circles */
47 for (var ci = 0; ci < total; ci++) {
48 var panel = panels[ci];
49 var circleWrap = document.createElement('div');
50 circleWrap.style.cssText = 'display:flex;flex-direction:column;align-items:center;flex:' + (ci < total - 1 ? '1' : '0') + ';min-width:60px';
51
52 var row = document.createElement('div');
53 row.style.cssText = 'display:flex;align-items:center;width:100%;justify-content:center;position:relative';
54
55 var circle = document.createElement('button');
56 circle.type = 'button';
57 circle.className = 'bkbg-msf-step-circle' + (ci === 0 ? ' is-active' : ' is-pending');
58 circle.textContent = ci + 1;
59 circle.setAttribute('aria-label', 'Go to step ' + (ci + 1));
60 (function (idx) {
61 circle.addEventListener('click', function () { goTo(idx); });
62 })(ci);
63
64 row.appendChild(circle);
65
66 if (ci < total - 1) {
67 var connector = document.createElement('div');
68 connector.className = 'bkbg-msf-connector';
69 row.appendChild(connector);
70 }
71
72 circleWrap.appendChild(row);
73
74 if (panel) {
75 var titleEl = panel.querySelector('.bkbg-msf-step-title');
76 if (titleEl) {
77 var lbl = document.createElement('span');
78 lbl.className = 'bkbg-msf-step-label' + (ci === 0 ? ' is-active' : '');
79 lbl.textContent = titleEl.textContent;
80 circleWrap.appendChild(lbl);
81 }
82 }
83
84 indicator.appendChild(circleWrap);
85 }
86 }
87
88 /* ── Update indicator state ───────────────────────────────────── */
89 function updateIndicator(idx) {
90 if (!indicator) return;
91
92 if (progStyle === 'bar') {
93 var fill = indicator.querySelector('.bkbg-msf-progress-fill');
94 if (fill) fill.style.width = ((idx / Math.max(1, total - 1)) * 100) + '%';
95 return;
96 }
97
98 if (progStyle === 'dots') {
99 var dots = indicator.querySelectorAll('.bkbg-msf-dot');
100 dots.forEach(function (dot, i) {
101 dot.className = 'bkbg-msf-dot ' + (i === idx ? 'is-active' : (i < idx ? 'is-done' : 'is-pending'));
102 });
103 return;
104 }
105
106 var circles = indicator.querySelectorAll('.bkbg-msf-step-circle');
107 var connectors = indicator.querySelectorAll('.bkbg-msf-connector');
108 var labels = indicator.querySelectorAll('.bkbg-msf-step-label');
109
110 circles.forEach(function (c, i) {
111 c.className = 'bkbg-msf-step-circle ' + (i === idx ? 'is-active' : (i < idx ? 'is-done' : 'is-pending'));
112 if (i < idx) c.textContent = '';
113 else c.textContent = i + 1;
114 });
115 connectors.forEach(function (c, i) {
116 c.classList.toggle('is-done', i < idx);
117 });
118 labels.forEach(function (l, i) {
119 l.classList.toggle('is-active', i === idx);
120 });
121 }
122
123 /* ── Show panel ───────────────────────────────────────────────── */
124 function showPanel(idx) {
125 panels.forEach(function (p, i) {
126 p.style.display = i === idx ? 'block' : 'none';
127 p.setAttribute('aria-hidden', i === idx ? 'false' : 'true');
128 });
129
130 /* Update prev/next buttons */
131 panels.forEach(function (p, i) {
132 var prevBtn = p.querySelector('.bkbg-msf-btn-prev');
133 var nextBtn = p.querySelector('.bkbg-msf-btn-next');
134 if (prevBtn) prevBtn.classList.toggle('is-hidden', idx === 0);
135 if (nextBtn) {
136 if (idx === total - 1) {
137 nextBtn.textContent = nextBtn.getAttribute('data-submit-label') || nextBtn.textContent;
138 }
139 }
140 });
141 }
142
143 /* ── Validate current panel ───────────────────────────────────── */
144 function validatePanel(idx) {
145 var panel = panels[idx];
146 if (!panel) return true;
147 var required = panel.querySelectorAll('[required]');
148 var valid = true;
149 required.forEach(function (field) {
150 field.style.borderColor = '';
151 if (!field.value || !field.value.trim()) {
152 field.style.borderColor = '#ef4444';
153 if (valid) field.focus();
154 valid = false;
155 }
156 });
157 return valid;
158 }
159
160 /* ── Navigate ─────────────────────────────────────────────────── */
161 function goTo(idx) {
162 current = Math.min(Math.max(idx, 0), total - 1);
163 showPanel(current);
164 updateIndicator(current);
165 wrapper.scrollIntoView({ behavior: 'smooth', block: 'start' });
166 }
167
168 /* ── Button click handler ─────────────────────────────────────── */
169 form.addEventListener('click', function (e) {
170 var btn = e.target.closest('[data-action]');
171 if (!btn) return;
172 var action = btn.getAttribute('data-action');
173
174 if (action === 'next') {
175 if (!validatePanel(current)) return;
176 goTo(current + 1);
177 } else if (action === 'prev') {
178 goTo(current - 1);
179 } else if (action === 'submit') {
180 if (!validatePanel(current)) return;
181 /* Show success */
182 panels.forEach(function (p) { p.style.display = 'none'; });
183 if (indicator) indicator.style.display = 'none';
184 if (success) success.classList.remove('is-hidden');
185 }
186 });
187
188 /* ── Init ─────────────────────────────────────────────────────── */
189 buildIndicator();
190 showPanel(0);
191 updateIndicator(0);
192
193 /* Cache submit label */
194 panels.forEach(function (p) {
195 var nb = p.querySelector('.bkbg-msf-btn-next[data-action="submit"]');
196 if (nb) nb.setAttribute('data-submit-label', nb.textContent);
197 });
198 });
199 })();
200