1/* Woo Checkout */ 2jQuery( document ).ready(function() { 3 var cfturnstileWooCheckoutAttempted = false; 4 5 // Track actual submission attempts so we don't reset on every checkout refresh. 6 jQuery( document.body ).on( 'submit', 'form.checkout', function() { 7 cfturnstileWooCheckoutAttempted = true; 8 }); 9 10 // If the page loads with an existing checkout error force a reset so the next submission has a fresh token. 11 if ( jQuery('.woocommerce-error, .woocommerce-NoticeGroup-checkout .woocommerce-error').length ) { 12 setTimeout( turnstileWooCheckoutReset, 50 ); 13 } 14 15 jQuery( document.body ).on( 'update_checkout updated_checkout applied_coupon_in_checkout removed_coupon_in_checkout', function() { 16 // Re-render if the widget container was replaced/emptied. 17 if ( jQuery('#cf-turnstile-woo-checkout').is(':empty') ) { 18 turnstileWooCheckoutReset(); 19 return; 20 } 21 22 // After a failed submit, Woo will typically refresh the checkout fragments. 23 // Reset here (only after an attempted submit) to avoid the stale/used token issue. 24 if ( cfturnstileWooCheckoutAttempted && jQuery('.woocommerce-error, .woocommerce-NoticeGroup-checkout .woocommerce-error').length ) { 25 setTimeout( turnstileWooCheckoutReset, 50 ); 26 cfturnstileWooCheckoutAttempted = false; 27 } 28 }); 29 30 // Woo triggers this when the AJAX checkout submission returns an error. 31 jQuery( document.body ).on( 'checkout_error', function() { 32 setTimeout( turnstileWooCheckoutReset, 50 ); 33 cfturnstileWooCheckoutAttempted = false; 34 }); 35}); 36function turnstileWooCheckoutReset() { 37 if ( typeof turnstile === 'undefined' ) { 38 return; 39 } 40 41 var el = document.getElementById('cf-turnstile-woo-checkout'); 42 if ( !el ) { 43 return; 44 } 45 46 // If Woo replaced the container and it's now empty, render a fresh widget. 47 if ( !el.innerHTML || el.innerHTML.trim() === '' ) { 48 try { 49 turnstile.render(el); 50 } catch (e) { 51 try { turnstile.render('#cf-turnstile-woo-checkout'); } catch (e2) {} 52 } 53 return; 54 } 55 56 // Preferred: reset the existing widget (clears the used/expired token). 57 try { 58 if ( typeof turnstile.reset === 'function' ) { 59 turnstile.reset(el); 60 return; 61 } 62 } catch (e) {} 63 64 // Fallback: remove + render. 65 try { 66 turnstile.remove(el); 67 } catch (e) { 68 try { turnstile.remove('#cf-turnstile-woo-checkout'); } catch (e2) {} 69 } 70 try { 71 turnstile.render(el); 72 } catch (e) { 73 try { turnstile.render('#cf-turnstile-woo-checkout'); } catch (e2) {} 74 } 75} 76/* On click ".checkout .showlogin" link re-render */ 77jQuery('.showlogin').on('click', function() { 78 turnstile.remove('.sct-woocommerce-login'); 79 turnstile.render('.sct-woocommerce-login'); 80}); 81 82/* Woo Checkout Block */ 83document.addEventListener('DOMContentLoaded', function() { 84 if (typeof wp !== 'undefined' && wp.data && typeof turnstile !== 'undefined') { 85 86 function setTurnstileExtensionData(token) { 87 var dispatch = wp.data.dispatch('wc/store/checkout'); 88 if (typeof dispatch.setExtensionData === 'function') { 89 dispatch.setExtensionData('simple-cloudflare-turnstile', { token: token }); 90 } else if (typeof dispatch.__internalSetExtensionData === 'function') { 91 dispatch.__internalSetExtensionData('simple-cloudflare-turnstile', { token: token }); 92 } 93 } 94 95 function cfturnstileWooBlockCheckoutRender() { 96 var turnstileItem = document.getElementById('cf-turnstile-woo-checkout'); 97 if (!turnstileItem) return; 98 99 // If already initialized by us, try reset to preserve state but clear token 100 if (turnstileItem.getAttribute('data-sct-init') === 'true' && turnstileItem.hasChildNodes()) { 101 try { 102 turnstile.reset(turnstileItem); 103 setTurnstileExtensionData(''); 104 return; 105 } catch (e) {} 106 } 107 108 // Ensure any existing widget (auto-rendered or otherwise) is removed 109 try { turnstile.remove(turnstileItem); } catch (e) {} 110 111 try { 112 turnstile.render(turnstileItem, { 113 sitekey: turnstileItem.dataset.sitekey, 114 callback: setTurnstileExtensionData, 115 'expired-callback': function() { setTurnstileExtensionData(''); } 116 }); 117 turnstileItem.setAttribute('data-sct-init', 'true'); 118 } catch (e) {} 119 } 120 121 // Re-render Turnstile after the Place order button is clicked 122 var cfturnstileWooBlockClickTimer = null; 123 jQuery(document.body).on('click', '.wc-block-components-checkout-place-order-button', function() { 124 if (cfturnstileWooBlockClickTimer) { 125 clearTimeout(cfturnstileWooBlockClickTimer); 126 } 127 cfturnstileWooBlockClickTimer = setTimeout(function() { 128 cfturnstileWooBlockCheckoutRender(); 129 }, 1250); 130 }); 131 132 // Render Turnstile when the checkout data is updated and the widget is not present or not initialized 133 var unsubscribe = wp.data.subscribe(function() { 134 const turnstileItem = document.getElementById('cf-turnstile-woo-checkout'); 135 if (turnstileItem && (turnstileItem.innerHTML.trim() === '' || turnstileItem.getAttribute('data-sct-init') !== 'true')) { 136 cfturnstileWooBlockCheckoutRender(); 137 } 138 }, 'wc/store/cart'); 139 } 140});
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.