PageSourceSearch

https://www.iowebstudio.com/wp-content/plugins/wpforms/assets/js/wpforms.js?ver=1.5.1

js iowebstudio.com collected 2026-10-06 09:27:18 UTC 30,403 bytes, 974 lines download raw bytes

1/* global wpforms_settings,grecaptcha,wpforms_validate,wpforms_timepicker */
2
3;(function($) {
4
5	'use strict';
6
7	var WPForms = {
8
9		/**
10		 * Start the engine.
11		 *
12		 * @since 1.2.3
13		 */
14		init: function() {
15
16			// Document ready
17			$(document).ready(WPForms.ready);
18
19			// Page load
20			$(window).on('load', WPForms.load);
21
22			WPForms.bindUIActions();
23			WPForms.bindOptinMonster();
24		},
25
26		/**
27		 * Document ready.
28		 *
29		 * @since 1.2.3
30		 */
31		ready: function() {
32
33			// Set user identifier
34			WPForms.setUserIndentifier();
35
36			WPForms.loadValidation();
37			WPForms.loadDatePicker();
38			WPForms.loadTimePicker();
39			WPForms.loadInputMask();
40			WPForms.loadPayments();
41
42			// Randomize elements.
43			$( '.wpforms-randomize' ).each( function() {
44				var $list      = $( this ),
45					$listItems = $list.children();
46				while ( $listItems.length ) {
47					$list.append( $listItems.splice( Math.floor( Math.random() * $listItems.length ), 1 )[0] );
48				}
49			});
50
51			$(document).trigger('wpformsReady');
52		},
53
54		/**
55		 * Page load.
56		 *
57		 * @since 1.2.3
58		 */
59		load: function() {
60
61		},
62
63		//--------------------------------------------------------------------//
64		// Initializing
65		//--------------------------------------------------------------------//
66
67		/**
68		 * Load jQuery Validation.
69		 *
70		 * @since 1.2.3
71		 */
72		loadValidation: function() {
73
74			// Only load if jQuery validation library exists
75			if (typeof $.fn.validate !== 'undefined') {
76
77				// jQuery Validation library will not correctly validate
78				// fields that do not have a name attribute, so we use the
79				// `wpforms-input-temp-name` class to add a temporary name
80				// attribute before validation is initialized, then remove it
81				// before the form submits.
82				$( '.wpforms-input-temp-name' ).each(function( index, el ) {
83					var random = Math.floor( Math.random() * 9999 ) + 1;
84					$( this ).attr( 'name', 'wpf-temp-' + random );
85				});
86
87				// Prepend URL field contents with http:// if user input doesn't contain a schema.
88				$( '.wpforms-validate input[type=url]' ).change( function () {
89					var url = $( this ).val();
90					if ( ! url ) {
91						return false;
92					}
93					if ( url.substr( 0, 7 ) !== 'http://' && url.substr( 0, 8 ) !== 'https://' ) {
94						$( this ).val( 'http://' + url );
95					}
96				});
97
98				$.validator.messages.required = wpforms_settings.val_required;
99				$.validator.messages.url = wpforms_settings.val_url;
100				$.validator.messages.email = wpforms_settings.val_email;
101				$.validator.messages.number = wpforms_settings.val_number;
102
103				// Payments: Validate method for Credit Card Number
104				if(typeof $.fn.payment !== 'undefined') {
105					$.validator.addMethod( "creditcard", function(value, element) {
106						//var type  = $.payment.cardType(value);
107						var valid = $.payment.validateCardNumber(value);
108						return this.optional(element) || valid;
109					}, wpforms_settings.val_creditcard);
110					// @todo validate CVC and expiration
111				}
112
113				// Validate method for file extensions
114				$.validator.addMethod( "extension", function(value, element, param) {
115					param = typeof param === "string" ? param.replace( /,/g, "|" ) : "png|jpe?g|gif";
116					return this.optional(element) || value.match( new RegExp( "\\.(" + param + ")$", "i" ) );
117				}, wpforms_settings.val_fileextension );
118
119				// Validate method for file size
120				$.validator.addMethod("maxsize", function(value, element, param) {
121					var maxSize = param,
122						optionalValue = this.optional(element),
123						i, len, file;
124					if (optionalValue) {
125						return optionalValue;
126					}
127					if (element.files && element.files.length) {
128						i = 0;
129						len = element.files.length;
130						for (; i < len; i++) {
131							file = element.files[i];
132							if (file.size > maxSize) {
133								return false;
134							}
135						}
136					}
137					return true;
138				}, wpforms_settings.val_filesize);
139
140				// Validate email addresses
141				$.validator.methods.email = function( value, element ) {
142					return this.optional( element ) || /^[a-z0-9.!#$%&'*+\/=?^_`{|}~-]+@((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}$/i.test( value );
143				};
144
145				// Validate confirmations
146				$.validator.addMethod("confirm", function(value, element, param) {
147					return $.validator.methods.equalTo.call(this, value, element, param);
148				}, wpforms_settings.val_confirm);
149
150				// Validate required payments
151				$.validator.addMethod( "required-payment", function( value, element ) {
152					return WPForms.amountSanitize( value ) > 0;
153				}, wpforms_settings.val_requiredpayment );
154
155				// Validate 12-hour time
156				$.validator.addMethod( "time12h", function( value, element ) {
157					return this.optional( element ) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test( value );
158				}, wpforms_settings.val_time12h );
159
160				// Validate 24-hour time
161				$.validator.addMethod( "time24h", function( value, element ) {
162					return this.optional(element) || /^(([0-1]?[0-9])|([2][0-3])):([0-5]?[0-9])(\ ?[AP]M)?$/i.test(value);
163				}, wpforms_settings.val_time24h );
164
165				// Finally load jQuery Validation library for our forms
166				$('.wpforms-validate').each(function() {
167					var form   = $(this),
168						formID = form.data('formid'),
169						properties;
170
171					// TODO: cleanup this BC with wpforms_validate.
172					if (typeof window['wpforms_'+formID] !== 'undefined' && window['wpforms_'+formID].hasOwnProperty('val
172idate')) {
173						properties = window['wpforms_'+formID].validate;
174					} else if ( typeof wpforms_validate !== 'undefined') {
175						properties = wpforms_validate;
176					} else {
177						properties = {
178							errorClass: 'wpforms-error',
179							validClass: 'wpforms-valid',
180							errorPlacement: function( error, element ) {
181								if ( element.attr( 'type' ) === 'radio' || element.attr( 'type' ) === 'checkbox' ) {
182									if ( element.hasClass( 'wpforms-likert-scale-option' ) ) {
183										if ( element.closest( 'table' ).hasClass( 'single-row' ) ) {
184											element.closest( 'table' ).after( error );
185										} else {
186											element.closest( 'tr' ).find( 'th' ).append( error );
187										}
188									} else if ( element.hasClass( 'wpforms-net-promoter-score-option' ) ) {
189										element.closest( 'table' ).after( error );
190									} else {
191										element.parent().parent().parent().append( error );
192									}
193								} else if ( element.is( 'select' ) && element.attr( 'class' ).match( /date-month|date-day|date-year/ ) ) {
194									if ( element.parent().find( 'label.wpforms-error:visible' ).length === 0 ) {
195										element.parent().find( 'select:last' ).after( error );
196									}
197								} else {
198									error.insertAfter(element);
199								}
200							},
201							highlight: function( element, errorClass, validClass ) {
202								var $element  = $( element ),
203									$field    = $element.closest( '.wpforms-field' ),
204									inputName = $element.attr( 'name' );
205								if ( $element.attr( 'type' ) === 'radio' || $element.attr( 'type' ) === 'checkbox' ) {
206									$field.find( 'input[name=\''+inputName+'\']' ).addClass( errorClass ).removeClass( validClass );
207								} else {
208									$element.addClass( errorClass ).removeClass( validClass );
209								}
210								$field.addClass( 'wpforms-has-error' );
211							},
212							unhighlight: function( element, errorClass, validClass ) {
213								var $element  = $( element ),
214									$field    = $element.closest( '.wpforms-field' ),
215									inputName = $element.attr( 'name' );
216								if ( $element.attr( 'type' ) === 'radio' || $element.attr( 'type' ) === 'checkbox' ) {
217									$field.find( 'input[name=\''+inputName+'\']' ).addClass( validClass ).removeClass( errorClass );
218								} else {
219									$element.addClass( validClass ).removeClass( errorClass );
220								}
221								$field.removeClass( 'wpforms-has-error' );
222							},
223							submitHandler: function(form) {
224
225								var $form   = $(form),
226									$submit = $form.find('.wpforms-submit'),
227									altText = $submit.data('alt-text');
228
229								if ( WPForms.empty( $submit.get(0).recaptchaID ) && $submit.get(0).recaptchaID !== 0 ) {
230									// Normal form.
231									if (altText) {
232										$submit.text(altText).prop('disabled', true);
233									}
234
235									// Remove name attributes if needed.
236									$( '.wpforms-input-temp-name' ).removeAttr('name');
237
238									form.submit();
239
240								} else {
241									// Form contains invisible reCAPTCHA.
242									grecaptcha.execute( $submit.get(0).recaptchaID );
243								}
244							},
245							onkeyup: function( element, event ) {
246								// This code is copied from JQuery Validate 'onkeyup' method with only one change: 'wpforms-novalidate-onkeyup' class check.
247								var excludedKeys = [ 16, 17, 18, 20, 35, 36, 37, 38, 39, 40, 45, 144, 225 ];
248
249								if ( $( element ).hasClass('wpforms-novalidate-onkeyup') ) {
250									return; // Disable onkeyup validation for some elements (e.g. remote calls).
251								}
252
253								if ( event.which === 9 && this.elementValue( element ) === "" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) {
254									return;
255								} else if ( element.name in this.submitted || element.name in this.invalid ) {
256									this.element( element );
257								}
258							},
259							onfocusout: function( element ) {
260								// This code is copied from JQuery Validate 'onfocusout' method with only one change: 'wpforms-novalidate-onkeyup' class check.
261								var validate = false;
262
263								if ( $( element ).hasClass('wpforms-novalidate-onkeyup') && !element.value ) {
264									validate = true; // Empty value error handling for elements with onkeyup validation disabled.
265								}
266
267								if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {
268									validate = true;
269								}
270
271								if ( validate ) {
272									this.element( element );
273								}
274							},
275						}
276					}
277					form.validate( properties );
278				});
279			}
280		},
281
282		/**
283		 * Load jQuery Date Picker.
284		 *
285		 * @since 1.2.3
286		 */
287		loadDatePicker: function() {
288
289			// Only load if jQuery datepicker library exists
290			if (typeof $.fn.flatpickr !== 'undefined') {
291				$('.wpforms-datepicker').each(function() {
292					var element = $(this),
293						form    = element.closest('.wpforms-form'),
294						formID  = form.data('formid'),
295						fieldID = element.closest('.wpforms-field').data('field-id'),
296						properties;
297
298					if (typeof window['wpforms_'+formID+'_'+fieldID] !== 'undefined' && window['wpforms_'+formID+'_'+fieldID].hasOwnProperty('datepicker')) {
299						properties = window['wpforms_'+formID+'_'+fieldID].datepicker;
300					} else if (typeof window['wpforms_'+formID] !== 'undefined' && window['wpforms_'+formID].hasOwnProperty('datepicker')) {
301						properties = window['wpforms_'+formID].datepicker;
302					} else if (typeof wpforms_datepicker !== 'undefined') {
303						properties = wpforms_datepicker;
304					} else {
305						properties = {
306							disableMobile: true
307						};
308					}
309
310					// Redefine locale only if user doesn't do that manually and we have the locale.
311					if (
312						! properties.hasOwnProperty( 'locale' ) &&
313						typeof wpforms_settings !== 'undefined' &&
314						wpforms_settings.hasOwnProperty( 'locale' )
315					) {
316						properties.locale = wpforms_settings.locale;
317					}
318
319					element.flatpickr(properties)
320				});
321			}
322		},
323
324		/**
325		 * Load jQuery Time Picker.
326		 *
327		 * @since 1.2.3
328		 */
329		loadTimePicker: function() {
330
331			// Only load if jQuery timepicker library exists
332			if (typeof $.fn.timepicker !== 'undefined') {
333				$('.wpforms-timepicker').each(function() {
334					var element = $(this),
335						form    = element.closest('.wpforms-form'),
336						formID  = form.data('formid'),
337						fieldID = element.closest('.wpforms-field').data('field-id'),
338						properties;
339
340					if (
341						typeof window['wpforms_'+formID+'_'+fieldID] !== 'undefined' &&
342						window['wpforms_'+formID+'_'+fieldID].hasOwnProperty('timepicker')
343					) {
344						properties = window['wpforms_'+formID+'_'+fieldID].timepicker;
345					} else if (
346						typeof window['wpforms_'+formID] !== 'undefined' &&
347						window['wpforms_'+formID].hasOwnProperty('timepicker')
348					) {
349						properties = window['wpforms_'+formID].timepicker;
350					} else if ( typeof wpforms_timepicker !== 'undefined') {
351						properties = wpforms_timepicker;
352					} else {
353						properties = {
354							scrollDefault: 'now',
355							forceRoundTime: true
356						};
357					}
358
359					element.timepicker(properties);
360				});
361			}
362		},
363
364		/**
365		 * Load jQuery input masks.
366		 *
367		 * @since 1.2.3
368		 */
369		loadInputMask: function() {
370
371			// Only load if jQuery input mask library exists
372			if (typeof $.fn.inputmask !== 'undefined') {
373				$('.wpforms-masked-input').inputmask();
374			}
375		},
376
377		/**
378		 * Payments: Do various payment-related tasks on load.
379		 *
380		 * @since 1.2.6
381		 */
382		loadPayments: function() {
383
384			// Update Total field(s) with latest calculation
385			$('.wpforms-payment-total').each(function(index, el) {
386				WPForms.amountTotal(this);
387			});
388
389			// Credit card validation
390			if(typeof $.fn.payment !== 'undefined') {
391				$('.wpforms-field-credit-card-cardnumber').payment('formatCardNumber');
392				$('.wpforms-field-credit-card-cardcvc').payment('formatCardCVC');
393			}
394		},
395
396		//--------------------------------------------------------------------//
397		// Binds.
398		//--------------------------------------------------------------------//
399
400		/**
401		 * Element bindings.
402		 *
403		 * @since 1.2.3
404		 */
405		bindUIActions: function() {
406
407			// Pagebreak navigation.
408			$(document).on('click', '.wpforms-page-button', function(event) {
409				event.preventDefault();
410				WPForms.pagebreakNav($(this));
411			});
412
413			// Payments: Update Total field(s) when latest calculation.
414			$(document).on('change input', '.wpforms-payment-price', function() {
415				WPForms.amountTotal(this, true);
416			});
417
418			// Payments: Restrict user input payment fields.
419			$(document).on('input', '.wpforms-payment-user-input', function() {
420				var $this = $(this),
421					amount = $this.val();
422				$this.val(amount.replace(/[^0-9.,]/g, ''));
423			});
424
425			// Payments: Sanitize/format user input amounts.
426			$(document).on('focusout', '.wpforms-payment-user-input', function() {
427				var $this     = $(this),
428					amount    = $this.val(),
429					sanitized = WPForms.amountSanitize(amount),
430					formatted = WPForms.amountFormat(sanitized);
431				$this.val(formatted);
432			});
433
434			// Payment radio/checkbox fields: preselect the selected payment (from dynamic/fallback population).
435			$( document ).ready( function () {
436				// Radios.
437				$( '.wpforms-field-radio .wpforms-image-choices-item input:checked' ).change();
438				$( '.wpforms-field-payment-multiple .wpforms-image-choices-item input:checked' ).change();
439				// Checkboxes.
440				$( '.wpforms-field-checkbox .wpforms-image-choices-item input' ).change();
441				$( '.wpforms-field-payment-checkbox .wpforms-image-choices-item input' ).change();
442			} );
443
444			// Rating field: hover effect.
445			$( '.wpforms-field-rating-item' ).hover(
446				function() {
447					$( this ).parent().find( '.wpforms-field-rating-item' ).removeClass( 'selected hover' );
448					$( this ).prevAll().andSelf().addClass( 'hover' );
449				},
450				function() {
451					$( this ).parent().find( '.wpforms-field-rating-item' ).removeClass( 'selected hover' );
452					$( this ).parent().find( 'input:checked' ).parent().prevAll().andSelf().addClass( 'selected' );
453				}
454			);
455
456			// Rating field: toggle selected state.
457			$( document ).on( 'change', '.wpforms-field-rating-item input', function() {
458
459				var $this  = $( this ),
460					$wrap  = $this.closest( '.wpforms-field-rating-items' ),
461					$items = $wrap.find( '.wpforms-field-rating-item' );
462
463				$items.removeClass( 'hover selected' );
464				$this.parent().prevAll().andSelf().addClass( 'selected' );
465			} );
466
467			// Rating field: preselect the selected rating (from dynamic/fallback population).
468			$( document ).ready( function () {
469				$( '.wpforms-field-rating-item input:checked' ).change();
470			} );
471
472			// Checkbox/Radio/Payment checkbox: toggle selected state class.
473			$( document ).on( 'change', '.wpforms-field-checkbox input, .wpforms-field-radio input, .wpforms-field-payment-multiple input, .wpforms-field-payment-checkbox input', function() {
474
475				var $this = $( this );
476
477				switch ( $this.attr( 'type' ) ) {
478					case 'radio':
479						$this.closest( 'ul' ).find( 'li' ).removeClass( 'wpforms-selected' ).find('input[type=radio]').removeAttr( 'checked' );
480						$this
481							.attr( 'checked', 'checked' )
482							.closest( 'li' ).addClass( 'wpforms-selected' );
483						break;
484
485					case 'checkbox':
486						if ( $this.prop( 'checked' ) ) {
487							$this.closest( 'li' ).addClass( 'wpforms-selected' );
488							$this.attr( 'checked', 'checked' );
489						} else {
490							$this.closest( 'li' ).removeClass( 'wpforms-selected' );
491							$this.removeAttr( 'checked' );
492						}
493						break;
494				}
495			} );
496		},
497
498		/**
499		 * Update Pagebreak navigation.
500		 *
501		 * @since 1.2.2
502		 */
503		pagebreakNav: function(el) {
504
505			var $this      = $(el),
506				valid      = true,
507				action     = $this.data('action'),
508				page       = $this.data('page'),
509				page2      = page,
510				next       = page+1,
511				prev       = page-1,
512				formID     = $this.data('formid'),
513				$form      = $this.closest('.wpforms-form'),
514				$page      = $form.find('.wpforms-page-'+page),
515				$submit    = $form.find('.wpforms-submit-container'),
516				$indicator = $form.find('.wpforms-page-indicator'),
517				$reCAPTCHA = $form.find('.wpforms-recaptcha-container'),
518				pageScroll = false;
519
520			// Page scroll
521			// TODO: cleanup this BC with wpform_pageScroll.
522			if ( window.wpforms_pageScroll === false ) {
523				pageScroll = false;
524			} else if ( !WPForms.empty( window.wpform_pageScroll ) ) {
525				pageScroll = window.wpform_pageScroll;
526			} else {
527				pageScroll = 75;
528			}
529
530			// Toggling between pages
531			if ( action === 'next' ){
532				// Validate
533				if (typeof $.fn.validate !== 'undefined') {
534					$page.find('input.wpforms-field-required, select.wpforms-field-required, textarea.wpforms-field-required, .wpforms-field-required input, .wpforms-field-file-upload input').each(function(index, el) {
535						if ( ! $(el).valid() ) {
536							valid = false;
537						}
538					});
539					// Scroll to first/top error on page
540					var $topError = $page.find('.wpforms-error').first();
541					if ($topError.length) {
542						$('html, body').animate({
543							scrollTop: $topError.offset().top-75
544						}, 750, function() {
545							$topError.focus();
546						});
547					}
548				}
549				// Move to next page
550				if (valid) {
551					page2 = next;
552					$page.hide();
553					var $nextPage = $form.find('.wpforms-page-'+next);
554					$nextPage.show();
555					if ( $nextPage.hasClass('last') ) {
556						$reCAPTCHA.show();
557						$submit.show();
558					}
559					if ( pageScroll ) {
560						// Scroll to top of the form
561						$('html, body').animate({
562							scrollTop: $form.offset().top-pageScroll
563						}, 1000);
564					}
565					$this.trigger('wpformsPageChange', [ page2, $form ] );
566				}
567			} else if ( action === 'prev' ) {
568				// Move to prev page
569				page2 = prev;
570				$page.hide();
571				$form.find('.wpforms-page-'+prev).show();
572				$reCAPTCHA.hide();
573				$submit.hide();
574				if ( pageScroll ) {
575					// Scroll to top of the form
576					$('html, body').animate({
577						scrollTop: $form.offset().top-pageScroll
578					}, 1000);
579				}
580				$this.trigger('wpformsPageChange', [ page2, $form ] );
581			}
582
583			if ( $indicator ) {
584				var theme = $indicator.data('indicator'),
585					color = $indicator.data('indicator-color');
586				if ('connector' === theme || 'circles' === theme) {
587					$indicator.find('.wpforms-page-indicator-page').removeClass('active');
588					$indicator.find('.wpforms-page-indicator-page-'+page2).addClass('active');
589					$indicator.find('.wpforms-page-indicator-page-number').removeAttr('style');
590					$indicator.find('.active .wpforms-page-indicator-page-number').css('background-color', color);
591					if ( 'connector' === theme) {
592						$indicator.find('.wpforms-page-indicator-page-triangle').removeAttr('style');
593						$indicator.find('.active .wpforms-page-indicator-page-triangle').css('border-top-color', color);
594					}
595				} else if ('progress' === theme) {
596					var $pageTitle = $indicator.find('.wpforms-page-indicator-page-title'),
597						$pageSep   = $indicator.find('.wpforms-page-indicator-page-title-sep'),
598						totalPages = $form.find('.wpforms-page').length,
599						width = (page2/totalPages)*100;
600					$indicator.find('.wpforms-page-indicator-page-progress').css('width', width+'%');
601					$indicator.find('.wpforms-page-indicator-steps-current').text(page2);
602					if ($pageTitle.data('page-'+page2+'-title')) {
603						$pageTitle.css('display','inline').text($pageTitle.data('page-'+page2+'-title'));
604						$pageSep.css('display','inline');
605					} else {
606						$pageTitle.css('display','none');
607						$pageSep.css('display','none');
608					}
609				}
610			}
611		},
612
613		/**
614		 * OptinMonster compatibility.
615		 *
616		 * Re-initialize after OptinMonster loads to accomodate changes that
617		 * have occurred to the DOM.
618		 *
619		 * @since 1.5.0
620		 */
621		bindOptinMonster: function() {
622
623			// OM v5.
624			document.addEventListener( 'om.Campaign.load', function( event ) {
625				WPForms.ready();
626				WPForms.optinMonsterRecaptchaReset( event.detail.Campaign.data.id );
627			} );
628
629			// OM Legacy.
630			$( document ).on( 'OptinMonsterOnShow', function( event, data, object ) {
631				WPForms.ready();
632				WPForms.optinMonsterRecaptchaReset( data.optin );
633			} );
634		},
635
636		/**
637		 * Reset/recreate reCAPTCHA v2 inside OptinMonster.
638		 *
639		 * @since 1.5.0
640		 */
641		optinMonsterRecaptchaReset: function ( optinId ) {
642
643			var $form               = $( '#om-' + optinId ).find( '.wpforms-form' ),
644				$recaptchaContainer = $form.find( '.wpforms-recaptcha-container' ),
645				$recaptcha          = $form.find( '.g-recaptcha' ),
646				recaptchaSiteKey    = $recaptcha.attr( 'data-sitekey' ),
647				recaptchaID         = 'recaptcha-' + Date.now();
648
649			if ( $form.length && $recaptcha.length ) {
650
651				$recaptcha.remove();
652				$recaptchaContainer.prepend( '<div class="g-recaptcha" id="' + recaptchaID + '" data-sitekey="' + recaptchaSiteKey + '"></div>' );
653
654				grecaptcha.render(
655					recaptchaID,
656					{
657						sitekey: recaptchaSiteKey,
658						callback: function(){
659							wpformsRecaptchaCallback( $( '#' + recaptchaID ) );
660						}
661					}
662				);
663			}
664		},
665
666		//--------------------------------------------------------------------//
667		// Other functions.
668		//--------------------------------------------------------------------//
669
670		/**
671		 * Payments: Calculate total.
672		 *
673		 * @since 1.2.3
674		 * @since 1.5.1 Added support for payment-checkbox field.
675		 */
676		amountTotal: function ( el, validate ) {
677
678			var validate = validate || false,
679				$form = $( el ).closest( '.wpforms-form' ),
680				total = 0,
681				totalFormatted = 0,
682				totalFormattedSymbol = 0,
683				currency = WPForms.getCurrency();
684
685			$( '.wpforms-payment-price', $form ).each( function ( index, el ) {
686
687				var amount = 0,
688					$this = $( this );
689
690				if ( $this.attr( 'type' ) === 'text' || $this.attr( 'type' ) === 'hidden' ) {
691					amount = $this.val();
692				}
693				else if ( ( $this.attr( 'type' ) === 'radio' || $this.attr( 'type' ) === 'checkbox' ) && $this.is( ':checked' ) ) {
694					amount = $this.data( 'amount' );
695				}
696				else if ( $this.is( 'select' ) && $this.find( 'option:selected' ).length > 0 ) {
697					amount = $this.find( 'option:selected' ).data( 'amount' );
698				}
699				if ( ! WPForms.empty( amount ) ) {
700					amount = WPForms.amountSanitize( amount );
701					total = Number( total ) + Number( amount );
702				}
703			} );
704
705			totalFormatted = WPForms.amountFormat( total );
706
707			if ( 'left' === currency.symbol_pos ) {
708				totalFormattedSymbol = currency.symbol + ' ' + totalFormatted;
709			}
710			else {
711				totalFormattedSymbol = totalFormatted + ' ' + currency.symbol;
712			}
713
714			$form.find( '.wpforms-payment-total' ).each( function ( index, el ) {
715				if ( 'hidden' === $( this ).attr( 'type' ) || 'text' === $( this ).attr( 'type' ) ) {
716					$( this ).val( totalFormattedSymbol );
717					if ( 'text' === $( this ).attr( 'type' ) && validate && $form.data( 'validator' ) ) {
718						$( this ).valid();
719					}
720				} else {
721					$( this ).text( totalFormattedSymbol );
722				}
723			} );
724		},
725
726		/**
727		 * Sanitize amount and convert to standard format for calculations.
728		 *
729		 * @since 1.2.6
730		 */
731		amountSanitize: function(amount) {
732
733			var currency = WPForms.getCurrency();
734
735			amount = amount.toString().replace(/[^0-9.,]/g,'');
736
737			if ( currency.decimal_sep === ',' && ( amount.indexOf(currency.decimal_sep) !== -1 ) ) {
738				if ( currency.thousands_sep === '.' && amount.indexOf(currency.thousands_sep) !== -1 ) {
739					amount = amount.replace(currency.thousands_sep,'');
740				} else if( currency.thousands_sep === '' && amount.indexOf('.') !== -1 ) {
741					amount = amount.replace('.','');
742				}
743				amount = amount.replace(currency.decimal_sep,'.');
744			} else if ( currency.thousands_sep === ',' && ( amount.indexOf(currency.thousands_sep) !== -1 ) ) {
745				amount = amount.replace(currency.thousands_sep,'');
746			}
747
748			return WPForms.numberFormat( amount, 2, '.', '' );
749		},
750
751		/**
752		 * Format amount.
753		 *
754		 * @since 1.2.6
755		 */
756		amountFormat: function(amount) {
757
758			var currency = WPForms.getCurrency();
759
760			amount = String(amount);
761
762			// Format the amount
763			if ( currency.decimal_sep === ',' && ( amount.indexOf(currency.decimal_sep) !== -1 ) ) {
764				var sepFound = amount.indexOf(currency.decimal_sep),
765					whole    = amount.substr(0, sepFound),
766					part     = amount.substr(sepFound+1, amount.strlen-1);
767				amount = whole + '.' + part;
768			}
769
770			// Strip , from the amount (if set as the thousands separator)
771			if ( currency.thousands_sep === ',' && ( amount.indexOf(currency.thousands_sep) !== -1 ) ) {
772				amount = amount.replace(',','');
773			}
774
775			if ( WPForms.empty( amount ) ) {
776				amount = 0;
777			}
778
779			return WPForms.numberFormat( amount, 2, currency.decimal_sep, currency.thousands_sep );
780		},
781
782		/**
783		 * Get site currency settings.
784		 *
785		 * @since 1.2.6
786		 */
787		getCurrency: function() {
788
789			var currency = {
790				code: 'USD',
791				thousands_sep: ',',
792				decimal_sep: '.',
793				symbol: '$',
794				symbol_pos: 'left'
795			};
796
797			// Backwards compatibility.
798			if ( typeof wpforms_settings.currency_code !== 'undefined' ) {
799				currency.code = wpforms_settings.currency_code;
800			}
801			if ( typeof wpforms_settings.currency_thousands !== 'undefined' ) {
802				currency.thousands_sep = wpforms_settings.currency_thousands;
803			}
804			if ( typeof wpforms_settings.currency_decimal !== 'undefined' ) {
805				currency.decimal_sep = wpforms_settings.currency_decimal;
806			}
807			if ( typeof wpforms_settings.currency_symbol !== 'undefined' ) {
808				currency.symbol = wpforms_settings.currency_symbol;
809			}
810			if ( typeof wpforms_settings.currency_symbol_pos !== 'undefined' ) {
811				currency.symbol_pos = wpforms_settings.currency_symbol_pos;
812			}
813
814			return currency;
815		},
816
817		/**
818		 * Format number.
819		 *
820		 * @link http://locutus.io/php/number_format/
821		 * @since 1.2.6
822		 */
823		numberFormat: function (number, decimals, decimalSep, thousandsSep) {
824
825			number = (number + '').replace(/[^0-9+\-Ee.]/g, '');
826			var n = !isFinite(+number) ? 0 : +number;
827			var prec = !isFinite(+decimals) ? 0 : Math.abs(decimals);
828			var sep = (typeof thousandsSep === 'undefined') ? ',' : thousandsSep;
829			var dec = (typeof decimalSep === 'undefined') ? '.' : decimalSep;
830			var s;
831
832			var toFixedFix = function (n, prec) {
833				var k = Math.pow(10, prec);
834				return '' + (Math.round(n * k) / k).toFixed(prec)
835			};
836
837			// @todo: for IE parseFloat(0.55).toFixed(0) = 0;
838			s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
839			if (s[0].length > 3) {
840				s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep)
841			}
842			if ((s[1] || '').length < prec) {
843				s[1] = s[1] || '';
844				s[1] += new Array(prec - s[1].length + 1).join('0')
845			}
846
847			return s.join(dec)
848		},
849
850		/**
851		 * Empty check similar to PHP.
852		 *
853		 * @link http://locutus.io/php/empty/
854		 * @since 1.2.6
855		 */
856		empty: function(mixedVar) {
857
858			var undef;
859			var key;
860			var i;
861			var len;
862			var emptyValues = [undef, null, false, 0, '', '0'];
863
864			for (i = 0, len = emptyValues.length; i < len; i++) {
865				if (mixedVar === emptyValues[i]) {
866					return true
867				}
868			}
869
870			if (typeof mixedVar === 'object') {
871				for (key in mixedVar) {
872					if (mixedVar.hasOwnProperty(key)) {
873						return false;
874					}
875				}
876				return true;
877			}
878
879			return false;
880		},
881
882		/**
883		 * Set cookie container user UUID.
884		 *
885		 * @since 1.3.3
886		 */
887		setUserIndentifier: function() {
888
889			if ( ( ( ! window.hasRequiredConsent && typeof wpforms_settings !== 'undefined' && wpforms_settings.uuid_cookie ) || ( window.hasRequiredConsent && window.hasRequiredConsent() ) ) && ! WPForms.getCookie( '_wpfuuid' ) ) {
890
891				// Generate UUID - http://stackoverflow.com/a/873856/1489528
892				var s         = new Array(36),
893					hexDigits = '0123456789abcdef',
894					uuid;
895
896				for (var i = 0; i < 36; i++) {
897					s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
898				}
899				s[14] = "4";
900				s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
901				s[8]  = s[13] = s[18] = s[23] = '-';
902
903				uuid = s.join("");
904
905				WPForms.createCookie('_wpfuuid', uuid, 3999);
906			}
907		},
908
909		/**
910		 * Create cookie.
911		 *
912		 * @since 1.3.3
913		 */
914		createCookie: function(name, value, days) {
915
916			var expires = '';
917
918			// If we have a days value, set it in the expiry of the cookie.
919			if ( days ) {
920				// If -1 is our value, set a session based cookie instead of a persistent cookie.
921				if ( '-1' === days ) {
922					expires = '';
923				} else {
924					var date = new Date();
925					date.setTime(date.getTime() + (days*24*60*60*1000));
926					expires = '; expires=' + date.toGMTString();
927				}
928			} else {
929				expires = '; expires=Thu, 01 Jan 1970 00:00:01 GMT';
930			}
931
932			// Write the cookie.
933			document.cookie = name + '=' + value + expires + '; path=/';
934		},
935
936		/**
937		 * Retrieve cookie.
938		 *
939		 * @since 1.3.3
940		 */
941		getCookie: function(name) {
942
943			var nameEQ = name + '=',
944				ca     = document.cookie.split(';');
945
946			for ( var i = 0; i < ca.length; i++ ) {
947				var c = ca[i];
948				while ( c.charAt(0) === ' ' ) {
949					c = c.substring(1, c.length);
950				}
951				if ( c.indexOf(nameEQ) == 0 ) {
952					return c.substring(nameEQ.length, c.length);
953				}
954			}
955
956			return null;
957		},
958
959		/**
960		 * Delete cookie.
961		 */
962		removeCookie: function(name) {
963
964			WPForms.createCookie(name, '',-1);
965		}
966	};
967
968	// Initialize.
969	WPForms.init();
970
971	// Add to global scope.
972	window.wpforms = WPForms;
973
974})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.