: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
} ).removeClass( 'wpforms-hidden-strict' );
$currentCountry.attr( { id: '', name: '' } ).addClass( 'wpforms-hidden-strict' );
// Real-time updates for a Date/Time date type
$builder.on( 'change', '.wpforms-field-option-row-date .type select', function( e ) { // eslint-disable-line no-unused-vars
id = $( this ).closest( '.wpforms-field-option-row' ).data( 'field-id' ),
addClass = value === 'datepicker' ? 'wpforms-date-type-datepicker' : 'wpforms-date-type-dropdown',
removeClass = value === 'datepicker' ? 'wpforms-date-type-dropdown' : 'wpforms-date-type-datepicker';
$( '#wpforms-field-' + id ).find( '.wpforms-date' ).addClass( addClass ).removeClass( removeClass );
$( '#wpforms-field-option-' + id ).addClass( addClass ).removeClass( removeClass );
const $limitDays = $this.closest( '.wpforms-field-option-group-advanced' )
.find( '.wpforms-field-option-row-date_limit_days, .wpforms-field-option-row-date_limit_days_options, .wpforms-field-option-row-date_disable_past_dates' ),
$limitDaysOptions = $( '#wpforms-field-option-row-' + id + '-date_limit_days_options' );
if ( value === 'dropdown' ) {
const $dateSelect = $( '#wpforms-field-option-' + id + '-date_format' );
if ( $dateSelect.find( 'option:selected' ).hasClass( 'datepicker-only' ) ) {
$dateSelect.prop( 'selectedIndex', 0 ).trigger( 'change' );
$( '#wpforms-field-option-' + id + '-date_limit_days' ).is( ':checked' )
? $limitDaysOptions.show()
: $limitDaysOptions.hide();
// Real-time updates for Date/Time date select format
$builder.on( 'change', '.wpforms-field-option-row-date .format select', function( e ) { // eslint-disable-line no-unused-vars
id = $( this ).closest( '.wpforms-field-option-row' ).data( 'field-id' ),
$field = $( '#wpforms-field-' + id );
if ( value === 'm/d/Y' ) {
$field.find( '.wpforms-date-dropdown .first option' ).text( wpforms_builder.date_select_month );
$field.find( '.wpforms-date-dropdown .second option' ).text( wpforms_builder.date_select_day );
} else if ( value === 'd/m/Y' ) {
$field.find( '.wpforms-date-dropdown .first option' ).text( wpforms_builder.date_select_day );
$field.find( '.wpforms-date-dropdown .second option' ).text( wpforms_builder.date_select_month );
// Real-time updates for Date/Time select format
$builder.on( 'change', '.wpforms-field-option-row-time .format select', function( e ) { // eslint-disable-line no-unused-vars
id = $this.closest( '.wpforms-field-option-row' ).data( 'field-id' );
// Determine a time format type.
// If the format contains `g` or `h`, then this is 12-hour format, otherwise 24 hours.
const format = $this.val().match( /[gh]/ ) ? 12 : 24,
minHour = format === 12 ? 1 : 0,
maxHour = format === 12 ? 13 : 24;
// Generate a new set of hour options.
for ( let i = minHour; i < maxHour; i++ ) {
hh = i < 10 ? '0' + i : i;
options += '<option value="{hh}">{hh}</option>'.replace( /{hh}/g, hh );
_.forEach( [ 'start', 'end' ], function( field ) {
const $hour = $builder.find( '#wpforms-field-option-' + id + '-time_limit_hours_' + field + '_hour' ),
$ampm = $builder.find( '#wpforms-field-option-' + id + '-time_limit_hours_' + field + '_ampm' );
let hourValue = parseInt( $hour.val(), 10 ),
hourValue = ampmValue === 'pm' ? hourValue + 12 : hourValue;
ampmValue = hourValue > 12 ? 'pm' : 'am';
hourValue = hourValue > 12 ? hourValue - 12 : hourValue;
hourValue = hourValue < 10 ? '0' + hourValue : hourValue;
$hour.html( options ).val( hourValue );
$ampm.toggleClass( 'wpforms-hidden-strict', format === 24 ).val( ampmValue );
$ampm.nextAll( 'div' ).toggleClass( 'wpforms-hidden-strict', format === 12 );
// Consider the field active when a disabled nav button is clicked
$builder.on( 'click', '.wpforms-pagebreak-button', function( e ) {
$( this ).closest( '.wpforms-field' ).trigger( 'click' );
app.fieldPageBreakInitDisplayPrevious( $builder.find( '.wpforms-field-pagebreak.wpforms-pagebreak-normal' ).first() );
.on( 'input', '.wpforms-field-option-row-next input', function( e ) { // eslint-disable-line no-unused-vars
// Real-time updates for "Next" pagebreak field option.
$next = $( '#wpforms-field-' + $this.parent().data( 'field-id' ) ).find( '.wpforms-pagebreak-next' );
$next.css( 'display', 'inline-block' ).text( value );
$next.css( 'display', 'none' ).empty();
.on( 'input', '.wpforms-field-option-row-prev input', function( e ) { // eslint-disable-line no-unused-vars
// Real-time updates for "Prev" pagebreak field option.
value = $this.val().trim(),
$field = $( '#wpforms-field-' + $this.parent().data( 'field-id' ) ),
$prevBtn = $field.find( '.wpforms-pagebreak-prev' );
if ( value && $field.prevAll( '.wpforms-field-pagebreak.wpforms-pagebreak-normal' ).length > 0 ) {
$prevBtn.removeClass( 'wpforms-hidden' ).text( value );
$prevBtn.addClass( 'wpforms-hidden' ).empty();
.on( 'change', '.wpforms-field-option-row-prev_toggle input', function( e ) { // eslint-disable-line complexity, no-unused-vars
// Real-time updates for "Display Previous" pagebreak field option.
const $input = $( this ),
$wrapper = $input.closest( '.wpforms-field-option-row-prev_toggle' );
if ( $wrapper.hasClass( 'wpforms-entry-preview-block' ) ) {
const $prev = $input.closest( '.wpforms-field-option-group-inner' ).find( '.wpforms-field-option-row-prev' );
const $prevLabel = $prev.find( 'input' ),
$prevBtn = $( '#wpforms-field-' + $input.closest( '.wpforms-field-option' ).data( 'field-id' ) ).find( '.wpforms-pagebreak-prev' );
$prev.toggleClass( 'wpforms-hidden', ! $input.prop( 'checked' ) );
$prevBtn.toggleClass( 'wpforms-hidden', ! $input.prop( 'checked' ) );
if ( $input.prop( 'checked' ) && ! $prevLabel.val() ) {
let message = $prevLabel.data( 'last-value' );
message = message && message.trim() ? message.trim() : wpforms_builder.previous;
$prevLabel.val( message );
// Backward compatibility for forms that were created before the toggle was added.
if ( ! $input.prop( 'checked' ) ) {
$prevLabel.data( 'last-value', $prevLabel.val() );
$prevLabel.trigger( 'input' );
.on( 'wpformsFieldAdd', app.fieldPagebreakAdd )
.on( 'wpformsFieldDelete', app.fieldPagebreakDelete )
.on( 'wpformsFieldAdd', app.toggleOrderSummaryConfirmation )
.on( 'wpformsFieldDelete', app.toggleOrderSummaryConfirmation )
.on( 'wpformsBeforeFieldDelete', app.fieldEntryPreviewDelete );
// Update Display Previous option visibility for all Pagebreak fields.
$builder.on( 'wpformsFieldMove wpformsFieldAdd wpformsFieldDelete', function( e ) { // eslint-disable-line no-unused-vars
$builder.find( '.wpforms-field-pagebreak.wpforms-pagebreak-normal' ).each( function( i ) { // eslint-disable-line no-unused-vars
app.fieldPageBreakInitDisplayPrevious( $( this ) );
// Real-time updates for "Page Title" pagebreak field option
$builder.on( 'input', '.wpforms-field-option-row-title input', function( e ) { // eslint-disable-line no-unused-vars
id = $this.parent().data( 'field-id' );
$( '#wpforms-field-' + id ).find( '.wpforms-pagebreak-title' ).text( value );
$( '#wpforms-field-' + id ).find( '.wpforms-pagebreak-title' ).empty();
// Real-time updates for "Page Navigation Alignment" pagebreak field option
$builder.on( 'change', '.wpforms-field-option-row-nav_align select', function( e ) { // eslint-disable-line no-unused-vars
$( '.wpforms-pagebreak-buttons' )
.removeClass( 'wpforms-pagebreak-buttons-center wpforms-pagebreak-buttons-left wpforms-pagebreak-buttons-right wpforms-pagebreak-buttons-split' )
.addClass( 'wpforms-pagebreak-buttons-' + value );
// Real-time updates for Single Item field "Item Price" option.
$builder.on( 'input', '.wpforms-field-option-row-price input', function() {
formatted = wpf.amountFormat( wpf.amountSanitize( value ) ),
id = $this.parent().data( 'field-id' ),
placeholder = $( '#wpforms-field-option-' + id + '-placeholder' ).val().trim(),
$preview = $( '#wpforms-field-' + id ),
newValue = value === '' && placeholder !== '' ? '' : formatted;
$preview.find( '.primary-input' ).val( newValue );
$preview.find( '.price' ).text( wpf.amountFormatCurrency( value ) );
// Real-time updates for Single Item field "Minimum Price" option.
$builder.on( 'input', '.wpforms-field-option-row-min_price input', function() {
sanitized = wpf.amountSanitize( amount ),
isEmpty = sanitized <= 0,
isValid = sanitized >= $this.data( 'minimum-price' ),
$fieldOptionRow = $this.parent(),
$preview = $( '#wpforms-field-' + $fieldOptionRow.data( 'field-id' ) );
$fieldOptionRow.find( '.wpforms-item-minimum-price-alert' ).toggleClass( 'wpforms-hidden', isValid );
$preview.find( '.item-min-price' ).toggleClass( 'wpforms-hidden', isEmpty );
$preview.toggleClass( 'min-price-warning', ! isValid );
$preview.find( '.fa-exclamation-triangle' ).toggleClass( 'wpforms-hidden', isValid );
$preview.find( '.min-price' ).text( wpf.amountFormatCurrency( amount ) );
// Real-time updates for price label for single item field.
$builder.on( 'input', '.wpforms-single-item-price-label-display', function() {
value = wpf.sanitizeHTML( $this.val(), '<>' ),
id = $this.parent().data( 'field-id' ),
$preview = $( `#wpforms-field-${ id }` ),
$price = wpf.amountFormatCurrency( $( `#wpforms-field-option-${ id }-price` ).val() );
$preview.find( '.price-label' ).html( `<span class="price"> ${ $price } </span>` );
$preview.find( '.price-label' ).html( value.replaceAll( '{price}', `<span class="price"> ${ $price } </span>` ) );
// Real-time updates for payment CC icons
$builder.on( 'change', '.wpforms-field-option-credit-card .payment-icons input', function() {
card = $this.data( 'card' ),
id = $this.parent().data( 'field-id' );
$( '#wpforms-field-' + id ).find( 'img.icon-' + card ).toggleClass( 'card_hide' );
// Generic updates for various additional placeholder fields (at least Stripe's "Name on Card").
$builder.on( 'input', '.wpforms-field-option input.placeholder-update', function( e ) { // eslint-disable-line no-unused-vars
id = $this.data( 'field-id' ),
subfield = $this.data( 'subfield' );
$( '#wpforms-field-' + id ).find( '.wpforms-' + subfield + ' input' ).attr( 'placeholder', value );
// Toggle Choice Layout advanced field option.
$builder.on( 'change', '.wpforms-field-option-row-input_columns select', function() {
id = $this.parent().data( 'field-id' );
cls = 'wpforms-list-2-columns';
} else if ( value === '3' ) {
cls = 'wpforms-list-3-columns';
} else if ( value === 'inline' ) {
cls = 'wpforms-list-inline';
$( '#wpforms-field-' + id ).removeClass( 'wpforms-list-2-columns wpforms-list-3-columns wpforms-list-inline' ).addClass( cls );
// Toggle the toggle field.
$builder.on( 'change', '.wpforms-field-option-row .wpforms-toggle-control input', function( e ) { // eslint-disable-line no-unused-vars
const $check = $( this ),
$control = $check.closest( '.wpforms-toggle-control' ),
$status = $control.find( '.wpforms-toggle-control-status' ),
state = $check.is( ':checked' ) ? 'on' : 'off';
$status.html( $status.data( state ) );
// Real-time updates for "Dynamic Choices" field option, for Dropdown,
// Checkboxes, and Multiple choice fields
$builder.on( 'change', '.wpforms-field-option-row-dynamic_choices select', function( e ) { // eslint-disable-line no-unused-vars
app.fieldDynamicChoiceToggle( $( this ) );
// Real-time updates for "Dynamic [type] Source" field option, for Dropdown,
// Checkboxes, and Multiple choice fields
$builder.on( 'change', '.wpforms-field-option-row-dynamic_taxonomy select, .wpforms-field-option-row-dynamic_post_type select', function( e ) { // eslint-disable-line no-unused-vars
app.fieldDynamicChoiceSource( $( this ) );
// Toggle Layout selector
$builder.on( 'click', '.toggle-layout-selector-display', function( e ) {
app.fieldLayoutSelectorToggle( this );
$builder.on( 'click', '.layout-selector-display-layout', function( e ) {
app.fieldLayoutSelectorLayout( this );
$builder.on( 'click', '.layout-selector-display-columns span', function( e ) {
app.fieldLayoutSelectorInsert( this );
// Real-time updates for a Rating field scale option.
$( document ).on( 'change', '.wpforms-field-option-row-scale select', function() {
id = $this.parent().data( 'field-id' ),
$icons = $( '#wpforms-field-' + id + ' .rating-icon' );
$icons.each( function( index ) { // eslint-disable-line no-unused-vars
// Real-time updates for a Rating field icon option.
$( document ).on( 'change', '.wpforms-field-option-row-icon select', function() {
id = $this.parent().data( 'field-id' ),
$icons = $( '#wpforms-field-' + id + ' .rating-icon' );
let iconClass = 'fa-star';
if ( 'heart' === value ) {
} else if ( 'thumb' === value ) {
iconClass = 'fa-thumbs-up';
} else if ( 'smiley' === value ) {
iconClass = 'fa-smile-o';
$icons.removeClass( 'fa-star fa-heart fa-thumbs-up fa-smile-o' ).addClass( iconClass );
// Real-time updates for a Rating field icon size option.
$( document ).on( 'change', '.wpforms-field-option-row-icon_size select', function() {
id = $this.parent().data( 'field-id' ),
$icons = $( '#wpforms-field-' + id + ' .rating-icon' );
if ( 'small' === value ) {
} else if ( 'large' === value ) {
$icons.css( 'font-size', fontSize + 'px' );
// Real-time updates for a Rating field icon color option.
$( document ).on( 'input', '.wpforms-field-option-row-icon_color input.wpforms-color-picker', function() {
id = $this.closest( '.wpforms-field-option-row' ).data( 'field-id' ),
$icons = $( '#wpforms-field-' + id + ' > i.fa' );
$icons.css( 'color', app.getValidColorPickerValue( $this ) );
// Real-time updates for a Checkbox field Disclaimer option.
$( document ).on( 'change', '.wpforms-field-option-row-disclaimer_format input', function() {
id = $this.closest( '.wpforms-field-option-row' ).data( 'field-id' ),
$desc = $( '#wpforms-field-' + id + ' .description' );
$desc.toggleClass( 'disclaimer' );
'.wpforms-field-option-row-limit_enabled input',
app.updateTextFieldsLimitControls( $( event.target ).closest( '.wpforms-field-option-row-limit_enabled' ).data().fieldId, event.target.checked );
'.wpforms-field-option-row-date_disable_past_dates input',
app.updateDisableTodaysDateControls( $( event.target ).closest( '.wpforms-field-option-row-date_disable_past_dates' ).data().fieldId, event.target?.checked );
'.wpforms-field-option-row-password-strength input',
app.updatePasswordStrengthControls( $( event.target ).parents( '.wpforms-field-option-row-password-strength' ).data().fieldId, event.target.checked );
'.wpforms-field-option-richtext .wpforms-field-option-row-media_enabled input',
app.updateRichTextMediaFieldsLimitControls
'.wpforms-field-option-richtext .wpforms-field-option-row-style select',
app.updateRichTextStylePreview
// File uploader - change style.
'.wpforms-field-option-file-upload .wpforms-field-option-row-style select, .wpforms-field-option-file-upload .wpforms-field-option-row-max_file_number input',
app.fieldFileUploadPreviewUpdate( event.target );
// Real-time updates for Number Slider field.
app.numberSliderEvents( $builder );
// Hide image and icon choices if dynamic choices are not off.
app.fieldDynamicChoiceToggleImageChoices();
app.fieldDynamicChoiceToggleIconChoices();
// Real-time updates for Payment field's 'Show price after item label' option.
$builder.on( 'change', '.wpforms-field-option-row-show_price_after_labels input', function( e ) { // eslint-disable-line no-unused-vars
const $input = $( this ),
$list = $input.closest( '.wpforms-field-option-group-basic' ).find( '.wpforms-field-option-row-choices .choices-list' );
app.fieldChoiceUpdate( $list.data( 'field-type' ), $list.data( 'field-id' ) );
.on( 'input', '.wpforms-field-option-row-preview-notice textarea', app.updatePreviewNotice )
.on( 'change', '.wpforms-field-option-row-preview-notice-enable input', app.toggleEntryPreviewNotice )
.on( 'wpformsFieldAdd', app.maybeLockEntryPreviewGroupOnAdd )
.on( 'wpformsFieldMove', app.maybeLockEntryPreviewGroupOnMove )
.on( 'click', '.wpforms-entry-preview-block', app.entryPreviewBlockField );
app.defaultStateEntryPreviewNotice();
* Check if we had focusout event from certain fields.
if ( elements.$focusOutTarget === null ) {
if ( elements.$defaultEmail.is( elements.$focusOutTarget ) ) {
const $field = elements.$focusOutTarget;
if ( $field.val() === '' ) {
wpforms_builder.ajax_url,
nonce: wpforms_builder.nonce,
action: 'wpforms_sanitize_default_email',