/** * Forumax Setup Wizard JavaScript * * Single-page multi-step wizard — no page reloads. * Updated to work with the Jobus-inspired redesign. * * @package Forumax * @since 2.2.0 */ (function ($) { 'use strict'; const Wizard = { currentStep: 1, totalSteps: 0, init: function () { this.totalSteps = parseInt( $('.forumax-setup-card').data('total-steps'), 10 ) || 5; this.bindEvents(); // Restore the last active step from localStorage (defaults to 1). const savedStep = parseInt( localStorage.getItem( 'forumax_setup_current_step' ), 10 ) || 1; const startStep = ( savedStep >= 1 && savedStep <= this.totalSteps ) ? savedStep : 1; this.goToStep( startStep, false ); }, bindEvents: function () { const self = this; // Next / Continue — intercepts the save step to fire AJAX first. $(document).on( 'click', '.forumax-btn-next', function () { if ( ! self.validateStep( self.currentStep ) ) return; const isSaveStep = ( self.currentStep === self.totalSteps - 1 ); if ( isSaveStep ) { self.saveSettings(); } else { self.goToStep( self.currentStep + 1 ); } }); // Previous $(document).on( 'click', '.forumax-btn-prev', function () { self.goToStep( self.currentStep - 1 ); }); // Step indicator — click any step to jump directly to it. $(document).on( 'click', '.forumax-progress-step', function () { const target = parseInt( $(this).data('step'), 10 ); if ( target && target !== self.currentStep ) { self.goToStep( target ); } }); // Radio card / layout option selection $(document).on( 'click', '.forumax-option-card, .forumax-layout-option', function () { $(this).find('input[type="radio"]').prop('checked', true).trigger('change'); }); // Toggle row: sync toggle switch appearance when clicking the row $(document).on( 'change', '.forumax-toggle-row input[type="checkbox"]', function () { // Visual state handled entirely via CSS :checked sibling selector. }); // Brand color picker ↔ hex input sync. $(document).on( 'input', '#brand_color', function () { $('#brand_color_hex').val( $(this).val() ); }); $(document).on( 'input change', '#brand_color_hex', function () { const hex = $(this).val(); if ( /^#[0-9A-Fa-f]{6}$/.test( hex ) ) { $('#brand_color').val( hex ); } }); // Auto-save form fields to localStorage $(document).on( 'change blur', '.forumax-setup-form input, .forumax-setup-form textarea', function () { const name = $(this).attr('name'); if ( ! name ) return; const val = $(this).is(':checkbox') ? $(this).is(':checked') : $(this).val(); localStorage.setItem( 'forumax_setup_' + name, val ); }); this.loadSavedData(); }, /** * Transition to a specific step. * * @param {number} step Target step number. * @param {boolean} animate Whether to animate the transition. */ goToStep: function ( step, animate ) { if ( step < 1 || step > this.totalSteps ) return; const prev = this.currentStep; this.currentStep = step; const $steps = $('.forumax-setup-step'); const $current = $steps.filter('[data-step="' + prev + '"]'); const $next = $steps.filter('[data-step="' + step + '"]'); if ( animate === false ) { $steps.hide().removeClass('forumax-step-animating'); $next.show(); } else { $current.animate({ opacity: 0 }, 120, function () { $(this).hide().css({ opacity: '' }); $next.show().addClass('forumax-step-animating'); setTimeout(function() { $next.removeClass('forumax-step-animating'); }, 350); }); } this.updateProgress( step ); this.updateNavigation( step ); // Persist active step so page refresh keeps the user on the same step. localStorage.setItem( 'forumax_setup_current_step', step ); // Scroll card body back to top on step change $('.forumax-setup-card-body').scrollTop(0); }, /** * Update numbered step circles. * * @param {number} step Active step number. */ updateProgress: function ( step ) { $('.forumax-progress-step').each(function () { const n = parseInt( $(this).data('step'), 10 ); $(this).removeClass('active completed'); if ( n === step ) $(this).addClass('active'); else if ( n < step ) $(this).addClass('completed'); }); }, /** * Show/hide navigation buttons based on current step. * * @param {number} step Active step number. */ updateNavigation: function ( step ) { const isFirst = step === 1; const isLast = step === this.totalSteps; const isSaveStep = step === this.totalSteps - 1; // Hide Back button on first step AND last step (completion) $('.forumax-btn-prev').toggle( !isFirst && !isLast ); // Next button hidden on last step $('.forumax-btn-next').toggle( !isLast ); // Finish button only shown on last step $('.forumax-btn-finish').toggle( isLast ); // Hide "Skip Setup" link on the last (completion) step $('.forumax-btn-skip-wizard').toggle( !isLast ); // Only show the upgrade banner on the completion step, avoid distraction during setup $('.forumax-upgrade-banner').toggle( isLast ); // Swap label & icon on the last settings step. const $next = $('.forumax-btn-next'); if ( isSaveStep ) { $next.html( ' ' + ( forumaxWizard.saveFinish || 'Save & Finish' ) ); } else { $next.html( ( forumaxWizard.continue || 'Continue' ) + ' ' ); } }, /** * Validate required fields on the current step panel. * * @param {number} step Step number to validate. * @return {boolean} Whether all required fields pass. */ validateStep: function ( step ) { const $panel = $('.forumax-setup-step[data-step="' + step + '"]'); const $required = $panel.find('input[required], textarea[required]'); let valid = true; $required.each(function () { if ( ! $(this).val() ) { valid = false; $(this).addClass('forumax-field-error'); if ( ! $(this).next('.forumax-error-msg').length ) { $('

' + ( forumaxWizard.fieldRequired || 'This field is required' ) + '

') .insertAfter(this); } } else { $(this).removeClass('forumax-field-error') .next('.forumax-error-msg').remove(); } }); return valid; }, /** * Restore previously saved field values from localStorage. */ loadSavedData: function () { $('.forumax-setup-form input, .forumax-setup-form textarea').each(function () { const name = $(this).attr('name'); if ( ! name ) return; const saved = localStorage.getItem( 'forumax_setup_' + name ); if ( saved === null ) return; if ( $(this).is(':checkbox') ) { $(this).prop('checked', saved === 'true'); } else if ( $(this).is(':radio') ) { if ( $(this).val() === saved ) $(this).prop('checked', true); } else { $(this).val(saved); } }); }, /** * Collect all wizard form values and POST them to the backend via AJAX. * On success, advance to the final completion step. */ saveSettings: function () { const self = this; const $btn = $('.forumax-btn-next'); const $notice = $('.forumax-save-error'); // Gather every named input in the wizard. const data = { action: 'forumax_save_wizard_settings', nonce: forumaxWizard.nonce }; $('.forumax-setup-step').find('input, textarea, select').each(function () { const name = $(this).attr('name'); if ( ! name ) return; if ( $(this).is(':checkbox') ) data[ name ] = $(this).is(':checked') ? '1' : '0'; else if ( $(this).is(':radio') ) { if ( $(this).is(':checked') ) data[ name ] = $(this).val(); } else data[ name ] = $(this).val(); }); // Show saving state. $btn.prop('disabled', true) .html(' ' + ( forumaxWizard.saving || 'Saving…' ) ); $notice.remove(); $.post( forumaxWizard.ajaxurl, data ) .done(function ( res ) { if ( res.success ) { // Clear all localStorage wizard data — DB is now the source of truth. self.clearLocalStorage(); self.goToStep( self.totalSteps ); } else { self.showSaveError( res.data && res.data.message ? res.data.message : ( forumaxWizard.saveError || 'Could not save settings. Please try again.' ) ); $btn.prop('disabled', false); self.updateNavigation( self.currentStep ); } }) .fail(function () { self.showSaveError( forumaxWizard.saveError || 'Could not save settings. Please try again.' ); $btn.prop('disabled', false); self.updateNavigation( self.currentStep ); }); }, /** * Display a save-error notice below the navigation footer. * * @param {string} message Error text to show. */ showSaveError: function ( message ) { $('.forumax-setup-card-footer').after( '

' + message + '

' ); }, /** * Clear all forumax_setup_* keys from localStorage. * Called after a successful AJAX save so stale data cannot overwrite DB values. */ clearLocalStorage: function () { for ( let i = localStorage.length - 1; i >= 0; i-- ) { const key = localStorage.key(i); if ( key && key.startsWith('forumax_setup_') ) { localStorage.removeItem(key); } } }, }; $(document).ready(function () { if ( $('.forumax-setup-card').length ) { Wizard.init(); } }); // Clear ALL saved wizard data (step + field values) when the wizard is finished. $(document).on('click', '.forumax-btn-finish', function () { Wizard.clearLocalStorage(); }); })(jQuery);