1import { getConfigValue, getCountryIso } from '../configs.js'; 2import { closeModal } from '../utils.js'; 3import { fetchPlaceholdersForLocale } from '../scripts.js'; 4import { loginMobile, sendOtpApiCall, getAuraLinkingDetails } from '../aura/api.js'; 5import { 6 validateInput, setErrorMessageForField, showErrorMessage, validatePhone, 7 resetMessage, 8} from '../forms.js'; 9import debounce from '../helpers/debounce.js'; 10import { loadCSS } from '../aem.js'; 11 12const placeholders = await fetchPlaceholdersForLocale(); 13let timerInterval; 14 15export function addFormValidation(form) { 16 form.querySelectorAll('input').forEach((input) => { 17 setErrorMessageForField(input, placeholders); 18 const button = form.querySelector('button') || form.closest('.contact-method').querySelector('button'); 19 input.addEventListener('input', () => { 20 if (!validateInput(input)) { 21 button.disabled = true; 22 } else { 23 button.disabled = false; 24 } 25 }); 26 }); 27} 28 29export function debouncedFormValidation(form) { 30 const button = form.querySelector('button') || form.closest('.contact-method').querySelector('button'); 31 form.querySelectorAll('input').forEach((input) => { 32 setErrorMessageForField(input, placeholders); 33 input.addEventListener('input', () => { 34 debounce(() => { 35 resetMessage(input); 36 button.disabled = false; 37 }, 300)(); 38 }); 39 40 input.addEventListener('blur', () => { 41 if (!validateInput(input)) { 42 button.disabled = true; 43 } 44 }); 45 }); 46} 47 48export function nextStage(joinAura) { 49 const curr = joinAura.querySelector('.show'); 50 curr.nextElementSibling.classList.add('show'); 51 curr.classList.remove('show'); 52} 53 54export function prevStage(joinAura) { 55 const curr = joinAura.querySelector('.show'); 56 curr.previousElementSibling.classList.add('show'); 57 curr.classList.remove('show'); 58} 59 60export async function addResendListener(otpContainer, mobileForm) { 61 const resendLinkEvent = otpContainer.querySelector('.otp-info-text a'); 62 const mobile = mobileForm.querySelector('#login-mobile').value; 63 const countrycode = await getConfigValue('country-code'); 64 const countryPrefix = `${await getCountryIso(countrycode)}`; 65 resendLinkEvent.addEventListener('click', async (event) => { 66 let response; 67 event.preventDefault(); 68 const auraLinkingDetails = getAuraLinkingDetails(); 69 if (auraLinkingDetails) { 70 const { type, value, countryIsoAdded } = auraLinkingDetails; 71 if (type !== null && value !== null) { 72 response = await sendOtpApiCall('', type, value, countryIsoAdded); 73 } else { 74 response = await loginMobile(mobile, countryPrefix); 75 } 76 if (response === true) { 77 // eslint-disable-next-line no-use-before-define 78 startResendOtpTimer(otpContainer, mobileForm); 79 } else { 80 const inputFieldWrapper = otpContainer.querySelector('.input-field-wrapper'); 81 otpContainer.querySelector('.otp-info-text a').classList.add('inactive'); 82 const errorMessage = response.parameters?.length > 0 ? response?.parameters[0] : 'Maximum number of attempts reached. Please try after sometime.'; 83 showErrorMessage(inputFieldWrapper, errorMessage); 84 } 85 } 86 }); 87} 88 89function startResendOtpTimer(otpContainer, mobileForm) { 90 const successMessageDiv = otpContainer.querySelector('.otp-success-message'); 91 const resendLink = otpContainer.querySelector('.otp-info-text p'); 92 const originalText = resendLink.innerHTML; 93 let timeRemaining = 60; 94 resendLink.textContent = `${placeholders.resending}` || 'Resending'; 95 successMessageDiv.classList.remove('hide-message'); 96 setTimeout(() => { 97 successMessageDiv.classList.add('hide-message'); 98 }, 5000); 99 timerInterval = setInterval(() => { 100 resendLink.classList.add('disabled'); 101 if (timeRemaining > 0) { 102 timeRemaining -= 1; 103 const seconds = timeRemaining < 10 ? `0${timeRemaining}` : timeRemaining; 104 resendLink.textContent = `${placeholders.resendIn || 'Resend In'} 00:${seconds}s`; 105 } else { 106 clearInterval(timerInterval); 107 resendLink.classList.remove('disabled'); 108 resendLink.innerHTML = originalText; 109 addResendListener(otpContainer, mobileForm); 110 } 111 }, 1000); 112} 113 114export function resetOtp(otpContainer, defaultOtpResendText, mobileForm) { 115 const resendText = otpContainer.querySelector('.otp-info-text p'); 116 const otpInput = otpContainer.querySelector('.aura-otp-form input'); 117 resendText.innerHTML = defaultOtpResendText; 118 if (otpInput) { 119 otpInput.value = ''; 120 } 121 clearInterval(timerInterval); 122 addResendListener(otpContainer, mobileForm); 123} 124 125export async function phonenumberValidation(mobileForm) { 126 const phoneInput = mobileForm.querySelector('#login-mobile'); 127 phoneInput.addEventListener('input', async (event) => { 128 event.target.value = event.target.value.replace(/[^0-9]/g, ''); 129 const countryName = await getConfigValue('country-code');
130 const mobile = phoneInput.value; 131 if (mobile === '') { 132 const inputFieldWrapper = mobileForm.querySelector('.input-field-wrapper'); 133 const errorMessage = placeholders.noMobileMessage || 'Please enter Mobile Number'; 134 showErrorMessage(inputFieldWrapper, errorMessage); 135 return; 136 } 137 if (event.target.value.length >= phoneInput.maxLength) { 138 const isValidPhoneNumber = await validatePhone( 139 phoneInput.value, 140 countryName, 141 ); 142 let phoneErrorMessage = placeholders.invalidMobileNumber || `The number provided ${phoneInput.value} is not a valid mobile number.`; 143 phoneErrorMessage = phoneErrorMessage.replace('{{mobile}}', phoneInput.value); 144 145 if (!isValidPhoneNumber) { 146 showErrorMessage(phoneInput, phoneErrorMessage); 147 mobileForm.querySelector('.aura-buttons button').disabled = true; 148 } else { 149 mobileForm.querySelector('.aura-buttons button').disabled = false; 150 } 151 } 152 }); 153} 154 155export async function phonenumberBlurValidation(mobileForm) { 156 const phoneInput = mobileForm.querySelector('#login-mobile'); 157 const button = mobileForm.querySelector('.aura-buttons button'); 158 const countryName = await getConfigValue('country-code'); 159 setErrorMessageForField(phoneInput, placeholders); 160 161 phoneInput.addEventListener('blur', async () => { 162 if (!validateInput(phoneInput)) { 163 button.disabled = true; 164 } else { 165 button.disabled = false; 166 } 167 if (phoneInput.value.length >= phoneInput.maxLength) { 168 const isValidPhoneNumber = await validatePhone( 169 phoneInput.value, 170 countryName, 171 ); 172 let phoneErrorMessage = placeholders.invalidMobileNumber || `The number provided ${phoneInput.value} is not a valid mobile number.`; 173 phoneErrorMessage = phoneErrorMessage.replace('{{mobile}}', phoneInput.value); 174 175 if (!isValidPhoneNumber) { 176 showErrorMessage(phoneInput, phoneErrorMessage); 177 button.disabled = true; 178 } else { 179 button.disabled = false; 180 } 181 } 182 }); 183 184 phoneInput.addEventListener('input', () => { 185 resetMessage(phoneInput); 186 button.disabled = false; 187 }); 188 189 phoneInput.addEventListener('keydown', (e) => { 190 if (e.ctrlKey || e.metaKey) { 191 return; 192 } 193 if (e.key.length === 1 && !/[\d]/.test(e.key)) { 194 e.preventDefault(); 195 } 196 }); 197} 198 199export function submitOnEnter(forms) { 200 forms.forEach((form) => { 201 form.addEventListener('keydown', (event) => { 202 if (event.key === 'Enter') { 203 event.preventDefault(); 204 const inputs = form.querySelectorAll('input'); 205 inputs.forEach((input) => { 206 if (input.value) { 207 input.dispatchEvent(new Event('blur', { cancelable: true, bubbles: true })); 208 } 209 }); 210 if (!form.querySelector('button').disabled) { 211 form.dispatchEvent(new Event('submit', { cancelable: true, bubbles: true })); 212 } 213 } 214 }); 215 }); 216} 217 218export function auraModalRedirection(congratsForm, dialogName, redirectName, reDecorate) { 219 congratsForm.addEventListener('click', async (event) => { 220 event.preventDefault(); 221 const lang = document.documentElement.lang || 'en'; 222 const redirectLink = await getConfigValue(redirectName); 223 closeModal(dialogName); 224 // For join-aura / link-aura remove the generic overlay once the modal is closed. 225 const genericOverlay = document.querySelector('.generic-overlay-background'); 226 if (genericOverlay?.classList.contains('show')) { 227 genericOverlay?.classList.remove('show'); 228 } 229 if (dialogName === 'link-your-aura-dialog') { 230 window.dispatchEvent(new CustomEvent('linkAuraSuccess')); 231 } 232 233 if (reDecorate) { 234 reDecorate(); 235 } 236 237 if (redirectLink && redirectLink !== '') { 238 window.location.href = `/${lang}${redirectLink}`; 239 } 240 }); 241} 242 243export async function loadAuraAutoEnrollmentCss() { 244 document.body.classList.add('aura-auto-enrollment'); 245 const cssFiles = [ 246 { base: '/styles/', file: 'aura-auto-enrollment.css' }, 247 ]; 248 const { getBrandPath } = await import('../scripts.js'); 249 const brandPath = getBrandPath(); 250 const excluded = ['ult']; 251 if (excluded.includes(brandPath)) { 252 return; 253 }
254 cssFiles.forEach(({ base, file }) => { 255 const brandSpecificPath = `${base}${brandPath}${file}`; 256 loadCSS(brandSpecificPath); 257 }); 258}
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.