PageSourceSearch

https://www.customboxesinc.com/theme/website/assets/js/form-validation.js

js customboxesinc.com collected 2026-09-26 06:31:35 UTC 5,282 bytes, 151 lines download raw bytes

1(function () {
2	'use strict';
3
4	function unwrap(wrapper) {
5		const parent = wrapper.parentNode;
6		while (wrapper.firstChild) {
7			parent.insertBefore(wrapper.firstChild, wrapper);
8		}
9		parent.removeChild(wrapper);
10	}
11
12	window.addEventListener('load', function () {
13		const forms = document.querySelectorAll('form');
14		forms.forEach(function (form) {
15			form.classList.add('formfields');
16			form.setAttribute('novalidate', true);
17
18			const fields = form.querySelectorAll('input[required], select[required], textarea[required]');
19			fields.forEach(field => {
20				const eventType = ['radio', 'checkbox', 'select-one'].includes(field.type) ? 'change' : 'input';
21
22				field.addEventListener(eventType, () => {
23					if (field.checkValidity() && field.value.trim() !== '') {
24						field.style.outline = '';
25						field.style.removeProperty('appearance');
26						field.style.removeProperty('width');
27						field.style.removeProperty('height');
28						field.style.removeProperty('border-radius');
29
30						const label = form.querySelector(`label[for="${field.id}"]`);
31						if (label) label.style.color = '';
32
33						const parentValidator = field.closest('.parent-validator');
34						if (parentValidator) {
35							const tooltip = parentValidator.querySelector('.invalid-tooltip');
36							if (tooltip) tooltip.remove();
37							unwrap(parentValidator);
38						}
39
40						if (field.type === 'radio') {
41							const tooltip = form.querySelector(`.radio-tooltip[data-group="${field.name}"]`);
42							if (tooltip) tooltip.remove();
43
44							const groupRadios = form.querySelectorAll(`input[type="radio"][name="${field.name}"][required]`);
45							groupRadios.forEach(r => {
46								r.style.outline = '';
47								r.style.removeProperty('appearance');
48								r.style.removeProperty('width');
49								r.style.removeProperty('height');
50								r.style.removeProperty('border-radius');
51
52								const rLabel = form.querySelector(`label[for="${r.id}"]`);
53								if (rLabel) rLabel.style.color = '';
54							});
55						}
56					}
57				});
58			});
59		});
60
61		const validatedForms = document.getElementsByClassName('formfields');
62		Array.prototype.forEach.call(validatedForms, function (form) {
63			form.addEventListener('submit', function (event) {
64				const existingTooltips = form.querySelectorAll('.invalid-tooltip');
65				existingTooltips.forEach(el => {
66					const parentValidator = el.closest('.parent-validator');
67					if (parentValidator) {
68						const field = parentValidator.querySelector('input, select, textarea');
69						if (field) {
70							parentValidator.parentNode.insertBefore(field, parentValidator);
71						}
72						parentValidator.remove();
73					} else {
74						el.remove();
75					}
76				});
77
78				const fields = Array.from(form.querySelectorAll('input[required], select[required], textarea[required]'));
79				let hasError = false;
80
81				for (let field of fields) {
82					field.style.outline = '';
83					field.style.removeProperty('appearance');
84					field.style.removeProperty('width');
85					field.style.removeProperty('height');
86					field.style.removeProperty('border-radius');
87
88					const label = form.querySelector(`label[for="${field.id}"]`);
89					if (label) label.style.color = '';
90
91					if (!field.checkValidity() || field.value.trim() === '') {
92						event.preventDefault();
93						event.stopPropagation();
94						hasError = true;
95
96						if (field.type === 'checkbox' || field.type === 'radio') {
97							field.style.appearance = 'none';
98							field.style.outline = '2px solid red';
99							field.style.width = '12px';
100							field.style.height = '12px';
101
102							if (field.type === 'radio') {
103								field.style.borderRadius = '50%';
104								const groupName = field.name;
105								const alreadyHasMessage = form.querySelector(`.radio-tooltip[data-group="${groupName}"]`);
106								if (!alreadyHasMessage) {
107									const message = document.createElement('div');
108									message.className = 'invalid-tooltip radio-tooltip';
109									message.setAttribute('data-group', groupName);
110									message.textContent = 'Please select an option';
111									const lastRadio = form.querySelector(`input[type="radio"][name="${groupName}"][required]:last-of-type`);
112									if (lastRadio && lastRadio.parentNode) {
113										lastRadio.parentNode.insertBefore(message, lastRadio.nextSibling);
114									}
115								}
116							}
117							if (label) {
118								label.style.color = 'red';
119							}
120						} else {
121							field.style.outline = '2px solid red';
122							if (!field.nextElementSibling || !field.nextElementSibling.classList.contains('invalid-tooltip')) {
123								const tooltip = document.createElement('div');
124								tooltip.className = 'invalid-tooltip';
125								tooltip.textContent = field.validationMessage || 'This field is required';
126
127								const wrapper = document.createElement('div');
128								wrapper.className = 'parent-validator';
129								field.parentNode.insertBefore(wrapper, field);
130								wrapper.appendChild(field);
131								wrapper.appendChild(tooltip);
132							}
133							if (label) {
134								label.style.color = 'red';
135							}
136						}
137
138						field.scrollIntoView({ behavior: 'smooth', block: 'center' });
139						field.focus();
140						break;
141					}
142				}
143
144				if (!hasError) {
145					form.classList.remove('was-validated');
146				}
147				form.classList.add('was-validated');
148			}, false);
149		});
150	}, false);
151})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.