PageSourceSearch

https://bestchinesemedicines.com/wp-content/plugins/simple-cloudfl…/js/integrations/woocommerce.js?ver=2.2

js bestchinesemedicines.com collected 2026-10-02 11:37:12 UTC 10,043 bytes, 268 lines download raw bytes

1/* Woo Checkout */
2( function () {
3
4    var WIDGET_ID = 'cf-turnstile-woo-checkout';
5
6    // Prefer the widget inside the checkout form, as Divi can leave stray copies
7    function cfturnstileWooWidget() {
8        return document.querySelector( 'form.checkout #' + WIDGET_ID ) || document.getElementById( WIDGET_ID );
9    }
10
11    function cfturnstileWooOnReady( fn ) {
12        if ( document.readyState === 'loading' ) {
13            document.addEventListener( 'DOMContentLoaded', fn );
14        } else {
15            fn();
16        }
17    }
18
19    function cfturnstileWooClicked( e, selector ) {
20        return !!( e.target && e.target.closest && e.target.closest( selector ) );
21    }
22
23    // Explicit render ignores data-*-callback, so pass the options in
24    function cfturnstileWooOpts( target ) {
25        return ( typeof window.cfturnstileOpts === 'function' ) ? window.cfturnstileOpts( target ) : {};
26    }
27
28    // Rendered but no token yet. Checks every input, as turnstile.remove() can leave an empty one behind
29    function cfturnstileWooAwaitingToken( el ) {
30        var inputs = el.querySelectorAll( 'input[name="cf-turnstile-response"]' );
31        for ( var i = 0; i < inputs.length; i++ ) {
32            if ( inputs[ i ].value ) {
33                return false;
34            }
35        }
36        return inputs.length > 0;
37    }
38
39    /* Give the classic checkout widget a fresh token */
40    function turnstileWooCheckoutReset() {
41        if ( typeof turnstile === 'undefined' ) {
42            return;
43        }
44
45        var el = cfturnstileWooWidget();
46        if ( !el ) {
47            return;
48        }
49
50        // Empty container, render a new widget
51        if ( !el.firstElementChild ) {
52            try { turnstile.render( el, cfturnstileWooOpts( el ) ); } catch ( e ) {}
53            return;
54        }
55
56        // No token yet, so nothing to clear
57        if ( cfturnstileWooAwaitingToken( el ) ) {
58            return;
59        }
60
61        // Otherwise reset in place
62        try {
63            turnstile.reset( el );
64            return;
65        } catch ( e ) {}
66
67        // reset() failed, so rebuild it
68        try { turnstile.remove( el ); } catch ( e ) {}
69        try { turnstile.render( el, cfturnstileWooOpts( el ) ); } catch ( e ) {}
70    }
71
72    /* "Show login" toggle: rebuild the login widget once the panel is open */
73    document.addEventListener( 'click', function ( e ) {
74        if ( !cfturnstileWooClicked( e, '.showlogin, .show-login, .e-show-login, .woocommerce-form-login-toggle a' ) ) {
75            return;
76        }
77        setTimeout( function () {
78            if ( typeof turnstile === 'undefined' ) {
79                return;
80            }
81            try { turnstile.remove( '.sct-woocommerce-login' ); } catch ( err ) {}
82            try { turnstile.render( '.sct-woocommerce-login', cfturnstileWooOpts( '.sct-woocommerce-login' ) ); } catch ( err ) {}
83        }, 250 );
84    } );
85
86    /* Classic checkout: keep the widget valid across fragment refreshes */
87    function cfturnstileWooRun() {
88
89        var $ = window.jQuery;
90
91        $( document ).ready( function () {
92
93            var attempted = false;
94
95            function hasCheckoutError() {
96                return !!document.querySelector( '.woocommerce-error' );
97            }
98
99            // Only reset after a real submission attempt, not on every checkout refresh.
100            $( document.body ).on( 'submit', 'form.checkout', function () {
101                attempted = true;
102            } );
103
104            // Error already showing on page load
105            if ( hasCheckoutError() ) {
106                setTimeout( turnstileWooCheckoutReset, 50 );
107            }
108
109            $( document.body ).on( 'update_checkout updated_checkout applied_coupon_in_checkout removed_coupon_in_checkout', function () {
110                var el = cfturnstileWooWidget();
111
112                // Container replaced or emptied, re-render
113                if ( !el || !el.firstElementChild ) {
114                    setTimeout( turnstileWooCheckoutReset, 300 );
115                    return;
116                }
117
118                // Failed submit, clear the used token
119                if ( attempted && hasCheckoutError() ) {
120                    setTimeout( turnstileWooCheckoutReset, 300 );
121                    attempted = false;
122                }
123            } );
124
125            // Fired when the AJAX checkout submission comes back with an error.
126            $( document.body ).on( 'checkout_error', function () {
127                setTimeout( turnstileWooCheckoutReset, 500 );
128                attempted = false;
129            } );
130        } );
131    }
132
133    /* Woo Checkout Block */
134    function cfturnstileWooBlockRun() {
135
136        function setExtensionData( token ) {
137            var dispatch = wp.data.dispatch( 'wc/store/checkout' );
138            if ( !dispatch ) {
139                return;
140            }
141            if ( typeof dispatch.setExtensionData === 'function' ) {
142                dispatch.setExtensionData( 'simple-cloudflare-turnstile', { token: token } );
143            } else if ( typeof dispatch.__internalSetExtensionData === 'function' ) {
144                dispatch.__internalSetExtensionData( 'simple-cloudflare-turnstile', { token: token } );
145            }
146        }
147
148        var widgetId = null;
149        var renderedEl = null;
150        var submitted = false;
151
152        function renderBlockWidget() {
153            // API may still be loading, the subscription below retries
154            if ( typeof turnstile === 'undefined' ) {
155                return;
156            }
157
158            var el = cfturnstileWooWidget();
159            if ( !el ) {
160                return;
161            }
162
163            // Already rendered into this element, reset in place
164            if ( el === renderedEl && el.firstElementChild ) {
165                // No token yet, so nothing to clear
166                if ( cfturnstileWooAwaitingToken( el ) ) {
167                    return;
168                }
169                try {
170                    turnstile.reset( el );
171                    setExtensionData( '' );
172                    return;
173                } catch ( e ) {}
174            }
175
176            // Woo can swap the container for a copy, so drop the old widget by id
177            if ( widgetId !== null ) {
178                try { turnstile.remove( widgetId ); } catch ( e ) {}
179                widgetId = null;
180            }
181            try { turnstile.remove( el ); } catch ( e ) {}
182
183            try {
184                widgetId = turnstile.render( el, {
185                    sitekey: el.dataset.sitekey,
186                    appearance: el.dataset.appearance || 'always',
187                    callback: setExtensionData,
188                    'expired-callback': function () { setExtensionData( '' ); }
189                } );
190                renderedEl = el;
191            } catch ( e ) {}
192        }
193
194        // The order was sent but failed, possibly at the gateway after it (e.g. 3DS), so the token may be spent
195        function resetAfterFailedSubmit() {
196            var checkout = wp.data.select( 'wc/store/checkout' );
197            if ( !checkout || typeof checkout.isProcessing !== 'function' || typeof checkout.hasError !== 'function' ) {
198                return;
199            }
200            if ( checkout.isProcessing() ) {
201                submitted = true;
202                return;
203            }
204            // Gateway still working, e.g. 3DS
205            if ( !submitted || ( checkout.isAfterProcessing() && !checkout.hasError() ) ) {
206                return;
207            }
208            submitted = false;
209            if ( checkout.hasError() || checkout.isIdle() ) {
210                renderBlockWidget();
211            }
212        }
213
214        // Render when the widget is missing or Woo replaced its container
215        function onStoreChange() {
216            var el = cfturnstileWooWidget();
217            if ( el && ( el !== renderedEl || !el.firstElementChild ) ) {
218                renderBlockWidget();
219            }
220            resetAfterFailedSubmit();
221        }
222        wp.data.subscribe( onStoreChange, 'wc/store/cart' );
223        wp.data.subscribe( onStoreChange, 'wc/store/checkout' );
224
225        renderBlockWidget();
226    }
227
228    // Run fn once ready() passes, as a delay-JS optimizer only loads our dependencies on the first interaction
229    function cfturnstileWooWhen( ready, fn ) {
230        if ( ready() ) {
231            fn();
232            return;
233        }
234        var tries = 0;
235        var wait = setInterval( function () {
236            if ( ready() ) {
237                clearInterval( wait );
238                fn();
239            } else if ( ++tries > 6000 ) { // ~10 min safety cap
240                clearInterval( wait );
241            }
242        }, 100 );
243    }
244
245    // Block checkout only, the classic checkout uses the same widget id
246    cfturnstileWooOnReady( function () {
247        if ( document.querySelector( '.wp-block-woocommerce-checkout, .wc-block-checkout' ) ) {
248            cfturnstileWooWhen( function () {
249                return typeof wp !== 'undefined' && !!wp.data && !!wp.data.select( 'wc/store/checkout' );
250            }, cfturnstileWooBlockRun );
251        }
252    } );
253
254    // Classic checkout: queue the widget if nothing else did, so it does not depend on Woo's jQuery events
255    cfturnstileWooOnReady( function () {
256        var el = document.querySelector( 'form.checkout #' + WIDGET_ID );
257        var queue = window.cfturnstileQueue = window.cfturnstileQueue || [];
258        if ( el && !el.firstElementChild && queue.indexOf( '-woo-checkout' ) === -1 ) {
259            queue.push( '-woo-checkout' );
260            if ( typeof window.cfturnstileRender === 'function' ) {
261                window.cfturnstileRender();
262            }
263        }
264    } );
265
266    cfturnstileWooWhen( function () { return typeof window.jQuery !== 'undefined'; }, cfturnstileWooRun );
267
268} )();

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.