1const staffEmail = document.getElementById("staff_email_id"); 2if (staffEmail) { 3 staffEmail.addEventListener("change", function () { 4 let staffSsoLogin = document.querySelector('#staff_non_sso_login'); 5 if (staffSsoLogin) { 6 staffSsoLogin.href = staffSsoLogin.href + `&email=${encodeURIComponent(staffEmail.value)}` 7 } 8 }) 9} 10 11// pre-populate email given in sign-in field to non-sso sign-in url 12const clientUserEmail = document.getElementById("client_user_email_id"); 13if (clientUserEmail) { 14 clientUserEmail.addEventListener("change", function () { 15 setclientUserEmailToNonSsoUrl.initialize(); 16 }) 17} 18 19var setclientUserEmailToNonSsoUrl = { 20 initialize: function () { 21 let clientEmail = document.querySelector('#client_user_email_id'); 22 let clientUserSsoLogin = document.querySelector('#client_user_non_sso_login'); 23 if (clientUserSsoLogin) { 24 clientUserSsoLogin.href = clientUserSsoLogin.href + `&email=${encodeURIComponent(clientEmail.value)}` 25 } 26 } 27} 28 29var toggleMetadataFields = { 30 initialize: function () { 31 var urlField = document.querySelector("#metadata_type_option_0_for_hiding"); 32 var fileField = document.querySelector("#metadata_type_option_1_for_hiding"); 33 var meta_data_file = document.querySelector("#client_sso_detail_metadata_file"); 34 let url_option = document.querySelector("#metadata_type_option_0"); 35 let file_option = document.querySelector("#metadata_type_option_1"); 36 if (url_option && url_option.checked) { 37 if (!(urlField.getAttribute("class").includes("optional"))) { 38 urlField.querySelector(".label").classList.add("required"); 39 fileField.querySelector(".label").classList.remove("required"); 40 meta_data_file.removeAttribute("required"); 41 } 42 urlField.classList.remove("hidden"); 43 fileField.classList.add("hidden"); 44 } else if (file_option && file_option.checked) { 45 if (!(urlField.getAttribute("class").includes("optional"))) { 46 fileField.querySelector(".label").classList.add("required"); 47 meta_data_file.setAttribute("required", ""); 48 urlField.querySelector(".label").classList.remove("required"); 49 } 50 fileField.classList.remove("hidden"); 51 urlField.classList.add("hidden"); 52 } 53 54 let providerTypeMicrosoft = document.querySelector("#provider-type-option-microsoft"); 55 if (providerTypeMicrosoft) { 56 let samlTidField = document.querySelector("#client-sso-detail-ms-saml-tid-attribute"); 57 let samlOidField = document.querySelector("#client-sso-detail-ms-saml-oid-attribute"); 58 let tidLabel = document.querySelector("label[for='" + samlTidField.id + "']"); 59 let oidLabel = document.querySelector("label[for='" + samlOidField.id + "']"); 60 const isChecked = providerTypeMicrosoft.checked; 61 62 [tidLabel, oidLabel].forEach((element) => { 63 element.classList.toggle("required", isChecked); 64 }); 65 66 [samlTidField, samlOidField].forEach((element) => { 67 isChecked ? element.setAttribute("required", isChecked) : element.removeAttribute("required"); 68 }); 69 } 70 } 71} 72 73var toggleSidebar = { 74 initialize: function () { 75 const enableSidebarCheckbox = document.getElementById('enableSidebarCheckbox'); 76 const conditionalFields = document.getElementById('side_bar_components'); 77 const sidebarImage = document.getElementById('sidebar_image'); 78 79 if (enableSidebarCheckbox) { 80 enableSidebarCheckbox.addEventListener('change', function() { 81 if (this.checked) { 82 conditionalFields.style.display = 'block'; 83 sidebarImage.style.display = 'block'; 84 } else { 85 conditionalFields.style.display = 'none'; 86 sidebarImage.style.display = 'none'; 87 } 88 }); 89 if (enableSidebarCheckbox.checked) { 90 conditionalFields.style.display = 'block'; 91 sidebarImage.style.display = 'block'; 92 } else { 93 conditionalFields.style.display = 'none'; 94 sidebarImage.style.display = 'none'; 95 } 96 } 97 } 98} 99 100 101var allowedServicesToggle = { 102 initialize: function () { 103 var input = document.querySelector('#allowed_services_select') 104 if (input) { 105 var whitelist_1 = [{value: "Interpretings", id: 'F2F'}, { 106 value: "Telephone interpreting", id: "TI" 107 }, {value: "Video remote interpreting", id: "VRI"}, { 108 value: "Translation / Transcription", id: "Translation" 109 }] 110 // init Tagify script on the above inputs 111 new Tagify(input, { 112 whitelist: whitelist_1.map(function (item) { 113 return typeof item == 'string' ? {value: item} : item 114 }), maxTags: 10, dropdown: { 115 maxItems: 20, // <- mixumum allowed rendered suggestions 116 classname: "tags-look", // <- custom classname for this dropdown, so it could be targeted 117 enabled: 0, // <- show suggestions on focus
118 closeOnSelect: false // <- do not hide the suggestions dropdown once an item has been selected 119 } 120 }) 121 122 const submit = document.getElementsByClassName('form-submit') 123 124 submit[0]?.addEventListener("click", function () { 125 const tag = document.getElementsByClassName('tagify') 126 const selected_tags = tag[0].childNodes 127 128 var selected_allowed_services = [] 129 for (let i = 0; i < selected_tags.length; i++) { 130 selected_allowed_services.push(selected_tags[i].id) 131 } 132 var allowed_services = document.getElementById("allowed_services"); 133 allowed_services.value = selected_allowed_services 134 }); 135 } 136 } 137} 138 139const passwordPolicyCriteria = { 140 initialize: function () { 141 const urlParams = new URLSearchParams(window.location.search); 142 const app_id = urlParams.get("app_id"); 143 const token = urlParams.get('token') 144 const that = this 145 const url = `${window.location.origin}/check_password_strength?app_id=${app_id}&token=${token}`; 146 let passwordField = document.querySelectorAll('.input-password-field'); 147 if(passwordField.length === 0) return; 148 const criteriaList = document.querySelectorAll('.criteria') 149 let submitCheckAttempted = false; 150 let validations = [{pattern: /.{12,}/, issue: 'Must be at least 12 characters'}, { 151 pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@!%*#?&])/, 152 issue: 'Must include uppercase letters,' + 'lowercase,number and special character' 153 }, {pattern: /\D$/, issue: 'Last character should not be a number'}] 154 let confirmPasswordField = document.getElementById('password-confirm-field'); 155 let errorMessage = confirmPasswordField.parentElement.querySelector(".error-text"); 156 this.confirmMessageMatch = (password) => { 157 errorMessage.classList.toggle("error-block", password.length === 0 ? false : password === confirmPasswordField.value); 158 } 159 this.resetSubmitCriteria = function () { 160 [4, 5].forEach((index) => { 161 const circle = criteriaList[index]?.querySelector('.circle'); 162 circle?.classList.remove('checked', 'unchecked'); 163 }); 164 submitCheckAttempted = false; 165 document.getElementById("error-block")?.classList.add('error-block'); 166 } 167 confirmPasswordField.addEventListener("focus", (event) => { 168 event.preventDefault(); 169 const password = passwordField[0].value; 170 this.confirmMessageMatch(password); 171 }) 172 confirmPasswordField.addEventListener("keyup", (event, field) => { 173 event.preventDefault(); 174 if (submitCheckAttempted) that.resetSubmitCriteria(); 175 const password = passwordField[0].value; 176 let isValid = password.length === 0 ? false : password === confirmPasswordField.value 177 let circle = criteriaList[3].querySelector('.circle'); 178 circle.classList.toggle('checked', isValid); 179 circle.classList.toggle('unchecked', !isValid); 180 this.confirmMessageMatch(password); 181 this.toCheckAllValid(); 182 }) 183 const handleKeyUp = (event, field) => { 184 event.preventDefault(); 185 if (submitCheckAttempted) that.resetSubmitCriteria(); 186 const password = field.value; 187 188 this.validationRegex(validations, criteriaList, password); 189 this.toCheckAllValid(); 190 if (confirmPasswordField.value.length > 0) { 191 this.confirmMessageMatch(password); 192 } 193 }; 194 this.toggleCheckbox = function (validate, circle) { 195 circle.classList.toggle('checked', validate); 196 circle.classList.toggle('unchecked', !validate); 197 } 198 this.checkPasswordStrength = (password) => { 199 return new Promise((resolve) => { 200 const encodedPassword = encodeURIComponent(password); 201 const xhr = new XMLHttpRequest(); 202 xhr.open('GET', url + '&password=' + encodedPassword); 203 xhr.responseType = 'json'; 204 xhr.onload = function () { 205 const response = xhr.response; 206 if (response && !response.errors) { 207 resolve({ 208 isOldPassword: response.is_old_password, 209 isCommonPassword: response.is_common_password 210 }); 211 } else { 212 resolve({ error: true }); 213 } 214 }; 215 xhr.onerror = function () { 216 resolve({ error: true }); 217 }; 218 xhr.send(); 219 }); 220 }; 221 passwordField.forEach((field) => { 222 field.addEventListener("input", (event) => handleKeyUp(event, field)); 223 }) 224 const form = document.getElementById('kt_sign_in_form'); 225 if (form) { 226 form.addEventListener('submit', async (event) => { 227 event.preventDefault(); 228 const passwordInput = passwordField[0]; 229 const password = passwordInput.value; 230 const clientSideValid = validations.every((v) => v.pattern.test(password)) 231 && password.length > 0 232 && password === confirmPasswordField.value; 233 234 if (!clientSideValid) { 235 this.validationRegex(validations, criteriaList, password); 236 this.toCheckAllValid(); 237 return; 238 } 239 240 const submitButton = document.querySelector(".submit-button"); 241 submitButton.disabled = true; 242 passwordInput.readOnly = true; 243 confirmPasswordField.readOnly = true; 244 245 const result = await this.checkPasswordStrength(password); 246 247 if (result.error) { 248 form.submit(); 249 return; 250 } 251 252 submitCheckAttempted = true; 253 254 that.toggleCheckbox(!result.isOldPassword, criteriaList[4].querySelector('.circle')); 255 that.toggleCheckbox(!result.isCommonPassword, criteriaList[5].querySelector('.circle')); 256 257 if (!result.isOldPassword && !result.isCommonPassword) { 258 form.submit(); 259 } else { 260 passwordInput.readOnly = false;
261 confirmPasswordField.readOnly = false; 262 that.toCheckAllValid(); 263 document.getElementById("error-block")?.classList.remove('error-block'); 264 } 265 }); 266 } 267 }, validationRegex: function (validations, criteriaList, password) { 268 criteriaList.forEach((criteria, index) => { 269 const circle = criteria.querySelector('.circle'); 270 if (index < 3) { 271 const isValid = validations[index].pattern.test(password); 272 this.toggleCheckbox(isValid, circle); 273 } else if (index === 3) { 274 let confirmFieldValue = document.getElementById('password-confirm-field').value; 275 276 let isValid = password.length === 0 ? false : password === confirmFieldValue 277 this.toggleCheckbox(isValid, circle); 278 } 279 }); 280 }, 281 toCheckAllValid: function () { 282 let submitButton = document.querySelector(".submit-button"); 283 let firstThreeCriteria = document.querySelectorAll('.custom-list .criteria:nth-child(-n+3) .circle.checked') 284 let confirmMatch = document.querySelector('.custom-list .criteria:nth-child(4) .circle.checked') 285 let clientSideValid = firstThreeCriteria.length === 3 && confirmMatch; 286 document.getElementById("error-block").classList.toggle('error-block', firstThreeCriteria.length === 3) 287 submitButton.disabled = !clientSideValid; 288 submitButton.parentElement.classList.toggle('disabled-cursor', !clientSideValid); 289 } 290}; 291 292const handleShowPassword = { 293 initialize: function () { 294 const eyeIcons = document.querySelectorAll('.eye-icon'); 295 eyeIcons.forEach((eyeIcon) => { 296 eyeIcon.addEventListener("click", function () { 297 let inputField = this.parentElement.querySelector('input'); 298 inputField.type = inputField.type === 'password' ? 'text' : 'password'; 299 this.parentElement.querySelectorAll(".eye-icon").forEach((eyeIcon) => { 300 eyeIcon.classList.toggle("eye-hide-icon") 301 }) 302 }) 303 }) 304 305 } 306} 307 308document.addEventListener("turbo:load", function () { 309 toggleMetadataFields.initialize(); 310 setclientUserEmailToNonSsoUrl.initialize(); 311 toggleSidebar.initialize() 312 passwordPolicyCriteria.initialize(); 313 handleShowPassword.initialize(); 314}); 315 316document.addEventListener("turbo:render", function () { 317 toggleMetadataFields.initialize(); 318 allowedServicesToggle.initialize(); 319}); 320 321document.addEventListener("change", function () { 322 toggleMetadataFields.initialize(); 323}); 324 325document.addEventListener("click", function () { 326 toggleMetadataFields.initialize(); 327}); 328 329document.addEventListener("DOMContentLoaded", function (e) { 330 allowedServicesToggle.initialize(); 331});
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.