document.addEventListener('DOMContentLoaded', (event) => { const form = document.querySelector('form'); const formElements = form.elements; setUpNavigation() }); function nextQuestion() { document.currentQuestion++; hideNavElementsAndQuestions(); showQuestion(`q${document.currentQuestion}`); setButtonVisiblity('back', true); setButtonVisiblity('next', true); if (document.currentQuestion === document.lastQuestion) { setButtonVisiblity('next', false); setButtonVisiblity('submit', true); } setNextButtonAvailability(); } function previousQuestion() { if (document.currentQuestion > 0) { document.currentQuestion--; hideNavElementsAndQuestions(); showQuestion(`q${document.currentQuestion}`); setButtonVisiblity('next', true); setButtonVisiblity('submit', false); document.nextEnabled = true; } setButtonVisiblity('back', document.currentQuestion !== 0); setNextButtonAvailability(); } function setUpNavigation() { const questions = document.querySelectorAll('.question'); document.currentQuestion = 0; document.nextEnabled = false; document.lastQuestion = questions.length - 1; hideNavElementsAndQuestions(); showQuestion(`q${document.currentQuestion}`); setButtonVisiblity('next', true); const nextButton = document.getElementById('next'); const backButton = document.getElementById('back'); nextButton.addEventListener('click', nextQuestion); backButton.addEventListener('click', previousQuestion); setNextButtonAvailability(); // check if next button should be enabled on every input, checkbox and radio button bellow class of .question change const inputs = document.querySelectorAll('.question input, .question select, .question textarea'); inputs.forEach(input => { input.addEventListener('change',()=> setNextButtonAvailability()); input.addEventListener('blur', () => setNextButtonAvailability()); }); } async function setNextButtonAvailability() { // check if current question is answered // and then enable the next button, disable it otherwise const currentQuestion = document.getElementById(`q${document.currentQuestion}`); const nextButton = document.getElementById('next'); const submitButton = document.getElementById('submit'); // check if any input in the current question is checked, or filled in case it is a text input let nextEnabled = false; if (document.currentQuestion === 0) { const name = document.getElementById('name'); const email = document.getElementById('email'); const errorDiv = document.getElementById('org-email-error'); if (name && email && name.value.trim() && email.value.trim()) { nextEnabled = await validateFormFields(nextButton, errorDiv); }else{ nextButton.disabled = true; if (errorDiv) errorDiv.textContent = ''; return } } else { const inputs = currentQuestion.querySelectorAll('input, select, textarea'); for (let input of inputs) { if (input.checkVisibility() === false){ continue; } if (input.type === 'checkbox' || input.type === 'radio') { if (input.checked) { nextEnabled = true; break; } } else { if (input.value) { nextEnabled = true; break; } } } } nextButton.disabled = !nextEnabled; submitButton.disabled = !nextEnabled; } function saveFormState(elements) { const formState = {}; for (let element of elements) { if (element.name) { if (element.type === 'select-multiple') { formState[element.name] = Array.from(element.selectedOptions).map(option => option.value); } else if (element.type === 'checkbox' || element.type === 'radio') { formState[element.name] = element.checked ? element.value : formState[element.name] || null; } else { formState[element.name] = element.value; } } } localStorage.setItem('formState', JSON.stringify(formState)); } function loadFormState(elements) { const formState = JSON.parse(localStorage.getItem('formState')); if (formState) { for (let element of elements) { if (element.name && formState[element.name] !== undefined) { if (element.type === 'select-multiple') { Array.from(element.options).forEach(option => { option.selected = formState[element.name].includes(option.value); }); } else if (element.type === 'checkbox' || element.type === 'radio') { element.checked = formState[element.name] === element.value; } else { element.value = formState[element.name]; } } } } } function hideNavElementsAndQuestions() { const questions = document.querySelectorAll('.question'); questions.forEach(question => { // add bootstrap hidden class to the element question.classList.add('d-none'); }); const nextButton = document.getElementById('next'); const backButton = document.getElementById('back'); const submitButton = document.getElementById('submit'); nextButton.classList.add('d-none'); backButton.classList.add('d-none'); submitButton.classList.add('d-none'); } function showQuestion(questionId) { const question = document.getElementById(questionId); question.classList.remove('d-none'); progressBar(); } function setButtonVisiblity(buttonId, visible) { const button = document.getElementById(buttonId); if (visible) { button.classList.remove('d-none'); } else { button.classList.add('d-none'); } } async function validateFormFields(nextBtn, errorDiv) { const nameInput = document.getElementById('name'); const emailInput = document.getElementById('email'); const name = nameInput.value.trim(); const email = emailInput.value.trim(); const resp = await fetch(`/api/validate_form_fields/?name=${name}&email=${email}`); const data = await resp.json(); if (data.errors && (data.errors.name || data.errors.email)) { errorDiv.textContent = (data.errors.name || '') + ' ' + (data.errors.email || ''); nextBtn.disabled = true; return false; } else { errorDiv.textContent = ''; nextBtn.disabled = false; return true; } } function progressBar() { const basic = Array.from(document.querySelectorAll('.basic-section')); const advanced = Array.from(document.querySelectorAll('.advanced-section')); const basicProgress = document.getElementById('basic-progress'); const advancedProgress = document.getElementById('advanced-progress'); const basicBar = document.getElementById('basic-progress-bar'); const advancedBar = document.getElementById('advanced-progress-bar'); const basicBarWrap = document.getElementById('basic-progress-bar-wrap'); const advancedBarWrap = document.getElementById('advanced-progress-bar-wrap'); let currentId = `q${document.currentQuestion}`; let idxBasic = basic.findIndex(q => q.id === currentId); let idxAdvanced = advanced.findIndex(q => q.id === currentId); if (idxBasic !== -1) { basicProgress.classList.remove('d-none'); basicBarWrap.classList.remove('d-none'); advancedProgress.classList.add('d-none'); advancedBarWrap.classList.add('d-none'); if (idxBasic === basic.length) { basicProgress.innerHTML = `Basic question ✓`; basicBarWrap.classList.add('d-none'); } else { basicProgress.innerText = `Question ${idxBasic + 1} / ${basic.length}`; } let percent = ((idxBasic + 1) / basic.length) * 100; basicBar.style.width = percent + "%"; basicBar.setAttribute('aria-valuenow', percent); } else if (idxAdvanced !== -1) { advancedProgress.classList.remove('d-none'); advancedBarWrap.classList.remove('d-none'); basicBarWrap.classList.add('d-none'); advancedProgress.innerText = `Advanced Question ${idxAdvanced + 1} / ${advanced.length}`; let percent = ((idxAdvanced + 1) / advanced.length) * 100; advancedBar.style.width = percent + "%"; advancedBar.setAttribute('aria-valuenow', percent); } else { basicProgress.classList.add('d-none'); advancedProgress.classList.add('d-none'); basicBarWrap.classList.add('d-none'); advancedBarWrap.classList.add('d-none'); } }