1(function () { 2 'use strict'; 3 4 const config = window.PMSBookingUi || {}; 5 const siteNames = Array.isArray(config.siteNames) ? config.siteNames.filter(Boolean) : []; 6 const screeningClass = 'pms-screening-booking'; 7 8 function isScreeningContainer(container) { 9 if (!container) return false; 10 if (container.classList.contains(screeningClass)) return true; 11 12 const text = container.textContent || ''; 13 return siteNames.some(function (name) { 14 return text.indexOf(name) !== -1; 15 }); 16 } 17 18 function markScreeningContainers() { 19 document.querySelectorAll('.amelia-v2-booking').forEach(function (container) { 20 if (isScreeningContainer(container)) { 21 container.classList.add(screeningClass); 22 } 23 }); 24 } 25 26 function replaceExactText(root, from, to) { 27 if (!root || !from || !to) return; 28 29 const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT); 30 let node; 31 32 while ((node = walker.nextNode())) { 33 if (node.nodeValue && node.nodeValue.trim() === from) { 34 node.nodeValue = node.nodeValue.replace(from, to); 35 } 36 } 37 } 38 39 function setNativeValue(input, value) { 40 const descriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value'); 41 if (!descriptor || !descriptor.set) { 42 input.value = value; 43 return; 44 } 45 46 descriptor.set.call(input, value); 47 input.dispatchEvent(new Event('input', { bubbles: true })); 48 } 49 50 function formatDOB(value) { 51 const digits = String(value || '').replace(/\D/g, '').slice(0, 8); 52 53 if (digits.length <= 2) return digits; 54 if (digits.length <= 4) return digits.slice(0, 2) + '/' + digits.slice(2); 55 56 return digits.slice(0, 2) + '/' + digits.slice(2, 4) + '/' + digits.slice(4); 57 } 58 59 function validateDOB(input) { 60 const value = input.value.trim(); 61 if (!value) return; 62 63 const formatted = formatDOB(value); 64 if (formatted !== value) { 65 setNativeValue(input, formatted); 66 } 67 68 const match = formatted.match(/^(\d{2})\/(\d{2})\/(\d{4})$/); 69 if (!match) { 70 input.setCustomValidity(config.dobFormatMessage || 'Please enter your date of birth as DD/MM/YYYY.'); 71 input.reportValidity(); 72 return; 73 } 74 75 const day = parseInt(match[1], 10);
76 const month = parseInt(match[2], 10); 77 const year = parseInt(match[3], 10); 78 const dob = new Date(year, month - 1, day); 79 const validDate = dob.getFullYear() === year && dob.getMonth() === month - 1 && dob.getDate() === day; 80 81 if (!validDate) { 82 input.setCustomValidity(config.dobInvalidMessage || 'Please enter a valid date of birth.'); 83 input.reportValidity(); 84 return; 85 } 86 87 const today = new Date(); 88 if (dob > today) { 89 input.setCustomValidity(config.dobFutureMessage || 'Date of birth cannot be in the future.'); 90 input.reportValidity(); 91 return; 92 } 93 94 let age = today.getFullYear() - year; 95 const birthdayThisYear = new Date(today.getFullYear(), month - 1, day); 96 if (today < birthdayThisYear) age--; 97 98 const minimumAge = Number.isFinite(Number(config.minimumAge)) ? Number(config.minimumAge) : 50; 99 if (age < minimumAge) { 100 input.setCustomValidity(config.dobAgeMessage || 'Please check your date of birth.'); 101 input.reportValidity(); 102 return; 103 } 104 105 input.setCustomValidity(''); 106 } 107 108 function setupDOBFields(container) { 109 const dobLabel = config.dobLabel || 'Date of Birth'; 110 111 container.querySelectorAll('label').forEach(function (label) { 112 if (label.textContent.replace('*', '').trim() !== dobLabel) return; 113 114 const wrapper = label.closest('.el-form-item') || label.closest('.am-fs__info-form__item') || label.parentElement; 115 const input = wrapper ? wrapper.querySelector('input') : null; 116 if (!input || input.dataset.pmsDobReady === '1') return; 117 118 input.dataset.pmsDobReady = '1'; 119 input.placeholder = 'DD/MM/YYYY'; 120 input.inputMode = 'numeric'; 121 input.autocomplete = 'bday'; 122 input.maxLength = 10; 123 124 input.addEventListener('keyup', function () { 125 const formatted = formatDOB(this.value); 126 if (formatted !== this.value) setNativeValue(this, formatted); 127 this.setCustomValidity(''); 128 }); 129 130 input.addEventListener('blur', function () { 131 validateDOB(this); 132 }); 133 }); 134 } 135 136 function enhance() { 137 markScreeningContainers(); 138 139 document.querySelectorAll('.amelia-v2-booking.' + screeningClass).forEach(function (container) { 140 replaceExactText(container, 'Employee Selection', config.employeeSelectionLabel || 'Choose a site'); 141 setupDOBFields(container); 142 }); 143 } 144 145 function start() { 146 enhance(); 147 148 const observer = new MutationObserver(function () { 149 enhance(); 150 }); 151 152 observer.observe(document.body, { childList: true, subtree: true }); 153 } 154 155 if (document.readyState === 'loading') { 156 document.addEventListener('DOMContentLoaded', start); 157 } else { 158 start(); 159 } 160})();
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.