(function() { 'use strict'; // Handle browser back/forward: reload the step content via HTMX window.addEventListener('popstate', function() { var stepArea = document.getElementById('wizard-step'); if (!stepArea) return; // Let HTMX handle the URL change by fetching the current URL's step content var path = window.location.pathname; if (path.indexOf('/step/') !== -1) { htmx.ajax('GET', path, { target: '#wizard-step', swap: 'innerHTML' }); } }); // After HTMX swaps, re-attach the OOB sidebar update document.addEventListener('htmx:afterSwap', function(event) { // The step_nav.html is included at the top of each partial, // so the sidebar nav gets updated via include (not OOB). // We need to move the nav from inside #wizard-step to the sidebar. var wizardStep = document.getElementById('wizard-step'); if (!wizardStep) return; var inlineNav = wizardStep.querySelector('#wizard-nav'); if (!inlineNav) return; var sidebar = document.querySelector('.wizard-sidebar'); if (!sidebar) return; var existingNav = sidebar.querySelector('#wizard-nav'); if (existingNav) { existingNav.replaceWith(inlineNav); } else { sidebar.appendChild(inlineNav); } }); // Custom HTML5 validation messages for wizard forms. // Replaces browser defaults ("Please fill out this field") with // field-specific messages using data-* attributes or fallback rules. function applyCustomValidation(root) { var inputs = root.querySelectorAll('input[required], input[minlength], input[pattern], textarea[minlength]'); inputs.forEach(function(input) { input.addEventListener('invalid', function(e) { var v = e.target.validity; var label = (e.target.closest('.form-group')?.querySelector('label')?.textContent || '').trim(); var custom = e.target.dataset.validationMessage; if (custom) { e.target.setCustomValidity(custom); } else if (v.valueMissing) { e.target.setCustomValidity(label ? label + ' is required' : 'This field is required'); } else if (v.tooShort) { var min = e.target.getAttribute('minlength'); e.target.setCustomValidity('Must be at least ' + min + ' characters'); } else if (v.tooLong) { var max = e.target.getAttribute('maxlength'); e.target.setCustomValidity('Must be ' + max + ' characters or fewer'); } else if (v.patternMismatch) { e.target.setCustomValidity(e.target.title || 'Please use the expected format'); } else if (v.typeMismatch) { e.target.setCustomValidity('Please enter a valid ' + (e.target.type || 'value')); } else { e.target.setCustomValidity(''); } }); // Clear custom message on input so re-validation works input.addEventListener('input', function() { this.setCustomValidity(''); }); }); } // Apply to initial page content applyCustomValidation(document.body); // Re-apply after HTMX swaps new wizard steps in document.addEventListener('htmx:afterSwap', function(event) { applyCustomValidation(event.detail.target); }); })();