PluginProbe
Forumax – AI Powered Advanced Community Forum Plugin / trunk
Forumax – AI Powered Advanced Community Forum Plugin vtrunk
2.4.4 2.4.3 2.4.2 2.4.1 2.4.0 trunk 1.0.8 1.1.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 2.0.0 2.1.0 All 29 releases
bbp-core / assets / admin / js / setup-wizard.js

setup-wizard.js in Forumax – AI Powered Advanced Community Forum Plugin trunk, at assets/admin/js/setup-wizard.js

314 lines 12.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Forumax Setup Wizard JavaScript
3 *
4 * Single-page multi-step wizard — no page reloads.
5 * Updated to work with the Jobus-inspired redesign.
6 *
7 * @package Forumax
8 * @since 2.2.0
9 */
10
11 (function ($) {
12 'use strict';
13
14 const Wizard = {
15
16 currentStep: 1,
17 totalSteps: 0,
18
19 init: function () {
20 this.totalSteps = parseInt( $('.forumax-setup-card').data('total-steps'), 10 ) || 5;
21 this.bindEvents();
22
23 // Restore the last active step from localStorage (defaults to 1).
24 const savedStep = parseInt( localStorage.getItem( 'forumax_setup_current_step' ), 10 ) || 1;
25 const startStep = ( savedStep >= 1 && savedStep <= this.totalSteps ) ? savedStep : 1;
26 this.goToStep( startStep, false );
27 },
28
29 bindEvents: function () {
30 const self = this;
31
32 // Next / Continue — intercepts the save step to fire AJAX first.
33 $(document).on( 'click', '.forumax-btn-next', function () {
34 if ( ! self.validateStep( self.currentStep ) ) return;
35
36 const isSaveStep = ( self.currentStep === self.totalSteps - 1 );
37 if ( isSaveStep ) {
38 self.saveSettings();
39 } else {
40 self.goToStep( self.currentStep + 1 );
41 }
42 });
43
44 // Previous
45 $(document).on( 'click', '.forumax-btn-prev', function () {
46 self.goToStep( self.currentStep - 1 );
47 });
48
49 // Step indicator — click any step to jump directly to it.
50 $(document).on( 'click', '.forumax-progress-step', function () {
51 const target = parseInt( $(this).data('step'), 10 );
52 if ( target && target !== self.currentStep ) {
53 self.goToStep( target );
54 }
55 });
56
57 // Radio card / layout option selection
58 $(document).on( 'click', '.forumax-option-card, .forumax-layout-option', function () {
59 $(this).find('input[type="radio"]').prop('checked', true).trigger('change');
60 });
61
62 // Toggle row: sync toggle switch appearance when clicking the row
63 $(document).on( 'change', '.forumax-toggle-row input[type="checkbox"]', function () {
64 // Visual state handled entirely via CSS :checked sibling selector.
65 });
66
67 // Brand color picker ↔ hex input sync.
68 $(document).on( 'input', '#brand_color', function () {
69 $('#brand_color_hex').val( $(this).val() );
70 });
71 $(document).on( 'input change', '#brand_color_hex', function () {
72 const hex = $(this).val();
73 if ( /^#[0-9A-Fa-f]{6}$/.test( hex ) ) {
74 $('#brand_color').val( hex );
75 }
76 });
77
78 // Auto-save form fields to localStorage
79 $(document).on( 'change blur', '.forumax-setup-form input, .forumax-setup-form textarea', function () {
80 const name = $(this).attr('name');
81 if ( ! name ) return;
82 const val = $(this).is(':checkbox') ? $(this).is(':checked') : $(this).val();
83 localStorage.setItem( 'forumax_setup_' + name, val );
84 });
85
86 this.loadSavedData();
87 },
88
89 /**
90 * Transition to a specific step.
91 *
92 * @param {number} step Target step number.
93 * @param {boolean} animate Whether to animate the transition.
94 */
95 goToStep: function ( step, animate ) {
96 if ( step < 1 || step > this.totalSteps ) return;
97
98 const prev = this.currentStep;
99 this.currentStep = step;
100
101 const $steps = $('.forumax-setup-step');
102 const $current = $steps.filter('[data-step="' + prev + '"]');
103 const $next = $steps.filter('[data-step="' + step + '"]');
104
105 if ( animate === false ) {
106 $steps.hide().removeClass('forumax-step-animating');
107 $next.show();
108 } else {
109 $current.animate({ opacity: 0 }, 120, function () {
110 $(this).hide().css({ opacity: '' });
111 $next.show().addClass('forumax-step-animating');
112
113 setTimeout(function() {
114 $next.removeClass('forumax-step-animating');
115 }, 350);
116 });
117 }
118
119 this.updateProgress( step );
120 this.updateNavigation( step );
121
122 // Persist active step so page refresh keeps the user on the same step.
123 localStorage.setItem( 'forumax_setup_current_step', step );
124
125 // Scroll card body back to top on step change
126 $('.forumax-setup-card-body').scrollTop(0);
127 },
128
129 /**
130 * Update numbered step circles.
131 *
132 * @param {number} step Active step number.
133 */
134 updateProgress: function ( step ) {
135 $('.forumax-progress-step').each(function () {
136 const n = parseInt( $(this).data('step'), 10 );
137 $(this).removeClass('active completed');
138 if ( n === step ) $(this).addClass('active');
139 else if ( n < step ) $(this).addClass('completed');
140 });
141 },
142
143 /**
144 * Show/hide navigation buttons based on current step.
145 *
146 * @param {number} step Active step number.
147 */
148 updateNavigation: function ( step ) {
149 const isFirst = step === 1;
150 const isLast = step === this.totalSteps;
151 const isSaveStep = step === this.totalSteps - 1;
152
153 // Hide Back button on first step AND last step (completion)
154 $('.forumax-btn-prev').toggle( !isFirst && !isLast );
155
156 // Next button hidden on last step
157 $('.forumax-btn-next').toggle( !isLast );
158
159 // Finish button only shown on last step
160 $('.forumax-btn-finish').toggle( isLast );
161
162 // Hide "Skip Setup" link on the last (completion) step
163 $('.forumax-btn-skip-wizard').toggle( !isLast );
164
165 // Only show the upgrade banner on the completion step, avoid distraction during setup
166 $('.forumax-upgrade-banner').toggle( isLast );
167
168 // Swap label & icon on the last settings step.
169 const $next = $('.forumax-btn-next');
170 if ( isSaveStep ) {
171 $next.html(
172 '<span class="dashicons dashicons-yes-alt"></span> ' +
173 ( forumaxWizard.saveFinish || 'Save & Finish' )
174 );
175 } else {
176 $next.html(
177 ( forumaxWizard.continue || 'Continue' ) +
178 ' <span class="dashicons dashicons-arrow-right-alt2"></span>'
179 );
180 }
181 },
182
183 /**
184 * Validate required fields on the current step panel.
185 *
186 * @param {number} step Step number to validate.
187 * @return {boolean} Whether all required fields pass.
188 */
189 validateStep: function ( step ) {
190 const $panel = $('.forumax-setup-step[data-step="' + step + '"]');
191 const $required = $panel.find('input[required], textarea[required]');
192 let valid = true;
193
194 $required.each(function () {
195 if ( ! $(this).val() ) {
196 valid = false;
197 $(this).addClass('forumax-field-error');
198 if ( ! $(this).next('.forumax-error-msg').length ) {
199 $('<p class="forumax-error-msg">' + ( forumaxWizard.fieldRequired || 'This field is required' ) + '</p>')
200 .insertAfter(this);
201 }
202 } else {
203 $(this).removeClass('forumax-field-error')
204 .next('.forumax-error-msg').remove();
205 }
206 });
207
208 return valid;
209 },
210
211 /**
212 * Restore previously saved field values from localStorage.
213 */
214 loadSavedData: function () {
215 $('.forumax-setup-form input, .forumax-setup-form textarea').each(function () {
216 const name = $(this).attr('name');
217 if ( ! name ) return;
218 const saved = localStorage.getItem( 'forumax_setup_' + name );
219 if ( saved === null ) return;
220
221 if ( $(this).is(':checkbox') ) {
222 $(this).prop('checked', saved === 'true');
223 } else if ( $(this).is(':radio') ) {
224 if ( $(this).val() === saved ) $(this).prop('checked', true);
225 } else {
226 $(this).val(saved);
227 }
228 });
229 },
230
231 /**
232 * Collect all wizard form values and POST them to the backend via AJAX.
233 * On success, advance to the final completion step.
234 */
235 saveSettings: function () {
236 const self = this;
237 const $btn = $('.forumax-btn-next');
238 const $notice = $('.forumax-save-error');
239
240 // Gather every named input in the wizard.
241 const data = { action: 'forumax_save_wizard_settings', nonce: forumaxWizard.nonce };
242
243 $('.forumax-setup-step').find('input, textarea, select').each(function () {
244 const name = $(this).attr('name');
245 if ( ! name ) return;
246 if ( $(this).is(':checkbox') ) data[ name ] = $(this).is(':checked') ? '1' : '0';
247 else if ( $(this).is(':radio') ) { if ( $(this).is(':checked') ) data[ name ] = $(this).val(); }
248 else data[ name ] = $(this).val();
249 });
250
251 // Show saving state.
252 $btn.prop('disabled', true)
253 .html('<span class="dashicons dashicons-update-alt" style="animation:spin 1s linear infinite"></span> ' + ( forumaxWizard.saving || 'Saving…' ) );
254
255 $notice.remove();
256
257 $.post( forumaxWizard.ajaxurl, data )
258 .done(function ( res ) {
259 if ( res.success ) {
260 // Clear all localStorage wizard data — DB is now the source of truth.
261 self.clearLocalStorage();
262 self.goToStep( self.totalSteps );
263 } else {
264 self.showSaveError( res.data && res.data.message ? res.data.message : ( forumaxWizard.saveError || 'Could not save settings. Please try again.' ) );
265 $btn.prop('disabled', false);
266 self.updateNavigation( self.currentStep );
267 }
268 })
269 .fail(function () {
270 self.showSaveError( forumaxWizard.saveError || 'Could not save settings. Please try again.' );
271 $btn.prop('disabled', false);
272 self.updateNavigation( self.currentStep );
273 });
274 },
275
276 /**
277 * Display a save-error notice below the navigation footer.
278 *
279 * @param {string} message Error text to show.
280 */
281 showSaveError: function ( message ) {
282 $('.forumax-setup-card-footer').after(
283 '<p class="forumax-save-error" style="color:#ef4444;font-size:13px;text-align:right;margin:4px 48px 0;">' +
284 message + '</p>'
285 );
286 },
287 /**
288 * Clear all forumax_setup_* keys from localStorage.
289 * Called after a successful AJAX save so stale data cannot overwrite DB values.
290 */
291 clearLocalStorage: function () {
292 for ( let i = localStorage.length - 1; i >= 0; i-- ) {
293 const key = localStorage.key(i);
294 if ( key && key.startsWith('forumax_setup_') ) {
295 localStorage.removeItem(key);
296 }
297 }
298 },
299 };
300
301 $(document).ready(function () {
302
303 if ( $('.forumax-setup-card').length ) {
304 Wizard.init();
305 }
306 });
307
308 // Clear ALL saved wizard data (step + field values) when the wizard is finished.
309 $(document).on('click', '.forumax-btn-finish', function () {
310 Wizard.clearLocalStorage();
311 });
312
313 })(jQuery);
314