1class RecaptchaHandler { 2 constructor() { 3 // Initialize WooCommerce forms 4 this.wcForms = { 5 login: document.querySelector(".woocommerce-form-login, .login"), 6 register: document.querySelector(".woocommerce-form-register, .register"), 7 checkout: document.querySelector("form.checkout"), 8 lostpassword: document.querySelector(".woocommerce-ResetPassword"), 9 }; 10 11 // Get specific forms that need reCAPTCHA 12 this.forms = [ 13 document.getElementById("commentform"), // Comment form 14 document.getElementById("loginform"), // WP login form 15 document.getElementById("registerform"), // WP register form 16 ].filter(Boolean); 17 18 // Initialize based on reCAPTCHA version 19 this.init(); 20 21 // Handle CF7 forms for v3 22 if (recaptchaVars.version === "v3") { 23 this.initializeCF7Forms(); 24 } 25 } 26 27 async initializeCF7Forms() { 28 const cf7Forms = document.querySelectorAll(".wpcf7-form"); 29 30 for (const form of cf7Forms) { 31 try { 32 const token = await this.executeRecaptcha("contact_form"); 33 this.updateTokenInput(form, token); 34 } catch (error) { 35 console.error("Error initializing CF7 form:", error); 36 } 37 } 38 39 // Handle CF7 form submission 40 document.addEventListener("wpcf7beforesubmit", async (e) => { 41 try { 42 const token = await this.executeRecaptcha("contact_form"); 43 this.updateTokenInput(e.target, token); 44 } catch (error) { 45 console.error("CF7 submission error:", error); 46 } 47 }); 48 } 49 50 init() { 51 if (recaptchaVars.version === "v3") { 52 this.initV3(); 53 } else { 54 this.initV2(); 55 } 56 } 57 58 initV2() { 59 // Handle regular form submissions 60 this.forms.forEach((form) => { 61 form.addEventListener("submit", (e) => this.handleV2Submit(e)); 62 }); 63 64 // Handle WooCommerce checkout 65 if (this.wcForms.checkout) { 66 jQuery("form.checkout").on("checkout_place_order", () => this.validateV2Checkout()); 67 } 68 69 // Reset captcha after CF7 submissions 70 document.addEventListener("wpcf7submit", () => this.resetCaptcha()); 71 } 72 73 initV3() { 74 // Handle regular form submissions 75 this.forms.forEach((form) => { 76 form.addEventListener("submit", (e) => this.handleV3Submit(e)); 77 }); 78 79 // Handle WooCommerce checkout 80 if (this.wcForms.checkout) { 81 jQuery("form.checkout").on("checkout_place_order", () => this.validateV3Checkout()); 82 } 83 84 // Initialize tokens and refresh every 90 seconds 85 this.initializeV3Tokens(); 86 setInterval(() => this.initializeV3Tokens(), 90000); 87 } 88 89 handleV2Submit(e) { 90 const form = e.target; 91 if (form.classList.contains("checkout")) return; 92 93 const recaptchaResponse = form.querySelector('[name="g-recaptcha-response"]')?.value; 94 if (!recaptchaResponse) { 95 e.preventDefault(); 96 alert("Please complete the reCAPTCHA verification."); 97 } 98 } 99 100 async handleV3Submit(e) { 101 const form = e.target; 102 if (form.classList.contains("checkout") || form.classList.contains("wpcf7-form")) return; 103 104 e.preventDefault(); 105 106 try { 107 const action = this.getFormAction(form); 108 const token = await this.executeRecaptcha(action); 109 this.updateTokenInput(form, token); 110 111 // Handle form submission 112 if (typeof form.submit === "function") { 113 form.submit(); 114 } else { 115 const hiddenSubmit = document.createElement("input"); 116 hiddenSubmit.type = "submit"; 117 hiddenSubmit.style.display = "none"; 118 form.appendChild(hiddenSubmit); 119 hiddenSubmit.click(); 120 form.removeChild(hiddenSubmit); 121 } 122 } catch (error) { 123 console.error("reCAPTCHA error:", error); 124 } 125 } 126 127 validateV2Checkout() { 128 const response = this.wcForms.checkout?.querySelector('[name="g-recaptcha-response"]')?.value; 129 if (!response) { 130 alert("Please complete the reCAPTCHA verification."); 131 return false; 132 } 133 return true; 134 } 135 136 async validateV3Checkout() { 137 try { 138 const token = await this.executeRecaptcha("wc_checkout"); 139 this.updateTokenInput(this.wcForms.checkout, token); 140 return true; 141 } catch (error) { 142 console.error("reCAPTCHA error:", error); 143 return false;
144 } 145 } 146 147 getFormAction(form) { 148 if (form === this.wcForms.login) return "wc_login"; 149 if (form === this.wcForms.register) return "wc_register"; 150 if (form === this.wcForms.checkout) return "wc_checkout"; 151 if (form === this.wcForms.lostpassword) return "wc_lostpassword"; 152 if (form.classList.contains("wpcf7-form")) return "contact_form"; 153 return form.getAttribute("data-recaptcha-action") || "submit"; 154 } 155 156 async executeRecaptcha(action) { 157 await this.ensureRecaptchaLoaded(); 158 return grecaptcha.execute(recaptchaVars.siteKey, { action }); 159 } 160 161 ensureRecaptchaLoaded() { 162 return new Promise((resolve) => { 163 const checkRecaptcha = setInterval(() => { 164 if (window.grecaptcha?.execute) { 165 clearInterval(checkRecaptcha); 166 resolve(); 167 } 168 }, 100); 169 }); 170 } 171 172 updateTokenInput(form, token) { 173 let tokenInput = form.querySelector('[name="recaptcha_response"]'); 174 if (!tokenInput) { 175 tokenInput = document.createElement("input"); 176 tokenInput.type = "hidden"; 177 tokenInput.name = "recaptcha_response"; 178 form.appendChild(tokenInput); 179 } 180 tokenInput.value = token; 181 } 182 183 async initializeV3Tokens() { 184 // Initialize regular forms 185 for (const form of this.forms) { 186 try { 187 const action = this.getFormAction(form); 188 const token = await this.executeRecaptcha(action); 189 this.updateTokenInput(form, token); 190 } catch (error) { 191 console.error("Error setting initial token for form:", error); 192 } 193 } 194 195 // Initialize WooCommerce forms 196 for (const [formType, form] of Object.entries(this.wcForms)) { 197 if (form) { 198 try { 199 const token = await this.executeRecaptcha(`wc_${formType}`); 200 this.updateTokenInput(form, token); 201 } catch (error) { 202 console.error(`Error setting initial token for ${formType}:`, error); 203 } 204 } 205 } 206 } 207 208 resetCaptcha() { 209 if (typeof grecaptcha !== "undefined" && recaptchaVars.version === "v2") { 210 grecaptcha.reset(); 211 } 212 } 213} 214 215// Initialize the handler 216let handler = null; 217 218const initRecaptcha = () => { 219 if (window.grecaptcha?.execute) { 220 handler = new RecaptchaHandler(); 221 } else { 222 setTimeout(initRecaptcha, 100); 223 } 224}; 225 226window.addEventListener("load", initRecaptcha); 227 228// Handle WooCommerce checkout updates 229if (typeof jQuery !== "undefined") { 230 jQuery(document.body).on("updated_checkout", () => { 231 if (recaptchaVars.version === "v3") { 232 handler?.initializeV3Tokens(); 233 } 234 }); 235}
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.