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.