1$.validator.setDefaults({ ignore: ":hidden" }); 2 3$(function () { 4 $('input[type="submit"]').click(function (event) { 5 const $formElement = $(this).closest("form"); 6 if (!$formElement.attr('data-token')) { 7 event.preventDefault() 8 void executeCustomValidation($formElement) 9 } 10 }); 11}); 12 13const executeCustomValidation = async ($formElement) => { 14 // If the all other inputs in the form are valid, execute grecaptcha check 15 if (($formElement && $formElement.valid()) || !$formElement) { 16 isValidCaptcha = await executeGoogleRecaptcha($formElement) 17 } 18 19 // Scroll to and focus on first error 20 if ($formElement.find('.input-validation-error:visible').length > 0) { 21 $('textarea.input-validation-error').closest(".textarea-container").addClass("input-error"); // Add class to textarea container to add outline style 22 const $firstError = $('.input-validation-error:visible:first') 23 let scrollToError = $firstError.parent().offset().top 24 // Set scroll to textarea's container (not immediate parent) 25 if ($firstError.is("textarea")) { 26 scrollToError = $firstError.closest(".text-area").offset().top 27 // If the first error is a text area 'count exceeded' error, scroll to the extra characters in the text area 28 if ($firstError.closest(".textarea-input").hasClass("count-exceeded")) { 29 textArea = $firstError.closest(".textarea-input")[0] 30 const textLength = textArea.value.length 31 textArea.setSelectionRange(textLength, textLength) 32 textArea.scrollTop = textArea.scrollHeight 33 } 34 }; 35 $('html, body').animate({ 36 scrollTop: scrollToError 37 }, 300); 38 $firstError.focus(); 39 }; 40} 41 42const executeGoogleRecaptcha = async ($formElement) => { 43 const siteKey = document.querySelector('[data-sitekey]').getAttribute('data-sitekey'); 44 const token = await grecaptcha.execute(siteKey, { action: 'SitecoreForms' }) 45 void populateRecaptchaInput(token, $formElement) 46} 47 48const populateRecaptchaInput = async (token, $formElement) => { 49 const myHeaders = new Headers(); 50 myHeaders.append("Content-Type", 'application/x-www-form-urlencoded; charset=UTF-8'); 51 const endpointUrl = new URL('/recaptchaapi/ValidateRecaptcha', window.location.origin) 52 const antiForgeryTokenInputEl = document.querySelector('input[name=__RequestVerificationToken]') 53 const antiForgeryTokenValue = antiForgeryTokenInputEl.value 54 const captchaRequest = { 55 Token: token 56 } 57 captchaRequest.__RequestVerificationToken = antiForgeryTokenValue 58 const urlEncodedRequestBody = new URLSearchParams(captchaRequest) 59 60 try { 61 const response = await fetch(endpointUrl, { 62 method: "POST", 63 body: urlEncodedRequestBody, 64 headers: myHeaders, 65 }); 66 67 if (!response.ok) { 68 handleCaptchaFail($formElement) 69 throw new Error(`Response status: ${response.status}`); 70 } 71 72 const responseCode = await response.text(); 73 if (responseCode !== "false") { 74 $formElement.attr('data-token', token) 75 $formElement.find('.recaptcha-error').addClass('is-hidden') 76 $formElement.find('input[type="submit"]').click() 77 return true 78 } else { 79 handleCaptchaFail($formElement) 80 } 81 } catch (e) { 82 handleCaptchaFail($formElement) 83 console.error(e); 84 } 85 return false 86} 87 88const handleCaptchaFail = ($formElement) => { 89 const $submitButton = $('input[type="submit"]'); 90 const $btnListYes = $('#btnlist-yes'); 91 const $btnListNo = $('#btnlist-no'); 92 const $checklistQuestionsContainer = $('.in-page-feedback-no') 93 const $recaptchaError = $('.recaptcha-error') 94 $formElement.attr('data-token', '') 95 96 // Disable submit buttons 97 $submitButton.attr('disabled', 'disabled'); 98 $btnListYes.attr('disabled', true).closest('.radio-button').addClass('disabled'); 99 $btnListNo.attr('disabled', true).closest('.radio-button').addClass('disabled'); 100 $checklistQuestionsContainer.addClass('is-hidden') 101 102 // Show recaptcha error 103 $recaptchaError.removeClass('is-hidden') 104 $('html').animate({scrollTop: $recaptchaError.offset().top,},800); 105}
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.