PageSourceSearch

https://www.internetmarketeers.nl/wp-content/plugins/studiocart-pro/public/js/ncs-cart-public.js

js internetmarketeers.nl collected 2026-10-06 18:25:38 UTC 104,871 bytes, 2,229 lines download raw bytes

1(function($) {
2    'use strict';
3
4    /**
5     * All of the code for your public-facing JavaScript source
6     * should reside in this file.
7     *
8     * Note: It has been assumed you will write jQuery code here, so the
9     * $ function reference has been prepared for usage within the scope
10     * of this function.
11     *
12     * This enables you to define handlers, for when the DOM is ready:
13     *
14     * $(function() {
15     *
16     * });
17     *
18     * When the window is loaded:
19     *
20     * $( window ).load(function() {
21     *
22     * });
23     *
24     * ...and/or other possibilities.
25     *
26     * Ideally, it is not considered best practise to attach more than a
27     * single DOM-ready or window-load handler for a particular page.
28     * Although scripts in the WordPress core, Plugins and Themes may be
29     * practising this, we should strive to set a better example in our own work.
30     */
31    var regExPhone = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/,
32        regExEmail = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/,
33        states = sc_country_select_states.sc_states,
34        sc_country = sc_country_select_states.sc_country,
35        $select_state,
36        $select_country;
37
38    $('.sc-open-modal').click(function (e) {
39        e.preventDefault();
40        var modal = $(this).data('item-id');
41        $('#' + modal).addClass('opened');
42    });
43    
44    $('.closemodal').click(function (e) {
45        e.preventDefault();
46        var el = $(this).closest('.opened');
47        el.removeClass('opened');
48    });
49
50    /* <fs_premium_only> */
51
52    /* It will redirect if anyone clicked on link before ready */
53    $(document).on('click', 'a[href*="sc-upsell-offer=yes"]', function(e) {
54
55        e.preventDefault();
56
57        if ('undefined' !== typeof studiocart.is_preview && '1' == studiocart.is_preview) {
58            e.stopPropagation();
59            return;
60        }
61
62        //window.location.href = studiocart.upsell_accept; 
63
64        return false;
65    });
66
67    $(document).on('click', 'a[href*="sc-upsell-offer=no"]', function(e) {
68
69        e.preventDefault();
70
71        if ('undefined' !== typeof studiocart.is_preview && '1' == studiocart.is_preview) {
72            e.stopPropagation();
73            return;
74        }
75
76        window.location.href = studiocart.upsell_decline;
77
78        return false;
79    });
80
81    /* Once the link is ready this will work to stop conditional propogation*/
82    $(document).on('click', '.sc-accept-upsell-link, .sc-decline-upsell-link', function(e) {
83
84        if ('undefined' !== typeof studiocart.is_preview && '1' == studiocart.is_preview) {
85            e.preventDefault();
86            e.stopPropagation();
87            return false;
88        }
89
90        if ($(this).hasClass('sc-accept-upsell-link')) {
91
92            $(this).css({ "pointer-events": "none", 'opacity': 0.85 }).text(sc_translate_frontend.processing + '...');
93            if (typeof studiocart.pay_method !== 'undefined' && studiocart.pay_method != 'stripe' && studiocart.pay_method != 'cod') {
94                $(this).trigger('studiocart/upsell/accept/' + studiocart.pay_method);
95                return false;
96            }
97
98            var url = $(this).attr('href'),
99                noUrl = $('.sc-decline-upsell-link').attr('href'),
100                urlVar = 'sc-oto',
101                data = {
102                    'action': 'sc_process_upsell',
103                    'sc-order': studiocart.sc_order,
104                    'sc-nonce': studiocart.sc_nonce,
105                    'step': studiocart.step,
106                };
107
108            // flag for downsells
109            if ('undefined' !== typeof studiocart.is_downsell && '1' == studiocart.is_downsell) {
110                data['downsell'] = 1;
111                urlVar = 'sc-oto-2'
112            }
113
114            $.post(studiocart.ajax, data, function(order_id) {
115                if (!isNaN(order_id)) { // order created
116                    url += '&' + urlVar + '=' + order_id;
117                    window.location.href = url;
118                    return false;
119                } else {
120
121                    // if card was declined or other error, alert and redirect to decline url
122                    var error = JSON.parse(order_id);
123                    if ('undefined' !== typeof error.message) {
124                        alert(error.message);
125                        window.location.href = noUrl;
126                    }
127
128                    // Otherwise try to reauthenticate card in confirmCardPayment
129                    var stripe = Stripe(stripe_key[0]),
130                        intent_id = error.intentId;
131
132                    stripe.confirmCardPayment(error.clientSecret, {
133                        payment_method: error.paymentMethod
134                    }).then(function(result) {
135                        if (result.error) {
136                            // Display error.message in your UI.
137                            alert(result.error.message);
138                            window.location.href = noUrl;
139                        } else {
140                            var data = {
141                                'action': 'save_order_to_db',
142                                'sc-order': studiocart.sc_order,
143                                'sc-nonce': studiocart.sc_nonce,
144                                'intent_id': intent_id,
145                                'intent_status': result.paymentIntent.status
146                            };
147
148                            // flag for downsells
149                            if ('undefined' !== typeof studiocart.is_downsell && '1' == studiocart.is_downsell) {
150                                data['downsell'] = 1;
151                                urlVar = 'sc-oto-2'
152                            }
153
154                            $.post(studiocart.ajax, data, function(order_id) {
155                                if (!isNaN(order_id)) {
156                                    url += '&' + urlVar + '=' + order_id;
157                                    window.location.href = url;
158                                    return false;
159                                } else {
160                                    alert(order_id);
161                                    window.location.href = noUrl;
162                                }
163                            });
164                        }
165                    });
166                    return false;
167                }
168            });
169            return false;
170
171        }
172
173    });
174
175
176
177    /* </fs_premium_only> */
178    function key_value_pair_selectize(json_data) {
179        let format_data = [];
180        $.each(json_data, function(i, item) {
181            let json_state = { 'state_key': i, 'state_value': item };
182            format_data.push(json_state);
183        });
184        return format_data;
185    }
186
187    function isValidPhonenumber(value) {
188        return (/^\d{7,}$/).test(value.replace(/[\s()+\-\.]|ext/gi, ''));
189    }
190
191    function isValidPassword(value) {
192        var lowerCaseLetters = /[a-z]/g;
193        if (!value.match(lowerCaseLetters)) {
194            return false;
195        }
196
197        // Validate numbers
198        var numbers = /[0-9]/g;
199        if (!value.match(numbers)) {
200            return false;
201        }
202
203        // Validate length
204        if (!value.length >= 8) {
205            return false;
206        }
207        return true;
208    }
209
210    function country_selectize() {
211        $('.sc-form-wrap').each(function(){
212            let current_country;
213            let current_state;
214
215            let form = $(this);
216            let form_id = '#'+form.attr('id');
217
218            if ($('#state', form_id).length) {
219                current_state = $('#state', form_id).val();
220            }
221                
222            if ($('#country', form_id).length < 1) {
223                current_country = sc_country;
224            } else {
225                current_country = $('#country', form_id).val();
226                $('#country', form_id).selectize()[0].selectize.destroy();
227                $select_country = $('#country', form_id).selectize({
228                    onChange: function(value) {
229                        if (!value.length) return;
230                        if ($('#state', form_id).length > 0) {
231                            $('#state', form_id).selectize()[0].selectize.clearOptions();
232                            $('#state', form_id).selectize()[0].selectize.destroy();
233                            let new_state_option = key_value_pair_selectize(states[value]);
234                            let state_placeholder = $('#state', form_id).attr('placeholder');
235                            let $required = "";
236                            if (jQuery('#state', form_id).hasClass('required')) {
237                                $required = "required";
238                            }
239                            if ($('#state option', form_id).length > 0) {
240                                state_placeholder = $('#state option[value=""]', form_id).text();
241                            }
242                            if (new_state_option.length === 0) {
243                                $('#state', form_id).replaceWith('<input id="state" name="state" type="text" class="form-control ' + $required + '" placeholder="' + state_placeholder + '" value="" aria-label="State">');
244                            } else {
245                                $('#state', form_id).replaceWith('<select id="state" name="state" class="form-control ' + $required + '" style="display: block;"><option value="" selected>' + state_placeholder + '</option></select>');
246                                $select_state = $('#state', form_id).selectize({
247                                    valueField: 'state_key',
248                                    labelField: 'state_value',
249                                    searchField: 'state_value',
250                                    options: new_state_option,
251                                    onChange: function(value) {
252                                        if (value.length >= 1) {
253                                            var $el = $('#state', form_id);
254                                            $el.removeClass('invalid').closest('.form-group').find('.error').remove();
255                                            $el.closest('.form-group').find('.selectize-input').removeClass('invalid');
256                                        }
257                                    }
258                                });
259                            }
260                        }
261
262                    }
263                });
264                $select_country[0].selectize.setValue(current_country);
265            }
266            if ($('#state', form_id).length > 0) {
267                let state_option = key_value_pair_selectize(states[current_country]);
268                if (state_option.length === 0) {
269                    $('#state', form_id).replaceWith('<input id="state" name="state" type="text" class="form-control  required" placeholder="State" value="'+current_state
269+'" aria-label="State">');
270                } else {
271                    $select_state = $('#state', form_id).selectize({
272                        valueField: 'state_key',
273                        labelField: 'state_value',
274                        searchField: 'state_value',
275                        options: state_option
276                    });
277                    $select_state[0].selectize.setValue(current_state);
278                }
279            }
280        });
281    }
282
283    $(document).ready(function() {
284
285        var originalText;
286
287        var update_form = async function(wrap_id){
288
289            wrap_id = wrap_id.replace('#', '');
290
291            $(".sc-stripe-express",'#'+wrap_id).hide();
292
293            var $item = $('input[name=sc_product_option]:checked', '#'+wrap_id);
294            if(!$item.closest('.item').hasClass('sc-selected')) {
295                $('input[name=sc_product_option]', '#'+wrap_id).each(function(){
296                    $(this).closest('.item').removeClass('sc-selected');
297                });
298                $item.closest('.item').addClass('sc-selected');
299            }
300
301            let form = document.getElementById(wrap_id);
302            form = form.getElementsByTagName('form')[0];
303
304            var paramObj = new FormData(form);
305            paramObj.set("action", "sc_update_cart_amount");
306
307            if (typeof sc_tax_settings !== 'undefined' && $('select[name="country"]', '#'+wrap_id).val() != '') {
308                //$('#sc_card_button').addClass('running').attr("disabled", true);
309                var tax_obj = {},
310                    tax_rate_data = {};
311                tax_obj.country = $('select[name="country"]', '#'+wrap_id).val() ? $('select[name="country"]', '#'+wrap_id).val() : "";
312                tax_obj.city = $('input[name="city"]', '#'+wrap_id).val() ? $('input[name="city"]', '#'+wrap_id).val() : "";
313                tax_obj.state = $('select[name="state"]', '#'+wrap_id).val() ? $('select[name="state"]', '#'+wrap_id).val() : "";
314                tax_obj.zip = $('input[name="zip"]', '#'+wrap_id).val() ? $('input[name="zip"]', '#'+wrap_id).val() : "";
315                tax_obj.vat_number = $('input[name="vat-number"]', '#'+wrap_id).val() ? $('input[name="vat-number"]', '#'+wrap_id).val() : "";
316                tax_obj.nonce = sc_tax_settings.nonce;
317                tax_obj.action = 'get_match_tax_rate';
318                $.ajax({
319                    type: "post",
320                    dataType: "json",
321                    url: studiocart.ajax,
322                    data: tax_obj,
323                    success: function(response) {
324                        tax_rate_data = response.rates;
325                        $('.vat_container', '#'+wrap_id).hide();
326                        let vat_error = "Invalid VAT Number";
327                        $('#vat_number', '#'+wrap_id).removeClass('valid invalid');
328                        $('#vat_number', '#'+wrap_id).parent().find('.error').remove();
329                        if (!response.is_valid_vat) {
330                            $('#vat_number', '#'+wrap_id).addClass('invalid');
331                            if (response.vat_error != "") {
332                                vat_error = response.vat_error;
333                            }
334                            if ($('#vat_number', '#'+wrap_id).parent().find('.error').length == 0) {
335                                $('#vat_number', '#'+wrap_id).parent().append('<div class="error">' + vat_error + '</div>')
336                            } else {
337                                $('#vat_number', '#'+wrap_id).parent().find('.error').html(vat_error);
338                            }
339                        } else if(tax_obj.vat_number != '') {
340                            $('#vat_number', '#'+wrap_id).addClass('valid');
341                        }
342                        if (response.is_vat) {
343                            $('.vat_container', '#'+wrap_id).show();
344                        }
345                        
346                    }
347                });
348            }
349
350            try {
351				const response = await fetch(studiocart.ajax, {
352					method: 'POST',
353					body:paramObj
354				});
355				if (response.ok) {
356					const resp = await response.json();
357					if (resp.order_summary_items) {
358                        var container = $('#'+wrap_id).find('.summary-items'),
359                            totalContainer = $('#'+wrap_id).find('.total');
360
361                        container.empty();
362                        totalContainer.empty();
363
364                        $('input[name="sc_amount"]', '#'+wrap_id ).val(resp.total);
365
366                        if (resp.total == 0 && typeof resp.sub_summary == 'undefined') {
367                            $('.pay-info', '#'+wrap_id).hide();
368                        } else {
369                            $('.pay-info', '#'+wrap_id).show();
370                        }
371
372                        if(resp.total != 0){
373                            $(".sc-stripe-express",'#'+wrap_id).show();
374                        }
375                        
376						if(resp.order_summary_items.length === 0) {
377                            $('.sc-stripe-express', '#'+wrap_id).hide();
378                            $('#sc_card_button', '#'+wrap_id).hide();
379                            container.append('<div class="item"><span class="sc-label">'+resp.empty+'</span></div>');
380                        } else {
381                            $('#sc_card_button', '#'+wrap_id).show();
382                            resp.order_summary_items.forEach(item => {
383                                if(Number(item.quantity) > 1) {
384                                    item.name += ' x ' + item.quantity;
385                                }
386                                container.append('<div class="item '+item.type+'"><span class="sc-label">'+item.name+'</span><span class="price">'+item.subtotal+'</span></div>');
387                            });
388
389                            totalContainer.append(resp.total_html);
390
391                            if (typeof resp.sub_summary != 'undefined') {
392                                totalContainer.append('<small>' + resp.sub_summary + '</small>');
393                            }
394                        }
395					}
396                    initialExpressPayment('#'+wrap_id);
397					return resp.success;
398				} else {
399					alert('Something went wrong.')
400				}
401			} catch (error) {
402				alert('Something went wrong.')
403			}
404            return false;
405
406        };
407
408        $(document).on('click', ".studiocart .coupon-code input[type='button']", function(e) {
409            e.preventDefault();
410            var form = '#'+$(this).closest('form').parent().attr('id');
411            $(this).attr('disabled', 'disabled');
412            clear_coupon(form);
413            if ($('#discount-code', form).val() == '') {
414                $(".coupon-code input[type='button']", form).removeAttr('disabled');
415            } else {
416                try_coupon($('#discount-code', form).val(), form);
417            }
418        });
419        
420        $(document).on('change', "#sc-credit", function() {
421            var form = '#'+$(this).closest('form').parent().attr('id');
422            if(!$(this).is(':checked')){
423                clear_coupon(form);
424                $(".coupon-code input[type='button']", form).removeAttr('disabled');
425            } else {
426                try_coupon('sc-credit', form);
427            }
428        });
429
430        $(document).on('click', ".sc-password-toggle", function() {
431            var field = $(this).parent().prev('.sc-password');
432            if ($(this).is(':checked')) {
433                field.attr('type', 'text');
434            } else {
435                field.attr('type', 'password');
436            }
437        });
438
439        $(document).on('change', 'input[name="pay-method"]', function() {
440            var form = '#'+$(this).closest('form').parent().attr('id');
441            togglePayMethods(form);
442        });
443
444        $(document).on('click', '#sc-coupon-toggle', function() {
445            var form = '#'+$(this).closest('form').parent().attr('id');
446            $('#sc-coupon-form', form).fadeToggle();
447            return false;
448        });
449
450        //function address_fields() {
451
452        if (typeof sc_popup == 'undefined' || !sc_popup.is_popup || sc_popup.is_popup == "false") {
453            country_selectize();
454        } else {
455            jQuery(document).on('elementor/popup/show', () => {
456                country_selectize();
457            });
458        }
459        //address_fields();
460
461        function togglePayMethods(form) {
462            var method = $('[name="pay-method"]:checked', form).val();
463            if (method != 'stripe') {
464                $('.sc-stripe', form).fadeOut();
465                //$('#paypal-button-container').fadeIn();
466            } else {
467                $('.sc-stripe', form).fadeIn();
468                $('#paypal-button-container', form).fadeOut();
469            }
470        }
471
472        function numberWithThousandsSep(x) {
473            var parts = x.toString().split(".");
474            parts[0] = parts[0].replace(/\B(?=(\d{3)+(?!\d))/g, sc_currency.thousep);
475            return parts.join(sc_currency.decisep);
476        }
477
478        function format_price(amt) {
479            var price;
480
481            // left positioned currency
482            if (sc_currency.position != 'right' && sc_currency.position != 'right-space') {
483                price = sc_currency.symbol;
484                if (sc_currency.position == 'left-space') {
485                    // with space
486                    price += ' ';
487                }
488
489                // format price
490                price += numberWithThousandsSep(parseFloat(amt).toFixed(sc_currency.decinum));
491            }
492
493            // right positioned currency
494            if (sc_currency.position == 'right' || sc_currency.position == 'right-space') {
495
496                // format price
497                price = numberWithThousandsSep(parseFloat(amt).toFixed(sc_currency.decinum));
498
499                if (sc_currency.position == 'right-space') {
500
501                    // with space
502                    price += ' ';
503
504                }
505
506                // left positioned currency
507                price += sc_currency.symbol;
508
509            }
510
511            // return price
512            return price;
513        }
514
515        $(document).on('change', 'input[name=sc_product_option]', function() {
516            var form = '#'+$(this).closest('form').parent().attr('id');
517            update_pwyw(form);
518        });
519
520        function update_pwyw(form) {
521            var dataType = $('input[name=sc_product_option]:checked', form).attr('data-val');
522            var dataPrice = $('input[name=sc_product_option]:checked', form).attr('data-price');
523            var id = $('input[name=sc_product_option]:checked', form).attr('id');
524            var value = $('input[name=sc_product_option]:checked', form).val();
525            $('.pwyw-input', form).fadeOut();
526            if (dataType && dataType == 'pwyw') {
527                $('#' + id, form).data('price', dataPrice);
528                $('#pwyw-amount-input-' + value, form).val(dataPrice);
529                $('#pwyw-input-block-' + value, form).fadeIn().focus();
530            } else {
531                $('#pwyw-input-block-' + value, form).fadeOut();
532            }
533        }
534
535         // Debounce function to limit how often the function runs
536         function debounce(func, delay) {
537            let debounceTimer;
538            return function() {
539                const context = this;
540                const args = arguments;
541                clearTimeout(debounceTimer);
542                debounceTimer = setTimeout(() => func.apply(context, args), delay);
543            };
544        }
545
546        $(document).on('change blur focusout', 'input[name^="pwyw_amount"]', function() {
547            var value = $(this).val();
548            var minvalue = $(this).attr('min');
549            var id = $('input[name=sc_product_option]:checked').attr('id');
550            var form = $(this).closest('form').parent().attr('id');
551            if (parseFloat(value) < parseFloat(minvalue)) {
552                $(this).addClass('invalid');
553                if ($(this).closest('.item').find('.error').length == 0)
554                    $(this).closest('.item').append('<div class="error">Please enter an amount greater than or equal to ' + format_price(parseFloat(minvalue).toFixed(2)) + '</div>')
555            }
556            if (value) {
557                $(this).closest('.item').remove('.error');
558                $("#" + id).attr('data-price', value);
559                $("#" + id).data('price', value);
560                $("#" + id).parent().find('.price').html('<span class="sc-Price-currencySymbol">$</span>' + parseFloat($("#" + id).attr('data-price')).toFixed(2));
561                update_form(form);
562            }
563        });
564
565        $(document).on('input', 'input[name^="pwyw_amount"]', debounce(function() {
566            var form = '#' + $(this).closest('form').parent().attr('id');
567            // Check Express payment 
568            initialExpressPayment(form);
569        }, 1000)); 
570
571        $(document).on('change', '#sc_qty, .sc_qty, input[name=sc_product_option], #sc-orderbump, .sc_orderbump, input[data-scq-price],select[name="country"], select[name="state"], input[name="city"], input[name="zip"], input[name="vat-number"]', function() {
572            var form = $(this).closest('form').parent().attr('id');
573            update_form(form);
574        });
575
576        $("#discount-code").keydown(function() {
577            $("#coupon-status").text('').hide();
578        });
579
580        $(".coupon-code.applied").on("click", "button.coupon", function(e) {
581            var form = $(this).closest('form').parent();
582            e.preventDefault();
583            form.find(".coupon-code").show();
584        });
585
586        function clear_coupon(form) {
587            $('.coupon-code.applied, .cart-discount', form).hide();
588            $('#sc-coupon-id', form).val('').removeData('type', 'amount', 'plans');
589            $("#coupon-status", form).delay(3000).fadeOut();
590            $('#sc-coupon-id', form).data('type')
591
592            $('#sc-payment-form .products .item', form).each(function() {
593                var $item = $(this).find('input[type="radio"]'),
594                    price = $item.data('og-price');
595
596                if (typeof $item.data('og-price') !== 'undefined') {
597                    $(this).find('.price').html(format_price(price));
598                    $item.data('price', price);
599                }
600                $(this).find('.coup-confirm').remove();
601            });
602            update_form(form);
603        }
604
605        function try_coupon(coup_code, form) {
606
607            var nonce = $('input[name=sc-nonce]', form).val(),
608                prod_id = $('input[name=sc_product_id]', form).val(),
609                coupon_applied_text,
610                obj = {
611                    action: "sc_validate_coupon",
612                    prod_id: prod_id,
613                    coup_code: coup_code,
614                    nonce: nonce,
615                    ip: sc_user[0],
616                    email: $('#email', form).val(),
617                }
618
619            if (!$('#email').val() && typeof sc_user[1] !== 'undefined') {
620                obj.email = sc_user[1];
621            }
622
623            $.ajax({
624                type: "post",
625                dataType: "json",
626                url: studiocart.ajax,
627                data: obj,
628                success: function(response) {
629                    if (!response.error) {
630                        let coupon_applied = true;
631                        if( $('#sc-payment-form .products .item', form).length) {
632                            let coupon_applied = false;
633                            $('#sc-payment-form .products .item', form).each(function(index) {
634                                var new_price,
635                                    $item = $(this).find('input[type="radio"]'),
636                                    price = ($item.data('og-price')) ? $item.data('og-price') : $item.data('price'),
637                                    installments = $item.data('installments'),
638                                    discount = response.amount;
639
640                                if (response.plan && !response.plan.includes($item.val())) {
641                                    return;
642                                }
643
644                                coupon_applied_text = format_price(response.amount);
645
646                                if (price <= 0 && (response.type == 'percent' || response.type == 'fixed')) {
647                                    return;
648                                }
649
650                                coupon_applied = true;
651
652                                if (response.type == 'percent' || response.type == 'cart-percent') {
653                                    coupon_applied_text = response.amount + '%';
654                                }
655
656                                if (response.type == 'percent') {
657                                    discount = price * (discount / 100);
658                                } else if (installments && response.amount_recurring) {
659                                    discount = response.amount_recurring;
660                                }
661
662                                new_price = (price - discount).toFixed(2);
663                                if (new_price < 0) {
664                                    new_price = (0).toFixed(2);
665                                }
666
667                                if (response.type != 'cart-percent' && response.type != 'cart-fixed') {
668                                    if (typeof response.duration !== 'undefined' && installments) {
669                                        $item.data('duration', response.duration);
670                                        $item.data('discount', discount);
671                                    } else {
672                                        $item.removeData('duration');
673                                    }
674
675                                    $(this).find('.price').html('<s>' + format_price(price) + '</s> ' + format_price(new_price));
676                                    $item.data('price', new_price).data('og-price', price);
677                                }
678
679                                if (response.plan) {
680                                    var plan_discount;
681                                    if (response.type != 'cart-percent' && response.type != 'percent') {
682                                        plan_discount = format_price(discount);
683                                    } else {
684                                        plan_discount = response.amount + '%';
685                                    }
686                                    coupon_applied_text = response.code + ' (-' + plan_discount + ')';
687                                    $(this).find('coup-confirm').remove();
688                                    $(this).find('label').append('<span class="coup-confirm">' + coupon_applied_text + '</span>');
689                                } else {
690                                    if (typeof response.success_text != 'undefined' && response.success_text != null) {
691                                        coupon_applied_text = response.success_text;
692                                    } else {
693                                        coupon_applied_text = sc_translate_frontend.you_got + ' ' + coupon_applied_text + ' ' + sc_translate_frontend.off;
694                                    }
695                                    $(".coupon-code.applied .coup-confirm", form).html(coupon_applied_text).parent().fadeIn();
696                                }
697
698                            });
699                        }
700                        
701                        if (coupon_applied) {
702                            $('#sc-coupon-id', form).val(response.code);
703                            if (response.type == 'cart-percent' || response.type == 'cart-fixed') {
704                                $('#sc-coupon-id', form).data('type', response.type).data('amount', response.amount);
705                            }
706                            if (response.plan) {
707                                $('#sc-coupon-id', form).data('plans', response.plan);
708                            }
709                            $('#sc-payment-form', form).trigger('studiocart/orderform/coupon_applied', [response]);
710                        }
711                    } else {
712                        $("#coupon-status", form).text(response.error).fadeIn();
713                        $('#sc-coupon-id', form).val('');
714
715                        if ($(".coupon-code input[type='button']", form).length > 0) {
716                            $(".coupon-code input[type='button']", form).show();
717                        } else {
718                            $("#coupon-status", form).delay(3000).fadeOut('normal', function() {
719                                $(this).remove();
720                            });
721                        }
722                        clear_coupon(form);
723                        $('#sc-payment-form', form).trigger('studiocart/orderform/coupon_rejected');
724                    }
725                    $(".coupon-code input[type='button']", form).removeAttr('disabled');
726                    update_form(form);
727                }
728            })
729        }
730
731        $(document).on('click', '.qty-dec, .qty-inc', function(e) {
732            e.preventDefault();
733            var input = $(this).closest('.my-4').find('input'),
734                val = input.val(),
735                form = $(this).closest('form').parent().attr('id');
736                
737            if($(this).hasClass('qty-dec') && parseInt(val) > 0) {
738                input.val(parseInt(val)-1);
739                update_form(form);
740            } else if($(this).hasClass('qty-inc')) {
741                input.val(parseInt(val)+1);
742                update_form(form);
743            }
744            return false;
745        });
746
747        /* Change Vat Customer Type */
748        $(document).on('change', 'input[name="vat-number-available"]', function() {
749            if (this.checked) {
750                $('.vat_number_field').fadeIn(0);
751            } else {
752                $('.vat_number_field').fadeOut(0);
753            }
754        });
755
756        // remove error message on focus
757        $(document).on('focus', '#sc-payment-form input, #sc-payment-form select', function() {
758            $(this).closest('.checkbox-wrap').removeClass('invalid').siblings('.error').remove();
759            $(this).removeClass('invalid valid').siblings('.error').remove();
760            $(this).closest('.form-group').find('input').removeClass('invalid')
761            $(this).closest('.form-group').find('.error').remove()
762
763            if ($(this).attr('id') == 'address1') {
764                $('.sc-address-2 .error').remove();
765            }
766
767            if ($(this).hasClass('selectized')) {
768                $(this).next('.selectize-control').find('.selectize-input').removeClass('invalid');
769            }
770        });
771
772        function invalidate_field($field, message) {
773            $field.removeClass('invalid').siblings('.error').remove();
774
775            if (($field.attr('type') == 'checkbox' && !$field.is(':checked'))) {
776                $field.closest('.checkbox-wrap').addClass('invalid').append('<div class="error">' + message + '</div>');
777            } else {
778                var $el = $field;
779                if ($field.attr('id') == 'address1' && $('.single-sc_product').length > 0) {
780                    $el = $('#sc-payment-form #address2');
781                }
782                $field.addClass('invalid');
783                $el.closest('.form-group').append('<div class="error">' + message + '</div>');
784                if ($field.hasClass('selectized')) {
785                    $field.next('.selectize-control').find('.selectize-input').addClass('invalid');
786                }
787                if ($field.closest('#customer-details.sc-checkout-step').length > 0 && $('.step-two').hasClass('sc-current')) {
788                    $('.steps.step-one a').click();
789                }
790            }
791        }
792
793        // check required on blur
794        $(document).on('blur', '#sc-payment-form input.required', function() {
795            $(this).removeClass('invalid').siblings('.error').remove();
796
797            if (($(this).attr('type') == 'checkbox' && !$(this).is(':checked'))) {
798                $(this).closest('.checkbox-wrap').addClass('invalid').append('<div class="error">' + sc_translate_frontend.field_required + '</div>');
799            } else if (($(this).val().length < 1)) {
800                var $el = $(this);
801                if ($(this).attr('id') == 'address1' && $('.single-sc_product').length > 0) {
802                    $el = $('#sc-payment-form #address2');
803                }
804                $(this).addClass('invalid');
805                $el.closest('.form-group').append('<div class="error">' + sc_translate_frontend.field_required + '</div>');
806            }
807        });
808
809        // check username on blur
810        $(document).on('blur', '#sc-wpuserid', function() {
811            $(this).removeClass('invalid valid').siblings('.error').remove();
812
813            if (($(this).val().length > 0)) {
814                checkUsername($(this));
815            }
816        });
817
818        $(document).on('click', '.sc-checkout-form-steps .steps', async function(event) {
819            event.preventDefault();
820            var form_wrapper = $(this).closest('.sc-form-wrap').attr('id');
821            if ($(this).hasClass('step-two')) {
822                var errors = await sc_validate(form_wrapper);
823                if (errors) {
824                    return false;
825                } else if (!$('[name="sc-lead-captured"]', '#'+form_wrapper).length) {
826                    sc_do_lead_capture(form_wrapper);
827                }
828            }
829
830            if ($(this).hasClass('sc-current')) {
831                return false;
832            }
833
834            $('#sc-payment-form', '#'+form_wrapper).toggleClass('step-1 step-2');
835            $('.sc-checkout-form-steps .steps', '#'+form_wrapper).toggleClass('sc-current');
836            return false;
837
838        });
839
840        async function checkUsername($el) {
841            $el.removeClass('valid');
842
843            var paramObj = new FormData();
844            paramObj.append('name', $el.val());
845            paramObj.append('sc-nonce', $('input[name=sc-nonce]').val());
846            paramObj.append('action', 'sc_check_username');
847
848            try {
849				const response = await fetch(studiocart.ajax, {
850					method: 'POST',
851					body:paramObj
852				});
853				if (response.ok) {
854					const resp = await response.json();
855					if (resp.success) {
856						$el.addClass('valid');
857						$('#sc_card_button, .sc-next-btn').removeAttr("disabled");
858					} else{
859						$el.addClass('invalid');
860						$el.closest('.form-group').append('<div class="error">' + resp.data.error + '</div>');
861						$('#sc_card_button, .sc-next-btn').attr("disabled", true);
862					}
863					return resp.success;
864				} else {
865					alert('Something went wrong.')
866					$el.addClass('invalid');
867					$('#sc_card_button, .sc-next-btn').attr("disabled", true);
868				}
869			} catch (error) {
870				alert('Something went wrong.')
871				$el.addClass('invalid');
872				$('#sc_card_button, .sc-next-btn').attr("disabled", true);
873			}
874            return false;
875        }
876
877        // check email address
878        $(document).on('blur', '#sc-payment-form input[type="email"]', function() {
879            if ($(this).val().length < 1) return;
880
881            var val = $(this).val();
882            var validEmail = regExEmail.test(val);
883            if (!validEmail) {
884                $(this).addClass('invalid').closest('.form-group').append('<div class="error">' + sc_translate_frontend.invalid_email + '</div>');
885            }
886        });
887
888        // check phone number
889        $(document).on('blur', '#sc-payment-form input[type="tel"]', function() {
890            if ($(this).val().length < 1) return;
891
892            var val = $(this).val();
893            var validPhone = isValidPhonenumber(val);
894            if (!validPhone) {
895                $(this).addClass('invalid').closest('.form-group').append('<div class="error">' + sc_translate_frontend.invalid_phone + '</div>');
896            }
897        });
898
899        // check password
900        $(document).on('blur', '#sc-payment-form input.sc-password', function() {
901            var val = $(this).val();
902            if (val.length) {
903                var validPass = isValidPassword(val);
904                if (!validPass) {
905                    $(this).addClass('invalid').closest('.form-group').append('<div class="error">' + sc_translate_frontend.invalid_pass + '</div>');
906                }
907            }
908        });
909
910        /* track any change to total amount due
911        $(document).on('change', '#sc-payment-form input', function() {
912            amount = false;
913        });*/
914
915        /* <fs_premium_only> */
916
917        /* Assign the class & link to specific button */
918        var accept_links = $('a[href*="sc-upsell-offer=yes"]');
919
920        if (accept_links.length > 0 && 'undefined' !== typeof studiocart.upsell_accept) {
921            accept_links.addClass('sc-accept-upsell-link');
922            accept_links.attr('href', studiocart.upsell_accept);
923            $('.sc-accept-upsell-link').trigger('studiocart/upsell/ready/accept_link');
924        }
925
926        var decline_links = $('a[href*="sc-upsell-offer=no"]');
927
928        if (decline_links.length > 0 && 'undefined' !== typeof studiocart.upsell_decline) {
929            decline_links.addClass('sc-decline-upsell-link');
930            decline_links.attr('href', studiocart.upsell_decline);
931            $('.sc-decline-upsell-link').trigger('studiocart/upsell/ready/decline_link');
932        }
933
934        /* </fs_premium_only> */
935
936        async function sc_validate(form_wrapper) {
937            var errors = false;
938
939            if ($('.elementor-editor-active').length > 0) {
940                return errors;
941            }
942
943            $(".error").remove();
944            $('#'+form_wrapper+' input').removeClass('invalid');
945
946            var fields = $('#'+form_wrapper+' input.required:visible, #'+form_wrapper+' select.required:visible, #'+form_wrapper+' select.required.selectized');
947            fields.each(function () {
948                if ($(this).attr('type') == 'checkbox' && !$(this).is(':checked')) {
949                    if($(this).attr('name').endsWith('[]')) {
950                        if($('#'+form_wrapper+' input[name="'+$(this).attr('name')+'"]:checked').length < 1) {
951                            $(this).addClass('invalid');
952                            if ($(this).closest('.form-group').find('.error').length == 0)
953                                $(this).closest('.form-group').append('<div class="error">' + sc_translate_frontend.field_required + '</div>');
954                            errors = true;
955                        }
956                    } else {
957                        $(this).closest('.checkbox-wrap').addClass('invalid').append('<div class="error">' + sc_translate_frontend.field_required + '</div>');
958                        errors = true;
959                    }
960                } else if ($(this).attr('type') == 'radio' && !$(this).is(':checked') && $('#'+form_wrapper+' input[name="'+$(this).attr('name')+'"]:checked').length < 1) {
961                    $(this).addClass('invalid');
962                    if ($(this).closest('.form-group').find('.error').length == 0)
963                        $(this).closest('.form-group').append('<div class="error">' + sc_translate_frontend.field_required + '</div>');
964                    errors = true;
965                } else if ($(this).attr('name') == 'pwyw_amount') {
966                    var value = $(this).val();
967                    var minvalue = $(this).attr('min');
968                    if (parseFloat(value) < parseFloat(minvalue)) {
969                        $(this).addClass('invalid');
970                        if ($(this).closest('.form-group').find('.error').length == 0)
971                            $(this).closest('.form-group').append('<div class="error">Please enter an amount greater thank or equal to <span class="sc-Price-currencySymbol">$</span>' + parseFloat(minvalue).toFixed(2) + '</div>')
972                        errors = true;
973                    }
974                } else if ($(this).val().length < 1) {
975                    var $el = $(this);
976                    if ($(this).attr('id') == 'address1' && $('.single-sc_product').length > 0) {
977                        $el = $('#'+form_wrapper+' #address2');
978                    }
979                    $(this).addClass('invalid');
980                    $el.closest('.form-group').append('<div class="error">' + sc_translate_frontend.field_required + '</div>');
981                    if ($(this).hasClass('selectized')) {
982                        $(this).next('.selectize-control').find('.selectize-input').addClass('invalid');
983                    }
984                    errors = true;
985                }
986            });
987
988            // check username 
989            if ($('#'+form_wrapper+' #sc-wpuserid').length > 0) {
990                var $username = $('#'+form_wrapper+' #sc-wpuserid');
991                if (($username.val().length > 0)) {
992                    var check = await checkUsername($username);
993                    if (check == false) {
994                        errors = true;
995                    }
996                }
997            }
998
999            // check email address
1000            $('#'+form_wrapper+' input[type="email"]').each(function () {
1001                if ($(this).val().length) {
1002                    var validEmail = regExEmail.test($(this).val());
1003                    if (!validEmail) {
1004                        $(this).addClass('invalid').closest('.form-group').append('<div class="error">' + sc_translate_frontend.invalid_email + '</div>');
1005                        errors = true;
1006                    }
1007                }
1008            });
1009
1010            // check phone number
1011            $('#'+form_wrapper+' input[type="phone"]').each(function () {
1012                if ($(this).val().length) {
1013                    var validPhone = isValidPhonenumber($(this).val());
1014                    if (!validPhone) {
1015                        $(this).addClass('invalid').closest('.form-group').append('<div class="error">' + sc_translate_frontend.invalid_phone + '</div>');
1016                        errors = true;
1017                    }
1018                }
1019            });
1020
1021
1022            // check password
1023            $('#'+form_wrapper+' input.sc-password').each(function () {
1024                if ($(this).val().length) {
1025                    var validPass = isValidPassword($(this).val());
1026                    if (!validPass) {
1027                        $(this).addClass('invalid').closest('.form-group').append('<div class="error">' + sc_translate_frontend.invalid_pass + '</div>');
1028                        errors = true;
1029                    }
1030                }
1031            });
1032
1033            if($('#'+form_wrapper+' input').closest('.form-group').find('.error').length>0){
1034                errors = true;
1035            }
1036
1037            return errors;
1038        }
1039
1040        // 2 step form
1041        $(document).on('click', '.sc-next-btn', async function () {
1042            var form_wrapper = $(this).data('form-wrapper');
1043            var errors = await sc_validate(form_wrapper);
1044            if (errors) {
1045                return;
1046            } else {
1047                if (!$('[name="sc-lead-captured"]', '#'+form_wrapper).length) {
1048                    sc_do_lead_capture(form_wrapper);
1049                }
1050                $('#sc-payment-form', '#'+form_wrapper).toggleClass('step-1 step-2');
1051                $('.sc-checkout-form-steps .steps', '#'+form_wrapper).toggleClass('sc-current');
1052            }
1053        });
1054
1055        function sc_do_lead_capture(wrap_id) {
1056            var form = '#'+wrap_id;
1057            var paramObj = {};
1058            $.each($('#sc-payment-form', form).serializeArray(), function(_, kv) {
1059                paramObj[kv.name] = kv.value;
1060            });
1061
1062            paramObj['action'] = 'sc_capture_lead';
1063
1064            $.post(studiocart.ajax, paramObj, function(response) {
1065                //console.log('capturing lead');
1066                if (response == 'OK') {
1067                    $('#sc-payment-form', form).trigger('studiocart/orderform/lead_captured');
1068                    var form = document.getElementById(wrap_id);
1069                    form = form.getElementsByTagName('form')[0];
1070
1071                    var hiddenInput = document.createElement('input');
1072                    hiddenInput.setAttribute('type', 'hidden');
1073                    hiddenInput.setAttribute('name', 'sc-lead-captured');
1074                    hiddenInput.setAttribute('value', 1);
1075                    form.appendChild(hiddenInput);
1076                }
1077            });
1078            return true;
1079        }
1080        
1081        // check pay info
1082        var $btn,
1083            $form,
1084            clientSecret,
1085            intent_id,
1086            amount,
1087            customer_id,
1088            sc_temp_order_id,
1089            prod_id,
1090            paymentMethodId;
1091            
1092        if ($('.sc-stripe #card-element').length > 0 || $('.sc-stripe-express #express-pay-element').length > 0) {
1093            // Create a Stripe client.
1094            var stripe = Stripe(stripe_key[0]);
1095            var card = {};
1096        }
1097        
1098        $('.sc-form-wrap').each(function(){
1099            
1100            let form_id = $(this).attr('id');
1101            let form = '#'+form_id;
1102
1103            // toggle pay methods
1104            togglePayMethods(form);
1105    
1106            if (typeof sc_coupon !== 'undefined') {
1107                try_coupon(sc_coupon[0], form);
1108            } else {
1109                update_pwyw(form);
1110                update_form(form);
1111            }
1112
1113            // check pay info
1114            var $btn = $('#sc_card_button', form);
1115                $form = $('#sc-payment-form', form);
1116    
1117            if ($('.sc-stripe #card-element', form).length > 0) {
1118                
1119                $('.sc-stripe #card-element', form).each(function(){
1120    
1121                    let form_wrapper = form_id;
1122                    // Create an instance of Elements.
1123                    var elements = stripe.elements();
1124					let $this = "#"+form_wrapper+" #card-element";
1125    
1126                    // Custom styling can be passed to options when creating an Element.
1127                    // (Note that this demo uses a wider set of styles than the guide below.)
1128                    var style = {
1129                        base: {
1130                            color: '#32325d',
1131                            fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
1132                            fontSmoothing: 'antialiased',
1133                            fontSize: '16px',
1134                            '::placeholder': {
1135                                color: '#aab7c4'
1136                            }
1137                        },
1138                        invalid: {
1139                            color: '#fa755a',
1140                            iconColor: '#fa755a'
1141                        }
1142                    };
1143    
1144                    // Create an instance of the card Element.
1145                    card[form_wrapper] = elements.create('card', { style: style });
1146    
1147                    // Add an instance of the card Element into the `card-element` <div>.
1148                    
1149                    card[form_wrapper].mount($this);
1150    
1151                    // Handle real-time validation errors from the card Element.
1152                    card[form_wrapper].addEventListener('change', function (event) {
1153                        var displayError = document.querySelector("#"+form_wrapper+" #card-errors");
1154                        if (event.error) {
1155                            displayError.textContent = event.error.message;
1156                        } else {
1157                            displayError.textContent = '';
1158                        }
1159                    });
1160    
1161                    // Reinitialize Stripe elements for forms inside Elementor popups
1162                    jQuery(document).on('elementor/popup/show', () => {
1163    
1164                        card[form_wrapper].unmount($this);
1165                        card[form_wrapper].mount($this);
1166    
1167                        // Handle real-time validation errors from the card Element.
1168                        card[form_wrapper].addEventListener('change', function (event) {
1169                            var displayError = document.querySelector("#"+form_wrapper+" #card-errors");
1170                            if (event.error) {
1171                                displayError.textContent = event.error.message;
1172                            } else {
1173                                displayError.textContent = '';
1174                            }
1175                        });
1176
1177                        // 100ms delay for open popup animation
1178                        setTimeout(() => {
1179                            if (typeof sc_coupon !== 'undefined') {
1180                                try_coupon(sc_coupon[0], "#"+form_wrapper);
1181                            } else {
1182                                update_pwyw("#"+form_wrapper);
1183                                update_form(form_wrapper);
1184                            }
1185                        }, 100);
1186                    });
1187                });
1188            }
1189    
1190            function onloadCallback() {
1191                grecaptcha.ready(function() {
1192                    var gsitekey = $(".sc-grtoken").attr("data-sitekey");
1193                    grecaptcha.execute(gsitekey, { action: 'submit' }).then(function(token) {
1194                        $(".sc-grtoken", form).val(token);
1195                    });
1196                });
1197            }
1198    
1199            // Handle form submission.
1200            $(document).on('click', form + ' #sc_card_button', async function(event) {
1201    
1202                $btn = $(this);
1203                originalText = $btn.find('span.text').text();
1204                $btn.addClass('running').attr("disabled", true);
1205                $btn.find('span.text').text(sc_translate_frontend.loading_processing);
1206    
1207                event.preventDefault();
1208                var form_wrapper = $btn.data('form-wrapper');
1209                var errors = await sc_validate(form_wrapper);
1210                var form = '#'+form_wrapper;
1211    
1212                if (errors) {
1213                    alert(sc_translate_frontend.missing_required);
1214                    $btn.removeClass('running').removeAttr("disabled");
1215                    $btn.find('span.text').text(originalText);
1216                    return false;
1217                } 
1218    
1219                if(jQuery(".g-recaptcha", form).length>0){
1220                    var gcaptchasize = jQuery(".g-recaptcha", form).attr("data-size");
1221                    if (gcaptchasize == "invisible") {
1222                        grecaptcha.ready(function() {
1223                            grecaptcha.execute();
1224                        });
1225                    }
1226                }
1227    
1228                if ($(".sc-grtoken", form).length > 0) {
1229                    grecaptcha.ready(function() {
1230                        var gsitekey = $(".sc-grtoken", form).attr("data-sitekey");
1231                        grecaptcha.execute(gsitekey, { action: 'submit' }).then(function(token) {
1232                            $(".sc-grtoken", form).val(token);
1233                        });
1234                    });
1235                }
1236    
1237                setTimeout(function() {
1238    
1239                    var is_subscription = $('.ob-sub:checked', form).length || ($('input[name="sc_product_option"]:checked', form).data('installments') && !$('.ob-replace:checked', form).length);
1240                   
1241                    if ($('#sc-payment-form [name="pay-method"]', form).length > 0) {
1242                        if ($('[name="pay-method"]:checked', form).val() != 'stripe' && ($('[name="sc_amount"]', form).val() != 0 || is_subscription) && $('[name="pay-method"]:checked', form).val() != 'cod') {
1243                            $('#sc-payment-form', form).trigger('studiocart/orderform/submit');
1244                            return false;
1245                        }
1246                    }
1247    
1248                    var paramObj = $('#sc-payment-form', form).serializeArray();
1249    
1250                    // process free payment, manual payment methods
1251                    var manual = ($('#sc-payment-form [name="pay-method"]:checked', form).val() == 'cod'),
1252                        plan = $('input[name=sc_product_option]:checked', form);
1253    
1254                    if ($('[name="sc_amount"]', form).val() == 0 && !is_subscription || manual) {
1255                        paramObj.push(
1256                            { name: "action", value: "save_order_to_db" }, 
1257                            { name: "pay-method", value: "cod" } // change method to "COD", otherwise order will get stuck in "pending" status
1258                        );
1259
1260                        $.post(studiocart.ajax, paramObj, function(res) {
1261                            var response = JSON.parse(res);
1262                            if ('undefined' !== typeof response.error) {
1263                                alert(response.error);
1264    
1265                                if ('undefined' !== typeof response.fields) {
1266                                    $.each(response.fields, function(i, item) {
1267                                        invalidate_field($('[name="' + item['field'] + '"]', form), item['message'])
1268                                    });
1269                                }
1270    
1271                                $btn = $('#sc_card_button', form);
1272                                $btn.removeClass('running').removeAttr("disabled");
1273                                $btn.find('span.text').text(originalText);
1274                            } else {
1275                                if ('undefined' !== typeof response.redirect) {
1276                                    window.location.href = response.redirect;
1277                                } else {
1278                                    // var formEl = document.getElementById(form_wrapper).firstChild;
1279
1280                                    if ('undefined' !== typeof response.formAction) {
1281                                        $form = $('#sc-payment-form', form);
1282                                        $form.attr('action', response.formAction);
1283                                    }
1284                                    var hiddenInput = document.createElement('input');
1285                                    hiddenInput.setAttribute('type', 'hidden');
1286                                    hiddenInput.setAttribute('name', 'sc_order_id');
1287                                    hiddenInput.setAttribute('value', response.order_id);
1288                                    $form.append(hiddenInput);
1289                                    $form.submit();
1290                                }
1291                            }
1292                        });
1293                        return false;
1294                    }
1295    
1296                    paramObj.push({name: "action", value: "create_payment_intent"});
1297    
1298                    if (!intent_id) {
1299    
1300                        // create new intent if none found
1301                        $.post(studiocart.ajax, paramObj, function(res) {
1302    
1303                            var response = JSON.parse(res);
1304                            if ('undefined' !== typeof response.error) {
1305                                alert(response.error);
1306                                if ('undefined' !== typeof response.fields) {
1307                                    $.each(response.fields, function(i, item) {
1308                                        invalidate_field($('[name="' + item['field'] + '"]', form), item['message'])
1309                                    });
1310                                }
1311                                $btn.removeClass('running').removeAttr("disabled");
1312                                $btn.find('span.text').text(originalText);
1313                                return false;
1314                            } else {
1315                                if ('undefined' !== typeof response.redirect) {
1316                                    window.location.href = response.redirect;
1317                                } else {
1318                                    clientSecret = response.clientSecret;
1319                                    intent_id = response.intent_id;
1320                                    customer_id = response.customer_id;
1321                                    amount = response.amount;
1322                                    sc_temp_order_id = response.sc_temp_order_id;
1323                                    prod_id = response.prod_id;
1324    
1325                                    if (is_subscription) {
1326                                        confirmSubscription(response, false, false, form_wrapper);
1327                                    } else {
1328                                        // create new order in db then send to stripe
1329                                        saveThenConfirm(response, form_wrapper);
1330                                    }
1331                                }
1332                            }
1333                        });
1334                    } else {
1335    
1336                        var intent = {
1337                            'clientSecret': clientSecret,
1338                            'intent_id': intent_id,
1339                            'customer_id': customer_id,
1340                            'amount': amount,
1341                            'prod_id':prod_id,
1342                            'sc_temp_order_id':sc_temp_order_id
1343                        };
1344    
1345                        if (is_subscription) {
1346                            // If a previous payment was attempted, get the lastest invoice
1347                            const latestInvoicePaymentIntentStatus = localStorage.getItem(
1348                                'latestInvoicePaymentIntentStatus'
1349                            );
1350    
1351                            if (
1352                                latestInvoicePaymentIntentStatus === 'requires_payment_method' ||
1353                                latestInvoicePaymentIntentStatus === 'requires_action'
1354                            ) {
1355                                const invoiceId = localStorage.getItem('latestInvoiceId');
1356                                const isPaymentRetry = true;
1357                                // create new payment method & retry payment on invoice with new payment method
1358                                confirmSubscription(
1359                                    intent,
1360                                    isPaymentRetry,
1361                                    invoiceId,
1362                                    form_wrapper
1363                                );
1364                            } else {
1365                                confirmSubscription(intent, false, false, form_wrapper);
1366                            }
1367                        } else {
1368                            if ($('input[name=order_id]').length == 0) {
1369                                // create new order in db then send to stripe
1370                                saveThenConfirm(intent, form_wrapper);
1371                            } else {
1372                                if (!amount) {
1373                                    paramObj['action'] = 'update_payment_intent_amt';
1374                                    paramObj['intent_id'] = intent.intent_id;
1375                                    $.post(studiocart.ajax, paramObj, function(amt) {
1376                                        if (!isNaN(amt)) {
1377                                            amount = amt;
1378                                            intent.amount = amt;
1379                                        }
1380                                    });
1381                                }
1382    
1383                                // create new order in db then send to 
1383stripe
1384                                confirmCardPayment(intent, form_wrapper);
1385                            }
1386                        }
1387                    }
1388    
1389                }, 1000);
1390    
1391            });
1392        });
1393
1394        $('.sc_cancel_sub').click(function() {
1395
1396            if (confirm(sc_translate_frontend.confirm_cancel_sub)) {
1397                var ajaxurl = studiocart.ajax;
1398                var _this = $(this);
1399                var id = _this.data('id');
1400                var wp_nonce = jQuery("#sc_nonce").val();
1401                var subscriber_id = (_this.data('item-id')) ? _this.data('item-id') : $("#sc_payment_intent").val();
1402                var payment_method = jQuery("#sc_payment_method").val();
1403                var prod_id = jQuery("#sc_product_id").val();
1404
1405                var data = {
1406                    'action': 'sc_unsubscribe_customer',
1407                    'prod_id': prod_id,
1408                    'subscription_id': subscriber_id,
1409                    'nonce': wp_nonce,
1410                    'id': id,
1411                    'payment_method': payment_method,
1412                };
1413
1414                // We can also pass the url value separately from ajaxurl for front end AJAX implementations
1415                jQuery.post(ajaxurl, data, function(response) {
1416                    console.log(response);
1417                    if (response == 'OK') {
1418                        alert(sc_translate_frontend.sub_cancel); //custom message
1419                        location.reload();
1420                    } else {
1421                        alert(response);
1422                    }
1423                }).fail(function() {
1424                    alert(response.fail);
1425                });
1426            } else {
1427                return false;
1428            }
1429        });
1430
1431        /**
1432         * Pause Start Subscription
1433         */
1434        $('.sc_pause_restart_sub').click(function(){
1435
1436            var confirmMessage = sc_translate_frontend.confirm_pause_sub;
1437            var successMessage = sc_translate_frontend.sub_paused;
1438            var type = $(this).data('action');
1439
1440            if(type == 'started'){
1441                confirmMessage = sc_translate_frontend.confirm_activate_sub;
1442                successMessage = sc_translate_frontend.sub_started;
1443            }
1444            
1445            if (confirm(confirmMessage)) { 
1446                var ajaxurl = studiocart.ajax;
1447                var _this = $(this);
1448                var id = _this.data('id');
1449                var wp_nonce	= jQuery("#sc_nonce").val();
1450                var payment_method	= jQuery("#sc_payment_method").val();
1451                var prod_id = jQuery("#sc_product_id").val();
1452                
1453                var data = {
1454                    'action': 'sc_pause_restart_subscription',
1455                    'prod_id': prod_id,
1456                    'nonce': wp_nonce,
1457                    'id': id,
1458                    'payment_method': payment_method,
1459                    'type':type,
1460                };
1461
1462                // We can also pass the url value separately from ajaxurl for front end AJAX implementations
1463                jQuery.post(ajaxurl, data, function(response) {
1464                    console.log(response);
1465                    if( response == 'OK' ){
1466                        alert(successMessage); //custom message
1467                        location.reload();
1468                    }else{
1469                            alert(response);
1470                    }
1471                }).fail(function() {
1472                    alert(response.fail);  
1473                });
1474            } else {
1475                return false;
1476            } 
1477        });
1478
1479        $('input.required, select.required, input[type="checkbox"].required').on('keyup change', async function () {
1480            var form = $(this).closest('form').parent().attr('id');
1481            let $this = "#"+form+" #express-pay-element";
1482            var errors = await sc_validate(form);
1483            if (errors) {
1484                $($this).css('pointer-events', 'none');
1485            }else{
1486                $($this).css('pointer-events', '');
1487            } 
1488        });
1489
1490        // Express Payment Onload
1491        function initialExpressPayment(form_wrapper) {
1492            if ($('.sc-stripe-express #express-pay-element', form_wrapper).length > 0) {
1493                $('.sc-stripe-express #express-pay-element', form_wrapper).each(function(){
1494                    $(this).hide();
1495                    let $this = form_wrapper+" #express-pay-element";
1496                    const elements = stripe.elements();
1497                    const form = form_wrapper.replace('#', '');
1498                    var product_name = $(form_wrapper + ' [name="sc_product_name"]').val();
1499                    var amount = Math.round(parseFloat($('input[name=sc_amount]', form_wrapper).val()) * 100);
1500                    var country = $('input[name=sc_currency_country_code]', form_wrapper).val().toUpperCase(),
1501                    currency = $('input[name=sc_currency_code]', form_wrapper).val().toLowerCase();
1502                    if(currency && country){
1503                        const paymentRequest = stripe.paymentRequest({
1504                            country: country,
1505                            currency: currency,
1506                            total: {
1507                                label: product_name,
1508                                amount: amount,
1509                            },
1510                            requestPayerName: true,
1511                            requestPayerEmail: true
1512                        });
1513                        
1514                        $($this).css('pointer-events', 'none');
1515    
1516                        card[form_wrapper] = elements.create('paymentRequestButton', {
1517                            paymentRequest: paymentRequest,
1518                            style: {
1519                                paymentRequestButton: {
1520                                type: 'default',
1521                                theme: 'dark',
1522                                height: '45px',
1523                                },
1524                            },
1525                        });
1526                        paymentRequest.canMakePayment().then(result => {
1527                            console.log('Can make payment result ::', result);
1528                            if (result && result.link) {
1529                                // Link is supported
1530                                card[form_wrapper].mount($this);
1531                                $($this).show();
1532                            } else {
1533                                // Link is not supported (country issue)
1534                                $($this).hide();
1535                        
1536                                // Show custom message or disable the button
1537                                var message = "Sorry, Express Payment is not supported in your region.";
1538                                // You can append this message to a specific element in your form or show it in a modal
1539                                $('#payment-method-message', form_wrapper).text(message).show();
1540                        
1541                                // Optionally disable or hide other parts of the UI
1542                                $('#sc_card_button', form_wrapper).prop('disabled', true);
1543                            }
1544                        }).catch(error => {
1545                            console.error('Error checking payment capability:', error);
1546                            $($this).hide();
1547                        
1548                            // Optional: Show a different message for error scenarios
1549                            $('#payment-method-message', form_wrapper).text("An error occurred while processing your payment options. Please try again.").show();
1550                        });
1551                        paymentRequest.on('paymentmethod', async (ev) => {
1552                            try {
1553                                $($this).css('pointer-events', 'none');
1554                                $('#sc_card_button', form_wrapper).addClass('running').attr('disabled', 'disabled');
1555                                // Validation
1556                                var errors = await sc_validate(form);
1557                                if (errors) {
1558                                    $($this).css('pointer-events', '');
1559                                    $('#sc_card_button', form_wrapper).removeClass('running').removeAttr("disabled");
1560                                    alert(sc_translate_frontend.missing_required);
1561                                    return ev.complete('fail');
1562                                } 
1563                                if(jQuery(".g-recaptcha", form_wrapper).length>0){
1564                                    var gcaptchasize = jQuery(".g-recaptcha", form_wrapper).attr("data-size");
1565                                    if (gcaptchasize == "invisible") {
1566                                        grecaptcha.ready(function() {
1567                                            grecaptcha.execute();
1568                                        });
1569                                    }
1570                                }
1571                                if ($(".sc-grtoken", form_wrapper).length > 0) {
1572                                    grecaptcha.ready(function() {
1573                                        var gsitekey = $(".sc-grtoken", form_wrapper).attr("data-sitekey");
1574                                        grecaptcha.execute(gsitekey, { action: 'submit' }).then(function(token) {
1575                                            $(".sc-grtoken", form_wrapper).val(token);
1576                                        });
1577                                    });
1578                                }
1579                                setTimeout(function() {
1580                                    var is_subscription = $('.ob-sub:checked', form_wrapper).length || ($('input[name="sc_product_option"]:checked', form_wrapper).data('installments') && !$('.ob-replace:checked', form_wrapper).length);
1581                                    var paramObj = $('#sc-payment-form', form_wrapper).serializeArray();
1582                                    var paymentMethod = ev.paymentMethod;
1583                                    paymentMethodId = paymentMethod['id'];
1584                                    paramObj.push({name: "action", value: "create_payment_intent"});                       
1585                                    paramObj.push({name: "sc_payment_method_id", value: paymentMethodId}); 
1586                                    paramObj.find(input => input.name == 'pay-method').value = "stripe";
1587                                    
1588                                    if (!intent_id) {
1589                                        // create new intent if none found
1590                                        $.post(studiocart.ajax, paramObj, function(res) {                
1591                                            var response = JSON.parse(res);
1592                                            response.paymentMethodId = paymentMethodId;
1593                                            if ('undefined' !== typeof response.redirect) {
1594                                                window.location.href = response.redirect;
1595                                            } else {
1596                                                clientSecret = response.clientSecret;
1597                                                intent_id = response.intent_id;
1598                                                customer_id = response.customer_id;
1599                                                amount = response.amount;
1600                                                sc_temp_order_id = response.sc_temp_order_id;
1601                                                prod_id = response.prod_id;
1602                                                if (is_subscription) {
1603                                                    // Create the subscription
1604                                                    createSubscription(
1605                                                        customer_id,
1606                                                        paymentMethodId,
1607                                                        false,
1608                                                        form,
1609                                                        ev
1610                                                    );
1611                                                } else {                                               
1612                                                    // create new order in db then send to 
1612stripe
1613                                                    $btn = $(form_wrapper + ' #sc_card_button').data('form-wrapper'); 
1614                                                    saveThenConfirm(response, $btn, true, ev);
1615                                                }
1616                                            }
1617                                        }).fail(function(jqXHR, textStatus, errorThrown) {
1618                                            ev.complete('fail');
1619                                            $($this).css('pointer-events', '');
1620                                            $('#sc_card_button', form_wrapper).removeClass('running').removeAttr("disabled");
1621                                            console.error('Error confirming the payment method:', textStatus, errorThrown);
1622                                            alert('An unexpected error occurred.');
1623                                        });
1624                                    } else {
1625                                        var intent = {
1626                                            'clientSecret': clientSecret,
1627                                            'intent_id': intent_id,
1628                                            'customer_id': customer_id,
1629                                            'amount': amount,
1630                                            'prod_id':prod_id,
1631                                            'sc_temp_order_id':sc_temp_order_id,
1632                                            'paymentMethodId' : paymentMethodId
1633                                        };
1634                                        if (is_subscription) {
1635                                            // If a previous payment was attempted, get the lastest invoice
1636                                            const latestInvoicePaymentIntentStatus = localStorage.getItem(
1637                                                'latestInvoicePaymentIntentStatus'
1638                                            );
1639                                            if (
1640                                                latestInvoicePaymentIntentStatus === 'requires_payment_method' ||
1641                                                latestInvoicePaymentIntentStatus === 'requires_action'
1642                                            ) {
1643                                                const invoiceId = localStorage.getItem('latestInvoiceId');
1644                                                const isPaymentRetry = true;
1645                                                // create new payment method & retry payment on invoice with new payment method
1646                                                confirmSubscription(
1647                                                    intent,
1648                                                    isPaymentRetry,
1649                                                    invoiceId,
1650                                                    form,
1651                                                    ev
1652                                                );
1653                                            } else {
1654                                                confirmSubscription(intent, false, false, form, ev);
1655                                            }
1656                                        } else {
1657                                            if ($('input[name=order_id]').length == 0) {
1658                                                // create new order in db then send to stripe
1659                                                $btn = $(form_wrapper + ' #sc_card_button').data('form-wrapper'); 
1660                                                saveThenConfirm(intent, $btn, true, ev);
1661                                            } else {
1662                                                if (!amount) {
1663                                                    paramObj['action'] = 'update_payment_intent_amt';
1664                                                    paramObj['intent_id'] = intent.intent_id;
1665                                                    $.post(studiocart.ajax, paramObj, function(amt) {
1666                                                        if (!isNaN(amt)) {
1667                                                            amount = amt;
1668                                                            intent.amount = amt;
1669                                                        }
1670                                                    });
1671                                                }
1672                                                // create new order in db then send to 
1672stripe
1673                                                confirmCardPayment(intent, form, true, ev);
1674                                            }
1675                                        }
1676                                    }
1677                                }, 1000);         
1678                            } catch (error) {
1679                                console.error('Error confirming the payment method:', error);
1680                                ev.complete('fail');
1681                                $($this).css('pointer-events', '');
1682                                $('#sc_card_button', form_wrapper).removeClass('running').removeAttr("disabled");
1683                                alert('An unexpected error occurred.');
1684                            }
1685                        });
1686                    }                    
1687                });
1688            }
1689        } 
1690
1691        function saveThenConfirm(intent, form_wrapper, isExpresspayment, ev) {
1692            confirmCardPayment(intent, form_wrapper, isExpresspayment, ev);
1693        }
1694
1695        function createSubscription(customerId, paymentMethodId, invoiceId, wrap_id, ev) {
1696            var f = document.getElementById(wrap_id);
1697            f = f.getElementsByTagName('form')[0];
1698            const form = new FormData(f);
1699            form.set('action', 'create_subscription');
1700            form.set('customerId', customerId);
1701            form.set('paymentMethodId', paymentMethodId);
1702            if (invoiceId) {
1703                form.set('invoiceId', invoiceId);
1704            }
1705            const params = new URLSearchParams(form);
1706            return (
1707                fetch(studiocart.ajax, {
1708                    method: 'post',
1709                    credentials: 'same-origin',
1710                    headers: {
1711                        'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
1712                    },
1713                    body: params
1714                })
1715                .then((response) => {
1716                    return response.json();
1717                })
1718                // If the card is declined, display an error to the user.
1719                .then((result) => {
1720                    if (result.error) {
1721                        // The card had an error when trying to attach it to a customer
1722                        throw result.error;
1723                    }
1724                    return result;
1725                })
1726                // Normalize the result to contain the object returned
1727                // by Stripe. Add the addional details we need.
1728                .then((result) => {
1729                    // Insert the token ID into the form so it gets submitted to the server
1730                    if ('undefined' !== typeof result.formAction) {
1731                        f.setAttribute('action', result.formAction);
1732                    }
1733                    var hiddenInput = document.createElement('input');
1734                    hiddenInput.setAttribute('type', 'hidden');
1735                    hiddenInput.setAttribute('name', 'sc_order_id');
1736                    hiddenInput.setAttribute('value', result.sc_order_id);
1737                    f.appendChild(hiddenInput);
1738                    return {
1739                        // Use the Stripe 'object' property on the
1740                        // returned result to understand what object is returned.
1741                        subscription: result,
1742                        paymentMethodId: paymentMethodId,
1743                    };
1744                })
1745                // Some payment methods require a customer to do additional
1746                // authentication with their financial institution.
1747                // Eg: 2FA for cards.
1748                .then(handlePaymentThatRequiresCustomerAction)
1749                // If attaching this card to a Customer object succeeds,
1750                // but attempts to charge the customer fail. You will
1751                // get a requires_payment_method error.
1752                .then(handleRequiresPaymentMethod)
1753                // No more actions required. Provision your service for the user.
1754                .then(function() {
1755                    if(ev){
1756                        ev.complete('success'); 
1757                    }
1758                    //console.log('result: ' + $('input[name=order_id]').val());
1759                    f.submit();
1760                })
1761                .catch((error) => {
1762                    if(ev){                        
1763                        ev.complete('fail'); 
1764                    }
1765                    // An error has happened. Display the failure to the user here.
1766                    // We utilize the HTML element we created.
1767                    displayError(error, wrap_id);
1768                })
1769            );
1770        }
1771
1772        function retryInvoiceWithNewPaymentMethod(
1773            customerId,
1774            paymentMethodId,
1775            invoiceId,
1776            wrap_id
1777        ) {
1778            var f = document.getElementById(wrap_id);
1779            f = f.getElementsByTagName('form')[0];
1780            const form = new FormData(f);
1781            form.set('action', 'create_subscription');
1782            form.set('customerId', customerId);
1783            form.set('paymentMethodId', paymentMethodId);
1784            if (invoiceId) {
1785                form.set('invoiceId', invoiceId);
1786            }
1787            const params = new URLSearchParams(form);
1788            return (
1789                fetch(studiocart.ajax, {
1790                    method: 'post',
1791                    credentials: 'same-origin',
1792                    headers: {
1793                        'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
1794                    },
1795                    body: params
1796                })
1797                .then((response) => {
1798                    return response.json();
1799                })
1800                // If the card is declined, display an error to the user.
1801                .then((result) => {
1802                    if (result.error) {
1803                        // The card had an error when trying to attach it to a customer
1804                        throw result;
1805                    }
1806                    return result;
1807                })
1808                // Normalize the result to contain the object returned
1809                // by Stripe. Add the addional details we need.
1810                .then((result) => {
1811                    return {
1812                        // Use the Stripe 'object' property on the
1813                        // returned result to understand what object is returned.
1814                        invoice: result,
1815                        paymentMethodId: paymentMethodId,
1816                        isRetry: true,
1817                    };
1818                })
1819                // Some payment methods require a customer to be on session
1820                // to complete the payment process. Check the status of the
1821                // payment intent to handle these actions.
1822                .then(handlePaymentThatRequiresCustomerAction)
1823                // No more actions required. Provision your service for the user.
1824                .then(function() {
1825                    if(ev){
1826                        ev.complete('success'); 
1827                    }
1828                    //console.log('result: ' + $('input[name=order_id]').val());
1829                    $form.submit();
1830                })
1831                .catch((error) => {
1832                    if(ev){
1833                        ev.complete('fail'); 
1834                    }
1835                    // An error has happened. Display the failure to the user here.
1836                    // We utilize the HTML element we created.
1837                    displayError(error, wrap_id);
1838                })
1839            );
1840        }
1841
1842        function handlePaymentThatRequiresCustomerAction({
1843            subscription,
1844            invoice,
1845            priceId,
1846            paymentMethodId,
1847            isRetry,
1848        }) {
1849            // If it's a first payment attempt, the payment intent is on the subscription latest invoice.
1850            // If it's a retry, the payment intent will be on the invoice itself.
1851            let paymentIntent = invoice ?
1852                invoice.payment_intent :
1853                subscription.latest_invoice.payment_intent;
1854
1855            if (!paymentIntent)
1856                return { subscription, priceId, paymentMethodId };
1857
1858            if (
1859                paymentIntent.status === 'requires_action' ||
1860                (isRetry === true && paymentIntent.status === 'requires_payment_method')
1861            ) {
1862                return stripe
1863                    .confirmCardPayment(paymentIntent.client_secret, {
1864                        payment_method: paymentMethodId,
1865                    })
1866                    .then((result) => {
1867                        if (result.error) {
1868                            // start code flow to handle updating the payment details
1869                            // Display error message in your UI.
1870                            // The card was declined (i.e. insufficient funds, card has expired, etc)
1871                            throw result;
1872                        } else {
1873                            if (result.paymentIntent.status === 'succeeded') {
1874                                // There's a risk of the customer closing the window before callback
1875                                // execution. To handle this case, set up a webhook endpoint and
1876                                // listen to invoice.paid. This webhook endpoint returns an Invoice.
1877                                return {
1878                                    priceId: priceId,
1879                                    subscription: subscription,
1880                                    invoice: invoice,
1881                                    paymentMethodId: paymentMethodId,
1882                                };
1883                            }
1884                        }
1885                    });
1886            } else {
1887                // No customer action needed
1888                return { subscription, priceId, paymentMethodId };
1889            }
1890        }
1891
1892        function handleRequiresPaymentMethod({
1893            subscription,
1894            paymentMethodId,
1895            priceId,
1896        }) {
1897            if (subscription.status === 'active' || subscription.status === 'trialing') {
1898                // subscription is active, no customer actions required.
1899                return { subscription, priceId, paymentMethodId };
1900            } else if (
1901                subscription.latest_invoice.payment_intent.status ===
1902                'requires_payment_method'
1903            ) {
1904                // Using localStorage to store the state of the retry here
1905                // (feel free to replace with what you prefer)
1906                // Store the latest invoice ID and status
1907                localStorage.setItem('latestInvoiceId', subscription.latest_invoice.id);
1908                localStorage.setItem(
1909                    'latestInvoicePaymentIntentStatus',
1910                    subscription.latest_invoice.payment_intent.status
1911                );
1912                throw { error: { message: 'Your card was declined.' } };
1913            } else {
1914                return { subscription, priceId, paymentMethodId };
1915            }
1916        }
1917
1918        function confirmSubscription(intent, isPaymentRetry = false, invoiceId = false, form_wrapper=false, ev) {
1919            var customer_name = $('#first_name', '#'.form_wrapper).val() + ' ' + $('#last_name', '#'.form_wrapper).val(),
1920                customer_email = $('#email', '#'.form_wrapper).val();
1921            stripe.createPaymentMethod({
1922                type: 'card',
1923                card: card[form_wrapper],
1924                billing_details: {
1925                    name: customer_name,
1926                    email: customer_email,
1927                },
1928            })
1929                .then((result) => {
1930                    if (result.error) {
1931                        displayError(result, form_wrapper);
1932                    } else {
1933                        if (isPaymentRetry) {
1934                            // Update the payment method and retry invoice payment
1935                            retryInvoiceWithNewPaymentMethod(
1936                                intent.customer_id,
1937                                result.paymentMethod.id,
1938                                invoiceId,
1939                                form_wrapper,
1940                                ev
1941                            );
1942                        } else {
1943                            // Create the subscription
1944                            createSubscription(
1945                                intent.customer_id,
1946                                result.paymentMethod.id,
1947                                false,
1948                                form_wrapper,
1949                                ev
1950                            );
1951                        }
1952                    }
1953                });
1954        }
1955
1956        function displayError(event, form_wrapper) {
1957            if (event.error) {
1958                alert(event.error.message);
1959            } else if (event) {
1960                alert(event);
1961            }
1962            $('#sc_card_button', '#'+form_wrapper).removeClass('running').removeAttr("disabled");
1963            $('#express-pay-element', '#'+form_wrapper).css('pointer-events', '');
1964        }
1965
1966        function confirmCardPayment(intent, wrap_id, isExpresspayment, ev) {
1967            var customer_name = $('#first_name').val() + ' ' + $('#last_name').val(),
1968                customer_email = $('#email').val();
1969            var confirmCardPaymentCall;
1970            if(isExpresspayment){
1971                confirmCardPaymentCall = stripe.confirmCardPayment(
1972                    intent.clientSecret,
1973                    {payment_method: intent.paymentMethodId},
1974                    {handleActions: false}
1975                );
1976            }else{
1977                confirmCardPaymentCall = stripe.confirmCardPayment(intent.clientSecret, {
1978                    payment_method: {
1979                        card: card[wrap_id],
1980                        billing_details: {
1981                            name: customer_name,
1982                            email: customer_email,
1983                        },
1984                    },
1985                    setup_future_usage: 'off_session'
1986                })
1987            }
1988            confirmCardPaymentCall.then(function(result) {
1989                if (result.error) {
1990                    // Display error.message in your UI.
1991                    if(isExpresspayment){
1992                        ev.complete('fail');
1993                        $('#express-pay-element', '#'+wrap_id).css('pointer-events', '');
1994                        $('#sc_card_button', '#'+wrap_id).removeClass('running').removeAttr("disabled");
1995                    }else{
1996                        displayError(result, wrap_id);
1997                    }                   
1998                } else {
1999                    var paramObj = {};
2000                    $.each($('#sc-payment-form').serializeArray(), function(_, kv) {
2001                        if (kv.name != 'sc-orderbump[]') {
2002                            paramObj[kv.name] = kv.value;
2003                            if (kv.name == 'pay-method') {
2004                                if(isExpresspayment){
2005                                    paramObj[kv.name] = "stripe";
2006                                }
2007                            }
2008                        }                        
2009                    });
2010                    $('input[name="sc-orderbump[]"]').each(function(key, value) {
2011                        if (this.checked) {
2012                            paramObj['sc-orderbump[' + key + ']'] = $(this).val();
2013                        }
2014                    });
2015                    if (intent.sc_temp_order_id) {
2016                        paramObj['sc_temp_order_id'] = intent.sc_temp_order_id;
2017                    }
2018                    paramObj['customer_id'] = intent.customer_id;
2019                    paramObj['intent_id'] = intent.intent_id;
2020                    paramObj['amount'] = intent.amount;
2021                    $.post(studiocart.ajax, paramObj, function(res) {
2022                        var response = JSON.parse(res);
2023                        if ('error' in response) {
2024                            alert(response.error);
2025                            if ('undefined' !== typeof response.fields) {
2026                                $.each(response.fields, function(i, item) {
2027                                    invalidate_field($('[name="' + item['field'] + '"]'), item['message'])
2028                                });
2029                            }
2030                            if(isExpresspayment){
2031                                ev.complete('fail');
2032                            }
2033                            $('#sc_card_button', '#'+wrap_id).find('span.text').text(originalText);
2034                            $('#sc_card_button', '#'+wrap_id).removeClass('running').removeAttr("disabled");
2035                            return false;
2036                        } else {
2037                            if (result.paymentIntent) {
2038                                var data = {
2039                                    'paymentIntent': result.paymentIntent,
2040                                    'action': 'update_stripe_order_status',
2041                                    'response': response,
2042                                    'intent_id': intent.intent_id,
2043                                    'sc-nonce': $('input[name=sc-nonce]').val(),
2044                                };
2045                                if (jQuery('input[name="sc-auto-login"]').length == 1) {
2046                                    data['sc-auto-login'] = 1;
2047                                }
2048                                $.post(studiocart.ajax, data, function(res) {
2049                                    //if (!isNaN(order_id)) {
2050                                    // Insert the token ID into the form so it gets submitted to the server
2051                                    if(isExpresspayment){
2052                                        ev.complete('success');
2053                                    }
2054                                    var response = JSON.parse(res);
2055                                    var form = document.getElementById(wrap_id);
2056                                    form = form.getElementsByTagName('form')[0];
2057                                    if ('undefined' !== typeof response.formAction) {
2058                                        form.setAttribute('action', response.formAction);
2059                                    }
2060                                    var hiddenInput = document.createElement('input');
2061                                    hiddenInput.setAttribute('type', 'hidden');
2062                                    hiddenInput.setAttribute('name', 'sc_order_id');
2063                                    hiddenInput.setAttribute('value', response.order_id);
2064                                    form.appendChild(hiddenInput);
2065                                    var hiddenInput2 = document.createElement('input');
2066                                    hiddenInput2.setAttribute('type', 'hidden');
2067                                    hiddenInput2.setAttribute('name', 'intent_id');
2068                                    hiddenInput2.setAttribute('value', intent.intent_id);
2069                                    form.appendChild(hiddenInput2);
2070                                    if (intent.amount == false) {
2071                                        intent.amount = response.amount
2072                                    }
2073                                    form.submit();
2074                                    //}
2075                                });
2076                            }
2077                        }
2078                    });
2079                }
2080            });
2081        }
2082
2083        /*--Added paypal Scripts--*/
2084        if (studiocart.pay_method == 'paypal') {
2085            $(document).on('studiocart/upsell/ready/accept_link', '.sc-accept-upsell-link', function() {
2086                $('a[href*="sc-upsell-offer=yes"],.sc-accept-upsell-link').attr('href', '#');
2087            });
2088
2089            $(document).on('studiocart/upsell/ready/decline_link', '.sc-decline-upsell-link', function() {
2090                $('a[href*="sc-upsell-offer=no"],.sc-decline-upsell-link').attr('href', studiocart.upsell_decline + '&sc-pp=1');
2091            });
2092        }
2093
2094        $(document).on('studiocart/upsell/accept/paypal', '.sc-accept-upsell-link', function(event) {
2095            let us_data = {
2096                'action': 'paypal_process_upsell',
2097                'sc-order': studiocart.sc_order,
2098                'sc-nonce': studiocart.sc_nonce,
2099                'cancel_url': window.location.href,
2100                'return_url': studiocart.upsell_accept,
2101            };
2102            // flag for downsells
2103            if ('undefined' !== typeof studiocart.is_downsell && '1' == studiocart.is_downsell) {
2104                us_data['downsell'] = 1;
2105            }
2106
2107            $.post(studiocart.ajax, us_data, function(res) {
2108                var response = JSON.parse(res);
2109                if ('undefined' !== typeof response.error) {
2110                    alert(response.error);
2111                    window.location.href = studiocart.upsell_decline + '&sc-pp=1';
2112                } else {
2113                    window.location.href = response.url;
2114                }
2115            });
2116            return false;
2117        });
2118
2119        // Handle paypal form submission.
2120        $(document).on('studiocart/orderform/submit', '#sc-payment-form', function(event) {
2121
2122            var form = '#' + $(this).parent().attr('id');
2123            if ($('.pay-methods', form).length > 0 && $('[name="pay-method"]:checked', form).val() != 'paypal') {
2124                return false;
2125            }
2126            var paramObj = $('#sc-payment-form', form).serializeArray();
2127
2128            paramObj.push(
2129                { name: "sc_page_id", value: studiocart.page_id }, 
2130                { name: "action", value: "sc_paypal_request" },
2131                { name: "cancel_url", value: window.location.href } 
2132            );
2133
2134            //var is_subscription = $('input[name="sc_product_option"]:checked').data('installments');
2135            $.post(studiocart.ajax, paramObj, function(res) {
2136                var response = JSON.parse(res);
2137                if ('undefined' !== typeof response.error) {
2138                    alert(response.error);
2139                    $('#sc_card_button', form).removeClass('running').removeAttr("disabled");
2140                } else {
2141                    window.location.href = response.url;
2142                }
2143            });
2144        });
2145    });
2146
2147    /**
2148     * My Account page tabs nested
2149     */
2150     jQuery('.ncs-nav-tabs li a').click(function() {
2151        var tab_id = jQuery(this).attr('href');
2152
2153        jQuery('.ncs-nav-tabs li a').removeClass('active');
2154        jQuery('.tabcontent').removeClass('active');
2155
2156        jQuery(this).addClass('active');
2157        jQuery("#" + tab_id).addClass('active');
2158    })
2159
2160    /**
2161     * Tabs left aligned on my account page
2162     */
2163    jQuery('ul.tabs-left li.tablinks').click(function() {
2164        var tab_id = jQuery(this).attr('data-tab');
2165
2166        jQuery('ul.tabs-left li.tablinks').removeClass('active');
2167        jQuery('.tabcontent').removeClass('active');
2168
2169        jQuery(this).addClass('active');
2170        jQuery("#" + tab_id).addClass('active');
2171    })
2172
2173    jQuery('.ncs-nav-tabs li a').click(function(event) {
2174        event.preventDefault();
2175        var parents = jQuery(this).parents('.ncs-account-list');
2176        parents.find('.ncs-nav-tabs li a').removeClass('active');
2177        jQuery(this).addClass('active');
2178        return false;
2179    });
2180
2181    /** Edit profile in my account */
2182
2183    jQuery("#editProfile").click(function(){
2184        jQuery(".ep_disabled").prop('disabled',false);
2185        jQuery(".ep_disabled").addClass('enable-input');
2186        jQuery("#editProfileCancel, #all-subscription-address-wrap").show();
2187        jQuery("#newPasswordDiv, #confirmNewPasswordDiv").show();
2188        jQuery(this).hide();
2189        jQuery("#updateProfile").show();
2190    });
2191
2192    jQuery("#editProfileCancel").click(function(){
2193        cancelEditProfile();
2194    });
2195
2196    jQuery("#updateProfile").click(function(){
2197        jQuery("#sc-loader").show();
2198        jQuery(this).prop('disabled',true);
2199        var formData = jQuery('#updateProfileForm').serialize();
2200
2201        let paramObj = {
2202            'action': 'update_user_profile',
2203            'form_data':formData
2204        };
2205
2206        $.post(studiocart.ajax, paramObj, function (res) {
2207            if ('undefined' !== typeof res.error) {
2208                jQuery("#p-alert").text(res.error).addClass('alert-error');
2209            } else {
2210                jQuery("#p-alert").removeClass('alert-error');
2211                jQuery("#p-alert").text(res.message).addClass('alert-success');
2212                cancelEditProfile();
2213            }
2214            jQuery("#updateProfile").prop('disabled',false);
2215            jQuery("#sc-loader").hide();
2216        });
2217        
2218    });
2219
2220    function cancelEditProfile(){
2221        jQuery(".ep_disabled").removeClass('enable-input');
2222        jQuery(".ep_disabled").prop('disabled',true);
2223        jQuery("#editProfileCancel, #all-subscription-address-wrap").hide();
2224        jQuery("#editProfile").show();
2225        jQuery("#newPasswordDiv, #confirmNewPasswordDiv").hide();
2226        jQuery("#updateProfile").hide();
2227    }
2228
2229})(jQuery);

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.