Newer
Older
tonitalia-pluginsoci / assets / js / form.js
(function () {
	'use strict';

	function initTonRegForm() {
		if (window.tonRegFormBootstrapped) {
			return;
		}

		var form = document.querySelector('.ton-reg-form__body');
		if (!form || form.getAttribute('data-ton-reg-js-init') === '1') {
			return;
		}

		form.setAttribute('data-ton-reg-js-init', '1');
		window.tonRegFormBootstrapped = true;

		var messages =
			typeof tonRegForm !== 'undefined'
				? tonRegForm
				: {
						msgRequired: 'Compila questo campo.',
						msgEmail: 'Inserisci un indirizzo email valido.',
						msgCf: 'Codice fiscale non valido (16 caratteri).',
						msgCap: 'Il CAP deve essere di 5 cifre.',
						msgProvincia: 'Inserisci la sigla provincia (2 lettere).',
						msgDate: 'Inserisci la data nel formato gg-mm-aaaa.',
						msgDateFuture: 'La data di dichiarazione non può essere futura.',
						msgCheckbox: 'Devi selezionare questa casella per continuare.',
						msgCaptcha: 'Inserisci la risposta alla verifica anti-spam.',
					};

		var cfRegex = /^[A-Z]{6}[0-9]{2}[A-Z][0-9]{2}[A-Z][0-9]{3}[A-Z]$/;
		var dateRegex = /^[0-9]{2}-[0-9]{2}-[0-9]{4}$/;
		var dateFieldNames = {
			data_nascita: true,
			data_dichiarazione: true,
		};

		function isDateField(name) {
			return !!dateFieldNames[name];
		}

		function isDateInput(input) {
			return input && input.name && isDateField(input.name);
		}

		function padDatePart(part) {
			var num = parseInt(part, 10);
			if (part.length === 1 && num >= 1 && num <= 9) {
				return '0' + part;
			}
			return part;
		}

		function normalizeItalianDate(value) {
			var trimmed = (value || '').trim();
			if (!trimmed) {
				return '';
			}

			var normalized = trimmed
				.replace(/[./]/g, '-')
				.replace(/\s+/g, '-')
				.replace(/-+/g, '-');
			var match = normalized.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/);
			if (!match) {
				return normalized;
			}

			return padDatePart(match[1]) + '-' + padDatePart(match[2]) + '-' + match[3];
		}

		function applyDateNormalization(input) {
			if (!isDateInput(input)) {
				return;
			}

			var previous = input.value;
			var normalized = normalizeItalianDate(previous);
			input.value = normalized;

			if (normalized !== previous) {
				input.dispatchEvent(new Event('change', { bubbles: true }));
			}
		}

		function normalizeProvince(value) {
			return (value || '').trim().toUpperCase();
		}

		function normalizeCodiceFiscale(value) {
			return (value || '').trim().toUpperCase().replace(/\s+/g, '');
		}

		function parseItalianDate(value) {
			if (!dateRegex.test(value)) {
				return null;
			}
			var parts = value.split('-');
			return new Date(parseInt(parts[2], 10), parseInt(parts[1], 10) - 1, parseInt(parts[0], 10));
		}

		function isFutureDate(value) {
			var date = parseItalianDate(value);
			if (!date) {
				return false;
			}
			var today = new Date();
			today.setHours(0, 0, 0, 0);
			date.setHours(0, 0, 0, 0);
			return date > today;
		}

		function showFieldError(fieldWrap, message) {
			var input = fieldWrap.querySelector('.ton-reg-form__input');
			var error = fieldWrap.querySelector('.ton-reg-form__error');
			if (!input || !error) {
				return;
			}
			fieldWrap.classList.add('ton-reg-form__field--invalid');
			error.textContent = message;
			error.hidden = false;
			input.setCustomValidity(message);
		}

		function clearFieldError(fieldWrap) {
			var input = fieldWrap.querySelector('.ton-reg-form__input');
			var error = fieldWrap.querySelector('.ton-reg-form__error');
			if (!input || !error) {
				return;
			}
			fieldWrap.classList.remove('ton-reg-form__field--invalid');
			error.hidden = true;
			error.textContent = '';
			input.setCustomValidity('');
		}

		function clearAllErrors() {
			form.querySelectorAll('.ton-reg-form__field').forEach(clearFieldError);
			form.querySelectorAll('.ton-reg-form__checkbox--invalid').forEach(function (el) {
				el.classList.remove('ton-reg-form__checkbox--invalid');
			});
		}

		function getFieldWrap(name) {
			return form.querySelector('.ton-reg-form__field[data-field="' + name + '"]');
		}

		function validateField(name) {
			var wrap = getFieldWrap(name);
			if (!wrap) {
				return true;
			}
			var input = wrap.querySelector('.ton-reg-form__input');
			if (!input) {
				return true;
			}

			var value = (input.value || '').trim();

			if (isDateField(name)) {
				value = normalizeItalianDate(value);
				input.value = value;
			}

			if ('provincia_nascita' === name || 'provincia_residenza' === name) {
				value = normalizeProvince(value);
				input.value = value;
			}

			if ('codice_fiscale' === name) {
				value = normalizeCodiceFiscale(value);
				input.value = value;
			}

			if (input.required && !value) {
				showFieldError(wrap, messages.msgRequired);
				return false;
			}

			if (!value) {
				clearFieldError(wrap);
				return true;
			}

			if ('email' === input.type && !input.checkValidity()) {
				showFieldError(wrap, messages.msgEmail);
				return false;
			}

			if ('codice_fiscale' === name) {
				if (!cfRegex.test(value)) {
					showFieldError(wrap, messages.msgCf);
					return false;
				}
			}

			if ('cap' === name && !/^[0-9]{5}$/.test(value)) {
				showFieldError(wrap, messages.msgCap);
				return false;
			}

			if (('provincia_nascita' === name || 'provincia_residenza' === name) && !/^[A-Za-z]{2}$/.test(value)) {
				showFieldError(wrap, messages.msgProvincia);
				return false;
			}

			if (isDateField(name) && !dateRegex.test(value)) {
				showFieldError(wrap, messages.msgDate);
				return false;
			}

			if ('data_dichiarazione' === name && dateRegex.test(value) && isFutureDate(value)) {
				showFieldError(wrap, messages.msgDateFuture);
				return false;
			}

			if (input.pattern && !isDateField(name) && !new RegExp('^(?:' + input.pattern + ')$').test(value)) {
				showFieldError(wrap, messages.msgRequired);
				return false;
			}

			clearFieldError(wrap);
			return true;
		}

		function validateCheckboxes() {
			var ok = true;
			form.querySelectorAll('input[type="checkbox"][required]').forEach(function (cb) {
				var label = cb.closest('.ton-reg-form__checkbox');
				if (!cb.checked) {
					if (label) {
						label.classList.add('ton-reg-form__checkbox--invalid');
					}
					ok = false;
				} else if (label) {
					label.classList.remove('ton-reg-form__checkbox--invalid');
				}
			});
			return ok;
		}

		function validateCaptcha() {
			var captcha = form.querySelector('#ton_reg_captcha_answer');
			if (!captcha) {
				return true;
			}
			if (!captcha.value && captcha.required) {
				captcha.setCustomValidity(messages.msgCaptcha);
				return false;
			}
			captcha.setCustomValidity('');
			return true;
		}

		function handleInputNormalization(input) {
			var wrap = input.closest('.ton-reg-form__field');
			if (wrap) {
				clearFieldError(wrap);
			}

			if ('codice_fiscale' === input.name && input.value) {
				input.value = normalizeCodiceFiscale(input.value);
			}

			if (isDateInput(input) && input.value) {
				input.value = input.value.replace(/[./]/g, '-');
			}

			if (('provincia_nascita' === input.name || 'provincia_residenza' === input.name) && input.value) {
				input.value = normalizeProvince(input.value);
			}
		}

		function handleFieldNormalization(input) {
			if (!input || !input.name) {
				return;
			}

			if (isDateInput(input)) {
				applyDateNormalization(input);
			}

			if ('provincia_nascita' === input.name || 'provincia_residenza' === input.name) {
				input.value = normalizeProvince(input.value);
			}

			if ('codice_fiscale' === input.name) {
				input.value = normalizeCodiceFiscale(input.value);
			}

			validateField(input.name);
		}

		form.addEventListener('input', function (e) {
			if (e.target && e.target.classList && e.target.classList.contains('ton-reg-form__input')) {
				handleInputNormalization(e.target);
			}
		});

		form.addEventListener(
			'focusout',
			function (e) {
				if (e.target && e.target.classList && e.target.classList.contains('ton-reg-form__input')) {
					handleFieldNormalization(e.target);
				}
			},
			true
		);

		function updateMinorBirthWarning() {
			var birthInput = form.querySelector('#ton_reg_data_nascita');
			if (!birthInput) {
				return;
			}

			var warning = form.querySelector('.ton-reg-form__warning');
			if (warning) {
				warning.remove();
			}

			var date = normalizeItalianDate(birthInput.value);
			if (!date || !dateRegex.test(date)) {
				return;
			}

			var parts = date.split('-');
			var birth = new Date(parseInt(parts[2], 10), parseInt(parts[1], 10) - 1, parseInt(parts[0], 10));
			var today = new Date();
			var age = today.getFullYear() - birth.getFullYear();
			var m = today.getMonth() - birth.getMonth();
			if (m < 0 || (m === 0 && today.getDate() < birth.getDate())) {
				age -= 1;
			}
			if (age < 18) {
				var div = document.createElement('div');
				div.className = 'ton-reg-form__warning';
				div.setAttribute('role', 'alert');
				div.textContent =
					'Se sei minorenne, la domanda deve essere firmata da entrambi i genitori o dal tutore legale.';
				form.insertBefore(div, form.firstChild);
			}
		}

		var birthInput = form.querySelector('#ton_reg_data_nascita');
		if (birthInput) {
			birthInput.addEventListener('change', updateMinorBirthWarning);
		}

		form.addEventListener('submit', function (e) {
			clearAllErrors();

			var fields = [
				'cognome',
				'nome',
				'luogo_nascita',
				'provincia_nascita',
				'data_nascita',
				'codice_fiscale',
				'comune_residenza',
				'provincia_residenza',
				'indirizzo',
				'numero_civico',
				'cap',
				'telefono',
				'email',
				'luogo_dichiarazione',
				'data_dichiarazione',
			];

			var valid = true;
			fields.forEach(function (name) {
				if (!validateField(name)) {
					valid = false;
				}
			});

			if (!validateCheckboxes()) {
				valid = false;
			}

			if (!validateCaptcha()) {
				valid = false;
			}

			if (!valid) {
				e.preventDefault();
				var firstInvalid = form.querySelector(
					'.ton-reg-form__field--invalid .ton-reg-form__input, .ton-reg-form__checkbox--invalid input, :invalid'
				);
				if (firstInvalid && firstInvalid.focus) {
					firstInvalid.focus();
				}
				return;
			}

			if (!form.checkValidity()) {
				e.preventDefault();
				form.reportValidity();
			}
		});
	}

	window.tonRegFormInit = initTonRegForm;

	if (/[?&]ton_reg=success(?:&|$)/.test(window.location.search)) {
		var successEl = document.getElementById('ton-reg-success');
		if (successEl) {
			successEl.scrollIntoView({ behavior: 'smooth', block: 'start' });
		}
	}

	if (document.readyState === 'loading') {
		document.addEventListener('DOMContentLoaded', initTonRegForm);
	} else {
		initTonRegForm();
	}
})();