1(function () { 2 const siteKey = window.__recaptchaEnterpriseSiteKey; 3 if (!siteKey || typeof grecaptcha === "undefined") return; 4 5 function captureRecaptchaEvent(eventName, props) { 6 try { 7 if (window.posthog && typeof window.posthog.capture === "function") { 8 window.posthog.capture(eventName, props); 9 } 10 } catch (err) { 11 // Never break submit for analytics failures. 12 } 13 } 14 15 function getOrCreateResponseInput(form) { 16 let input = form.querySelector('input[name="g-recaptcha-response"]'); 17 if (!input) { 18 input = document.createElement('input'); 19 input.type = 'hidden'; 20 input.name = 'g-recaptcha-response'; 21 form.appendChild(input); 22 } 23 return input; 24 } 25 26 // Button-driven flow (closest to Google's "add attributes to button" pattern) 27 // Use on a submit button with class="js-recaptcha-enterprise" and optional data-recaptcha-action. 28 document.addEventListener("click", function (e) { 29 const btn = e.target && e.target.closest ? e.target.closest(".js-recaptcha-enterprise") : null; 30 if (!btn) return; 31 32 const form = btn.form || (btn.closest ? btn.closest("form") : null); 33 if (!form || !(form instanceof HTMLFormElement)) return; 34 35 const isTrusted = e.isTrusted !== false; 36 const action = btn.dataset.recaptchaAction || form.dataset.recaptchaAction || "submit"; 37 38 // If the form has client-side validation rules, run them first so we 39 // don't trigger reCAPTCHA for obviously invalid input. 40 let isValid = true; 41 try { 42 const jq = window.jQuery; 43 if (typeof jq !== "undefined") { 44 const $form = jq(form); 45 let validator = $form.data("validator"); 46 47 // In some MVC setups, unobtrusive validation is parsed after load. 48 // Ensure rules are registered so `valid()` reflects field errors. 49 if (!validator && jq.validator && jq.validator.unobtrusive && typeof jq.validator.unobtrusive.parse === "function") { 50 jq.validator.unobtrusive.parse(form); 51 validator = $form.data("validator"); 52 } 53 54 if (validator) { 55 // `valid()` will also surface messages. 56 isValid = $form.valid(); 57 } else if (typeof form.checkValidity === "function") { 58 isValid = form.checkValidity(); 59 } 60 } else if (typeof form.checkValidity === "function") { 61 isValid = form.checkValidity(); 62 } 63 } catch (err) { 64 // If validation integration fails for any reason, fall back to 65 // previous behavior (always trigger reCAPTCHA). 66 isValid = true; 67 } 68 69 if (!isValid) return; 70 71 // Prevent multiple token requests for the same click/submit. 72 // Always preventDefault so a second click cannot POST with a cleared token. 73 if (form.dataset.recaptchaProcessing === "true") { 74 e.preventDefault(); 75 e.stopPropagation(); 76 // Second click while a token was already in flight was blocked 77 captureRecaptchaEvent("recaptcha_enterprise_duplicate_submit_blocked", { 78 action: action, 79 isTrusted: isTrusted, 80 hasToken: false, 81 pathname: window.location && window.location.pathname 82 }); 83 return; 84 } 85 form.dataset.recaptchaProcessing = "true"; 86 87 const input = getOrCreateResponseInput(form); 88 input.value = ""; 89 90 // Pause the click's default submit so we can inject the token first 91 e.preventDefault(); 92 93 if (!isTrusted) { 94 // That click was untrusted (often password manager / scripted) â still proceeded 95 captureRecaptchaEvent("recaptcha_enterprise_untrusted_click", { 96 action: action, 97 isTrusted: false, 98 hasToken: false, 99 pathname: window.location && window.location.pathname 100 }); 101 } 102 103 // Our handler took a valid submit click and started token fetch 104 captureRecaptchaEvent("recaptcha_enterprise_submit_intercepted", { 105 action: action, 106 isTrusted: isTrusted, 107 hasToken: false, 108 pathname: window.location && window.location.pathname 109 }); 110 111 function submitFormWithToken() { 112 if (typeof form.requestSubmit === "function") { 113 form.requestSubmit(btn); 114 } else { 115 form.submit(); 116 } 117 } 118 119 grecaptcha.enterprise.ready(function () { 120 grecaptcha.enterprise.execute(siteKey, { action: action }) 121 .then(function (token) { 122 const hasToken = !!(token && String(token).trim()); 123 input.value = token || ""; 124 delete form.dataset.recaptchaProcessing; 125 126 // Always submit so the server can show the existing 807 message when the token is empty. 127 if (!hasToken) { 128 // Empty token or execute rejected; form still submitted (will likely hit 807) 129 captureRecaptchaEvent("recaptcha_enterprise_token_failed", { 130 action: action, 131 isTrusted: isTrusted, 132 hasToken: false, 133 errorName: "empty_token", 134 pathname: window.location && window.location.pathname 135 }); 136 } else { 137 // Google returned a non-empty token; form submitted 138 captureRecaptchaEvent("recaptcha_enterprise_token_success", { 139 action: action, 140 isTrusted: isTrusted, 141 hasToken: true, 142 pathname: window.location && window.location.pathname 143 }); 144 } 145 146 submitFormWithToken(); 147 }) 148 .catch(function (err) { 149 input.value = ""; 150 delete form.dataset.recaptchaProcessing; 151 // Empty token or execute rejected; form still submitted (will likely hit 807) 152 captureRecaptchaEvent("recaptcha_enterprise_token_failed", { 153 action: action, 154 isTrusted: isTrusted, 155 hasToken: false, 156 errorName: err && err.name ? String(err.name) : "execute_rejected", 157 pathname: window.location && window.location.pathname 158 }); 159 // Same 807 path as an empty token so the click is not silent. 160 submitFormWithToken(); 161 }); 162 }); 163 });
164})();
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.