: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
/* global wpforms_settings, grecaptcha, hcaptcha, turnstile, wpformsRecaptchaCallback, wpformsRecaptchaV3Execute, wpforms_validate, wpforms_datepicker, wpforms_timepicker, Mailcheck, Choices, WPFormsPasswordField, WPFormsEntryPreview, punycode, tinyMCE, WPFormsUtils, JQueryDeferred, JQueryXHR */
/* eslint-disable no-unused-expressions, no-shadow, no-unused-vars */
// noinspection ES6ConvertVarToLetConst
var wpforms = window.wpforms || ( function( document, window, $ ) { // eslint-disable-line no-var
* Public functions and properties.
* Is updating token via ajax flag.
$( window ).on( 'load', function() {
// In the case of jQuery 3.+, we need to wait for a ready event first.
if ( typeof $.ready.then === 'function' ) {
$.ready.then( app.load );
// Clear URL - remove wpforms_form_id.
app.loadSmartPhoneField();
app.restoreSubmitButtonOnEventPersisted();
app.bindSmartPhoneField();
$( '.wpforms-randomize' ).each( function() {
$listItems = $list.children();
while ( $listItems.length ) {
$list.append( $listItems.splice( Math.floor( Math.random() * $listItems.length ), 1 )[ 0 ] );
// Unlock pagebreak navigation.
$( '.wpforms-page-button' ).prop( 'disabled', false );
$( document ).trigger( 'wpformsReady' );
$( '.wpforms-smart-phone-field' ).each( function() {
const $field = $( this );
app.fixPhoneFieldSnippets( $field );
//--------------------------------------------------------------------//
//--------------------------------------------------------------------//
* Remove wpforms_form_id from URL.
const loc = window.location;
if ( query.indexOf( 'wpforms_form_id=' ) !== -1 ) {
query = query.replace( /([&?]wpforms_form_id=[0-9]*$|wpforms_form_id=[0-9]*&|[?&]wpforms_form_id=[0-9]*(?=#))/, '' );
history.replaceState( {}, null, loc.origin + loc.pathname + query );
* Load jQuery Validation.
loadValidation() { // eslint-disable-line max-lines-per-function
// Only load if jQuery validation library exists.
if ( typeof $.fn.validate !== 'undefined' ) {
// jQuery Validation library will not correctly validate
// fields that do not have a name attribute, so we use the
// `wpforms-input-temp-name` class to add a temporary name
// attribute before validation is initialized, then remove it
// before the form submits.
$( '.wpforms-input-temp-name' ).each( function( index, el ) {
const random = Math.floor( Math.random() * 9999 ) + 1;
$( this ).attr( 'name', 'wpf-temp-' + random );
// Prepend URL field contents with https:// if user input doesn't contain a schema.
$( document ).on( 'change', '.wpforms-validate input[type=url]', function() {
const url = $( this ).val();
if ( url.substr( 0, 7 ) !== 'http://' && url.substr( 0, 8 ) !== 'https://' ) {
$( this ).val( 'https://' + url );
$.validator.messages.required = wpforms_settings.val_required;
$.validator.messages.url = wpforms_settings.val_url;
$.validator.messages.email = wpforms_settings.val_email;
$.validator.messages.number = wpforms_settings.val_number;
// Payments: Validate method for Credit Card Number.
if ( typeof $.fn.payment !== 'undefined' ) {
$.validator.addMethod( 'creditcard', function( value, element ) {
//var type = $.payment.cardType(value);
const valid = $.payment.validateCardNumber( value );
return this.optional( element ) || valid;
}, wpforms_settings.val_creditcard );
// @todo validate CVC and expiration
// Validate method for file extensions.
$.validator.addMethod( 'extension', function( value, element, param ) {
param = 'string' === typeof param ? param.replace( /,/g, '|' ) : 'png|jpe?g|gif';
return this.optional( element ) || value.match( new RegExp( '\\.(' + param + ')$', 'i' ) );
}, wpforms_settings.val_fileextension );
// Validate method for file size.
$.validator.addMethod( 'maxsize', function( value, element, param ) {
optionalValue = this.optional( element );
if ( element.files && element.files.length ) {
len = element.files.length;
file = element.files[ i ];
if ( file.size > maxSize ) {
}, wpforms_settings.val_filesize );
$.validator.addMethod( 'step', function( value, element, param ) {
const decimalPlaces = function( num ) {
if ( Math.floor( num ) === num ) {
return num.toString().split( '.' )[ 1 ].length || 0;
const decimals = decimalPlaces( param );
const decimalToInt = function( num ) {
return Math.round( num * Math.pow( 10, decimals ) );
const min = decimalToInt( $( element ).attr( 'min' ) );
value = decimalToInt( value ) - min;
return this.optional( element ) || decimalToInt( value ) % decimalToInt( param ) === 0;
// Validate email addresses.
$.validator.methods.email = function( value, element ) {
* This function combines is_email() from WordPress core
* and wpforms_is_email() to validate email addresses.
* @see https://developer.wordpress.org/reference/functions/is_email/
* @see https://github.com/awesomemotive/wpforms-plugin/blob/develop/wpforms/includes/functions/checks.php#L45
* @param {string} value The email address to validate.
* @return {boolean} True if the email address is valid, false otherwise.
const isEmail = function( value ) { // eslint-disable-line complexity
if ( typeof value !== 'string' ) {
// Do not allow callables, arrays, and objects.
// Check the length and position of the @ character.
const atIndex = value.indexOf( '@', 1 );
if ( value.length < 6 || value.length > 254 || atIndex === -1 ) {
// Check for more than one "@" symbol.
if ( value.indexOf( '@', atIndex + 1 ) !== -1 ) {
// Split email address into local and domain parts.
const [ local, domain ] = value.split( '@' );
// Check local and domain parts for existence.
if ( ! local || ! domain ) {
// Check local part for invalid characters and length.
const localRegex = /^[a-zA-Z0-9!#$%&'*+/=?^_`{|}~.-]+$/;
if ( ! localRegex.test( local ) || local.length > 63 ) {
// Check domain part for sequences of periods, leading and trailing periods, and whitespace.
const domainRegex = /\.{2,}/;
if ( domainRegex.test( domain ) || domain.trim( ' \t\n\r\0\x0B.' ) !== domain ) {
// Check domain part for length.
const domainArr = domain.split( '.' );
if ( domainArr.length < 2 ) {
// Check domain label for length, leading and trailing periods, and whitespace.
const domainLabelRegex = /^[a-z0-9-]+$/i;
for ( const domainLabel of domainArr ) {
domainLabel.length > 63 ||
domainLabel.trim( ' \t\n\r\0\x0B-' ) !== domainLabel ||
! domainLabelRegex.test( domainLabel )
// Congratulations! The email address is valid.
return this.optional( element ) || isEmail( value );
// Validate email by allowlist/blocklist.
$.validator.addMethod( 'restricted-email', function( value, element ) {
const $el = $( element );
if ( ! $el.val().length ) {
const $form = $el.closest( '.wpforms-form' ),
formId = $form.data( 'formid' );
! Object.prototype.hasOwnProperty.call( app.cache, formId ) ||
! Object.prototype.hasOwnProperty.call( app.cache[ formId ], 'restrictedEmailValidation' ) ||
! Object.prototype.hasOwnProperty.call( app.cache[ formId ].restrictedEmailValidation, value )
app.restrictedEmailRequest( element, value );
return app.cache[ formId ].restrictedEmailValidation[ value ];
}, wpforms_settings.val_email_restricted );
// Validate confirmations.
$.validator.addMethod( 'confirm', function( value, element, param ) {
const field = $( element ).closest( '.wpforms-field' );
return $( field.find( 'input' )[ 0 ] ).val() === $( field.find( 'input' )[ 1 ] ).val();
}, wpforms_settings.val_confirm );
// Validate required payments.
$.validator.addMethod( 'required-payment', function( value, element ) {
return app.amountSanitize( value ) > 0;
}, wpforms_settings.val_requiredpayment );
// Validate 12-hour time.
$.validator.addMethod( 'time12h', function( value, element ) {
// noinspection RegExpRedundantEscape
return this.optional( element ) || /^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test( value ); // eslint-disable-line no-useless-escape
}, wpforms_settings.val_time12h );
// Validate 24-hour time.
$.validator.addMethod( 'time24h', function( value, element ) {
// noinspection RegExpRedundantEscape
return this.optional( element ) || /^(([0-1]?[0-9])|([2][0-3])):([0-5]?[0-9])(\ ?[AP]M)?$/i.test( value ); // eslint-disable-line no-useless-escape
}, wpforms_settings.val_time24h );
// Validate Turnstile captcha.
$.validator.addMethod( 'turnstile', function( value ) {
}, wpforms_settings.val_turnstile_fail_msg );
$.validator.addMethod( 'time-limit', function( value, element ) { // eslint-disable-line complexity
const $input = $( element ),
minTime = $input.data( 'min-time' ),
isLimited = typeof minTime !== 'undefined';
const isRequired = $input.prop( 'required' );
if ( ! isRequired && app.empty( value ) ) {
const maxTime = $input.data( 'max-time' );
if ( app.compareTimesGreaterThan( maxTime, minTime ) ) {
return app.compareTimesGreaterThan( value, minTime ) && app.compareTimesGreaterThan( maxTime, value );
return ( app.compareTimesGreaterThan( value, minTime ) && app.compareTimesGreaterThan( value, maxTime ) ) ||
( app.compareTimesGreaterThan( minTime, value ) && app.compareTimesGreaterThan( maxTime, value ) );
}, function( params, element ) {
const $input = $( element );
let minTime = $input.data( 'min-time' ),
maxTime = $input.data( 'max-time' );
// Replace `00:**pm` with `12:**pm`.
minTime = minTime.replace( /^00:([0-9]{2})pm$/, '12:$1pm' );
maxTime = maxTime.replace( /^00:([0-9]{2})pm$/, '12:$1pm' );
// Proper format time: add space before AM/PM, make uppercase.
minTime = minTime.replace( /(am|pm)/g, ' $1' ).toUpperCase();
maxTime = maxTime.replace( /(am|pm)/g, ' $1' ).toUpperCase();
return wpforms_settings.val_time_limit
.replace( '{minTime}', minTime )
.replace( '{maxTime}', maxTime );
// Validate checkbox choice limit.
$.validator.addMethod( 'check-limit', function( value, element ) {
const $ul = $( element ).closest( 'ul' ),
choiceLimit = parseInt( $ul.attr( 'data-choice-limit' ) || 0, 10 );
if ( 0 === choiceLimit ) {
const $checked = $ul.find( 'input[type="checkbox"]:checked' );
return $checked.length <= choiceLimit;
}, function( params, element ) {
const choiceLimit = parseInt( $( element ).closest( 'ul' ).attr( 'data-choice-limit' ) || 0, 10 );
return wpforms_settings.val_checklimit.replace( '{#}', choiceLimit );
// Validate Smartphone Field.
if ( typeof $.fn.intlTelInput !== 'undefined' ) {
$.validator.addMethod( 'smart-phone-field', function( value, element ) {
if ( value.match( /[^\d()\-+\s]/ ) ) {
return this.optional( element ) || $( element ).intlTelInput( 'isValidNumber' );
}, wpforms_settings.val_phone );
// Validate Inputmask completeness.
$.validator.addMethod( 'inputmask-incomplete', function( value, element ) {
if ( value.length === 0 || typeof $.fn.inputmask === 'undefined' ) {
return $( element ).inputmask( 'isComplete' );
}, wpforms_settings.val_inputmask_incomplete );
// Validate Payment item value on zero.
$.validator.addMethod( 'required-positive-number', function( value, element ) {
return app.amountSanitize( value ) > 0;
}, wpforms_settings.val_number_positive );
* Validate Payment item minimum price value.
$.validator.addMethod( 'required-minimum-price', function( value, element, param ) {
const $el = $( element );
* The validation is passed in the following cases:
* 1) if a field is not filled in and not required.
* 2) if the minimum required price is equal to or less than the typed value.
* Note: since the param is returned in decimal format at all times, we need to format the value to compare it.
return ( value === '' && ! $el.hasClass( 'wpforms-field-required' ) ) || Number( app.amountSanitize( app.amountFormat( param ) ) ) <= Number( app.amountSanitize( value ) );
}, wpforms_settings.val_minimum_price );
// Validate US Phone Field.
$.validator.addMethod( 'us-phone-field', function( value, element ) {
if ( value.match( /[^\d()\-+\s]/ ) ) {
return this.optional( element ) || value.replace( /[^\d]/g, '' ).length === 10;
}, wpforms_settings.val_phone );
// Validate International Phone Field.
$.validator.addMethod( 'int-phone-field', function( value, element ) {
if ( value.match( /[^\d()\-+\s]/ ) ) {
return this.optional( element ) || value.replace( /[^\d]/g, '' ).length > 0;
}, wpforms_settings.val_phone );
// Validate password strength.
$.validator.addMethod( 'password-strength', function( value, element ) {
const $el = $( element );
return WPFormsPasswordField.passwordStrength( value, element ) >= Number( $el.data( 'password-strength-level' ) );
}, wpforms_settings.val_password_strength );
// Finally, load jQuery Validation library for our forms.
$( '.wpforms-validate' ).each( function() { // eslint-disable-line max-lines-per-function
formID = form.data( 'formid' );
// TODO: cleanup this BC with wpforms_validate.
if ( typeof window[ 'wpforms_' + formID ] !== 'undefined' && window[ 'wpforms_' + formID ].hasOwnProperty( 'validate' ) ) {
properties = window[ 'wpforms_' + formID ].validate;
} else if ( typeof wpforms_validate !== 'undefined' ) {
properties = wpforms_validate;
errorElement: app.isModernMarkupEnabled() ? 'em' : 'label',
errorClass: 'wpforms-error',
validClass: 'wpforms-valid',
ignore: ':hidden:not(textarea.wp-editor-area), .wpforms-conditional-hide textarea.wp-editor-area',
errorPlacement( error, element ) { // eslint-disable-line complexity
if ( app.isLikertScaleField( element ) ) {
element.closest( 'table' ).hasClass( 'single-row' )
? element.closest( '.wpforms-field' ).append( error )
: element.closest( 'tr' ).find( 'th' ).append( error );
} else if ( app.isWrappedField( element ) ) {
element.closest( '.wpforms-field' ).append( error );
} else if ( app.isDateTimeField( element ) ) {