: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if ( wpforms_builder.currency_decimal === ',' && ( amount.indexOf( wpforms_builder.currency_decimal ) !== -1 ) ) {
const sepFound = amount.indexOf( wpforms_builder.currency_decimal );
amount = amount.substr( 0, sepFound ) + '.' + amount.substr( sepFound + 1, amount.length - 1 );
// Strip "," from the amount (if set as the thousand separators)
if ( wpforms_builder.currency_thousands === ',' && ( amount.indexOf( wpforms_builder.currency_thousands ) !== -1 ) ) {
amount = amount.replace( /,/g, '' );
if ( wpf.empty( amount ) ) {
return wpf.numberFormat( amount, wpforms_builder.currency_decimals, wpforms_builder.currency_decimal, wpforms_builder.currency_thousands );
* Format amount with currency symbol.
* @param {string} amount Amount to format.
* @return {string} Formatted amount (for instance $ 128.00).
amountFormatCurrency( amount ) {
const sanitized = wpf.amountSanitize( amount ),
formatted = wpf.amountFormat( sanitized );
if ( wpforms_builder.currency_symbol_pos === 'right' ) {
result = formatted + ' ' + wpforms_builder.currency_symbol;
result = wpforms_builder.currency_symbol + formatted;
* @see http://locutus.io/php/number_format/
* @param {string} number Number to format.
* @param {number} decimals How many decimals should be there.
* @param {string} decimalSep What is the decimal separator.
* @param {string} thousandsSep What is the thousand separator.
* @return {string} Formatted number.
numberFormat( number, decimals, decimalSep, thousandsSep ) { // eslint-disable-line complexity
number = ( number + '' ).replace( /[^0-9+\-Ee.]/g, '' );
const n = ! isFinite( +number ) ? 0 : +number;
const precision = ! isFinite( +decimals ) ? 0 : Math.abs( decimals );
const sep = ( typeof thousandsSep === 'undefined' ) ? ',' : thousandsSep;
const dec = ( typeof decimalSep === 'undefined' ) ? '.' : decimalSep;
const toFixedFix = function( fixedN, fixedPrecision ) {
const k = Math.pow( 10, fixedPrecision );
return '' + ( Math.round( fixedN * k ) / k ).toFixed( fixedPrecision );
// @todo: for IE parseFloat(0.55).toFixed(0) = 0;
s = ( precision ? toFixedFix( n, precision ) : '' + Math.round( n ) ).split( '.' );
if ( s[ 0 ].length > 3 ) {
s[ 0 ] = s[ 0 ].replace( /\B(?=(?:\d{3})+(?!\d))/g, sep );
if ( ( s[ 1 ] || '' ).length < precision ) {
s[ 1 ] += new Array( precision - s[ 1 ].length + 1 ).join( '0' );
* Empty check similar to PHP.
* {@link http://locutus.io/php/empty}.
* @param {any} mixedVar A variable to check.
* @return {boolean} True if the variable is empty.
const emptyValues = [ undef, null, false, 0, '', '0' ];
for ( i = 0, len = emptyValues.length; i < len; i++ ) {
if ( mixedVar === emptyValues[ i ] ) {
if ( typeof mixedVar === 'object' ) {
for ( key in mixedVar ) {
if ( mixedVar.hasOwnProperty( key ) ) {
* @param {string|number|boolean|Array|Object} msg Debug message (any data).
// eslint-disable-next-line no-console
console.log( '%cWPForms Debug: ', 'color: #cd6622;', ...msg );
* @return {boolean} True if debug mode is enabled.
return ( ( window.location.hash && '#wpformsdebug' === window.location.hash ) || wpforms_builder.debug );
* Focus the input/textarea and put the caret at the end of the text.
* @param {jQuery} el Element.
const $thisVal = el.val();
el.val( '' ).val( $thisVal );
* Creates a object from form elements.
* @param {jQuery|string} el Element.
* @return {Object} Object.
formObject( el ) { // eslint-disable-line max-lines-per-function, complexity
const form = jQuery( el ),
fields = form.find( '[name]' ),
/* eslint-disable max-depth */
for ( let v = 0; v < fields.length; v++ ) {
const field = jQuery( fields[ v ] ),
name = field.prop( 'name' ).replace( /\]/gi, '' ).split( '[' );
if ( ( field.is( ':radio' ) || field.is( ':checkbox' ) ) && ! field.is( ':checked' ) ) {
for ( let i = name.length - 1; i >= 0; i-- ) {
let nestName = name[ i ];
if ( typeof nestName === 'undefined' ) {
if ( nestName.length === 0 ) {
if ( typeof arrayNames[ name[ i - 1 ] ] === 'undefined' ) {
arrayNames[ name[ i - 1 ] ] = 0;
arrayNames[ name[ i - 1 ] ] += 1;
nestName = arrayNames[ name[ i - 1 ] ];
if ( i === name.length - 1 ) {
if ( value === 'true' ) {
} else if ( value === 'false' ) {
} else if ( ! isNaN( parseFloat( value ) ) && parseFloat( value ).toString() === value ) {
value = parseFloat( value );
} else if ( typeof value === 'string' && ( value.substr( 0, 1 ) === '{' || value.substr( 0, 1 ) === '[' ) ) {
value = JSON.parse( value );
} else if ( typeof value === 'object' && value.length && field.is( 'select' ) ) {
for ( let j = 0; j < value.length; j++ ) {
newValue[ 'n' + j ] = value[ j ];
lineConf[ nestName ] = value;
lineConf[ nestName ] = newObj;
jQuery.extend( true, json, lineConf );
/* eslint-enable max-depth */
* Initialize WPForms admin area tooltips.
if ( typeof jQuery.fn.tooltipster === 'undefined' ) {
const isRTL = jQuery( 'body' ).hasClass( 'rtl' );
jQuery( '.wpforms-help-tooltip' ).tooltipster( {
position: isRTL ? 'left' : 'right',
* Restore WPForms admin area tooltip's title.
* @param {jQuery|undefined} $scope Searching scope.
restoreTooltips( $scope ) {
$scope = typeof $scope !== 'undefined' && $scope && $scope.length > 0 ? $scope.find( '.wpforms-help-tooltip' ) : jQuery( '.wpforms-help-tooltip' );
$scope.each( function() {
const $this = jQuery( this );
if ( jQuery.tooltipster.instances( this ).length !== 0 ) {
$this.attr( 'title', $this.tooltipster( 'content' ) );
* source: `https://github.com/segmentio/is-url/blob/master/index.js`
* @param {string} url URL for checking.
* @return {boolean} True if `url` is a valid URL.
// noinspection RegExpUnnecessaryNonCapturingGroup
* A URL must match #1 and then at least one of #2/#3.
* Use two levels of REs to avoid REDOS.
const protocolAndDomainRE = /^(?:http(?:s?):)?\/\/(\S+)/;
/* eslint-disable no-useless-escape */
// noinspection RegExpRedundantEscape
const localhostDomainRE = /^localhost[\:?\d]*(?:[^\:?\d]\S*)?$/;
// noinspection RegExpRedundantEscape
const nonLocalhostDomainRE = /^[^\s\.]+\.\S{2,}$/;
/* eslint-enable no-useless-escape */
if ( typeof url !== 'string' ) {
const match = url.match( protocolAndDomainRE );
const everythingAfterProtocol = match[ 1 ];
if ( ! everythingAfterProtocol ) {
return localhostDomainRE.test( everythingAfterProtocol ) || nonLocalhostDomainRE.test( everythingAfterProtocol );
* Uses: `https://github.com/cure53/DOMPurify`
* @since 1.7.8 Introduced optional allowed parameter.
* @param {string|undefined} string HTML to sanitize.
* @param {Array|undefined} allowed Array of allowed HTML tags.
* @return {string} Sanitized HTML.
sanitizeHTML( string = undefined, allowed = undefined ) {
const purify = window.DOMPurify;
if ( typeof purify === 'undefined' || typeof string === 'undefined' ) {
if ( typeof string !== 'string' ) {
string = string.toString();
if ( typeof allowed !== 'undefined' ) {
purifyOptions.ALLOWED_TAGS = allowed;
return purify.sanitize( string, purifyOptions ).trim();
* Uses: `https://stackoverflow.com/a/18750001/9745718`
* @param {string} string HTML to sanitize.
* @return {string} String with encoded HTML entities.
encodeHTMLEntities( string ) {
if ( typeof string !== 'string' ) {
string = string.toString();
return string.replace( /[\u00A0-\u9999<>&]/gim, function( i ) {
return '&#' + i.charCodeAt( 0 ) + ';';
* Radio Group for Checkboxes.
initRadioGroupForCheckboxes() {
$( document ).on( 'change', 'input[type="checkbox"].wpforms-radio-group', function() {
const $input = $( this );
if ( ! $input.prop( 'checked' ) ) {
const groupName = $input.data( 'radio-group' ),
$group = $( '.wpforms-radio-group-' + groupName ),
inputId = $input.attr( 'id' );
$group.each( function() {
if ( $item.attr( 'id' ) !== inputId ) {
$item.prop( 'checked', false );
* Pluck a certain field out of each object in a list.
* JS implementation of the `wp_list_pluck()`.
* @param {Array} arr Array of objects.
* @param {string} column Column.
* @return {Array} Array with extracted column values.
listPluck( arr, column ) {
return arr.map( function( x ) {
if ( typeof x !== 'undefined' ) {
* Wrapper to trigger a native or custom event and return the event object.
* @since 1.7.6 Deprecated.
* @deprecated Use `WPFormsUtils.triggerEvent` instead.
* @param {jQuery} $element Element to trigger event on.
* @param {string} eventName Event name to trigger (custom or native).
* @return {Event} Event object.
triggerEvent( $element, eventName ) {
// eslint-disable-next-line no-console
console.warn( 'WARNING! Function "wpf.triggerEvent( $element, eventName )" has been deprecated, please use the new "WPFormsUtils.triggerEvent( $element, eventName, args )" function instead!' );
return WPFormsUtils.triggerEvent( $element, eventName );
* Automatically add paragraphs to the text.
* JS implementation of the `wpautop()`.
* @see https://github.com/andymantell/node-wpautop/blob/master/lib/wpautop.js
* @param {string} pee Text to be replaced.
* @param {boolean} br Whether remaining \n characters should be replaced with <br />.
* @return {string} Text with replaced paragraphs.
wpautop( pee, br = true ) { // eslint-disable-line max-lines-per-function, complexity
const preTags = new Map();
const _autopNewlinePreservationHelper = function( matches ) {
return matches[ 0 ].replace( '\n', '<WPPreserveNewline />' );
if ( ( typeof pee ) !== 'string' && ! ( pee instanceof String ) ) {
if ( pee.trim() === '' ) {
pee = pee + '\n'; // Just to make things a little easier, pad the end.
if ( pee.indexOf( '<pre' ) > -1 ) {
const peeParts = pee.split( '</pre>' ),
lastPee = peeParts.pop();
function( peePart, index ) {
const start = peePart.indexOf( '<pre' );