PageSourceSearch

https://suquamishmuseum.org/wp-content/plugins/super-forms/assets/js/frontend/elements.js?ver=6.3.317

js suquamishmuseum.org collected 2026-10-02 10:32:31 UTC 171,217 bytes, 3,436 lines download raw bytes

1/* globals jQuery, SUPER, super_elements_i18n */
2"use strict";
3(function($) { // Hide scope, no $ conflict
4    // Switch between multiparts (prev/next or clicking on step)
5    SUPER.switchMultipart = function(e, target, dir){
6        // First get active part
7        var i, index, validate, result, skip, progress, multipart,
8            form = target.closest('.super-form'),
9            stepParams = (form.dataset.stepParams ? form.dataset.stepParams : ''), // default
10            nodes = form.querySelectorAll('.super-multipart'),
11            steps = form.querySelectorAll('.super-multipart-step'),
12            formId = form.querySelector('input[name="hidden_form_id"]').value,
13            activeMultipart = form.querySelector('.super-multipart-step.super-active'),
14            children = Array.prototype.slice.call(activeMultipart.parentNode.children),
15            total = form.querySelectorAll('.super-multipart').length,
16            currentStep = children.indexOf(activeMultipart);
17
18        if(dir==='prev'){
19            // From first to last?
20            if(currentStep===0){
21                index = nodes.length-1;
22            }else{
23                index = currentStep-1;
24            }
25        }
26        if(dir==='next'){
27            // From last to first?
28            if(total===currentStep+1){
29                index = 0;
30            }else{
31                // @since 2.0.0 - validate multi-part before going to next step
32                validate = form.querySelector('.super-multipart.super-active').dataset.validate;
33                if(validate=='true'){
34                    result = SUPER.validate_form({el: target, form: form.querySelector('.super-multipart.super-active'), submitButton: target, validateMultipart: true, event: e});
35                    if(result!==true) return false;
36                }
37                index = currentStep+1;
38            }
39        }
40        for( i = 0; i < nodes.length; i++){
41            nodes[i].classList.remove('super-active');
42            steps[i].classList.remove('super-active');
43            if(i===index){
44                nodes[i].classList.add('super-active');
45                steps[i].classList.add('super-active');
46            }
47        }
48        
49        // Required for toggle field and other possible elements to rerender proper size
50        SUPER.init_super_responsive_form_fields({form: form});
51
52        // Update URL parameters
53        if(stepParams!=='false'){
54            window.location.hash = 'step-'+formId+'-'+(parseInt(index,10)+1);
55        }
56        
57        // Make sure to skip the multi-part if no visible elements are found
58        skip = SUPER.skipMultipart(target, form);
59        if(skip===true) return false;
60
61        // Update progress bar
62        progress = 100 / total;
63        progress = progress * (index+1);
64        form.querySelector('.super-multipart-progress-bar').style.width = progress+'%';
65        index = 0;
66        
67        nodes = form.querySelectorAll('.super-multipart');
68        for( i = 0; i < nodes.length; i++){
69            if(!nodes[i].querySelector('.super-error-active')){
70                form.querySelectorAll('.super-multipart-steps .super-multipart-step')[index].classList.remove('super-error');
71            }
72            index++;
73        }
74        // Disable scrolling for multi-part prev/next
75        multipart = form.querySelector('.super-multipart.super-active');
76        if(typeof multipart.dataset.disableScrollPn === 'undefined'){
77            if(e && !e.shiftKey){
78                if(form.closest('.super-popup-content')){
79                    $(form.closest('.super-popup-content')).animate({
80                        scrollTop: $(form).offset().top - 30
81                    }, 500);
82                }else{
83                    $('html, body').animate({
84                        scrollTop: $(form).offset().top - 30
85                    }, 500);
86                }
87            }
88        }
89        // Focus first TAB index field in next multi-part
90        SUPER.focusFirstTabIndexField(e, form, multipart);
91
92    };
93    // Make sure to skip the multi-part if no visible elements are found
94    SUPER.skipMultipart = function(el, form, index, activeIndex){
95        var i, nodes, multipart, field, skip = true;
96        
97        nodes = form.querySelectorAll('.super-multipart.super-active .super-field:not(.super-button)');
98        for( i = 0; i < nodes.length; i++ ) {
99            field = nodes[i].querySelector('.super-shortcode-field');
100            if(field){ // This is a field
101                if(!SUPER.has_hidden_parent(field)) skip = false;
102            }else{ // This is either a HTML element or something else without a field
103                if(!SUPER.has_hidden_parent(nodes[i])) skip = false;
104            }
105            if(skip===false) return false;
106        }
107        if(skip){ // Only skip if no visible fields where to be found
108            multipart = form.querySelector('.super-multipart.super-active');
109            if( (el.classList.contains('super-prev-multipart')) || (el.classList.contains('super-next-multipart')) ){
110                if(el.classList.contains('super-prev-multipart')){
111                    if(multipart.querySelector('.super-prev-multipart')) multipart.querySelector('.super-prev-multipart').click();
112                }else{
113                    if(multipart.querySelector('.super-next-multipart')) multipart.querySelector('.super-next-multipart').click();
114                }
115            }else{
116                if(index < activeIndex){
117                    if(multipart.querySelector('.super-prev-multipart')) multipart.querySelector('.super-prev-multipart').click();
118                }else{
119                    if(multipart.querySelector('.super-next-multipart')) multipart.querySelector('.super-next-multipart').click();
120                }
121            }
122        }
123        return skip;
124    };
125    SUPER.focusFirstTabIndexField = function(e, form, multipart) {
126        var fields,highestIndex,lowestIndex,index,next, disableAutofocus = multipart.dataset.disableAutofocus;
127
128        if( typeof disableAutofocus === 'undefined' ) {
129            fields = $(multipart).find('.super-field:not('+super_elements_i18n.tab_index_exclusion+')[data-super-tab-index]');
130            highestIndex = 0;
131            fields.each(function(){
132                index = parseFloat($(this).attr('data-super-tab-index'));
133                if( index > highestIndex ) {
134                    highestIndex = index;
135                }
136            });
137            lowestIndex = highestIndex;
138            fields.each(function(){
139                index = parseFloat($(this).attr('data-super-tab-index'));
140                if( index < lowestIndex ) {
141                    lowestIndex = index;
142                }
143            });
144            next = $(multipart).find('.super-field:not('+super_elements_i18n.tab_index_exclusion+')[data-super-tab-index="'+lowestIndex+'"]');
145            SUPER.focusNextTabField(e, next[0], form, next[0]);
146        }
147    };
148
149    // @since 3.2.0 - function to return next field based on TAB index
150    SUPER.nextTabField = function(e, field, form, nextTabIndex){
151        if(!field) return false;
152        var nextTabIndexSmallIncrement,
153            nextField,
154            nextFieldSmallIncrement,
155            nextCustomField,
156            customTabIndex,
157            incNext = 1,
158            incNextSmall = 0.001;
159
160        if(e.shiftKey){
161            incNext = -incNext;
162            incNextSmall = -incNextSmall;
163        }
164        if(typeof nextTabIndex === 'undefined'){
165            nextTabIndexSmallIncrement = parseFloat(parseFloat(field.dataset.superTabIndex)+incNextSmall).toFixed(3);
166            nextTabIndex = parseFloat(field.dataset.superTabIndex)+incNext;
167        }
168        if(typeof field.dataset.superCustomTabIndex !== 'undefined'){
169            nextTabIndex = parseFloat(field.dataset.superCustomTabIndex)+incNext;
170        }
171
172        nextTabIndexSmallIncrement = parseFloat(nextTabIndexSmallIncrement);
173        nextTabIndex = parseFloat(parseFloat(nextTabIndex).toFixed(0));
174        nextFieldSmallIncrement = form.querySelector('.super-field[data-super-tab-index="'+nextTabIndexSmallIncrement+'"]');
175        if(nextFieldSmallIncrement){
176            nextField = nextFieldSmallIncrement;
177        }else{
178            nextField = form.querySelector('.super-field[data-super-tab-index="'+nextTabIndex+'"]');
179        }
180        nextCustomField = form.querySelector('.super-field[data-super-custom-tab-index="'+nextTabIndex+'"]');
181
182        // If custom index TAB field was found, and is not currently focussed
183        if( (nextCustomField) && (!nextCustomField.classList.contains('super-focus')) ) {
184            nextField = nextCustomField;
185        }
186        
187        if(!nextField) return false;
188
189        if(nextField.dataset.superCustomTabIndex){
190            customTabIndex = nextField.dataset.superCustomTabIndex;
191            if(typeof customTabIndex !== 'undefined') {
192                if(nextTabIndex < parseFloat(customTabIndex)){
193                    nextField = SUPER.nextTabField(e, field, form, nextTabIndex+incNext);
194                }
195            }
196        }
197        if(SUPER.has_hidden_parent(nextField)){
198            // Exclude conditionally
199            nextField = SUPER.nextTabField(e, field, form, nextTabIndex+incNext);
200        }
201        return nextField;
202    };
203
204    SUPER.init_adaptive_placeholder = function(){
205        var nodes = document.querySelectorAll('.super-adaptive-placeholder');
206        for (var i = 0; i < nodes.length; i++) {
207            var input = nodes[i].parentNode.querySelector('.super-shortcode-field');
208            if(!input) continue;
209
210            input.onclick = input.onfocus = function () {
211            }
212            input.onblur = function () {
213            }
214            input.addEventListener('keyup', function () {
215                var wrapper = this.closest('.super-field-wrapper');
216                var placeholder = wrapper.querySelector('.super-adaptive-placeholder');
217                var span = placeholder.children[0];
218                var filled = true,
219                    parent = this.closest('.super-field');
220                if(parent.classList.contains('super-currency')){
221                    if($(this).maskMoney('unmasked')[0]===0){
222                        filled = false;
223                    }
224                }
225                if (this.value.length === 0) filled = false;
226                if(filled){
227                    parent.classList.add('super-filled');
228                    span.innerHTML = placeholder.dataset.placeholderfilled;
229                }else{
230                    parent.classList.remove('super-filled');
231                    span.innerHTML = placeholder.dataset.placeholder;
232                }
233            });
234            input.oncut = input.onpaste = function (event) {
235                var wrapper = this.closest('.super-field-wrapper');
236                var placeholder = wrapper.querySelector('.super-adaptive-placeholder');
237                var span = placeholder.children[0];
238                var filled = true,
239                    input = event.target,
240                    parent = event.target.closest('.super-field');
241
242                if(parent.classList.contains('super-currency')){
243                    if($(input).maskMoney('unmasked')[0]===0){
244                        filled = false;
245                    }
246                }
247                if (event.type == 'cut' || event.type == 'paste') {
248                    setTimeout(function () {
249                        if (input.value.length === 0) filled = false;
250                        if(filled){
251                            parent.classList.add('super-filled');
252                            span.innerHTML = placeholder.dataset.placeholderfilled;
253                        }else{
254                            parent.classList.remove('super-filled');
255                            span.innerHTML = placeholder.dataset.placeholder;
256                        }
257                    }, 100);
258                }
259            }
260        }
261    };
262
263    // @since 1.3   - input mask
264    SUPER.init_masked_input = function(){
265        $('.super-shortcode-field[data-mask]').each(function(){
266            $(this).mask($(this).data('mask'));
267        });
268    };
269
270    // @since 2.1.0  - currency field
271    SUPER.init_currency_input = function(){
272        $('.super-currency .super-shortcode-field').each(function(){
273            var $currency = $(this).data('currency');
274            var $format = $(this).data('format');
275            var $decimals = $(this).data('decimals');
276            var $thousand_separator = $(this).data('thousand-separator');
277            var $decimal_seperator = $(this).data('decimal-separator');
278            $(this).maskMoney({
279                prefix: $currency,
280                suffix: $format,
281                affixesStay: true,
282                allowNegative: true,
283                thousands: $thousand_separator,
284                decimal: $decimal_seperator,
285                precision: $decimals
286            });
287            if(this.dataset.defaultValue!==''){
288                $(this).maskMoney('mask', this.dataset.defaultValue);
289                $(this).parents('.super-currency').addClass('super-filled');
290            }else{
291                $(this).parents('.super-currency').removeClass('super-filled');
292            }
293        });
294    };
295
296    // @since 2.0 - initialize color picker(s) 
297    SUPER.init_colorpicker = function(){
298        $('.super-color .super-shortcode-field').each(function(){
299            if(typeof $.fn.spectrum === "function") { 
300                if(!$(this).hasClass('super-picker-initialized')){
301                    var $value = $(this).val();
302                    if($value==='') $value = '#FFFFFF';
303                    $(this).spectrum({
304                        containerClassName: 'super-forms',
305                        replacerClassName: 'super-forms',
306                        color: $value,
307                        preferredFormat: "hex",
308                        showInput: true,
309                        chooseText: "Accept",
310                        cancelText: "Cancel",
311                        change: function(color) {
312                            this.value = color.toHexString();
313                        },
314                        move: function(color) {
315                            this.value = color.toHexString();
316                        },
317                        beforeShow: function(){
318                            SUPER.focusForm(this);
319                            SUPER.focusField(this);
320                        }
321                    }).addClass('super-picker-initialized');
322                }
323            }
324        });
325    };
326
327    // @since 2.0 - calculate age in years, months and days
328    SUPER.init_datepicker_get_age = function(dateString, return_value){
329        var now = new Date(),
330        yearNow = now.getYear(),
331        monthNow = now.getMonth(),
332        dateNow = now.getDate(),
333        dob = new Date(dateString.substring(6,10), dateString.substring(0,2)-1, dateString.substring(3,5)),
334        yearDob = dob.getYear(),
335        monthDob = dob.getMonth(),
336        dateDob = dob.getDate(),
337        age = {},
338        yearAge = yearNow - yearDob,
339        monthAge,
340        dateAge;
341        if(monthNow >= monthDob){
342            monthAge = monthNow - monthDob;
343        }else{
344            yearAge--;
345             monthAge = 12 + monthNow -monthDob;
346        }
347        if(dateNow >= dateDob){
348             dateAge = dateNow - dateDob;
349        }else{
350            monthAge--;
351             dateAge = 31 + dateNow - dateDob;
352            if (monthAge < 0) {
353                monthAge = 11;
354                yearAge--;
355            }
356        }
357        age = {
358            years: yearAge,
359            months: monthAge,
360            days: dateAge
361        };
362        if(return_value=='years'){
363            return age.years;
364        }
365        if(return_value=='months'){
366            return age.months;
367        }
368        if(return_value=='days'){
369            return age.days;
370        }
371    };
372
373    // init connected datepickers
374    SUPER.init_connected_datepicker = function($this, selectedDate, $parse_format, oneDay, skipFieldChangeForElement){
375        if(selectedDate===''){
376            $this.closest('.super-field').classList.remove('super-filled');
377        }else{
378            $this.closest('.super-field').classList.add('super-filled');
379        }
380
381        var original_selectedDate = selectedDate,
382            $format = $this.dataset.jsformat,
383            d,
384            year,month,day,
385            firstDate,
386            $connected_min,
387            $connected_date,
388            $connected_min_days,
389            min_date,
390            $parse,
391            $connected_max,
392            $connected_max_days,
393            max_date;
394
395        if(original_selectedDate!==''){
396            d = Date.parseExact(original_selectedDate, $parse_format);
397            if(d!==null){
398                year = d.toString('yyyy');
399                month = d.toString('MM');
400                day = d.toString('dd');                        
401                $this.dataset.mathYear = year;
402                $this.dataset.mathMonth = month;
403                $this.dataset.mathDay = day;
404                firstDate = new Date(Date.UTC(year, month-1, day));
405                $this.dataset.mathDiff = firstDate.getTime();
406                $this.dataset.mathAge = SUPER.init_datepicker_get_age(month+'/'+day+'/'+year, 'years');
407                $this.dataset.mathAgeMonths = SUPER.init_datepicker_get_age(month+'/'+day+'/'+year, 'months');
408                $this.dataset.mathAgeDays = SUPER.init_datepicker_get_age(month+'/'+day+'/'+year, 'days');
409                $connected_min = $this.dataset.connectedMin;
410                if( typeof $connected_min !== 'undefined' ) {
411                    if( $connected_min!=='' ) {
412                        $connected_date = document.querySelector('.super-shortcode-field.super-datepicker[name="'+$connected_min+'"]');
413                        if($connected_date){
414                            $format = $connected_date.dataset.jsformat;
415                            $connected_min_days = parseInt($this.dataset.connectedMinDays, 10);
416                            min_date = Date.parseExact(original_selectedDate, $parse_format).add({ days: $connected_min_days }).toString($format);
417                            $($connected_date).datepicker('option', 'minDate', min_date );
418                            var maxPicks =($this.dataset.maxpicks ? parseInt($this.dataset.maxpicks, 10) : 1);
419                            if(maxPicks<=1){
420                                if($connected_date.value===''){
421                                    $connected_date.value = min_date;
422                                }
423                                if($connected_date.value===''){
424                                    $connected_date.closest('.super-field').classList.remove('super-filled');
425                                }else{
426                                    $connected_date.closest('.super-field').classList.add('super-filled');
427                                }
428                                $parse = Date.parseExact($connected_date.value, $parse_format);
429                                if($parse!==null){
430                                    selectedDate = $parse.toString($format);
431                                    d = Date.parseExact(selectedDate, $format);
432                                    year = d.toString('yyyy');
433                                    month = d.toString('MM');
434                                    day = d.toString('dd');          
435                                    selectedDate = new Date(Date.UTC(year, month-1, day));
436                                    $connected_date.dataset.mathDiff = selectedDate.getTime();
437                                    SUPER.init_connected_datepicker($connected_date, $connected_date.value, $parse_format, oneDay);
438                                }
439                            }
440                        }
441                    }
442                }
443                $connected_max = $this.dataset.connectedMax;
444                if(typeof $connected_max !== 'undefined'){
445                    if( $connected_max!=='' ) {
446                        $connected_date = document.querySelector('.super-shortcode-field.super-datepicker[name="'+$connected_max+'"]');
447                        if($connected_date){
448                            $format = $connected_date.dataset.jsformat;
449                            $connected_max_days = parseInt($this.dataset.connectedMaxDays, 10);
450                            max_date = Date.parseExact(original_selectedDate, $parse_format).add({ days: $connected_max_days }).toString($format);
451                            $($connected_date).datepicker('option', 'maxDate', max_date );
452                            if($connected_date.value===''){
453                                $connected_date.value = max_date;
454                            }
455                            if($connected_date.value===''){
456                                $connected_date.closest('.super-field').classList.remove('super-filled');
457                            }else{
458                                $connected_date.closest('.super-field').classList.add('super-filled');
459                            }
460                            $parse = Date.parseExact($connected_date.value, $parse_format);
461                            if($parse!==null){
462                                selectedDate = $parse.toString($format);
463                                d = Date.parseExact(selectedDate, $format);
464                                year = d.toString('yyyy');
465                                month = d.toString('MM');
466                                day = d.toString('dd');          
467                                selectedDate = new Date(Date.UTC(year, month-1, day));
468                                $connected_date.dataset.mathDiff = selectedDate.getTime();
469                                SUPER.init_connected_datepicker($connected_date, $connected_date.value, $parse_format, oneDay);
470                            }
471                        }
472                    }
473                }
474            }
475        }
476        SUPER.after_field_change_blur_hook({el: $this});
477    };
478
479    // init Datepicker
480    SUPER.init_datepicker = function(skipFieldChangeForElement){
481        if(typeof skipFieldChangeForElement === 'undefined') skipFieldChangeForElement = ''
482        var i;
483
484        // Init datepickers
485        var oneDay = 24*60*60*1000, // hours*minutes*seconds*milliseconds
486            nodes = document.querySelectorAll('.super-datepicker');
487
488        for (i = 0; i < nodes.length; ++i) {
489            if(typeof datepicker === "function"){ 
490                $(nodes[i]).datepicker('destroy');
491            }
492        }
493
494        nodes = document.querySelectorAll('.super-datepicker:not(.super-picker-initialized)');
495        for (i = 0; i < nodes.length; ++i) {
496            var el = nodes[i],
497                form = SUPER.get_frontend_or_backend_form({el: el}),
498                format = el.dataset.format, //'MM/dd/yyyy';
499                jsformat = el.dataset.jsformat, //'MM/dd/yyyy';
500                isRTL = (el.closest('.super-form') ? el.closest('.super-form').classList.contains('super-rtl') : false),
501                min = el.dataset.minlength,
502                max = el.dataset.maxlength,
503                workDays,
504                weekends,
505                regex = /{([^\\\/\s"'+]*?)}/g,
506                range = el.dataset.range,
507                maxPicks =(el.dataset.maxpicks ? parseInt(el.dataset.maxpicks, 10) : 1),
508                firstDay = el.dataset.firstDay,
509                localization = el.dataset.localization,
510                widget,connectedMinDays,minDate,connectedMaxDays,maxDate,
511                parse,year,month,firstDate,$date,days,found,date,fullDate,dateFrom,
512                dateTo,d1,d2,from,to,check,day,exclDays,exclDaysOverride,exclDaysOverrideReplaced,exclDates,exclDatesReplaced,
513                changeMonth =(el.dataset.changeMonth==='true' ? true : false),
514                changeYear =(el.dataset.changeYear==='true' ? true : false),
515                showMonthAfterYear = (el.dataset.showMonthAfterYear==='true' ? true : false),
516                showWeek = (el.dataset.showWeek==='true' ? true : false),
517                numberOfMonths = parseInt(el.dataset.numberOfMonths, 10),
518                showOtherMonths = (el.dataset.showOtherMonths==='true' ? true : false),
519                selectOtherMonths = (el.dataset.selectOtherMonths==='true' ? true : false),
520
521                // @since 2.5.0 - Date.parseExact compatibility
522                parseFormat = [
523                    jsformat
524                ];
525                
526                // If localization is being used, use this date format instead
527                // Make sure to convert to correct format before using, plus update data attribute
528                if(localization!==''){
529                    if(typeof $.datepicker.regional[localization] !== 'undefined'){
530                        format = $.datepicker.regional[localization].dateFormat;
531                        jsformat = format;
532                        jsformat = jsformat.replace('DD', 'dddd');
533                        regex = /MM/i;
534                        if(regex.test(jsformat)){
535                            jsformat = jsformat.replace('MM', 'MMMM');
536                        }else{
537                            regex = /M/i;
538                            if(regex.test(jsformat)){
539                                jsformat = jsformat.replace('M', 'MMM');
540                            }
541                        }
542                        jsformat = jsformat.replace('mm', 'MM');
543                        regex = /yy/i;
544                        if(regex.test(jsformat)){
545                            jsformat = jsformat.replace('yy', 'yyyy');
546                        }else{
547                            regex = /y/i;
548                            if(regex.test(jsformat)){
549                                jsformat = jsformat.replace('y', 'yy');
550                            }
551                        }
552                        parseFormat = [
553                            jsformat
554                        ];
555                        el.dataset.format = format;
556                        el.dataset.jsformat = jsformat;
557                    }
558                }
559
560            // Check if range is valid value, if not set to default one
561            if(range.indexOf(':')===-1){
562                range = '-100:+5';
563            }
564            
565            // yy = short year
566            // yyyy = long year
567            // M = month (1-12)
568            // MM = month (01-12)
569            // MMM = month abbreviation (Jan, Feb ... Dec)
570            // MMMM = long month (January, February ... December)
571            // d = day (1 - 31)
572            // dd = day (01 - 31)
573            // ddd = day of the week in words (Monday, Tuesday ... Sunday)
574            // E = short day of the week in words (Mon, Tue ... Sun)
575            // D - Ordinal day (1st, 2nd, 3rd, 21st, 22nd, 23rd, 31st, 4th...)
576            // h = hour in am/pm (0-12)
577            // hh = hour in am/pm (00-12)
578            // H = hour in day (0-23)
579            // HH = hour in day (00-23)
580            // mm = minute
581            // ss = second
582            // SSS = milliseconds
583            // a = AM/PM marker
584            // p = a.m./p.m. marker
585
586            if(typeof min !== 'undefined') min = min.toString();
587            if(typeof max !== 'undefined') max = max.toString();
588
589            el.classList.add('super-picker-initialized');
590            if( el.value!=='' ) {
591                parse = Date.parseExact(el.value, parseFormat);
592                if( parse!==null ) {
593                    year = parse.toString('yyyy');
594                    month = parse.toString('MM');
595                    day = parse.toString('dd');
596                    el.dataset.mathYear = year;
597                    el.dataset.mathMonth = month;
598                    el.dataset.mathDay = day;
599                    firstDate = new Date(Date.UTC(year, month-1, day));
600                    el.dataset.mathDiff = firstDate.getTime();
601                    el.dataset.mathAge = SUPER.init_datepicker_get_age(month+'/'+day+'/'+year, 'years');
602                    el.dataset.mathAgeMonths = SUPER.init_datepicker_get_age(month+'/'+day+'/'+year, 'months');
603                    el.dataset.mathAgeDays = SUPER.init_datepicker_get_age(month+'/'+day+'/'+year, 'days');
604                    $date = Date.parseExact(day+'-'+month+'-'+year, parseFormat);
605                    if($date!==null){
606                        $date = $date.toString("dd-MM-yyyy");
607                        SUPER.init_connected_datepicker(el, $date, parseFormat, oneDay, skipFieldChangeForElement);
608                    }
609                }
610            }else{
611                el.dataset.mathYear = '0';
612                el.dataset.mathMonth = '0';
613                el.dataset.mathDay = '0';
614                el.dataset.mathDiff = '0';
615                el.dataset.mathAge = '0';
616            }
617
618            var multiDatesClassName = 'super-datepicker-multidates',
619                singleDatesClassName = 'super-datepicker-singledates';
620            var options = {
621                onClose: function( selectedDate ) {
622                    SUPER.init_connected_datepicker(this, selectedDate, parseFormat, oneDay, skipFieldChangeForElement);
623                },
624                beforeShowDay: function(dt) {
625                    workDays = (this.dataset.workDays == 'true');
626                    weekends = (this.dataset.weekends == 'true');
627                    day = dt.getDay();
628                    exclDays = this.dataset.exclDays;
629                    exclDates = (typeof this.dataset.exclDates !=='undefined' ? this.dataset.exclDates : undefined);
630                    exclDaysOverride = this.dataset.exclDaysOverride;
631                    exclDaysOverride = (typeof this.dataset.exclDaysOverride !=='undefined' ? this.dataset.exclDaysOverride : undefined);
632
633                    if(typeof exclDays !== 'undefined'){
634                        days = exclDays.split(',');
635                        found = (days.indexOf(day.toString()) > -1);
636                        if(found){
637                            if(typeof exclDaysOverride !== 'undefined'){
638                                regex = /{([^\\\/\s"'+]*?)}/g;
639                                exclDaysOverrideReplaced = SUPER.update_variable_fields.replace_tags({form: form, regex: regex, value: exclDaysOverride});
640                                exclDaysOverrideReplaced = exclDaysOverrideReplaced.split("\n");
641                                date = ('0' + dt.getDate()).slice(-2);
642                                month = ('0' + (dt.getMonth()+1)).slice(-2);
643                                fullDate = dt.getFullYear() + '-' + month + '-' + date;
644                                var x;
645                                for( x=0; x < exclDaysOverrideReplaced.length; x++ ) {
646                                    if(exclDaysOverrideReplaced[x]==='') continue;
647                                    // If excluding a fixed day of month
648                                    if(exclDaysOverrideReplaced[x].length<=2){
649                                        if(exclDaysOverrideReplaced[x]==day){
650                                            return [true, ""];
651                                        }
652                                    }
653                                    // If excluding a specific month
654                                    if(exclDaysOverrideReplaced[x].length===3){
655                                        if(exclDaysOverrideReplaced[x].toLowerCase()==dt.toString('MMM').toLowerCase()){
656                                            return [true, ""];
657                                        }
658                                    }
659                                    // If excluding a date range
660                                    if(exclDaysOverrideReplaced[x].split(';').length>1){
661                                        dateFrom = exclDaysOverrideReplaced[x].split(';')[0];
662                                        dateTo = exclDaysOverrideReplaced[x].split(';')[1];
663                                        d1 = dateFrom.split("-");
664                                        d2 = dateTo.split("-");
665                                        from = new Date(d1[0], parseInt(d1[1], 10)-1, d1[2]);  // -1 because months are from 0 to 11
666                                        to   = new Date(d2[0], parseInt(d2[1], 10)-1, d2[2]);
667                                        check = new Date(dt.getFullYear(), parseInt(month, 10)-1, date);
668                                        if(check >= from && check <= to){
669                                            return [true, ""];
670                                        }
671                                    }
672                                    // If excluding single date
673                                    if(exclDaysOverrideReplaced[x]==fullDate){
674                                        return [true, ""];
675                                    }
676                                }
677                                // Be default we disable this day
678                                return [false, "super-disabled-day"];
679                            }else{
680                                return [false, "super-disabled-day"];
681                            }
682                        }
683                    }
684                    if(typeof exclDates !== 'undefined'){
685                        regex = /{([^\\\/\s"'+]*?)}/g;
686                        exclDatesReplaced = SUPER.update_variable_fields.replace_tags({form: form, regex: regex, value: exclDates});
687                        exclDatesReplaced = exclDatesReplaced.split("\n");
688                        date = ('0' + dt.getDate()).slice(-2);
689                        month = ('0' + (dt.getMonth()+1)).slice(-2);
690                        fullDate = dt.getFullYear() + '-' + month + '-' + date;
691                        var y;
692                        for( y=0; y < exclDatesReplaced.length; y++ ) {
693                            if(exclDatesReplaced[y]==='') continue;
694                            // If excluding a fixed day of month
695                            if(exclDatesReplaced[y].length<=2){
696                                if(exclDatesReplaced[y]==day){
697                                    return [false, "super-disabled-day"];
698                                }
699                            }
700                            // If excluding a specific month
701                            if(exclDatesReplaced[y].length===3){
702                                if(exclDatesReplaced[y].toLowerCase()==dt.toString('MMM').toLowerCase()){
703                                    return [false, "super-disabled-day"];
704                                }
705                            }
706                            // If excluding a date range
707                            if(exclDatesReplaced[y].split(';').length>1){
708                                dateFrom = exclDatesReplaced[y].split(';')[0];
709                                dateTo = exclDatesReplaced[y].split(';')[1];
710                                d1 = dateFrom.split("-");
711                                d2 = dateTo.split("-");
712                                from = new Date(d1[0], parseInt(d1[1], 10)-1, d1[2]);  // -1 because months are from 0 to 11
713                                to   = new Date(d2[0], parseInt(d2[1], 10)-1, d2[2]);
714                                check = new Date(dt.getFullYear(), parseInt(month, 10)-1, date);
715                                if(check >= from && check <= to){
716                                    return [false, "super-disabled-day"];
717                                }
718                            }
719                            // If excluding single date
720                            if(exclDatesReplaced[y]==fullDate){
721                                return [false, "super-disabled-day"];
722                            }
723                        }
724                    }
725                    if( (weekends===true) && (workDays===true) ) {
726                        return [true, ""];
727                    }else{
728                        if(weekends===true){
729                            return [day === 0 || day == 6, ""];
730                        }
731                        if(workDays===true){
732                            return [day == 1 || day == 2 || day == 3 || day == 4 || day == 5, ""];
733                        }
734                    }
735                    return [];
736                },
737                beforeShow: function(input, inst) {
738                    var maxPicks = (inst.settings.maxPicks ? inst.settings.maxPicks : 1);
739                    widget = $(inst).datepicker('widget');
740                    widget[0].classList.add('super-datepicker-dialog');
741                    if(maxPicks<=1){
742                        widget[0].classList.remove(multiDatesClassName);
743                        widget[0].classList.add(singleDatesClassName);
744                        $('.super-datepicker[data-connected-min="'+$(this).attr('name')+'"]').each(function(){
745                            if($(this).val()!==''){
746                                connectedMinDays = $(this).data('connected-min-days');
747                                minDate = Date.parseExact($(this).val(), parseFormat).add({ days: connectedMinDays }).toString(jsformat);
748                                $(el).datepicker('option', 'minDate', minDate );
749                            }
750                        });
751                    }else{
752                        widget[0].classList.add(multiDatesClassName);
753                        widget[0].classList.remove(singleDatesClassName);
754                    }
755                    $('.super-datepicker[data-connected-max="'+$(this).attr('name')+'"]').each(function(){
756                        if($(this).val()!==''){
757                            connectedMaxDays = $(this).data('connected-max-days');
758                            maxDate = Date.parseExact($(this).val(), parseFormat).add({ days: connectedMaxDays }).toString(jsformat);
759                            $(el).datepicker('option', 'maxDate', maxDate );
760                        }
761                    });
762                },
763                yearRange: range, //'-100:+5', // specifying a hard coded year range
764                showAnim: '',
765                showOn: $(this).parent().find('.super-icon'),
766                minDate: min,
767                maxDate: max,
768                dateFormat: format, //mm/dd/yy    -    yy-mm-dd    -    d M, y    -    d MM, y    -    DD, d MM, yy    -    &apos;day&apos; d &apos;of&apos; MM &apos;in the year&apos; yy
769                firstDay: firstDay,
770                isRTL: isRTL,
771                closeText: super_elements_i18n.closeText,
772                prevText: super_elements_i18n.prevText,
773                nextText: super_elements_i18n.nextText,
774                currentText: super_elements_i18n.currentText,
775                monthNames: super_elements_i18n.monthNames, // set month names
776                monthNamesShort: super_elements_i18n.monthNamesShort, // set short month names
777                dayNames: super_elements_i18n.dayNames, // set days names
778                dayNamesShort: super_elements_i18n.dayNamesShort, // set short day names
779                dayNamesMin: super_elements_i18n.dayNamesMin, // set more short days names
780                weekHeader: super_elements_i18n.weekHeader,
781                changeMonth: changeMonth,
782                changeYear: changeYear,
783                showMonthAfterYear: showMonthAfterYear,
784                showWeek: showWeek,
785                numberOfMonths: numberOfMonths,
786                yearSuffix: '',
787                showOtherMonths: showOtherMonths,
788                selectOtherMonths: selectOtherMonths
789            };
790            
791            // Do a try catch because otherwise user might be locked out from the builder page if they made a mistake in entering for instance the "range" (yearRange)
792            try {
793                if(maxPicks>1){
794                    options.maxPicks = maxPicks;
795                    $(el).multiDatesPicker(options);
796                    // @since 4.9.583 - Fixes issue where the month would change back to January after selecting a second date or more
797                    $.datepicker._selectDateOverload = $.datepicker._selectDate;
798                    $.datepicker._selectDate = function (id, dateStr) {
799                        var target = $(id);
800                        var inst = this._getInst(target[0]);
801                        inst.inline = true;
802                        $.datepicker._selectDateOverload(id, dateStr);
803                        inst.inline = false;
804                        if (target[0].multiDatesPicker != null) {
805                            target[0].multiDatesPicker.changed = false;
806                        } else {
807                            target.multiDatesPicker.changed = false;
808                        }
809                        this._updateDatepicker(inst);
810                        // Close datepicker if it isn't a so called Multi-datepicker, or when maxPicks is set to 1
811                        if(typeof inst.settings.maxPicks==='undefined' || inst.settings.maxPicks<=1 ){
812                            $(target).datepicker('hide');
813                        }
814                    };
815                }else{
816                    $(el).datepicker(options);
817                }
818                if(typeof min !== 'undefined'){ 
819                    $(el).datepicker('option', 'minDate', min );
820                }
821
822                // @since 4.9.3 - Datepicker localization (language and format)
823                if(localization!==''){
824                    if(typeof $.datepicker.regional[localization] !== 'undefined'){
825                        $.datepicker.regional[localization].yearSuffix = '';
826                        $(el).datepicker( "option", $.datepicker.regional[localization] );
827                    }
828                }
829            } catch (error) {
830                // eslint-disable-next-line no-console
831                console.log(error);
832                alert(error);
833            }
834
835            $(el).parent().find('.super-icon').css('cursor','pointer');
836        }
837        $('.super-datepicker').parent().find('.super-icon').on('click',function(){
838            $(this).parent().find('.super-datepicker').datepicker('show');
839        });
840        $('.super-datepicker').on('click focus',function(){
841            if($('.super-timepicker').length){
842                $('.super-timepicker').timepicker('hide');
843            }
844            $(this).datepicker('show');
845        });
846
847
848        function set_timepicker_dif($this){
849            var $value = $this.val(),
850                hours,minutes,AMPM,sHours,sMinutes,
851                $h,$m,$s,today,dd,mm,yyyy,d,$timestamp;
852
853            // @since 3.4.0 - If Ante/Post meridiem 12 hour format make sure to convert it to 24 hour format
854            if( $this.data('format')=='h:i A' ) {
855                if($value==='') $value = '12:00 AM';
856                hours = Number($value.match(/^(\d+)/)[1]);
857                minutes = Number($value.match(/:(\d+)/)[1]);
858                AMPM = $value.match(/\s(.*)$/)[1];
859                if(AMPM == 'PM' && hours<12) hours = hours+12;
860                if(AMPM == 'AM' && hours==12) hours = hours-12;
861                sHours = hours.toString();
862                sMinutes = minutes.toString();
863                if( hours<10 ) sHours = '0' + sHours;
864                if( minutes<10 ) sMinutes = '0' + sMinutes;
865                $value = sHours + ':' + sMinutes;
866            }
867
868            $value = $value.split(':');
869            if(typeof $value[0] === 'undefined') $value[0] = '00';
870            if(typeof $value[1] === 'undefined') $value[1] = '00';
871            $h = $value[0];
872            $m = $value[1].split(' ');
873            $m = $m[0];
874            if(typeof $value[2] === 'undefined'){
875                $s = '00';
876            }else{
877                $s = $value[2];
878            }
879            today = new Date();
880            dd = today.getDate();
881            mm = today.getMonth();
882            yyyy = today.getFullYear();
883            d = new Date(Date.UTC(yyyy, mm, dd, $h, $m, $s));
884            $timestamp = d.getTime();
885            $this[0].dataset.mathDiff = $timestamp;
886            SUPER.after_field_change_blur_hook({el: $this[0]});
887        }
888
889        // Init timepickers
890        $('.super-timepicker:not(.ui-timepicker-input)').each(function(){
891            // Only if timepicker is a function
892            if (typeof $.fn.timepicker !== 'function') return false;
893            var $this = $(this),
894                form = SUPER.get_frontend_or_backend_form({el: this}),
895                regex = /{([^\\\/\s"'+]*?)}/g,
896                $is_rtl = form.classList.contains('super-rtl'),
897                $orientation = 'l',
898                format = $this.data('format'),
899                step = $this.data('step'),
900                range = $this.data('range'),
901                min = $this.data('minlength'),
902                max = $this.data('maxlength'),
903                duration = $this.data('duration'),
904                finalrange = [],
905                $form_id,
906                $form_size;
907
908            if(min==='') min = '00:00';
909            if(max==='') max = '23:59';
910            if(typeof min !== 'undefined') {
911                min = min.toString();
912                min = SUPER.update_variable_fields.replace_tags({form: form, regex: regex, value: min});
913                if(min.indexOf(':')===-1){
914                    if(min !== parseInt(min, 10)){
915                        min = parseInt(min, 10);
916                        var prevMin = min - (min % (step*60));
917                        min = prevMin + 1800;
918                    }
919                }
920            }
921            if(typeof max !== 'undefined') {
922                max = max.toString();
923                max = SUPER.update_variable_fields.replace_tags({form: form, regex: regex, value: max});
924                if(max.indexOf(':')===-1){
925                    if(max !== parseInt(max, 10)){
926                        max = parseInt(max, 10);
927                        var prevMax = max - (max % (step*60));
928                        max = prevMax + 1800;
929                    }
930                }
931            }
932            if((range!=='') && (typeof range !== 'undefined')){
933                range = range.split('\n');
934                $.each(range, function(key, value ) {
935                    finalrange.push(value.split('|'));
936                });
937            }
938            $form_id = form.id;
939            $form_size = form.dataset.fieldSize;
940            if($is_rtl===true){
941                $orientation = 'r';
942            }
943
944
945            $this.timepicker({
946                className: $form_id+' super-timepicker-dialog super-field-size-'+$form_size,
947                timeFormat: format,
948                step: step,
949                disableTimeRanges: finalrange,
950                minTime: min,
951                maxTime: max,
952                showDuration: duration,
953                orientation: $orientation
954            });
955            $this.parent().find('.super-icon').css('cursor','pointer');
956            set_timepicker_dif($this);
957        });
958
959        $('.super-timepicker').on('changeTime', function() {
960            set_timepicker_dif($(this));
961            if(this.value===''){
962                this.closest('.super-field').classList.remove('super-filled');
963            }else{
964                this.closest('.super-field').classList.add('super-filled');
965            }
966        });
967        $('.super-timepicker').parent().find('.super-icon').on('click',function(){
968            $(this).parent().find('.super-timepicker').timepicker('show');
969        });
970    };
971
972    // Initialize button colors
973    SUPER.init_button_colors = function( el ) {    
974        var i, nodes, type, color, light, dark, font, fontHover, wrap, icon, btnName, btnNameIcon;
975
976        if(!el){
977            nodes = document.querySelectorAll('.super-button .super-button-wrap');
978            for( i = 0; i < nodes.length; i++){
979                SUPER.init_button_colors(nodes[i]);
980            }
981        }else{
982            el = el.parentNode;
983            type = el.dataset.type;
984            color = el.dataset.color;
985            light = el.dataset.light;
986            dark = el.dataset.dark;
987            font = el.dataset.font;
988            fontHover = el.dataset.fontHover;
989            wrap = el.querySelector('.super-button-wrap');
990            icon = wrap.querySelector('.super-before');
991            btnName = wrap.querySelector('.super-button-name');
992            btnNameIcon = btnName.querySelector('i');
993            if(type=='diagonal'){
994                if(typeof color !== 'undefined'){
995                    wrap.style.borderColor = color;
996                }else{
997                    wrap.style.borderColor = '';
998                }
999                if(typeof font !== 'undefined'){
1000                    if(icon) icon.style.color = font;
1001                    btnName.style.color = font;
1002                    if(btnNameIcon) btnNameIcon.style.color = font;
1003                }else{
1004                    if(icon) icon.style.color = '';
1005                    btnName.style.color = '';
1006                    if(btnNameIcon) btnNameIcon.style.color = '';
1007                }
1008                el.querySelector('.super-button-wrap .super-after').style.backgroundColor = color;
1009            }
1010            if(type=='outline'){
1011                if(typeof color !== 'undefined'){
1012                    wrap.style.borderColor = color;
1013                }else{
1014                    wrap.style.borderColor = '';
1015                }
1016                wrap.style.backgroundColor = '';
1017                if(typeof font !== 'undefined'){
1018                    if(icon) icon.style.color = font;
1019                    btnName.style.color = font;
1020                    if(btnNameIcon) btnNameIcon.style.color = font;
1021                }else{
1022                    if(icon) icon.style.color = '';
1023                    btnName.style.color = '';
1024                    if(btnNameIcon) btnNameIcon.style.color = '';
1025                }
1026            }
1027            if(type=='2d'){
1028                wrap.style.backgroundColor = color;
1029                wrap.style.borderColor = light;
1030                if(icon) icon.style.color = font;
1031                btnName.style.color = font;
1032                if(btnNameIcon) btnNameIcon.style.color = font;
1033            }
1034            if(type=='3d'){
1035                wrap.style.backgroundColor = color;
1036                wrap.style.color = dark;
1037                wrap.style.borderColor = light;
1038                if(typeof fontHover !== 'undefined'){
1039                    if(icon) icon.style.color = font;
1040                    btnName.style.color = font;
1041                    if(btnNameIcon) btnNameIcon.style.color = font;
1042                }else{
1043                    if(typeof font !== 'undefined'){
1044                        if(icon) icon.style.color = font;
1045                        btnName.style.color = font;
1046                        if(btnNameIcon) btnNameIcon.style.color = font;
1047                    }else{
1048                        if(icon) icon.style.color = '';
1049                        btnName.style.color = '';
1050                        if(btnNameIcon) btnNameIcon.style.color = '';
1051                    }
1052                }
1053            }
1054            if(type=='flat'){
1055                wrap.style.backgroundColor = color;
1056                if(icon) icon.style.color = font;
1057                btnName.style.color = font;
1058                if(btnNameIcon) btnNameIcon.style.color = font;
1059            }
1060        }
1061    };
1062
1063    // Init button hover colors
1064    SUPER.init_button_hover_colors = function( el ) {  
1065        var type = el.dataset.type,
1066            color = el.dataset.color,
1067            hoverColor = el.dataset.hoverColor,
1068            hoverLight = el.dataset.hoverLight,
1069            hoverDark = el.dataset.hoverDark,
1070            font = el.dataset.font,
1071            fontHover = el.dataset.fontHover,
1072            wrap = el.querySelector('.super-button-wrap'),
1073            icon = wrap.querySelector('.super-before'),
1074            btnName = wrap.querySelector('.super-button-name'),
1075            btnNameIcon = btnName.querySelector('i');
1076        if(type=='2d'){
1077            wrap.style.backgroundColor = hoverColor;
1078            wrap.style.borderColor = hoverLight;
1079            if(icon) icon.style.color = fontHover;
1080            btnName.style.color = fontHover;
1081            if(btnNameIcon) btnNameIcon.style.color = fontHover;
1082        }
1083        if(type=='flat'){
1084            wrap.style.backgroundColor = hoverColor;
1085            if(icon) icon.style.color = fontHover;
1086            btnName.style.color = fontHover;
1087            if(btnNameIcon) btnNameIcon.style.color = fontHover;
1088        }
1089        if(type=='outline'){
1090            if(typeof hoverColor !== 'undefined'){
1091                wrap.style.backgroundColor = hoverColor;
1092            }else{
1093                if(typeof color !== 'undefined'){
1094                    wrap.style.backgroundColor = color;
1095                }else{
1096                    wrap.style.backgroundColor = '';
1097                }
1098            }
1099            wrap.style.borderColor = hoverColor;
1100            if(typeof fontHover !== 'undefined'){
1101                if(icon) icon.style.color = fontHover;
1102                btnName.style.color = fontHover;
1103                if(btnNameIcon) btnNameIcon.style.color = fontHover;
1104            }else{
1105                if(typeof font !== 'undefined'){
1106                    if(icon) icon.style.color = font;
1107                    btnName.style.color = font;
1108                    if(btnNameIcon) btnNameIcon.style.color = font;
1109                }else{
1110                    if(icon) icon.style.color = '';
1111                    btnName.style.color = '';
1112                    if(btnNameIcon) btnNameIcon.style.color = '';
1113                }
1114            }
1115        }
1116        if(type=='diagonal'){
1117            if(typeof color !== 'undefined'){
1118                wrap.style.borderColor = hoverColor;
1119            }else{
1120                wrap.style.borderColor = '';
1121            }
1122            if(typeof font !== 'undefined'){
1123                if(icon) icon.style.color = fontHover;
1124                btnName.style.color = fontHover;
1125                if(btnNameIcon) btnNameIcon.style.color = fontHover;
1126            }else{
1127                if(icon) icon.style.color = '';
1128                btnName.style.color = '';
1129                if(btnNameIcon) btnNameIcon.style.color = '';
1130            }
1131            wrap.querySelector('.super-after').style.backgroundColor = hoverColor;
1132            return false;
1133        }
1134        if(type=='2d'){
1135            return false;
1136        }
1137        if(typeof hoverColor !== 'undefined'){
1138            wrap.style.backgroundColor = hoverColor;
1139            if(type=='3d'){
1140                wrap.style.color = hoverDark;
1141                wrap.style.borderColor = hoverLight;
1142                if(typeof fontHover !== 'undefined'){
1143                    if(icon) icon.style.color = fontHover;
1144                    btnName.style.color = fontHover;
1145                    if(btnNameIcon) btnNameIcon.style.color = fontHover;
1146                }else{
1147                    if(typeof font !== 'undefined'){
1148                        if(icon) icon.style.color = font;
1149                        btnName.style.color = font;
1150                        if(btnNameIcon) btnNameIcon.style.color = font;
1151                    }else{
1152                        if(icon) icon.style.color = '';
1153                        btnName.style.color = '';
1154                        if(btnNameIcon) btnNameIcon.style.color = '';
1155                    }
1156                }
1157            }
1158        }
1159    };
1160
1161    // Retrieve amount of decimals based on a numberic value
1162    SUPER.get_decimal_places = function($number){
1163        var $match = (''+$number).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
1164        if (!$match) { return 0; }
1165        return Math.max(0, ($match[1] ? $match[1].length : 0) - ($match[2] ? +$match[2] : 0));
1166    };
1167    SUPER.getAllUrlParams = function(url) {
1168        var queryString = url ? url.split('?')[1] : window.location.search.slice(1);
1169        var obj = {};
1170        if (queryString) {
1171            queryString = queryString.split('#')[0];
1172            var arr = queryString.split('&');
1173            for (var i = 0; i < arr.length; i++) {
1174                var a = arr[i].split('=');
1175                var paramName = a[0];
1176                var paramValue = typeof (a[1]) === 'undefined' ? true : a[1];
1177                paramName = paramName.toLowerCase();
1178                if (typeof paramValue === 'string') paramValue = paramValue.toLowerCase();
1179                if (paramName.match(/\[(\d+)?\]$/)) {
1180                    var key = paramName.replace(/\[(\d+)?\]/, '');
1181                    if (!obj[key]) obj[key] = [];
1182                    if (paramName.match(/\[\d+\]$/)) {
1183                        var index = /\[(\d+)\]/.exec(paramName)[1];
1184                        obj[key][index] = paramValue;
1185                    } else {
1186                        obj[key].push(paramValue);
1187                    }
1188                } else {
1189                    if (!obj[paramName]) {
1190                        obj[paramName] = paramValue;
1191                    } else if (obj[paramName] && typeof obj[paramName] === 'string'){
1192                        obj[paramName] = [obj[paramName]];
1193                        obj[paramName].push(paramValue);
1194                    } else {
1195                        obj[paramName].push(paramValue);
1196                    }
1197                }
1198            }
1199        }
1200        return obj;
1201    };
1202    // Get index of element based on parent node
1203    SUPER.index = function (node, class_name) {
1204        var index = 0;
1205        while (node.previousElementSibling) {
1206            node = node.previousElementSibling;
1207            // Based on specified class name
1208            if (class_name) {
1209                if (node.classList.contains(class_name)) {
1210                    index++;
1211                }
1212            } else {
1213                index++;
1214            }
1215
1216        }
1217        return index;
1218    };
1219    SUPER.get_dynamic_column_depth = function(field, nameSuffix, clone, cloneIndex){
1220        if(typeof nameSuffix === 'undefined') nameSuffix = '';
1221        if(typeof cloneIndex === 'undefined') cloneIndex = 0;
1222        var allParents = $(field).parents('.super-duplicate-column-fields');
1223        var suffix = [];
1224        $(allParents).each(function(key){
1225            if(key===0){
1226                if(clone===this){
1227                    if(cloneIndex>0){
1228                        return;
1229                    }
1230                }
1231            }
1232            var currentParent = this;
1233            var currentParentIndex = SUPER.index(this, 'super-duplicate-column-fields');
1234            if(currentParentIndex===0 && key===0){
1235                // Skip it
1236                return;
1237            }
1238            suffix.push('['+currentParentIndex+']');
1239        });
1240        return suffix.reverse().join('');
1241    }
1242    SUPER.append_dynamic_column_depth = function(clone){
1243        var added_fields = {},
1244            added_fields_with_suffix = {},
1245            added_fields_without_suffix = [],
1246            i, field, parent, last_tab_index,
1247            nodes = clone.querySelectorAll('.super-shortcode-field[name]');
1248
1249        for (i = 0; i < nodes.length; ++i) {
1250            field = nodes[i];
1251            parent = field.closest('.super-field');
1252            if(field.classList.contains('super-fileupload')){
1253                field.classList.remove('super-rendered');
1254                field = field.parentNode.querySelector('.super-active-files');
1255            }
1256            // Keep valid TAB index
1257            if( (typeof parent.dataset.superTabIndex !== 'undefined') && (last_tab_index!=='') ) {
1258                last_tab_index = parseFloat(parseFloat(last_tab_index)+0.001).toFixed(3);
1259                parent.dataset.superTabIndex = last_tab_index;
1260            }
1261            added_fields[field.name] = field;
1262
1263            // Figure out how deep this node is inside dynamic columns
1264            var cloneIndex = $(clone).index();
1265            var dynamicParent = field.closest('.super-duplicate-column-fields');
1266            var nameSuffix = '';
1267            if(cloneIndex>0 && clone===dynamicParent){
1268                nameSuffix = '_'+(cloneIndex+1);
1269            }
1270            var levels = SUPER.get_dynamic_column_depth(field, nameSuffix, clone, cloneIndex);
1271            var originalFieldName = field.dataset.oname;
1272            field.name = originalFieldName+levels+nameSuffix;
1273            //field.value = field.name; 
1274            field.dataset.levels = levels;
1275            added_fields_with_suffix[originalFieldName] = field.name; 
1276            added_fields_without_suffix.push(field.name);
1277            if( field.classList.contains('hasDatepicker') ) field.classList.remove('hasDatepicker'); field.id = '';
1278            if( field.classList.contains('ui-timepicker-input') ) field.classList.remove('ui-timepicker-input');
1279        }
1280
1281
1282        // Now replace {tags} inside conditional logic/variable logic
1283        // Update conditional logic names
1284        // Update validate condition names
1285        // Update variable condition names 
1286        nodes = clone.querySelectorAll('.super-conditional-logic, .super-validate-conditions, .super-variable-conditions');
1287        for(i=0; i<nodes.length; ++i){
1288            // Before we continue replace any foreach(file_upload_fieldname)
1289            var regex = /{([-_a-zA-Z0-9]{1,})(\[.*?\])?(_\d{1,})?(?:;([a-zA-Z0-9]{1,}))?}/g;
1290            var m;
1291            var conditions = nodes[i].value;
1292            var replaceTagsWithValue = {};
1293            while ((m = regex.exec(conditions)) !== null) {
1294                // This is necessary to avoid infinite loops with zero-width matches
1295                if (m.index === regex.lastIndex) {
1296                    regex.lastIndex++;
1297                }
1298                var $o = (m[0] ? m[0] : ''); // original tag
1299                var $n = (m[1] ? m[1] : ''); // name
1300                var $d = (m[2] ? m[2] : ''); // depth
1301                var $dr = $d.replace(/[0-9]/g, "0") // depth reset to 0
1302                var $c = (m[3] ? m[3] : ''); // counter e.g: _2 or _3 etc.
1303                var $s = (m[4] ? m[4] : ''); // suffix
1304                if($s!=='') $s = ';'+$s;
1305                var currentFieldParent = $(nodes[i]).parents('.super-duplicate-column-fields:eq(0)');
1306                var findChildField = $(currentFieldParent).find('.super-shortcode-field[data-oname="'+$n+'"][data-olevels="'+$dr+'"]').first();
1307                if(findChildField.length===0) continue;
1308                var allParents = $(findChildField).parents('.super-duplicate-column-fields');
1309                var childParentIndex = $(findChildField).parents('.super-duplicate-column-fields:eq(0)').index();
1310                var suffix = [];
1311                $(allParents).each(function(key){
1312                    var currentParentIndex = $(this).index();  // e.g: 0, 1, 2
1313                    if(key===0 && currentParentIndex===0){
1314                        return;
1315                    }
1316                    suffix.push('['+currentParentIndex+']');
1317                });
1318                if(childParentIndex!==0){
1319                    delete suffix[0];
1320                }
1321                levels = suffix.reverse().join('');
1322                if(childParentIndex!==0){
1323                    replaceTagsWithValue[$o] = '{'+$n+levels+'_'+(childParentIndex+1)+$s+'}';
1324                    continue;
1325                }
1326                replaceTagsWithValue[$o] = '{'+$n+levels+$c+$s+'}';
1327            }
1328            var key;
1329            for(key in replaceTagsWithValue) {
1330                nodes[i].value = SUPER.replaceAll(nodes[i].value, key, replaceTagsWithValue[key]);
1331            }
1332        }
1333        $.each(added_fields, function(name, field) {
1334            SUPER.after_field_change_blur_hook({form: clone, el: field});
1335        });
1336        return {
1337            added_fields: added_fields,
1338            added_fields_with_suffix: added_fields_with_suffix,
1339            added_fields_without_suffix: added_fields_without_suffix
1340        }
1341    };
1342
1343    jQuery(document).ready(function ($) {
1344        
1345        SUPER.init_common_fields();
1346
1347        var $doc = $(document);
1348
1349        // When Elementor popup is opened re-init super forms
1350        $doc.on('elementor/popup/show', () => {
1351            SUPER.init_super_form_frontend();
1352        });
1353
1354        $doc.on('focusin', function(e){
1355            var i, nodes;
1356            if(!e.target.tagName || typeof e.target.closest !== 'function') return true;
1357            if(e.target.closest('.super-timepicker-dialog')){
1358                // timepicker element was clicked
1359                SUPER.focusForm(e.relatedTarget);
1360                return true;
1361            }
1362            if(e.target.closest('.super-datepicker-dialog')){
1363                // datepicker element was clicked
1364                SUPER.focusForm(e.relatedTarget);
1365                return true;
1366            }
1367            if(SUPER.lastTabKey){
1368                if(e.target.tagName==='FORM' && e.target.closest('.super-form')){
1369                    // Check if form is already focussed
1370                    if(e.target.classList.contains('super-form-focussed')){
1371                        // form is already focussed, just continue
1372                        return true;
1373                    }
1374                    // Focus form
1375                    // is a super form, lets focus it by adding super-form-focussed class
1376                    SUPER.focusForm(e.target);
1377                    SUPER.lastFocussedForm = e.target;
1378                    var form = SUPER.lastFocussedForm;
1379                    var field, visibleNodes = [];
1380                    if(SUPER.lastTabKey==='tab'){
1381                        e.target.blur();
1382                        // the form became focus via regular tab, so we must focus the first field
1383                        nodes = form.querySelectorAll('.super-field:not('+super_common_i18n.tab_index_exclusion+')');
1384                        for (i = 0; i < nodes.length; i++) {
1385                            if(SUPER.has_hidden_parent(nodes[i])) continue;
1386                            visibleNodes.push(nodes[i]);
1387                            break;
1388                        }
1389                        field = visibleNodes[0];
1390                        SUPER.focusNextTabField(e, field, form, field);
1391                    }
1392                    if(SUPER.lastTabKey==='shift+tab'){
1393                        if(SUPER.firstFocussedField){
1394                            // the form has focus, and the last focussed field was the first, so we do a regular shift+tab
1395                            return true;
1396                        }
1397                        e.target.blur();
1398                        // the form became focus via shift+tab, so we must focus the last field
1399                        nodes = form.querySelectorAll('.super-field:not('+super_common_i18n.tab_index_exclusion+')');
1400                        for (i = 0; i < nodes.length; i++) {
1401                            if(SUPER.has_hidden_parent(nodes[i])
1401) continue;
1402                            visibleNodes.push(nodes[i]);
1403                        }
1404                        field = visibleNodes[visibleNodes.length-1];
1405                        SUPER.focusNextTabField(e, field, form, field);
1406                    }
1407                    e.preventDefault();
1408                    return false;
1409                }else{
1410                    // Check if the element is part of the last focussed form
1411                    if(SUPER.lastFocussedForm && e.target.closest('form') && e.target.closest('form')===SUPER.lastFocussedForm){
1412                        // element is part of last focussed form, focus the element
1413                        SUPER.focusForm(e.target);
1414                        if(!e.target.classList.contains('super-placeholder')){
1415                            SUPER.focusField(e.target);
1416                        }
1417                    }else{
1418                        // element is not part of last focussed form, removing super-form-focussed class
1419                        if(SUPER.lastFocussedForm){
1420                            SUPER.lastFocussedForm.classList.remove('super-form-focussed');
1421                            SUPER.lastFocussedForm.tabIndex = 0;
1422                            // Make sure to remove focus/open classes
1423                            nodes = SUPER.lastFocussedForm.querySelectorAll('.super-focus');
1424                            for(i = 0; i < nodes.length; i++){
1425                                nodes[i].classList.remove('super-focus');
1426                                nodes[i].classList.remove('super-open');
1427                            }
1428                            nodes = SUPER.lastFocussedForm.querySelectorAll('.super-open');
1429                            for(i = 0; i < nodes.length; i++){
1430                                nodes[i].classList.remove('super-open');
1431                            }
1432                        }
1433                    }
1434                }
1435            }else{
1436                if(e.target.tagName==='FORM' && e.target.closest('.super-form')){
1437                    SUPER.focusForm(e.target);
1438                    SUPER.lastFocussedForm = e.target;
1439                    SUPER.lastFocussedForm.tabIndex = -1;
1440                }else{
1441                    // Might be a field inside the form
1442                    if(e.target.closest('.super-form')){
1443                        SUPER.focusField(e.target);
1444                        SUPER.focusForm(e.target.closest('form'));
1445                    }
1446                }
1447            }
1448        });
1449        $doc.keydown(function(e){
1450            SUPER.lastTabKey = undefined;
1451            var i, nodes,
1452                field,
1453                form,
1454                item,
1455                current,
1456                submitButton,
1457                nextSibling,
1458                keyCode = e.keyCode || e.which;
1459
1460            // 32 = space
1461            if (keyCode == 32) {
1462                field = document.querySelector('.super-focus');
1463                if(field){
1464                    form = field.closest('.super-form');
1465                    // If checkbox or radio, then we check/uncheck the current focussed item
1466                    if(field.classList.contains('super-checkbox') || field.classList.contains('super-radio')){
1467                        if(field.querySelector('.super-focus')){
1468                            if(field.classList.contains('super-checkbox')){
1469                                SUPER.simulateCheckboxItemClicked(e, field.querySelector('.super-focus'));
1470                            }else{
1471                                SUPER.simulateRadioItemClicked(e, field.querySelector('.super-focus'));
1472                            }
1473                        }
1474                        e.preventDefault();
1475                        return false;
1476                    }
1477                    // If toggle
1478                    if(field.classList.contains('super-toggle')){
1479                        field.querySelector('.super-toggle-switch').click();
1480                        e.preventDefault();
1481                        return false;
1482                    }
1483                }
1484            }
1485            
1486            // 13 = enter
1487            if (keyCode == 13) {
1488                field = document.querySelector('.super-focus');
1489                if(field){
1490                    if(field.classList.contains('super-text')){
1491                        var countryList = field.querySelector('.super-int-phone_country-list');
1492                        if(countryList){
1493                            if(!countryList.classList.contains('.super-int-phone_hide')){
1494                                e.preventDefault();
1495                                return false;
1496                            }
1497                        }
1498                    }
1499                    if(field.classList.contains('super-dropdown')){
1500                        item = field.querySelector('.super-focus');
1501                        if(item) item.click();
1502                        e.preventDefault();
1503                        return false;
1504                    }
1505                    if(field.classList.contains('super-file')){
1506                        field.querySelector('.super-fileupload-button').click();
1507                        e.preventDefault();
1508                        return false;
1509                    }
1510                    if( field.classList.contains('super-textarea') ) {
1511                        // Allow to add line breaks on textarea elements
1512                        return true;
1513                    }
1514                    form = field.closest('.super-form');
1515                    // @since 3.3.0 - Do not submit form if Enter is disabled
1516                    if(form && form.dataset.disableEnter=='true'){
1517                        e.preventDefault();
1518                        return false;
1519                    }
1520                    if(!form.querySelector('.super-form-button.super-loading')){
1521                        submitButton = form.querySelector('.super-form-button .super-button-wrap .super-button-name[data-action="submit"]');
1522                        if(submitButton) {
1523                            var args = {
1524                                el: undefined,
1525                                form: form,
1526                                submitButton: submitButton.parentNode,
1527                                validateMultipart: undefined,
1528                                event: e,
1529                                doingSubmit: true
1530                            };
1531                            SUPER.validate_form(args);
1532                        }
1533                    }
1534                    e.preventDefault();
1535                }
1536            }
1537            // 37 = left arrow
1538            // 38 = up arrow
1539            // 39 = right arrow
1540            // 40 = down arrow
1541            if ( keyCode == 37 || keyCode == 38 || keyCode == 39 || keyCode == 40 ) {
1542                field = document.querySelector('.super-focus');
1543                if(field){
1544                    // If toggle
1545                    if(field.classList.contains('super-toggle')){
1546                        field.querySelector('.super-toggle-switch').click();
1547                        e.preventDefault();
1548                        return false;
1549                    }
1550                    // Slider field
1551                    if(field.classList.contains('super-slider')){
1552                        var inputField = field.querySelector('.super-shortcode-field');
1553                        var value = inputField.value;
1554                        var steps = inputField.dataset.steps;
1555                        var newValue;
1556                        if(keyCode == 37 || keyCode == 38){
1557                            // Reverse
1558                            newValue = parseFloat(value)-parseFloat(steps);
1559                        }else{
1560                            newValue = parseFloat(value)+parseFloat(steps);
1561                        }
1562                        SUPER.reposition_slider_amount_label(inputField, newValue);
1563                        e.preventDefault();
1564                        return false;
1565                    }
1566                    // Star rating
1567                    if(field.classList.contains('super-rating')){
1568                        // First find last active star
1569                        nodes = field.querySelectorAll('.super-active');
1570                        if(keyCode == 37 || keyCode == 38){
1571                            // Reverse
1572                            if(nodes.length) nodes[nodes.length-2].click();
1573                        }else{
1574                            if(nodes.length){
1575                                // If it isn't last star, set next star to active
1576                                if(nodes[nodes.length-1].nextSibling && nodes[nodes.length-1].nextSibling.tagName==='I'){
1577                                    nodes[nodes.length-1].nextSibling.click();
1578                                }
1579                            }else{
1580                                // No active star yet
1581                                field.querySelector('i.super-rating-star').
1581click();
1582                            }
1583                        }
1584                        e.preventDefault();
1585                        return false;
1586                    }
1587
1588                    // Dropdown
1589                    if(field.classList.contains('super-dropdown')){
1590                        var all = field.querySelectorAll('.super-item:not(.super-placeholder)');
1591                        current = field.querySelector('.super-focus');
1592                        if(!current){
1593                            // If no item is focussed we grab the active item
1594                            current = field.querySelector('.super-active');
1595                        }
1596                        if(keyCode == 37 || keyCode == 38){
1597                            // go up (reverse)
1598                            if(current){
1599                                var prev = current.previousSibling;
1600                                if(prev && !prev.classList.contains('super-placeholder')){
1601                                    current.classList.remove('super-focus');
1602                                    prev.classList.add('super-focus');
1603                                }else{
1604                                    // continue at bottom (last item)
1605                                    all[0].classList.remove('super-focus');
1606                                    all[all.length-1].classList.add('super-focus');
1607                                }
1608                            }else{
1609                                // none selected yet, focus last
1610                                all[all.length-1].classList.add('super-focus');
1611                            }
1612                        }else{
1613                            // go down
1614                            if(current){
1615                                var next = current.nextSibling;
1616                                if(next){
1617                                    current.classList.remove('super-focus');
1618                                    next.classList.add('super-focus');
1619                                }else{
1620                                    // continue at top (first item)
1621                                    all[all.length-1].classList.remove('super-focus');
1622                                    all[0].classList.add('super-focus');
1623                                }
1624                            }else{
1625                                // none selected yet, focus first
1626                                all[0].classList.add('super-focus');
1627                            }
1628                        }
1629                        current = field.querySelector('.super-focus');
1630                        current.scrollIntoView({behavior: "auto", block: "center", inline: "center"});
1631                        e.preventDefault();
1632                        return false;
1633                    }
1634
1635                    // Checkbox / Radio
1636                    if(field.classList.contains('super-checkbox') || field.classList.contains('super-radio')){
1637                        if(field.querySelector('.super-focus')){
1638                            current = field.querySelector('.super-item.super-focus');
1639                            if(current){
1640                                // 37 = left arrow
1641                                // 38 = up arrow
1642                                if(keyCode == 37 || keyCode == 38){
1643                                    // prev
1644                                    nextSibling = current.previousSibling;
1645                                }else{
1646                                    // next
1647                                    nextSibling = current.nextSibling;
1648                                }
1649                                current.classList.remove('super-focus');
1650                                if(nextSibling && nextSibling.classList.contains('super-item')){
1651                                    nextSibling.classList.add('super-focus');
1652                                    if(field.classList.contains('super-radio')){
1653                                        nextSibling.click();
1654                                    }
1655                                }else{
1656                                    // left, up
1657                                    var innerNodes = field.querySelectorAll('.super-item');
1658                                    if(keyCode == 37 || keyCode == 38){
1659                                        innerNodes[innerNodes.length-1].classList.add('super-focus');
1660                                        if(field.classList.contains('super-radio')){
1661                                            innerNodes[innerNodes.length-1].click();
1662                                        }
1663                                    }else{
1664                                        innerNodes[0].classList.add('super-focus');
1665                                        if(field.classList.contains('super-radio')){
1666                                            innerNodes[0].click();
1667                                        }
1668                                    }
1669                                }
1670                                e.preventDefault();
1671                                return false;
1672                            }
1673                        }
1674                        e.preventDefault();
1675                        return false;
1676                    }
1677                }
1678            }
1679
1680            // 37 = left arrow
1681            // 39 = right arrow
1682            // TABs left/right navigation through keyboard keys
1683            if( (keyCode == 37) || (keyCode == 39) ) {
1684                nodes = document.querySelectorAll('.super-form .super-tabs-contents');
1685                for (i = 0; i < nodes.length; i++) {
1686                    field = nodes[i].closest('.super-shortcode');
1687                    if(!SUPER.has_hidden_parent(field, true)){ // Also include Multi-part for this check
1688                        // Only if no focussed field is found
1689                        // First get the currently active TAB
1690                        var activeTab = field.querySelector('.super-tabs-contents > .super-tabs-content.super-active');
1691                        var focusFound = activeTab.querySelectorAll('.super-focus').length;
1692                        if(focusFound) continue; // Do not go to next/prev TAB if there is a focussed field
1693                        // Only if not inside other TAB element
1694                        if(!field.closest('.super-tabs-contents')){
1695                            // Go left
1696                            if( keyCode == 37 ) nodes[i].querySelector(':scope > .super-content-prev').click();
1697                            // Go right
1698                            if( keyCode == 39 ) nodes[i].querySelector(':scope > .super-content-next').click();
1699                        }
1700                    }
1701                }
1702            }
1703
1704            // 9 = TAB
1705            if (keyCode == 9) {
1706                SUPER.firstFocussedField = false;
1707                SUPER.lastTabKey = 'tab';
1708                if(e.shiftKey){
1709                    SUPER.lastTabKey = 'shift+tab';
1710                }
1711                // Check if we have a focussed form
1712                form  = document.querySelector('.super-form-focussed')
1713                if(form){
1714                    // Check if we can find a currently focussed field
1715                    field = form.querySelector('.super-field.super-focus');
1716                    if(field){
1717                        // Check if first field of form
1718                        nodes = form.querySelectorAll('.super-field:not('+super_common_i18n.tab_index_exclusion+')');
1719                        var visibleNodes = [];
1720                        for (i = 0; i < nodes.length; i++) {
1721                            if(SUPER.has_hidden_parent(nodes[i])) continue;
1722                            visibleNodes.push(nodes[i]);
1723                        }
1724                        // if we shift+tab from second visible field to first visible field, we must set tabindex on form to -1
1725                        if(field===visibleNodes[1]){
1726                            if(SUPER.lastTabKey==='shift+tab'){
1727                                form.tabIndex = -1;
1728                                SUPER.focusNextTabField(e, field, form);
1729                                e.preventDefault();
1730                                return false;
1731                            }
1732                        }
1733                        if(field===visibleNodes[0]){
1734                            // The current field is the first field in the form
1735                            SUPER.firstFocussedField = true;
1736                            if(SUPER.lastTabKey==='shift+tab'){
1737                                // Unfocus current field
1738                                SUPER.resetFocussedFields();
1739                                return true;
1740                            }
1741                        }
1742                        if(field===visibleNodes[visibleNodes.length-1]){
1743                            // The current field is the last field in the form
1744                            if(SUPER.lastTabKey==='tab'){
1745                                // If this is the last field then we do a normal tab to get out of form focus
1746                                // Unfocus current field
1747                                field.classList.remove('super-focus');
1748                                if( field.classList.contains('super-form-button') ) {
1749                                    // Check if it's a button
1750                                    SUPER.init_button_colors(field.querySelector('.super-button-wrap'));
1751                                }else{
1752                                    // If not a button
1753                                    innerNodes = field.querySelectorAll('.super-focus');
1754                                    for ( i = 0; i < innerNodes.length; i++){
1755                                        innerNodes[i].classList.remove('super-focus');
1756                                    }
1757                                }
1758                                return true;
1759                            }
1760                        }
1761
1762                        SUPER.focusNextTabField(e, field, form);
1763                        e.preventDefault();
1764                        return false;
1765                    }else{
1766                        // No focussed field yet, let's focus the first field or last depending on tab, or shift+tab
1767                        if(SUPER.lastTabKey==='tab'){
1768                            SUPER.firstFocussedField = true;
1769                            nodes = form.querySelectorAll('.super-field:not('+super_common_i18n.tab_index_exclusion+')');
1770                            for (i = 0; i < nodes.length; i++) {
1771                                if(SUPER.has_hidden_parent(nodes[i])
1771) continue;
1772                                SUPER.focusNextTabField(e, nodes[i], form, nodes[i]);
1773                                e.preventDefault();
1774                                return false;
1775                            }
1776                        }
1777                        if(SUPER.lastTabKey==='shift+tab'){
1778                            return true;
1779                        }
1780                    }
1781                    e.preventDefault();
1782                    return false;
1783                }else{
1784                    // no focussed form found, just let the TAB event execute
1785                }
1786            }
1787        });
1788
1789
1790        // @SINCE 4.9.0 - TABS content next/prev switching
1791        $doc.on('click', '.super-content-prev, .super-content-next', function(e){
1792            // Make sure we stop any other events from being triggered
1793            e.preventDefault();
1794            var $this = $(this),
1795                $tab_menu = $this.parents('.super-shortcode:eq(0)').children('.super-tabs-menu'),
1796                $tab_content = $this.parents('.super-tabs-contents:eq(0)'),
1797                $total = $tab_menu.children('.super-tabs-tab').length,
1798                $index = $tab_content.children('.super-tabs-content.super-active').index();
1799            // Next
1800            if($this.hasClass('super-content-next')){
1801                $index++;
1802                if($index >= $total) {
1803                    $index = $total-1;
1804                }
1805                if($index >= $total-1){
1806                    $tab_menu.find('.super-tab-next').hide();
1807                }else{
1808                    $tab_menu.find('.super-tab-next').show();
1809                }
1810                $tab_menu.find('.super-tab-prev').show();
1811            }
1812            // Prev
1813            if($this.hasClass('super-content-prev')){
1814                $index--;
1815                if($index < 0) {
1816                    $index = 0;
1817                }
1818                if($index===0){
1819                    $tab_menu.find('.super-tab-prev').hide();
1820                }else{
1821                    $tab_menu.find('.super-tab-prev').show();
1822                }
1823                $tab_menu.find('.super-tab-next').show();
1824            }
1825            $tab_menu.children('.super-tabs-tab').removeClass('super-active');
1826            $tab_menu.children('.super-tabs-tab:eq('+($index)+')').addClass('super-active');
1827            $tab_content.children('.super-tabs-content').removeClass('super-active');
1828            $tab_content.children('.super-tabs-content:eq('+($index)+')').addClass('super-active');
1829            return false;
1830        });
1831        // @SINCE 4.8.0 - TABS next/prev switching
1832        $doc.on('click', '.super-tab-prev, .super-tab-next', function(e){
1833            // Make sure we stop any other events from being triggered
1834            e.preventDefault();
1835            var $this = $(this),
1836                $tab_menu = $this.parents('.super-tabs-menu:eq(0)'),
1837                $tab_content = $tab_menu.parent().children('.super-tabs-contents'),
1838                $total = $this.parents('.super-tabs-menu:eq(0)').children('.super-tabs-tab').length,
1839                $index = $this.parents('.super-tabs-menu:eq(0)').children('.super-tabs-tab.super-active').index();
1840            // Next
1841            if($this.hasClass('super-tab-next')){
1842                $index++;
1843                if($index >= $total) {
1844                    $index = $total-1;
1845                }
1846                if($index >= $total-1){
1847                    $tab_menu.find('.super-tab-next').hide();
1848                }else{
1849                    $tab_menu.find('.super-tab-next').show();
1850                }
1851                $tab_menu.find('.super-tab-prev').show();
1852
1853            }
1854            // Prev
1855            if($this.hasClass('super-tab-prev')){
1856                $index--;
1857                if($index < 0) {
1858                    $index = 0;
1859                }
1860                if($index===0){
1861                    $tab_menu.find('.super-tab-prev').hide();
1862                }else{
1863                    $tab_menu.find('.super-tab-prev').show();
1864                }
1865                $tab_menu.find('.super-tab-next').show();
1866            }
1867            $tab_menu.children('.super-tabs-tab').removeClass('super-active');
1868            $tab_menu.children('.super-tabs-tab:eq('+($index)+')').addClass('super-active');
1869            $tab_content.children('.super-tabs-content').removeClass('super-active');
1870            $tab_content.children('.super-tabs-content:eq('+($index)+')').addClass('super-active');
1871            return false;
1872        });
1873        // @since 4.8.0 - TABS switching
1874        $doc.on('click', '.super-shortcode .super-tabs-tab', function(e){
1875            // Make sure we stop any other events from being triggered
1876            e.preventDefault();
1877            var $this = $(this),
1878                $index = $this.index(),
1879                $tab_menu = $this.parent('.super-tabs-menu'),
1880                $tab_content = $tab_menu.parent().children('.super-tabs-contents');
1881            $tab_menu.children('.super-tabs-tab').removeClass('super-active');
1882            $this.addClass('super-active');
1883            $tab_content.children('.super-tabs-content').removeClass('super-active');
1884            $tab_content.children('.super-tabs-content:eq('+$index+')').addClass('super-active');
1885        });
1886
1887        // @since 4.8.0 - Accordion toggles
1888        $doc.on('click', '.super-accordion-item .super-accordion-header', function(){
1889            var $this = $(this).parent(),
1890                $parent = $this.parent();
1891            if($this.hasClass('super-active')){
1892                // Close all accordion
1893                $parent.children('.super-accordion-item').removeClass('super-active');
1894            }else{
1895                // Close other accordions, then open this one
1896                $parent.children('.super-accordion-item').removeClass('super-active');
1897                // Open current one
1898                $this.addClass('super-active');
1899                // Make sure to correclty set the slider dragger when accordion is opened
1900                var i, nodes = $this[0].querySelectorAll('.super-shortcode.super-slider');
1901                for(i=0; i<nodes.length; i++){
1902                    if(nodes[i].querySelector('.slider')){
1903                        var field = nodes[i].querySelector('.super-shortcode-field');
1904                        SUPER.reposition_slider_amount_label(field, field.value, true);
1905                    }
1906                }
1907            }
1908            SUPER.init_super_responsive_form_fields({form: $parent[0]});
1909        });
1910
1911        // @since 3.1.0 - auto transform to uppercase
1912        $doc.on('input', '.super-form .super-uppercase .super-shortcode-field', function() {
1913            $(this).val(function(_, val) {
1914                return val.toUpperCase();
1915            });
1916        });
1917
1918        // @since 1.7 - count words on textarea field (useful for translation estimates)
1919        var word_count_timeout = null;
1920        $doc.on('keyup blur', 'textarea.super-shortcode-field', function(e) {
1921            var $this = $(this),
1922                $time = 250,
1923                $text,
1924                $words,
1925                $removeNoneChars,
1926                $chars,
1927                $allChars;
1928            if(e.type!='keyup') $time = 0;
1929            if (word_count_timeout !== null) {
1930                clearTimeout(word_count_timeout);
1931            }
1932            word_count_timeout = setTimeout(function () {
1933                $text = $this.val();
1934                $words = $text.match(/\S+/g);
1935                $words = $words ? $words.length : 0;
1936                $removeNoneChars = $text.replace(/\s/g, ""); // use the \s quantifier to remove all white space, is equivalent to [\r\n\t\f\v ]
1937                $chars = $removeNoneChars.length; // count only characters after removing any whitespace, tabs, linebreaks etc.
1938                $allChars = $text.length; // count all characters
1939                $this.attr('data-word-count', $words);
1940                $this.attr('data-chars-count', $chars);
1941                $this.attr('data-allchars-count', $allChars);
1942                SUPER.after_field_change_blur_hook({el: $this[0]});
1943            }, $time);
1944        });
1945
1946        // Upon opening color picker
1947        $doc.on('click', '.super-color', function(){
1948            SUPER.focusField(this);
1949        });
1950
1951        // @since 1.2.4
1952        $doc.on('click', '.super-quantity .super-minus-button, .super-quantity .super-plus-button', function(){
1953            SUPER.focusField(this);
1954            var $this = $(this),
1955                $input_field = $this.parent().find('.super-shortcode-field'),
1956                $min = parseFloat($input_field.data('minnumber')),
1957                $max = parseFloat($input_field.data('maxnumber')),
1958                $field_value = $input_field.val(),
1959                $new_value,
1960                $steps = parseFloat($input_field.data('steps')),
1961                $decimals = SUPER.get_decimal_places($steps);
1962
1963            if($field_value==='') $field_value = 0;
1964            $field_value = parseFloat($field_value);
1965            if($this.hasClass('super-plus-button')){
1966                $new_value = $field_value + $steps;
1967                $new_value = parseFloat($new_value.toFixed($decimals));
1968                if($new_value > $max) return false;
1969            }else{
1970                $new_value = $field_value - $steps;
1971                $new_value = parseFloat($new_value.toFixed($decimals));
1972                if($new_value < $min) return false;
1973            }
1974            $input_field.val($new_value);
1975            SUPER.after_field_change_blur_hook({el: $input_field[0]});
1976        });
1977        // @since 4.9.0 - Quantity field only allow number input
1978        $doc.on('blur', '.super-quantity .super-shortcode-field', function() {
1979            // Remove empty decimal place
1980            if(this.value.indexOf('.')!==-1){
1981                var split = this.value.split("."), before = split[0], after = split[1];
1982                var result = before;
1983                if(after!=='') result += '.'+after;
1984                this.value = result;
1985            } 
1986        });
1987        $doc.on('input', '.super-quantity .super-shortcode-field', function() {
1988            // Exception when using steps with decimals, then allow to enter decimal number
1989            if(this.dataset.steps.indexOf('.')!==-1){
1990                // Count decimals
1991                var decimals = this.dataset.steps.toString().split(".")[1].length || 0; 
1992                var floor = Math.floor(this.dataset.steps);
1993                if(floor===this.dataset.steps) decimals = 0;
1994                this.value = (this.value.indexOf(".")!==-1) ? (this.value.substr(0, this.value.indexOf(".")) + this.value.substr(this.value.indexOf("."), (decimals+1))) : this.value;
1995                return;
1996            }
1997            // Only allow whole numbers
1998            this.value = this.value.replace(/[^0-9]/g, '');
1999        });
2000
2001        // @since 2.9.0 - toggle button
2002        $doc.on('click', '.super-toggle-switch', function(){
2003            var $this = $(this),
2004                $input_field = $this.parent().find('.super-shortcode-field'),
2005                $new_value = $this.find('.super-toggle-on').data('value');
2006            if( $this.hasClass('super-active')) {
2007                $new_value = $this.find('.super-toggle-off').data('value');
2008            }
2009            $this.toggleClass('super-active');
2010            $input_field.val($new_value);
2011            SUPER.focusField(this);
2012            SUPER.after_field_change_blur_hook({el: $input_field[0]});
2013        });
2014
2015        // @since 2.1 - trigger field change hook after currency field value has changed
2016        // @since 4.2 - trigger field change hook after quantity field value has changed
2017        var $calculation_threshold = null;
2018        $doc.on('keyup blur', '.super-form .super-currency .super-shortcode-field, .super-form .super-quantity .super-shortcode-field', function(e) {
2019            var $this = $(this);
2020            var $threshold = 0;
2021            if( (typeof $this.attr('data-threshold') !== 'undefined') && (e.type=='keyup') ) {
2022                $threshold = parseFloat($this.attr('data-threshold'));
2023                if ($calculation_threshold !== null) {
2024                    clearTimeout($calculation_threshold);
2025                }
2026                $calculation_threshold = setTimeout(function () {
2027                    SUPER.after_field_change_blur_hook({el: $this[0]});
2028                }, $threshold);
2029            }else{
2030                SUPER.after_field_change_blur_hook({el: $this[0]});
2031            }
2032        });
2033        
2034        $doc.on('click', '.super-form .super-duplicate-column-fields .super-add-duplicate', function(){
2035            
2036            var i, x, y,
2037                nodes,
2038                v,vv,
2039                found_field,
2040                el,
2041                parent,
2042                column,
2043                form,
2044                firstColumn,
2045                lastColumn,
2046                found,
2047                limit,
2048                unique_field_names = {},
2049                field_names = {},
2050                field_name,
2051                field_labels = {},
2052                counter = 0,
2053                field,
2054                clone,
2055                last_tab_index,
2056                added_fields = {},
2057                added_fields_with_suffix = {},
2058                added_fields_without_suffix = [],
2059                //field_counter = 0,
2060                element,
2061                foundElements = [],
2062                html_fields,
2063                data_fields,
2064                conditions,
2065                new_data_attr,
2066                new_data_fields,
2067                new_text,
2068                condition,
2069                replace_names,
2070                new_field,
2071                new_count,
2072                suffix,
2073                superMath,
2074                value_n,
2075                names,
2076                name,
2077                values,
2078                array,
2079                match,
2080                number,
2081                regex = /{([^\\\/\s"'+]*?)}/g,
2082                oldv,
2083                duplicate_dynamically;
2084
2085            el = $(this)[0];
2086            parent = el.closest('.super-duplicate-column-fields');
2087            // If custom padding is being used set $column to be the padding wrapper `div`
2088            column = ( parent.parentNode.classList.contains('super-column-custom-padding') ? el.closest('.super-column-custom-padding') : parent.closest('.super-column') );
2089            form = SUPER.get_frontend_or_backend_form({el: el, form: form});
2090            var duplicateColumns = column.querySelectorAll('.super-duplicate-column-fields');
2091            firstColumn = duplicateColumns[0];
2092            found = column.querySelectorAll(':scope > .super-duplicate-column-fields').length;
2093            limit = parseInt(column.dataset.duplicateLimit, 10);
2094            if( (limit!==0) && (found >= limit) ) {
2095                return false;
2096            }
2097
2098            
2099            unique_field_names = {}; // @since 2.4.0
2100            field_names = {};
2101            field_labels = {};
2102            counter = 0;
2103            nodes = firstColumn.querySelectorAll('.super-shortcode-field[name]');
2104            for (i = 0; i < nodes.length; ++i) {
2105                field = nodes[i];
2106                if(field.classList.contains('super-fileupload')){
2107                    field = field.parentNode.querySelector('.super-active-files');
2108                }
2109                name = field.name;
2110                unique_field_names[name] = name;
2111                field_names[counter] = name;
2112                field_labels[counter] = field.dataset.email;
2113                counter++;
2114            }
2115
2116            counter = column.querySelectorAll(':scope > .super-duplicate-column-fields').length;
2117            clone = firstColumn.cloneNode(true);
2118            lastColumn = duplicateColumns[(found-1)];
2119            lastColumn.parentNode.insertBefore(clone, lastColumn.nextElementSibling);
2120
2121            // @since 3.3.0 - hook after appending new column
2122            SUPER.after_appending_duplicated_column_hook(form, unique_field_names, clone);
2123
2124            // Now reset field values to default
2125            SUPER.init_clear_form({form: form, clone: clone});
2126
2127            // @since 3.2.0 - increment for tab index fields when dynamic column is cloned
2128            if($(clone).find('.super-shortcode[data-super-tab-index]').last().length){
2129                last_tab_index = $(clone).find('.super-shortcode[data-super-tab-index]').last().attr('data-super-tab-index');
2130            }else{
2131                last_tab_index = '';
2132            }
2133            last_tab_index = parseFloat(last_tab_index);
2134            
2135            // First rename then loop through conditional logic and update names, otherwise we might think that the field didn't exist!
2136            // Loop over all fields that are inside dynamic column and rename them accordingly
2137            var $info = SUPER.append_dynamic_column_depth(clone);
2138            added_fields_with_suffix = $info.added_fields_with_suffix;
2139 
2140            // @since 4.6.0 - update html field tags attribute
2141            // @since 4.6.0 - update accordion title and description field tags attribute
2142            // @since 4.9.6 - update google maps field tags attribute
2143            // Get all elements based on field tag attribute that contain one of these field names
2144            // Then convert it to an array and append the missing field names
2145            // @IMPORTANT: Only do this for elements that are NOT inside a dynamic column
2146            foundElements = [];
2147            $.each(added_fields_with_suffix, function( index ) {
2148                html_fields = form.querySelectorAll('[data-tags*="{'+index+'}"], .super-google-map[data-fields*="{'+index+'}"], .super-html-content[data-fields*="{'+index+'}"]');
2149                for (i = 0; i < html_fields.length; ++i) {
2150                    found = false;
2151                    for (x=0; x<foundElements.length; x++) {
2152                        if($(foundElements[x]).is(html_fields[i])) found = true;
2153                    }
2154                    if(!found) foundElements.push(html_fields[i]);
2155                }
2156            });
2157
2158            var formId = 0;
2159            if(form.querySelector('input[name="hidden_form_id"]')){
2160                formId = form.querySelector('input[name="hidden_form_id"]').value;
2161            }
2162            for(i=0; i<foundElements.length; i++) {
2163                if(!foundElements[i].parentNode.querySelector('textarea')) continue;
2164                var html = foundElements[i].parentNode.querySelector('textarea').value;
2165                html = SUPER.filter_foreach_statements(foundElements[i], 0, 0, html, undefined, formId, form);
2166                html = SUPER.replaceAll(html, '<%', '{');
2167                html = SUPER.replaceAll(html, '%>', '}');
2168                foundElements[i].innerHTML = html;
2169            }
2170            
2171            // Now replace {tags} inside HTML element
2172            for(i=0; i<foundElements.length; i++) {
2173                var html;
2174                // @since 4.9.0 - accordion title description {tags} compatibility
2175                if( foundElements[i].dataset.tags ) {
2176                    html = foundElements[i].dataset.original;
2177                }else{
2178                    if(!foundElements[i].parentNode.querySelector('textarea')) continue;
2179                    html = foundElements[i].parentNode.querySelector('textarea').value;
2180                }
2181                // If empty skip
2182                if(html===''){
2183                    continue;
2184                }
2185                // Before we continue replace any foreach(file_upload_fieldname)
2186                var regex = /{([-_a-zA-Z0-9]{1,})(\[.*?\])?(_\d{1,})?(?:;([a-zA-Z0-9]{1,}))?}/g;
2187                var m;
2188                var replaceTagsWithValue = {};
2189                while ((m = regex.exec(html)) !== null) {
2190                    // This is necessary to avoid infinite loops with zero-width matches
2191                    if (m.index === regex.lastIndex) {
2192                        regex.lastIndex++;
2193                    }
2194                    var $o = (m[0] ? m[0] : ''); // original tag
2195                    var $n = (m[1] ? m[1] : ''); // name
2196                    var $d = (m[2] ? m[2] : ''); // depth
2197                    var $dr = $d.replace(/[0-9]/g, "0") // depth reset to 0
2198                    var $c = (m[3] ? m[3] : ''); // counter e.g: _2 or _3 etc.
2199                    var $s = (m[4] ? m[4] : ''); // suffix
2200                    if($s!=='') $s = ';'+$s;
2201                    var currentFieldParent = $(foundElements[i]).parents('.super-duplicate-column-fields:eq(0)');
2202                    var findChildField = $(currentFieldParent).find('.super-shortcode-field[data-oname="'+$n+'"][data-olevels="'+$dr+'"]').first();
2203                    if(findChildField.length===0) continue;
2204                    var allParents = $(findChildField).parents('.super-duplicate-column-fields');
2205                    var childParentIndex = $(findChildField).parents('.super-duplicate-column-fields:eq(0)').index();
2206                    var suffix = [];
2207                    $(allParents).each(function(key){
2208                        var currentParentIndex = $(this).index();  // e.g: 0, 1, 2
2209                        if(key===0 && currentParentIndex===0){
2210                            return;
2211                        }
2212                        suffix.push('['+currentParentIndex+']');
2213                    });
2214                    if(childParentIndex!==0){
2215                        delete suffix[0];
2216                    }
2217                    var levels = suffix.reverse().join('');
2218                    if(childParentIndex!==0){
2219                        replaceTagsWithValue[$o] = '{'+$n+levels+'_'+(childParentIndex+1)+$s+'}';
2220                        continue;
2221                    }
2222                    replaceTagsWithValue[$o] = '{'+$n+levels+$c+$s+'}';
2223                }
2224                var key;
2225                for(key in replaceTagsWithValue) {
2226                    html = SUPER.replaceAll(html, key, replaceTagsWithValue[key]);
2227                }
2228                if( foundElements[i].dataset.tags ) {
2229                    if(foundElements[i].value || foundElements[i].dataset.value){
2230                        if(foundElements[i].value) foundElements[i].value = html;
2231                        if(foundElements[i].dataset.value) foundElements[i].dataset.value = html;
2232                    }else{
2233                        foundElements[i].dataset.original = html;
2234                    }
2235                }else{
2236                    if(!foundElements[i].parentNode.querySelector('textarea')) continue;
2237                    foundElements[i].parentNode.querySelector('textarea').value = html;
2238                }
2239
2240            }
2241            // Required to update calculations after adding dynamic column
2242            SUPER.after_field_change_blur_hook({form: form, el: undefined});
2243
2244            SUPER.init_replace_html_tags({el: undefined, form: form, foundElements: foundElements});
2245            
2246            // @since 2.4.0 - hook after adding new column
2247            SUPER.after_duplicating_column_hook(form, unique_field_names, clone);            
2248            
2249            SUPER.init_common_fields();
2250        });
2251
2252        // Delete dynamic column
2253        $doc.on('click', '.super-duplicate-column-fields .super-delete-duplicate', function(){
2254            var parent = this.closest('.super-duplicate-column-fields'),
2255                siblingRows = parent.parentNode.children,
2256                rowCount = 0,
2257                rowIndex;
2258            for(rowIndex=0; rowIndex<siblingRows.length; rowIndex++){
2259                if(siblingRows[rowIndex].classList.contains('super-duplicate-column-fields')) rowCount++;
2260            }
2261            if(rowCount<=1) return;
2262
2263            var i, x, nodes, found,
2264                form = this.closest('.super-form'),
2265                removedFields = {},
2266                dataFields,
2267                foundElements = [];
2268            nodes = parent.querySelectorAll('.super-shortcode-field');
2269            for (i = 0; i < nodes.length; ++i) {
2270                // Check if this is a file upload element, if so make sure we delete all files from the files object
2271                var fieldName = SUPER.get_field_name(nodes[i]); //SUPER.get_original_field_name = function(field){
2272                var fieldType = SUPER.get_field_type(form, fieldName);
2273                if(fieldType.type==='file'){
2274                    var w = nodes[i].closest('.super-field-wrapper');
2275                    var x, d = w.querySelectorAll('.super-fileupload-delete');
2276                    for(x=0; x<d.length; x++){
2277                        d[x].click();
2278                    }
2279                }
2280                var $this = $(nodes[i]);
2281                var $fieldWrapper = $this.parents('.super-field-wrapper:eq(0)');
2282                var $fieldName = $fieldWrapper.find('.super-active-files').attr('name');
2283                var $index = $this.parents('div:eq(0)').index();
2284                // Modify file list, and remove one element at $index
2285                // We use splice() instead of delete() because we don't want to leave the old index with an `undefined` value
2286                if(SUPER.files){
2287                    if(SUPER.files[formId]){
2288                        if(SUPER.files[formId][$fieldName]){
2289                            SUPER.files[formId][$fieldName].splice($index, 1); 
2290                        }
2291                    }
2292                }
2293                var $parent = $this.parents('.super-fileupload-files:eq(0)');
2294                var $wrapper = $parent.parents('.super-field-wrapper:eq(0)');
2295                var total = $wrapper.children('.super-fileupload').data('total-file-sizes') - $this.parents('div:eq(0)').data('file-size');
2296                $wrapper.children('.super-fileupload').data('total-file-sizes', total);
2297                $wrapper.children('input[type="hidden"]').val('');
2298                $this.parents('div:eq(0)').remove();
2299                var field = $fieldWrapper.find('.super-active-files')[0];
2300                SUPER.after_field_change_blur_hook({el: field, form: form});
2301                removedFields[nodes[i].dataset.oname] = nodes[i];
2302            }
2303            
2304            // Now we can remove the dynamic column
2305            parent.remove();
2306
2307            // @since 4.6.0 - update html field tags attribute
2308            // @since 4.6.0 - update accordion title and description field tags attribute
2309            // @since 4.9.6 - update google maps field tags attribute
2310            // Get all elements based on field tag attribute that contain one of these field names
2311            // Then convert it to an array and append the missing field names
2312            // @IMPORTANT: Only do this for elements that are NOT inside a dynamic column
2313            foundElements = [];
2314            $.each(removedFields, function( index ) {
2315                var html_fields = form.querySelectorAll('[data-tags*="{'+index+'}"], .super-google-map[data-fields*="{'+index+'}"], .super-html-content[data-fields*="{'+index+'}"]');
2316                for (i = 0; i < html_fields.length; ++i) {
2317                    if(!html_fields[i].closest('.super-duplicate-column-fields')){
2318                        found = false;
2319                        for(x=0; x<foundElements.length; x++) {
2320                            if($(foundElements[x]).is(html_fields[i])) found = true;
2321                        }
2322                        if(!found) foundElements.push(html_fields[i]);
2323                    }
2324                }
2325            });
2326
2327            var formId = 0;
2328            if(form.querySelector('input[name="hidden_form_id"]')){
2329                formId = form.querySelector('input[name="hidden_form_id"]').value;
2330            }
2331            for (i = 0; i < foundElements.length; ++i) {
2332                var html = foundElements[i].parentNode.querySelector('textarea').value;
2333                html = SUPER.filter_foreach_statements(foundElements[i], 0, 0, html, undefined, formId, form);
2334                html = SUPER.replaceAll(html, '<%', '{');
2335                html = SUPER.replaceAll(html, '%>', '}');
2336                foundElements[i].innerHTML = html;
2337            }
2338
2339            // @IMPORTANT
2340            // The below hook should come before the field change hook
2341            // This is because it will update the fields attribute on for instance the calculator element
2342            // If this hook is placed below the field change hook it would cause incorrect results
2343            SUPER.after_duplicating_column_hook(form, removedFields);
2344
2345            // Now we need to update the html elements
2346            SUPER.init_replace_html_tags({el: undefined, form: form, foundElements: foundElements});
2347
2348            // Reload google maps
2349            SUPER.google_maps_api.initMaps({form: form});
2350            
2351        });
2352
2353        // Close messages
2354        $doc.on('click', '.super-msg .super-close', function(){
2355            $(this).parents('.super-msg:eq(0)').fadeOut(500);
2356        });
2357
2358        $doc.on('click', '.super-fileupload-button', function(){
2359            SUPER.focusForm(this);
2360            SUPER.focusField(this);
2361            $(this).parents('.super-field-wrapper:eq(0)').find('.super-fileupload').trigger('click');
2362        });
2363        $doc.on('click', '.super-fileupload-delete', function(){
2364            var form = SUPER.get_frontend_or_backend_form({el: this});
2365            var formId = 0;
2366            if(form.querySelector('input[name="hidden_form_id"]')){
2367                formId = form.querySelector('input[name="hidden_form_id"]').value;
2368            }
2369            var $this = $(this);
2370            var $fieldWrapper = $this.parents('.super-field-wrapper:eq(0)');
2371            var $fieldName = $fieldWrapper.find('.super-active-files').attr('name');
2372            var fileNode = $this.parents('div:eq(0)')[0];
2373            // Only browser-pending File objects live in SUPER.files. Existing entry files and
2374            // server-issued receipts are represented by the DOM and must not shift that queue.
2375            if(fileNode && !fileNode.classList.contains('super-uploaded') && !fileNode.hasAttribute('data-upload-token')){
2376                var pendingIndex = 0;
2377                var sibling = fileNode.previousElementSibling;
2378                while(sibling){
2379                    if(!sibling.classList.contains('super-uploaded') && !sibling.hasAttribute('data-upload-token')) pendingIndex++;
2380                    sibling = sibling.previousElementSibling;
2381                }
2382                if(SUPER.files && SUPER.files[formId] && SUPER.files[formId][$fieldName]){
2383                    SUPER.files[formId][$fieldName].splice(pendingIndex, 1);
2384                }
2385            }
2386            var $parent = $this.parents('.super-fileupload-files:eq(0)');
2387            var $wrapper = $parent.parents('.super-field-wrapper:eq(0)');
2388            var total = $wrapper.children('.super-fileupload').data('total-file-sizes') - $this.parents('div:eq(0)').data('file-size');
2389            $wrapper.children('.super-fileupload').data('total-file-sizes', total);
2390            $wrapper.children('input[type="hidden"]').val('');
2391            $this.parents('div:eq(0)').remove();
2392            var field = $fieldWrapper.find('.super-active-files')[0];
2393            SUPER.after_field_change_blur_hook({el: field, form: form});
2394        });
2395        
2396        // @since 1.2.4 - autosuggest text field
2397        // @since 4.4.0 - autosuggest speed improvements
2398        var autosuggestTimeout = null;
2399        $doc.on('keyup', '.super-auto-suggest .super-shortcode-field', function () {
2400            var i,
2401                el = this,
2402                parent = el.closest('.super-field'),
2403                itemsToShow = [],
2404                itemsToHide = [],
2405                value,
2406                text = '',
2407                searchValue,
2408                regex,
2409                stringBold,
2410                wrapper = el.closest('.super-field-wrapper'),
2411                nodes = wrapper.querySelectorAll('.super-dropdown-list .super-item');
2412
2413            if (autosuggestTimeout !== null) clearTimeout(autosuggestTimeout);
2414            autosuggestTimeout = setTimeout(function () {
2415                value = el.value.toString();
2416                if (value === '') {
2417                    parent.classList.remove('super-string-found');
2418                    return false;
2419                }
2420                for (i = 0; i < nodes.length; i++) {
2421                    var stringValue = nodes[i].dataset.searchValue.toString();
2422                    var stringValue_l = stringValue.toLowerCase();
2423                    var isMatch = false;
2424                    if(el.dataset.logic=='start'){
2425                        // Starts with filter logic:
2426                        isMatch = stringValue_l.startsWith(value);
2427                    }else{
2428                        // Contains filter logic:
2429                        isMatch = stringValue_l.indexOf(value) !== -1;
2430                    }
2431                    if( isMatch===true ) {
2432                        itemsToShow.push(nodes[i]);
2433                        regex = RegExp([value].join('|'), 'gi');
2434                        text = stringValue.split(';')[0];
2435                        stringBold = text.replace(regex, '<span>$&</span>');
2436                        stringBold = stringBold.replace(/ /g, '\u00a0');
2437                        nodes[i].innerHTML = stringBold;
2438                    }else{
2439                        itemsToHide.push(nodes[i]);
2440                    }
2441                }
2442                [].forEach.call(itemsToShow, function (el) {
2443                    el.classList.add('super-match');
2444                });
2445                [].forEach.call(itemsToHide, function (el) {
2446                    el.classList.remove('super-match');
2447                });
2448                if (itemsToShow.length>0) {
2449                    parent.classList.add('super-string-found');
2450                    parent.classList.add('super-focus');
2451                } else {
2452                    parent.classList.remove('super-string-found');
2453                }
2454            }, 250);
2455        });
2456
2457        // Focus dropdowns
2458        $doc.on('click', '.super-dropdown-list:not(.super-autosuggest-tags-list)', function(e){
2459            var i, nodes, field = e.target.closest('.super-field');
2460            if(field.classList.contains('super-auto-suggest')) return false;
2461            SUPER.focusForm(field);
2462            if(!field.classList.contains('super-open')){
2463                nodes = document.querySelectorAll('.super-focus');
2464                for(i=0; i<nodes.length; i++){
2465                    nodes[i].classList.remove('super-focus');
2466                    nodes[i].classList.remove('super-open');
2467                }
2468                field.classList.add('super-open');
2469                SUPER.focusField(field);
2470                var searchField = e.target.closest('.super-field-wrapper').querySelector('input[name="super-dropdown-search"]');
2471                if(searchField) searchField.focus();
2472            }else{
2473                if(e.target.classList.contains('super-placeholder')){
2474                    field.classList.remove('super-open');
2475                }
2476            }
2477        });
2478        // Unfocus dropdown
2479        document.addEventListener('click', function(e){
2480            if(e.target.closest('.super-multipart-step')) return true;
2481            var i, nodes;
2482            if(!e.target.closest('.super-form')){
2483                // Timepicker list is outside form element because it is 
2484                // appended dynamically at the bottom of the page
2485                // hence we have to skip it explicitly
2486                if(e.target.closest('.super-timepicker-dialog')){
2487                    return true;
2488                }
2489                // If searching in dropdown, do not close it
2490                if(e.target.closest('.super-dropdown-search')){
2491                    return true;
2492                }
2493
2494                nodes = document.querySelectorAll('.super-form-focussed');
2495                for(i = 0; i < nodes.length; i++){
2496                    nodes[i].classList.remove('super-form-focussed');
2497                    nodes[i].tabIndex = 0;
2498                    SUPER.lastTabKey = undefined;
2499                }
2500                nodes = document.querySelectorAll('.super-focus');
2501                for(i = 0; i < nodes.length; i++){
2502                    if(nodes[i].classList.contains('super-keyword-tags')){
2503                        var f = nodes[i].querySelector('.super-keyword-filter');
2504                        if(f) f.value = ''; // empty value
2505                    }
2506                    nodes[i].classList.remove('super-focus');
2507                    nodes[i].classList.remove('super-open');
2508                }
2509                nodes = document.querySelectorAll('.super-open');
2510                for(i = 0; i < nodes.length; i++){
2511                    nodes[i].classList.remove('super-open');
2512                }
2513                if(e.target.closest('.super-setting')){
2514                    if(e.target.classList.contains('super-dropdown-placeholder')){
2515                        e.target.parentNode.classList.add('super-focus');
2516                        e.target.parentNode.classList.add('super-open');
2517                    }
2518                }
2519            }else{
2520                if(!e.target.closest('.super-dropdown')){
2521                    nodes = document.querySelectorAll('.super-dropdown.super-focus');
2522                    for(i = 0; i < nodes.length; i++){
2523                        nodes[i].classList.remove('super-focus');
2524                        nodes[i].classList.remove('super-open');
2525                    }
2526                    nodes = document.querySelectorAll('.super-dropdown.super-open');
2527                    for(i = 0; i < nodes.length; i++){
2528                        nodes[i].classList.remove('super-open');
2529                    }
2530                    if(e.target.classList.contains('super-shortcode') && !e.target.classList.contains('super-field')){
2531                        SUPER.resetFocussedFields();
2532                    }
2533                }
2534            }
2535        });
2536        
2537        // @since 1.2.8     - filter dropdown options based on keyboard press
2538        var timeout = null;
2539        $doc.on('keyup', 'input[name="super-dropdown-search"]', function(e){
2540            var i, nodes, el = this, stringValue, stringValue_l, words, regex, replacement, dropdownUI, stringBold, value, field, wrapper, found = false, firstFound=null, isMatch, keyCode = e.keyCode || e.which; 
2541            if( (keyCode == 13) || (keyCode == 40) || (keyCode == 38) ) {
2542                return false;
2543            }
2544            if (timeout !== null) clearTimeout(timeout);
2545            timeout = setTimeout(function () {
2546                el.value = '';
2547            }, 1000);
2548
2549            value = el.value.toString().toLowerCase();
2550            field = el.closest('.super-field');
2551            wrapper = el.closest('.super-field-wrapper');
2552            if( value==='' ) {
2553                field.classList.remove('super-string-found');
2554            }else{
2555                nodes = wrapper.querySelectorAll('.super-dropdown-list .super-item:not(.super-placeholder)');
2556                for(i=0; i<nodes.length; i++){
2557                    stringValue = nodes[i].dataset.searchValue.toString();
2558                    stringValue_l = stringValue.toLowerCase();
2559                    if(el.dataset.logic=='start'){
2560                        // Starts with filter logic:
2561                        isMatch = stringValue_l.startsWith(value);
2562                    }else{
2563                        // Contains filter logic:
2564                        isMatch = stringValue_l.indexOf(value) !== -1;
2565                    }
2566                    if( isMatch===true ) {
2567                        if( firstFound===null ) {
2568                            firstFound = nodes[i];
2569                        }
2570                        found = true;
2571                        words = [value]; 
2572                        regex = RegExp(words.join('|'), 'gi');
2573                        replacement = '<span>$&</span>';
2574                        stringBold = nodes[i].dataset.searchValue.replace(regex, replacement);
2575                        stringBold = stringBold.replace(/ /g, '\u00a0');
2576                        nodes[i].innerHTML = stringBold;
2577                        nodes[i].classList.add('super-focus');
2578                    }else{
2579                        nodes[i].innerHTML = stringValue;
2580                        nodes[i].classList.remove('super-focus');
2581                    }
2582                }
2583                if( found===true ) {
2584                    nodes = field.querySelectorAll('.super-dropdown-list .super-item.super-focus');
2585                    for(i=0; i<nodes.length; i++){
2586                        nodes[i].classList.remove('super-focus');
2587                    }
2588                    // If only one found, make it selected option by default
2589                    if(nodes.length===1){
2590                        field.classList.remove('super-string-found');
2591                    }else{
2592                        field.classList.add('super-string-found');
2593                    }
2594                    if(firstFound) firstFound.classList.add('super-focus');
2595                    field.classList.add('super-focus');
2596                    dropdownUI = $(field).find('.super-dropdown-list');
2597                    dropdownUI.scrollTop(dropdownUI.scrollTop() - dropdownUI.offset().top + $(firstFound).offset().top - 50); 
2598                }else{
2599                    // Nothing found, clear timeout
2600                    el.value = '';
2601                    field.classList.remove('super-string-found');
2602                }
2603            }
2604        });
2605
2606        // On choosing item, populate form with data
2607        $doc.on('click', '.super-wc-order-search .super-field-wrapper:not(.super-overlap) .super-dropdown-list .super-item, .super-auto-suggest .super-field-wrapper:not(.super-overlap) .super-dropdown-list .super-item', function(){
2608            var i, items,
2609                wrapper = this.closest('.super-field-wrapper'),
2610                parent = this.parentNode,
2611                field = this.closest('.super-field'),
2612                value = this.innerText,
2613                populate = wrapper.querySelector('.super-shortcode-field').dataset.wcosp;
2614
2615            items = parent.querySelectorAll('.super-item.super-active');
2616            for( i = 0; i < items.length; i++ ) {
2617                items[i].classList.remove('super-active');
2618            }
2619            this.classList.add('super-active');
2620            wrapper.querySelector('.super-shortcode-field').value = value;
2621            field.classList.remove('super-focus');
2622            field.classList.remove('super-open');
2623            field.classList.remove('super-string-found');
2624            wrapper.classList.add('super-overlap');
2625            field.classList.add('super-filled');
2626            SUPER.after_field_change_blur_hook({el: wrapper.querySelector('.super-shortcode-field')});
2627            if(populate=='true'){
2628                SUPER.populate_form_data_ajax({el: field, clear: false});
2629            }
2630        });
2631        // On removing item
2632        $doc.on('click', '.super-wc-order-search .super-field-wrapper.super-overlap li, .super-auto-suggest .super-field-wrapper.super-overlap li', function(){
2633            var i,items,
2634                el = this.closest('.super-field'),
2635                wrapper = this.closest('.super-field-wrapper'),
2636                field = wrapper.querySelector('.super-shortcode-field');
2637            
2638            field.value = '';
2639            items = wrapper.querySelectorAll('.super-active');
2640            for( i = 0; i < items.length; i++ ) {
2641                items[i].classList.remove('super-active');
2642            }
2643            wrapper.classList.remove('super-overlap');
2644            el.classList.remove('super-filled');
2645            field.focus();
2646            SUPER.after_field_change_blur_hook({el: field});
2647        });
2648
2649        // Update dropdown
2650        $doc.on('click', '.super-dropdown .super-dropdown-list .super-item:not(.super-placeholder)', function(e){
2651            SUPER.focusForm(this);
2652            SUPER.focusField(this);
2653            var i, nodes,
2654                form,
2655                field = this.closest('.super-field'),
2656                input,
2657                wrapper,
2658                parent,
2659                placeholder,
2660                value,
2661                name,
2662                validation,
2663                max,
2664                total,
2665                names,
2666                values,
2667                counter;
2668            
2669            e.stopPropagation();
2670            form = SUPER.get_frontend_or_backend_form({el: this});
2671            wrapper = this.closest('.super-field-wrapper');
2672            input = wrapper.querySelector('.super-shortcode-field');
2673            parent = this.closest('.super-dropdown-list');
2674            placeholder = parent.querySelector('.super-placeholder');
2675            if(!parent.classList.contains('multiple')){
2676                value = this.dataset.value;
2677                name = this.innerHTML;
2678                placeholder.innerHTML = name;
2679                placeholder.dataset.value = value;
2680                placeholder.classList.add('super-active');
2681                nodes = parent.querySelectorAll('.super-item');
2682                for ( i = 0; i < nodes.length; i++){
2683                    nodes[i].classList.remove('super-active');
2684                }
2685                this.classList.add('super-active');
2686                if(input) input.value = value;
2687                field.classList.remove('super-open');
2688            }else{
2689                max = (input.dataset.maxlength ? parseInt(input.dataset.maxlength, 10) : 1);
2690                total = parent.querySelectorAll('.super-item.super-active:not(.super-placeholder').length;
2691                if(this.classList.contains('super-active')){
2692                    this.classList.remove('super-active');    
2693                }else{
2694                    if(total >= max) return false;
2695                    this.classList.add('super-active');    
2696                    if(total+1 >= max){
2697                        field.classList.remove('super-open');
2698                    }
2699                }
2700                names = '';
2701                values = '';
2702                nodes = parent.querySelectorAll('.super-item.super-active:not(.super-placeholder');
2703                total = nodes.length;
2704                counter = 1;
2705                for ( i = 0; i < nodes.length; i++){
2706                    if((total == counter) || (total==1)){
2707                        names += nodes[i].innerHTML;
2708                        values += nodes[i].dataset.value;
2709                    }else{
2710                        names += nodes[i].innerHTML+',';
2711                        values += nodes[i].dataset.value+',';
2712                    }
2713                    counter++;
2714                }
2715                placeholder.innerHTML = names;
2716                if(input) input.value = values;
2717            }
2718
2719            // Switch to different language when clicked
2720            if(field.closest('.super-i18n-switcher')){
2721                // Generate new nonce
2722                var $this = $(this), $form = $this.closest('.super-form');
2723                // Remove initialized class
2724                $form.find('.super-button').remove();
2725                $form.removeClass('super-initialized');
2726                $.ajax({ 
2727                    url: super_elements_i18n.ajaxurl, 
2728                    type: 'post', 
2729                    data: { 
2730                        action: 'super_create_nonce'
2731                    },
2732                    success: function (nonce) {
2733                        $form.find('input[name="sf_nonce"]').val(nonce.trim());
2734                    },
2735                    complete: function(){
2736                        var $form_id = $form.find('input[name="hidden_form_id"]').val(),
2737                            $sf_nonce = $form.find('input[name="sf_nonce"]').val(),
2738                            $i18n = $this.attr('data-value');
2739
2740                        $this.parent().children('.super-item').removeClass('super-active');
2741                        $this.addClass('super-active');
2742                        // Also move to placeholder
2743                        $this.parents('.super-dropdown').children('.super-dropdown-placeholder').html($this.html());
2744                        
2745                        // Get URL parameters
2746                        var $queryString = window.location.search;
2747                        var $parameters = SUPER.getAllUrlParams($queryString);
2748                        $.ajax({
2749                            url: super_elements_i18n.ajaxurl,
2750                            type: 'post',
2751                            data: {
2752                                action: 'super_language_switcher',
2753                                form_id: $form_id,
2754                                i18n: $i18n,
2755                                parameters: $parameters,
2756                                sf_nonce: $sf_nonce,
2757                            },
2758                            success: function (result) {
2759                                var data = JSON.parse(result);
2760                                if(data.error && data.error===true){
2761                                    var i, nodes = document.querySelectorAll('.super-msg');
2762                                    for (i = 0; i < nodes.length; i++) { 
2763                                        nodes[i].remove();
2764                                    }
2765                                    var $html = '<div class="super-msg super-error">';                            
2766                                    $html += data.msg;
2767                                    $html += '<span class="super-close"></span>';
2768                                    $html += '</div>';
2769                                    $($html).prependTo($form);
2770                                }else{
2771                                    if(data.rtl==true){
2772                                        $form.addClass('super-rtl');
2773                                    }else{
2774                                        $form.removeClass('super-rtl');
2775                                    }
2776                                    $form.find('form').html(data.html);
2777                                    $form.data('i18n', $i18n);
2778                                }
2779                            },
2780                            complete: function(){
2781                                $form.removeClass('super-initialized');
2782                                $form.removeClass('super-rendered');
2783                                $form.find('.super-multipart-progress').remove();
2784                                $form.find('.super-multipart-steps').remove();
2785                            },
2786                            error: function (xhr, ajaxOptions, thrownError) {
2787                                // eslint-disable-next-line no-console
2788                                console.log(xhr, ajaxOptions, thrownError);
2789                                alert(super_elements_i18n.failed_to_process_data);
2790                            }
2791                        });
2792                    },
2793                    error: function (xhr, ajaxOptions, thrownError) {
2794                        // eslint-disable-next-line no-console
2795                        console.log(xhr, ajaxOptions, thrownError);
2796                        alert('Failed to generate nonce!');
2797                    }
2798                });
2799                return true;
2800            }
2801
2802            if(input && input.value===''){
2803                field.classList.remove('super-filled');
2804            }else{
2805                field.classList.add('super-filled');
2806            }
2807            validation = input.dataset.validation;
2808            if(typeof validation !== 'undefined' && validation !== false){
2809                SUPER.handle_validations({el: input, form: form, validation: validation});
2810            }
2811
2812            SUPER.after_field_change_blur_hook({el: input});
2813        });
2814
2815        $doc.on('click','.super-back-to-top',function(){
2816            var form = SUPER.get_frontend_or_backend_form({el: this});
2817            if(form.closest('.super-popup-content')){
2818                $(form.closest('.super-popup-content')).animate({
2819                    scrollTop: $(form).offset().top-200
2820                }, 1000);
2821            }else{
2822                $('html, body').animate({
2823                    scrollTop: $(form).offset().top-200
2824                }, 1000);
2825            }
2826        });
2827
2828        $doc.on('change', '.super-shortcode-field', function (e) {
2829            if(this.classList.contains('super-fileupload')) return false;
2830            var keyCode = e.keyCode || e.which; 
2831            if (keyCode != 9) { 
2832                var form = SUPER.get_frontend_or_backend_form({el: this}),
2833                    validation = this.dataset.validation,
2834                    conditionalValidation = this.dataset.conditionalValidation;
2835                SUPER.handle_validations({el: this, form: form, validation: validation, conditionalValidation: conditionalValidation});
2836                SUPER.after_field_change_blur_hook({el: this});
2837            }
2838        });
2839
2840        SUPER.simulateRadioItemClicked = function(e, el){
2841            var $form,$this,$parent,$field,$active,$validation;
2842            if( e.target.localName=='a' ) {
2843                if(e.target.target=='_blank'){
2844                    window.open(
2845                      e.target.href,
2846                      '_blank' // <- This is what makes it open in a new window.
2847                    );
2848                }else{
2849                    window.location.href = e.target.href;
2850                }
2851            }else{
2852                $form = SUPER.get_frontend_or_backend_form({el: el});
2853                SUPER.focusNextTabField(e, el, $form, el);
2854                $this = el.querySelector('input[type="radio"]');
2855                if(el.classList.contains('super-active')) return true;
2856                $parent = el.closest('.super-field-wrapper');
2857                $field = $parent.querySelector('.super-shortcode-field');
2858                $active = $parent.querySelector('.super-item.super-active');
2859                if($active){
2860                    $active.classList.remove('super-active');
2861                    $active.classList.remove('super-focus');
2862                }
2863                el.classList.add('super-active');
2864                el.classList.add('super-focus');
2865                el.closest('.super-field').classList.add('super-focus');
2866                $validation = $field.dataset.validation;
2867                $field.value = $this.value;
2868                if(typeof $validation !== 'undefined' && $validation !== false){
2869                    SUPER.handle_validations({el: $field, form: $form, validation: $validation});
2870                }
2871                SUPER.after_field_change_blur_hook({el: $field});
2872            }
2873            return false;
2874        };
2875        $doc.on('click', '.super-form .super-radio > .super-field-wrapper .super-item', function (e) {
2876            return SUPER.simulateRadioItemClicked(e, this);
2877        });
2878
2879        SUPER.simulateCheckboxItemClicked = function(e, el){
2880            var i, 
2881                $form,
2882                $checked,
2883                $value,
2884                $checkbox,
2885                $parent,
2886                $field,
2887                $counter,
2888                $maxlength,
2889                $validation;
2890
2891            if( e.target.localName=='a' ) {
2892                if(e.target.target=='_blank'){
2893                    window.open(
2894                      e.target.href,
2895                      '_blank' // <- This is what makes it open in a new window.
2896                    );
2897                }else{
2898                    window.location.href = e.target.href;
2899                }
2900            }else{
2901                $form = SUPER.get_frontend_or_backend_form({el: el});
2902                SUPER.focusNextTabField(e, el, $form, el);
2903
2904                $checkbox = el.querySelector('input[type="checkbox"]');
2905                $parent = $checkbox.closest('.super-field-wrapper');
2906                $field = $parent.querySelector('input[type="hidden"]');
2907                $counter = 0;
2908                $maxlength = $parent.querySelector('.super-shortcode-field').dataset.maxlength;
2909                $checked = $parent.querySelectorAll('label.super-active');
2910                if(el.classList.contains('super-active')){
2911                    el.classList.remove('super-active');
2912                }else{
2913                    if($checked.length >= parseInt($maxlength, 10)){
2914                        if(parseInt($maxlength,10)===1){
2915                            for (i = 0; i < $checked.length; ++i) {
2916                                $checked[i].classList.remove('super-active');
2917                                $checked[i].querySelector('input').checked = false;
2918                            }
2919                        }else{
2920                            return false;
2921                        }
2922                    }
2923                    el.classList.add('super-active');
2924                }
2925                $checked = $parent.querySelectorAll('label.super-active');
2926                $value = '';
2927                for (i = 0; i < $checked.length; ++i) {
2928                    if ($counter === 0) $value = $checked[i].querySelector('input').value;
2929                    if ($counter !== 0) $value = $value + ',' + $checked[i].querySelector('input').value;
2930                    $counter++;
2931                }
2932                $field.value = $value;
2933                $validation = $field.dataset.validation;
2934                if(typeof $validation !== 'undefined' && $validation !== false){
2935                    SUPER.handle_validations({el: $field, form: $form, validation: $validation});
2936                }
2937                SUPER.after_field_change_blur_hook({el: $field});
2938            }
2939            return false;
2940        };
2941        $doc.on('click', '.super-form .super-checkbox > .super-field-wrapper .super-item', function (e) {
2942            return SUPER.simulateCheckboxItemClicked(e, this);
2943        });
2944
2945        $doc.on('change', '.super-form select', function () {
2946            var $form = SUPER.get_frontend_or_backend_form({el: this}),
2947                $parent = this.closest('.super-field'),
2948                $min = this.dataset.minlength,
2949                $max = this.dataset.maxlength,
2950                $count,
2951                $validation;
2952            if($parent && (typeof this.options !== 'undefined')){
2953                $count = SUPER.selection_value_count(this, $parent);
2954                if(($min>0) && ($count < parseInt($min, 10))){
2955                    SUPER.handle_errors(this);
2956                }else if(($max!=='') && ($count > parseInt($max, 10))){
2957                    SUPER.handle_errors(this);
2958                }else{
2959                    this.closest('.super-field').classList.remove('super-error-active');
2960                }
2961            }else if(($min>0) && (SUPER.unicode_length(this.value) < parseInt($min, 10))){
2962                SUPER.handle_errors(this);
2963            }else if(($max!=='') && (SUPER.unicode_length(this.value) > parseInt($max, 10))){
2964                SUPER.handle_errors(this);
2965            }else{
2966                this.closest('.super-field').classList.remove('super-error-active');
2967            }
2968            $validation = this.dataset.validation;
2969            if(typeof $validation !== 'undefined' && $validation !== false){
2970                SUPER.handle_validations({el: this, form: $form, validation: $validation});
2971            }
2972            SUPER.after_field_change_blur_hook({el: this});
2973        });
2974        
2975        $doc.on('mouseleave','.super-button .super-button-wrap',function(){
2976            this.parentNode.classList.remove('super-focus');
2977            SUPER.init_button_colors( this );
2978        });
2979        $doc.on('mouseover','.super-button .super-button-wrap',function(){
2980            SUPER.init_button_hover_colors( this.parentNode );
2981        });
2982        
2983        // Multi Part Columns
2984        $doc.on('click','.super-multipart-step',function(e){
2985            var i, nodes,
2986                el = this,
2987                form = el.closest('.super-form'),
2988                stepParams = (form.dataset.stepParams ? form.dataset.stepParams : ''), // default
2989                form_id = form.querySelector('input[name="hidden_form_id"]').value,
2990                currentActive = form.querySelector('.super-multipart.super-active'),          
2991                currentActiveTab = form.querySelector('.super-multipart-step.super-active'),
2992                activeChildren = Array.prototype.slice.call( currentActiveTab.parentNode.children ),
2993                activeIndex = activeChildren.indexOf(currentActiveTab),
2994                clickedChildren = Array.prototype.slice.call( el.parentNode.children ),
2995                index = clickedChildren.indexOf(el),
2996                total = form.querySelectorAll('.super-multipart').length,
2997                validate,
2998                result,
2999                progress,
3000                multipart,
3001                skip;
3002
3003            // @since 2.0.0 - validate multi-part before going to next step
3004            if(activeIndex < index){ // Always allow going to previous step
3005                validate = currentActive.dataset.validate;
3006                if(validate=='true'){
3007                    result = SUPER.validate_form({el: el, form: currentActive, submitButton: el, validateMultipart: true, event: e});
3008                    if(result!==true) return false;
3009                }
3010            }
3011            if(stepParams!=='false'){
3012                window.location.hash = 'step-'+form_id+'-'+(parseInt(index,10)+1);
3013            }
3014
3015            progress = 100 / total;
3016            progress = progress * (index+1);
3017            multipart = form.querySelectorAll('.super-multipart')[index];
3018            if(form.querySelector('.super-multipart-progress-bar')){
3019                form.querySelector('.super-multipart-progress-bar').style.width = progress+'%';
3020            }
3021            nodes = form.querySelectorAll('.super-multipart-step');
3022            for ( i = 0; i < nodes.length; i++){
3023                nodes[i].classList.remove('super-active');
3024            }
3025            nodes = form.querySelectorAll('.super-multipart');
3026            for ( i = 0; i < nodes.length; i++){
3027                nodes[i].classList.remove('super-active');
3028            }
3029            multipart.classList.add('super-active');
3030            el.classList.add('super-active');
3031
3032            // @since 3.3.0 - make sure to skip the multi-part if no visible elements are found
3033            skip = SUPER.skipMultipart(el, form, index, activeIndex);
3034            if(skip===true) return false;
3035
3036            // Focus first TAB index field in next multi-part
3037            SUPER.focusFirstTabIndexField(e, form, multipart);
3038
3039            // Update HTML element to reflect changes e.g foreach() and if statements
3040            SUPER.init_replace_html_tags({form: form});
3041
3042            // Required for toggle field and other possible elements to rerender proper size
3043            SUPER.init_super_responsive_form_fields({form: form});
3044        });
3045        
3046        // Multi Part Next Prev Buttons
3047        $doc.on('click','.super-prev-multipart, .super-next-multipart',function(e){
3048            if(this.classList.contains('super-prev-multipart')){
3049                SUPER.switchMultipart(e, this, 'prev');
3050            }else{
3051                SUPER.switchMultipart(e, this, 'next');
3052            }
3053        });
3054
3055        // @since 4.9.3 - Adaptive Placeholders
3056        SUPER.init_adaptive_placeholder();
3057    });
3058
3059
3060    (function () {
3061        "use strict"; // Minimize mutable state :)
3062        // Define all the events for our elements
3063        var app = {};
3064        // querySelector shorthand
3065        app.q = function (s) {
3066            return document.querySelector(s);
3067        };
3068        // querySelectorAll shorthand
3069        app.qa = function (s) {
3070            return document.querySelectorAll(s);
3071        };
3072        // querySelectorAll based on parent shorthand
3073        app.qap = function (s, p) {
3074            // If no parent provided, default to Top element
3075            if (typeof p === 'undefined') p = app.wrapper;
3076            if (typeof p === 'string') p = app.wrapper.querySelector(p);
3077            return p.querySelectorAll(s);
3078        };
3079        // Remove all elements
3080        app.remove = function (e) {
3081            if (typeof e === 'undefined' || !e) return true;
3082            if (e.length) {
3083                for (var i = 0; i < e.length; i++) {
3084                    e[i].remove();
3085                }
3086            } else {
3087                e.remove();
3088            }
3089            return true;
3090        };
3091        // Remove class from elements
3092        app.removeClass = function (elements, class_name) {
3093            if (elements.length === 0) return true;
3094            if (elements.length) {
3095                for (var key = 0; key < elements.length; key++) {
3096                    elements[key].classList.remove(class_name);
3097                }
3098            } else {
3099                elements.classList.remove(class_name);
3100            }
3101        };
3102        // Add class from elements
3103        app.addClass = function (elements, class_name) {
3104            if (elements.length === 0) return true;
3105            if (elements.length) {
3106                for (var key = 0; key < elements.length; key++) {
3107                    elements[key].classList.add(class_name);
3108                }
3109            } else {
3110                elements.classList.add(class_name);
3111            }
3112        };
3113        // Get index of element based on parent node
3114        app.index = function (node, class_name) {
3115            var index = 0;
3116            while (node.previousElementSibling) {
3117                node = node.previousElementSibling;
3118                // Based on specified class name
3119                if (class_name) {
3120                    if (node.classList.contains(class_name)) {
3121                        index++;
3122                    }
3123                } else {
3124                    index++;
3125                }
3126
3127            }
3128            return index;
3129        };
3130        // Check if clicked inside element, by looping over it's "path"
3131        app.inPath = function (e, class_name) {
3132            if (!e.path) return false;
3133            var found = false;
3134            Object.keys(e.path).forEach(function (key) {
3135                if (e.path[key].classList) {
3136                    if (e.path[key].classList.contains(class_name)) {
3137                        found = true;
3138                    }
3139                }
3140            });
3141            return found;
3142        };
3143
3144        // Keyword element functions
3145        app.autosuggestTagsTimeout = null;
3146        app.keywords = {
3147            updateValue: function(field, tagsContainer, keywordField, filterField, wrapper){
3148                var i, values=[], nodes = wrapper.querySelectorAll('.super-autosuggest-tags > span');
3149                for(i=0; i<nodes.length; i++){
3150                    values.push(nodes[i].dataset.value);
3151                }
3152                keywordField.value = values.join(',');
3153                filterField.value = '';
3154                filterField.focus();
3155                if(!app.qap('span', tagsContainer).length){
3156                    field.classList.remove('super-filled');
3157                }else{
3158                    field.classList.add('super-filled');
3159                }
3160                // Scroll to bottom of tags container
3161                tagsContainer.scrollTop = tagsContainer.scrollHeight;
3162                SUPER.after_field_change_blur_hook({el: keywordField});
3163            },
3164            add: function(e, target){
3165                var i,
3166                    html = '',
3167                    field = target.closest('.super-field'),
3168                    value = target.dataset.value, // first_choice
3169                    searchValue = target.dataset.searchValue, // First choice
3170                    wrapper = target.closest('.super-field-wrapper'),
3171                    keywordField = wrapper.querySelector('.super-shortcode-field'),
3172                    tagsContainer = wrapper.querySelector('.super-autosuggest-tags'),
3173                    tags = tagsContainer.querySelectorAll('.super-keyword-tag'),
3174                    filterField = wrapper.querySelector('.super-keyword-filter'),
3175                    maxlength = parseInt(keywordField.dataset.maxlength, 10),
3176                    existingTags = [];
3177
3178                // Check if limit is reached
3179                if( maxlength!==0 && tags.length>=maxlength ) {
3180                    field.classList.add('super-filled');
3181                    field.classList.remove('super-string-found');
3182                    field.classList.add('super-focus');
3183                    app.keywords.updateValue(field, tagsContainer, keywordField, filterField, wrapper);
3184                    return false; 
3185                }
3186                // Loop over allready existing tags and add their value to an array
3187                for(i=0; i < tags.length; i++){
3188                    existingTags.push(tags[i].dataset.value);
3189                }
3190                // if this tag doesn't exists yet
3191                if(existingTags.indexOf(value)===-1){
3192                    var node = document.createElement('span');
3193                    node.className = 'super-noselect super-keyword-tag';
3194                    node.setAttribute('sfevents', '{"click":"keywords.remove"}');
3195                    node.dataset.value = value;
3196                    node.title = 'remove this tag';
3197                    node.innerHTML = searchValue;
3198                    filterField.parentNode.insertBefore(node, filterField.nextElementSibling);
3199                    target.classList.add('super-active');
3200                }
3201                if(!app.qap('span', tagsContainer).length){
3202                    field.classList.remove('super-filled');
3203                }else{
3204                    field.classList.add('super-filled');
3205                }
3206                field.classList.remove('super-string-found');
3207                field.classList.add('super-focus');
3208                app.keywords.updateValue(field, tagsContainer, keywordField, filterField, wrapper);
3209            },
3210            remove: function(e, target){
3211                var wrapper = target.closest('.super-field-wrapper'),
3212                    keywordField = wrapper.querySelector('.super-shortcode-field'),
3213                    filterField = wrapper.querySelector('.super-keyword-filter'),
3214                    field = target.closest('.super-field'),
3215                    tagsContainer = wrapper.querySelector('.super-autosuggest-tags');
3216
3217                target.remove();
3218                filterField.focus();
3219                app.keywords.updateValue(field, tagsContainer, keywordField, filterField, wrapper);
3220            },
3221            filter: function(e, target){
3222                // On keyup filter any keyword tags from the list
3223                var i,
3224                    parent = target.closest('.super-field'),
3225                    counter = 0,
3226                    html = '',
3227                    tag, tags,
3228                    duplicates = {},
3229                    method = target.dataset.method,
3230                    splitMethod = target.dataset.splitMethod,
3231                    itemsToShow = [],
3232                    itemsToHide = [],
3233                    value,
3234                    text = '',
3235                    searchValue,
3236                    regex,
3237                    stringBold,
3238                    wrapper = target.closest('.super-field-wrapper'),
3239                    field = target.closest('.super-field'),
3240                    tagsContainer = wrapper.querySelector('.super-autosuggest-tags'),
3241                    keywordField = wrapper.querySelector('.super-shortcode-field'),
3242                    filterField = wrapper.querySelector('.super-keyword-filter'),
3243                    max = (keywordField.dataset.maxlength ? parseInt(keywordField.dataset.maxlength, 10) : 0),
3244                    nodes = wrapper.querySelectorAll('.super-dropdown-list .super-item');
3245
3246                if(method=='free'){
3247                    if(splitMethod=='both') tags = target.value.split(/[ ,]+/);
3248                    if(splitMethod=='comma') tags = target.value.split(/[,]+/);
3249                    if(splitMethod=='space') tags = target.value.split(/[ ]+/);
3250                    if(tags.length>1){
3251                        tag = tags[0];
3252                        // First check if already exists
3253                        if(keywordField.value.split(',').indexOf(tag)===-1){
3254                            if(typeof duplicates[tag]==='undefined'){
3255                                counter = tagsContainer.querySelectorAll('.super-keyword-tag').length;
3256                                if(max===0 || counter<max){
3257                                    if(splitMethod!='comma') tag = tag.replace(/ /g,'');
3258                                    if( (tag!=='') && (tag.length>1) ) {
3259                                        var node = document.createElement('span');
3260                                        node.className = 'super-noselect super-keyword-tag';
3261                                        node.setAttribute('sfevents', '{"click":"keywords.remove"}');
3262                                        node.dataset.value = tag;
3263                                        node.innerHTML = tag;
3264                                        filterField.parentNode.insertBefore(node, filterField);
3265                                        target.classList.add('super-active');
3266                                    }
3267                                }
3268                            }
3269                            duplicates[tag] = tag;
3270                        }
3271                        app.keywords.updateValue(field, tagsContainer, keywordField, target, wrapper);
3272                    }
3273                }else{
3274                    if (app.autosuggestTagsTimeout !== null) clearTimeout(app.autosuggestTagsTimeout);
3275                    app.autosuggestTagsTimeout = setTimeout(function () {
3276                        value = target.value.toString().toLowerCase();
3277                        if (value === '') {
3278                            parent.classList.remove('super-string-found');
3279                            parent.classList.remove('super-no-match');
3280                            return false;
3281                        }
3282                        for (i = 0; i < nodes.length; i++) {
3283                            var stringValue = nodes[i].dataset.searchValue.toString();
3284                            var stringValue_l = stringValue.toLowerCase();
3285                            var isMatch = false;
3286                            if(keywordField.dataset.logic=='start'){
3287                                // Starts with filter logic:
3288                                isMatch = stringValue_l.startsWith(value);
3289                            }else{
3290                                // Contains filter logic:
3291                                isMatch = stringValue_l.indexOf(value) !== -1;
3292                            }
3293                            if( isMatch===true ) {
3294                                itemsToShow.push(nodes[i]);
3295                                regex = RegExp([value].join('|'), 'gi');
3296                                text = stringValue.split(';')[0];
3297                                stringBold = '<span class="super-wp-tag">'+text.replace(regex, '<span>$&</span>')+'</span>';
3298                                stringBold = stringBold.replace(/\r?\n|\r/g, "");
3299                                nodes[i].innerHTML = stringBold;
3300                            }else{
3301                                itemsToHide.push(nodes[i]);
3302                            }
3303                        }
3304                        [].forEach.call(itemsToShow, function (el) {
3305                            el.style.display = 'inline-block';
3306                            el.classList.add('super-active');
3307                        });
3308                        [].forEach.call(itemsToHide, function (el) {
3309                            el.style.display = 'none';
3310                            el.classList.remove('super-active');
3311                        });
3312                        if (itemsToShow.length>0) {
3313                            parent.classList.add('super-string-found');
3314                            parent.classList.add('super-focus');
3315                            parent.classList.remove('super-no-match');
3316                        } else {
3317                            parent.classList.remove('super-string-found');
3318                            parent.classList.add('super-no-match');
3319                        }
3320                    }, 250);
3321                }
3322            }
3323        }
3324
3325        // Trigger Events
3326        app.triggerEvent = function (e, target, eventType) {
3327            // Get element actions, and check for multiple event methods
3328            var actions, _event, _function, _currentFunc, sfevents;
3329            try {
3330                sfevents = JSON.parse(target.attributes.sfevents.value);
3331            } catch (error) {
3332                // eslint-disable-next-line no-console
3333                console.log(error);
3334                alert(error);
3335            }
3336            Object.keys(sfevents).forEach(function (key) {
3337                // Check if contains comma, meaning it has multiple event methods for this function
3338                _event = key.split(',');
3339                if (_event.length > 1) {
3340                    // Seems it contains multiple events, so let's split them up and create a new sfevents object
3341                    Object.keys(_event).forEach(function (e_key) {
3342                        sfevents[_event[e_key]] = sfevents[key];
3343                    });
3344                    delete sfevents[key];
3345                }
3346            });
3347            actions = sfevents[eventType];
3348            if (actions) {
3349                if(typeof actions === 'string'){
3350                    _currentFunc = app;
3351                    if(actions.split('.').length>1){
3352                        _function = actions.split('.');
3353                        for (var i = 0; i < _function.length; i++) {
3354                            // Skip if function name is 'app'
3355                            if (_function[i] == 'app') continue;
3356                            if (_currentFunc[_function[i]]) {
3357                                _currentFunc = _currentFunc[_function[i]];
3358                            } else {
3359                                // eslint-disable-next-line no-console
3360                                console.log('Function ' + actions + '() is undefined!');
3361                                break;
3362                            }
3363                        }
3364                        _currentFunc(e, target, eventType, actions);
3365                    }else{
3366                        if (_currentFunc[actions]) {
3367                            _currentFunc = _currentFunc[actions];
3368                            _currentFunc(e, target, eventType, actions);
3369                        } else {
3370                            // eslint-disable-next-line no-console
3371                            console.log('Function ' + actions + '() is undefined!');
3372                        }
3373                    }
3374                }else{
3375                    Object.keys(actions).forEach(function (key) { // key = function name
3376                        _currentFunc = app;
3377                        _function = key.split('.');
3378                        for (var i = 0; i < _function.length; i++) {
3379                            // Skip if function name is 'app'
3380                            if (_function[i] == 'app') continue;
3381                            if (_currentFunc[_function[i]]) {
3382                                _currentFunc = _currentFunc[_function[i]];
3383                            } else {
3384                                // eslint-disable-next-line no-console
3385                                console.log('Function ' + key + '() is undefined!');
3386                                break;
3387                            }
3388                        }
3389                        _currentFunc(e, target, eventType, actions[key]);
3390                    });
3391                }
3392            }
3393        };
3394        // Equivalent for jQuery's .on() function
3395        app.delegate = function (element, event, elements, callback) {
3396            element.addEventListener(event, function (event) {
3397                var target = event.target;
3398                while (target && target !== this) {
3399                    if (target.matches(elements)) {
3400                        callback(event, target);
3401                        return false;
3402                    }
3403                    target = target.parentNode;
3404                }
3405            });
3406        };
3407        // Iterate over all events, and listen to any event being triggered
3408        app.events = {
3409            click: [
3410                'body',
3411                '.super-keyword-filter',
3412                '.super-keyword-tags .super-item',
3413                '.super-keyword-tag'
3414            ],
3415            mousedown: [
3416                '.super-keyword-filter'
3417            ],
3418            onblur: [
3419                '.super-keyword-filter'
3420            ],
3421            keyup: [
3422                '.super-keyword-filter'
3423            ],
3424            keydown: [
3425                '.super-keyword-filter'
3426            ]
3427        };
3428        Object.keys(app.events).forEach(function (eventType) {
3429            var elements = app.events[eventType].join(", ");
3430            app.delegate(document, eventType, elements, function (e, target) {
3431                // Trigger event(s)
3432                if (typeof target.attributes.sfevents !== 'undefined') app.triggerEvent(e, target, eventType);
3433            });
3434        });
3435    })(jQuery);
3436})(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.