PageSourceSearch

https://laundrybutler.com.sg/wp-content/plugins/super-forms/assets/js/common.js?ver=6.1.4

js laundrybutler.com.sg collected 2026-10-02 01:09:45 UTC 438,655 bytes, 8,356 lines download raw bytes

vendor: 4,071 bytes, lines 1-7
1/* globals jQuery, SUPER, grecaptcha, super_common_i18n, ajaxurl, IBAN, tinyMCE, google, quicktags */
2"use strict";
3
4// polyfill remove() ie9 and above
5(function (arr) { arr.forEach(function (item) { if (item.hasOwnProperty('remove')) { return; } Object.defineProperty(item, 'remove', { configurable: true, enumerable: true, writable: true, value: function remove() { this.parentNode.removeChild(this); } }); }); })([Element.prototype, CharacterData.prototype, DocumentType.prototype]);
6// polyfill es6 promises (auto)
7!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.ES6Promise=e()}(this,function(){"use strict";function t(t){var e=typeof t;return null!==t&&("object"===e||"function"===e)}function e(t){return"function"==typeof t}function n(t){W=t}function r(t){z=t}function o(){return function(){return process.nextTick(a)}}function i(){return"undefined"!=typeof U?function(){U(a)}:c()}function s(){var t=0,e=new H(a),n=document.createTextNode("");return e.observe(n,{characterData:!0}),function(){n.data=t=++t%2}}function u(){var t=new MessageChannel;return t.port1.onmessage=a,function(){return t.port2.postMessage(0)}}function c(){var t=setTimeout;return function(){return t(a,1)}}function a(){for(var t=0;t<N;t+=2){var e=Q[t],n=Q[t+1];e(n),Q[t]=void 0,Q[t+1]=void 0}N=0}function f(){try{var t=Function("return this")().require("vertx");return U=t.runOnLoop||t.runOnContext,i()}catch(e){return c()}}function l(t,e){var n=this,r=new this.constructor(p);void 0===r[V]&&x(r);var o=n._state;if(o){var i=arguments[o-1];z(function(){return T(o,r,i,n._result)})}else j(n,r,t,e);return r}function h(t){var e=this;if(t&&"object"==typeof t&&t.constructor===e)return t;var n=new e(p);return w(n,t),n}function p(){}function v(){return new TypeError("You cannot resolve a promise with itself")}function d(){return new TypeError("A promises callback cannot return that same promise.")}function _(t,e,n,r){try{t.call(e,n,r)}catch(o){return o}}function y(t,e,n){z(function(t){var r=!1,o=_(n,e,function(n){r||(r=!0,e!==n?w(t,n):A(t,n))},function(e){r||(r=!0,S(t,e))},"Settle: "+(t._label||" unknown promise"));!r&&o&&(r=!0,S(t,o))},t)}function m(t,e){e._state===Z?A(t,e._result):e._state===$?S(t,e._result):j(e,void 0,function(e){return w(t,e)},function(e){return S(t,e)})}function b(t,n,r){n.constructor===t.constructor&&r===l&&n.constructor.resolve===h?m(t,n):void 0===r?A(t,n):e(r)?y(t,n,r):A(t,n)}function w(e,n){if(e===n)S(e,v());else if(t(n)){var r=void 0;try{r=n.then}catch(o){return void S(e,o)}b(e,n,r)}else A(e,n)}function g(t){t._onerror&&t._onerror(t._result),E(t)}function A(t,e){t._state===X&&(t._result=e,t._state=Z,0!==t._subscribers.length&&z(E,t))}function S(t,e){t._state===X&&(t._state=$,t._result=e,z(g,t))}function j(t,e,n,r){var o=t._subscribers,i=o.length;t._onerror=null,o[i]=e,o[i+Z]=n,o[i+$]=r,0===i&&t._state&&z(E,t)}function E(t){var e=t._subscribers,n=t._state;if(0!==e.length){for(var r=void 0,o=void 0,i=t._result,s=0;s<e.length;s+=3)r=e[s],o=e[s+n],r?T(n,r,o,i):o(i);t._subscribers.length=0}}function T(t,n,r,o){var i=e(r),s=void 0,u=void 0,c=!0;if(i){try{s=r(o)}catch(a){c=!1,u=a}if(n===s)return void S(n,d())}else s=o;n._state!==X||(i&&c?w(n,s):c===!1?S(n,u):t===Z?A(n,s):t===$&&S(n,s))}function M(t,e){try{e(function(e){w(t,e)},function(e){S(t,e)})}catch(n){S(t,n)}}function P(){return tt++}function x(t){t[V]=tt++,t._state=void 0,t._result=void 0,t._subscribers=[]}function C(){return new Error("Array Methods must be provided an Array")}function O(t){return new et(this,t).promise}function k(t){var e=this;return new e(L(t)?function(n,r){for(var o=t.length,i=0;i<o;i++)e.resolve(t[i]).then(n,r)}:function(t,e){return e(new TypeError("You must pass an array to race."))})}function F(t){var e=this,n=new e(p);return S(n,t),n}function Y(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function q(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object c
7onstructor cannot be called as a function.")}function D(){var t=void 0;if("undefined"!=typeof global)t=global;else if("undefined"!=typeof self)t=self;else try{t=Function("return this")()}catch(e){throw new Error("polyfill failed because global object is unavailable in this environment")}var n=t.Promise;if(n){var r=null;try{r=Object.prototype.toString.call(n.resolve())}catch(e){}if("[object Promise]"===r&&!n.cast)return}t.Promise=nt}var K=void 0;K=Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)};var L=K,N=0,U=void 0,W=void 0,z=function(t,e){Q[N]=t,Q[N+1]=e,N+=2,2===N&&(W?W(a):R())},B="undefined"!=typeof window?window:void 0,G=B||{},H=G.MutationObserver||G.WebKitMutationObserver,I="undefined"==typeof self&&"undefined"!=typeof process&&"[object process]"==={}.toString.call(process),J="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,Q=new Array(1e3),R=void 0;R=I?o():H?s():J?u():void 0===B&&"function"==typeof require?f():c();var V=Math.random().toString(36).substring(2),X=void 0,Z=1,$=2,tt=0,et=function(){function t(t,e){this._instanceConstructor=t,this.promise=new t(p),this.promise[V]||x(this.promise),L(e)?(this.length=e.length,this._remaining=e.length,this._result=new Array(this.length),0===this.length?A(this.promise,this._result):(this.length=this.length||0,this._enumerate(e),0===this._remaining&&A(this.promise,this._result))):S(this.promise,C())}return t.prototype._enumerate=function(t){for(var e=0;this._state===X&&e<t.length;e++)this._eachEntry(t[e],e)},t.prototype._eachEntry=function(t,e){var n=this._instanceConstructor,r=n.resolve;if(r===h){var o=void 0,i=void 0,s=!1;try{o=t.then}catch(u){s=!0,i=u}if(o===l&&t._state!==X)this._settledAt(t._state,e,t._result);else if("function"!=typeof o)this._remaining--,this._result[e]=t;else if(n===nt){var c=new n(p);s?S(c,i):b(c,t,o),this._willSettleAt(c,e)}else this._willSettleAt(new n(function(e){return e(t)}),e)}else this._willSettleAt(r(t),e)},t.prototype._settledAt=function(t,e,n){var r=this.promise;r._state===X&&(this._remaining--,t===$?S(r,n):this._result[e]=n),0===this._remaining&&A(r,this._result)},t.prototype._willSettleAt=function(t,e){var n=this;j(t,void 0,function(t){return n._settledAt(Z,e,t)},function(t){return n._settledAt($,e,t)})},t}(),nt=function(){function t(e){this[V]=P(),this._result=this._state=void 0,this._subscribers=[],p!==e&&("function"!=typeof e&&Y(),this instanceof t?M(this,e):q())}return t.prototype["catch"]=function(t){return this.then(null,t)},t.prototype["finally"]=function(t){var n=this,r=n.constructor;return e(t)?n.then(function(e){return r.resolve(t()).then(function(){return e})},function(e){return r.resolve(t()).then(function(){throw e})}):n.then(t,t)},t}();return nt.prototype.then=l,nt.all=O,nt.race=k,nt.resolve=h,nt.reject=F,nt._setScheduler=n,nt._setAsap=r,nt._asap=z,nt.polyfill=D,nt.Promise=nt,nt.polyfill(),nt});
8
9// polyfill for 'closest()' to support IE9+
10// reference: https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
11if (!Element.prototype.matches) {
12  Element.prototype.matches = Element.prototype.msMatchesSelector || 
13                              Element.prototype.webkitMatchesSelector;
14}
15if (!Element.prototype.closest) {
16  Element.prototype.closest = function(s) {
17    var el = this;
18
19    do {
20      if (el.matches(s)) return el;
21      el = el.parentElement || el.parentNode;
22    } while (el !== null && el.nodeType === 1);
23    return null;
24  };
25}
26
27window.SUPER = {};
28SUPER.files = [];
29
30// reCaptcha
31SUPER.reCaptchaScriptLoaded = false;
32SUPER.reCaptchaverifyCallback = function($response, $version, $element){
33    // Set data attribute on recaptcha containing response so we can verify this upon form submission
34    $element.attr('data-response', $response);
35};
36SUPER.add_error_status_parent_layout_element = function($, el){
37    var index;
38    // Add error class to Multi-part
39    index = $(el).parents('.super-multipart:eq(0)').index('.super-form form .super-multipart');
40    if(el.closest('.super-form') && el.closest('.super-form').querySelectorAll('.super-multipart-step')[index]){
41        el.closest('.super-form').querySelectorAll('.super-multipart-step')[index].classList.add('super-error');
42    }
43    // Add error class to TABS
44    if(el.closest('.super-tabs')){
45        index = $(el.closest('.super-tabs-content')).index();
46        if(el.closest('.super-tabs').querySelectorAll('.super-tabs-tab')[index]){
47            el.closest('.super-tabs').querySelectorAll('.super-tabs-tab')[index].classList.add('super-error');
48        }
49    }
50    // Add error class to Accordion
51    if(el.closest('.super-accordion-item')){
52        el.closest('.super-accordion-item').classList.add('super-error');
53    }
54};
55SUPER.remove_error_status_parent_layout_element = function($, el){
56    var index;
57    if( el.closest('.super-multipart') && !el.closest('.super-multipart').querySelector('.super-error-active')){
58        index = $(el).parents('.super-multipart:eq(0)').index('.super-form form .super-multipart');
59        if(el.closest('.super-form') && el.closest('.super-form').querySelectorAll('.super-multipart-step')[index]){
60            el.closest('.super-form').querySelectorAll('.super-multipart-step')[index].classList.remove('super-error');
61        }
62    }
63    // Remove error class from TABS
64    if( el.closest('.super-tabs-content') && !el.closest('.super-tabs-content').querySelector('.super-error-active')){
65        index = $(el.closest('.super-tabs-content')).index();
66        if(el.closest('.super-tabs') && el.closest('.super-tabs').querySelectorAll('.super-tabs-tab')[index]){
67            el.closest('.super-tabs').querySelectorAll('.super-tabs-tab')[index].classList.remove('super-error');
68        }
69    }
70    // Remove error class from Accordion if no more errors where found
71    if( el.closest('.super-accordion-item') && !el.closest('.super-accordion-item').querySelector('.super-error-active')){
72        el.closest('.super-accordion-item').classList.remove('super-error');
73    }
74};
75function SUPERreCaptchaRender(){
76    var $ = jQuery;
77    $('.super-shortcode.super-field.super-recaptcha:not(.super-rendered)').each(function(){
78        var $this = $(this);
79        var $element = $this.find('.super-recaptcha');
80        var $form = $this.closest('.super-form');
81        var $form_id = $form.find('input[name="hidden_form_id"]').val();
82        $element.attr('data-form',$form_id);
83        $element.attr('id','super-recaptcha-'+$form_id);
84        if($form.length===0){
85            $this.html('<i>reCAPTCHA will only be generated and visible in the Preview or Front-end</i>');  
86        }
87        if($this.data('sitekey')===''){
88            $this.html('<i>reCAPTCHA API key and secret are empty, please navigate to:<br />Super Forms > Settings > Form Settings and fill out your reCAPTCHA API key and secret</i>');  
89        }else{
90            if(typeof $form_id !== 'undefined'){
91                var checkExist = setInterval(function() {
92                    if( (typeof grecaptcha !== 'undefined') && (typeof grecaptcha.render !== 'undefined') ) {
93                        clearInterval(checkExist);
94                        $this.addClass('super-rendered');
95                        try {
96                            grecaptcha.render('super-recaptcha-'+$form_id, {
97                                sitekey : $element.data('sitekey'),
98                                theme : 'light',
99                                callback : function(token) {
100                                    SUPER.reCaptchaverifyCallback(token, 'v2', $element);
101                                }
102                            });
103                        }
104                        catch(error) {
105                            // continue regardless of error
106                        }
107                    }
108                }, 100);
109            }
110        }
111    });
112}
113function SUPERreCaptcha(){
114    var $ = jQuery;
115    // Load recaptcha api manually if theme uses ajax requests
116    if($('.super-shortcode.super-field.super-recaptcha:not(.super-rendered)').length){
117        if( (typeof grecaptcha === 'undefined') || (typeof grecaptcha.render === 'undefined') ) {
118            if(!SUPER.reCaptchaScriptLoaded){
119                $.getScript( 'https://www.google.com/recaptcha/api.js?onload=SUPERreCaptcha&render=explicit', function() {
120                    SUPER.reCaptchaScriptLoaded = true;
121                    SUPERreCaptchaRender();
122                });
123            }
124        }else{
125            if(!SUPER.reCaptchaScriptLoaded){
126                SUPER.reCaptchaScriptLoaded = true;
127                SUPERreCaptchaRender();
128            }
129        }
130    }
131}
132
133(function($) {
134
135    if(typeof super_common_i18n.ajaxurl === 'undefined'){
136        super_common_i18n.ajaxurl = ajaxurl;
137    }
138
139    SUPER.debug_time = function($name){
140        // eslint-disable-next-line no-console
141        console.time($name);
142    };
143    SUPER.debug_time_end = function($name){
144        // eslint-disable-next-line no-console
145        console.timeEnd($name);
146    };
147    SUPER.debug = function($log){
148        // eslint-disable-next-line no-console
149        console.log($log);
150    };
151
152    // Submit the form
153    SUPER.complete_submit = function(args){
154        // If form has g-recaptcha element
155        if(($(args.form).find('.g-recaptcha').length!=0) && (typeof grecaptcha !== 'undefined')) {
156            grecaptcha.ready(function(){
157                grecaptcha.execute($(args.form).find('.g-recaptcha .super-recaptcha').attr('data-sitekey'), {action: 'super_form_submit'}).then(function(token){
158                    args.token = token;
159                    SUPER.create_ajax_request(args);
160                });
161            });
162        }else{
163            SUPER.create_ajax_request(args);
164        }
165    };
166    // Send form submission through ajax request
167    SUPER.create_ajax_request = function(args){
168        var json_data;
169        args.form = $(args.form);
170        args.form0 = args.form[0];
171        args.showOverlay = args.form0.dataset.overlay;
172        // already defined: args.form_id
173        // already defined: args.entry_id
174        // already defined: args.list_id
175
176        // @since 1.3
177        args.data = SUPER.after_form_data_collected_hook(args.data);
178
179        // @since 3.2.0 - honeypot captcha check, if value is not empty cancel form submission
180        args.data.super_hp = args.form.find('input[name="super_hp"]').val();
181        if(args.data.super_hp!==''){
182            return false;
183        }
184
185        // @since 2.9.0 - json data POST
186        json_data = JSON.stringify(args.data);
187        args.form.find('textarea[name="json_data"]').val(json_data);
188
189        if(typeof args.token === 'undefined'){
190            if(args.form.find('.super-recaptcha:not(.g-recaptcha)').length!==0){
191                args.version = 'v2';
192                args.token = args.form.find('.super-recaptcha:not(.g-recaptcha) .super-recaptcha').attr('data-response');
193            }
194        }else{
195            args.version = 'v3';
196        }
197        // Create loader overlay
198        args = SUPER.createLoadingOverlay(args);
199        args.callback = function(){
200            SUPER.submit_form(args);
201        };
202        SUPER.before_email_send_hook(args);
203    };
204    SUPER.createLoadingOverlay = function(args){
205        args.loadingOverlay = document.createElement('div');
206        var html = '';
207        html += '<div class="super-loading-wrapper">';
208            html += '<div class="super-close"></div>';
209            html += '<div class="super-loading-text">';
210                html += '<div class="super-custom-el1"></div>';
211                html += '<div class="super-inner-text"></div>';
212                html += '<div class="super-progress">';
213                    html += '<div class="super-progress-bar"></div>';
214                html += '</div>';
215                html += '<div class="super-custom-el2"></div>';
216            html += '</div>';
217        html += '</div>';
218        args.loadingOverlay.innerHTML = html;
219        args.loadingOverlay.classList.add('super-loading-overlay');
220        args.loadingOverlay.querySelector('.super-inner-text').innerHTML = '<span>'+super_common_i18n.loadingOverlay.processing+'</span>';
221        args.loadingOverlay.querySelector('.super-close').innerHTML = '<span>'+super_common_i18n.loadingOverlay.close+'</span>';
222        if(args.showOverlay==="true"){
223            document.body.appendChild(args.loadingOverlay);
224        }
225        // Close modal (should also reset pdf generation)
226        var closeBtn = args.loadingOverlay.querySelector('.super-close');
227        if(closeBtn){
228            closeBtn.addEventListener('click', function(){
229                // Close overlay
230                SUPER.close_loading_overlay(args.loadingOverlay);
231            });
232        }
233        args.progressBar = document.querySelector('.super-loading-overlay .super-progress-bar');
234        return args;
235    };
236    SUPER.submit_form = function(args){
237        var total = 0;
238        args.files = SUPER.files[args.form_id];
239        if(args.files){
240            Object.keys(args.files).forEach(function() {
241                total++;
242                return true;
243            });
244        }
245        if(total>0){
246            args.loadingOverlay.querySelector('.super-inner-text').innerHTML = '<span>'+super_common_i18n.loadingOverlay.uploading_files+'</span>';
247            SUPER.upload_files(args, function(args){
248                SUPER.process_form_data(args);
249            });
250        }else{
251            SUPER.process_form_data(args);
252        }
253    };
254    SUPER.get_file_name_and_extension = function(fileName){
255        var m, n, e, regex = /(^.*)\.([^.]+)$/;
256        if ((m = regex.exec(fileName)) !== null) {
257            n = (m[1] ? m[1] : '');
258            e = (m[2] ? m[2] : '');
259        }
260        return {name: n, ext: e};
261    };
262    SUPER.get_single_uploaded_file_html = function(withoutHeader, uploaded, fileName, fileType, fileUrl){
263        var html = '', classes = '';
264        if(uploaded) classes = ' class="super-uploaded"';
265        if(withoutHeader) {
266            // We do not want a header
267        }else{
268            html += '<div data-name="'+fileName+'" title="'+fileName+'" data-type="'+fileType+'"'+classes+'" data-url="'+fileUrl+'">';
269        }
270        if(fileType && fileType.indexOf("image/") === 0){
271            html += '<span class="super-fileupload-image super-file-type-'+fileType.replace('/','-')+'">';
272                html += '<img src="'+fileUrl+'" />';
273            html += '</span>';
274        }else{
275            html += '<span class="super-fileupload-document super-file-type-'+fileType.replace('/','-')+'"></span>';
276        }
277        html += '<span class="super-fileupload-info">';
278            // Truncate file if it's too long
279            var f = SUPER.get_file_name_and_extension(fileName);
280            if(uploaded){
281                html += '<a href="'+fileUrl+'" target="_blank">'+f.name+'.'+f.ext+'</a>';
282            }else{
283                html += '<span class="super-fileupload-name">'+f.name+'.'+f.ext+'</span>';
284                html += '<span class="super-fileupload-delete"></span>';
285            }
286        html += '</span>';
287        if(withoutHeader) {
288            // We do not want a header
289        }else{
290            html += '</div>';
291        }
292        return html;
293    };
294    // Upload files
295    SUPER.upload_files = function(args, callback){
296        args._process_form_data_callback = callback;
297        args.formData = new FormData();
298        var x = 0, y = 0;
299        Object.keys(args.files).forEach(function(key) {
300            for( y = 0; y < args.files[key].length; y++){
301                x++;
302                args.formData.append('files['+key+']['+y+']', args.files[key][y]); // holds: file, src, name, size, type
303            }
304        });
305        if(x===0){
306            // Now process form data
307            args._process_form_data_callback(args);
308            return true;
309        }
310        args.formData.append('action', 'super_upload_files');
311        if(args.form_id) args.formData.append('form_id', args.form_id);
312        if(args.entry_id) args.formData.append('entry_id', args.entry_id);
313        if(args.list_id) args.formData.append('list_id', args.list_id);
314        if(args.sf_nonce) args.formData.append('sf_nonce', args.sf_nonce);
315        $.ajax({
316            type: 'post',
317            url: super_common_i18n.ajaxurl,
318            data: args.formData,
319            async: true,
320            cache: false,
321            contentType: false,
322            processData: false,
323            timeout: 60000, // 1m
324            xhr: function() {
325                var xhr = new window.XMLHttpRequest();
326                if(args.showOverlay==="true"){
327                    xhr.upload.addEventListener("progress", function(evt) {
328                        if (evt.lengthComputable) {
329                            var percentComplete = evt.loaded / evt.total;
330                            //Do something with upload progress here
331                            if(args.progressBar) args.progressBar.style.width = (100*percentComplete)+"%";  
332                        }
333                    }, false);
334                }
335                return xhr;
336            },
337            success: function(result){
338                result = JSON.parse(result);
339                if(result.error===true){
340                    // Display error message
341                    SUPER.form_submission_finished(args, result);
342                }else{
343                    var i, uploadedFiles, updateHtml=[], html=[], activeFiles, fieldWrapper, filesWrapper, field, file, files = result;
344                    Object.keys(files).forEach(function(fieldName) {
345                        activeFiles = args.form0.querySelector('.super-active-files[name="'+fieldName+'"]');
346                        if(!activeFiles) return true; // continue to next field
347                        fieldWrapper = activeFiles.closest('.super-field-wrapper');
348                        if(!fieldWrapper) return true; // continue to next field
349                        filesWrapper = fieldWrapper.querySelector('.super-fileupload-files');
350                        if(!filesWrapper) return true; // continue to next field
351                        uploadedFiles = filesWrapper.querySelectorAll('.super-uploaded');
352                        updateHtml[fieldName] = {
353                            filesWrapper: filesWrapper,
354                            html: ''
355                        }
356                        for(i=0; i<uploadedFiles.length; i++){
357                            updateHtml[fieldName].html += uploadedFiles[i].outerHTML;
358                        }
359                    });
360                    // Loop over files and update src for each image
361                    // We do not have to do this for other file types
362                    Object.keys(files).forEach(function(fieldName) {
363                        if(typeof updateHtml[fieldName].filesWrapper === 'undefined'){
364                            updateHtml[fieldName] = {
365                                filesWrapper: filesWrapper,
366                                html: ''
367                            }
368                        }
369                        field = files[fieldName];
370                        activeFiles = args.form0.querySelector('.super-active-files[name="'+fieldName+'"]');
371                        if(!activeFiles) return true; // continue to next field
372                        fieldWrapper = activeFiles.closest('.super-field-wrapper');
373                        if(!fieldWrapper) return true; // continue to next field
374                        filesWrapper = fieldWrapper.querySelector('.super-fileupload-files');
375                        if(!filesWrapper) return true; // continue to next field
376                        for(i=0; i<field.files.length; i++){
377                            file = field.files[i];
378                            updateHtml[fieldName].html += SUPER.get_single_uploaded_file_html(false, false, file.value, file.type, file.url);
379                            if(args.data[fieldName]){
380                                args.data[fieldName]['files'][i]['value'] = file.value;
381                                args.data[fieldName]['files'][i]['type'] = file.type;
382                                args.data[fieldName]['files'][i]['url'] = file.url;
383                                if(file.subdir) {
384                                    args.data[fieldName]['files'][i]['subdir'] = file.subdir;
385                                }
386                                if(file.attachment) {
387                                    args.data[fieldName]['files'][i]['attachment'] = file.attachment;
388                                }
389                            }
390                        }
391                        filesWrapper.innerHTML = html;
392                    });
393                    Object.keys(updateHtml).forEach(function(fieldName) {
394                        updateHtml[fieldName].filesWrapper.innerHTML = updateHtml[fieldName].html;
395                    });
396
397                    // Now process form data
398                    args._process_form_data_callback(args);
399                }
400            },
401            error: function (xhr, ajaxOptions, thrownError) {
402                // eslint-disable-next-line no-console
403                console.log(xhr, ajaxOptions, thrownError);
404                alert(super_common_i18n.errors.failed_to_process_data);
405            }
406        });
407    };
408    SUPER.process_form_data = function(args){
409        args.generatePdf = false;
410        args.pdfSettings = null;
411        if( typeof SUPER.form_js !== 'undefined' && 
412            typeof SUPER.form_js[args.form_id] !== 'undefined' && 
413            typeof SUPER.form_js[args.form_id]._pdf !== 'undefined' && 
414            SUPER.form_js[args.form_id]._pdf.generate === "true" ) {
415                args.generatePdf = true;
416                args.pdfSettings = SUPER.form_js[args.form_id]._pdf;
417                if(args.progressBar) args.progressBar.style.width = 0+'%';
418                if(args.pdfSettings.generatingText===''){
419                    args.loadingOverlay.querySelector('.super-inner-text').innerHTML = '<span>'+super_common_i18n.loadingOverlay.generating_pdf+'</span>';
420                }else{
421                    args.loadingOverlay.querySelector('.super-inner-text').innerHTML = '<span>'+args.pdfSettings.generatingText+'</span>';
422                }
423        }else{
424            // In case we are in back-end preview mode
425            if( typeof SUPER.get_form_settings === 'function' && 
426                typeof SUPER.get_form_settings()._pdf !== 'undefined' && 
427                SUPER.get_form_settings()._pdf.generate === "true" ) {
428                    args.generatePdf = true;
429                    args.pdfSettings = SUPER.get_form_settings()._pdf;
430                    if(args.progressBar) args.progressBar.style.width = 0+'%';
431                    if(args.pdfSettings.generatingText===''){
432                        args.loadingOverlay.querySelector('.super-inner-text').innerHTML = '<span>'+super_common_i18n.loadingOverlay.generating_pdf+'</span>';
433                    }else{
434                        args.loadingOverlay.querySelector('.super-inner-text').innerHTML = '<span>'+args.pdfSettings.generatingText+'</span>';
435                    }
436            }
437        }
438        if(args.generatePdf){
439            SUPER.pdf_generator_init(args, function(args){
440                // When debugging is enabled download file instantly without submitting the form
441                if(args.pdfSettings.debug==="true"){
442                    var innerText = args.loadingOverlay.querySelector('.super-inner-text');
443                    // Direct download of PDF
444                    args._pdf.save(args.pdfSettings.filename, {returnPromise: true}).then(function() {
445                        // Close loading overlay
446                        if(args.progressBar) args.progressBar.style.width = (100)+"%";  
447                        if(innerText) innerText.innerHTML = '<span>'+super_common_i18n.loadingOverlay.completed+'</span>';
448                        args.loadingOverlay.classList.add('super-success');
449                        if(args.pdfSettings.downloadBtn==='true'){
450                            args.loadingOverlay.classList.add('super-success');
451                            SUPER.show_pdf_download_btn(args);
452                        }
453                        // Close Popup (if any)
454                        if(typeof SUPER.init_popups === 'function' && typeof SUPER.init_popups.close === 'function' ){
455                            SUPER.init_popups.close(true);
456                        }
457                    }, function() {
458                        // Show error message
459                        if(innerText) innerText.innerHTML = '<span>Something went wrong while downloading the PDF</span>';
460                        args.loadingOverlay.classList.add('super-error');
461                    });
462                }
463                SUPER.save_data(args); 
464            });
465        }else{
466            SUPER.save_data(args);
467        }
468    };
469
470    // Focus form
471    SUPER.focusForm = function(target){
472        if(!target) return false;
473        if(target.tagName!=='FORM'){
474            target = target.closest('form');
475        }
476        // Only when form is initialized
477        if(target && target.closest('.super-initialized')){
478            target.classList.add('super-form-focussed');
479            target.tabIndex = -1;
480            SUPER.lastFocussedForm = target;
481        }
482    };
483    // Reset focussed fields
484    SUPER.resetFocussedFields = function(){
485        var i, nodes = document.querySelectorAll('.super-focus');
486        for(i=0; i<nodes.length; i++){
487            if(nodes[i].classList.contains('super-keyword-tags')){
488                var f = nodes[i].querySelector('.super-keyword-filter');
489                if(f) f.value = ''; // empty value
490            }
491            nodes[i].classList.remove('super-focus');
492        }
493    };
494    // Focus field
495    SUPER.focusField = function(target){
496        // Only when form is initialized
497        if(target && target.closest('.super-initialized')){
498            SUPER.resetFocussedFields();
499            if(target.classList.contains('super-field')){
500                target.classList.add('super-focus');
501            }else{
502                if(target.closest('.super-field')) {
503                    target.closest('.super-field').classList.add('super-focus');
504                }
505            }
506        }
507    };
508    SUPER.focusNextTabField = function(e, next, form, skipNext){
509        var i, nodes, parentTabElement, tabsElement, menuWrapper, menuNodes, contentsWrapper, contentNodes, keyCode = -1;
510        if(e) keyCode = e.keyCode || e.which;
511         
512        if(typeof skipNext !== 'undefined'){
513            next = skipNext;
514        }else{
515            next = SUPER.nextTabField(e, next, form);
516        }
517        if(!next) return false;
518
519        // Only for front-end and/or live preview, but not builder mode
520        if(next.closest('.super-preview-elements')){
521            return false;
522        }
523        
524        if(next.classList.contains('super-item')){
525            next = next.closest('.super-field');
526        }
527
528        // Check if inside multi-part, and if multi-part isn't active, make it active
529        if(next.closest('.super-multipart') && !next.closest('.super-multipart').classList.contains('super-active')) {
530            if(SUPER.lastTabKey==='shift+tab'){
531                SUPER.switchMultipart(e, next, 'prev');
532            }else{
533                SUPER.switchMultipart(e, next, 'next');
534            }
535        }
536        // Check if inside TAB element, and if TAB isn't active, make it active
537        parentTabElement = next.closest('.super-tabs-content');
538        while(parentTabElement){
539            if(!parentTabElement.classList.contains('super-active')){
540                tabsElement = parentTabElement.closest('.super-tabs');
541                menuWrapper = tabsElement.querySelector('.super-tabs-menu');
542                contentsWrapper = tabsElement.querySelector('.super-tabs-contents');
543                menuNodes = menuWrapper.querySelectorAll('.super-tabs-tab');
544                contentNodes = contentsWrapper.querySelectorAll('.super-tabs-content');
545                for(i=0; i<contentNodes.length; i++){
546                    if(contentNodes[i]===parentTabElement){
547                        contentNodes[i].classList.add('super-active');
548                        menuNodes[i].classList.add('super-active');
549                    }else{
550                        contentNodes[i].classList.remove('super-active');
551                        menuNodes[i].classList.remove('super-active');
552                    }
553                }
554            }
555            parentTabElement = parentTabElement.parentNode.closest('.super-tabs-content');
556        }
557        // Check if inside Accordion element, and if Accordion isn't active, make it active
558        parentTabElement = next.closest('.super-accordion-item');
559        while(parentTabElement){
560            if(!parentTabElement.classList.contains('super-active')){
561                tabsElement = parentTabElement.closest('.super-tabs');
562                contentNodes = tabsElement.querySelectorAll('.super-accordion-item');
563                for(i=0; i<contentNodes.length; i++){
564                    contentNodes[i].classList.remove('super-active');
565                    if(contentNodes[i]===parentTabElement){
566                        contentNodes[i].classList.add('super-active');
567                    }
568                }
569            }
570            parentTabElement = parentTabElement.parentNode.closest('.super-accordion-item');
571        }
572
573        if(e && e.type!=='click' && keyCode != 32){
574            // Only scroll into view via tabbing, not via clicking
575            next.scrollIntoView({behavior: "auto", block: "center", inline: "center"});
576        }
577        if(keyCode != 32){
578            // If not Space key press
579            nodes = form.querySelectorAll('.super-focus');
580            for ( i = 0; i < nodes.length; i++){
581                nodes[i].classList.remove('super-focus');
582                nodes[i].classList.remove('super-open');
583                if(nodes[i].querySelector('.super-shortcode-field')){
584                    nodes[i].querySelector('.super-shortcode-field').blur();
585                }
586                if( nodes[i].classList.contains('super-button-wrap') ) {
587                    SUPER.init_button_colors( nodes[i] );
588                }
589            }
590        }
591        nodes = form.querySelectorAll('.super-open');
592        for ( i = 0; i < nodes.length; i++){
593            nodes[i].classList.remove('super-open');
594        }
595        nodes = form.querySelectorAll('.super-color .super-shortcode-field');
596        for ( i = 0; i < nodes.length; i++){
597            $(nodes[i]).spectrum("hide");
598        }
599        if( next.classList.contains('super-checkbox') || next.classList.contains('super-radio') ) {
600            next.classList.add('super-focus');
601            if( (next.querySelector('.super-item.super-focus')) && (keyCode != 32) ){
602                var current = next.querySelector('.super-item.super-focus');
603                var nextSibling = current.nextSibling;
604                current.classList.remove('super-focus');
605                nextSibling.classList.add('super-focus');
606            }else{
607                var innerNodes = next.querySelectorAll('.super-item');
608                // Radio has active item
609                if(next.classList.contains('super-radio')){
610                    var activeFound = next.querySelector('.super-item.super-active');
611                }
612                if((SUPER.lastTabKey!=='tab' && keyCode != 9) || (keyCode == 1) ){
613                    // If not TAB key press
614                    return true;
615                }
616                if(activeFound){
617                    activeFound.classList.add('super-focus');
618                }else{
619                    // var innerNodes = next.querySelectorAll('.super-item');
620                    if(e.shiftKey){
621                        innerNodes[innerNodes.length-1].classList.add('super-focus');
622                    }else{
623                        innerNodes[0].classList.add('super-focus');
624                    }
625                }
626            }
627            e.preventDefault();
628            return false;
629        }
630        if( next.classList.contains('super-form-button') ) {
631            next.classList.add('super-focus');
632            SUPER.init_button_hover_colors( next );
633            next.querySelector('.super-button-wrap').focus();
634            e.preventDefault();
635            return false;
636        }
637        if( next.classList.contains('super-color')) {
638            next.classList.add('super-focus');
639            $(next.querySelector('.super-shortcode-field')).spectrum('show');
640            e.preventDefault();
641            return false;
642        }
643        if( next.classList.contains('super-keyword-tags')) {
644            next.classList.add('super-focus');
645            next.querySelector('.super-keyword-filter').focus();
646            e.preventDefault();
647            return false;
648        }
649        if( next.classList.contains('super-dropdown') ) {
650            next.classList.add('super-focus');
651            next.classList.add('super-open');
652            if(next.querySelector('input[name="super-dropdown-search"]')){
653                next.querySelector('input[name="super-dropdown-search"]').focus();
654                e.preventDefault();
655                return false;
656            }
657        }else{
658            next.classList.add('super-focus');
659        }
660        if(next.querySelector('.super-shortcode-field')){
661            next.querySelector('.super-shortcode-field').focus();
662        }
663        e.preventDefault();
664        return false;
665    };
666
667    // Only if field exists
668    SUPER.field_exists = function(form, name, regex){
669        return (SUPER.field(form, name, regex) ? 1 : 0);
670    };
671    SUPER.field = function(form, name, regex){
672        if(typeof name === 'undefined') name = '';
673        regex = (typeof regex === 'undefined' ? '' : regex );
674        // If we want to return all but not by name
675        if(name==='' && regex=='all') return form.querySelectorAll('.super-shortcode-field:not(.super-fileupload), .super-active-files, .super-recaptcha');
676        // If name is empty just return the first field only
677        if(name==='' && regex==='') return form.querySelector('.super-shortcode-field:not(.super-fileupload), .super-active-files');
678        // If no regex was defined return all field just by their exact name match
679        if(name!=='' && regex==='') return form.querySelector('.super-shortcode-field:not(.super-fileupload)[name="'+name+'"], .super-active-files[name="'+name+'"]');
680        // If regex is set to 'all' we want to search for multiple fields
681        // This is currently being used by the builder to determine duplicate field names
682        if(name!=='' && regex=='all') return form.querySelectorAll('.super-shortcode-field:not(.super-fileupload)[name="'+name+'"], .super-active-files[name="'+name+'"]');
683        // If a regex is defined, search for fields based on the regex
684        return form.querySelectorAll('.super-shortcode-field:not(.super-fileupload)[name'+regex+'="'+name+'"], .super-active-files[name="'+name+'"]');
685    };
686    SUPER.fields = function(form, selector){
687        return form.querySelectorAll(selector);
688    };
689    SUPER.fieldsByName = function(form, name){
690        if(name==='') return null; // Skip empty names due to "translation mode"
691        return form.querySelectorAll('.super-shortcode-field:not(.super-fileupload)[name="'+name+'"], .super-active-files[name="'+name+'"]');
692    };
693    
694    SUPER.has_hidden_parent = function(changedField, includeMultiParts){
695        if(changedField[0]) changedField = changedField[0];
696        
697        var p, parent;
698        parent = changedField.closest('.super-shortcode');
699        if( parent && (parent.style.display=='none') && (!parent.classList.contains('super-hidden')) ) {
700            return true;
701        }
702
703        if(parent.dataset.conditionalAction){
704            if((parent.classList.contains('super-conditional-hidden')) ||
705                (parent.dataset.conditionalAction==='hide' && parent.classList.contains('super-conditional-hidden')) ||
706                (parent.dataset.conditionalAction==='show' && !parent.classList.contains('super-conditional-visible'))) {
707                return true;
708            }
709        }
710
711        for (p = changedField && changedField.parentElement; p; p = p.parentElement) {
712            if(p.classList.contains('super-form')) break;
713            if(p.dataset.conditionalAction){
714                if((p.classList.contains('super-conditional-hidden')) ||
715                   (p.dataset.conditionalAction==='hide' && p.classList.contains('super-conditional-hidden')) ||
716                   (p.dataset.conditionalAction==='show' && !p.classList.contains('super-conditional-visible'))) {
717                    return true;
718                }
719            }
720        }
721        
722        // Also check for multi-parts if necessary
723        if(typeof includeMultiParts === 'undefined') includeMultiParts = false;
724        if(includeMultiParts && changedField.closest('.super-multipart') && !changedField.closest('.super-multipart').classList.contains('super-active')){
725            return true;
726        }
727        return false;
728    };
729
730    // Get/Set session data based on pointer
731    SUPER.get_session_pointer = function(key){
732        function getUrlVars() {
733            var vars = {};
734            window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
735                vars[key] = value;
736            });
737            return vars;
738        }
739        function getUrlParam(parameter, defaultvalue){
740            var urlparameter = defaultvalue;
741            if(window.location.href.indexOf(parameter) > -1){
742                urlparameter = getUrlVars()[parameter];
743            }
744            return urlparameter;
745        }
746        return key+'_'+getUrlParam('id', 0);
747    };
748    SUPER.set_session_data = function(key, data, method, raw){
749        if(typeof method === 'undefined') method = 'session';
750        if(typeof raw === 'undefined') raw = false;
751        if(key!=='_super_transfer_element_html') key = SUPER.get_session_pointer(key);
752        if(method==='session'){
753            try {
754                if(data===false){
755                    sessionStorage.removeItem(key);
756                }else{
757                    sessionStorage.setItem(key, data);
758                }
759            }
760            catch (e) {
761                // Empty data when localstorage is full
762                data = JSON.parse(data);
763                var length = data.length/2;
764                var i = 0;
765                while(i < length){
766                    if(typeof data[i] !== 'undefined'){
767                        delete data[i];
768                    }
769                    i++;
770                }
771                SUPER.set_session_data(key, data, method);
772            }
773        }else{
774            if(data===false){
775                localStorage.removeItem(key);
776            }else{
777                localStorage.setItem(key, data);
778            }
779        }
780    };
781    SUPER.get_session_data = function(key, method){
782        if(typeof method === 'undefined') method = 'session';
783        if(key!=='_super_transfer_element_html') key = SUPER.get_session_pointer(key);
784        if(method==='session'){
785            return sessionStorage.getItem(key);
786        }else{
787            return localStorage.getItem(key);
788        }
789    };
790
791    // Barcode generator
792    SUPER.generateBarcode = function(){
793        $('.super-barcode').each(function(){
794            var $this = $(this).find('input');
795            var $renderer = 'css';
796            var $barcode = $this.val();
797            var $barcodetype = $this.data('barcodetype');
798            var $background = $this.data('background');
799            var $barcolor = $this.data('barcolor');
800            var $barwidth = $this.data('barwidth');
801            var $barheight = $this.data('barheight');
802            var $modulesize = $this.data('modulesize');
803            var $rectangular = $this.data('rectangular');
804            var $quietzone = false;
805            if ($this.data('quietzone')==1) $quietzone = true;
806            var $settings = {
807                output:$renderer,
808                bgColor: $background,
809                color: $barcolor,
810                barWidth: $barwidth,
811                barHeight: $barheight,
812                moduleSize: $modulesize,
813                addQuietZone: $quietzone
814            };
815            if($rectangular==1){
816                $barcode = {code:$barcode, rect:true};
817            }
818            $this.parent().find('.super-barcode-target').barcode($barcode, $barcodetype, $settings);
819        });
820    };
821
822    // init Rating
823    SUPER.rating = function(){
824        $('.super-rating').on('mouseleave',function(){
825            $(this).find('.super-rating-star').removeClass('super-hover');
826        });
827        $('.super-rating-star').on('click',function(){
828            SUPER.focusForm(this);
829            SUPER.focusField(this);
830            $(this).parent().find('.super-rating-star').removeClass('super-active');
831            $(this).addClass('super-active');
832            $(this).prevAll('.super-rating-star').addClass('super-active');
833            var $rating = $(this).index()+1;
834            $(this).parent().find('input').val($rating);
835            SUPER.after_field_change_blur_hook({el: $(this).parent().find('input')[0]});
836        });
837        $('.super-rating-star').on('mouseover',function(){
838            $(this).parent().find('.super-rating-star').removeClass('super-hover');
839            $(this).addClass('super-hover');
840            $(this).prevAll('.super-rating-star').addClass('super-hover');
841        });
842    };
843
844
845    // @since 2.3.0 - init file upload fields
846    SUPER.init_fileupload_fields = function(){
847        $('.super-fileupload:not(.super-rendered)').each(function() {
848            $(this).addClass('super-rendered');
849            var formId = 0;
850            var form = SUPER.get_frontend_or_backend_form({el: this});
851            if(form.querySelector('input[name="hidden_form_id"]')){
852                formId = form.querySelector('input[name="hidden_form_id"]').value;
853            }
854            var field = $(this).parents('.super-field-wrapper:eq(0)').find('.super-active-files');
855            var fieldName = field.attr('name');
856            if(typeof SUPER.files[formId] === 'undefined'){
857                SUPER.files[formId] = [];
858            }
859            if(typeof SUPER.files[formId][fieldName] === 'undefined'){
860                SUPER.files[formId][fieldName] = [];
861            }
862            var i, file, fileName, fileUrl, fileType,
863                uploadedFiles = $(this).parents('.super-field-wrapper:eq(0)').find('.super-fileupload-files > .super-uploaded');
864            for(i=0; i<uploadedFiles.length; i++){
865                file = uploadedFiles[i];
866                fileName = file.dataset.name;
867                fileUrl = file.dataset.url;
868                fileType = file.dataset.type;
869                SUPER.files[formId][fieldName][i] = {};
870                SUPER.files[formId][fieldName][i]['type'] = fileType;
871                SUPER.files[formId][fieldName][i]['name'] = fileName;
872                SUPER.files[formId][fieldName][i]['url'] = fileUrl;
873            }
874
875            $(this).fileupload({
876                filesContainer : $(this).find(".super-fileupload-files"),
877                dropZone : $(this).parent('.super-field-wrapper'),
878                add: function(e, data) {
879                    var uploadErrors = [];
880                    if(data.originalFiles[0].size > ($(this).data('file-size')*1000000) ) {
881                        $(this).parents('.super-field-wrapper:eq(0)').find('.super-fileupload-files').children('div[data-name="'+data.originalFiles[0].name+'"]').remove();
882                        uploadErrors.push(super_common_i18n.errors.file_upload.filesize_too_big);
883                    }
884                    if(uploadErrors.length > 0) {
885                        alert(uploadErrors.join("\n"));
886                    }
887                },
888                dataType: 'json',
889                autoUpload: false,
890                maxFileSize: $(this).data('file-size')*1000000, // 5 MB
891                progressall: function (e, data) {
892                    var progress = parseInt(data.loaded / data.total * 100, 10);
893                    $(this).parent().children('.super-progress-bar').
893css('display','block').css('width', progress + '%');
894                }        
895            }).on('fileuploadadd', function (e, data) {
896                var formId = 0;
897                var form = SUPER.get_frontend_or_backend_form({el: this});
898                if(form.querySelector('input[name="hidden_form_id"]')){
899                    formId = form.querySelector('input[name="hidden_form_id"]').value;
900                }
901                $(this).removeClass('finished');
902                $(this).parents('.super-field-wrapper:eq(0)').find('.super-fileupload-files > div.error').remove();
903                data.context = $('<div/>').appendTo($(this).parents('.super-field-wrapper:eq(0)').find('.super-fileupload-files'));
904                var field = $(this).parents('.super-field-wrapper:eq(0)').find('.super-active-files')[0];
905                var fieldName = $(this).parents('.super-field-wrapper:eq(0)').find('.super-active-files').attr("name");
906                var el = $(this);
907                var accepted_file_types = el.data('accept-file-types');
908                var file_types_object = accepted_file_types.split('|');
909
910                // @since 4.4.0 - Upload limitation for all files combined
911                var upload_limit = $(this).data('upload-limit')*1000000; // e.g: 20 MB
912
913                $.each(data.files, function (index, file) {
914                    var total = el.data('total-file-sizes');
915                    if(typeof total === 'undefined'){
916                        total = file.size;
917                    }else{
918                        total = total+file.size;
919                    }
920                    if( (total>upload_limit) && (upload_limit!==0) ) {
921                        el.parents('.super-field-wrapper:eq(0)').find('.super-fileupload-files > div').last().remove();
922                        alert(super_common_i18n.errors.file_upload.upload_limit_reached);
923                    }else{
924                        var f = SUPER.get_file_name_and_extension(file.name);
925                        if( (file_types_object.indexOf(f.ext)!=-1) || (accepted_file_types==='') ) {
926                            el.data('total-file-sizes', total);
927                            data.context.parent('div').children('div[data-name="'+file.name+'"]').remove();
928                            if(typeof SUPER.files[formId] === 'undefined'){
929                                SUPER.files[formId] = [];
930                            }
931                            if(typeof SUPER.files[formId][fieldName] === 'undefined'){
932                                SUPER.files[formId][fieldName] = [];
933                            }
934                            if(file.type && file.type.indexOf("image/") === 0){
935                                var src = URL.createObjectURL(file)
936                            }
937                            var totalFiles = SUPER.files[formId][fieldName].length;
938                            SUPER.files[formId][fieldName][totalFiles] = file; //SUPER.files[formId][totalFiles] = file;
939                            SUPER.files[formId][fieldName][totalFiles]['url'] = src; // blob
940                            var html = SUPER.get_single_uploaded_file_html(true, false, file.name, file.type, src
940);
941                            data.context.data(data).attr('data-name',file.name).attr('title',file.name).attr('data-type',file.type).html(html);
942                            data.context.data('file-size',file.size);
943                            if(data.context[0].querySelector('img')){
944                                var img = data.context[0].querySelector('img');
945                                img.onload = function(){
946                                    //URL.revokeObjectURL(img.src); // free memory
947                                }
948                            }
949                            SUPER.after_field_change_blur_hook({el: field, form: form});
950                            //SUPER.init_replace_html_tags({el: el, form: form}); //undefined, form);
951                        }else{
952                            data.context.remove();
953                            alert(super_common_i18n.errors.file_upload.incorrect_file_extension);
954                        }
955                    }
956                });
957            }).on('fileuploadprocessalways', function (e, data) {
958                var index = data.index;
959                var file = data.files[index];
960                if (file.error) {
961                    $(this).parents('.super-field-wrapper:eq(0)').find('.super-fileupload-files').find("[data-name='" + file.name + "']").remove();
962                    alert(file.error);
963                }
964            }).on('fileuploadfail', function (e, data) {
965                var el = e.target;
966                var form = el.closest('.super-form');
967                SUPER.handle_errors(el);
968                $.each(data.files, function (index) {
969                    var error = $('<span class="super-error"/>').text(' (file upload failed)');
970                    $(data.context.children()[index]).children('.super-error').remove();
971                    $(data.context.children()[index]).append(error);
972                });
973                alert(data.errorThrown.message);
974                SUPER.reset_submit_button_loading_state(form);
975                SUPER.handle_validations({el: el, form: form});
976                SUPER.scrollToError(form);
977            }).on('fileuploadsubmit', function (e, data) {
978                data.formData = {
979                    'accept_file_types': $(this).data('accept-file-types'),
980                    'max_file_size': $(this).data('file-size')*1000000,
981                    'image_library': super_common_i18n.image_library
982                };
983            });
984        });
985    };
986
987    // @since 5.0.100 - international phonenumber field
988    SUPER.init_international_phonenumber_fields = function(){
989        $('.super-shortcode-field[type="int-phone"]:not(.super-rendered)').each(function(){
990            var input = this;
991            input.classList.add('super-rendered');
992            var settings = JSON.parse(input.dataset.intPhone),
993                preferredCountries = (settings.preferredCountries==='' ? '' : settings.preferredCountries.replace(/\s/g, '').split(',')),
994                onlyCountries = (settings.onlyCountries==='' ? '' : settings.onlyCountries.replace(/\s/g, '').split(',')),
995                localizedCountries = {},
996                items = (settings.localizedCountries==='' ? '' : settings.localizedCountries.split('\n')),
997                values;
998            $(items).each(function(i, v){
999                values = v.split("|");
1000                if(values[0] && values[1]){
1001                    localizedCountries[values[0]] = values[1];
1002                }
1003            });
1004            window.superTelInput(input, {
1005                separateDialCode: true,
1006                autoPlaceholder: "aggressive",
1007                utilsScript: super_common_i18n.super_int_phone_utils, //"utils.js", 
1008                preferredCountries: preferredCountries, // ["nl", "de", "be"] Specify the countries to appear at the top of the list.
1009                onlyCountries: onlyCountries, // ["nl", "de", "be"]
1010                localizedCountries: localizedCountries, //{ 'de': 'Deutschland' }
1011                placeholderNumberType: settings.placeholderNumberType, // "MOBILE" // "FIXED_LINE": 0, "MOBILE": 1, "FIXED_LINE_OR_MOBILE": 2, "TOLL_FREE": 3, "PREMIUM_RATE": 4, "SHARED_COST": 5, "VOIP": 6, "PE
1011RSONAL_NUMBER": 7, "PAGER": 8, "UAN": 9, "VOICEMAIL": 10, "UNKNOWN": -1
1012                customPlaceholder: function(selectedCountryPlaceholder) {
1013                    var adaptivePlaceholder = input.closest('.super-int-phone-field').querySelector('.super-adaptive-placeholder');
1014                    if(adaptivePlaceholder){
1015                        adaptivePlaceholder.dataset.placeholder = selectedCountryPlaceholder;
1016                        adaptivePlaceholder.querySelector('span').innerHTML = selectedCountryPlaceholder;
1017                    }
1018                    return selectedCountryPlaceholder;
1019                },
1020            });
1021            this.addEventListener("countrychange", function() {
1022                SUPER.after_field_change_blur_hook({el: this});
1023            });
1024            this.addEventListener("open:countrydropdown", function() {
1025                var form = SUPER.get_frontend_or_backend_form({el: this}),
1026                    i, nodes = form.querySelectorAll('.super-open');
1027                for ( i = 0; i < nodes.length; i++){
1028                    nodes[i].classList.remove('super-open');
1029                }
1030                this.closest('.super-shortcode').classList.add('super-open');
1031            });
1032            this.addEventListener("close:countrydropdown", function() {
1033                this.closest('.super-shortcode').classList.remove('super-open');
1034            });
1035        });
1036    };
1037
1038    // @since 3.5.0 - calculate distance (google)
1039    var distance_calculator_timeout = null; 
1040    SUPER.calculate_distance = function(args){
1041        if(!args.el) return false;
1042        if(args.el.classList.contains('super-distance-calculator')){
1043            var form = SUPER.get_frontend_or_backend_form(args),
1044                $method = args.el.dataset.distanceMethod,
1045                $origin_field,
1046                $origin,
1047                $destination_field,
1048                $destination,
1049                $value,
1050                $units,
1051                $result,
1052                $leg,
1053                $field,
1054                $calculation_value,
1055                $html,
1056                $alert_msg;
1057            if($method=='start'){
1058                $origin_field = args.el;
1059                $origin = args.el.value;
1060                $destination = args.el.dataset.distanceDestination;
1061                if(SUPER.field_exists(form, $destination)){
1062                    $destination_field = SUPER.field(form, $destination);
1063                    $destination = ($destination_field ? $destination_field.value : '');
1064                }
1065            }else{
1066                $origin_field = SUPER.field(form, args.el.dataset.distanceStart);
1067                $origin = ($origin_field ? $origin_field.value : '');
1068                $destination_field = args.el;
1069                $destination = args.el.value;
1070            }
1071            $value = $origin_field.dataset.distanceValue;
1072            $units = $origin_field.dataset.distanceUnits;
1073            if($value!='dis_text'){
1074                $units = 'metric';
1075            }
1076            if( ($origin==='') || ($destination==='') ) {
1077                return true;
1078            }
1079            if(distance_calculator_timeout !== null){
1080                clearTimeout(distance_calculator_timeout);
1081            }
1082            distance_calculator_timeout = setTimeout(function () {
1083                args.el.closest('.super-field-wrapper').classList.add('super-calculating-distance');
1084                $.ajax({
1085                    url: super_common_i18n.ajaxurl,
1086                    type: 'post',
1087                    data: {
1088                        action: 'super_calculate_distance',
1089                        units: $units,
1090                        origin: $origin,
1091                        destination: $destination
1092                    },
1093                    success: function (result) {
1094                        $result = JSON.parse(result);
1095                        if($result.status=='OK'){
1096                            $leg = $result.routes[0].legs[0];
1097                            $field = $origin_field.dataset.distanceField;
1098                            // distance  - Distance in meters
1099                            if( $value=='distance' ) {
1100                                $calculation_value = $leg.distance.value;
1101                            }
1102                            // dis_text  - Distance text in km or miles
1103                            if( $value=='dis_text' ) {
1104                                $calculation_value = $leg.distance.text;
1105                            }
1106                            // duration  - Duration in seconds
1107                            if( $value=='duration' ) {
1108                                $calculation_value = $leg.duration.value;
1109                            }
1110                            // dur_text  - Duration text in minutes
1111                            if( $value=='dur_text' ) {
1112                                $calculation_value = $leg.duration.text;
1113                            }
1114                            $field = SUPER.field(form, $field);
1115                            $field.value = $calculation_value;
1116                            if($calculation_value===''){
1117                                $field.closest('.super-shortcode').classList.remove('super-filled');
1118                            }else{
1119                                $field.closest('.super-shortcode').classList.add('super-filled');
1120                            }
1121                            SUPER.after_field_change_blur_hook({el: $field});
1122                            SUPER.init_replace_html_tags({el: $field, form: form}); //undefined, form);
1123                        }else{
1124                            if($result.status=='ZERO_RESULTS'){
1125                                $alert_msg = super_common_i18n.errors.distance_calculator.zero_results;
1126                            }else{
1127                                if($result.status=='OVER_QUERY_LIMIT'){
1128                                    $alert_msg = $result.error_message;
1129                                }else{
1130                                    if($result.error===true){
1131                                        $alert_msg = $result.msg;
1132                                    }else{
1133                                        $alert_msg = super_common_i18n.errors.distance_calculator.error;
1134                                    }
1135                                }
1136                            }
1137                            $('.super-msg').remove();
1138                            $result = JSON.parse(result);
1139                            $html = '<div class="super-msg super-error">';                            
1140                            $origin_field.blur();
1141                            if(typeof $destination_field !== 'undefined') $destination_field.blur();
1142                            $html += $alert_msg;
1143                            $html += '<span class="super-close"></span>';
1144                            $html += '</div>';
1145                            $($html).prependTo($(form));
1146                            $('html, body').animate({
1147                                scrollTop: $(form).offset().top-200
1148                            }, 1000);
1149                        }
1150                    },
1151                    complete: function(){
1152                        args.el.closest('.super-field-wrapper').classList.remove('super-calculating-distance');
1153                    },
1154                    error: function (xhr, ajaxOptions, thrownError) {
1155                        // eslint-disable-next-line no-console
1156                        console.log(xhr, ajaxOptions, thrownError);
1157                        alert(super_common_i18n.errors.failed_to_process_data);
1158                    }
1159                });
1160            }, 1000);
1161        }
1162    };
1163
1164    // Handle Conditional logic
1165    SUPER.conditional_logic = function(args){
1166        var logic,
1167            didLoop = false,
1168            form = SUPER.get_frontend_or_backend_form(args);
1169        if(typeof args.el !== 'undefined'){
1170            logic = form.querySelectorAll('.super-conditional-logic[data-fields*="{'+SUPER.get_original_field_name(args.el)+'}"]');
1171        }else{
1172            logic = form.querySelectorAll('.super-conditional-logic');
1173        }
1174        if(typeof logic !== 'undefined'){
1175            if(logic.length!==0){
1176                didLoop = true;
1177                args.conditionalLogic = logic;
1178                SUPER.conditional_logic.loop(args);
1179            }
1180        }
1181        // Make sure that we still update variable fields based on changed field.
1182        if( didLoop===false ) {
1183            SUPER.update_variable_fields(args);
1184        }
1185    };
1186
1187    // @since 3.6.0 - always make sure to return the value of the field in case it uses advanced tags like function like: value;value2
1188    // Also make sure to return multiple values in case of dropdown/checkbox or other multi value elements
1189    // Function to return the dynamic tag value based on conditions field check
1190    SUPER.return_dynamic_tag_value = function($parent, $value){
1191        if( typeof $value === 'undefined' ) return '';
1192        if( $value==='' ) return $value;
1193        if( (typeof $parent !== 'undefined') && ( ($parent.hasClass('super-dropdown')) || ($parent.hasClass('super-checkbox')) ) ) {
1194            var $values = $value.toString().split(',');
1195            var $new_values = '';
1196            $.each($values, function( index, value ) {
1197                var $value = value.toString().split(';');
1198                $value = $value[0];
1199                if($new_values===''){
1200                    $new_values += $value;
1201                }else{
1202                    $new_values += ','+$value;
1203                }
1204            });
1205            $value = $new_values;
1206        }else{
1207            $value = $value.toString().split(';');
1208            $value = $value[0];      
1209        }
1210        return $value;
1211    };
1212
1213    SUPER.conditional_logic.match_found = function($match_found, v, $shortcode_field_value, $shortcode_field_and_value, $parent, $parent_and, $variable){
1214        var $i = 0,
1215            $found,
1216            $checked,
1217            $string_value;
1218        switch(v.logic) {
1219          case 'equal':
1220            if( v.value==$shortcode_field_value ) $i++;
1221            break;
1222          case 'not_equal':
1223            if( v.value!=$shortcode_field_value ) $i++;
1224            break;
1225          case 'greater_than':
1226            if( parseFloat($shortcode_field_value)>parseFloat(v.value) ) $i++;
1227            break;
1228          case 'less_than':
1229            if( parseFloat($shortcode_field_value)<parseFloat(v.value) ) $i++;
1230            break;
1231          case 'greater_than_or_equal':
1232            if( parseFloat($shortcode_field_value)>=parseFloat(v.value) ) $i++;
1233            break;
1234          case 'less_than_or_equal':
1235            if( parseFloat($shortcode_field_value)<=parseFloat(v.value) ) $i++;
1236            break;
1237          case 'contains':
1238            if( (typeof $parent !== 'undefined') && (
1239                $parent.classList.contains('super-checkbox') || 
1240                $parent.classList.contains('super-radio') || 
1241                $parent.classList.contains('super-dropdown')) ) {
1242                $checked = $shortcode_field_value.split(',');
1243                $string_value = v.value.toString();
1244                Object.keys($checked).forEach(function(key) {
1245                    if( $checked[key].indexOf($string_value) >= 0) {
1246                        $i++;
1247                        return false;
1248                    }
1249                });
1250            }else{
1251                // If other field
1252                if( $shortcode_field_value.indexOf(v.value) >= 0) $i++;
1253            }
1254            break;
1255          case 'not_contains':
1256            if( (typeof $parent !== 'undefined') && (
1257                $parent.classList.contains('super-checkbox') || 
1258                $parent.classList.contains('super-radio') || 
1259                $parent.classList.contains('super-dropdown')) ) {
1260                $checked = $shortcode_field_value.split(',');
1261                $string_value = v.value.toString();
1262                $found = false;
1263                Object.keys($checked).forEach(function(key) {
1264                    if( $checked[key].indexOf($string_value) >= 0) {
1265                        $found = true;
1266                        return false;
1267                    }
1268                });
1269                if(!$found) $i++;
1270            }else{
1271                // If other field
1272                if( $shortcode_field_value.indexOf(v.value) == -1) $i++;
1273            }
1274            break;
1275
1276          default:
1277          // code block
1278        }
1279        if( v.and_method!=='' ) {
1280            switch(v.logic_and) {
1281              case 'equal':
1282                if( v.value_and==$shortcode_field_and_value ) $i++;
1283                break;
1284              case 'not_equal':
1285                if( v.value_and!=$shortcode_field_and_value ) $i++;
1286                break;
1287              case 'greater_than':
1288                if( parseFloat($shortcode_field_and_value)>parseFloat(v.value_and) ) $i++;
1289                break;
1290              case 'less_than':
1291                if( parseFloat($shortcode_field_and_value)<parseFloat(v.value_and) ) $i++;
1292                break;
1293              case 'greater_than_or_equal':
1294                if( parseFloat($shortcode_field_and_value)>=parseFloat(v.value_and) ) $i++;
1295                break;
1296              case 'less_than_or_equal':
1297                if( parseFloat($shortcode_field_and_value)<=parseFloat(v.value_and) ) $i++;
1298                break;
1299              case 'contains':
1300                if( (typeof $parent_and !== 'undefined') && ( 
1301                    $parent_and.classList.contains('super-checkbox') || 
1302                    $parent_and.classList.contains('super-radio') || 
1303                    $parent_and.classList.contains('super-dropdown')) ) {
1304                    $checked = $shortcode_field_and_value.split(',');
1305                    $string_value = v.value_and.toString();
1306                    Object.keys($checked).forEach(function(key) {
1307                        if( $checked[key].indexOf($string_value) >= 0) {
1308                            $i++;
1309                            return false;
1310                        }
1311                    });
1312                }else{
1313                    // If other field
1314                    if( $shortcode_field_and_value.indexOf(v.value_and) >= 0) $i++;
1315                }
1316                break;
1317              case 'not_contains':
1318                if( (typeof $parent_and !== 'undefined') && ( 
1319                    $parent_and.classList.contains('super-checkbox') || 
1320                    $parent_and.classList.contains('super-radio') || 
1321                    $parent_and.classList.contains('super-dropdown')) ) {
1322                    $checked = $shortcode_field_and_value.split(',');
1323                    $string_value = v.value_and.toString();
1324                    $found = false;
1325                    Object.keys($checked).forEach(function(key) {
1326                        if( $checked[key].indexOf($string_value) >= 0) {
1327                            $found = true;
1328                            return false;
1329                        }
1330                    });
1331                    if(!$found) $i++;
1332                }else{
1333                    // If other field
1334                    if( $shortcode_field_and_value.indexOf(v.value_and) == -1) $i++;
1335                }
1336                break;
1337              default:
1338              // code block
1339            }
1340        }
1341        // When we are checking for variable condition return on matches
1342        if($variable) return $i;
1343        // When we are checking conditional logic then we need to know the total matches as a whole, because we have a method (One/All)
1344        if( v.and_method=='and' ) {
1345            if($i>=2) $match_found++;
1346        }else{
1347            if($i>=1) $match_found++;
1348        }
1349        return $match_found;
1350    };
1351
1352    SUPER.get_conditional_validation_value = function(value, form){
1353        var conditionalParent,
1354            text_field,
1355            string_value,
1356            bracket,
1357            regex,
1358            name,
1359            element,
1360            sum,
1361            selected,
1362            checked;
1363
1364        string_value = value.toString();
1365        bracket = "{";
1366        if(string_value.indexOf(bracket) != -1){
1367            regex = /{([^\\\/\s"'+]*?)}/g;
1368            name = regex.exec(value);
1369            name = name[1];
1370            element = SUPER.field(form, name);
1371            if(element){
1372                text_field = true;
1373                conditionalParent = element.closest('.super-field');
1374                // Check if dropdown field
1375                if( (conditionalParent.classList.contains('super-dropdown')) ){
1376                    text_field = false;
1377                    sum = 0;
1378                    selected = conditionalParent.querySelectorAll('.super-dropdown-list .super-item.super-active:not(.super-placeholder)');
1379                    Object.keys(selected).forEach(function(key) {
1380                        sum += selected[key].dataset.value;
1381                    });
1382                    value = sum;
1383                }
1384                // Check if checkbox field
1385                if(conditionalParent.classList.contains('super-checkbox')){
1386                    text_field = false;
1387                    sum = 0;
1388                    checked = conditionalParent.querySelectorAll('input[type="checkbox"]:checked');
1389                    Object.keys(checked).forEach(function(key) {
1390                        sum += checked[key].value;
1391                    });
1392                    value = sum;
1393                }
1394                // Check if currency field
1395                if(conditionalParent.classList.contains('super-currency')){
1396                    text_field = false;
1397                    value = $(element).maskMoney('unmasked')[0];
1398                    value = (value) ? parseFloat(value) : 0;
1399                }
1400                // Check if text or textarea field
1401                if(text_field===true) value = (element.value) ? element.value : '';
1402            }
1403        }
1404        return value;
1405    }
1406
1407
1408    SUPER.conditional_logic.get_field_value = function($logic, $shortcode_field_value, $shortcode_field, $parent){
1409        if( $logic=='greater_than' || $logic=='less_than' || $logic=='greater_than_or_equal' || $logic=='less_than_or_equal' ) {
1410            var $sum = 0,
1411                $selected;
1412            // Check if dropdown field
1413            if( $parent.classList.contains('super-dropdown') ){
1414                $selected = $parent.querySelectorAll('.super-dropdown-list .super-item.super-active:not(.super-placeholder)');
1415                Object.keys($selected).forEach(function(key) {
1416                    $sum += parseFloat($selected[key].dataset.value);
1417                });
1418                $shortcode_field_value = $sum;
1419            }
1420            // Check if checkbox field
1421            if( $parent.classList.contains('super-checkbox') ) {
1422                $selected = $parent.querySelectorAll('.super-active');
1423                Object.keys($selected).forEach(function(key) {
1424                    $sum += parseFloat($selected[key].querySelector('input').value);
1425                });
1426                $shortcode_field_value = $sum;
1427            }
1428
1429            // @since 2.3.0 - compatibility with conditional logic
1430            // Check if currency field (since Super Forms v2.1)
1431            if( $parent.classList.contains('super-currency') ) {
1432                var $value = $($shortcode_field).maskMoney('unmasked')[0];
1433                $shortcode_field_value = ($value) ? parseFloat($value) : 0;
1434            }
1435        }
1436        return $shortcode_field_value;
1437    };
1438    SUPER.conditional_logic.loop = function(args){
1439        args.regex = /{([^\\\/\s"'+]*?)}/g;
1440        var v,
1441            $v,
1442            $this,
1443            $json,
1444            $wrapper,
1445            $field,
1446            $trigger,
1447            $action,
1448            $conditions,
1449            $total,
1450            $regex = /{([^\\\/\s"'+]*?)}/g,
1451            $shortcode_field_value,
1452            $shortcode_field_and_value,
1453            $continue,
1454            $continue_and,
1455            $skip,
1456            $skip_and,
1457            $field_name,
1458            $shortcode_field,
1459            $shortcode_field_and,
1460            $parent,
1461            $parent_and,
1462            $hide_wrappers,
1463            $show_wrappers,
1464            $changed_wrappers,
1465            $inner,
1466            $element,
1467            $data_fields,
1468            $is_variable,
1469            $is_validate,
1470            $match_found,
1471            $prev_match_found,
1472            $updated_variable_fields = {},
1473            $validation_error = false;
1474
1475        Object.keys(args.conditionalLogic).forEach(function(key) {
1476            $prev_match_found = false;
1477            $this = args.conditionalLogic[key];
1478            args.currentTextarea = $this;
1479            $wrapper = $this.closest('.super-shortcode');
1480            $field = $wrapper.querySelector('.super-shortcode-field');
1481            $is_variable = false;
1482            $is_validate = false;
1483            if($this.classList.contains('super-variable-conditions')){
1484                $is_variable = true;
1485                $action = $wrapper.dataset.conditionalVariableAction;
1486            }else{
1487                if($this.classList.contains('super-validate-conditions')){
1488                    $is_validate = true;
1489                    $action = 'show';
1490                    $trigger = 'one';
1491                }else{
1492                    $trigger = $wrapper.dataset.conditionalTrigger;
1493                    $action = $wrapper.dataset.conditionalAction;
1494                }
1495            }
1496
1497            // Check if condition is a variable condition, also check if this is a text field, and if the form is being submitted.
1498            // If all are true, we must skip this condition to make sure any manual input data won't be reset/overwritten
1499            if( ($is_variable===true) && ($wrapper.classList.contains('super-text')===true) && (args.doingSubmit===true) ) {
1500                return false;                
1501            }
1502
1503            $json = $this.value;
1504            if(($action) && ($action!='disabled')){
1505                $conditions = JSON.parse($json);
1506                if($conditions){
1507                    $total = 0;
1508                    $match_found = 0;
1509                    Object.keys($conditions).forEach(function(key) {
1510                        if(!$prev_match_found){
1511                            $total++;
1512                            v = $conditions[key];
1513                            // @since 3.5.0 - make sure {tags} are replaced with the correct field value to check conditional logic
1514                            args.value = v.value;
1515                            v.value = SUPER.update_variable_fields.replace_tags(args);
1516                            args.value = v.value_and;
1517                            v.value_and = SUPER.update_variable_fields.replace_tags(args);
1518                            args.value = v.field;
1519                            args.bwc = true;
1520                            $shortcode_field_value = SUPER.update_variable_fields.replace_tags(args);
1521                            args.value = v.field_and;
1522                            args.bwc = true;
1523                            $shortcode_field_and_value = SUPER.update_variable_fields.replace_tags(args);
1524                            delete args.bwc;
1525                            $continue = false;
1526                            $continue_and = false;
1527                            $skip = false;
1528                            $skip_and = false;
1529                            // If conditional field selectors don't contain curly braces, then append and prepend them for backwards compatibility
1530                            if(v.field!=='' && v.field.indexOf('{')===-1) v.field = '{'+v.field+'}';
1531                            if(typeof v.field_and !== 'undefined' && v.field_and!=='' && v.field_and.indexOf('{')===-1) v.field_and = '{'+v.field_and+'}';
1532
1533                            while (($v = $regex.exec(v.field)) !== null) {
1534                                // This is necessary to avoid infinite loops with zero-width matches
1535                                if ($v.index === $regex.lastIndex) {
1536                                    $regex.lastIndex++;
1537                                }
1538                                $field_name = $v[1].split(';')[0];
1539                                if($field_name=='dynamic_column_counter'){
1540                                    continue;
1541                                }
1542                                $shortcode_field = SUPER.field(args.form, $field_name);
1543                                if(!$shortcode_field) {
1544                                    $continue = true;
1545                                    continue;
1546                                }
1547                                $skip = SUPER.has_hidden_parent($shortcode_field);
1548                                $parent = $shortcode_field.closest('.super-shortcode');
1549                            }
1550                            if(v.and_method!==''){ 
1551                                if(v.and_method==='and' && $continue) return;
1552                                while (($v = $regex.exec(v.field_and)) !== null) {
1553                                    // This is necessary to avoid infinite loops with zero-width matches
1554                                    if ($v.index === $regex.lastIndex) {
1555                                        $regex.lastIndex++;
1556                                    }
1557                                    $field_name = $v[1].split(';')[0];
1558                                    if($field_name=='dynamic_column_counter'){
1559                                        continue;
1560                                    }
1561                                    $shortcode_field_and = SUPER.field(args.form, $field_name);
1562                                    if(!$shortcode_field_and){
1563                                        $continue_and = true;
1564                                        continue;
1565                                    }
1566                                    $skip_and = SUPER.has_hidden_parent($shortcode_field_and);
1567                                    $parent_and = $shortcode_field_and.closest('.super-shortcode');
1568                                }
1569                                if(v.and_method==='or' && !$continue_and){
1570                                    $continue = false;
1571                                }
1572                            }
1573                            if($continue || $continue_and) return;
1574                            if( (v.and_method==='and' && ($skip || $skip_and) && !$is_variable) ||
1575                               (v.and_method==='or' && ($skip && $skip_and) && !$is_variable) ) {
1576                                // Exclude conditionally
1577                            }else{
1578                                $shortcode_field_value = SUPER.return_dynamic_tag_value($($parent), $shortcode_field_value);
1579                                $shortcode_field_and_value = SUPER.return_dynamic_tag_value($($parent_and), $shortcode_field_and_value);
1580                                if(!$shortcode_field_value) $shortcode_field_value = '';
1581                                if(!$shortcode_field_and_value) $shortcode_field_and_value = '';
1582                                // Generate correct value before checking conditional logic
1583                                $shortcode_field_value = SUPER.conditional_logic.get_field_value(v.logic, $shortcode_field_value, $shortcode_field, $parent);
1584                                // Generate correct and value before checking conditional logic
1585                                if(v.and_method!==''){ 
1586                                    $shortcode_field_and_value = SUPER.conditional_logic.get_field_value(v.logic_and, $shortcode_field_and_value, $shortcode_field_and, $parent_and);
1587                                }
1588                                if($is_variable){
1589                                    $match_found = SUPER.conditional_logic.match_found(0, v, $shortcode_field_value, $shortcode_field_and_value, $parent , $parent_and, true);
1590                                    if( v.and_method=='and' ) {
1591                                        if($match_found>=2) {
1592                                            $prev_match_found = true;
1593                                            if( v.new_value!=='' ) {
1594                                                args.value = v.new_value;
1595                                                v.new_value = SUPER.update_variable_fields.replace_tags(args);
1596                                            }
1597                                            $field.value = v.new_value;
1598                                        }else{
1599                                            // @important - we must check if changed field is undefined
1600                                            // because when either "Save form progression" or "Retrieve last entry data" is enabled
1601                                            // in combination with a variable field depending on a other field to retrieve it values
1602                                            // (think of, search customer field, e.g: autosuggest feature with customer data)
1603                                            // because it would try to re-populate the variable field (could be text field) with it's data
1604                                            // but on page load this text field might already contain data which we rather not override :)
1605                                            // @important - or should we grab the data-default-value attribute?
1606                                            if(typeof args.el !== 'undefined'){
1607                                                $field.value = ''; // No match was found just set to an empty string
1608                                            }
1609                                        }
1610                                    }else{
1611                                        if($match_found>=1) {
1612                                            $prev_match_found = true;
1613                                            if( v.new_value!=='' ) {
1614                                                args.value = v.new_value;
1615                                                v.new_value = SUPER.update_variable_fields.replace_tags(args);
1616                                            }
1617                                            $field.value = v.new_value;
1618                                        }else{
1619                                            // @important - we must check if changed field is undefined
1620                                            // because when either "Save form progression" or "Retrieve last entry data" is enabled
1621                                            // in combination with a variable field depending on a other field to retrieve it values
1622                                            // (think of, search customer field, e.g: autosuggest feature with customer data)
1623                                            // because it would try to re-populate the variable field (could be text field) with it's data
1624                                            // but on page load this text field might already contain data which we rather not override :)
1625                                            // @important - or should we grab the data-default-value attribute?
1626                                            if(typeof args.el !== 'undefined'){
1627                                                $field.value = ''; // No match was found just set to an empty string
1628                                            }
1629                                        }
1630                                    }
1631                                    // No matter what, we will always apply and then remove the 'entry-data' attribute if it existed
1632                                    if(typeof $field.dataset.entryValue !== 'undefined'){
1633                                        $field.value = $field.dataset.entryValue;
1634                                        delete $field.dataset.entryValue;
1635                                    }
1636                                    // Add the field to the updated fields array 
1637                                    $updated_variable_fields[$field.name] = $field;
1638                                }else{
1639                                    $match_found = SUPER.conditional_logic.match_found($match_found, v, $shortcode_field_value, $shortcode_field_and_value, $parent , $parent_and, false);
1640                                }
1641                            }
1642                        }
1643                    });
1644                    if(!$is_variable){
1645                        $hide_wrappers = [];
1646                        $show_wrappers = [];
1647                        $changed_wrappers = [];
1648                        if($trigger=='all'){
1649                            if($match_found==$total){
1650                                if( ($action==='show') && (!$wrapper.classList.contains('super-conditional-visible')) ){
1651                                    $changed_wrappers.push($wrapper);
1652                                    $show_wrappers.push($wrapper);
1653                                }
1654                                if( ($action==='hide') && ($wrapper.classList.contains('super-conditional-visible')) ){
1655                                    $changed_wrappers.push($wrapper);
1656                                    $hide_wrappers.push($wrapper);
1657                                }
1658                                if( ($action==='readonly') && (!$wrapper.classList.contains('super-readonly')) ){
1659                                    $hide_wrappers.push($wrapper);
1660                                }
1661                            }else{
1662                                if( ($action==='show') && ($wrapper.classList.contains('super-conditional-visible')) ){
1663                                    $changed_wrappers.push($wrapper);
1664                                    $hide_wrappers.push($wrapper);
1665                                }
1666                                if( ($action==='hide') && (!$wrapper.classList.contains('super-conditional-visible')) ){
1667                                    $changed_wrappers.push($wrapper);
1668                                    $show_wrappers.push($wrapper);
1669                                }
1670                                if( ($action==='readonly') && ($wrapper.classList.contains('super-readonly')) ){
1671                                    $show_wrappers.push($wrapper);
1672                                }
1673                            }
1674                        }else{
1675                            if($match_found!==0){
1676                                if( ($action==='show') && (!$wrapper.classList.contains('super-conditional-visible')) ){
1677                                    $changed_wrappers.push($wrapper);
1678                                    $show_wrappers.push($wrapper);
1679                                }
1680                                if( ($action==='hide') && ($wrapper.classList.contains('super-conditional-visible')) ){
1681                                    $changed_wrappers.push($wrapper);
1682                                    $hide_wrappers.push($wrapper);
1683                                }
1684                                if( ($action==='readonly') && (!$wrapper.classList.contains('super-readonly')) ){
1685                                    $hide_wrappers.push($wrapper);
1686                                }
1687                            }else{
1688                                if( ($action==='show') && ($wrapper.classList.contains('super-conditional-visible')) ){
1689                                    $changed_wrappers.push($wrapper);
1690                                    $hide_wrappers.push($wrapper);
1691                                }
1692                                if( ($action==='hide') && (!$wrapper.classList.contains('super-conditional-visible')) ){
1693                                    $changed_wrappers.push($wrapper);
1694                                    $show_wrappers.push($wrapper);
1695                                }
1696                                if( ($action==='readonly') && ($wrapper.classList.contains('super-readonly')) ){
1697                                    $show_wrappers.push($wrapper);
1698                                }
1699                            }
1700                        }
1701                        
1702                        // Check if we are conditionally validating a field
1703                        if($is_validate){
1704                            // Hide wrappers
1705                            Object.keys($hide_wrappers).forEach(function() {
1706                                $validation_error = true;
1707                            });
1708                        }else{
1709                            Object.keys($hide_wrappers).forEach(function(key) {
1710                                if($hide_wrappers[key].classList.contains('super-error-active')){
1711                                    $hide_wrappers[key].classList.remove('super-error-active');
1712                                }
1713                                var $innerNodes = $hide_wrappers[key].querySelectorAll('.super-error-active');
1714                                Object.keys($innerNodes).forEach(function(ikey) {
1715                                    $innerNodes[ikey].classList.remove('super-error-active');
1716                                });
1717                                // Check if parent is multi-part, tab, accordion, if so remove error class if no errors found
1718                                // Remove error class from Multi-part if no more errors where found
1719                                SUPER.remove_error_status_parent_layout_element($, $hide_wrappers[key]);
1720                            });
1721                            if($action=='readonly'){
1722                                // Hide wrappers
1723                                Object.keys($hide_wrappers).forEach(function(key) {
1724                                    $hide_wrappers[key].classList.add('super-readonly');
1725                                });
1726                                // Show wrappers
1727                                Object.keys($show_wrappers).forEach(function(key) {
1728                                    $show_wrappers[key].classList.remove('super-readonly');
1729                                });
1730                            }else{
1731                                // Hide wrappers
1732                                Object.keys($hide_wrappers).forEach(function(key) {
1733                                    $hide_wrappers[key].classList.add('super-conditional-hidden');
1734                                    $hide_wrappers[key].classList.remove('super-conditional-visible');
1735                                });
1736                                // Show wrappers
1737                                Object.keys($show_wrappers).forEach(function(key) {
1738                                    $show_wrappers[key].classList.remove('super-conditional-hidden');
1739                                    $show_wrappers[key].classList.add('super-conditional-visible');
1740                                    // Make sure signatures resizes/refreshes after becoming visible
1741                                    if(typeof SUPER.refresh_signatures === 'function'){
1742                                        SUPER.refresh_signatures('', $show_wrappers[key]);
1743                                    }
1744                                    // Resize toggle elements
1745                                    SUPER.resize_toggle_element($show_wrappers[key]);
1746                                    // Reposition slider dragger
1747                                    SUPER.reposition_slider_element($show_wrappers[key], true);
1748                                });
1749                                // @since 2.4.0 - call change blur hook on the fields inside the update column
1750                                Object.keys($changed_wrappers).forEach(function(key) {
1751                                    $inner = $changed_wrappers[key].querySelectorAll('.super-shortcode-field');
1752                                    Object.keys($inner).forEach(function(key) {
1753                                        $parent = $inner[key].closest('.super-shortcode');
1754                                        $element = $parent.querySelector('div[data-fields]');
1755                                        if($element){
1756                                            $data_fields = $element.dataset.fields;
1757                                            if($data_fields){
1758                                                $data_fields = $data_fields.split('}');
1759                                                Object.keys($data_fields).forEach(function(key) {
1760                                                    v = $data_fields[key];
1761                                                    if(v!==''){
1762                                                        v = v.replace('{','');
1763                                                        $field = SUPER.field(args.form, v);
1764                                                        if($field){
1765                                                            SUPER.after_field_change_blur_hook({el: $field, form: args.form, skip: true});
1766                                                        }
1767                                                    }
1768                                                });
1769                                            }
1770                                        }
1771                                        SUPER.after_field_change_blur_hook({el: $inner[key], form: args.form, skip: true});
1772                                    });
1773                                });
1774                            }
1775                        }
1776                    }
1777                }
1778            }
1779        });
1780
1781        if($is_validate){
1782            return $validation_error;
1783        }
1784        
1785        // @since 2.3.0 - update conditional logic and other variable fields based on the updated variable field
1786        $.each($updated_variable_fields, function( index, field ) {
1787            if(field.value===''){
1788                field.closest('.super-shortcode').classList.remove('super-filled');
1789            }else{
1790                field.closest('.super-shortcode').classList.add('super-filled');
1791            }
1792            SUPER.after_field_change_blur_hook({el: field});
1793        });
1794
1795        // @since 1.4
1796        if(!$is_variable){
1797            SUPER.update_variable_fields(args);
1798        }
1799    };
1800
1801    // @since 5.0.120 Filter foreach() statements
1802    SUPER.filter_foreach_statements = function($htmlElement, $counter, $depth, $html, $fileLoopRows, formId, originalFormReference){
1803        // Before we continue replace any foreach(file_upload_fieldname)
1804        var regex = /(<%|{|foreach\()([-_a-zA-Z0-9]{1,})(\[.*?\])?(_\d{1,})?(?:;([a-zA-Z0-9]{1,}))?(%>|}|\):)/g;
1805        var m;
1806        var $originalHtml = $html;
1807        var replaceTagsWithValue = {};
1808        //replaceTagsWithValue['<%counter%>'] = '';
1809        while ((m = regex.exec($html)) !== null) {
1810            // This is necessary to avoid infinite loops with zero-width matches
1811            if (m.index === regex.lastIndex) {
1812                regex.lastIndex++;
1813            }
1814            var $o = (m[0] ? m[0] : ''); // original name
1815            var $start = (m[1] ? m[1] : ''); // starts with e.g: foreach( or <%
1816            var $n = (m[2] ? m[2] : ''); // name
1817            var $d = (m[3] ? m[3] : ''); // depth
1818            var $dr = $d.replace(/[0-9]/g, "0") // depth reset to 0
1819            var $c = (m[4] ? m[4] : ''); // counter e.g: _2 or _3 etc.
1820            var $s = (m[5] ? m[5] : ''); // suffix
1821            if($s!=='') $s = ';'+$s;
1822            var $end = (m[6] ? m[6] : ''); // ends with e.g: ): or %>
1823            var fieldType = SUPER.get_field_type(originalFormReference, $n+$d);
1824            if(fieldType.type==='file'){
1825                var childParentIndex = $($htmlElement).parents('.super-duplicate-column-fields:eq(0)').index();
1826                if(childParentIndex>0){
1827                    $html = $html.replaceAll('foreach('+$n+$d+')', 'foreach('+$n+$d+'_'+(childParentIndex+1)+')');
1828                }
1829            }
1830        }
1831        // var findChildField = $(currentFieldParent).find('.super-shortcode-field[data-oname="'+$n+'"][data-olevels="'+$dr+'"]').first();
1832        // if(findChildField.length===0) continue;
1833        // var allParents = $(findChildField).parents('.super-duplicate-column-fields');
1834        // var childParentIndex = $(findChildField).parents('.super-duplicate-column-fields:eq(0)').index();
1835        // var suffix = [];
1836        // $(allParents).each(function(key){
1837        //     var currentParentIndex = $(this).index();  // e.g: 0, 1, 2
1838        //     if(key===0 && currentParentIndex===0){
1839        //         return;
1840        //     }
1841        //     suffix.push('['+currentParentIndex+']');
1842        // });
1843        // if(childParentIndex!==0){
1844        //     delete suffix[0];
1845        // }
1846        // var levels = suffix.reverse().join('');
1847        // if(childParentIndex!==0){
1848        //     replaceTagsWithValue[$o] = $start+$n+levels+'_'+(childParentIndex+1)+$s+$end;
1849        //     continue;
1850        // }
1851        // replaceTagsWithValue[$o] = $start+$n+levels+$c+$s+$end;
1852
1853
1854        if(typeof $counter === 'undefined') $counter = 0;
1855        if(typeof $fileLoopRows === 'undefined') $fileLoopRows = [];
1856        // Check if endforeach; was found otherwise skip it
1857        if($html.indexOf('endforeach;')===-1) {
1858            return $html;  
1859        }
1860        var $chars = $html.split(''),
1861            $prefix = '', // any content before loop starts
1862            $innerContent = '', // any content inside the loop
1863            $suffix = '', // any content after loop ends
1864            $captureSuffix = false,
1865            $captureFieldname = false,
1866            $captureContent = false,
1867            $fieldName = '',
1868            $skipUpTo = 0,
1869            $k,
1870            $v;
1871
1872        Object.keys($chars).forEach(function(k) {
1873            $k = parseInt(k, 10);
1874            $v = $chars[k];
1875            if($skipUpTo!==0 && $skipUpTo > k){
1876                return;
1877            }
1878            if($captureSuffix){
1879                $suffix += $v;
1880                return;
1881            }
1882            if($captureFieldname){
1883                if( ($chars[$k] && $chars[$k]===')') &&
1884                    ($chars[$k+1] && $chars[$k+1]===':') ) {
1885                    $captureFieldname = false;
1886                    $captureSuffix = false;
1887                    $captureContent = true;
1888                    $skipUpTo = $k+2; // Skip up to key 8
1889                    return;
1890                }else{
1891                    $fieldName += $v;
1892                }
1893            }
1894            if($captureContent){
1895                if((($chars[$k]) && $chars[$k]==='f') &&
1896                (($chars[$k+1]) && $chars[$k+1]==='o') &&
1897                (($chars[$k+2]) && $chars[$k+2]==='r') &&
1898                (($chars[$k+3]) && $chars[$k+3]==='e') &&
1899                (($chars[$k+4]) && $chars[$k+4]==='a') &&
1900                (($chars[$k+5]) && $chars[$k+5]==='c') &&
1901                (($chars[$k+6]) && $chars[$k+6]==='h') &&
1902                (($chars[$k+7]) && $chars[$k+7]==='(')){
1903                    $depth++;
1904                }
1905                if((($chars[$k]) && $chars[$k]==='e') &&
1906                (($chars[$k+1]) && $chars[$k+1]==='n') &&
1907                (($chars[$k+2]) && $chars[$k+2]==='d') &&
1908                (($chars[$k+3]) && $chars[$k+3]==='f') &&
1909                (($chars[$k+4]) && $chars[$k+4]==='o') &&
1910                (($chars[$k+5]) && $chars[$k+5]==='r') &&
1911                (($chars[$k+6]) && $chars[$k+6]==='e') &&
1912                (($chars[$k+7]) && $chars[$k+7]==='a') &&
1913                (($chars[$k+8]) && $chars[$k+8]==='c') &&
1914                (($chars[$k+9]) && $chars[$k+9]==='h') &&
1915                (($chars[$k+10]) && $chars[$k+10]===';')){
1916                    $depth--;
1917                    $captureFieldname = false;
1918                    $captureContent = true;
1919                    $captureSuffix = false;
1920                    if($depth===0){
1921                        // foreach ended
1922                        // capture suffix
1923                        $captureFieldname = false;
1924                        $captureContent = false;
1925                        $captureSuffix = true;
1926                        $skipUpTo = $k+11; // Skip up to key 11
1927                        return;
1928                    }
1929                    // capture inner content including inner foreach items
1930                    $innerContent += $v;
1931                    return;
1932                }
1933                // capture inner content including inner foreach items
1934                $innerContent += $v;
1935            }
1936            if($depth===0){
1937                if((($chars[$k]) && $chars[$k]==='f') &&
1938                (($chars[$k+1]) && $chars[$k+1]==='o') &&
1939                (($chars[$k+2]) && $chars[$k+2]==='r') &&
1940                (($chars[$k+3]) && $chars[$k+3]==='e') &&
1941                (($chars[$k+4]) && $chars[$k+4]==='a') &&
1942                (($chars[$k+5]) && $chars[$k+5]==='c') &&
1943                (($chars[$k+6]) && $chars[$k+6]==='h') &&
1944                (($chars[$k+7]) && $chars[$k+7]==='(')){
1945                    $depth++;
1946                    $captureSuffix = false;
1947                    $captureContent = false;
1948                    $captureFieldname = true;
1949                    $skipUpTo = $k+8; // Skip up to key 8
1950                    return;
1951                }else{
1952                    $prefix += $v; // any content before loop starts
1953                }
1954            }else{
1955                // Depth is not 0
1956            }
1957        });
1958        var $original = $innerContent,
1959            $row = $innerContent,
1960            $field_name = $fieldName,
1961            $splitName = $field_name.split(';'),
1962            $field_name = $splitName[0],
1963            $value_n = ($splitName[1] ? $splitName[1] : ''),
1964            $original_field_name = $field_name,
1965            $i = 1,
1966            $ii = 0,
1967            $rows = '';
1968
1969        var currentField = SUPER.field(originalFormReference, $field_name);
1970        var fieldType = SUPER.get_field_type(originalFormReference, $field_name);
1971        while( currentField ) {
1972            var currentFieldParent = $(currentField).parents('.super-duplicate-column-fields:eq(0)');
1973            var regex = /(<%|{|foreach\()([-_a-zA-Z0-9]{1,})(\[.*?\])?(_\d{1,})?(?:;([a-zA-Z0-9]{1,}))?(%>|}|\):)/g;
1974            var m;
1975            $row = $original;
1976            var replaceTagsWithValue = {};
1977            //replaceTagsWithValue['<%counter%>'] = '';
1978            while ((m = regex.exec($row)) !== null) {
1979                // This is necessary to avoid infinite loops with zero-width matches
1980                if (m.index === regex.lastIndex) {
1981                    regex.lastIndex++;
1982                }
1983                var $o = (m[0] ? m[0] : ''); // original name
1984                var $start = (m[1] ? m[1] : ''); // starts with e.g: foreach( or <%
1985                var $n = (m[2] ? m[2] : ''); // name
1986                var $d = (m[3] ? m[3] : ''); // depth
1987                var $dr = $d.replace(/[0-9]/g, "0") // depth reset to 0
1988                var $c = (m[4] ? m[4] : ''); // counter e.g: _2 or _3 etc.
1989                var $s = (m[5] ? m[5] : ''); // suffix
1990                if($s!=='') $s = ';'+$s;
1991                var $end = (m[6] ? m[6] : ''); // ends with e.g: ): or %>
1992                var fieldType = SUPER.get_field_type(originalFormReference, $field_name);
1993                //replaceTagsWithValue[$o] = $start+$n+levels+$c+$s+$end;
1994                //var dynamicColumnIndex = $(fieldType.field).parents('.super-duplicate-column-fields:eq(0)').index()+1;
1995                //replaceTagsWithValue['<%counter%>'] = dynamicColumnIndex;
1996                if(fieldType.type==='file'){
1997                    // Loop over all current files
1998                    if(SUPER.files[formId]){
1999                        var files = SUPER.files[formId][$field_name];
2000                        if(!files){
2001                            $row = '';
2002                        }else{
2003                            if(files.length===0) $row = '';
2004                            //$rows = '';
2005                            for(var x=0; x<files.length; x++){
2006                                replaceTagsWithValue = [];
2007                                replaceTagsWithValue['<%counter%>'] = (x+1);
2008                                // This retrieves the total amount of files (uploaded and yet to be uploaded)
2009                                var totalFiles = currentField.closest('.super-shortcode').querySelectorAll('.super-fileupload-files > div').length;
2010                                replaceTagsWithValue['<%total_files%>'] = totalFiles;
2011                                replaceTagsWithValue['<%total%>'] = totalFiles;
2012                                replaceTagsWithValue['<%count%>'] = totalFiles;
2013                                // This retrieves the total amount of files selected for upload (yet to be uploaded files)
2014                                totalFiles = currentField.closest('.super-shortcode').querySelectorAll('.super-fileupload-files > div:not(.super-uploaded)').length;
2015                                replaceTagsWithValue['<%new_count%>'] = totalFiles;
2016                                // This retrieves the total amount of files that are already uploaded previously
2017                                totalFiles = currentField.closest('.super-shortcode').querySelectorAll('.super-fileupload-files > div.super-uploaded').length;
2018                                replaceTagsWithValue['<%existing_count%>'] = totalFiles;
2019                                // Field label
2020                                replaceTagsWithValue['<%label%>'] = currentField.dataset.email;
2021                                replaceTagsWithValue['<%email%>'] = currentField.dataset.email;
2022                                replaceTagsWithValue['<%email_label%>'] = currentField.dataset.email;
2023                                // Name
2024                                replaceTagsWithValue['<%name%>'] = files[x].name;
2025                                replaceTagsWithValue['<%basename%>'] = files[x].name;
2026                                // URL
2027                                replaceTagsWithValue['<%url%>'] = files[x].url;
2028                                replaceTagsWithValue['<%src%>'] = files[x].url;
2029                                // Size
2030                                replaceTagsWithValue['<%filesize%>'] = files[x].size;
2031                                replaceTagsWithValue['<%size%>'] = files[x].size;
2032                                // Type
2033                                replaceTagsWithValue['<%type%>'] = files[x].type;
2034                                replaceTagsWithValue['<%mime%>'] = files[x].type;
2035                                // Field Label
2036                                replaceTagsWithValue['<%label%>'] = files[x].label;
2037                                // Extension
2038                                var f = SUPER.get_file_name_and_extension(files[x].name);
2039                                replaceTagsWithValue['<%ext%>'] = f.ext.toLowerCase();
2040                                replaceTagsWithValue['<%extension%>'] = f.ext.toLowerCase();
2041                                // Attachment
2042                                replaceTagsWithValue['<%attachment_id%>'] = files[x].name;
2043                                replaceTagsWithValue['<%attachment%>'] = files[x].name;
2044                                var key;
2045                                $row = $original;
2046                                for(key in replaceTagsWithValue) {
2047                                    $row = $row.replaceAll(key, replaceTagsWithValue[key]);
2048                                }
2049                                $rows += $row;
2050                            }
2051                            replaceTagsWithValue = [];
2052                            $row = '';
2053                        }
2054                    }
2055                }else{
2056                    var findChildField = $(currentFieldParent).find('.super-shortcode-field[data-oname="'+$n+'"][data-olevels="'+$dr+'"]').first();
2057                    if(findChildField.length===0) {
2058                        continue;
2059                    } 
2060                    var allParents = $(findChildField).parents('.super-duplicate-column-fields');
2061                    var childParentIndex = $(findChildField).parents('.super-duplicate-column-fields:eq(0)').index();
2062                    var suffix = [];
2063                    $(allParents).each(function(key){
2064                        var currentParentIndex = $(this).index();  // e.g: 0, 1, 2
2065                        if(key===0 && currentParentIndex===0){
2066                            return;
2067                        }
2068                        suffix.push('['+currentParentIndex+']');
2069                    });
2070                    if(childParentIndex!==0){
2071                        delete suffix[0];
2072                    }
2073                    var levels = suffix.reverse().join('');
2074                    if(childParentIndex!==0){
2075                        //replaceTagsWithValue['<%counter%>'] = (childParentIndex+1);
2076                        replaceTagsWithValue[$o] = $start+$n+levels+'_'+(childParentIndex+1)+$s+$end;
2077                        if($start!=='foreach('){
2078                            replaceTagsWithValue['<%counter%>'] = $start+$n+levels+'_'+(childParentIndex+1)+';index'+$end;
2079                        }
2080                        continue;
2081                    }
2082                    replaceTagsWithValue[$o] = $start+$n+levels+$c+$s+$end;
2083                    if($start!=='foreach('){
2084                        replaceTagsWithValue['<%counter%>'] = $start+$n+levels+$c+';index'+$end;
2085                    }
2086                    //$row = $row.replaceAll('<%counter%>', '<%'+$field_name+';index%>');
2087                }
2088            }
2089            var key;
2090            for(key in replaceTagsWithValue) {
2091                $row = $row.replaceAll(key, replaceTagsWithValue[key]);
2092            }
2093            if($htmlElement.closest('.super-duplicate-column-fields')){
2094                $rows += $row;
2095                break;
2096            }else{
2097                $i++;
2098                $field_name = $original_field_name+'_'+$i;
2099                currentField = SUPER.field(originalFormReference, $field_name);
2100                if(currentField){
2101                    //$row = $row.replaceAll('<%counter%>', '<%'+$field_name+';index%>');
2102                    //var dynamicColumnIndex = $(currentField).parents('.super-duplicate-column-fields:eq(0)').index()+1;
2103                    //$row = $row.replaceAll('<%counter%>', dynamicColumnIndex);
2104                }
2105                $rows += $row;
2106            }
2107        }
2108
2109        $rows = $prefix + $rows + $suffix;
2110        $innerContent = $innerContent.split($original).join($rows);
2111        $ii++;
2112        $counter++;
2113        return SUPER.filter_foreach_statements($htmlElement, $counter, $depth, $innerContent, $fileLoopRows, formId, originalFormReference);
2114    };
2115
2116    // @since 4.6.0 Filter if() statements
2117    SUPER.filter_if_statements = function($html){
2118        // If does not contain 'endif;' we can just return the `$html` without doing anything
2119        if($html.indexOf('endif;')===-1) {
2120            return $html;  
2121        }
2122        var re = /\s*['|"]?(.*?)['|"]?\s*(==|!=|>=|<=|>|<|\?\?|!\?\?)\s*['|"]?(.*?)['|"]?\s*$/,
2123            m,
2124            v,
2125            show_counter,
2126            method,
2127            conditions,
2128            array = $html.split(''),
2129            if_index = 0,
2130            skip_up_to = 0,
2131            capture_elseifcontent = false,
2132            capture_conditions = false,
2133            capture_suffix = false,
2134            statements = [],
2135            prefix = '',
2136            first_if_found = false,
2137            depth = 0,
2138            result = '',
2139            i,
2140            ci,
2141            cv,
2142            v1,
2143            v2,
2144            show,
2145            operator;
2146
2147        Object.keys(array).forEach(function(k) {
2148            k = parseInt(k, 10);
2149            v = array[k];
2150            if(skip_up_to!==0 && skip_up_to > k){
2151                return;
2152            }
2153            if(!SUPER.if_match(array, k) && first_if_found===false ) {
2154                prefix += v;
2155            }else{
2156                first_if_found = true;
2157                if(capture_conditions){
2158                    if( ((typeof array[k] !== 'undefined') && array[k]===')') && 
2159                        ((typeof array[k+1] !== 'undefined') && (array[k+1]===':')) ) {
2160                        capture_elseifcontent = false;
2161                        capture_suffix = false;
2162                        capture_conditions = false;
2163                        skip_up_to = k+2;
2164                        return;
2165                    }
2166                    if(typeof statements[if_index] === 'undefined'){
2167                        statements[if_index] = [];
2168                    }
2169                    if(typeof statements[if_index].conditions === 'undefined'){
2170                        statements[if_index].conditions = '';
2171                    }
2172                    statements[if_index].conditions += v;
2173                    return;
2174                }
2175                if(depth===0){
2176                    if(SUPER.if_match(array, k)){
2177                        if_index++;
2178                        depth++;
2179                        capture_elseifcontent = false;
2180                        capture_suffix = false;
2181                        capture_conditions = true;
2182                        skip_up_to = k+3;
2183                        return;
2184                    }
2185                }else{
2186                    if(SUPER.if_match(array, k)){
2187                        depth++;
2188                    }
2189                }
2190                if( ((typeof array[k] !== 'undefined') && array[k]==='e') && 
2191                    ((typeof array[k+1] !== 'undefined') && array[k+1]==='n') && 
2192                    ((typeof array[k+2] !== 'undefined') && array[k+2]==='d') && 
2193                    ((typeof array[k+3] !== 'undefined') && array[k+3]==='i') && 
2194                    ((typeof array[k+4] !== 'undefined') && array[k+4]==='f') && 
2195                    ((typeof array[k+5] !== 'undefined') && array[k+5]===';') ) {
2196                    depth--;
2197                    if(depth===0){
2198                        capture_elseifcontent = false;
2199                        capture_conditions = false;
2200                        capture_suffix = true;
2201                        skip_up_to = k+6;
2202                        return;
2203                    }
2204                }
2205                if(depth==1){
2206                    if( ((typeof array[k] !== 'undefined') && array[k]==='e') && 
2207                        ((typeof array[k+1] !== 'undefined') && array[k+1]==='l') &&
2208                        ((typeof array[k+2] !== 'undefined') && array[k+2]==='s') &&
2209                        ((typeof array[k+3] !== 'undefined') && array[k+3]==='e') &&
2210                        ((typeof array[k+4] !== 'undefined') && array[k+4]==='i') &&
2211                        ((typeof array[k+5] !== 'undefined') && array[k+5]==='f') &&
2212                        ((typeof array[k+6] !== 'undefined') && array[k+6]===':') ) {
2213                        capture_elseifcontent = true;
2214                        capture_suffix = false;
2215                        capture_conditions = false;
2216                        skip_up_to = k+7;
2217                        return;
2218                    }
2219                }
2220                if(depth===0 && capture_suffix){
2221                    if(typeof statements[if_index].suffix === 'undefined') statements[if_index].suffix = ''; 
2222                    statements[if_index].suffix += v;
2223                    return;
2224                }
2225                if(depth>=1 && capture_elseifcontent){
2226                    if(typeof statements[if_index].elseif_content === 'undefined') statements[if_index].elseif_content = '';
2227                    statements[if_index].elseif_content += v;
2228                    return;
2229                }
2230                if(depth>=1){
2231                    if(typeof statements[if_index].inner_content === 'undefined') statements[if_index].inner_content = '';
2232                    statements[if_index].inner_content += v;
2233                    return;
2234                }
2235            }
2236        });
2237
2238        for (i = 0; i < statements.length; i++) { 
2239            if(typeof statements[i]==='undefined') continue;
2240            v = statements[i];
2241            show_counter = 0;
2242            method = '&&';
2243            conditions = v.conditions.split('&&');
2244            if(conditions.length==1){
2245                conditions = v.conditions.split('||');
2246                if(conditions.length>1){
2247                    method = '||';
2248                }
2249            }
2250            for (ci = 0; ci < conditions.length; ci++) {
2251                if(typeof conditions[ci]==='undefined') continue;
2252                cv = conditions[ci];
2253                if ((m = re.exec(cv)) !== null) {
2254                    v1 = m[1];
2255                    operator = m[2];
2256                    v2 = m[3];
2257                    show = false;
2258                    if(operator==='==' && v1==v2) show = true;
2259                    if(operator==='!=' && v1!=v2) show = true;
2260                    if(operator==='>=' && v1>=v2) show = true;
2261                    if(operator==='<=' && v1<=v2) show = true;
2262                    if(operator==='>' && v1>v2) show = true;
2263                    if(operator==='<' && v1<v2) show = true;
2264                    if(operator==='??' && v1.indexOf(v2) > -1) show = true;
2265                    if(operator==='!??' && v1.indexOf(v2) === -1) show = true;
2266                    if(show){
2267                        show_counter++;
2268                    }
2269                }
2270            }            
2271            if(method=='||' && show_counter>0){
2272                if(typeof v.inner_content !== 'undefined' && v.inner_content!=='') {
2273                    result += SUPER.filter_if_statements(v.inner_content);
2274                }
2275            }else{
2276                if(conditions.length===show_counter){
2277                    if(typeof v.inner_content !== 'undefined' && v.inner_content!=='') {
2278                        result += SUPER.filter_if_statements(v.inner_content);
2279                    }
2280                }else{
2281                    if(typeof v.elseif_content !== 'undefined' && v.elseif_content!=='') {
2282                        result += SUPER.filter_if_statements(v.elseif_content);
2283                    }
2284                }
2285            }
2286            if(typeof v.suffix !== 'undefined' && v.suffix!=='') {
2287                result += v.suffix;
2288            }
2289        }
2290        return prefix+result;
2291    };
2292
2293    // @since 5.0.120 - Find foreach() match
2294    SUPER.foreach_match = function($array, $k){
2295        if( ((typeof $array[$k] !== 'undefined') && $array[$k]==='f') && 
2296            ((typeof $array[$k+1] !== 'undefined') && $array[$k+1]==='o') && 
2297            ((typeof $array[$k+2] !== 'undefined') && $array[$k+2]==='r') && 
2298            ((typeof $array[$k+3] !== 'undefined') && $array[$k+3]==='e') && 
2299            ((typeof $array[$k+4] !== 'undefined') && $array[$k+4]==='a') && 
2300            ((typeof $array[$k+5] !== 'undefined') && $array[$k+5]==='c') && 
2301            ((typeof $array[$k+6] !== 'undefined') && $array[$k+6]==='h') && 
2302            ((typeof $array[$k+7] !== 'undefined') && $array[$k+7]==='(') ) {
2303            return true;
2304        }
2305        return false;       
2306    };
2307    // @since 4.6.0 - Find if() match
2308    SUPER.if_match = function($array, $k){
2309        if( ((typeof $array[$k] !== 'undefined') && $array[$k]==='i') && 
2310            ((typeof $array[$k+1] !== 'undefined') && $array[$k+1]==='f') && 
2311            ((typeof $array[$k+2] !== 'undefined') && $array[$k+2]==='(') ) {
2312            return true;
2313        }
2314        return false;       
2315    };
2316
2317    // @since 1.4 - Update variable fields
2318    SUPER.update_variable_fields = function(args){
2319        if(typeof args.el !== 'undefined'){
2320            args.conditionalLogic = args.form.querySelectorAll('.super-variable-conditions[data-fields*="{'+SUPER.get_original_field_name(args.el)+'}"]');
2321        }else{
2322            args.conditionalLogic = args.form.querySelectorAll('.super-variable-conditions');
2323        }
2324        if(typeof args.conditionalLogic !== 'undefined'){
2325            if(args.conditionalLogic.length!==0){
2326                SUPER.conditional_logic.loop(args);
2327            }
2328        }
2329    };
2330
2331    // @since 3.0.0 - replace variable field {tags} with actual field values
2332    SUPER.update_variable_fields.replace_tags = function(args){
2333        if(args.form.classList.contains('super-generating-pdf')){
2334            // Must reference to original form (which is currently the placeholder)
2335            var formId = parseInt(args.form.id.replace('super-form-', ''), 10);
2336            args.form = document.querySelector('#super-form-'+formId+'-placeholder');
2337        }
2338        if(typeof args.defaultValues === 'undefined') args.defaultValues = false;
2339        if(typeof args.bwc === 'undefined') args.bwc = false;
2340        if(typeof args.target === 'undefined') args.target = null;
2341        if(typeof args.value !== 'undefined' && args.bwc){
2342            // If field name is empty do nothing
2343            if(args.value==='') return '';
2344            // If field name doesn't contain any curly braces, then append and prepend them and continue;
2345            if(args.value.indexOf('{')===-1) {
2346                args.value = '{'+args.value+'}';   
2347            } 
2348        }
2349        var $array = [],
2350            $value = '',
2351            $i = 0,
2352            $name,
2353            $old_name,
2354            $options,
2355            $value_type,
2356            $value_n,
2357            $default_value,
2358            $parent,
2359            $text_field,
2360            $sum,
2361            $selected,
2362            $new_value,
2363            $match,
2364            key,
2365            $values,
2366            $element,
2367            $regex = /{([^\\\/\s"'+]*?)}/g;
2368
2369        while (($match = $regex.exec(args.value)) !== null) {
2370            if($match[0]==='{}') continue;
2371            $array[$i] = $match[1];
2372            $i++;
2373        }
2374        for ($i = 0; $i < $array.length; $i++) {
2375            $element = undefined; // @important!
2376            $name = $array[$i];
2377            if($name=='pdf_page' && typeof SUPER.pdf_tags !== 'undefined' ){
2378                return SUPER.pdf_tags.pdf_page;
2379            }
2380            if($name=='pdf_total_pages' && typeof SUPER.pdf_tags !== 'undefined' ){
2381                return SUPER.pdf_tags.pdf_total_pages;
2382            }
2383            if($name=='dynamic_column_counter'){
2384                
2385                if(args.target){
2386                    
2387                    args.value = $(args.target).parents('.super-duplicate-column-fields:eq(0)').index()+1;
2388                    return args.value;
2389                }else{
2390                    if(args.currentTextarea){
2391                        
2392                        args.value = $(args.currentTextarea).parents('.super-duplicate-column-fields:eq(0)').index()+1;
2393                        return args.value;
2394                    }
2395                }
2396            }
2397            
2398            // @since 3.2.0 - Compatibility with advanced tags {option;2;int}
2399            $old_name = $name;
2400            $options = $name.toString().split(';');
2401            $name = $options[0]; // this is the field name e.g: {option;2} the variable $name would contain: option
2402            $value_type = 'var'; // return field value as 'var' or 'int' {field;2;var} to return varchar or {field;2;int} to return integer
2403
2404            if(typeof $options[1] === 'undefined'){
2405                $value_n = 0;
2406            }else{
2407                $value_n = $options[1];
2408                // if the index value is 1 set it to 0 so it will return the value
2409                if($value_n==1){
2410                    $value_n = 0;
2411                }
2412                if(typeof $options[2] !== 'undefined'){
2413                    if( ($options[2]!='var') && ($options[2]!='int') ) {
2414                        $value_type = 'var';
2415                    }else{
2416                        $value_type = $options[2];
2417                    }
2418                }
2419            }
2420
2421            $default_value = '';
2422            if($value_type=='int'){
2423                $default_value = 0;
2424            }
2425
2426            // Use * for contains search
2427            // e.g: {field_*}
2428            // usage: $("input[id*='field_']")
2429            if($name.indexOf('*') >= 0){
2430                $name = $name.replace('*','');
2431                $element = SUPER.field(args.form, $name, '*');
2432            }
2433            // Use ^ for starts with search
2434            // e.g: {field_1_^}
2435            // usage: $("input[id^='field_1_']")
2436            if($name.indexOf('^') >= 0){
2437                $name = $name.replace('^','');
2438                $element = SUPER.field(args.form, $name, '^');
2439            }
2440            // Use $ for ends with search
2441            // e.g: {$_option}
2442            // usage: $("input[id$='_option']")
2443            if($name.indexOf('$') >= 0){
2444                $name = $name.replace('$','');
2445                $element = SUPER.field(args.form, $name, '$');
2446            }
2447            if(!$element) $element = SUPER.field(args.form, $name);
2448            if($element){
2449                if($element[0]) $element = $element[0];
2450                // Check if parent column or element is hidden (conditionally hidden)
2451                if( SUPER.has_hidden_parent($element) ) {
2452                    // Exclude conditionally
2453                    // Lets just replace the field name with 0 as a value
2454                    args.value = args.value.replace('{'+$old_name+'}', $default_value);
2455                }else{
2456                    $parent = $element.closest('.super-shortcode');
2457                    if( !$element ) {
2458                        // Lets just replace the field name with 0 as a value
2459                        args.value = args.value.replace('{'+$old_name+'}', $default_value);
2460                    }else{
2461                        $text_field = true;
2462                        $parent = $element.closest('.super-field');
2463
2464                        if($value_n=='index') {
2465                            var dynamicParentIndex = $($element).parents('.super-duplicate-column-fields:eq(0)').index();
2466                            args.value = args.value.replace('{'+$old_name+'}', dynamicParentIndex+1);
2467                            continue;
2468                        }
2469
2470                        // Check if international phonenumber field
2471                        if($parent.classList.contains('super-int-phone-field')){
2472                            $text_field = false;
2473                            //var input = document.querySelector('#phone');
2474                            var intPhone = window.superTelInputGlobals.getInstance($element);
2475                            $value = intPhone.getNumber();
2476                        }
2477
2478                        // Check if dropdown field
2479                        if($parent.classList.contains('super-dropdown')){
2480                            $text_field = false;
2481                            $sum = '';
2482
2483                            // @since 3.2.0 - check if we want to return integer for this {tag}  e.g: {field;2;int}
2484                            if($value_type=='int') {
2485                                $sum = 0;
2486                            }
2487
2488                            $selected = $parent.querySelectorAll('.super-dropdown-list .super-item.super-active:not(.super-placeholder)');
2489                            for (key = 0; key < $selected.length; key++) {
2490                                // @since 3.6.0 - check if we want to return the label instead of a value
2491                                if($value_n=='label'){
2492                                    $new_value = $selected[key].textContent;
2493                                }else{
2494                                    $new_value = $selected[key].dataset.value.toString().split(';');
2495                                    if($value_n===0){
2496                                        $new_value = $new_value[0];
2497                                    }else{
2498                                        // return default value if undefined
2499                                        if(typeof $new_value[($value_n-1)]==='undefined'){
2500                                            $new_value = $new_value[0];
2501                                        }else{
2502                                            $new_value = $new_value[($value_n-1)];
2503                                        }
2504                                    }
2505                                }
2506                                if(typeof $new_value==='undefined'){
2507                                    $new_value = '';
2508                                }
2509
2510                                // @since 3.2.0 - check if we want to return integer for this {tag}  e.g: {field;2;int}
2511                                if($value_type=='int'){
2512                                    $sum += parseFloat($new_value);
2513                                }else{
2514                                    if($sum===''){
2515                                        $sum += $new_value;
2516                                    }else{
2517                                        $sum += ','+$new_value;
2518                                    }
2519                                }                         
2520                            }
2521                            $value = $sum;
2522                        }
2523                        // Check if checkbox field
2524                        if($parent.classList.contains('super-checkbox')){
2525                            $text_field = false;
2526                            $selected = $parent.querySelectorAll('.super-field-wrapper .super-item.super-active');
2527                            $values = '';
2528                            for (key = 0; key < $selected.length; key++) {
2529                                // @since 3.6.0 - check if we want to return the label instead of a value
2530                                if($value_n=='label'){
2531                                    if($values===''){
2532                                        $values += $selected[key].textContent;
2533                                    }else{
2534                                        $values += ', '+$selected[key].textContent;
2535                                    }
2536                                }else{
2537                                    if($values===''){
2538                                        $values += $selected[key].querySelector('input').value;
2539                                    }else{
2540                                        $values += ','+$selected[key].querySelector('input').value;
2541                                    }
2542                                }
2543                            }
2544                            $sum = '';
2545                            
2546                            // @since 3.2.0 - check if we want to return integer for this {tag}  e.g: {field;2;int}
2547                            if($value_type=='int') {
2548                                $sum = 0;
2549                            }
2550                            // @since 3.6.0 - check if we want to return the label instead of a value
2551                            if($value_n=='label'){
2552                                $sum += $values;
2553                            }else{
2554                                // @since 1.7.0 - checkbox compatibility with advanced tags like {field;2} etc.
2555                                var $new_value_array = $values.toString().split(',');
2556                                for (key = 0; key < $new_value_array.length; key++) {
2557                                    var v = $new_value_array[key].toString().split(';');
2558                                    if($value_n===0){
2559                                        $new_value = v[0];
2560                                    }else{
2561                                        $new_value = v[($value_n-1)];
2562                                    }
2563                                    if(typeof $new_value==='undefined'){
2564                                        $new_value = '';
2565                                    }
2566
2567                                    // @since 3.2.0 - check if we want to return integer for this {tag}  e.g: {field;2;int}
2568                                    if($value_type=='int'){
2569                                        $sum += parseFloat($new_value);
2570                                    }else{
2571                                        if($sum===''){
2572                                            $sum += $new_value;
2573                                        }else{
2574                                            $sum += ','+$new_value;
2575                                        }
2576                                    }
2577                                }
2578                            }
2579
2580                            $value = $sum;
2581                        }
2582                        // @since 1.7.0 - check for radio tags because it now can contain advanced tags like {field;2} etc.
2583                        if($parent.classList.contains('super-radio')){
2584                            $text_field = false;
2585                            $new_value = $element.value.toString().split(';');
2586                            if($value_n===0){
2587                                $new_value = $new_value[0];
2588                            }else{
2589                                $new_value = $new_value[($value_n-1)];
2590                            }
2591                            if(typeof $new_value==='undefined'){
2592                                $new_value = '';
2593                            }
2594
2595                            // @since 3.6.0 - check if we want to return the label instead of a value
2596                            if($value_n=='label'){
2597                                $new_value = '';
2598                                $selected = $element.closest('.super-field').querySelector('.super-field-wrapper .super-active');
2599                                if($selected){
2600                                    $new_value = $selected.textContent;
2601                                }
2602                            }
2603
2604                            // @since 3.2.0 - check if we want to return integer for this {tag}  e.g: {field;2;int}
2605                            if($value_type=='int'){
2606                                $value = parseFloat($new_value);
2607                            }else{
2608                                $value = ($new_value);
2609                            }
2610                        }
2611
2612                        // @since 3.8.0 - check if variable field and check for advanced tags like {field;2} etc.
2613                        if($parent.classList.contains('super-hidden')){
2614                            if($parent.dataset.conditionalVariableAction=='enabled'){
2615                                $text_field = false;
2616                                // Check contains semicolon as seperator, but also check if it doesn't contain a double quote,
2617                                // because this would indicate that the user is trying to create a serialized array,
2618                                // to update for instance meta data for a third party plugin
2619                                if($element.value.indexOf('"')!==-1){
2620                                    $value = $element.value;
2621                                }else{
2622                                    $new_value = $element.value.toString().split(';');
2623                                    if($value_n===0){
2624                                        $new_value = $new_value[0];
2625                                    }else{
2626                                        $new_value = $new_value[($value_n-1)];
2627                                    }
2628                                    if(typeof $new_value==='undefined'){
2629                                        $new_value = '';
2630                                    }
2631                                    if($value_type=='int'){
2632                                        $value = parseFloat($new_value);
2633                                    }else{
2634                                        $value = $new_value;
2635                                    }
2636                                }
2637                            }
2638                        }
2639                        
2640                        // Check if file upload field
2641                        if($parent.classList.contains('super-file')){
2642                            $text_field = false;
2643                            $new_value = '';
2644                            if($value_n===0) {
2645                                $value_n = 'allFileNames';
2646                            }
2647                            if($value_n=='email' || $value_n=='email_label' || $value_n=='emailLabel'){
2648                                $new_value = $parent.querySelector('.super-active-files').dataset.email;
2649                            }else{
2650                                var regex = /\[(\d*)\]/,
2651                                    i=0, // file index
2652                                    m, // regex matches
2653                                    totalFiles=0,
2654                                    files, formId = parseInt(args.form.id.replace('super-form-', ''), 10);
2655                                if($value_n=='allFileNames' || $value_n=='allFileUrls' || $value_n=='allFileLinks' ){
2656                                    var allFileNames = '';
2657                                    var allFileUrls = '';
2658                                    var allFileLinks = '';
2659                                    if(SUPER.files[formId]){
2660                                        if(SUPER.files[formId][$element.name]){
2661                                            files = SUPER.files[formId][$element.name];
2662                                            for(i=0; i<files.length; i++){
2663                                                if($value_n=='allFileNames') allFileNames += SUPER.html_encode(files[i].name)+'<br />';
2664                                                if($value_n=='allFileUrls') allFileUrls += SUPER.html_encode(files[i].url)+'<br />';
2665                                                if($value_n=='allFileLinks') allFileLinks += '<a href="'+SUPER.html_encode(files[i].url)+'">'+SUPER.html_encode(files[i].name)+'</a><br />';
2666                                            }
2667                                        }
2668                                    }
2669                                    if($value_n=='allFileNames'){ $new_value = allFileNames; }
2670                                    if($value_n=='allFileUrls'){ $new_value = allFileUrls; }
2671                                    if($value_n=='allFileLinks'){ $new_value = allFileLinks; }
2672                                }else{
2673                                    if(SUPER.files[formId]){
2674                                        if(SUPER.files[formId][$element.name]){
2675                                            files = SUPER.files[formId][$element.name]
2676                                            m = regex.exec($value_n);
2677                                            if(m) i = parseInt(m[1],10);
2678                                            // This retrieves the total amount of files (uploaded and yet to be uploaded)
2679                                            if($value_n.substring(0, 11)==='total_files' || $value_n.substring(0, 5)==='total' || $value_n.substring(0, 5)==='count'){
2680                                                totalFiles = $parent.querySelectorAll('.super-fileupload-files > div').length;
2681                                                $new_value = totalFiles;
2682                                            }
2683                                            // This retrieves the total amount of files selected for upload (yet to be uploaded files)
2684                                            if($value_n.substring(0, 9)==='new_count'){
2685                                                totalFiles = $parent.querySelectorAll('.super-fileupload-files > div:not(.super-uploaded)').length;
2686                                                $new_value = totalFiles;
2687                                            }
2688                                            // This retrieves the total amount of files that are already uploaded previously
2689                                            if($value_n.substring(0, 14)==='existing_count'){
2690                                                totalFiles = $parent.querySelectorAll('.super-fileupload-files > div.super-uploaded').length;
2691                                                $new_value = totalFiles;
2692                                            }
2693                                            if(files[i]) {
2694                                                if($value_n.substring(0, 3)==='url' || $value_n.substring(0, 3)==='src'){
2695                                                    $new_value = files[i].url;
2696                                                }
2697                                                if($value_n.substring(0, 4)==='size' || $value_n.substring(0, 8)==='filesize'){
2698                                                    $new_value = files[i].size;
2699                                                }
2700                                                if($value_n.substring(0, 4)==='type' || $value_n.substring(0, 4)==='mime'){
2701                                                    $new_value = files[i].type;
2702                                                }
2703                                                if($value_n.substring(0, 8)==='basename' || $value_n.substring(0, 4)==='name'){
2704                                                    $new_value = files[i].name;
2705                                                }
2706                                                if($value_n.substring(0, 3)==='ext'){
2707                                                    var f = SUPER.get_file_name_and_extension(files[i].name);
2708                                                    $new_value = f.ext.toLowerCase();
2709                                                }
2710                                            }
2711                                        }
2712                                    }
2713                                }
2714                            }
2715                            $value = $new_value;
2716                        }
2717
2718                        // Check if datepicker field
2719                        if($parent.classList.contains('super-date')){
2720                            $text_field = false;
2721                            $value = $element.value;
2722                            if($value_n === 'day' || $value_n === 'month' || $value_n === 'year' || $value_n === 'timestamp'){
2723                                if($value_n === 'day'){
2724                                    $value = ($element.getAttribute('data-math-day')) ? parseFloat($element.getAttribute('data-math-day')) : 0;
2725                                }
2726                                if($value_n === 'month'){
2727                                    $value = ($element.getAttribute('data-math-month')) ? parseFloat($element.getAttribute('data-math-month')) : 0;
2728                                }
2729                                if($value_n === 'year'){
2730                                    $value = ($element.getAttribute('data-math-year')) ? parseFloat($element.getAttribute('data-math-year')) : 0;
2731                                }
2732                                if($value_n === 'timestamp'){
2733                                    $value = ($element.getAttribute('data-math-diff')) ? parseFloat($element.getAttribute('data-math-diff')) : 0;
2734                                }
2735                            }else{
2736                                if($element.getAttribute('data-return_age')=='true'){
2737                                    $value = ($element.getAttribute('data-math-age')) ? parseFloat($element.getAttribute('data-math-age')) : 0;
2738                                }
2739                                // @since 1.2.0 - check if we want to return the date birth years, months or days for calculations
2740                                if($element.getAttribute('data-date-math')=='years'){
2741                                    $value = ($element.getAttribute('data-math-age')) ? parseFloat($element.getAttribute('data-math-age')) : 0;
2742                                }
2743                                if($element.getAttribute('data-date-math')=='months'){
2744                                    $value = ($element.getAttribute('data-math-age-months')) ? parseFloat($element.getAttribute('data-math-age-months')) : 0;
2745                                }
2746                                if($element.getAttribute('data-date-math')=='days'){
2747                                    $value = ($element.getAttribute('data-math-age-days')) ? parseFloat($element.getAttribute('data-math-age-days')) : 0;
2748                                }
2749                            }
2750                        }
2751
2752                        if( $text_field===true ) {
2753                            // Check if text field is a auto-suggest, if so grab the value from the selected item
2754                            if($element.closest('.super-shortcode').classList.contains('super-auto-suggest') || $element.closest('.super-shortcode').classList.contains('super-wc-order-search')){
2755                                if($element.closest('.super-field-wrapper').querySelector('.super-active')){
2756                                    $new_value = $element.closest('.super-field-wrapper').querySelector('.super-active').dataset.value;
2757                                    $new_value = $new_value.toString().split(';');
2758                                    if($value_n===0){
2759                                        $new_value = $new_value[0];
2760                                    }else{
2761                                        $new_value = $new_value[($value_n-1)];
2762                                    }
2763                                    if(typeof $new_value==='undefined'){
2764                                        $new_value = '';
2765                                    }
2766                                    $value = $new_value;
2767                                }
2768                            }else{
2769                                $value = $element.value;
2770                            }
2771                            if( args.target ) {
2772                                if( (typeof $element.dataset.value !== 'undefined') && (args.target.classList.contains('super-html-content')) ) {
2773                                    $value = $element.dataset.value;
2774                                }
2775                            }
2776                            if( $value_type=='int' ) {
2777                                $value = ($value) ? parseFloat($value) : '';
2778                            }
2779                        }
2780                        // Grab E-mail Label
2781                        if($value_n=='email' || $value_n=='email_label' || $value_n=='emailLabel'){
2782                            $value = $element.dataset.email;
2783                            if($value.indexOf('%d')!==-1){
2784                                var dynamicParentIndex = $($element).parents('.super-duplicate-column-fields:eq(0)').index();
2785                                $value = $value.replaceAll('%d', dynamicParentIndex+1);
2786                            }
2787                        }
2788                        if( ($value_type=='int') && (isNaN($value)) ) {
2789                            $value = $default_value;
2790                        }
2791                        args.value = args.value.replace('{'+$old_name+'}', $value);
2792                    }
2793                }
2794            }
2795        }
2796        return args.value;
2797    };
2798
2799    SUPER.close_loading_overlay = function(loadingOverlay){
2800        if(loadingOverlay) loadingOverlay.remove();
2801    };
2802    SUPER.reset_submit_button_loading_state = function(form){
2803        var submitButton = form.querySelector('.super-form-button.super-loading');
2804        if(submitButton){
2805            submitButton.classList.remove('super-loading');
2806            var buttonName = submitButton.querySelector('.super-button-name');
2807            var normal = buttonName.dataset.normal;
2808            buttonName.innerHTML = normal;
2809        }
2810    };
2811
2812
2813    // Show PDF download button
2814    SUPER.show_pdf_download_btn = function(args){
2815        var btn = document.createElement('div');
2816        btn.classList.add('super-pdf-download-btn');
2817        btn.innerHTML = args.pdfSettings.downloadBtnText;
2818        args.loadingOverlay.querySelector('.super-loading-text').appendChild(btn);
2819        btn.addEventListener('click', function(){
2820            args._pdf.save(args.pdfSettings.filename);
2821        });
2822    };
2823    // Form submission is finished
2824    SUPER.form_submission_finished = function(args, result){ 
2825        if(args.showOverlay==="true"){
2826            // Display message inside overlay
2827            if(args.progressBar) args.progressBar.style.width = 100+"%";  
2828            var innerText = args.loadingOverlay.querySelector('.super-inner-text');
2829            if(innerText) {
2830                innerText.innerHTML = '<span>'+super_common_i18n.loadingOverlay.completed+'</span>';
2831            }
2832            // Check if there is a message
2833            if(result.msg!==''){
2834                // Check if this is an error message
2835                if(result.error===true){
2836                    args.loadingOverlay.classList.add('super-error');
2837                    // Display the error/success message
2838                    if(innerText) innerText.innerHTML = result.msg;
2839                }else{
2840                    args.loadingOverlay.classList.add('super-success');
2841                    if(args.generatePdf && args.pdfSettings.downloadBtn==='true'){
2842                        SUPER.show_pdf_download_btn(args);
2843                    }
2844                    // Close Popup (if any)
2845                    if(typeof SUPER.init_popups === 'function' && typeof SUPER.init_popups.close === 'function' ){
2846                        SUPER.init_popups.close(true);
2847                    }
2848                    if(result.redirect){
2849                        // When redirecting to different page show redirect message instead of thank you message
2850                        innerText.innerHTML = SUPER.update_variable_fields.replace_tags({form: args.form0, value: super_common_i18n.loadingOverlay.redirecting});
2851                    }else{
2852                        // Display the error/success message
2853                        if(innerText) innerText.innerHTML = result.msg;
2854                    }
2855                }
2856                // Convert any JS to executable JS
2857                var node = innerText.querySelector('script');
2858                if(node && node.tagName === 'SCRIPT'){
2859                    var script  = document.createElement("script");
2860                    script.text = node.innerHTML;
2861                    for( var i = node.attributes.length-1; i >= 0; i-- ) {
2862                        script.setAttribute( node.attributes[i].name, node.attributes[i].value );
2863                    }
2864                    node.parentNode.replaceChild(script, node);
2865                }
2866            }else{
2867                // We do not want to display a thank you message, but might want to display a Download PDF button
2868                if(args.generatePdf && args.pdfSettings.downloadBtn==='true'){
2869                    args.loadingOverlay.classList.add('super-success');
2870                    SUPER.show_pdf_download_btn(args);
2871                }else{
2872                    // Just close the overlay, no need to show download button and we do not have a message to display
2873                    SUPER.close_loading_overlay(args.loadingOverlay);
2874                }
2875                // Close Popup (if any)
2876                if(typeof SUPER.init_popups === 'function' && typeof SUPER.init_popups.close === 'function' ){
2877                    SUPER.init_popups.close(true);
2878                }
2879            }
2880        }else{
2881            // Redirect user to specified url
2882            if(result.redirect){
2883                window.location.href = result.redirect;
2884            }else{
2885                // Display message in legacy mode
2886                // But only display if not empty
2887                if(result.msg!==''){
2888                    // Remove existing messages
2889                    var ii,
2890                        html,
2891                        nodes = document.querySelectorAll('.super-msg');
2892                    for (ii = 0; ii < nodes.length; ii++) { 
2893                        nodes[ii].remove();
2894                    }
2895                    // Check for errors, if there are any display them to the user 
2896                    if(result.error===true){
2897                        html = '<div class="super-msg super-error">';
2898                        if(typeof result.fields !== 'undefined'){
2899                            $.each(result.fields, function( index, value ) {
2900                                $(value+'[name="'+index+'"]').parent().addClass('error');
2901                            });
2902                        }                               
2903                    }else{
2904                        html = '<div class="super-msg super-success"';
2905                        // @since 3.4.0 - option to not display the message
2906                        if(result.display===false){
2907                            html += 'style="display:none;">';
2908                        }
2909                        html += '>';
2910                    }
2911                    html += result.msg;
2912                    html += '<span class="super-close"></span>';
2913                    html += '</div>';
2914                    if(args.form){
2915                        $(html).prependTo($(args.form));
2916                        $('html, body').animate({
2917                            scrollTop: $(args.form).offset().top-200
2918                        }, 1000);
2919                    }
2920                }
2921            }
2922        }
2923        // Redirect user to specified url
2924        if(result.redirect){
2925            window.location.href = result.redirect;
2926        }
2927        // @since 3.4.0 - keep loading state active
2928        if(result.loading!==true){
2929            if(typeof args.form !== 'undefined') {
2930                SUPER.reset_submit_button_loading_state(args.form[0]);
2931                if(result.error===false){
2932                    // @since 2.0.0 - hide form or not
2933                    if($(args.form).data('hide')===true){
2934                        $(args.form).find('.super-field, .super-multipart-progress, .super-field, .super-multipart-steps').fadeOut(500);
2935                        setTimeout(function () {
2936                            $(args.form).find('.super-field, .super-shortcode').remove();
2937                        }, 500);
2938                    }else{
2939                        // @since 2.0.0 - clear form after submitting
2940                        if($(args.form).data('clear')===true){
2941                            SUPER.init_clear_form({form: args.form0});
2942                        }
2943                    }
2944                    if(result.msg===''){
2945                        // Close Popup (if any)
2946                        if(typeof SUPER.init_popups === 'function' && typeof SUPER.init_popups.close === 'function' ){
2947                            SUPER.init_popups.close(true);
2948                        }
2949                    }
2950                }
2951            }
2952        }
2953    };
2954
2955    // Trim strings
2956    SUPER.trim = function($this) {
2957        if(typeof $this === 'string'){
2958            return $this.replace(/^\s+|\s+$|\s+(?=\s)/g, "");
2959        }
2960    };
2961
2962    // Check for errors, validate fields
2963    SUPER.handle_validations = function(args){
2964        if(args.el.closest('[data-conditional-action="show"]')){
2965            if(args.el.closest('[data-conditional-action="show"]').classList.contains('super-conditional-hidden')){
2966                return false;
2967            }
2968        }
2969        if(args.el.closest('.super-shortcode').classList.contains('super-hidden')) return false;
2970        var parent = args.el.closest('.super-field'),
2971            result,
2972            error = false,
2973            regex,
2974            value,
2975            numbers,
2976            pattern,
2977            attr,
2978            text_field,
2979            total,
2980            field_value,
2981            value2,
2982            counter,
2983            checked,
2984            custom_regex = (args.el.parentNode.querySelector('.super-custom-regex') ? args.el.parentNode.querySelector('.super-custom-regex').value : undefined), // @since 1.2.5 - custom regex
2985            mayBeEmpty = (typeof args.el.dataset.mayBeEmpty !== 'undefined' ? args.el.dataset.mayBeEmpty : 'false'),
2986            allowEmpty = false,
2987            urlRegex = /^(http(s)?:\/\/)?(www\.)?[a-zA-Z0-9]+([-.]{1}[a-zA-Z0-9]+)*\.[a-zA-Z]{2,5}(:[0-9]{1,5})?(\/.*)?$/;
2988        
2989        // @since   4.9.0 -  Conditional required fields
2990        // Before we proceed, check if field is empty
2991        if (args.el.value === '') {
2992            // If it is empty, check if it allowed to be empty
2993            if (typeof mayBeEmpty !== 'undefined') {
2994                if (mayBeEmpty == 'false') {
2995                    allowEmpty = false;
2995 // Do not allow field to be empty
2996                }
2997                if (mayBeEmpty == 'true') {
2998                    allowEmpty = true; // Allow field to be empty
2999                }
3000                if (mayBeEmpty == 'conditions') {
3001                    // Allow field to be empty only when following conditions are met
3002                    allowEmpty = true; 
3003                    args.conditionalLogic = args.form.querySelectorAll('.super-validate-conditions');
3004                    if(typeof args.conditionalLogic !== 'undefined'){
3005                        if(args.conditionalLogic.length!==0){
3006                            result = SUPER.conditional_logic.loop(args);
3007                            if (!result) {
3008                                allowEmpty = false; // when condition is met, we do not allow field to be empty
3009                            }
3010                        }
3011                    }
3012                }
3013            }
3014        }
3015        regex = new RegExp(custom_regex);
3016        if( custom_regex && args.validation=='custom' ) {
3017            if(!regex.test(args.el.value)) error = true;
3018        }
3019        if (args.validation == 'captcha') {
3020            error = true;
3021        }
3022        if (args.validation == 'numeric') {
3023            regex = /^\d+$/;
3024            if (!regex.test(args.el.value)) error = true;
3025        }
3026        if (args.validation == 'float') {
3027            regex = /^[+-]?\d+(\.\d+)?$/;
3028            if (!regex.test(args.el.value)) error = true;
3029        }
3030        if (args.validation == 'email') {
3031            regex = /^([\w-.+]+@([\w-]+\.)+[\w-]{2,63})?$/;
3032            if ((args.el.value.length < 4) || (!regex.test(args.el.value))) {
3033                error = true;
3034            }
3035        }
3036        if (args.validation == 'phone') {
3037            regex = /^((\+)?[1-9]{1,2})?([-\s.])?((\(\d{1,4}\))|\d{1,4})(([-\s.])?[0-9]{1,12}){1,2}$/;
3038            value = args.el.value;
3039            numbers = value.split("").length;
3040            if (10 <= numbers && numbers <= 20 && regex.test(value)) {
3041                // is valid, continue
3042            }else{
3043                error = true;
3044            }
3045        }
3046        if (args.validation == 'website') {
3047            pattern = new RegExp(urlRegex);
3048            if(!pattern.test(args.el.value)) error = true;
3049        }
3050        // @since 2.6.0 - IBAN validation
3051        if (args.validation == 'iban') {
3052            if( (IBAN.isValid(args.el.value)===false) && (args.el.value!=='') ) error = true;
3053        }
3054        attr = args.el.dataset.minlength;
3055        if (typeof attr !== 'undefined' && attr !== false) {
3056            text_field = true;
3057            total = 0;
3058            if(parent.classList.contains('super-checkbox')){
3059                text_field = false;
3060                checked = parent.querySelectorAll('.super-item.super-active');
3061                if(checked.length < attr){
3062                    error = true;
3063                }
3064            }
3065            if(parent.classList.contains('super-dropdown')){
3066                text_field = false;
3067                total = parent.querySelectorAll('.super-dropdown-list .super-item.super-active:not(.super-placeholder)').length;
3068                if(total < attr) error = true;
3069            }
3070            if(parent.classList.contains('super-keyword-tags')){
3071                text_field = false;
3072                total = parent.querySelectorAll('.super-autosuggest-tags > span').length;
3073                if(total < attr) error = true;
3074            }
3075            if(text_field===true){
3076                if(!parent.classList.contains('super-date')){
3077                    if(args.el.value.length < attr) error = true;
3078                }
3079            }       
3080        }
3081        attr = args.el.dataset.maxlength;
3082        if (typeof attr !== 'undefined' && attr !== false) {
3083            text_field = true;
3084            total = 0;
3085            if(parent.classList.contains('super-checkbox')){
3086                text_field = false;
3087                checked = parent.querySelectorAll('.super-item.super-active');
3088                if(checked.length > attr) error = true;
3089            }
3090            if(parent.classList.contains('super-dropdown')){
3091                text_field = false;
3092                total = parent.querySelectorAll('.super-dropdown-list .super-item.super-active:not(.super-placeholder)').length;
3093                if(total > attr) error = true;
3094            }
3095            if(parent.classList.contains('super-keyword-tags')){
3096                text_field = false;
3097                total = parent.querySelectorAll('.super-autosuggest-tags > span').length;
3098                if(total > attr) error = true;
3099            }
3100            if(text_field===true){
3101                if(!parent.classList.contains('super-date')){
3102                    if(args.el.value.length > attr) error = true;
3103                }
3104            }
3105        }
3106        attr = args.el.dataset.minnumber;
3107        if (typeof attr !== 'undefined' && attr !== false) {
3108            // Check if currency field
3109            if(parent.classList.contains('super-currency')){
3110                value = $(args.el).maskMoney('unmasked')[0];
3111                value = (value) ? parseFloat(value) : 0;
3112                if( value < parseFloat(attr) ) error = true;
3113            }else{
3114                if( parseFloat(args.el.value) < parseFloat(attr) ) error = true;
3115            }
3116        }
3117        attr = args.el.dataset.maxnumber;
3118        if (typeof attr !== 'undefined' && attr !== false) {
3119            // Check if currency field
3120            if(parent.classList.contains('super-currency')){
3121                value = $(args.el).maskMoney('unmasked')[0];
3122                value = (value) ? parseFloat(value) : 0;
3123                if( value > parseFloat(attr) ) error = true;
3124            }else{
3125                if( parseFloat(args.el.value) > parseFloat(attr) ) error = true;
3126            }
3127        }
3128
3129        // Datepicker min dates
3130        if(parent && parent.classList.contains('super-date')){
3131            attr = args.el.dataset.minpicks;
3132            if (typeof attr !== 'undefined' && attr !== false) {
3133                if( parseInt(attr,10)>0 ) {
3134                    if(args.el.value==='') error = true;
3135                    total = args.el.value.split(',').length;
3136                    if( total < parseFloat(attr) ) error = true;
3137                }
3138            }
3139        }
3140
3141        // @since   1.0.6
3142        if( typeof args.conditionalValidation!=='undefined' && args.conditionalValidation!='none' && args.conditionalValidation!=='' ) {
3143            field_value = args.el.value;
3144            // Check if currency field
3145            if(parent.classList.contains('super-currency')){
3146                value = $(args.el).maskMoney('unmasked')[0];
3147                field_value = (value) ? parseFloat(value) : 0;
3148            }
3149            value = args.el.dataset.conditionalValidationValue;
3150            value2 = args.el.dataset.conditionalValidationValue2;
3151            if(typeof value !== 'undefined') value = SUPER.get_conditional_validation_value(value, args.form);
3152            if(typeof value2 !== 'undefined') value2 = SUPER.get_conditional_validation_value(value2, args.form);
3153            counter = 0;
3154            if(args.conditionalValidation=='equal' && field_value==value) counter++;
3155            if(args.conditionalValidation=='not_equal' && field_value!=value) counter++;
3156            if(args.conditionalValidation=='contains' && field_value.indexOf(value) >= 0) counter++;
3157            if(args.conditionalValidation=='not_contains' && field_value.indexOf(value) == -1) counter++;
3158            field_value = parseFloat(field_value);
3159            value = parseFloat(value);
3160            value2 = parseFloat(value2);
3161            if(args.conditionalValidation=='greater_than' && field_value>value) counter++;
3162            if(args.conditionalValidation=='less_than' && field_value<value) counter++;
3163            if(args.conditionalValidation=='greater_than_or_equal' && field_value>=value) counter++;
3164            if(args.conditionalValidation=='less_than_or_equal' && field_value<=value) counter++;
3165            // @since 3.6.0 - more specific conditional validation options
3166            // > && <
3167            // > || <
3168            if( (args.conditionalValidation=='greater_than_and_less_than') && ((field_value>value) && (field_value<value2)) ) counter++;
3169            if( (args.conditionalValidation=='greater_than_or_less_than') && ((field_value>value) || (field_value<value2)) ) counter++;
3170            // >= && <
3171            // >= || <
3172            if( (args.conditionalValidation=='greater_than_or_equal_and_less_than') && ((field_value>=value) && (field_value<value2)) ) counter++;
3173            if( (args.conditionalValidation=='greater_than_or_equal_or_less_than') && ((field_value>=value) || (field_value<value2)) ) counter++;
3174            // > && <=
3175            // > || <=
3176            if( (args.conditionalValidation=='greater_than_and_less_than_or_equal') && ((field_value>value) && (field_value<=value2)) ) counter++;
3177            if( (args.conditionalValidation=='greater_than_or_less_than_or_equal') && ((field_value>value) || (field_value<=value2)) ) counter++;
3178            // >= && <=
3179            // >= || <=
3180            if( (args.conditionalValidation=='greater_than_or_equal_and_less_than_or_equal') && ((field_value>=value) && (field_value<=value2)) ) counter++;
3181            if( (args.conditionalValidation=='greater_than_or_equal_or_less_than_or_equal') && ((field_value>=value) || (field_value<=value2)) ) counter++;
3182            if(counter===0) error = true;
3183        }
3184        // @since 4.3.0 - extra validation check for files
3185        if(args.el.classList.contains('super-fileupload')){
3186            attr = args.el.parentNode.querySelector('.super-active-files').dataset.minfiles;
3187            if (typeof attr !== 'undefined' && attr !== false) {
3188                total = args.el.parentNode.querySelectorAll('.super-fileupload-files > div').length;
3189                if(total < attr) error = true;
3190            }
3191            attr = args.el.parentNode.querySelector('.super-active-files').dataset.maxfiles;
3192            if (typeof attr !== 'undefined' && attr !== false) {
3193                total = args.el.parentNode.querySelectorAll('.super-fileupload-files > div').length;
3194                if(total > attr) error = true;
3195            }
3196            if(args.el.closest('.super-shortcode').classList.contains('super-error-active')){
3197                error = true;
3198            }
3199        }
3200        // @since 5.0.022 - extra validation check for international phone numbers
3201        if(args.el.closest('.super-int-phone')){
3202            var super_int_phone = window.superTelInputGlobals.getInstance(args.el);
3203            if(!super_int_phone.isValidNumber()){
3204                error = true;
3205            }
3206        }
3207
3208        // Display error messages
3209        if(allowEmpty && args.el.value==='') error = false;
3210        if(typeof args.validation !== 'undefined' && !allowEmpty && args.el.value==='') error = true;
3211        if(error){
3212            SUPER.handle_errors(args.el);
3213            SUPER.add_error_status_parent_layout_element($, args.el);
3214        }else{
3215            if(args.el.closest('.super-field')) args.el.closest('.super-field').classList.remove('super-error-active');
3216            SUPER.remove_error_status_parent_layout_element($, args.el);
3217        }
3218        return error;
3219    };
3220
3221    // Output errors for each field
3222    SUPER.handle_errors = function(el){
3223        if(el.closest('.super-field')) el.closest('.super-field').classList.add('super-error-active');
3224    };
3225
3226    // Validate the form
3227    SUPER.validate_form = function(args){ // form, submitButton, validateMultipart, e, doingSubmit
3228        SUPER.resetFocussedFields();
3229        SUPER.conditional_logic(args);
3230
3231        // // Check if any of the stripe elements are filled out correctly
3232        // // Pass this to the form data so we can do a check (if Stripe is enabled)
3233        // super-stripe-ideal-element
3234        // super-stripe-cc-element
3235        // super-stripe-iban-element
3236        SUPER.before_validating_form_hook(args);
3237
3238        var i = 0, nodes,
3239            action = (args.submitButton.querySelector('.super-button-name') ? args.submitButton.querySelector('.super-button-name').dataset.action : ''),
3240            url = (typeof args.submitButton.dataset.href !== 'undefined' ? decodeURIComponent(args.submitButton.dataset.href) : undefined) ,
3241            proceed = SUPER.before_submit_button_click_hook(args.event, args.submitButton),
3242            regex = /{([^\\\/\s"'+]*?)}/g,
3243            array = [],
3244            error = false,
3245            name,
3246            field,
3247            element,
3248            target,
3249            submitButtonName,
3250            oldHtml,
3251            loading,
3252            total,
3253            match,
3254            value,
3255            fileError,
3256            attr,
3257            validation,
3258            conditionalValidation,
3259            textField;
3260
3261        // Set action to empty string when the button is a multi-part button
3262        if(args.submitButton.classList.contains('super-next-multipart') || args.submitButton.classList.contains('super-prev-multipart')){
3263            action = '';
3264        }
3265
3266        if(action=='clear'){
3267            SUPER.init_clear_form({form: args.form});
3268            return false;
3269        }
3270        if(action=='print'){
3271            SUPER.init_print_form(args);
3272            return false;
3273        }
3274        if(proceed===true){
3275            if( (url!=='') && (typeof url !== 'undefined') ){
3276                while ((match = regex.exec(url)) !== null) {
3277                    array[i] = match[1];
3278                    i++;
3279                }
3280                for (i = 0; i < array.length; i++) {
3281                    name = array[i];
3282                    element = SUPER.field(args.form, name);
3283                    if(element){
3284                        value = element.value;
3285                        url = url.replace('{'+name+'}', value);
3286                        
3287                    }
3288                }
3289                url = url.replace('{', '').replace('}', '');
3290                if( url=='#' ) {
3291                    return false;
3292                }else{
3293                    target = args.submitButton.dataset.target;
3294                    if( (target!=='undefined') && (target=='_blank') ) {
3295                        window.open( url, '_blank' );
3296                    }else{
3297                        window.location.href = url;
3298                    }
3299                    return false;
3300                }
3301            }else{
3302                if(args.submitButton.closest('.super-form-button') && args.submitButton.closest('.super-form-button').classList.contains('super-loading')){
3303                    return false;
3304                }
3305            }
3306        }
3307        // @since 2.0 - multipart validation
3308        if(typeof args.validateMultipart === 'undefined') args.validateMultipart = '';
3309
3310        // @since 1.2.4     make sure the text editor saves content to it's textarea
3311        if( typeof tinyMCE !== 'undefined' ) {
3312            if( typeof tinyMCE.triggerSave !== 'undefined' ) {
3313                tinyMCE.triggerSave();
3314            }
3315        }
3316
3317        nodes = SUPER.field(args.form, '', 'all');
3318        for ( i = 0; i < nodes.length; i++) {
3319            field = nodes[i];
3320            textField = true;
3321            if(!SUPER.has_hidden_parent(field)){
3322                // super-shortcode-field super-fileupload super-rendered
3323                if(field.classList.contains('super-active-files')){
3324                    textField = false;
3325                    fileError = false;
3326                    attr = parseFloat(field.dataset.minfiles);
3327                    if (!isNaN(attr) && typeof attr !== 'undefined' && attr !== false) {
3328                        total = field.parentNode.querySelectorAll('.super-fileupload-files > div').length;
3329                        if(total < attr) {
3330                            fileError = true;
3331                        }
3332                    }
3333                    attr = parseFloat(field.dataset.maxfiles);
3334                    if (!isNaN(attr) && typeof attr !== 'undefined' && attr !== false) {
3335                        total = field.parentNode.querySelectorAll('.super-fileupload-files > div').length;
3336                        if(total > attr) {
3337                            fileError = true;
3338                        }
3339                    }
3340                    if(fileError===true){
3341                        error = true;
3342                        SUPER.handle_errors(field);
3343                        SUPER.add_error_status_parent_layout_element($, field);
3344                    }else{
3345                        if(field.closest('.super-field')) field.closest('.super-field').classList.remove('super-error-active');
3346                        SUPER.remove_error_status_parent_layout_element($, field);
3347                    }
3348                }
3349                if(textField===true){
3350                    validation = field.dataset.validation;
3351                    conditionalValidation = field.dataset.conditionalValidation;
3352                    if (SUPER.handle_validations({el: field, form: args.form, validation: validation, conditionalValidation: conditionalValidation})) {
3353                        error = true;
3354                    }
3355                }
3356            }
3357        }
3358
3359        // Activate possible TABS and Accordions to display errors
3360        var tabs = args.form.querySelectorAll('.super-tabs-tab.super-error');
3361        if(tabs && tabs[0]) tabs[0].click();
3362        var accordions = args.form.querySelectorAll('.super-accordion-item.super-error');
3363        if(accordions && accordions[0]) accordions[0].querySelector('.super-accordion-header').click();
3364        if(error===false){
3365            // Check if there are other none standard elements that have an active error
3366            // Currently used by Stripe feature to check for invalid card numbers for instance
3367            if(args.form.querySelectorAll('.super-error-active').length){
3368                SUPER.scrollToError(args.form);
3369                return true;
3370            }
3371            // @since 2.0.0 - multipart validation
3372            if(args.validateMultipart===true) return true;
3373            submitButtonName = args.submitButton.querySelector('.super-button-name');
3374            args.submitButton.closest('.super-form-button').classList.add('super-loading');
3375            oldHtml = submitButtonName.innerHTML;
3376            // @since 2.0.0 - submit button loading state name
3377            loading = args.submitButton.querySelector('.super-button-name').dataset.loading;
3378            if(super_common_i18n.loading!='Loading...') {
3379                loading = super_common_i18n.loading;
3380            }
3381            submitButtonName.innerHTML = loading;
3382
3383            var y=0, 
3384                codeNodes = args.form.querySelectorAll('.super-shortcode-field[data-code="true"]'),
3385                totalNodes = codeNodes.length;
3386            for(y=0; y<codeNodes.length; y++){
3387                codeNodes[y].classList.remove('super-generated');
3388            }
3389            for(y=0; y<codeNodes.length; y++){
3390                SUPER.update_unique_code(codeNodes[y], 'true');
3391            }
3392            var completeSubmitInterval = setInterval(function(){
3393                var codeNodes = args.form.querySelectorAll('.super-shortcode-field.super-generated[data-code="true"]');
3394                if(codeNodes.length !== totalNodes){
3395                    // Still doing things...
3396                }else{
3397                    clearInterval(completeSubmitInterval);
3398                    // Prepare arguments
3399                    SUPER.prepare_form_data($(args.form), function(formData){
3400                        args = {
3401                            event: args.event,
3402                            form: args.form,
3403                            data: formData.data,
3404                            form_id: formData.form_id,
3405                            entry_id: formData.entry_id,
3406                            list_id: formData.list_id,
3407                            oldHtml: oldHtml,
3408                            sf_nonce: formData.sf_nonce
3409                        };
3410                        args.callback = function(){
3411                            SUPER.complete_submit(args);
3412                        };
3413                        SUPER.before_submit_hook(args);
3414                    }); 
3415                }
3416            }, 100);
3417
3418        }else{
3419            SUPER.scrollToError(args.form, args.validateMultipart);
3420        }
3421        SUPER.after_validating_form_hook(undefined, args.form);
3422
3423    };
3424
3425    SUPER.scrollToError = function(form, validateMultipart){
3426        var scroll = true, step, children, index, total, progress, multipart, proceed;
3427        // @since 2.0 - multipart validation
3428        if(validateMultipart===true) {
3429            scroll = true;
3430            if(typeof form.dataset.disableScroll !== 'undefined'){
3431                scroll = false;
3432            }
3433            if(scroll){
3434                $('html, body').animate({
3435                    scrollTop: $(form).offset().top-30
3436                }, 1000);
3437            }
3438            return false;
3439        }
3440
3441        if(form.querySelector('.super-multipart-step.super-error')){
3442            step = form.querySelector('.super-multipart-step.super-error');
3443            children = Array.prototype.slice.call( step.parentNode.children );
3444            index = children.indexOf(step);
3445            total = form.querySelectorAll('.super-multipart').length;
3446            progress = 100 / total;
3447            progress = progress * (index+1);
3448            multipart = form.querySelectorAll('.super-multipart')[index];
3449            scroll = true;
3450            if(typeof multipart.dataset.disableScroll !== 'undefined'){
3451                scroll = false;
3452            }
3453            form.querySelector('.super-multipart-progress-bar').style.width = progress+'%';
3454            form.querySelector('.super-multipart-step.super-active').classList.remove('super-active');
3455            form.querySelector('.super-multipart.super-active').classList.remove('super-active');
3456            multipart.classList.add('super-active');
3457            step.classList.add('super-active');
3458
3459            // @since 2.1.0
3460            proceed = SUPER.before_scrolling_to_error_hook(form, $(form).offset().top - 30);
3461            if(proceed!==true) return false;
3462
3463            // @since 4.2.0 - disable scrolling when multi-part contains errors
3464            if(scroll){
3465                // Scroll to first error field
3466                var current = multipart.querySelector('.super-error-active');
3467                current.scrollIntoView({behavior: "auto", block: "center", inline: "center"});
3468                // Focus first error field
3469                SUPER.focusNextTabField({keyCode: 32, preventDefault: function(){}}, current, form, current);
3470            }
3471        }else{
3472            // @since 2.1.0
3473            proceed = SUPER.before_scrolling_to_error_hook(form, $(form).find('.super-error-active').offset().top-200);
3474            if(proceed!==true) return false;
3475            $('html, body').animate({
3476                scrollTop: $(form).find('.super-error-active').offset().top-200
3477            }, 1000);
3478
3479        }
3480    };
3481
3482    // @since 1.2.3
3483    SUPER.auto_step_multipart = function(args){
3484        // If triggered field change is not inside active multi-part we skip it
3485        var activeMultipart = args.el.closest('.super-multipart.super-active');
3486        if(!activeMultipart) return false;
3487        var i, nodes, totalFields, counter;
3488        if(activeMultipart){
3489            if( activeMultipart.dataset.stepAuto=='yes') {
3490                totalFields = 0;
3491                nodes = activeMultipart.querySelectorAll('.super-shortcode-field');
3492                for (i = 0; i < nodes.length; ++i) {
3493                    if(!SUPER.has_hidden_parent(nodes[i])){
3494                        // Also exclude any hidden fields, because `has_hidden_parent()` doesn't check for this
3495                        if(nodes[i].type=='hidden'){
3496                            if(nodes[i].closest('.super-shortcode').classList.contains('super-hidden')){
3497                                continue;
3498                            }
3499                        }
3500                        totalFields++;
3501                    }
3502                }
3503                counter = 1;
3504                nodes = activeMultipart.querySelectorAll('.super-shortcode-field');
3505                for (i = 0; i < nodes.length; ++i) {
3506                    if(!SUPER.has_hidden_parent(nodes[i])){
3507                        if(totalFields==counter){
3508                            if(nodes[i].name==args.el.name){
3509                                setTimeout(function (){
3510                                    var activeMultipart = args.form.querySelector('.super-multipart-step.super-active'),
3511                                    children = Array.prototype.slice.call(activeMultipart.parentNode.children),
3512                                    total = args.form.querySelectorAll('.super-multipart').length,
3513                                    currentStep = children.indexOf(activeMultipart);
3514                                    if(total===currentStep+1){
3515                                        // Except if already last step
3516                                    }else{
3517                                        SUPER.switchMultipart(undefined, args.el, 'next');
3518                                    }
3519                                }, 200);
3520                                break;
3521                            }
3522                        }
3523                        counter++;
3524                    }
3525                }
3526            }
3527        }
3528    };
3529
3530    // Define Javascript Filters/Hooks
3531    SUPER.save_form_params_filter = function(params){
3532        var i, name, functions = super_common_i18n.dynamic_functions.save_form_params_filter;
3533        if(typeof functions !== 'undefined'){
3534            for( i = 0; i < functions.length; i++){
3535                name = functions[i].name;
3536                if(typeof SUPER[name] === 'undefined') continue;
3537                params = SUPER[name](params);
3538            }
3539        }
3540        return params;
3541    };
3542    SUPER.before_submit_hook = function(args){
3543        var proceed=true, i, name, functions = super_common_i18n.dynamic_functions.before_submit_hook;
3544        if(typeof functions !== 'undefined'){
3545            for( i = 0; i < functions.length; i++){
3546                name = functions[i].name;
3547                if(typeof SUPER[name] === 'undefined') continue;
3548                var result = SUPER[name](args);
3549                result = JSON.parse(result);
3550                // Check for errors, if there are any display them to the user 
3551                if(result.error===true){
3552                    proceed = false;
3553                    var ii,
3554                        nodes = document.querySelectorAll('.super-msg'),
3555                        html = '<div class="super-msg super-error">';
3556                    for (ii = 0; ii < nodes.length; ii++) { 
3557                        nodes[ii].remove();
3558                    }
3559                    if(typeof result.fields !== 'undefined'){
3560                        $.each(result.fields, function( index, value ) {
3561                            $(value+'[name="'+index+'"]').parent().addClass('error');
3562                        });
3563                    }                               
3564                    html += result.msg;
3565                    html += '<span class="super-close"></span>';
3566                    html += '</div>';
3567                    $(html).prependTo($(args.form));
3568                    var btn = args.form.querySelector('.super-form-button.super-loading');
3569                    if(btn) {
3570                        var btnName = btn.querySelector('.super-button-name');
3571                        btnName.innerHTML = args.oldHtml;
3572                        btn.classList.remove('super-loading');
3573                    }
3574                    $('html, body').animate({
3575                        scrollTop: $(args.form).offset().top-200
3576                    }, 1000);
3577                }
3578            }
3579        }
3580        // Submit form if we may proceed
3581        if(proceed) args.callback();
3582    };
3583    SUPER.before_email_send_hook = function(args){
3584        var i, name, found = 0, functions = super_common_i18n.dynamic_functions.before_email_send_hook;
3585        if(typeof functions !== 'undefined'){
3586            for( i = 0; i < functions.length; i++){
3587                name = functions[i].name;
3588                if(typeof SUPER[name] === 'undefined') continue;
3589                found++;
3590                SUPER[name](args);
3591            }
3592        }
3593        // Call callback function when no functions were defined by third party add-ons
3594        if(found==0) args.callback(args);
3595    };
3596    SUPER.before_validating_form_hook = function(args){
3597        var i, name, functions = super_common_i18n.dynamic_functions.before_validating_form_hook;
3598        if(typeof functions !== 'undefined'){
3599            for( i = 0; i < functions.length; i++){
3600                name = functions[i].name;
3601                if(typeof SUPER[name] === 'undefined') continue;
3602                SUPER[name](args);
3603            }
3604        }
3605    };
3606    SUPER.after_validating_form_hook = function(changedField, form){
3607        var i, name, functions = super_common_i18n.dynamic_functions.after_validating_form_hook;
3608        if(typeof functions !== 'undefined'){
3609            for( i = 0; i < functions.length; i++){
3610                name = functions[i].name;
3611                if(typeof SUPER[name] === 'undefined') continue;
3612                SUPER[name](changedField, form);
3613            }
3614        }
3615    };
3616    SUPER.after_initializing_forms_hook = function(args){
3617        var i, name, functions = super_common_i18n.dynamic_functions.after_initializing_forms_hook;
3618        if(typeof functions !== 'undefined'){
3619            for( i = 0; i < functions.length; i++){
3620                name = functions[i].name;
3621                if(typeof SUPER[name] === 'undefined') continue;
3622                SUPER[name](args);
3623            }
3624        }
3625        // Replace {tags} for any fields with default value that contains tags
3626        var form = SUPER.get_frontend_or_backend_form(args);
3627        var defaultValues = form.querySelectorAll('.super-replace-tags .super-shortcode-field');
3628        if(typeof defaultValues !== 'undefined'){
3629            for(i = 0; i<defaultValues.length; i++){
3630                var oldValue = defaultValues[i].value;
3631                defaultValues[i].value = SUPER.update_variable_fields.replace_tags({form: form, value: defaultValues[i].value, defaultValues: true});
3632                var newValue = defaultValues[i].value;
3633                // If values changed
3634                if(oldValue!=newValue){
3635                    SUPER.after_field_change_blur_hook({el: defaultValues[i]});
3636                }
3637                defaultValues[i].closest('.super-replace-tags').classList.remove('super-replace-tags');
3638            }
3639        }
3640
3641        args.callback(args);
3642    };
3643
3644    // @since 3.6.0 - function to retrieve either the form element in back-end preview mode or on front-end
3645    SUPER.get_frontend_or_backend_form = function(args){
3646        var final_form = (typeof args.form === 'undefined' ? undefined : args.form);
3647        if(args.el){
3648            // If field exists, try to find parent
3649            if(args.el.closest('.super-form')) final_form = args.el.closest('.super-form');
3650            if(args.el.closest('.super-preview-elements')) final_form = args.el.closest('.super-preview-elements');
3651        }else{
3652            // If field doesn't exist
3653            if(!args.form){
3654                if(document.querySelector('.super-preview-elements')) final_form = document.querySelector('.super-preview-elements');
3655                if(document.querySelector('.super-live-preview')) final_form = document.querySelector('.super-live-preview');
3656            }else{
3657                final_form = args.form;
3658            }
3659        }
3660        // If we couldn't find anything return document body
3661        if(!final_form) final_form = document.body;
3662        // @since 3.7.0 - check if we need to change the $form element to the form level instead of multi-part level
3663        if(final_form && final_form.classList.contains('super-multipart')){
3664            final_form = final_form.closest('.super-form');
3665        }
3666        return final_form;
3667    };
3668
3669    // After field value changed
3670    SUPER.after_field_change_blur_hook = function(args){
3671        args.form = SUPER.get_frontend_or_backend_form(args);
3672        var $functions = super_common_i18n.dynamic_functions.after_field_change_blur_hook;
3673        jQuery.each($functions, function(key, value){
3674            if(typeof SUPER[value.name] !== 'undefined') {
3675                SUPER[value.name](args);
3676            }
3677        });
3678        if( typeof args.el !== 'undefined'  && (args.skip!==true) ) {
3679            SUPER.auto_step_multipart(args);
3680        }
3681        SUPER.save_form_progress(args);
3682    };
3683
3684    // @since 4.9.0 - hook so that add-ons can initialize their elements more easily
3685    SUPER.after_init_common_fields = function(){
3686        var $functions = super_common_i18n.dynamic_functions.after_init_common_fields;
3687        jQuery.each($functions, function(key, value){
3688            if(typeof SUPER[value.name] !== 'undefined') {
3689                SUPER[value.name]();
3690            }
3691        });
3692    };
3693
3694    // @since 3.2.0 - save form progress
3695    SUPER.save_form_progress_timeout = null; 
3696    SUPER.save_form_progress = function(args){
3697        if( !args.form.classList.contains('super-save-progress') ) {
3698            return false;
3699        }
3700        if(SUPER.save_form_progress_timeout !== null){
3701            clearTimeout(SUPER.save_form_progress_timeout);
3702        }
3703        SUPER.save_form_progress_timeout = setTimeout(function () {
3704            SUPER.prepare_form_data($(args.form), function(formData){
3705                var $form_id = formData.form_id;
3706                formData = SUPER.after_form_data_collected_hook(formData.data);
3707                $.ajax({
3708                    url: super_common_i18n.ajaxurl,
3709                    type: 'post',
3710                    data: {
3711                        action: 'super_save_form_progress',
3712                        data: formData,
3713                        form_id: $form_id
3714                    }
3715                });
3716            });
3717        }, 1000); 
3718        // 1 second timeout, to make sure that we do not make unnecessary requests to the server
3719    };
3720
3721    // @since 1.2.8 
3722    SUPER.after_email_send_hook = function(args){
3723        var $event,
3724            ga = window[window.GoogleAnalyticsObject || 'ga'],
3725            $ga_tracking,
3726            $proceed,
3727            $values,
3728            $parameters;
3729
3730        if (typeof ga == 'function') {
3731            $ga_tracking = super_common_i18n.ga_tracking;
3732            $ga_tracking = $ga_tracking.split('\n');
3733            $($ga_tracking).each(function(index, value){
3734                // Check if this is a global event or for a specific form (based on form ID):
3735                $proceed = true;
3736                $values = value.split(":");
3737                if($values.length>1){
3738                    $event = $values[1].split("|");
3739                    if(!args.form.hasClass('super-form-'+$values[0])){
3740                        $proceed = false;
3741                    }
3742                }else{
3743                    $event = $values[0].split("|");
3744                }
3745
3746                // Only proceed if this was an event that needs to be executed globally, or if the ID matches the submitted form
3747                if($proceed){
3748                    if( ( (typeof $event[1] === 'undefined') || ($event[1]==='') ) || 
3749                        ( (typeof $event[2] === 'undefined') || ($event[2]==='') ) ) {
3750                        // eslint-disable-next-line no-console
3751                        console.log('Seems like we are missing required ga() parameters!');
3752                    }else{
3753
3754                        // Event Tracking
3755                        if( ($event[0]=='send') && ($event[1]=='event') ) {
3756                            if( (typeof $event[3] === 'undefined') || ($event[3]==='') ) {
3757                                // eslint-disable-next-line no-console
3758                                console.log('ga() is missing the "eventAction" parameter (The type of interaction e.g. "play")');
3759                            }else{
3760                                $parameters = {};
3761                                $parameters.hitType = $event[1];
3762                                $parameters.eventCategory = $event[2];
3763                                $parameters.eventAction = $event[3];
3764                                if( typeof $event[4] !== 'undefined' ) {
3765                                    $parameters.eventLabel = $event[4];
3766                                }
3767                                if( typeof $event[5] !== 'undefined' ) {
3768                                    $parameters.eventValue = $event[5];
3769                                }
3770                                ga($event[0], $parameters);
3771                            }
3772                        }
3773                    }
3774                }
3775
3776            });
3777        }
3778        var $functions = super_common_i18n.dynamic_functions.after_email_send_hook;
3779        jQuery.each($functions, function(key, value){
3780            if(typeof SUPER[value.name] !== 'undefined') {
3781                SUPER[value.name](args);
3782            }
3783        });
3784    };
3785
3786    // @since 1.3
3787    SUPER.after_responsive_form_hook = function($classes, $form, $new_class, $window_classes, $new_window_class){
3788        var $functions = super_common_i18n.dynamic_functions.after_responsive_form_hook;
3789        jQuery.each($functions, function(key, value){
3790            if(typeof SUPER[value.name] !== 'undefined') {
3791                SUPER[value.name]($classes, $form, $new_class, $window_classes, $new_window_class);
3792            }
3793        });    
3794    };
3795
3796    // Grab fields data and return all data as an object
3797    SUPER.prepare_form_data_fields = function($form){
3798        var $data = {},
3799            $field,
3800            $files;
3801
3802        $form.find('.super-shortcode-field').each(function(){
3803            var $this = $(this),
3804                $hidden = false,
3805                $parent = $this.parents('.super-shortcode:eq(0)'),
3806                $i,
3807                $new_value,
3808                $selected_items,
3809                $email_value,
3810                $item_value;
3811
3812            // Proceed only if it's a valid field (which must have a field name)
3813            if(typeof $this.attr('name')==='undefined') {
3814                return true;
3815            }
3816
3817            $this.parents('.super-shortcode.super-column').each(function(){
3818                if($(this).css('display')=='none'){
3819                    $hidden = true;
3820                }
3821            });
3822            
3823            if( ( $hidden===true )  || ( ( $parent.css('display')=='none' ) && ( !$parent.hasClass('super-hidden') ) ) ) {
3824                // Exclude conditionally
3825            }else{
3826                if($this.hasClass('super-fileupload')){
3827                    $parent = $this.parents('.super-field-wrapper:eq(0)');
3828                    $field = $parent.find('.super-active-files');
3829                    $files = $parent.find('.super-fileupload-files > div');
3830                    $data[$field.attr('name')] = {
3831                        'label':$field.data('email'),
3832                        'type':'files',
3833                        'exclude':$field.data('exclude'),
3834                        'exclude_entry':$field.data('exclude-entry'),
3835                        'files':{}};
3836                    $files.each(function($index,$file){
3837                        $file = $(this);
3838                        $data[$field.attr('name')].files[$index] = { 
3839                            'name':$field.attr('name'),
3840                            'value':$file.attr('data-name'),
3841                            'url':$file.attr('data-url'),
3842                            'label':$field.data('email'),
3843                            'exclude':$field.data('exclude'),
3844                            'exclude_entry':$field.data('exclude-entry'),
3845                            'excludeconditional':$field.data('excludeconditional'),
3846                        };
3847                    });
3848                }else{
3849                    $data[$this.attr('name')] = { 
3850                        'name':$this.attr('name'),
3851                        'value':$this.val(),
3852                        'label':$this.data('email'),
3853                        'exclude':$this.data('exclude'),
3854                        'replace_commas':$this.data('replace-commas'),
3855                        'exclude_entry':$this.data('exclude-entry'),
3856                        'excludeconditional':$this.data('excludeconditional'),
3857                        'type':'var'
3858                    };
3859
3860                    if($this.attr('name')==='mailchimp_list_id'){
3861                        if($this.attr('data-subscriber-tags')) $data[$this.attr('name')].subscriber_tags = $this.attr('data-subscriber-tags');
3862                        if($this.attr('data-vip')) $data[$this.attr('name')].vip = $this.attr('data-vip');
3863                    }
3864                    var $super_field = $this.parents('.super-field:eq(0)');
3865
3866                    // Check if international phonenumber field
3867                    if($super_field.hasClass('super-int-phone-field')){
3868                        var intPhone = window.superTelInputGlobals.getInstance($this[0]);
3869                        $data[$this.attr('name')].value = intPhone.getNumber();
3870                    }
3871
3872                    if($super_field.hasClass('super-signature')){
3873                        $data[$this.attr('name')].signatureLines = $super_field.find('.super-signature-lines').val();
3874                        //$data[$this.attr('name')].value = $super_field.find('.super-signature-canvas').signature('toJSON');
3875                    }
3876                    
3877                    if($super_field.hasClass('super-date')){
3878                        $data[$this.attr('name')].timestamp = $this[0].dataset.mathDiff;
3879                    }
3880
3881                    if($super_field.hasClass('super-textarea')){
3882                        $data[$this.attr('name')].type = 'text';
3883                    }
3884                    if($super_field.hasClass('super-html')){
3885                        $data[$this.attr('name')].type = 'html';
3886                    }
3887
3888                    // @since 3.2.0 - also save lat and lng for ACF google maps compatibility
3889                    if($this.hasClass('super-address-autopopulate')){
3890                        $data[$this.attr('name')].type = 'google_address';
3891                        $data[$this.attr('name')].geometry = {
3892                            location: {
3893                                'lat':$this.data('lat'),
3894                                'lng':$this.data('lng'),
3895                            }
3896                        };
3897                    }
3898                    
3899                    // @since 2.2.0 - generate unique code (make sure to save it after form completion)
3900                    if($super_field.hasClass('super-hidden')){
3901                        if($this.data('code')===true) {
3902                            $data[$this.attr('name')].code = 'true';
3903                            if($this.attr('data-invoice-padding')){
3904                                $data[$this.attr('name')].invoice_padding = $this.attr('data-invoice-padding');
3905                            }
3906                        }
3907                    }
3908
3909                    // @since 3.6.0 - replace correct data value for autosuggest fields
3910                    // @since 4.6.0 - replace correct data value for wc order search
3911                    if( $super_field.hasClass('super-auto-suggest') || $super_field.hasClass('super-wc-order-search') ) {
3912                        var $value = $super_field.find('.super-field-wrapper .super-dropdown-list > .super-active').attr('data-value');
3913                        if( typeof $value !== 'undefined' ) {
3914                            // Also make sure to always save the first value
3915                            $data[$this.attr('name')].value = $value.split(";")[0];
3916                        }
3917                    }
3918
3919                    if( $super_field.hasClass('super-dropdown') ) {
3920                        $i = 0;
3921                        $new_value = '';
3922                        $selected_items = $super_field.find('.super-field-wrapper .super-dropdown-list > .super-active');
3923                        $selected_items.each(function(){
3924                            if($i===0){
3925                                $new_value += $(this).text();
3926                                if($this.data('admin-email-value')=='both') {
3927                                    $new_value += ' ('+$(this).data('value')+')';
3928                                }
3929                            }else{
3930                                $new_value += ', '+$(this).text();
3931                                if($this.data('admin-email-value')=='both') {
3932                                    $new_value += ' ('+$(this).data('value')+')';
3933                                }
3934                            }
3935                            $i++;
3936                        });
3937                        $data[$this.attr('name')].option_label = $new_value;
3938
3939                        if( ($this.data('admin-email-value')=='label') || ($this.data('admin-email-value')=='both') ) {
3940                            $data[$this.attr('name')].admin_value = $new_value; 
3941                        }else{
3942                            $i = 0;
3943                            $new_value = '';
3944                            $selected_items.each(function(){
3945                                $item_value = $(this).data('value').toString().split(';');
3946                                if($i===0){
3947                                    $new_value += $item_value[0];
3948                                }else{
3949                                    $new_value += ', '+$item_value[0];
3950                                }
3951                                $i++;
3952                            });
3953                            $data[$this.attr('name')].value = $new_value; 
3954                        }
3955                        $email_value = $this.data('confirm-email-value');
3956                        if( ($email_value=='label') || ($email_value=='both') ) {
3957                            $i = 0;
3958                            $new_value = '';
3959                            $selected_items.each(function(){
3960                                $item_value = $(this).data('value').toString().split(';');
3961                                if($i===0){
3962                                    $new_value += $(this).text();
3963                                    if($email_value=='both') {
3964                                        $new_value += ' ('+$item_value[0]+')';
3965                                    }
3966                                }else{
3967                                    $new_value += ', '+$(this).text();
3968                                    if($email_value=='both') {
3969                                        $new_value += ' ('+$item_value[0]+')';
3970                                    }
3971                                }
3972                                $i++;
3973                            });
3974                            $data[$this.attr('name')].confirm_value = $new_value; 
3975                        }
3976                        $email_value = $this.data('contact-entry-value');
3977                        if( ($email_value=='label') || ($email_value=='both') ) {
3978                            $i = 0;
3979                            $new_value = '';
3980                            $selected_items.each(function(){
3981                                $item_value = $(this).data('value').toString().split(';');
3982                                if($i===0){
3983                                    $new_value += $(this).text();
3984                                    if($email_value=='both') {
3985                                        $new_value += ' ('+$item_value[0]+')';
3986                                    }
3987                                }else{
3988                                    $new_value += ', '+$(this).text();
3989                                    if($email_value=='both') {
3990                                        $new_value += ' ('+$item_value[0]+')';
3991                                    }
3992                                }
3993                                $i++;
3994                            });
3995                            $data[$this.attr('name')].entry_value = $new_value; 
3996                        }
3997                    }
3998                    if( $super_field.hasClass('super-checkbox') || $super_field.hasClass('super-radio') ) {
3999                        $i = 0;
4000                        $new_value = '';
4001                        $selected_items = $super_field.find('.super-field-wrapper .super-active');
4002                        $selected_items.each(function(){
4003                            $item_value = $(this).find('input').val().toString().split(';');
4004                            if($i===0){
4005                                $new_value += $(this).text();
4006                                if($this.data('admin-email-value')=='both') {
4007                                    $new_value += ' ('+$item_value[0]+')';
4008                                }
4009                            }else{
4010                                $new_value += ', '+$(this).text();
4011                                if($this.data('admin-email-value')=='both') {
4012                                    $new_value += ' ('+$item_value[0]+')';
4013                                }
4014                            }
4015                            $i++;
4016                        });
4017                        $data[$this.attr('name')].option_label = $new_value;
4018
4019                        if( ($this.data('admin-email-value')=='label') || ($this.data('admin-email-value')=='both') ) {
4020                            $data[$this.attr('name')].admin_value = $new_value; 
4021                        }else{
4022                            $i = 0;
4023                            $new_value = '';
4024                            $selected_items.each(function(){
4025                                $item_value = $(this).find('input').val().toString().split(';');
4026                                if($i===0){
4027                                    $new_value += $item_value[0];
4028                                }else{
4029                                    $new_value += ','+$item_value[0];
4030                                }
4031                                $i++;
4032                            });
4033                            $data[$this.attr('name')].value = $new_value; 
4034                        }
4035                        $email_value = $this.data('confirm-email-value');
4036                        if( ($email_value=='label') || ($email_value=='both') ) {
4037                            $i = 0;
4038                            $new_value = '';
4039                            $selected_items.each(function(){
4040                                $item_value = $(this).find('input').val().toString().split(';');
4041                                if($i===0){
4042                                    $new_value += $(this).text();
4043                                    if($email_value=='both') {
4044                                        $new_value += ' ('+$item_value[0]+')';
4045                                    }
4046                                }else{
4047                                    $new_value += ', '+$(this).text();
4048                                    if($email_value=='both') {
4049                                        $new_value += ' ('+$item_value[0]+')';
4050                                    }
4051                                }
4052                                $i++;
4053                            });
4054                            $data[$this.attr('name')].confirm_value = $new_value; 
4055                        }
4056                        $email_value = $this.data('contact-entry-value');
4057                        if( ($email_value=='label') || ($email_value=='both') ) {
4058                            $i = 0;
4059                            $new_value = '';
4060                            $selected_items.each(function(){
4061                                $item_value = $(this).find('input').val().toString().split(';');
4062                                if($i===0){
4063                                    $new_value += $(this).text();
4064                                    if($email_value=='both') {
4065                                        $new_value += ' ('+$item_value[0]+')';
4066                                    }
4067                                }else{
4068                                    $new_value += ', '+$(this).text();
4069                                    if($email_value=='both') {
4070                                        $new_value += ' ('+$item_value[0]+')';
4071                                    }
4072                                }
4073                                $i++;
4074                            });
4075                            $data[$this.attr('name')].entry_value = $new_value; 
4076                        }
4077                    }
4078                }
4079            }
4080        });
4081        return $data;
4082    };
4083
4084    // @since 3.2.0 - prepare form data
4085    SUPER.prepare_form_data = function($form, callback){
4086        var $data = SUPER.prepare_form_data_fields($form),
4087            $form_id = '',
4088            $entry_id = '',
4089            $list_id = '',
4090            $dynamic_columns = {},
4091            $dynamic_arrays = [],
4092            $map_key_names = [],
4093            $first_property_name,
4094            new_key,
4095            i,
4096            $dynamic_column_fields_data;
4097
4098        // Loop through all dynamic columns and create an JSON string based on all the fields
4099        $form.find('.super-column[data-duplicate-limit]').each(function(){
4100            $dynamic_arrays = [];
4101            $map_key_names = [];
4102            $first_property_name = undefined;
4103            $(this).find('.super-duplicate-column-fields').each(function(){
4104                $dynamic_column_fields_data = SUPER.prepare_form_data_fields($(this));
4105                if(typeof $first_property_name === 'undefined'){
4106                    $first_property_name = Object.getOwnPropertyNames($dynamic_column_fields_data)[0];
4107                }
4108                $dynamic_arrays.push($dynamic_column_fields_data);
4109            });
4110            if($first_property_name!==undefined){
4111                Object.keys($dynamic_arrays[0]).forEach(function(key) {
4112                    $map_key_names.push(key);
4113                });
4114                Object.keys($dynamic_arrays).forEach(function(key) {
4115                    if(key>0){
4116                        i = 0;
4117                        Object.keys($dynamic_arrays[key]).forEach(function(old_key) {
4118                            new_key = $map_key_names[i];
4119                            if (old_key !== new_key) {
4120                                Object.defineProperty($dynamic_arrays[key], new_key, Object.getOwnPropertyDescriptor($dynamic_arrays[key], old_key));
4121                                delete $dynamic_arrays[key][old_key];
4122                            }
4123                            i++;
4124                        });
4125                    }
4126                });
4127                $dynamic_columns[$first_property_name] = $dynamic_arrays;
4128            }
4129        });
4130        if(Object.keys($dynamic_columns).length>0){
4131            $data._super_dynamic_data = $dynamic_columns;
4132        }
4133
4134        if($form.find('input[name="hidden_form_id"]').length !== 0) {
4135            $form_id = $form.find('input[name="hidden_form_id"]').val();
4136        }
4137        $data.hidden_form_id = { 
4138            'name':'hidden_form_id',
4139            'value':$form_id,
4140            'type':'form_id'
4141        };
4142
4143        // @since 2.2.0 - update contact entry by ID
4144        if($form.find('input[name="hidden_contact_entry_id"]').length !== 0) {
4145            $entry_id = $form.find('input[name="hidden_contact_entry_id"]').val();
4146        }
4147        $data.hidden_contact_entry_id = { 
4148            'name':'hidden_contact_entry_id',
4149            'value':$entry_id,
4150            'type':'entry_id'
4151        };
4152
4153        // When editing entry via Listings add-on
4154        if($form.find('input[name="hidden_list_id"]').length !== 0) {
4155            $list_id = $form.find('input[name="hidden_list_id"]').val();
4156        }
4157
4158        // Generate new nonce
4159        $.ajax({
4160            url: super_common_i18n.ajaxurl,
4161            type: 'post',
4162            data: {
4163                action: 'super_create_nonce'
4164            },
4165            success: function (nonce) {
4166                // Update new nonce
4167                $('input[name="sf_nonce"]').val(nonce);
4168            },
4169            complete: function(){
4170                if(typeof callback === 'function'){
4171                    callback({
4172                        data:$data, 
4173                        form_id:$form_id, 
4174                        entry_id:$entry_id, 
4175                        list_id:$list_id,
4176                        sf_nonce: $form.find('input[name="sf_nonce"]').val()
4177                    });
4178                }
4179
4180            },
4181            error: function (xhr, ajaxOptions, thrownError) {
4182                // eslint-disable-next-line no-console
4183                console.log(xhr, ajaxOptions, thrownError);
4184                alert('Could not generate nonce');
4185            }
4186        });
4187
4188    };
4189
4190    // @since 1.3
4191    SUPER.after_form_data_collected_hook = function(data){
4192        var i, name, functions = super_common_i18n.dynamic_functions.after_form_data_collected_hook;
4193        for ( i = 0; i < functions.length; i++) {
4194            name = functions[i].name;
4195            if(typeof SUPER[name] !== 'undefined') {
4196                data = SUPER[name](data);
4197            }
4198        }
4199        return data;
4200    };
4201
4202    // @since 1.3
4203    SUPER.after_duplicate_column_fields_hook = function(el, field, counter, column, fieldNames, fieldLabels){
4204        var i, name, functions = super_common_i18n.dynamic_functions.after_duplicate_column_fields_hook;
4205        for ( i = 0; i < functions.length; i++) {
4206            name = functions[i].name;
4207            if(typeof SUPER[name] !== 'undefined') {
4208                SUPER[name](el, field, counter, column, fieldNames, fieldLabels);
4209            }
4210        }
4211    };
4212
4213    // @since 3.3.0
4214    SUPER.after_appending_duplicated_column_hook = function(form, uniqueFieldNames, clone){
4215        var i, name, functions = super_common_i18n.dynamic_functions.after_appending_duplicated_column_hook;
4216        for ( i = 0; i < functions.length; i++) {
4217            name = functions[i].name;
4218            if(typeof SUPER[name] !== 'undefined') {
4219                SUPER[name](form, uniqueFieldNames, clone);
4220            }
4221        }
4222    };
4223
4224    // @since 2.4.0
4225    SUPER.after_duplicating_column_hook = function(form, uniqueFieldNames, clone){
4226        var i, name, functions = super_common_i18n.dynamic_functions.after_duplicating_column_hook;
4227        for ( i = 0; i < functions.length; i++) {
4228            name = functions[i].name;
4229            if(typeof SUPER[name] !== 'undefined') {
4230                SUPER[name](form, uniqueFieldNames, clone);
4231            }
4232        }
4233    };
4234
4235    // @since 1.9
4236    SUPER.before_submit_button_click_hook = function(e, $submit_button){
4237        var $proceed = true;
4238        var $functions = super_common_i18n.dynamic_functions.before_submit_button_click_hook;
4239        jQuery.each($functions, function(key, value){
4240            if(typeof SUPER[value.name] !== 'undefined') {
4241                $proceed = SUPER[value.name](e, $proceed, $submit_button);
4242            }
4243        });
4244        return $proceed;
4245    };
4246    SUPER.after_preview_loaded_hook = function($form_id){
4247        var $functions = super_common_i18n.dynamic_functions.after_preview_loaded_hook;
4248        jQuery.each($functions, function(key, value){
4249            if(typeof SUPER[value.name] !== 'undefined') {
4250                SUPER[value.name]($form_id);
4251            }
4252        });
4253    };
4254
4255    // @since 2.0.0
4256    SUPER.after_form_cleared_hook = function(form){
4257        var functions = super_common_i18n.dynamic_functions.after_form_cleared_hook;
4258        jQuery.each(functions, function(key, value){
4259            if(typeof SUPER[value.name] !== 'undefined') {
4260                SUPER[value.name](form);
4261            }
4262        });
4263    };
4264
4265    // @since 2.1.0
4266    SUPER.before_scrolling_to_error_hook = function(form, scroll){
4267        var proceed = true;
4268        var functions = super_common_i18n.dynamic_functions.before_scrolling_to_error_hook;
4269        jQuery.each(functions, function(key, value){
4270            if(typeof SUPER[value.name] !== 'undefined') {
4271                proceed = SUPER[value.name](proceed, form, scroll);
4272            }
4273        });
4274        return proceed;
4275    };
4276    SUPER.before_scrolling_to_message_hook = function($form, $scroll){
4277        var $proceed = true;
4278        var $functions = super_common_i18n.dynamic_functions.before_scrolling_to_message_hook;
4279        jQuery.each($functions, function(key, value){
4280            if(typeof SUPER[value.name] !== 'undefined') {
4281                $proceed = SUPER[value.name]($proceed, $form, $scroll);
4282            }
4283        });
4284        return $proceed;
4285    };
4286
4287    // @since 3.0.0 - google maps API for places auto complete/populate and other libraries such as:
4288    
4289    // drawing provides a graphical interface for users to draw polygons, rectangles, pol
4289ylines, circles, and markers on the map. 
4290    // Consult the Drawing library documentation for more information.
4291
4292    // geometry includes utility functions for calculating scalar geometric values (such as distance and area) on the surface of the earth. 
4293    // Consult the Geometry library documentation for more information.
4294
4295    // places enables your application to search for places such as establishments, geographic locations, or prominent points of interest, within a defined area.
4296    // Consult the Places library documentation for more information.
4297
4298    // visualization provides heatmaps for visual representation of data.
4299    // Consult the Visualization library documentation for more information.
4300
4301    SUPER.google_maps_api = function(){};
4302    SUPER.google_maps_init = function(args){
4303        if(typeof args === 'undefined') args = {};
4304        if(!args.form) return true;
4305        // @since 3.0.0
4306        SUPER.google_maps_api.initAutocomplete(args);
4307        // @since 3.5.0
4308        SUPER.google_maps_api.initMaps(args);
4309    };
4310
4311    SUPER.get_field_name = function(field){
4312        if(field.classList.contains('super-fileupload')){
4313            field = field.parentNode.querySelector('.super-active-files');
4314        }
4315        if(field.name) return field.name;
4316    };
4317    SUPER.get_original_field_name = function(field){
4318        if(field.classList.contains('super-fileupload')){
4319            field = field.parentNode.querySelector('.super-active-files');
4320        }
4321        if(field.dataset.oname) return field.dataset.oname;
4322    };
4323    SUPER.get_field_type = function(form, name){
4324        var node = form.querySelector('.super-shortcode-field[name="'+name+'"]');
4325        if(node) {
4326            return {field: node, type: node.type}
4327        }
4328        node = form.querySelector('.super-active-files[name="'+name+'"]');
4329        if(node) {
4330            return {field: node, type: 'file'}
4331        }
4332        return {field: undefined, type: 'text'}
4333    };
4334
4335    SUPER.strip_tags = function(input,allowed){
4336        allowed = (((allowed || "") + "").toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join(''); // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
4337        var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi, commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
4338        return input.replace(commentsAndPhpTags, '').replace(tags, function ($0, $1) { return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : ''; });
4339    }
4340
4341
4342    // @since 3.5.0 - function for intializing google maps elements
4343    SUPER.google_maps_api.allMaps = [];
4344    SUPER.google_maps_api.initMaps = function(args){
4345        var $form_id = 0;
4346        if(args.form.querySelector('input[name="hidden_form_id"]')){
4347            $form_id = args.form.querySelector('input[name="hidden_form_id"]').value;
4348        }
4349
4350        if(typeof SUPER.google_maps_api.allMaps[$form_id] === 'undefined'){
4351            SUPER.google_maps_api.allMaps[$form_id] = [];
4352        }
4353
4354        var $maps;
4355        if(!args.el){
4356            $maps = args.form.querySelectorAll('.super-google-map:not(.super-map-rendered)');
4357        }else{
4358            var field_name = SUPER.get_original_field_name(args.el);
4359            $maps = args.form.querySelectorAll('.super-google-map[data-fields*="{'+field_name+'}"]');
4360        }
4361
4362        // Loop through maps
4363        Object.keys($maps).forEach(function(key) {
4364            $maps[key].classList.add('super-map-rendered');
4365            var $data = JSON.parse($maps[key].querySelector('textarea').value);
4366                // Address Marker location
4367                args.value = $data.address;
4368                var $address = SUPER.update_variable_fields.replace_tags(args);
4369                // Directions API (route)
4370                args.value = $data.origin;
4371                var $origin = SUPER.update_variable_fields.replace_tags(args);
4372                args.value = $data.destination;
4373                var $destination = SUPER.update_variable_fields.replace_tags(args);
4374                args.value = $data.directionsPanel;
4375                var $directionsPanel = SUPER.update_variable_fields.replace_tags(args);
4376                var $populateDistance = $data.populateDistance;
4377                var $populateDuration = $data.populateDuration;
4378                args.value = $data.travelMode;
4379                var $travelMode = SUPER.update_variable_fields.replace_tags(args);
4380                args.value = $data.unitSystem;
4381                var $unitSystem = SUPER.update_variable_fields.replace_tags(args);
4382                // Waypoints
4383                args.value = $data.optimizeWaypoints;
4384                var $optimizeWaypoints = SUPER.update_variable_fields.replace_tags(args);
4385                args.value = $data.provideRouteAlternatives;
4386                var $provideRouteAlternatives = SUPER.update_variable_fields.replace_tags(args);
4387                args.value = $data.avoidFerries;
4388                var $avoidFerries = SUPER.update_variable_fields.replace_tags(args);
4389                args.value = $data.avoidHighways;
4390                var $avoidHighways = SUPER.update_variable_fields.replace_tags(args);
4391                args.value = $data.avoidTolls;
4392                var $avoidTolls = SUPER.update_variable_fields.replace_tags(args);
4393                args.value = $data.region;
4394                var $region = SUPER.update_variable_fields.replace_tags(args);
4395                // we will implement this in a later version  DRIVING mode (only when travelMode is DRIVING)
4396                // we will implement this in a later version  $departureTime = SUPER.update_variable_fields.replace_tags(args),
4397                // we will implement this in a later version  $trafficModel = SUPER.update_variable_fields.replace_tags(args),
4398                // we will implement this in a later version  TRANSIT mode (only when travelMode is TRANSIT)
4399                // we will implement this in a later version  $transitArrivalTime = SUPER.update_variable_fields.replace_tags(args),
4400                // we will implement this in a later version  $transitDepartureTime = SUPER.update_variable_fields.replace_tags(args),
4401                // we will implement this in a later version  $transitModes = SUPER.update_variable_fields.replace_tags(args),
4402                // we will implement this in a later version  $routingPreference = SUPER.update_variable_fields.replace_tags(args),
4403                // UI Settings
4404                args.value = $data.disableDefaultUI;
4405                var $disableDefaultUI = SUPER.update_variable_fields.replace_tags(args);
4406                args.value = $data.zoom;
4407                var $zoom = SUPER.update_variable_fields.replace_tags(args);
4408                if($zoom==='') $zoom = 5; // Default to 5
4409                $zoom = parseInt($zoom, 10);
4410                var $address_marker = $data.address_marker,
4411                $polyline_stroke_weight = $data.polyline_stroke_weight,
4412                $polyline_stroke_color = $data.polyline_stroke_color,
4413                $polyline_stroke_opacity = $data.polyline_stroke_opacity,
4414                // currently not in use? $polyline_geodesic = $data.polyline_geodesic,
4415                $polylines,
4416                $path = [],
4417                $coordinates,
4418                $lat,
4419                $lng,
4420                $field_name,
4421                $lat_min = '',
4422                $lat_max = '',
4423                $lng_min = '',
4424                $lng_max = '',
4425                Path,
4426                geocoder;
4427
4428                // Only if map wasn't yet initialized
4429                SUPER.google_maps_api.allMaps[$form_id][key] = new google.maps.Map(document.getElementById('super-google-map-'+$form_id), {
4430                    center: {lat: 0, lng: 0},
4431                    zoom: $zoom,
4432                    disableDefaultUI: ('true' === $disableDefaultUI),
4433                    //mapTypeId: \'terrain\'
4434                });
4435                SUPER.google_maps_api.allMaps[$form_id][key]['super_el'] = $maps[key];
4436                //SUPER.google_maps_api.allMaps[formId][i].setOptions({
4437                //});
4438
4439            // Draw Polylines
4440            if( $data.enable_polyline=='true' ) {
4441                $polylines = $data.polylines.split('\n');
4442                $($polylines).each(function(index, value){
4443                    $coordinates = value.split("|");
4444                    $lat = $coordinates[0];
4445                    $lng = $coordinates[1];
4446                    // If {tag} was found
4447                    var regex = /{([^\\\/\s"'+]*?)}/g;
4448                    if(regex.exec($lat)!==null){
4449                        $field_name = $lat.replace('{','').replace('}','');                       
4450                        $lat = SUPER.field(args.form, $field_name).dataset.lat;
4451                        if(!$lat) $lat = 0;
4452                    }
4453                    if(regex.exec($lng)!==null){
4454                        $field_name = $lng.replace('{','').replace('}','');
4455                        $lng = SUPER.field(args.form, $field_name).dataset.lng;
4456                        if(!$lng) $lng = 0;
4457                    }
4458                    $lat = parseFloat($lat);
4459                    $lng = parseFloat($lng);
4460                    // Add markers at each point
4461                    if( $lat!==0 && $lng!==0 ) {
4462                        new google.maps.Marker({
4463                            position: {lat: $lat, lng: $lng},
4464                            map: SUPER.google_maps_api.allMaps[$form_id][key]
4465                        });
4466                    }
4467                    $path.push({lat: $lat, lng: $lng});
4468                    if( $lat_min==='' ) {
4469                        $lat_min = $lat;
4470                        $lat_max = $lat;
4471                        $lng_min = $lng;
4472                        $lng_max = $lng;
4473                    } 
4474                    if($lat_min>$lat) $lat_min = $lat;
4475                    if($lat_max<$lat) $lat_max = $lat;
4476                    if($lng_min>$lng) $lng_min = $lng;
4477                    if($lng_max<$lng) $lng_max = $lng;
4478                });
4479                if( $lat_min===0 || $lat_max===0 || $lng_min===0 || $lng_max===0 ) {
4480                    SUPER.google_maps_api.allMaps[$form_id][key].setCenter(new google.maps.LatLng(
4481                        (($lat_max + $lat_min) / 2.0),
4482                        (($lng_max + $lng_min) / 2.0)
4483                    ));                    
4484                }else{
4485                    SUPER.google_maps_api.allMaps[$form_id][key].setCenter(new google.maps.LatLng(
4486                        (($lat_max + $lat_min) / 2.0),
4487                        (($lng_max + $lng_min) / 2.0)
4488                    ));
4489                    SUPER.google_maps_api.allMaps[$form_id][key].fitBounds(new google.maps.LatLngBounds(
4490                        new google.maps.LatLng($lat_min, $lng_min), // bottom left
4491                        new google.maps.LatLng($lat_max, $lng_max) //top right
4492                    ));
4493                    Path = new google.maps.Polyline({
4494                        path: $path,
4495                        // currently not in use? geodesic: $polyline_geodesic,
4496                        strokeColor: $polyline_stroke_color,
4497                        strokeOpacity: $polyline_stroke_opacity,
4498                        strokeWeight: $polyline_stroke_weight
4499                    });
4500                    Path.setMap(SUPER.google_maps_api.allMaps[$form_id][key]);
4501                }
4502            }
4503
4504            // If directions panel is enabled
4505            var target, panel=null;
4506            target = args.form.querySelector('.super-google-map-'+$form_id);
4507            if($directionsPanel=='true'){
4508                if(target.parentNode.querySelector('.super-google-map-directions')){
4509                    target.parentNode.querySelector('.super-google-map-directions').remove();
4510                }
4511                if( ($origin==='') || ($destination==='') ) {
4512                    target.parentNode.classList.remove('super-has-
4512panel');
4513                }else{
4514                    target.parentNode.classList.add('super-has-panel');
4515                    // Only create if not exists
4516                    if(!target.parentNode.querySelector('.super-google-map-directions')){
4517                        panel = document.createElement('div');
4518                        panel.classList.add('super-google-map-directions');
4519                        panel.style.height = target.parentNode.offsetHeight+'px';
4520                        panel.style.overflowY = "scroll";
4521                        target.parentNode.appendChild(panel);
4522                        // this is only used when PDF addon is released var printBtn = document.createElement('div');
4523                        // this is only used when PDF addon is released printBtn.classList.add('super-google-map-print');
4524                        // this is only used when PDF addon is released printBtn.innerHTML = 'Print';
4525                        // this is only used when PDF addon is released target.parentNode.appendChild(printBtn);
4526                        // this is only used when PDF addon is released if(typeof jsPDF !== 'undefined') {
4527                        // this is only used when PDF addon is released     printBtn.addEventListener('click', function(){
4528                        // this is only used when PDF addon is released         var pdf = new jsPDF();
4529                        // this is only used when PDF addon is released         // Starting at page 1
4530                        // this is only used when PDF addon is released         if(typeof SUPER.generate_pdf !== 'undefined') {
4531                        // this is only used when PDF addon is released             SUPER.generate_pdf(target, pdf, 1, function(pdf){
4532                        // this is only used when PDF addon is released                 // Finally we download the PDF file
4533                        // this is only used when PDF addon is released                 pdf.save("download-page-1.pdf");
4534                        // this is only used when PDF addon is released             }); 
4535                        // this is only used when PDF addon is released         }
4536                        // this is only used when PDF addon is released     });
4537                        // this is only used when PDF addon is released }
4538                    }
4539                }
4540            }
4541
4542            // Set Directions (route)
4543            if( ($origin!=='') && ($destination!=='') ) {
4544                var directionsService = new google.maps.DirectionsService();
4545                var directionsRenderer = new google.maps.DirectionsRenderer({
4546                    draggable: true,
4547                    map: SUPER.google_maps_api.allMaps[$form_id][key],
4548                    panel: ($directionsPanel=='true' ? SUPER.google_maps_api.allMaps[$form_id][i]['super_el'].querySelector('.super-google-map-directions') : null)
4549                    // panel: document.getElementById('right-panel')
4550                });
4551                //directionsRenderer.setMap($map);
4552                // If waypoints is not empty make sure to create a proper object for it
4553                if($data.waypoints!==''){
4554                    var w = $data.waypoints.split('\n');
4555                    var i = 0;
4556                    var $xw = [];
4557                    for( i=0; i < w.length; i++ ) {
4558                        // Get waypoint location
4559                        var v = w[i].split('|');
4560                        if(typeof v[1] === 'undefined') v[1] = 'false';
4561                        // {waypoint;2}
4562                        var location = v[0].replace('{','').replace('}','');
4563                        var isTag = false;
4564                        if(location!==v[0]) isTag = true;
4565                        var advancedTags = location.split(';');
4566                        var fieldName = advancedTags[0];
4567                        var originFieldName = fieldName;
4568                        var advancedIndex = "";
4569                        if(advancedTags[1]){
4570                            advancedIndex = advancedTags[1];
4571                        }
4572
4573                        // {stopover;2}
4574                        var stopover = v[1].replace('{','').replace('}','');
4575                        var stopoverIsTag = false;
4576                        if(stopover!==v[1]) stopoverIsTag = true;
4577                        var stopoverAdvancedTags = stopover.split(';');
4578                        var stopoverFieldName = stopoverAdvancedTags[0];
4579                        var originStopoverFieldName = stopoverFieldName;
4580                        var stopoverAdvancedIndex = "";
4581                        if(stopoverAdvancedTags[1]){
4582                            stopoverAdvancedIndex = stopoverAdvancedTags[1];
4583                        }
4584
4585                        // Check if either one is a tag, if so look for dynamic columns
4586                        if(isTag || stopoverIsTag){
4587                            var x=2;
4588                            var dynamicFieldName = originFieldName+'_'+x;
4589                            var stopoverDynamicFieldName = originStopoverFieldName+'_'+x;
4590                            var found = SUPER.field_exists(args.form, dynamicFieldName);
4591                            var stopoverFound = SUPER.field_exists(args.form, stopoverDynamicFieldName);
4592                            var rows = '';
4593                            while(found || stopoverFound){
4594                                // Location
4595                                var tag = '';
4596                                if(isTag){
4597                                    tag = '{'+dynamicFieldName+'}';
4598                                    if(advancedIndex!==''){ tag = '{'+dynamicFieldName+';'+advancedIndex+'}'; }
4599                                }else{
4600                                    tag = location;
4601                                }
4602                                rows += tag;
4603
4604                                // Stopover
4605                                if(stopoverIsTag){
4606                                    tag = '{'+stopoverDynamicFieldName+'}';
4607                                    if(stopoverAdvancedIndex!==''){ tag = '{'+stopoverDynamicFieldName+';'+stopoverAdvancedIndex+'}'; }
4608                                }else{
4609                                    tag = stopover;
4610                                }
4611                                // Stopover
4612                                rows += "|"+tag+"\n";
4613                                // Find for next field and if it exists we add it
4614                                x++;
4615                                dynamicFieldName = fieldName+'_'+x;
4616                                found = SUPER.field_exists(args.form, dynamicFieldName)
4617                            }
4618                        }
4619                        var waypoints = w[i]+"\n"+rows;
4620                        var xw = waypoints.split("\n");
4621                        i = 0;
4622                        for(i=0; i < xw.length; i++){
4623                            if(xw[i]==='') continue;
4624                            var values = xw[i].split('|');
4625                            args.value = values[0];
4626                            location = SUPER.update_variable_fields.replace_tags(args);
4627                            // Waypoint may not be empty!
4628                            if(location==='') continue;
4629                            args.value = values[1];
4630                            stopover = SUPER.update_variable_fields.replace_tags(args);
4631                            stopover = ('true'===stopover); // convert to boolean
4632                            $xw.push({ location: location, stopover: stopover });
4633                        }
4634                    }
4635                }
4636                var request = {
4637                    origin: $origin,
4638                    destination: $destination,
4639                    travelMode: $travelMode,
4640                    unitSystem: google.maps.UnitSystem[$unitSystem],
4641                    waypoints: $xw, 
4642                    optimizeWaypoints: ('true' === $optimizeWaypoints),
4643                    provideRouteAlternatives: ('true' === $provideRouteAlternatives),
4644                    avoidFerries: ('true' === $avoidFerries),
4645                    avoidHighways: ('true' === $avoidHighways),
4646                    avoidTolls: ('true' === $avoidTolls),
4647                    region: $region // 'US', 'NL', 'DE', 'UK' etc.
4648                };
4649
4650                // we will implement this in a later version  // transitOptions (only when travelMode is TRANSIT)
4651                // we will implement this in a later version  if($travelMode==='TRANSIT'){
4652                // we will implement this in a later version      request['transitOptions'] = {
4653                // we will implement this in a later version          arrivalTime: $transitArrivalTime,
4654                // we will implement this in a later version          departureTime: $transitDepartureTime,
4655                // we will implement this in a later version          modes: $transitModes, // ['BUS'],
4656                // we will implement this in a later version          routingPreference: $routingPreference // 'FEWER_TRANSFERS', 'LESS_WALKING'
4657                // we will implement this in a later version      }
4658                // we will implement this in a later version  }
4659
4660                // we will implement this in a later version  // drivingOptions (only when travelMode is DRIVING)
4661                // we will implement this in a later version  if($travelMode==='DRIVING'){
4662                // we will implement this in a later version      if($departureTime==='') $departureTime = new Date(Date.now() + 0); // departureTime: new Date(Date.now() + N),  // for the time N milliseconds from now.
4663                // we will implement this in a later version      if($trafficModel==='') $trafficModel = 'bestguess';
4664                // we will implement this in a later version      request['drivingOptions'] = {
4665                // we will implement this in a later version          departureTime: $departureTime,
4666                // we will implement this in a later version          trafficModel: $trafficModel
4667                // we will implement this in a later version      }
4668                // we will implement this in a later version  }
4669
4670                directionsService.route(request, function (result, status) {
4671                    if (status == 'OK') {
4672                        directionsRenderer.setDirections(result);
4673                        if($directionsPanel=='true'){
4674                            var totalDist = 0;
4675                            var totalTime = 0;
4676                            var myroute = result.routes[0];
4677                            for (var i = 0; i < myroute.legs.length; i++) {
4678                                totalDist += myroute.legs[i].distance.value; // indicates the distance in meters even when unitSystem is set to "IMPERIAL"
4679                                totalTime += myroute.legs[i].duration.value; // indicates the duration in seconds
4680                            }
4681                            // var distance;
4682                            // var unit = 'km';
4683                            // if($unitSystem=='IMPERIAL') {
4684                            //     // Convert meters to miles
4685                            //     distance = (totalDist / 1609).toFixed(1);
4686                            //     unit = 'mile';
4687                            // }else{
4688                            //     distance = (totalDist / 1000).toFixed(1);
4689                            // }
4690                            // var timeUnit;
4691                            // if((totalTime / 60).toFixed(2) >= 60){
4692                            //     timeUnit = "hours";
4693                            //     if((totalTime / 60).toFixed(2) == 60){
4694                            //         timeUnit = "hour";
4695                            //     }
4696                            // }else{
4697                            //     timeUnit = "minutes";
4698                            //     if((totalTime / 60).toFixed(2) == 1){
4699                            //         timeUnit = "minute";
4700                            //     }
4701                            // }
4702                            // var time = ((totalTime / 60).toFixed(2) < 60 ? (totalTime / 60).toFixed(0) : (totalTime / 60 / 60).toFixed(1));
4703                            // html = "<strong>Distance:</strong> " + distance + " "+unit+"<br /><strong>Duration:</strong> " + time + " " + timeUnit + "<br />" + html;
4704                            // panel.innerHTML = html;
4705
4706                            // Populate fields with values if defined
4707                            var field; 
4708                            if($populateDistance!==''){
4709                                // Check if field exists in this form
4710                                if(SUPER.field_exists(args.form, $populateDistance)){
4711                                    field = SUPER.field(args.form, $populateDistance);
4712                                    field.value = totalDist; // indicates the distance in meters
4713                                    SUPER.after_field_change_blur_hook({el: field});
4714                                }
4715                            }
4716                            if($populateDuration!==''){
4717                                // Check if field exists in this form
4718                                if(SUPER.field_exists(args.form, $populateDuration)){
4719                                    field = SUPER.field(args.form, $populateDuration);
4720                                    field.value = totalTime; // indicates the duration in seconds
4721                                    SUPER.after_field_change_blur_hook({el: field});
4722                                }
4723                            }
4724                        }
4725                    }else{
4726                        // Display error message
4727                        result = {
4728                            msg: 'Route was not successful for the following reason: ' + status,
4729                            loading: true,
4730                            error: true
4731                        }
4732                        SUPER.form_submission_finished(args, result);
4733                    }
4734                });
4735                return true;
4736            }
4737
4738            // Add Address Marker
4739            if( $address!=='' ) {
4740                geocoder = new google.maps.Geocoder();
4741                geocoder.geocode( { 'address': $address}, function(result, status) {
4742                    if (status == 'OK') {
4743                        // Center map based on given address
4744                        SUPER.google_maps_api.allMaps[$form_id][key].setCenter(result[0].geometry.location);
4745                        // Add marker on address location
4746                        if( $address_marker=='true' ) {
4747                            new google.maps.Marker({
4748                                map: SUPER.google_maps_api.allMaps[$form_id][key],
4749                                position: result[0].geometry.location
4750                            });
4751                        }
4752                    } else {
4753                        // Display error message
4754                        result = {
4755                            msg: 'Geocode was not successful for the following reason: ' + status,
4756                            loading: true,
4757                            error: true
4758                        }
4759                        SUPER.form_submission_finished(args, result);
4760                    }
4761                });
4762                return true;
4763            }
4764        });
4765    };
4766
4767    SUPER.google_maps_api.initAutocomplete = function(args){
4768        var url, field, items = args.form.querySelectorAll('.super-address-autopopulate:not(.super-autopopulate-init)');
4769        Object.keys(items).forEach(function(key) {
4770            field = items[key];
4771            field.classList.add('super-autopopulate-init');
4772            args.el = field;
4773            if(typeof google === 'undefined'){
4774                url = '//maps.googleapis.com/maps/api/js?';
4775                if(field.dataset.apiRegion!=='') url += 'region='+field.dataset.apiRegion+'&';
4776                if(field.dataset.apiLanguage!=='') url += 'language='+field.dataset.apiLanguage+'&';
4777                url += 'key='+field.dataset.apiKey+'&libraries=drawing,geometry,places,visualization&callback=SUPER.google_maps_init'
4778                $.getScript( url, function() {
4779                    SUPER.google_maps_api.initAutocompleteCallback(args);
4780                });
4781            }else{
4782                SUPER.google_maps_api.initAutocompleteCallback(args);
4783            }
4784        });
4785    };
4786    SUPER.google_maps_api.initAutocompleteCallback = function(args){
4787        var i, x, s, obj = {}, inputField, autocomplete = [];
4788            autocomplete[args.el.name] = new google.maps.places.Autocomplete(args.el);
4789        var mapping = {
4790            street_number: 'street_number',
4791            route: 'street_name',
4792            locality: 'city', // see: https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete-addressform
4793            postal_town: 'city', // see: https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete-addressform
4794            sublocality_level_1: 'city', // see: https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete-addressform
4795            administrative_area_level_2: 'municipality',
4796            administrative_area_level_1: 'state',
4797            country: 'country',
4798            postal_code: 'postal_code',
4799            lat: 'lat',
4800            lng: 'lng'
4801        };
4802        
4803        // Check if any of the address components is mapped
4804        var $returnAddressComponent = false;
4805        for (var key in mapping) {
4806            if($(args.el).data('map-'+mapping[key])){
4807                $returnAddressComponent = true;
4808            }
4809        }
4810        
4811        var $returnName = false;
4812        if($(args.el).data('map-name')) $returnName = true;
4813
4814        mapping.formatted_phone_number = 'formatted_phone_number';
4815        var $returnFormattedPhoneNumber = false;
4816        if($(args.el).data('map-formatted_phone_number')) $returnFormattedPhoneNumber = true;
4817
4818        mapping.international_phone_number = 'international_phone_number';
4819        var $returnInternationalPhoneNumber = false;
4820        if($(args.el).data('map-international_phone_number')) $returnInternationalPhoneNumber = true;
4821
4822        mapping.website = 'website';
4823        var $returnWebsite = false;
4824        if($(args.el).data('map-website')) $returnWebsite = true;
4825
4826        var fields = ['formatted_address', 'geometry.location']; // This data is always used
4827        if($returnAddressComponent) fields.push('address_components');
4828        if($returnName) fields.push('name');
4829        if($returnFormattedPhoneNumber) fields.push('formatted_phone_number');
4830        if($returnInternationalPhoneNumber) fields.push('international_phone_number');
4831        if($returnWebsite) fields.push('website');
4832
4833        var thisAutocomplete = autocomplete[args.el.name];
4834        thisAutocomplete.setFields(fields);
4835        thisAutocomplete.el = args.el;
4836        thisAutocomplete.form = args.form;
4837
4838        s = $(args.el).data('countries'); // Could be empty or a comma seperated string e.g: fr,nl,de
4839        if(s){
4840            x = s.split(',');
4841            obj.countries = [];
4842            for(i=0; i<x.length; i++){
4843                obj.countries.push(x[i].trim());
4844            }
4845            thisAutocomplete.setComponentRestrictions({
4846                country: obj.countries, // e.g: ["us", "pr", "vi", "gu", "mp"],
4847            });
4848        }
4849        s = $(args.el).data('types'); // Could be empty or a comma seperated string e.g: fr,nl,de
4850        if(s){
4851            x = s.split(',');
4852            obj.types = [];
4853            for(i=0; i<x.length; i++){
4854                obj.types.push(x[i].trim());
4855            }
4856            thisAutocomplete.setTypes(obj.types);
4857        }
4858        thisAutocomplete.addListener( 'place_changed', function () {
4859            // Set text field to the formatted address
4860            var place = thisAutocomplete.getPlace();
4861            thisAutocomplete.el.value = place.formatted_address;
4862            SUPER.calculate_distance({el: thisAutocomplete.el});
4863
4864            var street_data = {
4865                number: {
4866                    long: '',
4867                    short: ''
4868                },
4869                name: {
4870                    long: '',
4871                    short: ''
4872                }
4873            };
4874
4875            // @since 3.2.0 - add address latitude and longitude for ACF google map compatibility
4876            var lat = place.geometry.location.lat();
4877            var lng = place.geometry.location.lng();
4878            thisAutocomplete.el.dataset.lat = lat;
4879            thisAutocomplete.el.dataset.lng = lng;
4880
4881            // @since 3.5.0 - trigger / update google maps in case {tags} have been used
4882            args.el = thisAutocomplete.el;
4883            args.form = thisAutocomplete.form;
4884            SUPER.google_maps_init(args);
4885
4886            $(thisAutocomplete.el).trigger('keyup');
4887            var $attribute;
4888            var $val;
4889            var $address;
4890            
4891            if($returnAddressComponent){
4892                place.address_components.push({
4893                    long_name: lat,
4894                    short_name: lat,
4895                    types: ["lat"]
4896                });
4897                place.address_components.push({
4898                    long_name: lng,
4899                    short_name: lng,
4900                    types: ["lng"]
4901                });
4902                for (var i = 0; i < place.address_components.length; i++) {
4903                    var item = place.address_components[i];
4904                    var long = item.long_name;
4905                    var short = item.short_name;
4906                    var types = item.types;
4907                    // Street number
4908                    if(types.indexOf('street_number')!==-1){
4909                        street_data.number.long = long;
4910                        street_data.number.short = short;
4911                    }
4912                    // Street name
4913                    if(types.indexOf('route')!==-1){
4914                        street_data.name.long = long;
4915                        street_data.name.short = short;
4916                    }
4917                    $attribute = $(thisAutocomplete.el).data('map-'+mapping[types[0]]);
4918                    if(typeof $attribute !=='undefined'){
4919                        $attribute = $attribute.split('|');
4920                        inputField = SUPER.field(thisAutocomplete.form, $attribute[0]);
4921                        if(inputField){
4922                            if($attribute[1]==='') $attribute[1] = 'long';
4923                            $val = place.address_components[i][$attribute[1]+'_name'];
4924                            inputField.value = $val;
4925                            if($val===''){
4926                                inputField.closest('.super-shortcode').classList.remove('super-filled');
4927                            }else{
4928                                inputField.closest('.super-shortcode').classList.add('super-filled');
4929                            }
4930                            SUPER.after_field_change_blur_hook({el: inputField}); // @since 3.1.0 - trigger hooks after changing the value
4931                        }
4932                    }
4933                }
4934            }
4935
4936            // Name of the place
4937            $attribute = $(thisAutocomplete.el).data('map-name');
4938            if(typeof $attribute !=='undefined'){
4939                $attribute = $attribute.split('|');
4940                inputField = SUPER.field(thisAutocomplete.form, $attribute[0]);
4941                if(inputField){
4942                    if($attribute[1]==='') $attribute[1] = 'long';
4943                    $val = place.name;
4944                    inputField.value = $val;
4945                    if($val===''){
4946                        inputField.closest('.super-shortcode').classList.remove('super-filled');
4947                    }else{
4948                        inputField.closest('.super-shortcode').classList.add('super-filled');
4949                    }
4950                    SUPER.after_field_change_blur_hook({el: inputField}); // @since 3.1.0 - trigger hooks after changing the value
4951                }
4952            }
4953
4954            // Formatted address of the place
4955            $attribute = $(thisAutocomplete.el).data('map-formatted_address');
4956            if(typeof $attribute !=='undefined'){
4957                $attribute = $attribute.split('|');
4958                inputField = SUPER.field(thisAutocomplete.form, $attribute[0]);
4959                if(inputField){
4960                    if($attribute[1]==='') $attribute[1] = 'long';
4961                    $val = place.formatted_address;
4962                    inputField.value = $val;
4963                    if($val===''){
4964                        inputField.closest('.super-shortcode').classList.remove('super-filled');
4965                    }else{
4966                        inputField.closest('.super-shortcode').classList.add('super-filled');
4967                    }
4968                    SUPER.after_field_change_blur_hook({el: inputField}); // @since 3.1.0 - trigger hooks after changing the value
4969                }
4970            }
4971
4972            // Formatted phone number
4973            $attribute = $(thisAutocomplete.el).data('map-formatted_phone_number');
4974            if(typeof $attribute !=='undefined'){
4975                $attribute = $attribute.split('|');
4976                inputField = SUPER.field(thisAutocomplete.form, $attribute[0]);
4977                if(inputField){
4978                    if($attribute[1]==='') $attribute[1] = 'long';
4979                    $val = place.formatted_phone_number;
4980                    inputField.value = $val;
4981                    if($val===''){
4982                        inputField.closest('.super-shortcode').classList.remove('super-filled');
4983                    }else{
4984                        inputField.closest('.super-shortcode').classList.add('super-filled');
4985                    }
4986                    SUPER.after_field_change_blur_hook({el: inputField}); // @since 3.1.0 - trigger hooks after changing the value
4987                }
4988            }
4989
4990            // International phone number
4991            $attribute = $(thisAutocomplete.el).data('map-international_phone_number');
4992            if(typeof $attribute !=='undefined'){
4993                $attribute = $attribute.split('|');
4994                inputField = SUPER.field(thisAutocomplete.form, $attribute[0]);
4995                if(inputField){
4996                    if($attribute[1]==='') $attribute[1] = 'long';
4997                    $val = place.international_phone_number;
4998                    inputField.value = $val;
4999                    if($val===''){
5000                        inputField.closest('.super-shortcode').classList.remove('super-filled');
5001                    }else{
5002                        inputField.closest('.super-shortcode').classList.add('super-filled');
5003                    }
5004                    SUPER.after_field_change_blur_hook({el: inputField}); // @since 3.1.0 - trigger hooks after changing the value
5005                }
5006            }
5007
5008            // Busniness website
5009            $attribute = $(thisAutocomplete.el).data('map-website');
5010            if(typeof $attribute !=='undefined'){
5011                $attribute = $attribute.split('|');
5012                inputField = SUPER.field(thisAutocomplete.form, $attribute[0]);
5013                if(inputField){
5014                    if($attribute[1]==='') $attribute[1] = 'long';
5015                    $val = place.website;
5016                    inputField.value = $val;
5017                    if($val===''){
5018                        inputField.closest('.super-shortcode').classList.remove('super-filled');
5019                    }else{
5020                        inputField.closest('.super-shortcode').classList.add('super-filled');
5021                    }
5022                    SUPER.after_field_change_blur_hook({el: inputField}); // @since 3.1.0 - trigger hooks after changing the value
5023                }
5024            }
5025
5026            // @since 3.5.0 - combine street name and number
5027            $attribute = $(thisAutocomplete.el).data('map-street_name_number');
5028            if( typeof $attribute !=='undefined' ) {
5029                $attribute = $attribute.split('|');
5030                inputField = SUPER.field(thisAutocomplete.form, $attribute[0]);
5031                if(inputField){
5032                    $address = '';
5033                    if( street_data.name[$attribute[1]]!=='' ) $address += street_data.name[$attribute[1]];
5034                    if( $address!=='' ) {
5035                        $address += ' '+street_data.number[$attribute[1]];
5036                    }else{
5037                        $address += street_data.number[$attribute[1]];
5038                    }
5039                    inputField.value = $address;
5040                    if($address===''){
5041                        inputField.closest('.super-shortcode').classList.remove('super-filled');
5042                    }else{
5043                        inputField.closest('.super-shortcode').classList.add('super-filled');
5044                    }
5045                    SUPER.after_field_change_blur_hook({el: inputField}); // @since 3.1.0 - trigger hooks after changing the value
5046                }
5047            }
5048
5049            // @since 3.5.1 - combine street number and name
5050            $attribute = $(thisAutocomplete.el).data('map-street_number_name');
5051            if( typeof $attribute !=='undefined' ) {
5052                $attribute = $attribute.split('|');
5053                inputField = SUPER.field(thisAutocomplete.form, $attribute[0]);
5054                if(inputField){
5055                    $address = '';
5056                    if( street_data.number[$attribute[1]]!=='' ) $address += street_data.number[$attribute[1]];
5057                    if( $address!=='' ) {
5058                        $address += ' '+street_data.name[$attribute[1]];
5059                    }else{
5060                        $address += street_data.name[$attribute[1]];
5061                    }
5062                    inputField.value = $address;
5063                    if($address===''){
5064                        inputField.closest('.super-shortcode').classList.remove('super-filled');
5065                    }else{
5066                        inputField.closest('.super-shortcode').classList.add('super-filled');
5067                    }
5068                    SUPER.after_field_change_blur_hook({el: inputField}); // @since 3.1.0 - trigger hooks after changing the value
5069                }
5070            }
5071        });
5072    };
5073
5074    // Checkbox handler
5075    SUPER.checkboxes = function(){
5076        $('.super-checkbox').each(function(){
5077            var $value = '';
5078            var $counter = 0;
5079            var $checked = $(this).find('input[type="checkbox"]:checked');
5080            $checked.each(function () {
5081                if ($counter === 0) $value = $(this).val();
5082                if ($counter !== 0) $value = $value + ',' + $(this).val();
5083                $counter++;
5084            });
5085            $(this).find('input[type="hidden"]').val($value);
5086        });
5087        $('.super-radio, .super-shipping').each(function(){
5088            var $name = $(this).find('.super-shortcode-field').attr('name');
5089            $(this).find('input[type="radio"]').attr('name','group_'+$name);
5090        });
5091        $('.super-shipping').each(function(){
5092            if(!$(this).hasClass('html-finished')){
5093                var $currency = $(this).find('.super-shortcode-field').attr('data-currency');
5094                $(this).find('input[type="radio"]').each(function(){
5095                    var $html = $(this).parent().html();
5096                    var $value = $(this).val();
5097                    $(this).parent().html($html+'<span class="super-shipping-price"> &#8212; '+$currency+''+parseFloat($value).toFixed(2)+'</span>');
5098                });
5099                $(this).addClass('html-finished');
5100            }        
5101        });
5102    };
5103
5104    // @since 3.2.0 - Reverse columns
5105    SUPER.reverse_columns = function($form){
5106        $($form).find('.super-grid').each(function(){
5107            var $grid = $(this);
5108            var $columns = $grid.children('div.super-column:not(.super-not-responsive)');
5109            $grid.append($columns.get().reverse());
5110            $grid.children('div.super-column:last-child').removeClass('first-column');
5111            $grid.children('div.super-column:eq(0)').addClass('first-column');
5112        });
5113    };
5114
5115    // Handle columns
5116    SUPER.handle_columns = function(){
5117        var $this,
5118            $exclusion,
5119            $fields,
5120            $width = 0;
5121
5122        $('div.super-field').each(function(){
5123            if($(this).hasClass('super-grouped')){
5124                if((!$(this).prev().hasClass('super-grouped')) || ($(this).prev().hasClass('super-grouped-end'))){
5125                    $(this).addClass('super-grouped-start'); 
5126                }
5127            }
5128        });
5129        $('.super-field > .super-label').each(function () {
5130            if($(this).parent().index()); 
5131            if (!$(this).parent().hasClass('super-grouped')) {
5132                if ($(this).outerWidth(true) > $width) $width = $(this).outerWidth(true);
5133            }
5134        });
5135        //Checkbox fields
5136        SUPER.checkboxes();
5137        //Barcodes
5138        SUPER.generateBarcode();
5139        //Rating
5140        SUPER.rating();
5141
5142        var forms = document.querySelectorAll('.super-form');
5143        Object.keys(forms).forEach(function(key) {
5144            $this = forms[key];
5145
5146            // @since 3.2.0 
5147            // Add tab indexes to all fields
5148            // Check if RTL support is enabled, if so we must reverse columns order before we add TAB indexes to fields
5149            if( $this.classList.contains('super-rtl') ) {
5150                // Reverse column order before adding TAB indexes
5151                SUPER.reverse_columns($this);
5152            }
5153            // - After we reverted the column order, loop through all the fields and add the correct TAB indexes
5154            $exclusion = super_common_i18n.tab_index_exclusion;
5155
5156            $fields = $($($this).find('.super-field:not('+$exclusion+')').get());
5157            $fields.each(function(key, value){
5158                $(value).attr('data-super-tab-index', key);
5159            });
5160            // Now we have added the TAB indexes, make sure to reverse the order back to normal in case of RTL support
5161            if( $this.classList.contains('super-rtl') ) {
5162                SUPER.reverse_columns($this);
5163            }
5164            // Because of the FireFox bug with adaptive placeholders we must loop over all fields to check if they are not empty.
5165            // if the field is not empty we will add the super-filled class to it's parent node
5166            var i=0, el, value, nodes = $this.querySelectorAll('.super-text .super-shortcode-field, .super-textarea .super-shortcode-field, .super-currency .super-shortcode-field, .super-dropdown .super-shortcode-field');
5167            for(i=0; i<nodes.length; i++){
5168                if(nodes[i].value!==''){
5169                    el = nodes[i].closest('.super-shortcode');
5170                    if(el.querySelector('.super-adaptive-placeholder')){
5171                        el.querySelector('.super-adaptive-placeholder').children[0].innerHTML = el.querySelector('.super-adaptive-placeholder').dataset.placeholderfilled;
5172                        el.classList.add('super-filled');
5173                    }
5174                }
5175            }
5176            // ... but for signatures (if used)
5177            nodes = $this.querySelectorAll('.super-signature');
5178            for(i=0; i<nodes.length; i++){
5179                value = nodes[i].querySelector('.super-signature-lines').value;
5180                if(value!==''){
5181                    value = value.replace('\\"lines\\"', '"lines"');
5182                    $(nodes[i]).find('.super-signature-canvas').signature('enable').signature('draw', value);
5183                }
5184            }
5185            // .. but for toggle field
5186            nodes = $this.querySelectorAll('.super-toggle .super-shortcode-field');
5187            for(i=0; i<nodes.length; i++){
5188                if(nodes[i].value!==''){
5189                    el = nodes[i].closest('.super-shortcode');
5190                    if(nodes[i].value===el.querySelector('.super-toggle-on').dataset.value){
5191                        el.querySelector('.super-toggle-switch').classList.add('super-active');
5192                    }
5193                }
5194            }
5195            // .. but for radio buttons
5196            nodes = $this.querySelectorAll('.super-radio .super-shortcode-field');
5197            for(i=0; i<nodes.length; i++){
5198                if(nodes[i].value!==''){
5199                    el = nodes[i].closest('.super-shortcode');
5200                    var items = el.querySelectorAll('.super-item');
5201                    for(var ii = 0; ii < items.length; ii++){
5202                        var input = items[ii].querySelector('input');
5203                        if(input.value == nodes[i].value){
5204                            input.checked = true;
5205                            items[ii].classList.add('super-active');
5206                            break; // Radio button can only have 1 active item
5207                        }
5208                    }
5209                }
5210            }
5211            // .. but for checkboxes
5212            nodes = $this.querySelectorAll('.super-checkbox .super-shortcode-field');
5213            for(i=0; i<nodes.length; i++){
5214                if(nodes[i].value!==''){
5215                    el = nodes[i].closest('.super-shortcode');
5216                    items = el.querySelectorAll('.super-item');
5217                    for(ii = 0; ii < items.length; ii++){
5218                        input = items[ii].querySelector('input');
5219                        items[ii].classList.remove('super-active');
5220                        input.checked = false;
5221                        var options = nodes[i].value.split(',');
5222                        if(options.indexOf(input.value)!==-1){
5223                            input.checked = true;
5224                            items[ii].classList.add('super-active');
5225                        }
5226                    }
5227                }
5228            }
5229
5230            // Collect arguments to be parsed to the after initialization hook
5231            var args = {
5232                el: undefined,
5233                form: $this,
5234                callback: function(args){
5235                    args.form.classList.add('super-rendered');
5236                    if (!args.form.classList.contains('preload-disabled')) {
5237                        if (!args.form.classList.contains('super-initialized')) {
5238                            setTimeout(function (){
5239                                $(args.form).fadeOut(100, function () {
5240                                    args.form.classList.add('super-initialized');
5241                                    $(args.form).fadeIn(500);
5242                                });
5243                            }, 500);
5244                        }
5245                    } else {
5246                        args.form.classList.add('super-initialized');
5247                    }
5248                }
5249            };
5250            SUPER.after_initializing_forms_hook(args);
5251
5252            // Trigger fake windows resize
5253            var resizeEvent = window.document.createEvent('UIEvents');
5254            resizeEvent.initUIEvent('resize', true, false, window, 0);
5255            window.dispatchEvent(resizeEvent);
5256        });
5257
5258    };
5259
5260    // Remove responsive class from the form
5261    SUPER.remove_super_form_classes = function($this, $classes){
5262        $.each($classes, function( k, v ) {
5263            $this.removeClass(v);
5264        });
5265    };
5266
5267    // Escape any user input to prepare for injection into HTML (prevents XSS)
5268    SUPER.html_encode = function(value){
5269        return String(value).replace(/[^\w. ]/gi, function(c){
5270            return '&#'+c.charCodeAt(0)+';';
5271        });
5272    };
5273
5274    // Replace HTML element {tags} with field values
5275    // @since 1.2.7
5276    SUPER.init_replace_html_tags = function(args){
5277        var originalFormReference,
5278            decodeHtml,
5279            $i,
5280            $v,
5281            $row_regex,
5282            $html_fields,
5283            $target,
5284            $html,
5285            $originalHtml,
5286            $splitName,
5287            $newName,
5288            $original,
5289            $field_name,
5290            $value_n,
5291            $original_field_name,
5292            $rv,
5293            $return,
5294            $rows,
5295            $row,
5296            $regex,
5297            $array,
5298            $values,
5299            $new_value,
5300            $match,
5301            $fileLoopRows = [],
5302            formId = parseInt(args.form.id.replace('super-form-', ''), 10);
5303
5304        // Only when not on canvas in builder mode
5305        if(args.form.classList.contains('super-preview-elements')){
5306            return false;
5307        }
5308
5309        // Continue otherwise
5310        if(typeof args.foundElements !== 'undefined') {
5311            if(args.foundElements.length>0){
5312                $html_fields = args.foundElements;
5313            }else{
5314                $html_fields = args.form.querySelectorAll('[data-tags], .super-google-map, .super-html-content');
5315            }
5316        }else{
5317            if(typeof args.el === 'undefined') {
5318                $html_fields = args.form.querySelectorAll('[data-tags], .super-google-map, .super-html-content');
5319            }else{
5320                var n = SUPER.get_original_field_name(args.el);
5321                $html_fields = args.form.querySelectorAll('[data-tags*="{'+n+'}"], .super-google-map[data-fields*="{'+n+'}"], .super-html-content[data-fields*="{'+n+'}"]');
5322            }
5323        }
5324        $regex = /{([^\\\/\s"'+]*?)}/g;
5325        Object.keys($html_fields).forEach(function(key) {
5326            var $counter = 0;
5327            $target = $html_fields[key];
5328            // @since 4.9.0 - accordion title description {tags} compatibility
5329            if( $target.dataset.tags ) {
5330                $html = $target.dataset.original;
5331                //classList.contains('super-heading-title') || $target.classList.contains('super-heading-description') || 
5332                //$target.classList.contains('super-tab-title') || $target.classList.contains('super-tab-desc') || 
5333                //$target.classList.contains('super-accordion-title') || $target.classList.contains('super-accordion-desc') ) {
5334            }else{
5335                if(!$target.parentNode.querySelector('textarea')){
5336                    return true;
5337                }
5338                $html = $target.parentNode.querySelector('textarea').value;
5339            }
5340            // If empty skip
5341            if($html===''){
5342                return true;
5343            }
5344            
5345            // When generating PDF, we must have a reference to the original form
5346            originalFormReference = args.form;
5347            if(args.form.classList.contains('super-generating-pdf')){
5348                originalFormReference = document.querySelector('#super-form-'+formId+'-placeholder');
5349            }
5350
5351            // @since 5.0.120 - foreach statement compatibility
5352            $regex = /<%(.*?)%>|{(.*?)}/;
5353            var $skipUpdate = true;
5354            if ((m = $regex.exec($html)) !== null) {
5355                $skipUpdate = false;
5356            }
5357            $html = SUPER.filter_foreach_statements($target, 0, 0, $html, undefined, formId, originalFormReference);
5358            $html = $html.replaceAll('<%', '{');
5359            $html = $html.replaceAll('%>', '}');
5360
5361            // Check if html contains {tags}, if not we don't have to do anything.
5362            // This also solves bugs with for instance third party plugins
5363            // That use shortcodes to initialize elements, which initialization would be lost
5364            // upon updating the HTML content based on {tags}.
5365            // This can be solved by NOT using either of the {} curly braces inside the HTML content
5366            $regex = /({|foreach\()([-_a-zA-Z0-9\[\]]{1,})(\[.*?])?(?:;([a-zA-Z0-9]{1,}))?(}|\):)/g;
5367            // If it has {tags} then continue
5368            var m;
5369            var replaceTagsWithValue = {};
5370            while ((m = $regex.exec($html)) !== null) {
5371                decodeHtml = true;
5372                $skipUpdate = false;
5373                // This is necessary to avoid infinite loops with zero-width matches
5374                if (m.index === $regex.lastIndex) {
5375                    $regex.lastIndex++;
5376                }
5377                var $n = (m[2] ? m[2] : ''); // name
5378                var $d = (m[3] ? m[3] : ''); // depth
5379                var $s = (m[4] ? m[4] : ''); // suffix
5380                if($s==='allFileNames' || $s==='allFileUrls' || $s==='allFileLinks'){
5381                    decodeHtml = false;
5382                }else{
5383                    var fieldType = SUPER.get_field_type(originalFormReference, $n);
5384                    if($s==='' && fieldType.type==='file'){
5385                        decodeHtml = false;
5386                    }
5387                }
5388                // Get field type
5389                if($s!=='') $s = ';'+$s;
5390                $values = $n+$d+$s;
5391                args.value = '{'+$values+'}'; //values[1];
5392                args.target = $target;
5393                $new_value = SUPER.update_variable_fields.replace_tags(args);
5394                delete args.target;
5395                if(decodeHtml){
5396                    $new_value = SUPER.html_encode($new_value);
5397                }
5398                replaceTagsWithValue[$values] = $new_value;
5399            }
5400            var key;
5401            for(key in replaceTagsWithValue) {
5402                $html = $html.replaceAll('{'+key+'}', replaceTagsWithValue[key]);
5403            }
5404            if($skipUpdate) return true;
5405            // @since 4.6.0 - if statement compatibility
5406            $html = SUPER.filter_if_statements($html);
5407            
5408            if($target.value || $target.dataset.value){
5409                if($target.value) $target.value = $html;
5410                if($target.dataset.value) $target.dataset.value = $html;
5411            }else{
5412                $target.innerHTML = $html;
5413            }
5414            var $parent = $target.closest('.super-shortcode');
5415            if($parent){
5416                var $field = $parent.querySelector('.super-shortcode-field');
5417                if($field) $field.value = $html;
5418            }
5419        });
5420    };
5421
5422    // Replace datepickers default value {tags} with field values
5423    SUPER.init_replace_datepicker_default_value_tags = function(args){
5424        var i, nodes;
5425        if(typeof args.el === 'undefined') {
5426            nodes = args.form.querySelectorAll('.super-shortcode-field.super-datepicker');
5427        }else{
5428            nodes = args.form.querySelectorAll('.super-shortcode-field.super-datepicker[data-absolute-default*="{'+SUPER.get_field_name(args.el)+'}"]');
5429        }
5430        // Update default value for datepickers in case they contain {tags}
5431        for(i=0; i<nodes.length; i++){
5432            var absoluteDefault = nodes[i].dataset.absoluteDefault,
5433                $match,
5434                $regex = /{([^\\\/\s"'+]*?)}/g,
5435                $array = [],
5436                $counter = 0,
5437                $values,
5438                $new_value;
5439            if(absoluteDefault==='') continue;
5440            while (($match = $regex.exec(absoluteDefault)) !== null) {
5441                $array[$counter] = $match[1];
5442                $counter++;
5443            }
5444            if( $array.length===0 ) continue;
5445            if( $array.length>0 ) {
5446                for ($counter = 0; $counter < $array.length; $counter++) {
5447                    $values = $array[$counter];
5448                    args.value = '{'+$values+'}';
5449                    args.target = args.form;
5450                    $new_value = SUPER.update_variable_fields.replace_tags(args);
5451                    delete args.target;
5452                    absoluteDefault = absoluteDefault.replace('{'+$values+'}', $new_value);
5453                }
5454            }
5455            nodes[i].classList.remove('super-picker-initialized');
5456            SUPER.init_datepicker(nodes[i]);
5457            $(nodes[i]).datepicker('setDate', absoluteDefault);
5458        }
5459    };
5460
5461    // Replace form action attribute {tags} with field values
5462    // @since 4.4.6
5463    SUPER.init_replace_post_url_tags = function(args){
5464        var $match,
5465            $target = args.form.querySelector('form'),
5466            $actiontags = ($target ? $target.dataset.actiontags : ''),
5467            $regex = /{([^\\\/\s"'+]*?)}/g,
5468            $array = [],
5469            $counter = 0,
5470            $values,
5471            $new_value;
5472
5473        // Only if action is defined
5474        if($target){
5475            while (($match = $regex.exec($actiontags)) !== null) {
5476                $array[$counter] = $match[1];
5477                $counter++;
5478            }
5479            if( $array.length>0 ) {
5480                for ($counter = 0; $counter < $array.length; $counter++) {
5481                    $values = $array[$counter];
5482                    args.value = '{'+$values+'}';
5483                    args.target = $target;
5484                    $new_value = SUPER.update_variable_fields.replace_tags(args);
5485                    delete args.target;
5486                    $actiontags = $actiontags.replace('{'+$values+'}', $new_value);
5487                }
5488            }
5489            $target.action = $actiontags;
5490        }
5491    };
5492
5493    // Init text editors
5494    SUPER.init_text_editors = function(){
5495        if( typeof tinyMCE !== 'undefined' ) {
5496            $('.super-text-editor:not(.super-initialized)').each(function(){
5497                var $this = $(this),
5498                    $name = $this.attr('id'),
5499                    $incl_url = $this.data('incl-url');
5500
5501                tinyMCE.execCommand('mceRemoveEditor', true, $name);
5502                var tinyMCEPreInit = {
5503                    baseURL: $this.data('baseurl'),
5504                    suffix: '.min',
5505                    mceInit: {},
5506                    qtInit: {},
5507                    ref: {},
5508                    load_ext: function(url,lang){
5509                        var sl=tinyMCE.ScriptLoader;
5510                        sl.markDone(url+'/langs/'+lang+'.js');
5511                        sl.markDone(url+'/langs/'+lang+'_dlg.js');
5512                    }
5513                };
5514                tinyMCEPreInit.mceInit[$name] = {
5515                    theme:"modern",
5516                    skin:"lightgray",
5517                    language:"en",
5518                    formats:{
5519                        alignleft: [{
5520                            selector: "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li", 
5521                            styles: {
5522                                textAlign:"left"
5523                            }
5524                        },{
5525                            selector: "img,table,dl.wp-caption", 
5526                            classes: "alignleft"
5527                        }],
5528                        aligncenter: [{
5529                            selector: "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li", 
5530                            styles: {
5531                                textAlign:"center"
5532                            }
5533                        },{
5534                            selector: "img,table,dl.wp-caption", 
5535                            classes: "aligncenter"
5536                        }],
5537                        alignright: [{
5538                            selector: "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li", 
5539                            styles: {
5540                                textAlign:"right"
5541                            }
5542                        },{
5543                            selector: "img,table,dl.wp-caption", 
5544                            classes: "alignright"
5545                        }],strikethrough: {
5546                            inline: "del"
5547                        }
5548                    },
5549                    relative_urls:false,
5550                    remove_script_host:false,
5551                    convert_urls:false,
5552                    browser_spellcheck:true,
5553                    fix_list_elements:true,
5554                    entities:"38,amp,60,lt,62,gt",
5555                    entity_encoding:"raw",
5556                    keep_styles:false,
5557                    cache_suffix:"wp-mce-4310-20160418",
5558                    preview_styles:"font-family font-size font-weight font-style text-decoration text-transform",
5559                    end_container_on_empty_block:true,
5560                    wpeditimage_disable_captions:false,
5561                    wpeditimage_html5_captions:true,
5562                    // @since 4.0.0 - delete 'wpembed' from plugin list  because Wordpress 4.8 and latest tinymce dropped wpembed 
5563                    plugins:"charmap,colorpicker,hr,lists,media,paste,tabfocus,textcolor,fullscreen,wordpress,wpautoresize,wpeditimage,wpemoji,wpgallery,wplink,wpdialogs,wptextpattern,wpview",
5564                    wp_lang_attr:"en-US",
5565                    content_css:$incl_url+"/css/dashicons.css,"+$incl_url+"/js/tinymce/skins/wordpress/wp-content.css",
5566                    selector:"#"+$name,
5567                    resize:"vertical",
5568                    menubar:false,
5569                    wpautop:false,
5570                    indent:false,
5571                    toolbar1:"bold,italic,strikethrough,bullist,numlist,blockquote,hr,alignleft,aligncenter,alignright,link,unlink,wp_more,spellchecker,fullscreen,wp_adv",
5572                    toolbar2:"formatselect,underline,alignjustify,forecolor,pastetext,removeformat,charmap,outdent,indent,undo,redo,wp_help",
5573                    toolbar3:"",
5574                    toolbar4:"",
5575                    tabfocus_elements:":prev,:next",
5576                    body_class:$name+" post-type-page post-status-publish locale-en-us"
5577                };
5578
5579                tinyMCEPreInit.qtInit[$name] = {
5580                    id:$name,
5581                    buttons:"strong,em,link,block,del,ins,img,ul,ol,li,code,more,close"
5582                };
5583
5584                tinyMCEPreInit.ref = {
5585                    // @since 4.0.0 - delete 'wpembed' from plugin list  because Wordpress 4.8 and latest tinymce dropped wpembed 
5586                    plugins:"charmap,colorpicker,hr,lists,media,paste,tabfocus,textcolor,fullscreen,wordpress,wpautoresize,wpeditimage,wpemoji,wpgallery,wplink,wpdialogs,wptextpattern,wpview",
5587                    theme:"modern",
5588                    language:"en"
5589                };
5590
5591                if( ($this.data('teeny')=='true') || ($this.data('teeny')===true) ){
5592                    tinyMCEPreInit.mceInit[$name].toolbar2 = false;
5593                }
5594                if( ($this.data('force-br')=='true') || ($this.data('force-br')===true) ){
5595                    tinyMCEPreInit.mceInit[$name].forced_root_block = false;
5596                    tinyMCEPreInit.mceInit[$name].force_br_newlines = true;
5597                    tinyMCEPreInit.mceInit[$name].force_p_newlines = false;
5598                    tinyMCEPreInit.mceInit[$name].convert_newlines_to_brs = true;
5599                }
5600
5601                var init, id, $wrap;
5602                for ( id in tinyMCEPreInit.mceInit ) {
5603                    init = tinyMCEPreInit.mceInit[id];
5604                    $wrap = tinyMCE.$( '#wp-' + id + '-wrap' );
5605                    if ( ( $wrap.hasClass( 'tmce-active' ) || ! Object.prototype.hasOwnProperty.call(tinyMCEPreInit.qtInit, id) ) && ! init.wp_skip_init ) {
5606                        tinyMCE.init( init );
5607                        if ( ! window.wpActiveEditor ) {
5608                            window.wpActiveEditor = id;
5609                        }
5610                    }
5611                }
5612                for ( id in tinyMCEPreInit.qtInit ) {
5613                    quicktags( tinyMCEPreInit.qtInit[id] );
5614
5615                    if ( ! window.wpActiveEditor ) {
5616                        window.wpActiveEditor = id;
5617                    }
5618                }
5619            });
5620        }
5621    };
5622
5623    // @since 2.0.0 - set dropdown placeholder function
5624    SUPER.init_set_dropdown_placeholder = function($form){
5625        if(typeof $form === 'undefined') $form = $('.super-form');
5626
5627        $form.find('.super-dropdown-list').each(function(){
5628            var $this = $(this);
5629            var $field = $this.parent('.super-field-wrapper').find('.super-shortcode-field');
5630            var $first_item = $this.find('.super-item:eq(1)');
5631
5632            // @since 3.1.0 - first check if the field is not empty by GET or POST
5633            var $value = $field.val();
5634            if($value===''){
5635                // @since   1.1.8    - check if we can find a default value
5636                $value = $field.data('default-value');
5637            }
5638
5639            if( (typeof $value !== 'undefined') &&  ($value!=='') ) {
5640                $field.val($value);
5641                var $new_placeholder = '';
5642                $value = $value.toString().split(',');
5643                $.each($value, function( index, value ) {
5644                    value = $.trim(value).split(';')[0];
5645                    // Lets find the option name based on the matched value
5646                    $this.find('.super-item:not(.super-placeholder)').each(function(){
5647                        var $item_first_value = $(this).attr('data-value').split(';')[0];
5648                        if($item_first_value==value){
5649                            $(this).addClass('super-active');
5650                            if($new_placeholder===''){
5651                                $new_placeholder += $(this).html();
5652                            }else{
5653                                $new_placeholder += ', '+$(this).html();
5654                            }
5655                        }
5656                    });
5657                });
5658                // Only if placeholder is not empty
5659                if($new_placeholder!=='') $this.children('.super-placeholder').html($new_placeholder);
5660            }else{
5661                $field.val('');
5662                var $placeholder = $field.attr('placeholder');
5663                if( (typeof $placeholder !== 'undefined') &&  ($placeholder!=='') ) {
5664                    $this.children('.super-placeholder').attr('data-value', '').html($placeholder);
5665                }else{
5666                    if($this.children('.super-placeholder').html()===''){
5667                        $first_item.addClass('super-active');
5668                        $this.children('.super-placeholder').attr('data-value', $first_item.attr('data-value')).html($first_item.html());
5669                    }
5670                }
5671            }
5672        });
5673    };
5674
5675    // @since 3.1.0 - print form data
5676    SUPER.init_print_form = function(args){
5677        var items,
5678            $data,
5679            $parent,
5680            $css,
5681            nodes,
5682            el,
5683            $items,
5684            i, ii,
5685            $file_id,
5686            win = window.open('','printwindow'),
5687            $html = '',
5688            $print_file = args.submitButton.querySelector('input[name="print_file"]');
5689        if( $print_file && $print_file.value!=='' && $print_file.value!='0' ) {
5690            // @since 3.9.0 - print custom HTML
5691            $file_id = $print_file.value;
5692            SUPER.prepare_form_data($(args.form), function(formData){
5693                formData = SUPER.after_form_data_collected_hook(formData.data);
5694                $.ajax({
5695                    url: super_common_i18n.ajaxurl,
5696                    type: 'post',
5697                    data: {
5698                        action: 'super_print_custom_html',
5699                        data: formData,
5700                        file_id: $file_id
5701                    },
5702                    success: function (result) {
5703                        win.document.write(result);
5704                        win.document.close();
5705                        win.focus();
5706                        // @since 2.3 - chrome browser bug
5707                        setTimeout(function() {
5708                            win.print();
5709                            win.close();
5710                        }, 250);
5711                        return false;
5712                    },
5713                    error: function (xhr, ajaxOptions, thrownError) {
5714                        // eslint-disable-next-line no-console
5715                        console.log(xhr, ajaxOptions, thrownError);
5716                        alert(super_common_i18n.errors.failed_to_process_data);
5717                        return false;
5718                    }
5719                });
5720            });
5721        }else{
5722            $css = "<style type=\"text/css\">";
5723            $css += "body {font-family:Arial,sans-serif;color:#444;-webkit-print-color-adjust:exact;}";
5724            $css += "table {font-size:12px;}";
5725            $css += "table th{text-align:right;font-weight:bold;font-size:12px;padding-right:5px;}";
5726            $css += "table td{font-size:12px;}";
5727            $css += "</style>";
5728            $html = $css;
5729            $html += '<table>';
5730            nodes = args.form.querySelectorAll('.super-shortcode-field');
5731            for (i = 0; i < nodes.length; i++) { 
5732                el = nodes[i];
5733                $items = '';
5734                if( (el.name=='hidden_form_id') || (el.name=='id') ) continue;
5735                $parent = el.closest('.super-shortcode');
5736                $html += '<tr>';
5737                $html += '<th>';
5738                $html += el.dataset.email;
5739                $html += '</th>';
5740                $html += '<td>';
5741                    if($parent.classList.contains('super-radio')){
5742                        $html += ($parent.querySelector('.super-active') ? $parent.querySelector('.super-active').innerText : '');
5743                    }else if($parent.classList.contains('super-dropdown')){
5744                        items = $parent.querySelectorAll('.super-dropdown-list .super-active');
5745                        for (ii = 0; ii < items.length; ii++) { 
5746                            $items += ($items==='' ? items[ii].innerText : ', '+items[ii].innerText);
5747                        }
5748                        $html += $items;
5749                    }else if($parent.classList.contains('super-checkbox')){
5750                        items = $parent.querySelectorAll('.super-active');
5751                        for (ii = 0; ii < items.length; ii++) { 
5752                            $items += ($items==='' ? items[ii].innerText : ', '+items[ii].innerText);
5753                        }
5754                        $html += $items;
5755                    }else{
5756                        $html += el.value;
5757                    }
5758                $html += '</td>';
5759                $html += '</tr>';
5760            }
5761            $html += '</table>';
5762            win.document.write($html);
5763            win.document.close();
5764            win.focus();
5765            // @since 2.3 - chrome browser bug
5766            setTimeout(function() {
5767                win.print();
5768                win.close();
5769            }, 250);
5770            return false;
5771        }
5772    };
5773
5774    // @since 2.0.0 - clear / reset form fields
5775    SUPER.init_clear_form = function(args){
5776        var field, nodes, innerNodes, i, ii,
5777            children, index, element, dropdownItem, 
5778            option, switchBtn, activeItem,
5779            value = '',
5780            default_value,
5781            main_form = args.form,
5782            new_value = '',
5783            new_placeholder = '';
5784
5785        if(typeof args.clone !== 'undefined') {
5786            args.form = args.clone;
5787            // @since 2.7.0 - reset fields after adding column dynamically
5788            // Slider field
5789            nodes = args.form.querySelectorAll('.super-shortcode.super-slider > .super-field-wrapper > *:not(.super-shortcode-field)');
5790            for (i = 0; i < nodes.length; i++) { 
5791                nodes[i].remove();
5792            }
5793            // Color picker
5794            nodes = args.form.querySelectorAll('.super-color .sp-replacer');
5795            for (i = 0; i < nodes.length; i++) { 
5796                nodes[i].remove();
5797            }
5798        }
5799
5800        // @since 3.2.0 - remove the google autocomplete init class from fields
5801        nodes = args.form.querySelectorAll('.super-address-autopopulate.super-autopopulate-init');
5802        for (i = 0; i < nodes.length; i++) { 
5803            nodes[i].classList.remove('super-autopopulate-init');
5804        }
5805        // @since 3.5.0 - remove datepicker picker initialized class
5806        // @since 4.5.0 - remove color picker initialized class
5807        nodes = args.form.querySelectorAll('.super-picker-initialized');
5808        for (i = 0; i < nodes.length; i++) { 
5809            nodes[i].classList.remove('super-picker-initialized');
5810        }
5811
5812        // @since 3.6.0 - remove the active class from autosuggest fields
5813        nodes = args.form.querySelectorAll('.super-auto-suggest .super-dropdown-list .super-item.super-active');
5814        for (i = 0; i < nodes.length; i++) { 
5815            nodes[i].style.display = '';
5816            nodes[i].classList.remove('super-active');
5817        }
5818        nodes = args.form.querySelectorAll('.super-overlap');
5819        for (i = 0; i < nodes.length; i++) { 
5820            if(args.clear===false){
5821                if(!nodes[i].closest('.super-wc-order-search')){
5822                    nodes[i].classList.remove('super-overlap');
5823                }
5824            }else{
5825                nodes[i].classList.remove('super-overlap');
5826            }
5827        }
5828        // @since 4.8.20 - reset keyword fields
5829        nodes = args.form.querySelectorAll('.super-keyword-tags .super-keyword-filter');
5830        for (i = 0; i < nodes.length; i++) { 
5831            nodes[i].style.display = 'block';
5832            nodes[i].value = '';
5833        }
5834        nodes = args.form.querySelectorAll('.super-keyword-tags .super-autosuggest-tags > span');
5835        for (i = 0; i < nodes.length; i++) { 
5836            nodes[i].remove();
5837        }
5838        nodes = args.form.querySelectorAll('.super-keyword-tags .super-autosuggest-tags-list .super-active');
5839        for (i = 0; i < nodes.length; i++) { 
5840            nodes[i].classList.remove('super-active');
5841        }
5842        nodes = args.form.querySelectorAll('.super-keyword-tags .super-shortcode-field');
5843        for (i = 0; i < nodes.length; i++) { 
5844            nodes[i].value = '';
5845        }
5846        //nodes = args.form.querySelectorAll('.super-keyword-tags');
5847        //for (i = 0; i < nodes.length; i++) {
5848        //    field = nodes[i].querySelector('.super-keyword-filter');
5849        //    field.placeholder = field.dataset.placeholder;
5850        //}
5851        // @since 4.8.0 - reset TABs to it's initial state (always first TAB active)
5852        nodes = args.form.querySelectorAll('.super-tabs-menu .super-tabs-tab');
5853        if(nodes){
5854            if(nodes[0]) nodes[0].click();
5855        }
5856        // Remove all dynamic added columns
5857        nodes = args.form.querySelectorAll('.super-duplicate-column-fields');
5858        for (i = 0; i < nodes.length; i++) {
5859            children = Array.prototype.slice.call( nodes[i].parentNode.children );
5860            index = children.indexOf(nodes[i]);
5861            if(index>0) nodes[i].remove();
5862        }
5863
5864        // Remove error classes and filled classes
5865        nodes = args.form.querySelectorAll('.super-error, .super-error-active, .super-filled');
5866        for (i = 0; i < nodes.length; i++) { 
5867            if(args.clear===false){
5868                if(!nodes[i].classList.contains('super-wc-order-search')){
5869                    nodes[i].classList.remove('super-error');
5870                    nodes[i].classList.remove('super-error-active');
5871                    nodes[i].classList.remove('super-filled');
5872                }
5873            }else{
5874                nodes[i].classList.remove('super-error');
5875                nodes[i].classList.remove('super-error-active');
5876                nodes[i].classList.remove('super-filled');
5877            }
5878        }
5879
5880        // Clear all fields
5881        nodes = args.form.querySelectorAll('.super-shortcode-field');
5882        for (i = 0; i < nodes.length; i++) {
5883            if(nodes[i].name=='hidden_form_id') continue;
5884            element = nodes[i];
5885            default_value = '';
5886            default_value = element.dataset.defaultValue;
5887            if(typeof element.dataset.absoluteDefault!=='undefined'){
5888                default_value = element.dataset.absoluteDefault;
5889            }
5890            field = element.closest('.super-field');
5891            if(!field) continue; // Continue to next field
5892            if(args.clear===false && field.classList.contains('super-wc-order-search')){
5893                continue;
5894            }
5895
5896            // If value is not empty, set filled status
5897            if( default_value !== "" ) {
5898                field.classList.add('super-filled');
5899            }else{
5900                field.classList.remove('super-filled');
5901            }
5902
5903            // Checkbox and Radio buttons
5904            if( field.classList.contains('super-checkbox') || field.classList.contains('super-radio') ){
5905                innerNodes = field.querySelectorAll('.super-item');
5906                for (ii = 0; ii < innerNodes.length; ii++) { 
5907                    if(innerNodes[ii].classList.contains('super-default-selected')){
5908                        innerNodes[ii].classList.add('super-active');
5909                        innerNodes[ii].querySelector('input').checked = true;
5910                    }else{
5911                        innerNodes[ii].classList.remove('super-active');
5912                        innerNodes[ii].querySelector('input').checked = false;
5913                    }
5914                }
5915            }
5916
5917            // Quantity field
5918            if(field.classList.contains('super-quantity')){
5919                if(default_value==='') default_value = 0;
5920            }
5921
5922            // Currency field
5923            if(field.classList.contains('super-currency')){
5924                element.value = default_value;
5925                continue; // Continue to next field
5926            }
5927
5928            // Color picker
5929            if(field.classList.contains('super-color')){
5930                if(typeof $.fn.spectrum === "function") {
5931                    if(default_value==='') default_value = '#fff';
5932                    $(field.querySelector('.super-shortcode-field')).spectrum('set', default_value);
5933                }
5934                continue; // Continue to next field
5935            }
5936
5937            // Toggle field
5938            if(field.classList.contains('super-toggle')){
5939                switchBtn = field.querySelector('.super-toggle-switch');
5940                activeItem = switchBtn.querySelector('label[data-value="'+default_value+'"]');
5941                // If it does not exists, then we default to "off" setting
5942                if(!activeItem){
5943                    default_value = switchBtn.querySelector('.super-toggle-off').dataset.value;
5944                    activeItem = switchBtn.querySelector('label[data-value="'+default_value+'"]');
5945                }
5946                if(activeItem.classList.contains('super-toggle-on')){
5947                    switchBtn.classList.add('super-active');
5948                }else{
5949                    switchBtn.classList.remove('super-active');
5950                }
5951                element.value = activeItem.dataset.value;
5952                continue;
5953            }
5954
5955            // Dropdown field
5956            if(field.classList.contains('super-dropdown')){
5957                innerNodes = field.querySelectorAll('.super-dropdown-list .super-item.super-active');
5958                for (ii = 0; ii < innerNodes.length; ii++) { 
5959                    innerNodes[ii].classList.remove('super-active');
5960                }
5961                innerNodes = field.querySelectorAll('.super-dropdown-list .super-item.super-default-selected');
5962                for (ii = 0; ii < innerNodes.length; ii++) { 
5963                    innerNodes[ii].classList.add('super-active');
5964                }
5965                if(innerNodes.length){
5966                    field.classList.add('super-filled');
5967                }
5968                if(typeof default_value === 'undefined') default_value = '';
5969                option = field.querySelector('.super-dropdown-list .super-item:not(.super-placeholder)[data-value="'+default_value+'"]:not(.super-placeholder)');
5970                if(option){
5971                    field.querySelector('.super-placeholder').innerHTML = option.innerText;
5972                    option.classList.add('super-active');
5973                    element.value = default_value;
5974                    element.value = '';
5975                }else{
5976                    if(field.querySelectorAll('.super-dropdown-list .super-item.super-active').length===0){
5977                        if( (typeof element.placeholder !== 'undefined') && (element.placeholder!=='') ) {
5978                            field.querySelector('.super-placeholder').innerHTML = element.placeholder;
5979                            dropdownItem = field.querySelector('.super-dropdown-list .super-item[data-value="'+element.placeholder+'"]');
5980                            if(dropdownItem) dropdownItem.classList.add('super-active');
5981                        }else{
5982                            field.querySelector('.super-placeholder').innerHTML = field.querySelector('.super-dropdown-list .super-item').innerText;
5983                        }
5984                        element.value = '';
5985                    }else{
5986                        innerNodes = field.querySelectorAll('.super-dropdown-list .super-item.super-active');
5987                        for (ii = 0; ii < innerNodes.length; ii++) { 
5988                            if(new_value===''){
5989                                new_value += innerNodes[ii].dataset.value;
5990                            }else{
5991                                new_value += ','+innerNodes[ii].dataset.value;
5992                            }
5993                            if(new_placeholder===''){
5994                                new_placeholder += innerNodes[ii].innerText;
5995                            }else{
5996                                new_placeholder += ', '+innerNodes[ii].innerText;
5997                            }
5998                        }
5999                        field.querySelector('.super-placeholder').innerHTML = new_placeholder;
6000                        element.value = new_value;
6001                    }
6002                }
6003                continue;
6004            }
6005
6006            // Autosuggest field
6007            if(field.classList.contains('super-auto-suggest')){
6008                innerNodes = field.querySelectorAll('.super-dropdown-list .super-item.super-active');
6009                for (ii = 0; ii < innerNodes.length; ii++) { 
6010                    innerNodes[ii].classList.remove('super-active');
6011                }
6012                field.querySelector('.super-field-wrapper').classList.remove('super-overlap');
6013                element.value = '';
6014                continue;
6015            }
6016
6017            // File upload field
6018            if(field.classList.contains('super-file')){
6019                field.querySelector('.super-fileupload-files').innerHTML = '';
6020                field.querySelector('.super-progress-bar').removeAttribute('style');
6021                field.querySelector('.super-active-files').value = '';
6022                continue;
6023            }
6024
6025            if(typeof default_value !== 'undefined'){
6026                value = default_value;
6027                element.value = value;
6028                // Slider field
6029                if(field.classList.contains('super-slider')){
6030                    // Only have to set new value if slider was already initialized (this depends on clearing form after a dynamic column was added)
6031                    if(element.parentNode.querySelector('.slider')){
6032                        SUPER.reposition_slider_amount_label(element, value);
6033                    }
6034                    continue;
6035                }
6036                // Rating field
6037                if(field.classList.contains('super-rating')){
6038                    innerNodes = field.querySelectorAll('.super-rating-star');
6039                    for (ii = 0; ii < innerNodes.length; ii++) {
6040                        if((parseInt(value,10)-1) < ii){
6041                            innerNodes[ii].classList.add('super-active');
6042                        }else{
6043                            innerNodes[ii].classList.remove('super-active');
6044                        }
6045                    }
6046                }
6047            }
6048            element.value = value;
6049        }
6050
6051        if(typeof args.clone !== 'undefined') {
6052            // A column was duplicated
6053        }else{
6054            SUPER.after_field_change_blur_hook({form: main_form});
6055        }
6056        
6057        // After form cleared
6058        SUPER.after_form_cleared_hook(args.form);
6059    };
6060
6061
6062    // Populate form with entry data found after ajax call
6063    SUPER.populate_form_with_entry_data = function(data, form, clear){
6064        if(typeof clear === 'undefined') clear = true;
6065        var i,ii,iii,nodes,items,item,options,wrapper,input,innerNodes,firstValue,dropdown,setFieldValue,itemFirstValue,
6066            html,files,element,field,stars,currentStar,firstField,firstFieldName,
6067            switchBtn,activeItem,signatureDataUrl,fieldName,
6068            dynamicFields = {},        
6069            updatedFields = {};        
6070        
6071        data = JSON.parse(data);
6072        if(data!==false && data.length!==0){
6073        
6074            // First clear the form
6075            SUPER.init_clear_form({form: form, clear: clear});
6076
6077            // Find all dynamic columns and get the first field name
6078            nodes = form.querySelectorAll('.super-duplicate-column-fields');
6079            for ( i = 0; i < nodes.length; i++ ) {
6080                firstField = SUPER.field(nodes[i]);
6081                if(firstField){
6082                    firstFieldName = firstField.name;
6083                    dynamicFields[firstFieldName] = firstField;
6084                }
6085            }
6086            // Create extra dynamic columns as long as they exist in the data
6087            Object.keys(dynamicFields).forEach(function(index) {
6088                i = 2;
6089                while(typeof data[index+'_'+i] !== 'undefined'){
6090                    if(SUPER.field_exists(form, index+'_'+i)===0) {
6091                        dynamicFields[index].closest('.super-duplicate-column-fields').querySelector('.super-add-duplicate').click();
6092                    }
6093                    i++;
6094                }
6095            });
6096            Object.keys(data).forEach(function(i) {
6097                if(data[i].length===0) return true;
6098                html = '';
6099                files = '';
6100                fieldName = data[i].name;
6101                // If we are dealing with files we must set name to the first item (if it exists), if no files exists, we skip it
6102                if( data[i].type=='files' ) {
6103                    if( (typeof data[i].files !== 'undefined') && (data[i].files.length!==0) ) {
6104                        fieldName = data[i].files[0].name;
6105                    }else{
6106                        return true; // Skip it!
6107                    }
6108                }
6109                if(!fieldName) return true; // Either no field exists, or it's "_super_dynamic_data"
6110                // Get the element
6111                element = SUPER.field(form, fieldName);
6112                // If no element was found, go to next field
6113                if(!element) return true;
6114                // Add to list of updated fields, required to trigger hook `after_field_change_blur_hook`
6115                if(element.value!=data[i].value) {
6116                    updatedFields[fieldName] = element;
6117                }
6118
6119                field = element.closest('.super-field');
6120                // Update field value by default
6121                element.value = data[i].value;
6122                
6123                // If field is filled out add the class otherwise remove the class
6124                if(element.value===''){
6125                    element.closest('.super-shortcode').classList.remove('super-filled');
6126                }else{
6127                    element.closest('.super-shortcode').classList.add('super-filled');
6128                }
6129                
6130                // Internation phonenumber
6131                if(field.classList.contains('super-int-phone-field')){
6132                    var intPhone = window.superTelInputGlobals.getInstance(element);
6133                    intPhone.setNumber(data[i].value);
6134                    return true;
6135                }
6136
6137                // Color picker
6138                if(field.classList.contains('super-color')){
6139                    if(typeof $.fn.spectrum === "function") {
6140                        $(field.querySelector('.super-shortcode-field')).spectrum('set', data[i].value);
6141                    }
6142                    return true;
6143                }
6144
6145                // Signature element
6146                if(field.classList.contains('super-signature')){
6147                    if(typeof $.fn.signature === "function") {
6148                        signatureDataUrl = data[i].value;
6149                        field.classList.add('super-filled'); // Make sure to be able to delete signature to be able to draw a new one
6150                        $(field.querySelector('.super-signature-canvas')).signature('draw', signatureDataUrl)
6151                    }
6152                    return true;
6153                }
6154
6155                // Toggle field
6156                if(field.classList.contains('super-toggle')){
6157                    switchBtn = field.querySelector('.super-toggle-switch');
6158                    activeItem = switchBtn.querySelector('label[data-value="'+data[i].value+'"]');
6159                    if(activeItem.classList.contains('super-toggle-on')){
6160                        switchBtn.classList.add('super-active');
6161                    }else{
6162                        switchBtn.classList.remove('super-active');
6163                    }
6164                    return true;
6165                }
6166
6167                // File upload field
6168                if(data[i].type=='files'){
6169                    if((typeof data[i].files !== 'undefined') && (data[i].files.length!==0)){
6170                        $.each(data[i].files, function( fi, fv ) {
6171                            if(fi===0) {
6172                                files += fv.value;
6173                            }else{
6174                                files += ','+fv.value;
6175                            }
6176                            element = form.querySelector('.super-active-files[name="'+fv.name+'"]');
6177                            field = element.closest('.super-field');     
6178                            html += SUPER.get_single_uploaded_file_html(false, true, fv.value, fv.type, fv.url);
6179                        });
6180                        element.value = files;
6181                        field.querySelector('.super-fileupload-files').innerHTML = html;
6182                        field.querySelector('.super-fileupload').classList.add('finished');
6183                    }else{
6184                        field.querySelector('.super-fileupload-files').innerHTML = '';
6185                        field.querySelector('.super-progress-bar').removeAttribute('style');
6186                        field.querySelector('.super-active-files').value = '';
6187                    }
6188                    return true;
6189                }
6190                // Slider field
6191                if(field.classList.contains('super-slider')){
6192                    SUPER.reposition_slider_amount_label(field, data[i].value);
6193                    return true;
6194                }
6195                // Autosuggest field
6196                if(field.classList.contains('super-auto-suggest')){
6197                    if(data[i].value!==''){
6198                        firstValue = data[i].value.split(';')[0];
6199                        dropdown = field.querySelector('.super-dropdown-list');
6200                        setFieldValue = '';
6201                        nodes = dropdown.querySelectorAll('.super-item.super-active');
6202                        for ( ii = 0; ii < nodes.length; ii++){
6203                            nodes[ii].classList.remove('super-active');
6204                        }
6205                        nodes = dropdown.querySelectorAll('.super-item[data-value^="'+firstValue+'"]');
6206                        for ( ii = 0; ii < nodes.length; ii++){
6207                            itemFirstValue = nodes[ii].dataset.value.split(';')[0];
6208                            if(itemFirstValue==firstValue){
6209                                field.querySelector('.super-field-wrapper').classList.add('super-overlap');
6210                                nodes[ii].classList.add('super-active');
6211                                if(setFieldValue===''){
6212                                    setFieldValue += nodes[ii].innerText;
6213                                }else{
6214                                    setFieldValue += ','+nodes[ii].innerText;
6215                                }
6216                            }
6217                        }
6218                        element.value = setFieldValue;
6219                    }else{
6220                        nodes = dropdown.querySelectorAll('.super-dropdown-list .super-item.super-active');
6221                        for ( ii = 0; ii < nodes.length; ii++){
6222                            nodes[ii].classList.remove('super-active');
6223                        }
6224                    }
6225                    return true;
6226                }
6227                // Dropdown field
6228                if(field.classList.contains('super-dropdown')){
6229                    if(data[i].value!==''){
6230                        options = data[i].value.split(',');
6231                        dropdown = field.querySelector('.super-dropdown-list');
6232                        setFieldValue = '';
6233                        nodes = dropdown.querySelectorAll('.super-item.super-active');
6234                        for ( ii = 0; ii < nodes.length; ii++){
6235                            nodes[ii].classList.remove('super-active');
6236                        }
6237                        for ( ii = 0; ii < options.length; ii++){
6238                            innerNodes = dropdown.querySelectorAll('.super-item:not(.super-placeholder)[data-value^="'+options[ii]+'"]');
6239                            for ( iii = 0; iii < innerNodes.length; iii++){
6240                                itemFirstValue = innerNodes[iii].dataset.value.split(';')[0];
6241                                innerNodes[iii].classList.add('super-active');
6242                                if(setFieldValue===''){
6243                                    setFieldValue += itemFirstValue;
6244                                }else{
6245                                    setFieldValue += ','+itemFirstValue;
6246                                }
6247                            }
6248                        }
6249                        element.value = setFieldValue;
6250                    }else{
6251                        nodes = field.querySelectorAll('.super-dropdown-list .super-item.super-active');
6252                        for ( ii = 0; ii < nodes.length; ii++){
6253                            nodes[ii].classList.remove('super-active');
6254                        }
6255                        nodes = field.querySelectorAll('.super-dropdown-list .super-item.super-default-selected');
6256                        for ( ii = 0; ii < nodes.length; ii++){
6257                            nodes[ii].classList.add('super-active');
6258                        }
6259                    }
6260                    SUPER.init_set_dropdown_placeholder();
6261                    return true;
6262                }
6263                // Radio buttons
6264                if(field.classList.contains('super-radio')){
6265                    wrapper = field.querySelector('.super-field-wrapper');
6266                    items = wrapper.querySelectorAll('.super-item');
6267                    for( ii = 0; ii < items.length; ii++){
6268                        input = items[ii].querySelector('input');
6269                        items[ii].classList.remove('super-active');
6270                        input.checked = false;
6271                    }
6272                    for( ii = 0; ii < items.length; ii++){
6273                        input = items[ii].querySelector('input');
6274                        if(data[i].value!=='' && input.value == data[i].value){
6275                            input.checked = true;
6276                            items[ii].classList.add('super-active');
6277                            break; // Radio button can only have 1 active item
6278                        }
6279                    }
6280                    if(data[i].value===''){
6281                        // Radio button can only have 1 active item
6282                        item = wrapper.querySelector('.super-item.super-default-selected');
6283                        item.classList.add('super-active');  
6284                        item.querySelector('input').checked = true;
6285                    }
6286                    return true;
6287                }
6288                // Checkboxes
6289                if(field.classList.contains('super-checkbox')){
6290                    wrapper = field.querySelector('.super-field-wrapper');
6291                    items = wrapper.querySelectorAll('.super-item');
6292                    for( ii = 0; ii < items.length; ii++){
6293                        input = items[ii].querySelector('input');
6294                        items[ii].classList.remove('super-active');
6295                        input.checked = false;
6296
6297                        if(data[i].value!==''){
6298                            options = data[i].value.split(',');
6299                            if(options.indexOf(input.value)!==-1){
6300                                input.checked = true;
6301                                items[ii].classList.add('super-active');
6302                            }
6303                        }
6304                    }
6305                    if(data[i].value===''){
6306                        items = wrapper.querySelectorAll('.super-item.super-default-selected');
6307                        for( ii = 0; ii < items.length; ii++){
6308                            items[ii].classList.add('super-active');  
6309                            items[ii].querySelector('input').checked = true;
6310                        }
6311                    }
6312                    return true;
6313                }
6314                // Rating field
6315                if(field.classList.contains('super-rating')){
6316                    stars = field.querySelectorAll('.super-rating-star');
6317                    currentStar = parseInt(data[i].value) || 0;
6318                    for( ii = 0; ii < stars.length; ii++){
6319                        if(ii+1 <= currentStar){
6320                            stars[ii].classList.add('super-active');
6321                        }else{
6322                            stars[ii].classList.remove('super-active');
6323                        }
6324                    }
6325                    return true;
6326                }
6327            });
6328            // @since 2.4.0 - after inserting all the fields, update the conditional logic and variable fields
6329            Object.keys(updatedFields).forEach(function(key) {
6330                SUPER.after_field_change_blur_hook({el: updatedFields[key]});
6331            });
6332        }
6333    };
6334
6335    // Retrieve entry data through ajax
6336    // (this function is called when search field is changed, or when $_GET is set on page load)
6337    SUPER.populate_form_data_ajax = function(args){
6338        if(typeof args.clear === 'undefined') args.clear = true;
6339        var orderId,
6340            value,
6341            skipFields,
6342            method,
6343            form = SUPER.get_frontend_or_backend_form(args);
6344
6345        // If we are populating based of WC order search
6346        if(args.el.classList.contains('super-wc-order-search')){
6347            // Get order ID based on active item
6348            value = args.el.querySelector('.super-active').dataset.value;
6349            orderId = value.split(';')[0];
6350            // Check if we need to skip any fields
6351            skipFields = '';
6352            if(args.el.querySelector('.super-shortcode-field')){
6353                if(args.el.querySelector('.super-shortcode-field').dataset.wcoss){
6354                    skipFields = args.el.querySelector('.super-shortcode-field').dataset.wcoss; 
6355                }
6356            } 
6357            // We now have the order ID, let's search the order and get entry data if possible
6358            args.el.querySelector('.super-field-wrapper').classList.add('super-populating');
6359            $.ajax({
6360                url: super_common_i18n.ajaxurl,
6361                type: 'post',
6362                data: {
6363                    action: 'super_populate_form_data',
6364                    order_id: orderId,
6365                    skip: skipFields
6366                },
6367                success: function (data) {
6368                    SUPER.populate_form_with_entry_data(data, form, args.clear);
6369                },
6370                complete: function(){
6371                    args.el.querySelector('.super-field-wrapper').classList.remove('super-populating');
6372                },
6373                error: function (xhr, ajaxOptions, thrownError) {
6374                    // eslint-disable-next-line no-console
6375                    console.log(xhr, ajaxOptions, thrownError);
6376                    alert(super_common_i18n.errors.failed_to_process_data);
6377                }
6378            });
6379        }else{
6380            args.el.dataset.typing = 'false';
6381            value = args.el.value;
6382            method = args.el.dataset.searchMethod;
6383            // Check if we need to skip any fields
6384            skipFields = (args.el.dataset.searchSkip ? args.el.dataset.searchSkip : '');
6385            if( value.length > 2 ) {
6386                args.el.closest('.super-field-wrapper').classList.add('super-populating');
6387                $.ajax({
6388                    url: super_common_i18n.ajaxurl,
6389                    type: 'post',
6390                    data: {
6391                        action: 'super_populate_form_data',
6392                        value: value,
6393                        method: method,
6394                        skip: skipFields
6395                    },
6396                    success: function (data) {
6397                        SUPER.populate_form_with_entry_data(data, form, args.clear);
6398                    },
6399                    complete: function(){
6400                        args.el.closest('.super-field-wrapper').classList.remove('super-populating');
6401                    },
6402                    error: function (xhr, ajaxOptions, thrownError) {
6403                        // eslint-disable-next-line no-console
6404                        console.log(xhr, ajaxOptions, thrownError);
6405                        alert(super_common_i18n.errors.failed_to_process_data);
6406                    }
6407                });
6408            }
6409        }
6410    };
6411    SUPER.update_unique_code = function(el, submittingForm){
6412        $.ajax({
6413            url: super_common_i18n.ajaxurl,
6414            type: 'post',
6415            data: {
6416                action: 'super_update_unique_code',
6417                submittingForm: submittingForm,
6418                codesettings: el.dataset.codesettings // {"invoice_key:"","len":"7","char":"1","pre":"","inv":"","invp":"4","suf":"","upper":"true","lower":""}
6419            },
6420            success: function (result) {
6421                el.value = result;
6422                el.classList.add('super-generated');
6423                SUPER.after_field_change_blur_hook({el: el});
6424            },
6425            error: function (xhr, ajaxOptions, thrownError) {
6426                // eslint-disable-next-line no-console
6427                console.log(xhr, ajaxOptions, thrownError);
6428                alert('Failed to generate unique code');
6429            }
6430        });
6431    }
6432    // init the form on the frontend
6433    SUPER.init_super_form_frontend = function(){
6434
6435        // Do not do anything if all forms where intialized already
6436        if(document.querySelectorAll('.super-form').length===document.querySelectorAll('.super-form.super-initialized').length){
6437            return true;
6438        }
6439      
6440        // @since 3.3.0 - make sure to load dynamic columns correctly based on found contact entry data when a search field is being used
6441        $('.super-shortcode-field[data-search="true"]:not(.super-dom-populated)').each(function(){
6442            var field = this;
6443            if(field.value!==''){
6444                field.classList.add('super-dom-populated');
6445                SUPER.populate_form_data_ajax({el: field});
6446            }
6447        });
6448
6449        SUPER.init_text_editors();
6450
6451        // @since 2.3.0 - init file upload fields
6452        SUPER.init_fileupload_fields();
6453
6454        SUPER.init_international_phonenumber_fields();
6455
6456        //Set dropdown placeholder
6457        SUPER.init_set_dropdown_placeholder($('.super-form:not(.super-rendered)'));
6458
6459        // @since 1.1.8     - set radio button to correct value
6460        $('.super-field.super-radio').each(function(){
6461            var field = this.querySelector('.super-shortcode-field');
6462            if(field){
6463                var fieldValue = field.value;
6464                var itemsList = field.closest('.super-field-wrapper');
6465                var i, selectedValues = fieldValue.split(',');
6466                var nodes = itemsList.querySelectorAll('.super-item input[type="radio"]');
6467                // Loop over all items
6468                for(i=0; i<nodes.length; i++){
6469                    // Check if value is in array
6470                    if( (fieldValue === nodes[i].value) || (fieldValue !== '' && ((selectedValues.indexOf(nodes[i].value)!==-1) || (selectedValues.indexOf(nodes[i].value.trim())!==-1))) ) {
6471                        nodes[i].closest('.super-item').classList.add('super-active');
6472                        nodes[i].checked = true;
6473                    }else{
6474                        nodes[i].closest('.super-item').classList.remove('super-active');
6475                        nodes[i].checked = false;
6476                    }
6477                }
6478            }
6479        });
6480
6481        // @since 1.1.8     - set checkbox to correct value
6482        $('.super-field.super-checkbox').each(function(){
6483            var field = this.querySelector('.super-shortcode-field');
6484            if(field){
6485                var fieldValue = field.value;
6486                var itemsList = field.closest('.super-field-wrapper');
6487                var i, selectedValues = fieldValue.split(',');
6488                var nodes = itemsList.querySelectorAll('.super-item input[type="checkbox"]');
6489                // Loop over all items
6490                for(i=0; i<nodes.length; i++){
6491                    // Check if value is in array
6492                    if( (fieldValue === nodes[i].value) || (fieldValue !== '' && ((selectedValues.indexOf(nodes[i].value)!==-1) || (selectedValues.indexOf(nodes[i].value.trim())!==-1))) ) {
6493                        nodes[i].closest('.super-item').classList.add('super-active');
6494                        nodes[i].checked = true;
6495                    }else{
6496                        nodes[i].closest('.super-item').classList.remove('super-active');
6497                        nodes[i].checked = false;
6498                    }
6499                }
6500            }
6501        });
6502
6503        // @since 1.3   - input mask
6504        $('.super-shortcode-field[data-mask]').each(function(){
6505            $(this).mask($(this).data('mask'));
6506        });
6507
6508        // Populate signature element with possible saved form progress
6509        $('.super-form').each(function(){
6510            if($(this).hasClass('super-save-progress')){
6511                $(this).find('.super-signature').each(function(){
6512                    var value = $(this).find('.super-signature-lines').val();
6513                    if(value!==''){
6514                        value = value.replace('\\"lines\\"', '"lines"');
6515                        $(this).find('.super-signature-canvas').signature('enable').signature('draw', value);
6516                    }
6517                });
6518            }
6519        });
6520
6521        // Loop over all fields that are inside dynamic column and rename them accordingly
6522        var i, nodes = document.querySelectorAll('.super-duplicate-column-fields .super-shortcode-field[name]');
6523        for (i = 0; i < nodes.length; ++i) {
6524            var field = nodes[i];
6525            if(field.classList.contains('super-fileupload')){
6526                field = field.parentNode.querySelector('.super-active-files');
6527            }
6528            // Figure out how deep this node is inside dynamic columns
6529            var parent = nodes[i].closest('.super-duplicate-column-fields');
6530            var parentIndex = $(parent).index();  // e.g: 0, 1, 2
6531            var nameSuffix = '_'+parentIndex;
6532            if(parentIndex===0) nameSuffix = '';
6533            var originalFieldName = field.dataset.oname;
6534            var newName = originalFieldName+nameSuffix;
6535            field.name = newName;
6536            var allParents = $(nodes[i]).parents('.super-duplicate-column-fields');
6537            var suffix = [];
6538            $(allParents).each(function(key){
6539                // Skip last parent, because we don't need it
6540                if(allParents.length===(key+1)){
6541                    return;
6542                }
6543                var currentParentIndex = $(this).index();  // e.g: 0, 1, 2
6544                suffix.push('['+currentParentIndex+']');
6545            });
6546            var levels = suffix.reverse().join('');
6547            field.name = originalFieldName+levels;
6548            //field.value = field.name; 
6549            field.dataset.olevels = levels;
6550        }
6551
6552
6553        // Multi-part
6554        $('.super-form:not(.super-preview-elements)').each(function(){
6555            var form = this,
6556                $form = $(this),
6557                $multipart = {},
6558                $multiparts = [],
6559                $submit_button,
6560                $button_clone,
6561                $total = $form.find('.super-multipart').length,
6562                $prev,
6563                $next,
6564                $progress,
6565                $progress_steps,
6566                $progress_bar,
6567                $clone;
6568
6569            if($form.parent().hasClass('elementor-text-editor')){
6570                var $form_id = $form.find('input[name="hidden_form_id"]').val();
6571                $form.html('<p style="color:red;font-size:12px;"><strong>'+super_common_i18n.elementor.notice+':</strong> [Form ID: '+$form_id+ '] - '+super_common_i18n.elementor.msg+'</p>');
6572                return false;
6573            }
6574
6575            if( $total!==0 ) {
6576                // Lets check if this form has already rendered the multi-parts
6577                if( !$form.find('.super-multipart:eq(0)').hasClass('super-rendered') ) {
6578                    // First Multi-part should be set to active automatically
6579                    $form.find('.super-multipart:eq(0)').addClass('super-active').addClass('super-rendered');
6580                    // If a custom prev/next multipart button was found do not add any automatically
6581                    var hasPrevNextBtns = true;
6582                    if( $form.find('.super-prev-multipart').length===0 && $form.find('.super-next-multipart').length===0 ) {
6583                        hasPrevNextBtns = false;
6584                    }
6585                    if(!hasPrevNextBtns){
6586                        $submit_button = $form.find('.super-button:last');
6587                        $clone = $submit_button.clone();
6588                        $($clone).appendTo($form.find('.super-multipart:last'));
6589                        $button_clone = $submit_button[0].outerHTML;
6590                        $submit_button.remove();
6591                        $($button_clone).appendTo($form.find('.super-multipart').not(':last')).removeClass('super-button-align-left').removeClass('super-button-align-center').removeClass('super-button-align-right').removeClass('super-form-button').addClass('super-next-multipart').find('.super-button-name').html(super_common_i18n.directions.next);
6592                        $($button_clone).appendTo($form.find('.super-multipart').not(':first')).removeClass('super-button-align-left').removeClass('super-button-align-center').removeClass('super-button-align-right').removeClass('super-form-button').addClass('super-prev-multipart').find('.super-button-name').html(super_common_i18n.directions.prev);
6593                    }
6594
6595                    // Now lets loop through all the multi-parts and set the data such as name and description
6596                    $form.find('.super-multipart').each(function(){
6597                        if(!hasPrevNextBtns){
6598                            if( typeof $(this).data('prev-text') === 'undefined' ) {
6599                                $prev = super_common_i18n.directions.prev;
6600                            }else{
6601                                $prev = $(this).data('prev-text');
6602                            }
6603                            if( typeof $(this).data('next-text') === 'undefined' ) {
6604                                $next = super_common_i18n.directions.next;
6605                            }else{
6606                                $next = $(this).data('next-text');
6607                            }
6608                            $(this).find('.super-prev-multipart .super-button-name').html($prev);
6609                            $(this).find('.super-next-multipart .super-button-name').html($next);
6610                        }
6611                        $multipart = {
6612                            name: $(this).data('step-name'),
6613                            description: $(this).data('step-description'),
6614                            image: $(this).data('image'),
6615                            icon: $(this).data('icon'),
6616                        };
6617                        $multiparts.push($multipart);
6618                    });
6619
6620                    // Lets setup the progress steps
6621                    $progress_steps  = '<ul class="super-multipart-steps">';
6622                    $.each($multiparts, function( index, value ) {
6623                        if($total==1){
6624                            $progress_steps += '<li class="super-multipart-step super-active last-step">';
6625                        }else{
6626                            if((index===0) && ($total != (index+1))){
6627                                $progress_steps += '<li class="super-multipart-step super-active">';
6628                            }else{
6629                                if($total == (index+1)){
6630                                    $progress_steps += '<li class="super-multipart-step last-step">';
6631                                }else{
6632                                    $progress_steps += '<li class="super-multipart-step">';
6633                                }
6634                            }
6635                        }
6636                        $progress_steps += '<span class="super-multipart-step-wrapper">';
6637                        if(value.image) {
6638                            $progress_steps += '<span class="super-multipart-step-image"><img src="'+value.image+'" /></span>';
6639                        }else{
6640                            if(value.icon) {
6641                                $progress_steps += '<span class="super-multipart-step-icon"><i class="fas fa-'+value.icon+'"></i></span>';  
6642                            }else{
6643                                $progress_steps += '<span class="super-multipart-step-count">'+(index+1)+'</span>';
6644                            }
6645                        }
6646                        if( value.name!=='' ) {
6647                            $progress_steps += '<span class="super-multipart-step-name">'+value.name+'</span>';
6648                        }
6649                        if( value.description!=='' ) {
6650                            $progress_steps += '<span class="super-multipart-step-description">'+value.description+'</span>';
6651                        }
6652                        $progress_steps += '</span>';
6653                        $progress_steps += '</li>';
6654                    });
6655                    $progress_steps += '</ul>';
6656
6657                    // Here we set the correct progress bar in percentages
6658                    $progress = 100 / $total;
6659                    $progress_bar  = '<div class="super-multipart-progress">';
6660                    $progress_bar += '<div class="super-multipart-progress-inner">';
6661                    $progress_bar += '<div class="super-multipart-progress-bar" style="width:'+$progress+'%"></div>';
6662                    $progress_bar += '</div>';
6663                    $progress_bar += '</div>';
6664
6665                    // @4.7.0 - place after language switcher
6666                    if($form.find('.super-i18n-switcher').length!=0){
6667                        $($progress_steps).insertAfter($form.find('.super-i18n-switcher'));
6668                        $($progress_bar).insertAfter($form.find('.super-i18n-switcher'));
6669                    }else{
6670                        $form.prepend($progress_steps);
6671                        $form.prepend($progress_bar);
6672                    }
6673                }
6674                
6675                // @SINCE 4.9.520 - Remember multi-part position/location and allow to anchor to a specific multi-part
6676                // Example: http://domain.com/page#step-49344-3
6677                var currentStep = window.location.hash.substring(1);
6678                if(currentStep!==''){
6679                    var explodedStep = currentStep.split('-');
6680                    if(explodedStep[0]==='step'){
6681                        var stepFormID = explodedStep[1];
6682                        var multiPart = explodedStep[2];
6683                        // Lookup the form based on the ID
6684                        var multiPartForm = document.querySelector('.super-form-'+stepFormID);
6685                        if(multiPartForm){
6686                            // We found a form, check if it contains a multi-part, if so then make it active
6687                            var nodes = multiPartForm.querySelectorAll('.super-multipart');
6688                            // If there are not enough multi-parts default to the first one
6689                            if(nodes.length < multiPart) multiPart = "1";
6690                            for(var i = 0; i < nodes.length; i++){
6691                                if(multiPart==(i+1)){
6692                                    nodes[i].classList.add('super-active');
6693                                }else{
6694                                    nodes[i].classList.remove('super-active');
6695                                }
6696                            }
6697                            nodes = multiPartForm.querySelectorAll('.super-multipart-step');
6698                            for(i = 0; i < nodes.length; i++){
6699                                if(multiPart==(i+1)){
6700                                    nodes[i].classList.add('super-active');
6701                                }else{
6702                                    nodes[i].classList.remove('super-active');
6703                                }
6704                            }
6705                            var progress = 100 / nodes.length;
6706                            progress = progress * parseInt(multiPart, 10);
6707                            form.querySelector('.super-multipart-progress-bar').style.width = progress+'%';
6708                        }
6709                    }
6710                }
6711            }
6712            SUPER.init_common_fields({form: form});
6713            SUPER.init_super_responsive_form_fields({form: form});
6714        });
6715
6716        $(window).resize(function() {
6717            var i, nodes = document.querySelectorAll('.super-form:not(.super-generating-pdf)');
6718            for(i=0; i<nodes.length; i++){
6719                SUPER.init_super_responsive_form_fields({form: nodes[i]});
6720            }
6721        });
6722        
6723        var $handle_columns_interval = setInterval(function(){
6724            if(($('.super-form').length != $('.super-form.super-rendered').length) || ($('.super-form').length===0)){
6725                SUPER.handle_columns();
6726            }else{
6727                clearInterval($handle_columns_interval);
6728            }
6729        }, 100);
6730    };
6731
6732    // Reposition slider amount label
6733    SUPER.reposition_slider_amount_label = function(field, value, conditionalUpdate){
6734        if(typeof conditionalUpdate === 'undefined') conditionalUpdate = false;
6735        if(typeof value === 'undefined') {
6736            value = field.value;
6737            // Set a class so that we don't focus this field
6738            if(conditionalUpdate) field.classList.add('super-prevent-focus');
6739            $(field).simpleSlider("setValue", 0);
6740            // Set a class so that we don't focus this field
6741            if(conditionalUpdate) field.classList.add('super-prevent-focus');
6742            $(field).simpleSlider("setValue", value);
6743        }else{
6744            if(value !== field.value){
6745                // Set a class so that we don't focus this field
6746                if(conditionalUpdate) field.classList.add('super-prevent-focus');
6747                $(field).simpleSlider("setValue", 0);
6748                // Set a class so that we don't focus this field
6749                if(conditionalUpdate) field.classList.add('super-prevent-focus');
6750                $(field).simpleSlider("setValue", value);
6751            }else{
6752                if(conditionalUpdate){
6753                    if(value===0 || value==="0"){
6754                        // Set a class so that we don't focus this field
6755                        if(conditionalUpdate) field.classList.add('super-prevent-focus');
6756                        $(field).simpleSlider("setValue", 1);
6757                    }else{
6758                        // Set a class so that we don't focus this field
6759                        if(conditionalUpdate) field.classList.add('super-prevent-focus');
6760                        $(field).simpleSlider("setValue", 0);
6761                    }
6762                    // Set a class so that we don't focus this field
6763                    if(conditionalUpdate) field.classList.add('super-prevent-focus');
6764                    $(field).simpleSlider("setValue", value);
6765                }
6766            }
6767        }
6768    };
6769    // Init Slider fields
6770    SUPER.init_slider_field = function(){
6771        $('.super-slider').each(function () {
6772            var $this = $(this),
6773                $field,
6774                $steps,
6775                $min,
6776                $max,
6777                $currency,
6778                $format,
6779                $value,
6780                $decimals,
6781                $thousand_separator,
6782                $decimal_separator,
6783                $regex,
6784                $wrapper,
6785                $number,
6786                $amount,
6787                $dragger,
6788                $slider_width,
6789                $amount_width,
6790                $dragger_margin_left,
6791                $offset_left;
6792
6793            if( $this.find('.slider').length===0 ) {
6794                $field = $this.find('.super-shortcode-field');
6795                $steps = $field.data('steps');
6796                $min = $field.data('minnumber');
6797                $max = $field.data('maxnumber');
6798                if(typeof $min === 'undefined') $min = 0;
6799                if(typeof $max === 'undefined') $max = 100;
6800                $currency = $field.data('currency');
6801                $format = $field.data('format');
6802                $value = ($field.val()==='' ? 0 : parseFloat($field.val()));
6803                $decimals = $field.data('decimals');
6804                $thousand_separator = $field.data('thousand-separator');
6805                $decimal_separator = $field.data('decimal-separator');
6806                $regex = '\\d(?=(\\d{' + (3 || 3) + '})+' + ($decimals > 0 ? '\\D' : '$') + ')';
6807                if( $value<$min ) {
6808                    $value = $min;
6809                }
6810                $value = parseFloat($value).toFixed(Math.max(0, ~~$decimals));
6811                $value = ($decimal_separator ? $value.replace('.', $decimal_separator) : $value).replace(new RegExp($regex, 'g'), '$&' + ($thousand_separator || ''));
6812                $field.simpleSlider({
6813                    snap: true,
6814                    step: $steps,
6815                    range: [$min, $max],
6816                    animate: false
6817                });
6818                $wrapper = $field.parents('.super-field-wrapper:eq(0)');
6819                $wrapper.append('<span class="amount"><i>'+$currency+''+$value+''+$format+'</i></span>');
6820                $field.on("slider:changed", function ($event, $data) {
6821                    // Only focus form/field when form is already initialized
6822                    if(this.classList.contains('super-prevent-focus')){
6823                        this.classList.remove('super-prevent-focus');
6824                    }else{
6825                        SUPER.focusForm(this);
6826                        SUPER.focusField(this);
6827                    }
6828                    $number = parseFloat($data.value).toFixed(Math.max(0, ~~$decimals));
6829                    $number = ($decimal_separator ? $number.replace('.', $decimal_separator) : $number).replace(new RegExp($regex, 'g'), '$&' + ($thousand_separator || ''));
6830                    $amount = $wrapper.children('.amount');
6831                    $dragger = $data.el[0].querySelector('.dragger');
6832                    $amount.children('i').html($currency+''+($number)+''+$format);
6833                    setTimeout(function(){
6834                        $slider_width = $data.el[0].offsetWidth;
6835                        $amount_width = $amount[0].offsetWidth;
6836                        $dragger_margin_left = $dragger.style.marginLeft.replace('px','');
6837                        if($dragger_margin_left<0){
6838                            $dragger_margin_left = -$dragger_margin_left;
6839                        }
6840                        $offset_left = $dragger.offsetLeft + $dragger_margin_left;
6841                        // If offset doesn't have to be less than 0
6842                        if($offset_left<0){
6843                            $offset_left = 0;
6844                        }
6845                        if($slider_width < ($offset_left + $amount_width)){
6846                            $amount.css('right', '0px');
6847                            $amount.css('left', 'inherit');
6848                        }else{
6849                            $amount.css('right', 'inherit');
6850                            $amount.css('left', $offset_left+'px');
6851                        }
6852                    },1);
6853                });
6854                SUPER.reposition_slider_amount_label($field[0]);
6855            }
6856        });
6857        $('.slider-field').each(function () {
6858            var $this = $(this),
6859                $field = $this.children('input'),
6860                $steps = $field.data('steps'),
6861                $min = $field.data('min'),
6862                $max = $field.data('max');
6863            if($this.children('.slider').length===0){
6864                $field.simpleSlider({
6865                    snap: true,
6866                    step: $steps,
6867                    range: [$min, $max]
6868                });
6869                $field.show();
6870            }
6871        });
6872    };
6873    
6874    // Init Carousel/Sliders (currently used for checkboxes and radio buttons only)
6875    SUPER.init_carouseljs = function(){
6876        if(typeof CarouselJS !== 'undefined'){
6877            // Initialize CarouselJS
6878            // eslint-disable-next-line no-undef
6879            CarouselJS.init();
6880        }
6881    };
6882
6883    // Init Tooltips
6884    SUPER.init_tooltips = function(){
6885        if ( $.isFunction($.fn.tooltipster) ) {
6886            var i, form, formId, formTheme, nodes = document.querySelectorAll('.super-tooltip:not(.tooltipstered)');
6887            for(i=0; i<nodes.length; i++){
6888                formId = 0;
6889                form = SUPER.get_frontend_or_backend_form({el: nodes[i]});
6890                if(form.querySelector('input[name="hidden_form_id"]')){
6891                    formId = form.querySelector('input[name="hidden_form_id"]').value;
6892                }
6893                formTheme = '';
6894                if(form.classList.contains('super-default-rounded')){
6895                    formTheme = 'tooltip-super-default-rounded';
6896                }
6897                if(form.classList.contains('super-full-rounded')){
6898                    formTheme = 'tooltip-super-full-rounded';
6899                }
6900                $(nodes[i]).tooltipster({
6901                    theme: 'tooltip-super-form tooltip-super-form-'+formId+' '+formTheme,
6902                    contentAsHTML: true,
6903                    trigger: 'custom',
6904                    triggerOpen: {
6905                        click: true,
6906                        tap: true,
6907                        mouseenter: true,
6908                        touchstart: true
6909                    },
6910                    triggerClose: {
6911                        click: true,
6912                        tap: true,
6913                        mouseleave: true,
6914                        originClick: true,
6915                        touchleave: true
6916                    }
6917                });
6918            }
6919        }
6920    };
6921
6922    // Init color pickers
6923    SUPER.init_color_pickers = function(){
6924        if ( $.isFunction($.fn.wpColorPicker) ) {
6925            $('.super-color-picker').each(function(){
6926                if($(this).find('.wp-picker-container').length===0){
6927                    $(this).children('input').wpColorPicker({
6928                        change: function(event, ui) {
6929                            // event = standard jQuery event, produced by whichever control was changed.
6930                            // ui = standard jQuery UI object, with a color member containing a Color.
6930js object
6931                            if(typeof SUPER.backend_setting_changed === "function") { 
6932                                SUPER.backend_setting_changed($(this), ui.color.toString());
6933                            }
6934                        },
6935                        palettes: ['#FFFFFF', '#000000', '#444444', '#8E8E8E', '#9A9A9A', '#CDCDCD', '#6E7177', '#F26C68', '#49B4B6' ]
6936                    });
6937                }
6938            });
6939        }
6940    };
6941
6942    // Init common fields to init
6943    SUPER.init_common_fields = function(){
6944        if(typeof SUPERreCaptcha === 'function') SUPERreCaptcha(); // This function name may not contain a dot. so we have to call it manually.
6945        SUPER.after_init_common_fields();
6946    };
6947
6948    SUPER.resize_toggle_element = function(p){
6949        var i, nodes = [];
6950        if(p.classList.contains('super-toggle')){
6951            nodes.push(p);
6952        }else{
6953            nodes = p.querySelectorAll('.super-toggle');
6954        }
6955        for( i=0; i<nodes.length; i++ ) {
6956            // Grab on/off nodes
6957            var sw = nodes[i].querySelector('.super-toggle-switch');
6958            var gr = nodes[i].querySelector('.super-toggle-group');
6959            var on = nodes[i].querySelector('.super-toggle-on');
6960            var ha = nodes[i].querySelector('.super-toggle-handle');
6961            var off = nodes[i].querySelector('.super-toggle-off');
6962            // Reset width for both
6963            sw.style.width = '';
6964            gr.style.width = '';
6965            on.style.width = '';
6966            off.style.width = '';
6967            ha.style.width = '';
6968            // Grab the width
6969            var width = 0;
6970            var onWidth = on.offsetWidth+40; // padding left/right 20px
6971            var offWidth = off.offsetWidth+40; // padding left/right 20px
6972            var haWidth = ha.offsetWidth+4;
6973            ha.style.width = haWidth+'px';
6974            // Now compare, and set new width
6975            width = onWidth;
6976            if(onWidth < offWidth){
6977                width = offWidth;
6978            }
6979            sw.style.width = width+(haWidth/2)+'px';
6980            gr.style.width = ((width+(haWidth/2))*2)-2+'px';
6981            on.style.width = width+'px';
6982            off.style.width = width+'px';
6983        }
6984    };
6985    SUPER.reposition_slider_element = function(p, conditionalUpdate){
6986        if(typeof conditionalUpdate === 'undefined') conditionalUpdate = false;
6987        var i, nodes = [];
6988        if(p.classList.contains('super-slider')){
6989            nodes.push(p);
6990        }else{
6991            nodes = p.querySelectorAll('.super-slider');
6992        }
6993        for( i=0; i<nodes.length; i++ ) {
6994            var $element = $(nodes[i]);
6995            var $wrapper = $element.children('.super-field-wrapper');
6996            var $field = $wrapper.children('.super-shortcode-field'); 
6997            if(typeof $field.data("slider-object") === 'undefined'){
6998                // Regenerate slider because this is a cloned form
6999                if(nodes[i].querySelector('.slider')){
7000                    nodes[i].querySelector('.slider').remove();
7001                }
7002                SUPER.init_slider_field();
7003            }else{
7004                var $value = $field.val();
7005                if($wrapper.children('.slider').length){
7006                    SUPER.reposition_slider_amount_label($field[0], $value, conditionalUpdate);
7007                }
7008            }
7009        }
7010    };
7011
7012    // Handle the responsiveness of the form
7013    SUPER.responsive_form_fields_timeout = {};
7014    SUPER.init_super_responsive_form_fields = function(args){
7015        if(typeof $ === 'undefined') $ = jQuery;
7016        if(typeof args === 'undefined') args = {};
7017        if(typeof args.form === 'undefined') {
7018            args.form = document.querySelector('.super-form');
7019        }
7020        var formId = (args.form.querySelector('input[name="hidden_form_id"]') ? args.form.querySelector('input[name="hidden_form_id"]').value : 0);
7021		if (SUPER.responsive_form_fields_timeout[formId] !== null) {
7022			clearTimeout(SUPER.responsive_form_fields_timeout[formId]);
7023		}
7024        SUPER.responsive_form_fields_timeout[formId] = setTimeout(function () {
7025            var $classes = [
7026                'super-first-responsiveness',
7027                'super-second-responsiveness',
7028                'super-third-responsiveness',
7029                'super-fourth-responsiveness',
7030                'super-last-responsiveness'
7031            ];
7032            var $window_classes = [
7033                'super-window-first-responsiveness',
7034                'super-window-second-responsiveness',
7035                'super-window-third-responsiveness',
7036                'super-window-fourth-responsiveness',
7037                'super-window-last-responsiveness'
7038            ];
7039
7040            var $new_class = '';
7041            var $new_window_class = '';
7042            var $window_width = $(window).outerWidth(true);
7043
7044            var $this = $(args.form);
7045            var $width = $this.outerWidth(true);
7046            // Change in width, apply responsiveness
7047            if($width > 0 && $width < 530){
7048                SUPER.remove_super_form_classes($this,$classes);
7049                $this.addClass($classes[0]);
7050                $new_class = $classes[0];
7051            }
7052            if($width >= 530 && $width < 760){
7053                SUPER.remove_super_form_classes($this,$classes);
7054                $this.addClass($classes[1]);
7055                $new_class = $classes[1];
7056            }
7057            if($width >= 760 && $width < 1200){
7058                SUPER.remove_super_form_classes($this,$classes);
7059                $this.addClass($classes[2]);
7060                $new_class = $classes[2];
7061            }
7062            if($width >= 1200 && $width < 1400){
7063                SUPER.remove_super_form_classes($this,$classes);
7064                $this.addClass($classes[3]);
7065                $new_class = $classes[3];
7066            }
7067            if($width >= 1400){
7068                SUPER.remove_super_form_classes($this,$classes);
7069                $this.addClass($classes[4]);
7070                $new_class = $classes[4];
7071            }
7072
7073            // @since 1.9 - add the window width responsiveness classes
7074            if($window_width > 0 && $window_width < 530){
7075                SUPER.remove_super_form_classes($this,$window_classes);
7076                $this.addClass($window_classes[0]);
7077                $new_window_class = $window_classes[0];
7078            }
7079            if($window_width >= 530 && $window_width < 760){
7080                SUPER.remove_super_form_classes($this,$window_classes);
7081                $this.addClass($window_classes[1]);
7082                $new_window_class = $window_classes[1];
7083            }
7084            if($window_width >= 760 && $window_width < 1200){
7085                SUPER.remove_super_form_classes($this,$window_classes);
7086                $this.addClass($window_classes[2]);
7087                $new_window_class = $window_classes[2];
7088            }
7089            if($window_width >= 1200 && $window_width < 1400){
7090                SUPER.remove_super_form_classes($this,$window_classes);
7091                $this.addClass($window_classes[3]);
7092                $new_window_class = $window_classes[3];
7093            }
7094            if($window_width >= 1400){
7095                SUPER.remove_super_form_classes($this,$window_classes);
7096                $this.addClass($window_classes[4]);
7097                $new_window_class = $window_classes[4];
7098            }
7099
7100            // @since 3.2.0 - check if RTL support is enabled, if so we must revert column order on mobile devices
7101            if( $this.hasClass('super-rtl') ) {
7102                if( (!$this.hasClass('super-rtl-reversed')) && ($new_class=='super-first-responsiveness') ) {
7103                    $this.find('.super-grid').each(function(){
7104                        var $grid = $(this);
7105                        var $columns = $grid.children('div.super-column:not(.super-not-responsive)');
7106                        $grid.append($columns.get().reverse());
7107                        $grid.children('div.super-column:last-child').removeClass('first-column');
7108                        $grid.children('div.super-column:eq(0)').addClass('first-column');
7109                    });
7110                    $this.addClass('super-rtl-reversed');
7111                }else{
7112                    if( ($this.hasClass('super-rtl-reversed')) && ($new_class!='super-first-responsiveness') ) {
7113                        $this.find('.super-grid').each(function(){
7114                            var $grid = $(this);
7115                            var $columns = $grid.children('div.super-column:not(.super-not-responsive)');
7116                            $grid.append($columns.get().reverse());
7117                            $grid.children('div.super-column:last-child').removeClass('first-column');
7118                            $grid.children('div.super-column:eq(0)').addClass('first-column');
7119                        });
7120                        $this.removeClass('super-rtl-reversed');
7121                    }
7122                }
7123            }
7124
7125            // Resize toggle elements
7126            SUPER.resize_toggle_element(args.form);
7127            // Reposition slider dragger
7128            SUPER.reposition_slider_element(args.form);
7129
7130            // @since 1.3
7131            SUPER.after_responsive_form_hook($classes, args.form, $new_class, $window_classes, $new_window_class);
7132
7133            if(typeof args.callback === 'function'){
7134                args.callback();
7135            }
7136        }, 500);
7137    };
7138
7139    // Update field visibility
7140    SUPER.init_field_filter_visibility = function($this, type) {
7141        if(typeof type === 'undefined') type = '';
7142        var $nodes,
7143            $name;
7144        if(typeof $this ==='undefined'){
7145            $nodes = $('.super-elements-container .super-field.super-filter[data-filtervalue], .super-settings .super-field.super-filter[data-filtervalue]');
7146            $nodes.addClass('super-hidden');
7147        }else{
7148            $name = $this.find('.super-element-field').attr('name');
7149            $nodes =  $('.super-elements-container .super-field[data-parent="'+$name+'"], .super-settings .super-field[data-parent="'+$name+'"]');
7150        }
7151        $nodes.each(function(){
7152            var $this = $(this),
7153                $container = $this.parents('.super-elements-container:eq(0)'),
7154                $filtervalue = $this.data('filtervalue'),
7155                $parent,
7156                $value,
7157                $visibility,
7158                $filtervalues,
7159                $string_value,
7160                $match_found = false;
7161
7162            if($container.length===0){
7163                $container = $this.parents('.super-settings:eq(0)');
7164            }
7165            $parent = $container.find('.super-element-field[name="'+$this.data('parent')+'"]');
7166            // If is radio button
7167            if($parent.attr('type')=='radio'){
7168                $parent = $container.find('.super-element-field[name="'+$this.data('parent')+'"]:checked');
7169            }
7170            $value = $parent.val();
7171            if(typeof $value==='undefined') $value = '';
7172            $parent = $parent.parents('.super-field.super-filter:eq(0)');
7173
7174            $visibility = $parent.hasClass('super-hidden');
7175            if($visibility===true){
7176                $visibility = 'hidden';
7177            }else{
7178                $visibility = 'visible';
7179            }
7180            $filtervalues = $filtervalue.toString().split(',');
7181            $string_value = $value.toString();
7182            $.each($filtervalues, function( index, value ) {
7183                if( value==$string_value ) {
7184                    $match_found = true;
7185                }
7186            });
7187            if( $match_found && ($visibility!='hidden') ) {
7188                $this.removeClass('super-hidden');
7189            }else{
7190                $this.addClass('super-hidden');
7191            }
7192            SUPER.init_field_filter_visibility($this, type);
7193        });
7194
7195        // Apply styles after changing settings
7196        // Toggle RTL styles
7197        if(document.querySelector('input[name="theme_rtl"]')){
7198            var theme_rtl = document.querySelector('input[name="theme_rtl"]').value;
7199            if(document.querySelector('.super-preview-elements')){
7200                if(theme_rtl==='true'){
7201                    document.querySelector('.super-preview-elements').classList.add('super-rtl');
7202                }else{
7203                    document.querySelector('.super-preview-elements').classList.remove('super-rtl');
7204                }
7205            }
7206        }
7207    };
7208
7209    // @since 3.1.0 - init distance calculator fields
7210    SUPER.init_distance_calculators = function(){
7211        var i, form, method, destination, destinationField,
7212            nodes = document.querySelectorAll('.super-form .super-distance-calculator');
7213
7214        for( i = 0; i < nodes.length; i++){
7215            form = SUPER.get_frontend_or_backend_form({el: nodes[i]});
7216            method = nodes[i].dataset.distanceMethod;
7217            if(method=='start'){
7218                destination = nodes[i].dataset.distanceDestination;
7219                destinationField = SUPER.field(form, destination);
7220                if(destinationField){
7221                    destinationField.dataset.distanceStart = nodes[i].name;
7222                }
7223            }
7224        }
7225    };
7226    SUPER.pdf_generator_init = function(args, callback){
7227        args._save_data_callback = callback;
7228
7229        // Page margins and print area
7230        // Media                Page size           Print area              Margins
7231        //                                                                  Top         Bottom      Sides
7232        // A/Letter (U.S.)      8.5 x 11 in.        8.2 x 10.6 in.          .22 in.     .18 in      .15 in
7233        // A4 (Metric)          210 x 297 mm        200 x 287 mm            5 mm        5 mm        5 mm
7234        // Legal Short (U.S.)   8.5 x 14 in.        8.2 x 11.7 in           1.15 in.    1.15 in.    .15 in.
7235        // Legal (U.S.)         8.5 x 14 in.        8.2 x 11.7 in. (Color)  1.15 in     2.25 in.    .15 in.
7236        //                                          8.2 x 13.5 in. (Black)  .23 in      .23 in.     .15 in.
7237
7238        // Page formats
7239        // Format       Size in Millimeters     Size in Inches          Point (pt)
7240        // A0           841 x 1189              33.1 x 46.8
7241        // A1           594 x 841               23.4 x 33.1
7242        // A2           420 x 594               16.5 x 23.4
7243        // A3           297 x 420               11.7 x 16.5
7244        // A4           210 x 297               8.3 x 11.7              595.28, 841.89
7245        // A5           148 x 210               5.8 x 8.3
7246        // A6           105 x 148               4.1 x 5.8
7247        // A7           74 x 105                2.9 x 4.1
7248        // A8           52 x 74                 2.0 x 2.9
7249        // A9           37 x 52	                1.5 x 2.0
7250        // A10          26 x 37                 1.0 x 1.5
7251
7252
7253        args.orientation = args.pdfSettings.orientation;
7254        args.format = args.pdfSettings.format;
7255        // Check if custom format is defined
7256        var customFormat = args.pdfSettings.customformat;
7257        if(typeof customFormat !== 'undefined' && customFormat!==''){
7258            customFormat = customFormat.split(',');
7259            if(typeof customFormat[1] !== 'undefined'){
7260                customFormat[0] = customFormat[0].trim();
7261                customFormat[1] = customFormat[1].trim();
7262                if(customFormat[0]!=='' && customFormat[1]!==''){
7263                    args.format = customFormat;
7264                }
7265            }
7266        }
7267
7268        // For quick debugging purposes only:
7269        // eslint-disable-next-line no-undef
7270        args._pdf = new jsPDF({
7271            orientation: args.orientation,   // Orientation of the first page. Possible values are "portrait" or "landscape" (or shortcuts "p" or "l").
7272            format: args.format,             // The format of the first page.  Default is "a4"
7273            putOnlyUsedFonts: false,    // Only put fonts into the PDF, which were used.
7274            compress: false,            // Compress the generated PDF.
7275            precision: 16,              // Precision of the element-positions.
7276            userUnit: 1.0,              // Not to be confused with the base unit. Please inform yourself before you use it.
7277            floatPrecision: 16,         // or "smart", default is 16
7278            unit: args.pdfSettings.unit                  // Measurement unit (base unit) to be used when coordinates are specified.
7279        });                             // Possible values are "pt" (points), "mm", "cm", "m", "in" or "px".
7280                                            // Can be:
7281                                            // a0 - a10
7282                                            // b0 - b10
7283                                            // c0 - c10
7284                                            // dl
7285                                            // letter
7286                                            // government-letter
7287                                            // legal
7288                                            // junior-legal
7289                                            // ledger
7290                                            // tabloid
7291                                            // credit-card
7292
7293        if(super_common_i18n.fonts){
7294            args._pdf.addFileToVFS('NotoSans-Regular-normal.ttf', super_common_i18n.fonts.NotoSans.regular);
7295            args._pdf.addFont('NotoSans-Regular-normal.ttf', 'NotoSans-Regular', 'normal');
7296            args._pdf.addFileToVFS('NotoSans-Bold-bold.ttf', super_common_i18n.fonts.NotoSans.bold);
7297            args._pdf.addFont('NotoSans-Bold-bold.ttf', 'NotoSans-Bold', 'bold');
7298        }
7299
7300        // PDF width: 595.28 pt
7301        // PDF height: 841.89 pt
7302        
7303        // PDF width: 210.0015555555555 mm
7304        // PDF height: 297.0000833333333 mm
7305
7306        // PDF width: 21.000155555555555 cm
7307        // PDF height: 29.700008333333333 cm
7308
7309        // PDF width: 8.267777777777777 in
7310        // PDF height: 11.692916666666667 in
7311
7312        // PDF width: 446.46 px
7313        // PDF height: 631.4175 px
7314
7315        // pt to px  = X / 1.333333333333333
7316        // mm to px  = X / 0.4703703703703702
7317        // cm to px  = X / 0.04703703703703702
7318        // in to px  = X / 0.0185185185010975
7319        args.unitRatio = 1;
7320        if(args.pdfSettings.unit=='pt') args.unitRatio = 1.333333333333333;
7321        if(args.pdfSettings.unit=='mm') args.unitRatio = 0.4703703703703702;
7322        if(args.pdfSettings.unit=='cm') args.unitRatio = 0.04703703703703702;
7323        if(args.pdfSettings.unit=='in') args.unitRatio = 0.0185185185010975;
7324        var pageWidth = args._pdf.internal.pageSize.getWidth();
7325        var pageHeight = args._pdf.internal.pageSize.getHeight();
7326        args.pageWidthPortrait = pageWidth;
7327        args.pageHeightPortrait = pageHeight;
7328        args.pageWidthLandscape = pageHeight;
7329        args.pageHeightLandscape = pageWidth;
7330        args.pageWidthInPixels = pageWidth / args.unitRatio;
7331        args.pageHeightInPixels = pageHeight / args.unitRatio;
7332        
7333        // Make form scrollable based on a4 height
7334        var scrollAmount = 0;
7335
7336        args.scrollAmount = scrollAmount;
7337        args.pdfSettings.filename = SUPER.update_variable_fields.replace_tags({form: args.form0, value: args.pdfSettings.filename});
7338
7339        // Blur/unfocus any focussed field
7340        // bug in google chrome on mobile devices
7341        // .....
7342        //
7343        // Add a timeout (just to be sure)
7344        setTimeout(function(){
7345            SUPER.pdf_generator_prepare(args, function(args){
7346                // Start generating pages (starting at page 1)
7347                args.currentPage = 1;
7348                SUPER.pdf_generator_generate_page(args);
7349            });
7350        }, 5000);
7351        return false;
7352    };
7353    SUPER._pdf_generator_done_callback = function(args){
7354        // Reset everything to how it was
7355        SUPER.pdf_generator_reset(args.form0);
7356        // Attach as file to form data
7357        var datauristring = args._pdf.output('datauristring', {
7358            filename: args.pdfSettings.filename
7359        });
7360        var exclude = 0;
7361        if(args.pdfSettings.adminEmail!=='true' && args.pdfSettings.confirmationEmail!=='true'){
7362            exclude = 2; // Exclude from both emails
7363        }else{
7364            if(args.pdfSettings.adminEmail==='true' && args.pdfSettings.confirmationEmail==='true'){
7365                exclude = 0;
7365 // Do not exclude
7366            }else{
7367                if(args.pdfSettings.adminEmail==='true'){
7368                    exclude = 1; // Exclude from confirmation email only
7369                }
7370                if(args.pdfSettings.confirmationEmail==='true'){
7371                    exclude = 3; // Exclude from admin email only
7372                }
7373            }
7374        }
7375        args.data._generated_pdf_file = {
7376            files: [{
7377                label: args.pdfSettings.emailLabel,
7378                name: args.pdfSettings.filename,
7379                datauristring: datauristring,
7380                value: args.pdfSettings.filename
7381            }],
7382            label: args.pdfSettings.emailLabel,
7383            type: 'files',
7384            exclude: exclude
7385        };
7386        // We PDF has been generated, continue with form submission
7387        args._save_data_callback(args);
7388    };
7389    SUPER.pdf_generator_prepare = function(args, callback){
7390        var form = args.form0;
7391
7392        // Define PDF tags
7393        SUPER.pdf_tags = {
7394            pdf_page: '{pdf_page}',
7395            pdf_total_pages: '{pdf_total_pages}'
7396        };
7397
7398        // Must hide scrollbar
7399        document.documentElement.classList.add('super-hide-scrollbar');
7400        form.classList.add('super-generating-pdf');
7401        
7402        // Normalize font styles
7403        var normalizeFontStylesNodesClasses = 'h1, h2, h3, h4, h5, h6, .super-label, .super-description, .super-heading-title, .super-heading-description, .super-text .super-shortcode-field, .super-textarea .super-shortcode-field, .super-filled .super-adaptive-placeholder > span, .super-dropdown.super-filled .super-item.super-placeholder, .super-checkbox .super-item > div, .super-radio .super-item > div, .super-quantity .super-shortcode-field, .super-toggle-switch, .super-currency .super-shortcode-field, .super-slider .amount, .super-calculator-currency-wrapper, .super-calculator-label, .super-fileupload-name, .super-fileupload-button-text, .super-toggle-prefix-label > span, .super-toggle-suffix-label > span, .super-html-title, .super-html-subtitle, .super-html-content',
7404        normalizeFontStylesNodesClassesExploded = normalizeFontStylesNodesClasses.split(','),
7405        newNormalizeFontStylesNodesClasses = '';
7406        for(i=0; i<normalizeFontStylesNodesClassesExploded.length; i++){
7407            if(i>0) newNormalizeFontStylesNodesClasses += ', ';
7408            newNormalizeFontStylesNodesClasses += '.super-pdf-page-container '+normalizeFontStylesNodesClassesExploded[i];
7409        }
7410
7411        // Must hide elements
7412        var css = '.super-hide-scrollbar {overflow: -moz-hidden-unscrollable!important; overflow: hidden!important;}';
7413        // Required to render pseudo elements (html2canvas code was altered for this)
7414        css += '.super-pdf-page-container.super-pdf-clone .super-form *:before,';
7415        css += '.super-pdf-page-container.super-pdf-clone .super-form *:after {display:none!important;}';
7416        // Set font weight, line height and letter spacing to normal sizes to avoid inconsistencies between PDF and rendered text in PDF
7417        css += newNormalizeFontStylesNodesClasses + '{font-family:"Helvetica", "Arial", sans-serif!important;font-weight:normal!important;line-height:1.2!important;letter-spacing:0!important;}';
7418        // Remove any form padding
7419        css += '.super-pdf-page-container .super-form.super-adaptive { padding-top: 0px!important; }';
7420        // Hide none essential elements/styles from the PDF output
7421        css += '.super-generating-pdf:not(.super-pdf-placeholder) *,';
7422        css += '.super-generating-pdf:not(.super-pdf-placeholder) *:after,';
7423        css += '.super-generating-pdf:not(.super-pdf-placeholder) .super-accordion-header:after,';
7424        css += '.super-generating-pdf:not(.super-pdf-placeholder) .super-accordion-header:before { transition: initial!important; }';
7425        css += '.super-generating-pdf:not(.super-pdf-placeholder) .super-accordion-header:before,';
7426        css += '.super-generating-pdf:not(.super-pdf-placeholder) .super-accordion-header:after,';
7427        css += '.super-generating-pdf:not(.super-pdf-placeholder) .super-form-button,';
7428        css += '.super-generating-pdf:not(.super-pdf-placeholder) .super-multipart-progress,';
7429        css += '.super-generating-pdf:not(.super-pdf-placeholder) .super-multipart-steps,';
7430        css += '.super-generating-pdf:not(.super-pdf-placeholder) .super-prev-multipart,';
7431        css += '.super-generating-pdf:not(.super-pdf-placeholder) .super-next-multipart,';
7432        css += '.super-generating-pdf:not(.super-pdf-placeholder) .super-tabs-menu,';
7433        css += '.super-generating-pdf:not(.super-pdf-placeholder) .super-duplicate-actions,';
7434        css += '.super-generating-pdf:not(.super-pdf-placeholder) .super-signature-clear { display: none!important; }';
7435        css += '.super-generating-pdf:not(.super-pdf-placeholder) .super-accordion-header { border: 1px solid #d2d2d2; }';
7436        css += '.super-generating-pdf:not(.super-pdf-placeholder) .super-accordion-header { border: 1px solid #d2d2d2; }';
7437        css += '.super-pdf-header, .super-pdf-body, .super-pdf-footer { display: block; float: left; width: 100%; overflow: hidden; }';
7438        // Header margins
7439        var headerMarginBottom = parseFloat(args.pdfSettings.margins.header.bottom)+parseFloat(args.pdfSettings.margins.body.top);
7440        css += '.super-pdf-header {padding: '+args.pdfSettings.margins.header.top+args.pdfSettings.unit+' '+args.pdfSettings.margins.header.right+args.pdfSettings.unit+' '+headerMarginBottom+args.pdfSettings.unit+' '+args.pdfSettings.margins.header.left+args.pdfSettings.unit+' }';
7441        css += '.super-pdf-header .super-form, .super-pdf-header .super-form form {padding:0!important;margin:0!important;float:left!important;width:100%!important;}';
7442        // Body margins
7443        css += '.super-pdf-body {padding: 0'+args.pdfSettings.unit+' '+args.pdfSettings.margins.body.right+args.pdfSettings.unit+' 0'+args.pdfSettings.unit+' '+args.pdfSettings.margins.body.left+args.pdfSettings.unit+';}';
7444        // Footer margins
7445        var footerMarginTop = parseFloat(args.pdfSettings.margins.footer.top)+parseFloat(args.pdfSettings.margins.body.bottom);
7446        css += '.super-pdf-footer {padding: '+footerMarginTop+args.pdfSettings.unit+' '+args.pdfSettings.margins.footer.right+args.pdfSettings.unit+' '+args.pdfSettings.margins.footer.bottom+args.pdfSettings.unit+' '+args.pdfSettings.margins.footer.left+args.pdfSettings.unit+'; }';
7447        css += '.super-pdf-footer .super-form, .super-pdf-footer .super-form form {padding:0!important;margin:0!important;float:left!important;width:100%!important;}';
7448
7449        var head = document.head || document.getElementsByTagName('head')[0],
7450        style = document.createElement('style');
7451        style.id = 'super-generating-pdf';
7452        head.appendChild(style);
7453        style.type = 'text/css';
7454        if (style.styleSheet){
7455            // This is required for IE8 and below.
7456            style.styleSheet.cssText = css;
7457        } else {
7458            style.appendChild(document.createTextNode(css));
7459        }
7460
7461        var formId = form.querySelector('input[name="hidden_form_id"]').value;
7462
7463
7464        // Add form placeholder (fake form)
7465        var placeholder = form.cloneNode(true);
7466        placeholder.id = placeholder.id+'-placeholder';
7467        placeholder.classList.add('super-pdf-placeholder');
7468        args.placeholder = placeholder;
7469        form.parentNode.insertBefore(placeholder, form.nextSibling);
7470
7471        // Remove responsiveness classes, so that mobile and desktop PDF look identical
7472        var clonedForm = form.cloneNode(true);
7473        var newClassName = '';
7474        //var oldClassName = clonedForm.className;
7475        for(var i=0; i<clonedForm.classList.length; i++){
7476            // e.g: super-first-responsiveness, super-window-first-responsiveness
7477            if(clonedForm.classList[i].indexOf('responsiveness')===-1){
7478                newClassName += clonedForm.classList[i]+' ';
7479            }
7480        }
7481        // Update classname
7482        clonedForm.className = newClassName;
7483        args.form0.className = newClassName;
7484        var headerClone = clonedForm.cloneNode(true);
7485        var footerClone = clonedForm.cloneNode(true);
7486        
7487        // PDF page container
7488        var pdfPageContainer = document.createElement('div');
7489        args.pdfPageContainer = pdfPageContainer;
7490        var html = '<div class="super-pdf-header">';
7491            // Put any header(s) here
7492        html += '</div>';
7493        html += '<div class="super-pdf-body">';
7494            // Put form here
7495        html += '</div>';
7496        html += '<div class="super-pdf-footer">';
7497            // Put any footer(s) here
7498        html += '</div>';
7499        pdfPageContainer.innerHTML = html;
7500        pdfPageContainer.classList.add('super-pdf-page-container');
7501        document.body.appendChild(pdfPageContainer);
7502        pdfPageContainer.style.width = (args.pageWidthInPixels*2)+'px';
7503        pdfPageContainer.style.zIndex = "-999999999";
7504        pdfPageContainer.style.left = "-9999px";
7505        pdfPageContainer.style.top = "0px";
7506        // ------- for debugging only: ----
7507        //debugger;
7508        //pdfPageContainer.style.zIndex = "9999999999";
7509        //pdfPageContainer.style.left = "0px";
7510        //pdfPageContainer.style.top = "0px";
7511        // ------- for debugging only: ----
7512        pdfPageContainer.style.position = "fixed";
7513        pdfPageContainer.style.backgroundColor = "#ffffff";
7514        pdfPageContainer.style.height = (args.pageHeightInPixels*2)+'px';
7515        pdfPageContainer.style.maxHeight = (args.pageHeightInPixels*2)+'px';
7516        pdfPageContainer.style.overflow = "hidden";
7517        pdfPageContainer.querySelector('.super-pdf-header').appendChild(headerClone);
7518        pdfPageContainer.querySelector('.super-pdf-body').appendChild(args.form0);
7519        pdfPageContainer.querySelector('.super-pdf-footer').appendChild(footerClone);
7520
7521        // Put header before form
7522        headerClone.querySelector('form').innerHTML = '';
7523        var header = form.querySelector('.super-shortcode[data-pdfoption="header"]');
7524        if(header){
7525            if(header.classList.contains('super-column')){
7526                header = header.closest('.super-grid').cloneNode(true);
7527            }else{
7528                header = header.cloneNode(true);
7529            }
7530            header.classList.add('pdf-generated-header');
7531            headerClone.querySelector('form').appendChild(header);
7532        }
7533
7534        // Put footer after form
7535        footerClone.querySelector('form').innerHTML = '';
7536        var footer = form.querySelector('.super-shortcode[data-pdfoption="footer"]');
7537        if(footer){
7538            if(footer.classList.contains('super-column')){
7539                footer = footer.closest('.super-grid').cloneNode(true);
7540            }else{
7541                footer = footer.cloneNode(true);
7542            }
7543            footer.classList.add('pdf-generated-footer');
7544            footerClone.querySelector('form').appendChild(footer);
7545        }
7546
7547        // Resize PDF body height based on header/footer heights
7548        var headerFooterHeight = 0;
7549        headerFooterHeight += pdfPageContainer.querySelector('.super-pdf-header').clientHeight;
7550        headerFooterHeight += pdfPageContainer.querySelector('.super-pdf-footer').clientHeight;
7551        args.scrollAmount = (args.pageHeightInPixels*2)-headerFooterHeight;
7552        pdfPageContainer.querySelector('.super-pdf-body').style.height = args.scrollAmount+'px';
7553        pdfPageContainer.querySelector('.super-pdf-body').style.maxHeight = args.scrollAmount+'px';
7554
7555        // Make all mutli-parts visible
7556        // Make all TABs visible
7557        // Make all accordions visible
7558        var nodes = form.querySelectorAll('.super-multipart,.super-tabs-content,.super-accordion-item');
7559        for( i=0; i < nodes.length; i++){
7560            if(nodes[i].classList.contains('super-active')){
7561                nodes[i].classList.add('super-active-origin');         
7562            }else{
7563                nodes[i].classList.add('super-active');
7564            }
7565        }
7566
7567        // Normalize all font sizes
7568        // Example of allowed font sizes are: 10px, 12.5px, 15px, 17.5px, 20px etc. (increment with 2.5px)
7569        // Other font sizes creates issues within the PDF
7570        // We only have to loop over fields that we are going to print out
7571        nodes = pdfPageContainer.querySelectorAll(normalizeFontStylesNodesClasses);
7572        for( i=0; i < nodes.length; i++ ) {
7573            var el = nodes[i];
7574            if(el.classList.contains('super-heading-title')){
7575                el = el.children[0];
7576            }
7577            var fontSize = parseFloat(window.getComputedStyle(el, null).getPropertyValue('font-size'));
7578            var newFontSize = 2.5 * Math.ceil(fontSize/2.5);
7579            el.style.fontSize = newFontSize+'px';
7580        }
7581
7582        SUPER.init_super_responsive_form_fields({form: form, callback: function(){
7583
7584            // First disable the UI on the map for nicer print of the map
7585            // And make map fullwidth and directions fullwidth
7586            for(i=0; i < SUPER.google_maps_api.allMaps[formId].length; i++){
7587                SUPER.google_maps_api.allMaps[formId][i].setOptions({
7588                    disableDefaultUI: true
7589                });
7590                nodes = SUPER.google_maps_api.allMaps[formId][i]['super_el'].querySelectorAll(':scope > div');
7591                for(var x=0; x < nodes.length; x++){
7592                    nodes[x].style.width = '100%';
7593                    if(nodes[x].classList.contains('super-google-map-directions')){
7594                        nodes[x].style.overflowY = 'initial';
7595                        nodes[x].style.height = 'auto';
7596                    }
7597                }
7598            }
7599            
7600            // Convert height of textarea to fit content (otherwie it would be cut of during printing)
7601            function adjustHeight(el, minHeight) {
7602                // compute the height difference which is caused by border and outline
7603                var outerHeight = parseInt(window.getComputedStyle(el).height, 10);
7604                var diff = outerHeight - el.clientHeight;
7605                // set the height to 0 in case of it has to be shrinked
7606                el.style.height = 0;
7607                // set the correct height
7608                // el.scrollHeight is the full height of the content, not just the visible part
7609                el.style.height = Math.max(minHeight, el.scrollHeight + diff) + 'px';
7610            }
7611            // we use the "data-adaptheight" attribute as a marker
7612            // iterate through all the textareas on the page
7613            var i, el, minHeight, nodes = form.querySelectorAll('.super-textarea .super-shortcode-field');
7614            for(i=0; i<nodes.length; i++){
7615                el = nodes[i];
7616                // we need box-sizing: border-box, if the textarea has padding
7617                el.style.boxSizing = el.style.mozBoxSizing = 'border-box';
7618                // we don't need any scrollbars, do we? :)
7619                el.style.overflowY = 'hidden';
7620                // the minimum height initiated through the "rows" attribute
7621                minHeight = el.scrollHeight * 1.03;
7622                el.addEventListener('input', function() {
7623                    adjustHeight(el, minHeight);
7624                });
7625                // we have to readjust when window size changes (e.g. orientation change)
7626                window.addEventListener('resize', function() {
7627                    adjustHeight(el, minHeight);
7628                });
7629                // we adjust height to the initial content
7630                adjustHeight(el, minHeight);
7631            }
7632
7633            // Loop over any possible PDF page break elements, and add the height to fill up the rest of the page with "nothing"
7634            nodes = form.querySelectorAll('.super-pdf_page_break');
7635            args.pageOrientationChanges = {};
7636            for(i=0; i<nodes.length; i++){
7637                var pos = nodes[i].getBoundingClientRect();
7638                var headerHeight = args.pdfPageContainer.querySelector('.super-pdf-header').clientHeight;
7639                var belongsToPage = Math.ceil((pos.top-headerHeight)/args.scrollAmount)-1;
7640                var dynamicHeight = (args.scrollAmount*(belongsToPage+1)) - (pos.top - headerHeight);
7641                nodes[i].style.height = dynamicHeight+'px';
7642                args.pageOrientationChanges[belongsToPage+2] = 'unchanged';
7643                if(nodes[i].classList.contains('pdf-orientation-portrait')){
7644                    args.pageOrientationChanges[belongsToPage+2] = 'portrait';
7645                }
7646                if(nodes[i].classList.contains('pdf-orientation-landscape')){
7647                    args.pageOrientationChanges[belongsToPage+2] = 'landscape';
7648                }
7649                if(nodes[i].classList.contains('pdf-orientation-default')){
7650                    args.pageOrientationChanges[belongsToPage+2] = 'default';
7651                }
7652            }
7653
7654            // Grab the total form height, this is required to know how many pages will be generated for the PDF file
7655            // This way we can also show the progression to the end user
7656            //scrollAmount = (pageHeightInPixels*2);
7657            args.totalPages = Math.ceil(form.clientHeight/args.scrollAmount);
7658            args.totalPercentagePerPage = (100/args.totalPages) / 3;
7659            args.pdfPercentageCompleted = 0;
7660            callback(args);
7661        }});
7662    };
7663
7664
7665
7666    // PDF Generation
7667    SUPER.pdf_generator_generate_page = function(args){
7668        args.pdfPercentageCompleted += args.totalPercentagePerPage;
7669        if(args.progressBar) args.progressBar.style.width = args.pdfPercentageCompleted+"%";  
7670        var form = args.form0.closest('.super-form');
7671        // When canceled the following class will no longer exist, and we should not proceed
7672        if(form && !form.classList.contains('super-generating-pdf')){
7673            return false;
7674        }
7675        if(args.currentPage===1){
7676            if(args.orientation==='portrait'){
7677                args.pageWidth = args.pageWidthPortrait;
7678                args.pageHeight = args.pageHeightPortrait;
7679            }else{
7680                args.pageWidth = args.pageWidthLandscape;
7681                args.pageHeight = args.pageHeightLandscape;
7682            }
7683        }else{
7684            // Change the PDF container width based on orientation
7685            var headerFooterHeight = 0;
7686            if(args.pageOrientationChanges[args.currentPage]==='portrait'){
7687                args.pdfPageContainer.style.width = (args.pageWidthInPixels*2)+'px';
7688                args.pdfPageContainer.style.height = (args.pageHeightInPixels*2)+'px';
7689                args.pdfPageContainer.style.maxHeight = (args.pageHeightInPixels*2)+'px';
7690                args.pageWidth = args.pageWidthPortrait;
7691                args.pageHeight = args.pageHeightPortrait;
7692                args.pageWidthInPixels = args.pageWidth / args.unitRatio;
7693                args.pageHeightInPixels = args.pageHeight / args.unitRatio;
7694                headerFooterHeight += args.pdfPageContainer.querySelector('.super-pdf-header').clientHeight;
7695                headerFooterHeight += args.pdfPageContainer.querySelector('.super-pdf-footer').clientHeight;
7696                args.scrollAmount = (args.pageHeightInPixels*2)-headerFooterHeight;
7697            }
7698            if(args.pageOrientationChanges[args.currentPage]==='landscape'){
7699                args.pdfPageContainer.style.width = (args.pageHeightInPixels*2)+'px';
7700                args.pdfPageContainer.style.height = (args.pageWidthInPixels*2)+'px';
7701                args.pdfPageContainer.style.maxHeight = (args.pageWidthInPixels*2)+'px';
7702                args.pageWidth = args.pageWidthLandscape;
7703                args.pageHeight = args.pageHeightLandscape;
7704                args.pageWidthInPixels = args.pageWidth / args.unitRatio;
7705                args.pageHeightInPixels = args.pageHeight / args.unitRatio;
7706                headerFooterHeight += args.pdfPageContainer.querySelector('.super-pdf-header').clientHeight;
7707                headerFooterHeight += args.pdfPageContainer.querySelector('.super-pdf-footer').clientHeight;
7708                args.scrollAmount = (args.pageWidthInPixels*2)-headerFooterHeight;
7709            }
7710            // Reset any PDF page break heights
7711            var i, nodes = form.querySelectorAll('.super-pdf_page_break');
7712            for(i=0; i<nodes.length; i++){
7713                nodes[i].style.height = '0px';
7714            }
7715            // Reset scroll
7716            form.querySelector('form').style.marginTop = '';
7717
7718            // Loop over any possible PDF page break elements, and add the height to fill up the rest of the page with "nothing"
7719            nodes = form.querySelectorAll('.super-pdf_page_break');
7720            args.pageOrientationChanges = {};
7721            for(i=0; i<nodes.length; i++){
7722                var pos = nodes[i].getBoundingClientRect();
7723                var headerHeight = args.pdfPageContainer.querySelector('.super-pdf-header').clientHeight;
7724                var belongsToPage = Math.ceil((pos.top-headerHeight)/args.scrollAmount)-1;
7725                var dynamicHeight = (args.scrollAmount*(belongsToPage+1)) - (pos.top - headerHeight);
7726                nodes[i].style.height = dynamicHeight+'px';
7727                args.pageOrientationChanges[belongsToPage+2] = 'unchanged';
7728                if(nodes[i].classList.contains('pdf-orientation-portrait')){
7729                    args.pageOrientationChanges[belongsToPage+2] = 'portrait';
7730                }
7731                if(nodes[i].classList.contains('pdf-orientation-landscape')){
7732                    args.pageOrientationChanges[belongsToPage+2] = 'landscape';
7733                }
7734                if(nodes[i].classList.contains('pdf-orientation-default')){
7735                    args.pageOrientationChanges[belongsToPage+2] = 'default';
7736                }
7737            }
7738            args.pdfPageContainer.querySelector('.super-pdf-body').style.height = args.scrollAmount+'px';
7739            args.pdfPageContainer.querySelector('.super-pdf-body').style.maxHeight = args.scrollAmount+'px';
7740            // Scroll to the "fake" page
7741            form.querySelector('form').style.marginTop = "-"+(args.scrollAmount * (args.currentPage-1))+'px';
7742        }
7743        
7744
7745        // Set form width and height according to a4 paper size minus the margins
7746        // 210 == 793px
7747        // 297 == 1122px
7748        // Media                Page size           Print area              Margins
7749        // A4 (Metric)          210 x 297 mm        200 x 287 mm            5 mm        5 mm        5 mm
7750
7751        // Update PDF tags
7752        SUPER.pdf_tags = {
7753            pdf_page: args.currentPage,
7754            pdf_total_pages: args.totalPages
7755        };
7756
7757        // Update pdf {tags}
7758        SUPER.after_field_change_blur_hook({el: undefined, form: form});
7759        var pdfHeaderForm = document.querySelector('.super-pdf-header .super-form');
7760        SUPER.after_field_change_blur_hook({el: undefined, form: pdfHeaderForm});
7761        var pdfFooterForm = document.querySelector('.super-pdf-footer .super-form');
7762        SUPER.after_field_change_blur_hook({el: undefined, form: pdfFooterForm});
7763
7764        // Scroll to the "fake" page
7765        //form.querySelector('form').style.marginTop = "-"+(args.scrollAmount * (args.currentPage-1))+'px';
7766
7767        // Because disabling the UI takes some time, add a timeout
7768        var timeout = (args.currentPage===1 ? 200 : 0);
7769        setTimeout(function(){
7770            // Now allow printing
7771            try {
7772                // Only if not already canceled/reset
7773                if(form && !form.classList.contains('super-generating-pdf')){
7774                    return false;
7775                }
7776                // eslint-disable-next-line no-undef
7777                args.pdfPercentageCompleted += args.totalPercentagePerPage;
7778                if(args.progressBar) args.progressBar.style.width = args.pdfPercentageCompleted+"%";  
7779                html2canvas(document.querySelector('.super-pdf-page-container'), {
7780                    scrollX: 0, // Important, do not remove
7781                    scrollY: 0,  // -window.scrollY, // Important, do not remove
7782                    scale: args.pdfSettings.renderScale, // The scale to use for rendering (higher means better quality, but larger file size)
7783                    currentPage: args.currentPage,
7784                    useCORS: true,
7785                    allowTaint: false,
7786                    backgroundColor: '#ffffff'
7787                }).then(function(canvas) {
7788                    // Only if not already canceled/reset
7789                    if(form && !form.classList.contains('super-generating-pdf')){
7790                        return false;
7791                    }
7792                    args.pdfPercentageCompleted += args.totalPercentagePerPage;
7793                    if(args.pdfPercentageCompleted > 99){
7794                        args.pdfPercentageCompleted = 100;
7795                    }
7796                    if(args.progressBar) args.progressBar.style.width = args.pdfPercentageCompleted+"%";  
7797                    //var percentage = (100/args.totalPages)*args.currentPage;
7798                    //if(args.progressBar) args.progressBar.style.width = percentage+"%";  
7799                    var imgData = canvas.toDataURL("image/jpeg", 1.0);
7800                    // Add this image as 1 single page
7801                    args._pdf.addImage(
7802                        imgData,    // imageData as base64 encoded DataUrl or Image-HTMLElement or Canvas-HTMLElement
7803                        'JPEG',     // format of file if filetype-recognition fails or in case of a Canvas-Element needs to be specified (default for Canvas is JPEG),
7804                                    // e.g. 'JPEG', 'PNG', 'WEBP'
7805                        0,          // x Coordinate (in units declared at inception of PDF document) against left edge of the page
7806                        0,          // y Coordinate (in units declared at inception of PDF document) against upper edge of the page
7807                        args.pageWidth,
7808                        args.pageHeight
7809                    );
7810                    // Make PDF searchable when text rendering is enabled
7811                    if(!args.pdfSettings.textRendering) args.pdfSettings.textRendering = 'true';
7812                    if(args.pdfSettings.textRendering==='true'){
7813                        SUPER.pdf_generator_render_text(args);
7814                    }
7815                    // If there are more pages to be processed, go ahead
7816                    if(form.querySelector('form').clientHeight > (args.scrollAmount * args.currentPage)){
7817                        args.currentPage++;
7818                        if(typeof args.pageOrientationChanges[args.currentPage] !== 'undefined' ){
7819                            if(args.pageOrientationChanges[args.currentPage]==='unchanged'){
7820                                if(typeof args.lastPageOrientation === 'undefined' ){
7821                                    args.lastPageOrientation = args.pdfSettings.orientation;
7822                                }
7823                                args._pdf.addPage(args.pdfSettings.format, args.lastPageOrientation);
7824                            }else{
7825                                if(args.pageOrientationChanges[args.currentPage]==='default'){
7826                                    args._pdf.addPage(args.pdfSettings.format, args.pdfSettings.orientation);
7827                                    args.lastPageOrientation = args.pdfSettings.orientation;
7828                                }else{
7829                                    args._pdf.addPage(args.pdfSettings.format, args.pageOrientationChanges[args.currentPage]);
7830                                    args.lastPageOrientation = args.pageOrientationChanges[args.currentPage];
7831                                }
7832                            }
7833                        }else{
7834                            args._pdf.addPage(args.pdfSettings.format, args.pdfSettings.orientation);
7835                            args.lastPageOrientation = args.pdfSettings.orientation;
7836                        }
7837                        SUPER.pdf_generator_generate_page(args);
7838                    }else{                   
7839                        // No more pages to generate (submit form / send email)
7840                        SUPER._pdf_generator_done_callback(args);
7841                    }
7842                });
7843            }
7844            catch(error) {
7845                console.log("Error: ", error);
7846            }
7847        }, timeout );
7848    }
7849    // PDF render text
7850    SUPER.pdf_generator_render_text = function(args){
7851        // If so add a text node on the exact position
7852        var i, nodes, formWidth, pdfPageWidth, scale,
7853            lineHeight = 1.194,
7854            drawRectangle = false, // true,
7855            renderingMode = 'invisible', // fill,
7856            resume, el,
7857            // Loop over all elements and see if the element is included in the PDF
7858            pdfPageContainer = document.querySelector('.super-pdf-page-container'),
7859            //pdfHeader = pdfPageContainer.querySelector('.super-pdf-header'),
7860            //pdfBody = pdfPageContainer.querySelector('.super-pdf-body'),
7861            //pdfFooter = pdfPageContainer.querySelector('.super-pdf-footer'),
7862            convertToPixel = 1,
7863            convertFromPixel = 1,
7864            charSpaceMultiplier = 0.00135;
7865
7866        // Convert unit to pixel
7867        if(args.pdfSettings.unit=='pt') convertToPixel = 1.333333333333333;
7868        if(args.pdfSettings.unit=='mm') convertToPixel = 3.7795275591;
7869        if(args.pdfSettings.unit=='cm') convertToPixel = 37.7952755906
7870        if(args.pdfSettings.unit=='in') convertToPixel = 96;
7871        // Convert pixel to unit
7872        if(args.pdfSettings.unit=='pt') convertFromPixel = 0.75;
7873        if(args.pdfSettings.unit=='mm') convertFromPixel = 0.2645833333;
7874        if(args.pdfSettings.unit=='cm') convertFromPixel = 0.0264583333;
7875        if(args.pdfSettings.unit=='in') convertFromPixel = 0.0104166667;
7876        // Convert pixel to unit
7877        if(args.pdfSettings.unit=='pt') charSpaceMultiplier = 0.00200;
7878        if(args.pdfSettings.unit=='mm') charSpaceMultiplier = 0.00200;
7879        if(args.pdfSettings.unit=='cm') charSpaceMultiplier = 0.00200;
7880        if(args.pdfSettings.unit=='in') charSpaceMultiplier = 0.00200;
7881        var topLineHeightDivider = 1;
7882        if(args.pdfSettings.unit=='px') topLineHeightDivider = 2;
7883        var m = args.pdfSettings.margins;
7884        var bodyMargins = {
7885            top: parseFloat(m.body.top)*convertToPixel,
7886            right: parseFloat(m.body.right)*convertToPixel,
7887            bottom: parseFloat(m.body.bottom)*convertToPixel,
7888            left: parseFloat(m.body.left)*convertToPixel,
7889        };
7890        
7891        // Determine scale
7892        formWidth = args.form0.clientWidth;
7893        formWidth = formWidth + bodyMargins.left + bodyMargins.right;
7894        pdfPageWidth = args._pdf.internal.pageSize.getWidth()*convertToPixel;
7895        scale = formWidth / pdfPageWidth;
7896
7897        if(super_common_i18n.fonts){
7898            args._pdf.setFont('NotoSans-Regular');
7899        }else{
7900            args._pdf.setFont('Helvetica');
7901        }
7902        args._pdf.setTextColor('red');
7903        args._pdf.setLineWidth(1*convertFromPixel);
7904
7905        nodes = pdfPageContainer.querySelectorAll('.super-label, .super-description, .super-heading-title, .super-heading-description, .super-filled .super-adaptive-placeholder > span, .super-dropdown.super-filled .super-item.super-placeholder, .super-checkbox .super-item > div, .super-radio .super-item > div, .super-toggle-switch, .super-slider .amount, .super-calculator-currency-wrapper, .super-calculator-label, .super-fileupload-name, .super-fileupload-button-text, .super-toggle-prefix-label > span, .super-toggle-suffix-label > span, .super-html-title, .super-html-subtitle, .super-html-content, .super-text .super-shortcode-field, .super-textarea .super-shortcode-field, .super-quantity .super-shortcode-field, .super-currency .super-shortcode-field');
7906        for( i=0; i < nodes.length; i++ ) {
7907            el = nodes[i];
7908            // For HTML content we will need to do some special things because a HTML element will contain unkown nodes with unkown styles
7909            // We will first have to wrap any stand alone text inside a <div> tag. This way we can more accurately position the overlapping text
7910            // After that we can loop over nodes and check for child nodes and do the same thing
7911            // Once done we can then do a final loop
7912            if(el.classList.contains('super-html-content')){
7913                // Wrap individual text inside "span" tags
7914                //var regex = /(?<=(>))((?![<])(.{1,}?))(?=<)/gm;
7915                //var str = el.innerHTML;
7916                //var subst = '<span class="super-pdf-text">$2</span>';
7917                //// The substituted value will be contained in the result variable
7918                //var result = str.replace(regex, subst);
7919                //regex = /(?<=<.+?>)([\s]+(?!<).{1,}[\s]+)(?=<.+?>)/gm;
7920                //str = result;
7921                //subst = '<span class="super-pdf-text">$1</span>';
7922                //// The substituted value will be contained in the result variable
7923                //el.innerHTML = str.replace(regex, subst);
7924                //var childNodes = el.querySelectorAll('.super-pdf-text');
7925                //for(var x=0; x < childNodes.length; x++){
7926                //    resume = SUPER.draw_pdf_text(i, childNodes[x], childNodes, args, renderingMode, charSpaceMultiplier, convertFromPixel, scale, pdfPageContainer, lineHeight, topLineHeightDivider, drawRectangle);
7927                //    if(resume) continue;
7928                //}
7929                continue;
7930            }
7931            resume = SUPER.pdf_generator_draw_pdf_text(i, el, nodes, args, renderingMode, charSpaceMultiplier, convertFromPixel, scale, pdfPageContainer, lineHeight, topLineHeightDivider, drawRectangle);
7932            if(resume) continue;
7933        }
7934    };
7935    // PDF Draw text
7936    SUPER.pdf_generator_draw_pdf_text = function(i, el, nodes, args, renderingMode, charSpaceMultiplier, convertFromPixel, scale, pdfPageContainer, lineHeight, topLineHeightDivider, drawRectangle){
7937        if(super_common_i18n.fonts){
7938            args._pdf.setFont('NotoSans-Regular');
7939        }else{
7940            args._pdf.setFont('Helvetica');
7941        }
7942        args._pdf.setFontType('normal');
7943
7944        var tmpPosTop, paddingRight, paddingLeft, paddingTop, pos, value = '';
7945        if(el.classList.contains('super-heading-title')){
7946            el = nodes[i].children[0];
7947        }
7948        if(el.classList.contains('super-heading-description')){
7949            el = nodes[i].children[0];
7950        }
7951        if(el.classList.contains('super-toggle-switch')){
7952            if(el.classList.contains('super-active')){
7953                el = el.querySelector('.super-toggle-on');
7954                value = el.querySelector('.super-toggle-on > span').innerText;
7955                paddingRight = (parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-right'))/scale)*convertFromPixel;
7956            }else{
7957                el = el.querySelector('.super-toggle-off');
7958                value = el.querySelector('.super-toggle-off > span').innerText;
7959                paddingLeft = (parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-left'))/scale)*convertFromPixel;
7960            }
7961        }else{
7962            if(el.closest('.super-text, .super-textarea, .super-quantity, .super-currency')){
7963                if(el.value) {
7964                    value = el.value;
7965                }else if(el.innerText) {
7966                    value = el.innerText;
7967                }
7968            }else{
7969                value = el.innerText;
7970            }
7971        }
7972        if(value==='') return true; //continue;
7973        pos = el.getBoundingClientRect();
7974        // Before we print the text, we must check if it's visible for this specific PDF page
7975        tmpPosTop = pos.top;
7976        // Only if not header and not footer, because these are printed on every single page
7977        if((!el.closest('.super-pdf-header')) && !el.closest('.super-pdf-footer')){
7978            var headerHeight = pdfPageContainer.querySelector('.super-pdf-header').clientHeight;
7979            if((tmpPosTop-(headerHeight-1)) < 0 || tmpPosTop > (args.scrollAmount+(headerHeight-1))){
7980                return true; //continue;
7981            }
7982        }
7983        var posWidth = (pos.width/scale)*convertFromPixel;
7984        var posHeight = (pos.height/scale)*convertFromPixel;
7985        var posLeft = ((pos.left+9999)/scale)*convertFromPixel;
7986        var posTop = ((tmpPosTop)/scale)*convertFromPixel;
7987        if(el.classList.contains('super-pdf-text')){
7988            if(el.parentNode.tagName==='STRONG' || el.parentNode.tagName==='TH'){
7989                if(super_common_i18n.fonts){
7990                    args._pdf.setFont('NotoSans-Bold');
7991                }else{
7992                    args._pdf.setFont('Helvetica');
7993                }
7994                args._pdf.setFontType('bold');
7995            }
7996            posWidth = ((pos.width+1)/scale)*convertFromPixel;
7997        }
7998        if(el.closest('.super-toggle-prefix-label') || el.closest('.super-toggle-suffix-label')){
7999            posTop = ((tmpPosTop+1)/scale)*convertFromPixel;
8000            posWidth = ((pos.width+1)/scale)*convertFromPixel;
8001        }
8002        if(el.closest('.super-radio') || el.closest('.super-checkbox') || el.classList.contains('super-fileupload-button-text')){
8003            posWidth = ((pos.width+1)/scale)*convertFromPixel;
8004        }
8005        var fontSize = parseFloat(window.getComputedStyle(el, null).getPropertyValue('font-size'));
8006        var fontSizePoint = fontSize * 0.67;
8007        value = args._pdf.setFontSize(fontSizePoint).splitTextToSize(value, posWidth);
8008        var charSpace = -(fontSize*charSpaceMultiplier)*convertFromPixel;
8009        var topLineHeight = (((fontSize*lineHeight)-fontSize)/topLineHeightDivider)*convertFromPixel;
8010        if(el.closest('.super-adaptive-placeholder')){
8011            posLeft = posLeft+(posWidth/2);
8012            if(drawRectangle) args._pdf.rect(posLeft, posTop+topLineHeight, posWidth, posHeight);
8013            args._pdf.text(value, posLeft, posTop+topLineHeight, {align: 'center', charSpace: charSpace, lineHeightFactor: lineHeight, baseline: 'hanging', renderingMode: renderingMode});
8014            return true; //continue;
8015        }
8016        if(el.closest('.super-dropdown')){
8017            paddingLeft = (parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-left'))/scale)*convertFromPixel;
8018            args._pdf.text(value, posLeft+paddingLeft, posTop+(posHeight/2), {charSpace: charSpace, lineHeightFactor: lineHeight, baseline: 'middle', renderingMode: renderingMode}); 
8019            return true; //continue;
8020        }
8021        if(el.closest('.super-radio') || el.closest('.super-checkbox')){
8022            if(drawRectangle) args._pdf.rect(posLeft, posTop+topLineHeight, posWidth, posHeight);
8023            args._pdf.text(value, posLeft, posTop+topLineHeight, {charSpace: charSpace, lineHeightFactor: lineHeight, baseline: 'hanging', renderingMode: renderingMode}); 
8024            return true; //continue;
8025        }
8026        if(el.closest('.super-toggle-switch')){
8027            if(el.closest('.super-toggle-switch').classList.contains('super-active')){
8028                if(drawRectangle) args._pdf.rect(posLeft+((posWidth-paddingRight)/2), posTop, posWidth-paddingRight, posHeight);
8029                args._pdf.text(value, posLeft+((posWidth-paddingRight)/2), posTop+(posHeight/2), {align: 'center', charSpace: charSpace, lineHeightFactor: lineHeight, baseline: 'middle', renderingMode: renderingMode}); 
8030            }else{
8031                if(drawRectangle) args._pdf.rect(posLeft+paddingLeft+((posWidth-paddingLeft)/2), posTop, posWidth-paddingLeft, posHeight);
8032                args._pdf.text(value, posLeft+paddingLeft+((posWidth-paddingLeft)/2), posTop+(posHeight/2), {align: 'center', charSpace: charSpace, lineHeightFactor: lineHeight, baseline: 'middle', renderingMode: renderingMode}); 
8033            }
8034            return true; //continue;
8035        }
8036        if(el.closest('.super-quantity')){
8037            if(drawRectangle) args._pdf.rect(posLeft, posTop+(posHeight/2), posWidth, posHeight);
8038            posLeft = posLeft+(posWidth/2);
8039            args._pdf.text(value, posLeft, posTop+(posHeight/2), {align: 'center', charSpace: charSpace, lineHeightFactor: lineHeight, baseline: 'middle', renderingMode: renderingMode}); 
8040            return true; //continue;
8041        }
8042        if(el.closest('.super-textarea')){
8043            paddingLeft = (parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-left'))/scale)*convertFromPixel;
8044            paddingTop = (parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-top'))/scale)*convertFromPixel;
8045            if(drawRectangle) args._pdf.rect(posLeft, posTop, posWidth, posHeight);
8046            args._pdf.text(value, posLeft+paddingLeft, posTop+paddingTop+topLineHeight, {charSpace: charSpace, lineHeightFactor: lineHeight, baseline: 'hanging', renderingMode: renderingMode}); 
8047            return true; //continue;
8048        }
8049        if(el.closest('.super-text') || el.closest('.super-currency')){
8050            paddingLeft = (parseFloat(window.getComputedStyle(el, null).getPropertyValue('padding-left'))/scale)*convertFromPixel;
8051            if(drawRectangle) args._pdf.rect(posLeft, posTop, posWidth, posHeight);
8052            args._pdf.text(value, posLeft+paddingLeft, posTop+(posHeight/2), {charSpace: charSpace, lineHeightFactor: lineHeight, baseline: 'middle', renderingMode: renderingMode}); 
8053            return true; //continue;
8054        }
8055        if(drawRectangle) args._pdf.rect(posLeft, posTop+topLineHeight, posWidth, posHeight);
8056        args._pdf.text(value, posLeft, posTop+topLineHeight, {charSpace: charSpace, lineHeightFactor: lineHeight, baseline: 'hanging', renderingMode: renderingMode}); 
8057        return true; //continue;
8058    };
8059    SUPER.pdf_generator_reset = function(form){
8060        // Only if not already canceled/reset
8061        if(form && !form.classList.contains('super-generating-pdf')){
8062            return false;
8063        }
8064        // Show scrollbar again
8065        document.documentElement.classList.remove('super-hide-scrollbar');
8066        var inlineStyle = document.querySelector('#super-generating-pdf');
8067        if(inlineStyle) inlineStyle.remove();
8068        // Make all mutli-parts invisible again (except for the last active multi-part)
8069        // Make all TABs invisible
8070        // Make all accordions invisible
8071        var nodes = form.querySelectorAll('.super-multipart,.super-tabs-content,.super-accordion-item');
8072        for(var i=0; i < nodes.length; i++){
8073            if(!nodes[i].classList.contains('super-active-origin')){
8074                nodes[i].classList.remove('super-active');
8075            }else{
8076                nodes[i].classList.remove('super-active-origin');
8077            }
8078        }
8079        // Reset any PDF page break heights
8080        nodes = form.querySelectorAll('.super-pdf_page_break');
8081        for(i=0; i<nodes.length; i++){
8082            nodes[i].style.height = '0px';
8083        }
8084        
8085        // @@@@@@@@@@@@@@
8086        // // Re-enable the UI for Maps and resize to original width
8087        // for(i=0; i < SUPER.google_maps_api.allMaps[$form_id].length; i++){
8088        //     SUPER.google_maps_api.allMaps[$form_id][i].setOptions({
8089        //         disableDefaultUI: false
8090        //     });
8091        //     var children = SUPER.google_maps_api.allMaps[$form_id][i]['super_el'].querySelectorAll(':scope > div');
8092        //     for(var x=0; x < children.length; x++){
8093        //         children[x].style.width = '';
8094        //         if(children[x].classList.contains('super-google-map-directions')){
8095        //             children[x].style.overflowY = 'scroll';
8096        //             children[x].style.height = SUPER.google_maps_api.allMaps[$form_id][i]['super_el'].querySelector('super-google-map-'+$form_id).offsetHeight+'px';
8097        //         }
8098        //     }
8099        // }
8100        // @@@@@@@@@@@@@@
8101
8102        // Restore form position and remove the cloned form
8103        // Before removing cloned form, insert original form before cloned form
8104        form.querySelector('form').style.marginTop = '';
8105        SUPER.reset_submit_button_loading_state(form);
8106        var placeholder = document.querySelector('.super-pdf-placeholder');
8107        placeholder.parentNode.insertBefore(form, placeholder.nextSibling);
8108        form.classList.remove('super-generating-pdf');
8109        placeholder.remove();
8110        var pdfPageContainer = document.querySelector('.super-pdf-page-container');
8111        if(pdfPageContainer) pdfPageContainer.remove();
8112        SUPER.init_super_responsive_form_fields({form: form});
8113    };
8114    SUPER.save_data = function(args){
8115        if(args.progressBar) args.progressBar.style.width = 0+'%';
8116        args.loadingOverlay.querySelector('.super-inner-text').innerHTML = '<span>'+super_common_i18n.loadingOverlay.processing+'</span>';
8117        var formData = new FormData();
8118        formData.append('action', 'super_submit_form');
8119        if(args.form_id) formData.append('form_id', args.form_id);
8120        if(args.entry_id) formData.append('entry_id', args.entry_id);
8121        if(args.list_id) formData.append('list_id', args.list_id);
8122        if(args.sf_nonce) formData.append('sf_nonce', args.sf_nonce);
8123        if(args.token) formData.append('token', args.token);
8124        if(args.version) formData.append('version', args.version);
8125        if(args.data) formData.append('data', JSON.stringify(args.data));
8126        formData.append('i18n', args.form.data('i18n')); // @since 4.7.0 translation
8127        $.ajax({
8128            type: 'post',
8129            url: super_common_i18n.ajaxurl,
8130            data: formData,
8131            async: true,
8132            cache: false,
8133            contentType: false,
8134            processData: false,
8135            timeout: 60000, // 1m
8136            xhr: function() {
8137                var xhr = new window.XMLHttpRequest();
8138                if(args.showOverlay==="true"){
8139                    xhr.upload.addEventListener("progress", function(evt) {
8140                        if (evt.lengthComputable) {
8141                            var percentComplete = evt.loaded / evt.total;
8142                            //Do something with upload progress here
8143                            if(args.progressBar) args.progressBar.style.width = (100*percentComplete)+"%";  
8144                            //if(args._pdf!==false){
8145                            //    if(args.progressBar) args.progressBar.style.width = ((50*percentComplete)+50)+"%";  
8146                            //}else{
8147                            //    if(args.progressBar) args.progressBar.style.width = (100*percentComplete)+"%";  
8148                            //}
8149                        }
8150                    }, false);
8151                }
8152                return xhr;
8153            },
8154            success: function(result){
8155                result = JSON.parse(result);
8156                if(result.error===true){
8157                    // Display error message
8158                    SUPER.form_submission_finished(args, result);
8159                }else{
8160                    // Update new nonce
8161                    if(result.response_data && result.response_data.sf_nonce){
8162                        $('input[name="sf_nonce"]').val(result.response_data.sf_nonce);
8163                    }
8164                    // Clear form progression (if enabled)
8165                    if( args.form[0].classList.contains('super-save-progress') ) {
8166                        $.ajax({
8167                            url: super_common_i18n.ajaxurl,
8168                            type: 'post',
8169                            data: {
8170                                action: 'super_save_form_progress',
8171                                data: '',
8172                                form_id: args.form_id
8173                            }
8174                        });
8175                    }
8176                    // Trigger js hook and continue
8177                    SUPER.after_email_send_hook(args);
8178                    // If a hook is redirecting we should avoid doing other things
8179                    if(args.form.data('is-redirecting')){
8180                        // However if a hook is doing things in the back-end, we must check until finished
8181                        if(args.form.data('is-doing-things')){
8182                            clearInterval(SUPER.submit_form_interval);
8183                            SUPER.submit_form_interval = setInterval(function(){
8184                                if(args.form.data('is-doing-things')){
8185                                    // Still doing things...
8186                                }else{
8187                                    clearInterval(SUPER.submit_form_interval);
8188                                    // Form submission is finished
8189                                    SUPER.form_submission_finished(args, result);
8190                                }
8191                            }, 100);
8192                        }
8193                        return false; // Stop here, we are redirecting the form (used by Stripe)
8194                    }
8195
8196                    // @since 2.2.0 - custom form POST method
8197                    if( (args.form.find('form').attr('method')=='post') && (args.form.find('form').attr('action')!=='') ){
8198                        args.form.find('form').submit(); // When doing custom POST, the form will redirect itself
8199                        return false;
8200                    }
8201                    // Form submission is finished
8202                    SUPER.form_submission_finished(args, result);
8203                }
8204            },
8205            error: function (xhr, ajaxOptions, thrownError) {
8206                // eslint-disable-next-line no-console
8207                console.log(xhr, ajaxOptions, thrownError);
8208                alert(super_common_i18n.errors.failed_to_process_data);
8209            }
8210        });
8211    };
8212
8213    
8214    jQuery(document).ready(function ($) {
8215        
8216        var $doc = $(document);
8217
8218        // Fix chrome autofill honeypot issue
8219        var $super_hp = $doc.find('input[name="super_hp"]');
8220        window.setInterval(function() {
8221            $super_hp.each(function(){
8222                var hasValue = $(this).val().length > 0; //Normal
8223                if(!hasValue){
8224                    if($(this).is("\\:-webkit-autofill")) {
8225                        hasValue = true;
8226                    }
8227                }
8228                if (hasValue) {
8229                    $super_hp.val('');
8230                }
8231            });
8232        }, 1000);
8233
8234        // @since 3.1.0 - google distance calculation between 2 addresses
8235        $doc.on('change keyup keydown blur', '.super-form .super-text .super-distance-calculator:not(.super-address-autopopulate)', function(){
8236            var field = this;
8237            if (timeout !== null) clearTimeout(timeout);
8238            timeout = setTimeout(function () {
8239                SUPER.calculate_distance({el: field});
8240            }, 1000);
8241        });
8242
8243        SUPER.init_field_filter_visibility();
8244        $doc.on('change keyup keydown blur','.super-field.super-filter',function(){
8245            if(this.closest('.super-form-settings')){
8246                SUPER.init_field_filter_visibility($(this));
8247            }else{
8248                SUPER.init_field_filter_visibility($(this), 'element_settings');
8249            }
8250        });  
8251
8252        $doc.on('click', '.super-field.super-currency',function(){
8253            var $field = $(this);
8254            var $form = $field.closest('.super-form');
8255            $form.find('.super-focus').removeClass('super-focus');
8256            $field.addClass('super-focus');
8257        });
8258
8259        $doc.on('keyup', '.super-icon-search input', function(){
8260            var $value = $(this).val();
8261            var $icons = $(this).parents('.super-icon-field').children('.super-icon-list').children('i');
8262            if($value===''){
8263                $icons.css('display','inline-block');   
8264            }else{
8265                $icons.each(function(){
8266                    if($(this).is('[class*="'+$value+'"]')) {
8267                        $(this).css('display','inline-block');
8268                    }else{
8269                        $(this).css('display','none');
8270                    }
8271                });
8272            }
8273        });
8274
8275        $doc.on('click','.super-icon-list i',function(){
8276            if($(this).hasClass('super-active')){
8277                $(this).parent().find('i').removeClass('super-active');
8278                $(this).parents('.super-icon-field').find('input').val('');
8279            }else{
8280                $(this).parent().find('i').removeClass('super-active');
8281                $(this).parents('.super-icon-field').find('input').val($(this).attr('class'));
8282                $(this).addClass('super-active');
8283            }
8284        });
8285
8286        var timeout = null;
8287        $doc.on('keyup paste', '.super-text .super-shortcode-field[data-search="true"]', function(){ 
8288            var field = this;
8289            if (timeout !== null) clearTimeout(timeout);
8290            timeout = setTimeout(function () {
8291                SUPER.populate_form_data_ajax({el: field});
8292            }, 1000);
8293        });
8294
8295        // WooCommerce Order Search Method (wcosm)
8296        var timeout2 = null;
8297        $doc.on('keyup', '.super-text .super-shortcode-field[data-wcosm]', function(){ 
8298            var $this = $(this);
8299            if (timeout2 !== null) {
8300                clearTimeout(timeout2);
8301            }
8302            timeout2 = setTimeout(function () {
8303                var $value = $this.val();
8304                var $method = $this.data('wcosm');
8305                var $filterby = $this.data('wcosfb');
8306                var $return_label = $this.data('wcosrl');
8307                var $return_value = $this.data('wcosrv');
8308                var $populate = $this.data('wcosp');
8309                var $skip = $this.data('wcoss');
8310                var $status = $this.data('wcosst');
8311                if( $value.length>0 ) {
8312                    $this.parents('.super-field-wrapper:eq(0)').addClass('super-populating');
8313                    $.ajax({
8314                        url: super_common_i18n.ajaxurl,
8315                        type: 'post',
8316                        data: {
8317                            action: 'super_search_wc_orders',
8318                            value: $value,
8319                            method: $method,
8320                            filterby: $filterby,
8321                            return_label: $return_label,
8322                            return_value: $return_value,
8323                            populate: $populate,
8324                            skip: $skip,
8325                            status: $status
8326                        },
8327                        success: function (result) {
8328                            if(result!==''){
8329                                $this.parents('.super-shortcode:eq(0)').addClass('super-focus');
8330                                $this.parents('.super-shortcode:eq(0)').addClass('super-string-found');
8331                            }
8332                            var ul = $this.parents('.super-field-wrapper:eq(0)').children('.super-dropdown-list');
8333                            if(ul.length){
8334                                ul.html(result);
8335                            }else{
8336                                $('<ul class="super-dropdown-list">'+result+'</ul>').appendTo($this.parents('.super-field-wrapper:eq(0)'));
8337                            }
8338                        },
8339                        complete: function(){
8340                            $this.parents('.super-field-wrapper:eq(0)').removeClass('super-populating');
8341                        },
8342                        error: function (xhr, ajaxOptions, thrownError) {
8343                            // eslint-disable-next-line no-console
8344                            console.log(xhr, ajaxOptions, thrownError);
8345                            alert(super_common_i18n.errors.failed_to_process_data);
8346                        }
8347                    });
8348                }
8349            }, 1000);
8350        });
8351
8352        SUPER.init_common_fields();
8353    });
8354
8355})(jQuery);
8356

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.