PageSourceSearch

https://gowashy.com/wp-content/plugins/webba-booking-lite/public/js/wbk5-frontend.js?ver=5.0.28

js gowashy.com collected 2026-10-01 14:29:37 UTC 84,053 bytes, 2,207 lines download raw bytes

1class WEBBA5_Form {
2    constructor(container) {
3        const get_this = () => {
4            return this
5        }
6
7        this.container = container
8        get_this().init_nice_select()
9
10        var screen_count = container.find(
11            '.appointment-content-screen-w'
12        ).length
13
14        // wbk_hidden wbk_service_checkbox_holder
15        if (this.container.find('[data-slug="link_payment"]').length > 0) {
16            get_this().initiaize_payments()
17        }
18        jQuery('.wbk_service_description_switcher').click(function (e) {
19            e.preventDefault()
20            jQuery(this).toggleClass('wbk_rotate_90')
21            jQuery(this)
22                .closest('li')
23                .find('.wbk_service_description_holder')
24                .toggleClass('wbk_hidden')
25        })
26        var i = 1
27
28        if (container.find('.wbk_service_categories').length == 0) {
29            get_this()
30                .container.find('.wbk_service_label')
31                .removeClass('wbk_hidden')
32
33            get_this()
34                .container.find('.wbk_service_item')
35                .removeClass('wbk_hidden')
36        }
37
38        container.find('.wbk_service_categories').change(function () {
39            container.find('.wbk_services').prop('checked', false)
40
41            container.find('.wbk_services').trigger('change')
42            if (jQuery(this).val() == 0) {
43                get_this()
44                    .container.find('.wbk_service_label')
45                    .addClass('wbk_hidden')
46
47                get_this()
48                    .container.find('.wbk_service_item')
49                    .addClass('wbk_hidden')
50
51                return
52            }
53            var services_opt = jQuery(this)
54                .find('option:selected')
55                .attr('data-services')
56                .split('-')
57
58            get_this()
59                .container.find('.wbk_service_item')
60                .addClass('wbk_hidden')
61
62            jQuery.each(services_opt, function (index, value) {
63                container
64                    .find('.wbk_service_item[data-servicei_id="' + value + '"]')
65                    .removeClass('wbk_hidden')
66            })
67        })
68
69        container.find('.appointment-content-screen-w').each(function () {
70            if (i == screen_count) {
71                return
72            }
73
74            if (jQuery(this).attr('data-slug') == 'payment_optional') {
75                i++
76                return
77            }
78            get_this().add_status_bar_item(
79                i,
80                jQuery(this).attr('data-title'),
81                jQuery(this).attr('data-slug')
82            )
83            i++
84        })
85
86        container
87            .find('.appointment-content-screen-active-w')
88            .find('.wbk-input')
89            .addClass('linear-animation-w')
90        container
91            .find('.appointment-status-list-w > li')
92            .first()
93            .addClass('active-w')
94
95        container.find('.button-next-w').click(function () {
96            get_this().next_step()
97            return false
98        })
99        container.find('.button-prev-w').click(function () {
100            get_this().prev_step()
101            return false
102        })
103
104        jQuery(document).on(
105            'wbk_after_screen_rendered',
106            function (event, response) {
107                get_this().after_screen_rendered(response)
108            }
109        )
110        this.container.attr('data-step', '1')
111        this.validate_prev_next_buttons()
112        this.validate_form()
113        this.set_input_events()
114
115        if (jQuery('.appointment-content-payment-optional').length > 0) {
116            container.find('.wbk_services').change(function () {
117                var payable = false
118
119                if (!get_this().is_multi_service()) {
120                    if (
121                        container
122                            .find('.wbk_services:checked')
123                            .attr('data-payable') == 'true'
124                    ) {
125                        payable = true
126                    }
127                } else {
128                    get_this()
129                        .container.find('.wbk_service_checkbox:checked')
130                        .each(function () {
131                            if (jQuery(this).attr('data-payable') == 'true') {
132                                payable = true
133                            }
134                        })
135                }
136                if (payable) {
137                    container
138                        .find('[data-slug="payment_optional"]')
139                        .not('li')
140                        .addClass('appointment-content-screen-w')
141                    container
142                        .find('[data-slug="payment_optional"]')
143                        .not('li')
144                        .removeClass(' appointment-content-payment-optional')
145                    container
146                        .find('[data-slug="final_screen"]')
147                        .attr('data-request', 'wbk_approve_payment')
148
149                    if (
150                        get_this().container.find(
151                            '.appointment-status-list-w > li[data-slug="payment_optional"]'
152                        ).length == 0
153                    ) {
154                        get_this().add_status_bar_item(
155                            i,
156                            container
157                                .find('[data-slug="payment_optional"]')
158                                .attr('data-title'),
159                            container
160                                .find('[data-slug="payment_optional"]')
161                                .attr('data-slug')
162                        )
163                    }
164                } else {
165                    container
166                        .find('[data-slug="payment_optional"]')
167                        .not('li')
168                        .removeClass('appointment-content-screen-w')
169                    container
170                        .find('[data-slug="payment_optional"]')
171                        .not('li')
172                        .addClass(' appointment-content-payment-optional')
173                    container
174                        .find('[data-slug="final_screen"]')
175                        .attr('data-request', 'wbk_book')
176
177                    container
178                        .find('li.appointment-content-payment-optional')
179                        .remove()
180                    get_this().remove_status_bar_item('payment_optional')
181                }
182                get_this().update_mobile_step()
183            })
184        }
185
186        this.circle_chart()
187
188        this.update_mobile_step()
189        get_this().init_scroll_bars()
190        if (this.container.find('.wbk_services_hidden').length > 0) {
191            this.get_service_data()
192        }
193
194        jQuery('.wbk-addgg-link').click(function () {
195            window.location.href = jQuery(this).attr('data-link')
196        })
197
198        this.container.find('form').on('submit', function (e) {
199            e.preventDefault()
200        })
201    }
202    async get_service_data() {
203        this.container
204            .find('.appointment-content-scroll-w')
205            .append('<div class="wbk-loading"></div>')
206        var response = await this.do_request('wbk_prepare_service_data')
207        response = jQuery.parseJSON(response)
208        this.prepare_service_data_init(response)
209        this.container.find('.wbk-loading').remove()
210        this.container.find('.wbk_date_picked_row').removeClass('wbk_hidden')
211    }
212
213    is_multi_service() {
214        return this.container.find('.wbk_service_checkbox').length > 0
215    }
216    circle_chart() {
217        var color = this.container
218            .find('.circle-chart-wb')
219            .attr('data-circle-color')
220        this.container.find('.circle-chart-wb').easyPieChart({
221            animate: false,
222            barColor: '#ffffff',
223            trackColor: color,
224            scaleColor: false,
225            lineWidth: 6,
226        })
227    }
228
229    validate_stripe_input(card_maintained) {
230        const get_this = () => {
231            return this
232        }
233        if (!card_maintained) {
234            this.container
235                .find('.button-approve-stripe-payment')
236                .prop('disabled', true)
237            return false
238        } else {
239            this.container
240                .find('.button-approve-stripe-payment')
241                .prop('disabled', false)
242            return true
243        }
244    }
245
246    process_conditional(elem) {
247        const get_this = () => {
248            return this
249        }
250        if (this.container.find('[name="_wpcf7cf_options"]').length == 0) {
251            return
252        }
253        var condition = jQuery.parseJSON(
254            this.container.find('[name="_wpcf7cf_options"]').val()
255        )
256
257        jQuery.each(condition.conditions, function (i, data) {
258            var and_rules = data.and_rules
259            var then_field = data.then_field
260
261            jQuery.each(and_rules, function (k, rule) {
262                if (
263                    rule.if_field == elem.attr('name') &&
264                    rule.operator == 'equals'
265                ) {
266                    if (rule.if_value == elem.val()) {
267                        jQuery('[data-id="' + then_field + '"]').css(
268                            'display',
269                            'block'
270                        )
271                    } else {
272                        jQuery('[data-id="' + then_field + '"]').css(
273                            'display',
274                            'none'
275                        )
276                    }
277                }
278                if (
279                    rule.if_field == elem.attr('name') &&
280                    rule.operator == 'not equals'
281                ) {
282                    if (rule.if_value != elem.val()) {
283                        jQuery('[data-id="' + then_field + '"]').css(
284                            'display',
285                            'block'
286                        )
287                    } else {
288                        jQuery('[data-id="' + then_field + '"]').css(
289                            'display',
290                            'none'
291                        )
292                    }
293                }
294            })
295        })
296    }
297
298    set_input_events() {
299        const get_this = () => {
300            return this
301        }
302        this.container.find('.wbk-input').on('input', function () {
303            get_this().process_conditional(jQuery(this))
304            get_this().validate_form()
305        })
306        this.container.find('.wbk-file').on('input', function () {
307            get_this().validate_form()
308        })
309        this.container.find('.wbk-book-quantity').change(function () {
310            get_this().set_multiple_data()
311        })
312
313        this.container.find('[name="quantity"]').trigger('change')
314        this.container.find('.wbk-input').change(function () {
315            get_this().process_conditional(jQuery(this))
316            get_this().validate_form()
317        })
318    }
319
320    get_multi_service_name_by_id(service_id) {
321        return this.container
322            .find('.wbk_service_checkbox[value="' + service_id + '"]')
323            .closest('.wbk_service_item')
324            .find('.wbk_single_service_title')
325            .html()
326    }
327
328    after_screen_rendered(response) {
329        const get_this = () => {
330            return this
331        }
332        var request = this.container
333            .find('.appointment-content-screen-active-w')
334            .attr('data-request')
335
336        switch (request) {
337            case 'wbk_prepare_service_data':
338                get_this().prepare_service_data_init(response)
339                var value = ''
340                if (get_this().is_multi_service()) {
341                    value = []
342                    get_this()
343                        .container.find('.wbk_service_checkbox:checked')
344                        .each(function () {
345                            value.push(
346                                jQuery(this)
347                                    .closest('.wbk_service_checkbox_holder')
348                                    .find('.wbk_single_service_title')
349                                    .html()
350                            )
351                        })
352                } else {
353                    value = get_this()
354                        .container.find('.wbk_services:checked')
355                        .closest('.custom-radiobutton-w')
356                        .find('.wbk_single_service_title')
357                        .text()
358                    value = [value]
359                }
360
361                get_this().set_step_subtitle('services', value)
362
363                break
364            case 'wbk_render_booking_form':
365                var value = []
366                const checked = get_this()
367                    .container.find('.wbk_local_time_checkbox')
368                    .is(':checked')
369                get_this()
370                    .container.find('.wbk_times > option:selected')
371                    .each(function () {
372                        var date_time_string = ''
373                        if (checked) {
374                            date_time_string = jQuery(this).attr(
375                                'data-time_string_local'
376                            )
377                        } else {
378                            date_time_string =
379                                jQuery(this).attr('data-time_string')
380                        }
381                        value.push(date_time_string)
382                    })
383                get_this().set_step_subtitle('date_time', value)
384                this.container
385                    .find('.appointment-content-screen-active-w')
386                    .html(
387                        '<div style="display:none" class="hider-w">' +
388                            response +
389                            '</div>'
390                    )
391
392                this.init_nice_select()
393                get_this().init_scroll_bars()
394                this.container
395                    .find('.appointment-content-screen-active-w')
396                    .find('.hider-w')
397                    .fadeIn('slow', function () {})
398
399                this.container.find('.wbk-checkbox-custom').each(function () {
400                    var exculsive = jQuery(this).hasClass(
401                        'wpcf7-exclusive-checkbox'
402                    )
403                    var chk_id = jQuery(this).attr('id')
404                    var chk_label = jQuery("label[for='" + chk_id + "']").html()
405                    var new_checkbox_html =
406                        '<div class="wbk_checkbox_container"><label class="wbk-input-label" for="' +
407                        chk_id +
408                        '" >' +
409                        chk_label +
410                        '</label>'
411                    var checkbox_data_validation = ''
412                    if (jQuery(this).hasClass('wpcf7-validates-as-required')) {
413                        checkbox_data_validation =
414                            ' data-validation="not_empty" '
415                    }
416                    new_checkbox_html +=
417                        '<input type="text" ' +
418                        checkbox_data_validation +
419                        '  class="wbk-input wbk_chk_proxy wbk-custom-field wbk_hidden" name="' +
420                        chk_id +
421                        '">'
422
423                    var i = 0
424                    jQuery(this)
425                        .find('input[type="checkbox"]')
426                        .each(function () {
427                            i++
428                            var chk_val = jQuery(this).attr('value')
429
430                            new_checkbox_html +=
431                                '<label for="' +
432                                chk_id +
433                                '_' +
434                                i +
435                                '" class="checkbox-row-w one-row-w">'
436                            new_checkbox_html +=
437                      
437          '<span class="checkbox-custom-w">' +
438                                '<input type="checkbox" ' +
439                                checkbox_data_validation +
440                                ' data-exclusive="' +
441                                exculsive +
442                                '" data-id="' +
443                                chk_id +
444                                '" class="wbk_input_checkbox_option"' +
445                                'name="' +
446                                chk_id +
447                                '" id="' +
448                                chk_id +
449                                '_' +
450                                i +
451                                '" value="' +
452                                chk_val +
453                                '">' +
454                                '<span class="checkmark-w"></span>' +
455                                '</span>' +
456                                '<span class="checkbox-text-w">' +
457                                '<span class="checkbox-title-w">' +
458                                chk_val +
459                                '</span>' +
460                                '</span>' +
461                                '</label>'
462                        })
463                    new_checkbox_html +=
464                        '</div><div style="display:block;width:100%;height:50px"></div>'
465                    get_this()
466                        .container.find("label[for='" + chk_id + "']")
467                        .replaceWith(new_checkbox_html)
468                    jQuery(this).remove()
469                })
470                get_this()
471                    .container.find('.appointment-content-screen-active-w')
472                    .find('[name="wbk-name"]')
473                    .attr('name', 'custname')
474                get_this()
475                    .container.find('.appointment-content-screen-active-w')
476                    .find('[name="wbk-email"]')
477                    .attr('name', 'email')
478                get_this()
479                    .container.find('.appointment-content-screen-active-w')
480                    .find('[name="wbk-phone"]')
481                    .attr('name', 'phone')
482
483                get_this()
484                    .container.find('.appointment-content-screen-active-w')
485                    .find(
486                        '.wbk-text:not([name="custname"]):not([name="email"]):not([name="phone"]), .wbk-textarea:not([name="wbk-comment"]), .wbk-select:not(.nice-select):not(.wbk-book-quantity)'
487                    )
488                    .addClass('wbk-custom-field')
489                    .removeAttr('id')
490
491                get_this()
492                    .container.find('.appointment-content-screen-active-w')
493                    .find('.wbk-text , .wbk-textarea, .wbk-select')
494                    .addClass('wbk-input')
495
496                get_this()
497                    .container.find('.appointment-content-screen-active-w')
498                    .find('.wbk-file')
499                    .each(function () {
500                        if (jQuery(this).attr('aria-required') == 'true') {
501                            jQuery(this).attr(
502                                'data-validation',
503                                'file_required'
504                            )
505                        }
506                    })
507
508                get_this()
509                    .container.find('.appointment-content-screen-active-w')
510                    .find('.wbk-input')
511                    .each(function () {
512                        if (jQuery(this).attr('aria-required') == 'true') {
513                            jQuery(this).attr('data-validation', 'not_empty')
514                        }
515                    })
516                get_this()
517                    .container.find('[name="email"]')
518                    .attr('data-validation', 'email')
519                get_this()
520                    .container.find('[name="phone"]')
521                    .attr('data-validation', 'phone')
522
523                // custom checkbox processing
524                jQuery('.wbk_input_checkbox_option').change(function () {
525                    var check_id = jQuery(this).attr('data-id')
526                    if (jQuery(this).attr('data-exclusive') == 'true') {
527                        jQuery('input[data-id="' + check_id + '"]')
528                            .not(this)
529                            .prop('checked', false)
530                    }
531                    var values = []
532                    jQuery('input[data-id="' + check_id + '"]').each(
533                        function () {
534                            if (jQuery(this).is(':checked')) {
535                                values.push(jQuery(this).attr('value'))
536                            }
537                        }
538                    )
539                    values = values.join()
540                    jQuery(this)
541                        .closest('.wbk_checkbox_container')
542                        .find('.wbk_chk_proxy')
543                        .val(values)
544                    jQuery(this)
545                        .closest('.wbk_checkbox_container')
546                        .find('.wbk_chk_proxy')
547                        .trigger('change')
548                })
549
550                jQuery(document).trigger('wbk_form_rendered')
551
552                this.set_input_events()
553
554                // custom data processing
555                get_this()
556                    .container.find('[name="wbk-comment"]')
557                    .attr('name', 'comment')
558                get_this()
559                    .container.find('.wbk-custom-field')
560                    .change(function () {
561                        var custom_data = []
562                        get_this()
563                            .container.find('.wbk-custom-field')
564                            .each(function () {
565                                if (
566                                    jQuery(this).closest(
567                                        '[data-class="wpcf7cf_group"]'
568                                    ).length > 0
569                                ) {
570                                    if (
571                                        jQuery(this)
572                                            .closest(
573                                                '[data-class="wpcf7cf_group"]'
574                                            )
575                                            .attr('style') == 'display: none;'
576                                    ) {
577                                        return
578                                    }
579                                }
580                                var id = wbk_strip_html(
581                                    jQuery(this).attr('name')
582                                )
583                                var val = ''
584                                var title = ''
585
586                                var val = wbk_strip_html(jQuery(this).val())
587
588                                title = wbk_strip_html(
589                                    get_this()
590                                        .container.find(
591                                            'label[for="' + id + '"]'
592                                        )
593                                        .html()
594                                )
595                                custom_data.push([id, title, val])
596                            })
597                        custom_data = JSON.stringify(custom_data)
598                        get_this()
599                            .container.find('.wbk-extra')
600                            .html(custom_data)
601                    })
602
603                this.container
604                    .find('.wbk-input')
605                    .not('[name="custname"]')
606                    .not('[name="email"]')
607                    .not('[name="phone"]')
608                    .not('.wbk_not_change_amount')
609                    .change(function () {
610                        get_this().update_amount()
611                    })
612
613                get_this().container.find('.wbk-custom-field').trigger('change')
614
615                get_this().set_multiple_data()
616
617                if (wbkl10n.phoneformat.trim() != '') {
618                    get_this()
619                        .container.find('[name="phone"]')
620                        .mask(wbkl10n.phoneformat)
621                }
622
623                get_this().validate_form()
624                return
625                break
626            case 'wbk_book':
627                if (
628                    this.container
629                        .find('.appointment-content-screen-active-w')
630                        .attr('data-slug') == 'payment_optional' ||
631                    this.container
632                        .find('.appointment-content-screen-active-w')
633                        .attr('data-slug') == 'payment'
634                ) {
635                    this.container
636                        .find('.appointment-content-screen-active-w')
637                        .append(response.thanks_message)
638                    get_this().initiaize_payments()
639                }
640                break
641        }
642        this.validate_form()
643    }
644
645    initiaize_payments() {
646        const get_this = () => {
647            return this
648        }
649
650        this.container.find('.button-prev-w').remove()
651        this.container
652            .find('.button-next-w')
653            .html(
654                wbkl10n.continue +
655                    '<span class="btn-ring-wb" style="opacity: 0;"></span>'
656            )
657        this.container
658            .find('.button-next-w')
659            .after(
660                '<button type="button" style="display:none" class="button-w button-approve-stripe-payment" disabled>' +
661                    wbkl10n.approve_payment_text +
662                    '<span class="btn-ring-wb" style="opacity: 0;"></span></button>'
663            )
664        this.container.find('.button-next-w').prop('disabled', true)
665        get_this().init_scroll_bars()
666        this.init_nice_select()
667
668        get_this()
669            .container.find('.wbk_coupon_input')
670            .on('input', function () {
671                if (jQuery(this).val().trim() == '') {
672                    get_this()
673                        .container.find('.wbk_apply_coupon')
674                        .attr('disabled', true)
675                } else {
676                    get_this()
677                        .container.find('.wbk_apply_coupon')
678                        .attr('disabled', false)
679                }
680            })
681        get_this()
682            .container.find('.wbk_apply_coupon')
683            .click(function () {
684                get_this().apply_coupon()
685            })
686
687        get_this()
688            .container.find('[name="payment-method"')
689            .change(function () {
690                var method = jQuery(this).val()
691                get_this()
692                    .container.find('.wbk_payment_method_desc')
693                    .toggle(false)
694
695                get_this()
696                    .container.find('[value="' + method + '"]')
697                    .parent()
698                    .siblings('.wbk_payment_method_desc')
699                    .slideToggle()
700
701                if (method == 'stripe') {
702                    get_this().container.find('.button-next-w').toggle(false)
703                    get_this()
704                        .container.find('.button-approve-stripe-payment')
705                        .toggle(true)
706
707                    if (
708                        get_this().container.find('.StripeElement').length == 0
709                    ) {
710                        var style = {
711                            base: {
712                                lineHeight: '50px',
713                                color: '#000',
714                                fontSize: '16px',
715                            },
716                        }
717                        var locale = jQuery('html').attr('lang')
718                        if (
719                            locale.length == '' ||
720                            locale.length == 'undefined'
721                        ) {
722                            locale = 'en'
723                        }
724                        if (locale.length > 2) {
725                            locale = locale.slice(0, 2)
726                        }
727                        get_this().stripe = Stripe(wbkl10n.stripe_public_key)
728                        var elements = get_this().stripe.elements()
729                        var stripe_hide_postal =
730                            wbkl10n.stripe_hide_postal == 'true'
731                        get_this().card = elements.create('card', {
732                            style: style,
733                            hidePostalCode: stripe_hide_postal,
734                        })
735                        get_this().card.mount('#card-element')
736                        get_this().card.addEventListener(
737                            'change',
738                            function (event) {
739                                if (event.error) {
740                                    get_this()
741                                        .container.find('#card-errors')
742                                        .html(event.error.message)
743                                } else {
744                                    get_this()
745                                        .container.find('#card-errors')
746                                        .html('')
747                                }
748                                if (event.complete) {
749                                    get_this().validate_stripe_input(true)
750                                } else {
751                                    get_this().validate_stripe_input(false)
752                                }
753                            }
754                        )
755                        get_this().container.find('')
756                    }
757                } else {
758                    get_this().container.find('.button-next-w').toggle(true)
759                    get_this()
760                        .container.find('.button-approve-stripe-payment')
761                        .toggle(false)
762                }
763            })
764
765        get_this()
766            .container.find('.button-approve-stripe-payment')
767            .click(function () {
768                var valid = true
769                var wbk_stripe_fields = {}
770                var wbk_stripe_address = {}
771                var details_provided = false
772                jQuery('.wbk-stripe-additional-field')
773                    .not('.nice-select')
774                    .each(function () {
775                        if (jQuery(this).val().trim() == '') {
776                            jQuery(this).prev('label').addClass('input-error-w')
777
778                            valid = false
779                        }
780                        var current_field = jQuery(this).attr('data-field')
781                        if (current_field == 'name') {
782                            wbk_stripe_fields[current_field] =
783                                jQuery(this).val()
784                        } else {
785                            details_provided = true
786                            wbk_stripe_address[current_field] =
787                                jQuery(this).val()
788                        }
789                    })
790                if (!valid) {
791                    return false
792                }
793                if (details_provided) {
794                    wbk_stripe_fields['address'] = wbk_stripe_address
795                }
796                get_this().change_button_status(jQuery(this), 'loading')
797                get_this()
798                    .stripe.createPaymentMethod('card', get_this().card, {
799                        billing_details: wbk_stripe_fields,
800                    })
801                    .then(function (result) {
802                        if (result.error) {
803                            get_this().change_button_status(
804                                get_this().container.find(
805                                    '.button-approve-stripe-payment'
806                                ),
807                                'regular'
808                            )
809                            get_this().show_error(result.error.message)
810                        } else {
811                            get_this()
812                                .container.find('.wbk_stripe_payment_method_id')
813                                .val(result.paymentMethod.id)
814
815                            get_this().stripe_process_payment()
816                        }
817                    })
818
819                return false
820            })
821
822        if (get_this().container.find('[name="payment-method"').length == 0) {
823            jQuery('.button-next-w').remove()
824            return
825        }
826
827        this.set_input_events()
828        get_this().validate_form()
829    }
830
831    async apply_coupon() {
832        var btn = this.container.find('.wbk_apply_coupon')
833        this.change_button_status(btn, 'loading')
834
835        var response = await this.do_request('wbk_apply_coupon')
836        if (response == false) {
837            this.show_error('An unexpected error occoured.')
838            return
839        }
840        response = jQuery.parseJSON(response)
841        if (response.status == 'fail') {
842            this.show_error(response.description)
843            return
844        }
845        if (response.status == 'payment_complete') {
846            this.finalize(response)
847        }
848        this.change_button_status(btn, 'regular')
849        if (response.status == 'applied') {
850            this.container
851                .find('.payment-details-wrapper-w')
852                .replaceWith(response.payment_card)
853        }
854    }
855
856    async update_amount() {
857        if (this.container.find('.wbk_quantities option').length == 0) {
858            return
859        }
860        var valid = true
861        this.container.find('.wbk_quantities option').each(function () {
862            if (jQuery(this).val() == 0) {
863                valid = false
864            }
865        })
866        if (!valid) {
867            return
868        }
869        if (this.container.find('.payment-details-wrapper-w').length == 0) {
870            if (this.container.find('.wbk_dynamic_total').length == 0) {
871                this.set_step_subtitle('payment_optional', [
872                    '<span class="wbk_loader_s"></span>',
873                ])
874                this.set_step_subtitle('payment', [
875                    '<span class="wbk_loader_s"></span>',
876                ])
877            } else {
878                this.container
879                    .find('.wbk_dynamic_total')
880                    .replaceWith('<span class="wbk_loader_s"></span>')
881            }
882            var response = await this.do_request('wbk_calculate_amounts')
883            if (response == false) {
884                this.show_error('An unexpected error occoured.')
885                return
886            }
887            response = jQuery.parseJSON(response)
888            if (response.status == 'fail') {
889                this.show_error(response.description)
890                return
891            }
892            this.container
893                .find('.wbk_loader_s')
894                .replaceWith(
895                    '<span class="wbk_dynamic_total">
895' +
896                        response.total_formated +
897                        '</span>'
898                )
899            this.container
900                .find('.wbk_form_label_total')
901                .html(response.total_formated)
902        } else {
903            this.remove_step_subtitle('payment_optional')
904            this.remove_step_subtitle('payment')
905        }
906    }
907
908    async stripe_process_payment() {
909        const get_this = () => {
910            return this
911        }
912        var response = await this.do_request('wbk_approve_payment')
913        if (response == false) {
914            get_this().change_button_status(
915                get_this().container.find('.button-approve-stripe-payment'),
916                'regular'
917            )
918            this.show_error('An unexpected error occoured.')
919            return
920        }
921        response = jQuery.parseJSON(response)
922        if (response.status == 'fail') {
923            get_this().change_button_status(
924                get_this().container.find('.button-approve-stripe-payment'),
925                'regular'
926            )
927            this.show_error(response.description)
928            return
929        }
930        if (response.status == 'success') {
931            if (parseInt(response.result[0]) == 1) {
932                if (response.result.thanks_message != '') {
933                    this.finalize(response.result)
934                }
935                if (response.result.url != '') {
936                    window.location.href = response.result.url
937                }
938            } else {
939                this.stripe
940                    .handleCardAction(response.result[1])
941                    .then((result) => {
942                        if (result.error) {
943                            this.show_error(result.error)
944                            get_this().change_button_status(
945                                get_this().container.find(
946                                    '.button-approve-stripe-payment'
947                                ),
948                                'regular'
949                            )
950                        } else {
951                            get_this()
952                                .container.find('.wbk_stripe_payment_intent_id')
953                                .val(result.paymentIntent.id)
954
955                            get_this()
956                                .container.find('.wbk_stripe_payment_method_id')
957                                .val('')
958                            this.stripe_process_payment()
959                        }
960                    })
961            }
962        }
963        if (response.status == 'fail') {
964            get_this().change_button_status(
965                get_this().container.find('.button-approve-stripe-payment'),
966                'regular'
967            )
968            this.show_error(response.result[1])
969        }
970    }
971
972    remove_step_subtitle(slug) {
973        this.container
974            .find(".appointment-status-list-w li[data-slug='" + slug + "']")
975            .find('.subtitle-list-w')
976            .remove()
977    }
978
979    set_step_subtitle(slug, list) {
980        this.remove_step_subtitle(slug)
981        var html = '<ul class="subtitle-list-w" style="display:none;">'
982        jQuery.each(list, function (index, value) {
983            html += '<li>' + value + '</li>'
984        })
985        html += '</ul>'
986        this.container
987            .find(".appointment-status-list-w li[data-slug='" + slug + "']")
988            .find('.text-w')
989            .append(html)
990        this.container
991            .find(".appointment-status-list-w li[data-slug='" + slug + "']")
992            .find('.text-w')
993            .find('ul')
994            .slideToggle()
995    }
996
997    init_scroll_bars() {
998        if (
999            this.container
1000                .find('.appointment-content-screen-active-w')
1001                .attr('data-request') == 'wbk_render_booking_form'
1002        ) {
1003            if (
1004                this.container
1005                    .find('.appointment-content-screen-active-w')
1006                    .find('.nice-select').length > 0
1007            ) {
1008                jQuery('.appointment-content-scroll-w').css('height', 'auto')
1009                if (jQuery('.wbk_custom_form_spacer').length == 0) {
1010                    jQuery('.appointment-content-scroll-w').append(
1011                        '<div class="wbk_custom_form_spacer"></div>'
1012                    )
1013                }
1014                return
1015            }
1016        }
1017        jQuery('.appointment-content-scroll-w').css('height', '555px')
1018        Scrollbar.initAll({ alwaysShowTracks: true, damping: 0.5 })
1019    }
1020
1021    async search_time_slots() {
1022        const get_this = () => {
1023            return this
1024        }
1025        if (wbkl10n.multi_booking != 'enabled') {
1026            this.deselect_all_slots()
1027        }
1028        this.container.find('.dynamic-slots-w').remove()
1029        this.container
1030            .find('.appointment-content-scroll-w')
1031            .append('<div class="wbk-loading"></div>')
1032        var response = await this.do_request('wbk_search_time')
1033        if (response == false) {
1034            this.show_error('An unexpected error occoured.')
1035            return
1036        }
1037        if (response.status == 'fail') {
1038            this.show_error(response.description)
1039            return
1040        }
1041        response = jQuery.parseJSON(response)
1042        this.container.find('.wbk-loading').remove()
1043        Scrollbar.destroyAll()
1044        this.container
1045            .find('.appointment-content-screen-active-w')
1046            .append(
1047                '<div class="dynamic-slots-w dynamic-content-w">' +
1048                    response.data +
1049                    '</div>'
1050            )
1051        get_this().init_scroll_bars()
1052        this.container.find('.timeslot_radio-w').click(function () {
1053            var time = jQuery(this)
1054                .closest('label')
1055                .find('.time-w')
1056                .attr('data-start')
1057            var service_id = jQuery(this)
1058                .closest('label')
1059                .find('.time-w')
1060                .attr('data-service')
1061            var time_string =
1062                jQuery(this)
1063                    .closest('label')
1064                    .find('.time-w')
1065                    .attr('data-server-date') +
1066                ' ' +
1067                jQuery(this)
1068                    .closest('label')
1069                    .find('.time-w')
1070                    .attr('data-server-time')
1071            var time_string_local =
1072                jQuery(this)
1073                    .closest('label')
1074                    .find('.time-w')
1075                    .attr('data-local-date') +
1076                ' ' +
1077                jQuery(this)
1078                    .closest('label')
1079                    .find('.time-w')
1080                    .attr('data-local-time')
1081            get_this().select_time_slot(
1082                time,
1083                time_string,
1084                time_string_local,
1085                service_id
1086            )
1087        })
1088        this.container.find('.appointment-content-screen-active-w')
1089        if (this.container.find('.time-w').length > 0) {
1090            if (
1091                this.container
1092                    .find('.time-w')
1093                    .first()
1094                    .attr('data-server-time') !=
1095                this.container.find('.time-w').first().attr('data-local-time')
1096            ) {
1097                this.container
1098                    .find('.wbl_local_time_switcher')
1099                    .removeClass('wbk_hidden')
1100            }
1101            this.container.find('.wbk_local_time_checkbox').change(function () {
1102                const checked = jQuery(this).is(':checked')
1103                get_this().switch_local_time(checked)
1104                get_this().render_selected_time_slots_list()
1105            })
1106            const checked = get_this()
1107                .container.find('.wbk_local_time_checkbox')
1108                .is(':checked')
1109            if (!checked) {
1110                this.container.find('.wbk_local_time_checkbox').trigger('click')
1111            }
1112        }
1113    }
1114    switch_local_time(state) {
1115        if (state) {
1116            this.container.find('.time-w').each(function () {
1117                jQuery(this).html(jQuery(this).attr('data-local-time'))
1118            })
1119        } else {
1120            this.container.find('.time-w').each(function () {
1121                jQuery(this).html(jQuery(this).attr('data-server-time'))
1122            })
1123        }
1124    }
1125
1126    deselect_all_slots() {
1127        this.container.find('.wbk_times > option').remove()
1128        this.container.find('.wbk_services_final > option').remove()
1129        this.render_selected_time_slots_list()
1130    }
1131
1132    deselect_time_slot(timestamp, service_id) {
1133        this.container.find('.wbk_times > option').each(function () {
1134            if (
1135                jQuery(this).attr('value') == timestamp &&
1136                jQuery(this).attr('data-service') == service_id
1137            ) {
1138                jQuery(this).remove()
1139            }
1140        })
1141        this.container.find('.wbk_services_final > option').each(function () {
1142            if (
1143                jQuery(this).attr('value') == service_id &&
1144                jQuery(this).attr('data-time') == timestamp
1145            ) {
1146                jQuery(this).remove()
1147            }
1148        })
1149        this.container.find('.time-w').each(function () {
1150            if (
1151                jQuery(this).attr('data-start') == timestamp &&
1152                jQuery(this).attr('data-service') == service_id
1153            ) {
1154                jQuery(this)
1155                    .closest('label')
1156                    .find('.timeslot_radio-w')
1157                    .prop('checked', false)
1158            }
1159        })
1160
1161        this.render_selected_time_slots_list()
1162    }
1163
1164    select_time_slot(timestamp, time_string, time_string_local, service_id) {
1165        const get_this = () => {
1166            return this
1167        }
1168        var exit = false
1169        this.container.find('.wbk_times option').each(function () {
1170            if (
1171                parseInt(jQuery(this).attr('value')) == parseInt(timestamp) &&
1172                parseInt(jQuery(this).attr('data-service')) ==
1173                    parseInt(service_id)
1174            ) {
1175                exit = true
1176                return
1177            }
1178        })
1179        if (exit) {
1180            return
1181        }
1182
1183        if (wbkl10n.multi_booking != 'enabled') {
1184            this.deselect_all_slots()
1185        }
1186        this.container
1187            .find('.wbk_times')
1188            .append(
1189                '<option  data-time_string_local="' +
1190                    time_string_local +
1191                    '" data-time_string="' +
1192                    time_string +
1193                    '" data-service="' +
1194                    service_id +
1195                    '" value="' +
1196                    timestamp +
1197                    '" >' +
1198                    time_string +
1199                    '</option>'
1200            )
1201        this.container
1202            .find('.wbk_services_final')
1203            .append(
1204                '<option data-time="' +
1205                    timestamp +
1206                    '" value="' +
1207                    service_id +
1208                    '" >' +
1209                    service_id +
1210                    '</option>'
1211            )
1212        this.container.find('.wbk_times option').prop('selected', true)
1213        this.container.find('.wbk_times').trigger('change')
1214
1215        this.container.find('.wbk_services_final option').prop('selected', true)
1216        this.container.find('.wbk_services_final').trigger('change')
1217
1218        this.render_selected_time_slots_list()
1219        if (wbkl10n.auto_next == 'enabled') {
1220            this.container.find('.button-next-w').trigger('click')
1221        }
1222    }
1223    add_class_for_seleced_slots() {
1224        this.container.find('.timeslot_radio-w').each(function () {
1225            if (jQuery(this).is(':checked')) {
1226                jQuery(this)
1227                    .siblings('.radio-time-block-w')
1228                    .addClass('wb_slot_checked')
1229            } else {
1230                jQuery(this)
1231                    .siblings('.radio-time-block-w')
1232                    .removeClass('wb_slot_checked')
1233            }
1234        })
1235    }
1236
1237    render_selected_time_slots_list() {
1238        const get_this = () => {
1239            return this
1240        }
1241        this.container.find('.details-list-w > li').remove()
1242        this.container
1243            .find('.wbk_times > option')
1244            .not('.nice-select > option')
1245            .each(function () {
1246                var service_id = jQuery(this).attr('data-service')
1247                var time = jQuery(this).attr('value')
1248
1249                const checked = get_this()
1250                    .container.find('.wbk_local_time_checkbox')
1251                    .is(':checked')
1252                var date_time_string = ''
1253                if (checked) {
1254                    date_time_string = jQuery(this).attr(
1255                        'data-time_string_local'
1256                    )
1257                } else {
1258                    date_time_string = jQuery(this).attr('data-time_string')
1259                }
1260                var service_name = ''
1261                if (get_this().is_multi_service()) {
1262                    service_name =
1263                        get_this().get_multi_service_name_by_id(service_id) +
1264                        ' '
1265                }
1266
1267                get_this()
1268                    .container.find('.details-list-w')
1269                    .append(
1270                        '<li><span class="details-item-text-w">' +
1271                            service_name +
1272                            date_time_string +
1273                            '</span><span data-service="' +
1274                            service_id +
1275                            '" data-time="' +
1276                            time +
1277                            '" class="block-close-wb"></span></li>'
1278                    )
1279                get_this()
1280                    .container.find('.block-close-wb')
1281                    .last()
1282                    .unbind('click')
1283                get_this()
1284                    .container.find('.block-close-wb')
1285                    .last()
1286                    .click(function () {
1287                        get_this().deselect_time_slot(time, service_id)
1288                    })
1289            })
1290        this.add_class_for_seleced_slots()
1291        this.validate_form()
1292    }
1293    set_multiple_data() {
1294        const get_this = () => {
1295            return this
1296        }
1297        this.container.find('.wbk_quantities option').remove()
1298        this.container.find('.wbk_services_per_slot option').remove()
1299
1300        var qty_html = ''
1301        var services_html = ''
1302        this.container.find('.wbk_times option').each(function () {
1303            var service_id = jQuery(this).attr('data-service')
1304            var timestamp = jQuery(this).attr('value')
1305            var quantity_for_service = get_this()
1306                .container.find(
1307                    '.wbk-book-quantity[data-service=' + service_id + ']'
1308                )
1309                .val()
1310
1311            qty_html +=
1312                '<option value="' +
1313                quantity_for_service +
1314                '">' +
1315                quantity_for_service +
1316                '</option>'
1317            services_html +=
1318                '<option value="' + service_id + '">' + service_id + '</option>'
1319        })
1320
1321        this.container.find('.wbk_quantities').html(qty_html)
1322        this.container.find('.wbk_services_per_slot').html(services_html)
1323        this.container.find('.wbk_quantities option').prop('selected', true)
1324        this.container
1325            .find('.wbk_services_per_slot option')
1326            .prop('selected', true)
1327    }
1328    prepare_service_data_init(response) {
1329        const get_this = () => {
1330            return this
1331        }
1332
1333        var disability_result = []
1334        disability_result.push(true)
1335        var range_min = undefined
1336        var range_max = undefined
1337        var initial_date = undefined
1338        var allowed_timestamps = []
1339
1340        this.disabled_dates = response.disabilities.split(';')
1341        this.disabled_days_of_week = response.week_disabilities
1342
1343        this.disabled_dates_horizontal = []
1344        var last_date = new Date()
1345        last_date.setDate(last_date.getDate() + 360)
1346
1347        for (var d = new Date(); d <= last_date; d.setDate(d.getDate() + 1)) {
1348            var date_string =
1349                d.getFullYear() + ',' + d.getMonth() + ',' + d.getDate()
1350            if (!this.disabled_dates.includes(date_string)) {
1351                this.disabled_dates_horizontal.push(
1352                    d.getFullYear() +
1353                        '/' +
1354                        ('0' + (d.getMonth() + 1)).slice(-2) +
1355                        '/' +
1356                        ('0' + d.getDate()).slice(-2)
1357                )
1358            }
1359        }
1360
1361        if (response.disabilities != '') {
1362            var day_disabilities_all = response.disabilities.split(';')
1363            var index
1364            for (index = 0; index < day_disabilities_all.length; index++) {
1365                var disablity_current_day =
1366                    day_disabilities_all[index].split(',')
1367                disability_result.push(disablity_current_day)
1368                var converte_date = new Date(
1369                    disablity_current_day[0],
1370                    disablity_current_day[1],
1371                    disablity_current_day[2],
1372                    0,
1373                    0,
1374                    0
1375                )
1376                allowed_timestamps.push(converte_date.getTime())
1377            }
1378            if (disability_result.length > 1) {
1379                initial_date = disability_result[1]
1380            }
1381        }
1382
1383        if (response.limits != '') {
1384            var date_range = response.limits.split('-')
1385
1386            range_min = date_range[0].split(',')
1387            range_min[0] = parseInt(range_min[0])
1388            range_min[1] = parseInt(range_min[1]) - 1
1389            range_min[2] = parseInt(range_min[2])
1390
1391            range_max = date_range[1].split(',')
1392            range_max[0] = parseInt(range_max[0])
1393            range_max[1] = parseInt(range_max[1]) - 1
1394            range_max[2] = parseInt(range_max[2])
1395
1396            var range_start = new Date(range_min[0], range_min[1], range_min[2])
1397            var range_end = new Date(range_max[0], range_max[1], range_max[2])
1398            var now = new Date()
1399
1400            if (range_start < now) {
1401                range_min[0] = now.getFullYear()
1402                range_min[1] = now.getMonth()
1403                range_min[2] = now.getDate()
1404            }
1405        }
1406        if (this.is_ios()) {
1407            disability_result = response.week_disabilities
1408        }
1409
1410        var date_html = this.container.find('.wbk_date').prop('outerHTML')
1411
1412        this.container.find('.wbk_date').replaceWith(date_html)
1413        this.container.find('[name="date"]').remove()
1414        var fixed_startofweek = 0
1415        if (!this.is_ios()) {
1416            fixed_startofweek = wbkl10n.startofweek
1417        }
1418
1419        this.date_input = this.container.find('.wbk_date').pickadate({
1420            min: true,
1421            monthsFull: [
1422                wbkl10n.january,
1423                wbkl10n.february,
1424                wbkl10n.march,
1425                wbkl10n.april,
1426                wbkl10n.may,
1427                wbkl10n.june,
1428                wbkl10n.july,
1429                wbkl10n.august,
1430                wbkl10n.september,
1431                wbkl10n.october,
1432                wbkl10n.november,
1433                wbkl10n.december,
1434            ],
1435            monthsShort: [
1436                wbkl10n.jan,
1437                wbkl10n.feb,
1438                wbkl10n.mar,
1439                wbkl10n.apr,
1440                wbkl10n.mays,
1441                wbkl10n.jun,
1442                wbkl10n.jul,
1443                wbkl10n.aug,
1444                wbkl10n.sep,
1445                wbkl10n.oct,
1446                wbkl10n.nov,
1447                wbkl10n.dec,
1448            ],
1449            weekdaysFull: [
1450                wbkl10n.sunday,
1451                wbkl10n.monday,
1452                wbkl10n.tuesday,
1453                wbkl10n.wednesday,
1454                wbkl10n.thursday,
1455                wbkl10n.friday,
1456                wbkl10n.saturday,
1457            ],
1458            weekdaysShort: [
1459                wbkl10n.sun,
1460                wbkl10n.mon,
1461                wbkl10n.tue,
1462                wbkl10n.wed,
1463                wbkl10n.thu,
1464                wbkl10n.fri,
1465                wbkl10n.sat,
1466            ],
1467            today: wbkl10n.today,
1468            clear: wbkl10n.clear,
1469            close: wbkl10n.close,
1470            firstDay: parseInt(fixed_startofweek),
1471            format: wbkl10n.picker_format,
1472            disable: disability_result,
1473            labelMonthNext: wbkl10n.nextmonth,
1474            labelMonthPrev: wbkl10n.prevmonth,
1475            formatSubmit: 'yyyy/mm/dd',
1476            hiddenPrefix: 'wbk-date',
1477            onOpen: function () {
1478                jQuery('.wbk_date').removeClass('linear-animation-w')
1479                if (range_min != undefined) {
1480                    this.set('highlight', range_min)
1481                } else {
1482                    if (initial_date != undefined) {
1483                        this.set('highlight', initial_date)
1484                    }
1485                }
1486            },
1487            onRender: function () {
1488                jQuery('.picker__day').addClass('picker__day--disabled')
1489                jQuery('.picker__day').each(function () {
1490                    var current_pick = jQuery(this).attr('data-pick')
1491                    var elem = jQuery(this)
1492                    jQuery.each(allowed_timestamps, function (key, value) {
1493                        if (value == current_pick) {
1494                            elem.removeClass('picker__day--disabled')
1495                        }
1496                    })
1497                })
1498                jQuery(document).trigger('wbk_picker_on_render', [response])
1499            },
1500            onClose: function () {
1501                jQuery(document.activeElement).blur()
1502            },
1503            onSet: function (thingSet) {
1504                if (typeof thingSet.select != 'undefined') {
1505                    get_this().add_horizontal_calendar()
1506                    get_this().search_time_slots()
1507                } else {
1508                    if (
1509                        get_this()
1510                            .container.find('[name="date_formated"]')
1511                            .val() == ''
1512                    ) {
1513                        get_this().hide_horizontal_calendar()
1514                    }
1515                }
1516            },
1517        })
1518
1519        jQuery('input[name="wbk-datedate_formated_submit"]').addClass(
1520            'wbk-input'
1521        )
1522        jQuery('input[name="wbk-datedate_formated_submit"]').attr(
1523            'name',
1524            'date'
1525        )
1526        jQuery('input[name="date"]').attr('data-validation', 'not_empty')
1527
1528        var open_calendar = true
1529        if (range_min != undefined) {
1530            var picker = this.date_input.pickadate('picker')
1531            picker.set('min', range_min)
1532            picker.set('max', range_max)
1533
1534            if (
1535                range_min[0] == range_max[0] &&
1536                range_min[1] == range_max[1] &&
1537                range_min[2] == range_max[2]
1538            ) {
1539                picker.set('select', range_min)
1540                open_calendar = false
1541            }
1542        }
1543        if (open_calendar) {
1544            this.container.find('.wbk_date').trigger('click')
1545        }
1546
1547        jQuery('#calendar-horizontal-w button').click(function (e) {
1548            e.preventDefault()
1549        })
1550    }
1551
1552    is_ios() {
1553        return (
1554            [
1555                'iPad Simulator',
1556                'iPhone Simulator',
1557                'iPod Simulator',
1558                'iPad',
1559                'iPhone',
1560                'iPod',
1561            ].includes(navigator.platform) ||
1562            (navigator.userAgent.includes('Mac') && 'ontouchend' in document)
1563        )
1564    }
1565
1566    remove_status_bar_item(slug) {
1567        this.container
1568            .find('.appointment-status-list-w')
1569            .find('[data-slug="' + slug + '"]')
1570            .remove()
1571    }
1572
1573    add_horizontal_calendar() {
1574        const get_this = () => {
1575            return this
1576        }
1577        this.container.find('.wbk_horizontal_calendar_container').html('')
1578        var id =
1579            'horizontal_calendar_' +
1580            (Math.random() + 1).toString(36).substring(7)
1581        this.container
1582            .find('.wbk_horizontal_calendar_container')
1583            .append('<div class="calendar-horizontal-w" id="' + id + '"></div>')
1584        var locale = jQuery('html').attr('lang')
1585        if (locale.length == '' || locale.length == 'undefined') {
1586            locale = 'en'
1587        }
1588        if (locale.length > 2) {
1589            locale = locale.slice(0, 2)
1590        }
1591        this.container.find('#' + id).rescalendar({
1592            id: id,
1593            format: 'YYYY/MM/DD',
1594            refDate: get_this().container.find('[name="date"]').val(),
1595            calSize: 5,
1596            jumpSize: 0,
1597            disabledDays: this.disabled_dates_horizontal,
1598            dataKeyField: 'name',
1599            dataKeyValues: ['item1'],
1600            locale: locale,
1601        })
1602        this.container
1603            .find('.wbk_horizontal_calendar_container')
1604            .removeClass('wbk_fade_out')
1605        this.container
1606            .find('.wbk_horizontal_calendar_container')
1607            .addClass('wbk_fade_in')
1608        this.container.find('.move_to_yesterday').attr('type', 'button')
1609        this.container.find('.move_to_tomorrow').attr('type', 'button')
1610        this.container.find('.move_to_tomorrow').click(function () {
1611            get_this().set_horizontal_calendar_event()
1612        })
1613        this.container.find('.move_to_yesterday').click(function () {
1614            get_this().set_horizontal_calendar_event()
1615        })
1616        this.set_horizontal_calendar_event()
1617    }
1618    set_horizontal_calendar_event() {
1619        const get_this = () => {
1620            return this
1621        }
1622        this.container.find('.day_cell').click(function (e) {
1623            if (jQuery(this).hasClass('disabledDay')) {
1624                e.preventDefault()
1625                return
1626            }
1627            get_this().set_horizontal_calendar_event()
1628            var horizontal_value = jQuery(this)
1629                .closest('.day_cell')
1630                .attr('data-celldate')
1631            horizontal_value = horizontal_value.split('/')
1632            var new_date = new Date(
1633                horizontal_value[0],
1634                horizontal_value[1] - 1,
1635                horizontal_value[2]
1636            )
1637            var picker = get_this().date_input.pickadate('picker')
1638            picker.set('select', new_date)
1639        })
1640    }
1641
1642    hide_horizontal_calendar() {
1643        this.container
1644            .find('.wbk_horizontal_calendar_container')
1645            .addClass('wbk_fade_out')
1646        this.container
1647            .find('.wbk_horizontal_calendar_container')
1648            .removeClass('wbk_fade_in')
1649    }
1650
1651    add_status_bar_item(num, title, slug) {
1652        var html =
1653            '<li data-slug=' +
1654            slug +
1655            '>\
1656                        <div class="circle__box-w">\
1657                            <div class="circle__wrapper-w circle__wrapper--right-w">\
1658                                <div class="circle__whole-w circle__right-w"></div>\
1659                            </div><div class="circle__wrapper-w circle__wrapper--left-w">\
1660                                    <div class="circle__whole-w circle__left-w"></div>\
1661                                </div><div class="circle-digit-w"> ' +
1662            num +
1663            '</div>\
1664                        </div>\
1665                        <div class="text-w">\
1666                            <div class="text-title-w">' +
1667            title +
1668            '</div>\
1669                        </div>\
1670                    </li>'
1671        this.container.find('.appointment-status-list-w').append(html)
1672    }
1673
1674    change_button_status(elem, status) {
1675        if (status == 'loading') {
1676            elem.addClass('loading-btn-wb')
1677            elem.find('.btn-ring-wb').css('opacity', '1')
1678            elem.attr('disabled', true)
1679        }
1680        if (status == 'regular') {
1681            elem.removeClass('loading-btn-wb')
1682            elem.find('.btn-ring-wb').css('opacity', '0')
1683            elem.attr('disabled', false)
1684        }
1685    }
1686
1687    init_nice_select() {
1688        jQuery('.wbk-select').niceSelect('destroy')
1689        jQuery('.wbk-select').niceSelect()
1690        jQuery('.nice-select').click(function () {
1691            //    Scrollbar.destroyAll();
1692            //    jQuery('.appointment-content-scroll-w').css('overflow', 'hidden');
1693            //    jQuery('.appointment-content-scroll-w').css('height', 'auto');
1694        })
1695
1696        jQuery('.wbk-select').on('change', function () {
1697            //    Scrollbar.initAll({ alwaysShowTracks: true, damping: 0.5 });
1698            //   jQuery('.appointment-content-scroll-w').css('height', '555px');
1699        })
1700        jQuery(document).on('nice-select-close', function () {
1701            //    Scrollbar.initAll({ alwaysShowTracks: true, damping: 0.5 });
1702            //     jQuery('.appointment-content-scroll-w').css('height', '555px');
1703        })
1704    }
1705
1706    get_next_screen() {
1707        return this.container
1708            .find('.appointment-content-screen-active-w')
1709            .nextAll('.appointment-content-screen-w')
1710            .first()
1711    }
1712    get_prev_screen() {
1713        return this.container
1714            .find('.appointment-content-screen-active-w')
1715            .prevAll('.appointment-content-screen-w')
1716            .first()
1717    }
1718
1719    do_request(action) {
1720        return new Promise((resolve) => {
1721            var form_data = new FormData(this.container.find('form')[0])
1722            var offset = new Date().getTimezoneOffset()
1723            var time_zone_client =
1724                Intl.DateTimeFormat().resolvedOptions().timeZone
1725            if (typeof time_zone_client == 'undefined') {
1726                time_zone_client = ''
1727            }
1728            form_data.append('nonce', wbkl10n.wbkf_nonce)
1729            form_data.append('offset', offset)
1730            form_data.append('time_zone_client', time_zone_client)
1731            form_data.append('action', action)
1732
1733            const result = jQuery.ajax({
1734                url: wbkl10n.ajaxurl,
1735                type: 'POST',
1736                data: form_data,
1737                cache: false,
1738                processData: false,
1739                contentType: false,
1740                success: function (response) {
1741                    resolve(response)
1742                },
1743                error: function () {
1744                    resolve(false)
1745                },
1746                complete: function () {},
1747            })
1748        })
1749    }
1750
1751    mark_checked_services() {
1752        this.container
1753            .find('.wbk_service_item')
1754            .removeClass('wbk_service_item_active')
1755
1756        this.container.find('.wbk_services').each(function () {
1757            if (jQuery(this).is(':checked')) {
1758                jQuery(this)
1759                    .closest('.wbk_service_item')
1760                    .addClass('wbk_service_item_active')
1761            }
1762        })
1763    }
1764
1765    validate_form() {
1766        const get_this = () => {
1767            return this
1768        }
1769        this.mark_checked_services()
1770        let passed = false
1771
1772        this.container
1773            .find('.appointment-content-screen-active-w')
1774            .find('.wbk-input, .wbk-file')
1775            .not('.nice-select')
1776            .not('[type="radio"]')
1777            .each(function () {
1778                if (
1779                    jQuery(this).closest('[data-class="wpcf7cf_group"]')
1780                        .length > 0
1781                ) {
1782                    if (
1783                        jQuery(this)
1784                            .closest('[data-class="wpcf7cf_group"]')
1785                            .attr('style') == 'display: none;'
1786                    ) {
1787                        return
1788                    }
1789                }
1790                const elem = jQuery(this)
1791                const value = jQuery(this).val()
1792                const field_name = jQuery(this).attr('data-validationmsg')
1793                switch (jQuery(this).attr('data-validation')) {
1794                    case 'file_required':
1795                        if (jQuery(this).get(0).files.length == 0) {
1796                            passed = false
1797                        } else {
1798                            passed = true
1799                        }
1800                        break
1801                    case 'positive':
1802                        passed = wbk_check_integer_min_max(value, 1, 99999999)
1803                        break
1804                    case 'not_empty':
1805                        var min = 1
1806                        var max = 16384
1807                        var attr = jQuery(this).attr('minlength')
1808                        if (typeof attr !== 'undefined' && attr !== false) {
1809                            min = attr
1810                        }
1811                        attr = jQuery(this).attr('maxnlength')
1812                        if (typeof attr !== 'undefined' && attr !== false) {
1813                            max = attr
1814                        }
1815
1816                        passed = wbk_check_string(value, min, max)
1817                        break
1818                    case 'must_have_items':
1819                        passed = false
1820                        if (jQuery(this).is('select')) {
1821                            elem.find('option').each(function () {
1822                                if (jQuery(this).prop('selected')) {
1823                                    passed = true
1824                                }
1825                            })
1826                        }
1827                        if (jQuery(this).is(':checkbox')) {
1828                            var checkbox_name = jQuery(this).attr('name')
1829                            var val = jQuery(
1830                                '[name="' + checkbox_name + '"]'
1831                            ).each(function () {
1832                                if (jQuery(this).is(':checked')) {
1833                                    passed = true
1834                                }
1835                            })
1836                        }
1837                        break
1838                    case 'email':
1839                        passed = wbk_check_email(value)
1840                        break
1841                    case 'phone':
1842                        passed = wbk_check_string(
1843                            value,
1844                            wbkl10n.phone_required,
1845                            30
1846                        )
1847                        break
1848                    default:
1849                        passed = true
1850                }
1851
1852                if (
1853                    jQuery(this).val() != '' &&
1854                    passed == false &&
1855                    !jQuery(this).is(':focus')
1856                ) {
1857                    jQuery(this).addClass('input-error-w')
1858                }
1859                if (jQuery(this).val() != '' && passed == true) {
1860                    jQuery(this).removeClass('input-error-w')
1861                }
1862
1863                if (!passed) {
1864                    get_this()
1865                        .container.find('.button-next-w')
1866                        .prop('disabled', true)
1867                    return passed
1868                }
1869            })
1870
1871        // check if service radio button is present and checked
1872        if (
1873            this.container
1874                .find('.appointment-content-screen-active-w')
1875                .find('.wbk_services[type="radio"]').length > 0
1876        ) {
1877            var radio_val = this.container
1878                .find('.appointment-content-screen-active-w')
1879                .find('.wbk_services[type="radio"]:checked')
1880                .val()
1881
1882            if (radio_val == undefined) {
1883                passed = false
1884            } else {
1885                passed = true
1886            }
1887        }
1888
1889        // check if payment method radio button is present and checked
1890        if (
1891            this.container
1892                .find('.appointment-content-screen-active-w')
1893                .find('.payment-method-list-w').length > 0
1894        ) {
1895            var radio_val = this.container
1896                .find('.appointment-content-screen-active-w')
1897                .find('input[type="radio"]:checked')
1898                .val()
1899
1900            if (radio_val == undefined) {
1901                passed = false
1902            } else {
1903                passed = true
1904            }
1905        }
1906
1907        if (!passed) {
1908            get_this().container.find('.button-next-w').prop('disabled', true)
1909        } else {
1910            get_this().container.find('.button-next-w').prop('disabled', false)
1911        }
1912
1913        return passed
1914    }
1915
1916    clear_fields(element, clear_slots = true) {
1917        if (clear_slots) {
1918            element.find('.dynamic-content-w').remove()
1919
1920            element.find('.wbk_times > option').remove()
1921            element.find('.wbk_services_final > option').remove()
1922            this.render_selected_time_slots_list()
1923            element
1924                .find('.wbk-input')
1925                .not('.wbk_service_checkbox')
1926                .not('.wbk_service_radio')
1927                .val('')
1928        }
1929        element.find('select.wbk-input').not('.wbk_services_hidden').val(0)
1930        element.find('select.wbk-input').trigger('change')
1931        element.find('.wbk-input').niceSelect('update')
1932        element.attr('style', '')
1933        element.find('.wbk_quantities > option').remove()
1934        element.find('.wbk-book-quantity').remove()
1935    }
1936
1937    validate_prev_next_buttons() {
1938        const get_this = () => {
1939            return this
1940        }
1941        var step = parseInt(get_this().container.attr('data-step'))
1942        if (step == 1) {
1943            get_this()
1944                .container.find('.button-prev-w')
1945                .addClass('wbk_invisible')
1946        } else {
1947            get_this()
1948                .container.find('.button-prev-w')
1949                .removeClass('wbk_invisible')
1950        }
1951    }
1952
1953    finalize(response) {
1954        const get_this = () => {
1955            return this
1956        }
1957        this.container.find('.appointment-status-wrapper-w').fadeOut('fast')
1958        this.container
1959            .find('.appointment-content-w')
1960            .fadeOut('fast', function () {
1961                if (typeof response !== 'object') {
1962                    response = jQuery.parseJSON(response)
1963                }
1964                get_this().container.append(response.thanks_message)
1965            })
1966
1967        jQuery(document).trigger('webba_booking_finalize', [response, this])
1968    }
1969
1970    prev_step() {
1971        const get_this = () => {
1972            return this
1973        }
1974        this.container.find('.wbk_quantities option').remove()
1975        var prev_screen = get_this().get_prev_screen()
1976        var step = parseInt(get_this().container.attr('data-step'))
1977        get_this()
1978            .container.find(
1979                '.appointment-status-list-w li:nth-child(' + step + ')'
1980            )
1981            .removeClass('active-w')
1982        step--
1983        get_this().container.attr('data-step', step)
1984        get_this()
1985            .container.find(
1986                '.appointment-status-list-w li:nth-child(' + step + ')'
1987            )
1988            .addClass('active-w')
1989        get_this()
1990            .container.find(
1991                '.appointment-status-list-w li:nth-child(' + step + ')'
1992            )
1993            .removeClass('completed-w')
1994
1995        Scrollbar.destroyAll()
1996        get_this().change_button_status(
1997            get_this().container.find('.button-next-w'),
1998            'regular'
1999        )
2000
2001        this.clear_fields(
2002            get_this().container.find('.appointment-content-screen-active-w')
2003        )
2004
2005        get_this()
2006            .container.find('.appointment-content-screen-active-w')
2007            .removeClass('appointment-content-screen-active-w')
2008        prev_screen.addClass('appointment-content-screen-active-w')
2009        var slug = prev_screen.attr('data-slug')
2010        this.remove_step_subtitle(slug)
2011        this.remove_step_subtitle('payment_optional')
2012        this.clear_fields(prev_screen, false)
2013        this.init_scroll_bars()
2014        this.validate_prev_next_buttons()
2015
2016        this.container.find('.wbk_times option').prop('selected', true)
2017        this.container.find('.wbk_services_final option').prop('selected', true)
2018
2019        this.validate_form()
2020
2021        get_this().update_mobile_step()
2022        jQuery(document).trigger('wbk_after_prev', [this])
2023    }
2024    is_last_step() {
2025        var elements = this.container
2026            .find('.appointment-content-screen-active-w')
2027            .nextAll('.appointment-content-screen-w')
2028        if (elements.length == 1) {
2029            return true
2030        }
2031        return false
2032    }
2033    update_mobile_step() {
2034        var total_steps = parseInt(
2035            this.container.find('.appointment-status-list-w > li').length
2036        )
2037        if (total_steps == 0) {
2038            return
2039        }
2040        var step = parseInt(this.container.attr('data-step'))
2041        this.container
2042            .find('.circle-chart-text-wb')
2043            .html(step + ' ' + wbkl10n.of + ' ' + total_steps)
2044
2045        var acive_step_title = this.container
2046            .find('.appointment-status-list-w > li.active-w')
2047            .find('.text-title-w')
2048            .html()
2049
2050        this.container.find('.current-step-w').html(acive_step_title)
2051        var next_li = this.container
2052            .find('.appointment-status-list-w > li.active-w')
2053            .nextAll('li')
2054
2055        if (next_li.length > 0) {
2056            var next_text = this.container.find('.button-next-w').html()
2057            this.container
2058                .find('.next-step-w')
2059                .html(next_text + ': ' + next_li.find('.text-title-w').html())
2060        }
2061        var progress = parseInt((100 * step) / total_steps)
2062        this.container
2063            .find('.circle-chart-wb')
2064            .data('easyPieChart')
2065            .update(progress)
2066    }
2067    async next_step() {
2068        const get_this = () => {
2069            return this
2070        }
2071        this.container
2072            .find('.wbk_service_item')
2073            .removeClass('timeslot-animation-w')
2074
2075        // validation
2076        if (!this.validate_form()) {
2077            return
2078        }
2079        var next_screen = get_this().get_next_screen()
2080        if (next_screen.length == 0) {
2081            get_this().change_button_status(
2082                get_this().container.find('.button-next-w'),
2083                'loading'
2084            )
2085
2086            return
2087        }
2088        this.clear_fields(next_screen)
2089        var can_proceed = false
2090        var response = null
2091     
2091   if (next_screen.attr('data-request') != '') {
2092            get_this().change_button_status(
2093                get_this().container.find('.button-next-w'),
2094                'loading'
2095            )
2096            response = await this.do_request(next_screen.attr('data-request'))
2097            if (response == false) {
2098                get_this().show_error('An unexpected error occoured.')
2099                return
2100            }
2101
2102            try {
2103                response = jQuery.parseJSON(response)
2104                if (response.status == 'fail') {
2105                    get_this().change_button_status(
2106                        get_this().container.find('.button-next-w'),
2107                        'regular'
2108                    )
2109                    this.show_error(response.description)
2110                    return
2111                }
2112                if ((response.url != undefined && response.url) != '') {
2113                    window.location.href = response.url
2114                    return
2115                }
2116            } catch (e) {}
2117            if (get_this().is_last_step()) {
2118                get_this().finalize(response)
2119                return
2120            }
2121            if (response != false) {
2122                if (typeof response.webba5_html !== 'undefined') {
2123                    this.container.find('.appointment-content-screen-active-w')
2124                        .response.webba5_html
2125                }
2126            }
2127            if (response != false) {
2128                can_proceed = true
2129            }
2130        } else {
2131            can_proceed = true
2132        }
2133        if (can_proceed) {
2134            var step = parseInt(get_this().container.attr('data-step'))
2135            get_this()
2136                .container.find('.input-error-w')
2137                .removeClass('input-error-w')
2138            get_this().container.find('.form-error-w').toggle(false)
2139            get_this()
2140                .container.find(
2141                    '.appointment-status-list-w li:nth-child(' + step + ')'
2142                )
2143                .removeClass('active-w')
2144            get_this()
2145                .container.find(
2146                    '.appointment-status-list-w li:nth-child(' + step + ')'
2147                )
2148                .addClass('completed-w')
2149
2150            step++
2151            get_this().container.attr('data-step', step)
2152            get_this()
2153                .container.find(
2154                    '.appointment-status-list-w li:nth-child(' + step + ')'
2155                )
2156                .addClass('active-w')
2157            Scrollbar.destroyAll()
2158            get_this()
2159                .container.find('.appointment-content-screen-active-w')
2160                .fadeOut('fast', function () {
2161                    get_this().change_button_status(
2162                        get_this().container.find('.button-next-w'),
2163                        'regular'
2164                    )
2165                    get_this()
2166                        .container.find('.appointment-content-screen-active-w')
2167                        .removeClass('appointment-content-screen-active-w')
2168                    next_screen.addClass('appointment-content-screen-active-w')
2169                    next_screen
2170                        .find('.wbk-input')
2171                        .addClass('linear-animation-w')
2172
2173                    jQuery(document).trigger('wbk_after_screen_rendered', [
2174                        response,
2175                    ])
2176                    jQuery(document).trigger('wbk_after_next', [this, response])
2177                })
2178            get_this().validate_prev_next_buttons()
2179            get_this().update_mobile_step()
2180        }
2181    }
2182    show_error(message) {
2183        this.container.find('.form-error-message-w').html(message)
2184        this.container.find('.form-error-w').toggle(true)
2185    }
2186}
2187
2188let webba_forms = []
2189jQuery(function ($) {
2190    jQuery('.appointment-box-w').each(function () {
2191        var form = new WEBBA5_Form(jQuery(this))
2192        webba_forms.push(form)
2193    })
2194    if (jQuery('#grve-safebutton-area').length > 0) {
2195        jQuery('#grve-safebutton-area').find('.main-block-w').remove()
2196    } else {
2197        if (jQuery('.main-block-w').length > 1) {
2198            jQuery('.main-block-w').not(':last').remove()
2199        }
2200    }
2201})
2202
2203function wbk_strip_html(html) {
2204    let tmp = document.createElement('DIV')
2205    tmp.innerHTML = html
2206    return tmp.textContent || tmp.innerText || ''
2207}

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.