1const validateName = e => e.trim().match(/^[a-zA-Z\- ]{1,50}$/) !== null; 2 3const validateEmail = e => e.trim().match(/^(?=.{3,320}$)[-!#$%&'*+/0-9=?A-Z^_a-z{|}~](\.?[-!#$%&'*+/0-9=?A-Z^_a-z{|}~]){0,63}@[a-zA-Z0-9](-?[a-zA-Z0-9])*(\.[a-zA-Z](-?[a-zA-Z0-9])*)+$/) !== null; 4 5const validateString = e => e.trim().match(/^[a-zA-Z0-9_-]{3,40}$/) !== null; 6 7const validatePassword = e => { 8 if (e.length < 8) { 9 return false; 10 } 11 const t = /(.)\1{3,}/; 12 const a = /0123|1234|2345|3456|4567|5678|6789|7890|abcd|bcde|cdef|defg|efgh|fghi|ghij|hijk|ijkl|jklm|klmn|lmno|mnop|nopq|opqr|pqrs|qrst|rstu|stuv|tuvw|uvwx|vwxy|wxyz/i; 13 const r = /3210|4321|5432|6543|7654|8765|9876|0987|dcba|edcb|fedc|gfed|hgfed|ihgfe|jihgf|lkji|mlkj|nmlk|onml|ponm|qpon|rqp|srqp|utsr|vuts|wvut|xwvu|yxwv|zyxw/i; 14 const s = !t.test(e) && !a.test(e) && !r.test(e); 15 return s; 16}; 17 18const validatePasswordMatch = (e, t) => e === t.value; 19 20const validationData = { 21 "#plus-signup-first-name": { 22 validate: validateName, 23 message: "Please enter a valid first name" 24 }, 25 "#plus-signup-last-name": { 26 validate: validateName, 27 message: "Please enter a valid last name" 28 }, 29 "#plus-login-email": { 30 validate: validateEmail, 31 message: "Please enter a valid email address" 32 }, 33 "#plus-signup-email": { 34 validate: validateEmail, 35 message: "Please enter a valid email address" 36 }, 37 "#plus-signup-username": { 38 validate: validateString, 39 message: `Please ensure your username meets the following criteria:<ul><li>Alphanumeric, length between 3 and 40 characters</li><li>Allowed special characters: hyphens, underscores</li></ul>` 40 }, 41 "#plus-signup-password": { 42 validate: validatePassword, 43 message: `Please ensure your password meets the following criteria:<ul>\n <li>Minimum length of 8 characters</li><li>No more than 3 characters repeated or in sequential order</li></ul>` 44 }, 45 "#plus-signup-password-confirm": { 46 validate: validatePasswordMatch, 47 message: "Passwords do not match" 48 }, 49 "#plus-account-first-name": { 50 validate: validateName, 51 message: "Please enter a valid first name" 52 }, 53 "#plus-account-last-name": { 54 validate: validateName, 55 message: "Please enter a valid last name" 56 }, 57 "#plus-account-email": { 58 validate: validateEmail, 59 message: "Please enter a valid email address" 60 }, 61 "#plus-account-display-name": { 62 validate: validateString, 63 message: `Please ensure your username meets the following criteria:<ul><li>Alphanumeric, length between 3 and 40 characters</li><li>Allowed special characters: hyphens, underscores</li></ul>` 64 }, 65 "#plus-account-password": { 66 validate: validatePassword, 67 message: `Please ensure your password meets the following criteria:<ul>\n <li>Minimum length of 8 characters</li><li>No more than 3 characters repeated or in sequential order</li></ul>` 68 }, 69 "#plus-account-password-confirm": { 70 validate: validatePasswordMatch, 71 message: "Passwords do not match" 72 } 73}; 74 75export const formStatus = {}; 76 77export function passwordVisibility() { 78 const e = document.querySelectorAll(".plus-form__field-wrap--password"); 79 if (!e) return; 80 e.forEach(e => { 81 const t = e.querySelector(".plus-form__field--password"); 82 const a = e.querySelector(".plus-form__field--pass-visibility"); 83 const r = () => { 84 t.type = a.checked ? "text" : "password"; 85 a.nextElementSibling.classList.toggle("shown", a.checked); 86 }; 87 a.addEventListener("click", r); 88 r(); 89 }); 90}; 91
92export function placeholderLabels() { 93 const e = document.querySelectorAll(".plus-form__label:not(.plus-form__label--checkbox)"); 94 if (!e) return; 95 e.forEach(e => { 96 const t = getFieldForLabel(e); 97 t.addEventListener("focus", () => fieldFocusHandler(t, e)); 98 t.addEventListener("blur", () => fieldBlurHandler(t, e)); 99 }); 100}; 101 102export function updateFormStatus(e) { 103 const t = e.querySelectorAll(".plus-form__label"); 104 formStatus[e.id] = Array.from(t).map(e => getFieldForLabel(e).classList.contains("error")); 105 e.firstElementChild.setAttribute("aria-hidden", !formStatus[e.id].includes(true)); 106}; 107 108export function fieldFocusHandler(e, t) { 109 clearFieldError(e); 110 if (!e.value) { 111 t.classList.add("is-label"); 112 } 113}; 114 115export function fieldBlurHandler(e, t) { 116 const a = e.value; 117 if (a) { 118 const t = validateFormField(e); 119 if (!t) { 120 const t = validationData[`#${e.id}`]; 121 const a = t && t.message ? t.message : "Input invalid"; 122 showFieldError(e, a); 123 } 124 } else if (e.required) { 125 showFieldError(e, "Please fill in this form field"); 126 t.classList.toggle("is-label"); 127 } else { 128 t.classList.toggle("is-label"); 129 } 130}; 131 132export function getFieldForLabel(e) { 133 const t = e.getAttribute("for"); 134 if (!t) return false; 135 return document.querySelector(`#${t}`); 136}; 137 138export function getLabelForField(e) { 139 return document.querySelector(`.plus-form__label[for='${e.id}']`); 140}; 141 142export function showFieldError(e, t, a = true) { 143 if (e.classList.contains("error")) return; 144 const r = e.closest("form"); 145 e.setAttribute("aria-describedby", `${e.id}_error`); 146 const s = e.closest(".plus-form__field-wrap"); 147 const l = t ? t : "Field required, please fill in this form field"; 148 const i = s.querySelector(".plus-form__error-label"); 149 i.id = `${e.id}_error`; 150 i.setAttribute("role", "alert"); 151 i.setAttribute("aria-hidden", false); 152 i.innerHTML = l; 153 e.classList.add("error"); 154 s.classList.add("error"); 155 updateFormStatus(r); 156 if (a) { 157 r.firstElementChild.innerHTML = "Please fix the form fields in error."; 158 } 159}; 160 161export function clearFieldError(e) { 162 e.removeAttribute("aria-describedby"); 163 const t = e.closest(".plus-form__field-wrap"); 164 const a = document.querySelector(`#${e.id}_error`); 165 if (!a) return; 166 a.removeAttribute("role"); 167 a.setAttribute("aria-hidden", true); 168 a.id = ""; 169 e.classList.remove("error"); 170 t.classList.remove("error"); 171 const r = e.closest("form"); 172 updateFormStatus(r); 173}; 174 175export function validateFormField(e) { 176 const t = e.id; 177 if (!t) return false; 178 const a = e.value.trim(); 179 if (!a) return false; 180 const r = validationData[`#${t}`] && typeof validationData[`#${t}`].validate === "function" ? validationData[`#${t}`].validate : e => !!e; 181 if (t.includes("password-confirm")) { 182 const e = t.replace("-confirm", ""); 183 const s = document.querySelector(`#${e}`); 184 if (!s) { 185 console.error("Password field not found, please check form field ids.", t, e); 186 return; 187 } 188 return r(a, s); 189 } 190 return r(a); 191}; 192 193export async function submitForm(e, t) { 194 const a = await fetch(e, { 195 method: "POST", 196 credentials: "same-origin", 197 body: t 198 }); 199 return a.json(); 200}; 201 202export function submitValidationAsync(e) { 203 return new Promise(t => { 204 let a = false; 205 if (e.required) { 206 if (e.value === "") { 207 showFieldError(e); 208 a = true; 209 } 210 if (e.id === "plus-signup-consent" && !e.checked) { 211 showFieldError(e, "Please consent to the terms and privacy policy to signup"); 212 a = true; 213 } 214 } 215 t(a); 216 }); 217}; 218 219export function submitWithErrors(e) { 220 e.classList.add("emphasize"); 221 setTimeout(() => { 222 e.classList.remove("emphasize"); 223 }, 600); 224};
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.