: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Init Display Previous option for Pagebreak field.
* @param {jQuery} $field Page Break field jQuery object.
fieldPageBreakInitDisplayPrevious( $field ) {
const id = $field.data( 'field-id' ),
$prevToggle = $( '#wpforms-field-option-row-' + id + '-prev_toggle' ),
$prev = $( '#wpforms-field-option-row-' + id + '-prev' ),
$prevBtn = $field.find( '.wpforms-pagebreak-prev' );
if ( $field.prevAll( '.wpforms-field-pagebreak.wpforms-pagebreak-normal' ).length > 0 ) {
$prevToggle.removeClass( 'hidden' );
$prev.removeClass( 'hidden' );
if ( $prevToggle.find( 'input' ).is( ':checked' ) ) {
$prevBtn.removeClass( 'wpforms-hidden' ).text( $prev.find( 'input' ).val() );
$prevToggle.addClass( 'hidden' );
$prev.addClass( 'hidden' );
$prevBtn.addClass( 'wpforms-hidden' );
* Field Dynamic Choice toggle.
* @param {Element} el Element.
fieldDynamicChoiceToggle( el ) { // eslint-disable-line complexity, max-lines-per-function
$thisOption = $this.parent(),
id = $thisOption.data( 'field-id' );
const $choices = $( '#wpforms-field-option-row-' + id + '-choices' ),
$images = $( '#wpforms-field-option-' + id + '-choices_images' ),
$icons = $( '#wpforms-field-option-' + id + '-choices_icons' );
// Hide image and icon choices if "dynamic choices" is not off.
app.fieldDynamicChoiceToggleImageChoices();
app.fieldDynamicChoiceToggleIconChoices();
// Fire an event when a field's dynamic choices option was changed.
$builder.trigger( 'wpformsFieldDynamicChoiceToggle', [ id ] );
wpf.fieldOptionLoading( $thisOption );
// Remove previous dynamic post type or taxonomy source options.
$( '#wpforms-field-option-row-' + id + '-dynamic_post_type' ).remove();
$( '#wpforms-field-option-row-' + id + '-dynamic_taxonomy' ).remove();
* Post type- or Taxonomy-based dynamic populating.
// Hide choice images and icons options, not applicable.
$images.addClass( 'wpforms-hidden' );
$icons.addClass( 'wpforms-hidden' );
// Hide `Bulk Add` toggle.
$choices.find( '.toggle-bulk-add-display' ).addClass( 'wpforms-hidden' );
field_id: id, // eslint-disable-line camelcase
action: 'wpforms_builder_dynamic_choices',
nonce: wpforms_builder.nonce,
$.post( wpforms_builder.ajax_url, data, function( res ) {
$thisOption.after( res.data.markup );
// eslint-disable-next-line no-console
// Hide loading indicator.
wpf.fieldOptionLoading( $thisOption, true );
// Re-init tooltips for new field.
// Trigger Dynamic source updates.
$( '#wpforms-field-option-' + id + '-dynamic_' + value ).find( 'option' ).first().prop( 'selected', true );
$( '#wpforms-field-option-' + id + '-dynamic_' + value ).trigger( 'change' );
} ).fail( function( xhr, textStatus, e ) { // eslint-disable-line no-unused-vars
// eslint-disable-next-line no-console
console.log( xhr.responseText );
return; // Nothing more for dynamic populating.
* "Off" - no dynamic populating.
let type = $( '#wpforms-field-option-' + id ).find( '.wpforms-field-option-hidden-type' ).val();
// Show choice images and icon options.
$images.removeClass( 'wpforms-hidden' );
$icons.removeClass( 'wpforms-hidden' );
// Show `Bulk Add` toggle.
$choices.find( '.toggle-bulk-add-display' ).removeClass( 'wpforms-hidden' );
$( '#wpforms-field-' + id ).find( '.wpforms-alert' ).remove();
if ( [ 'checkbox', 'radio', 'payment-multiple', 'payment-checkbox' ].indexOf( type ) > -1 ) {
app.fieldChoiceUpdate( type, id );
// Toggle elements and hide loading indicator.
$choices.find( 'ul' ).removeClass( 'wpforms-hidden' );
$choices.find( '.wpforms-alert' ).addClass( 'wpforms-hidden' );
wpf.fieldOptionLoading( $thisOption, true );
return; // Nothing more for those types.
// Get original field choices.
const $field = $( '#wpforms-field-' + id );
$primary = $field.find( '.primary-input' );
$( '#wpforms-field-option-row-' + id + '-choices li' ).each( function() {
label: wpf.sanitizeHTML( $this.find( '.label' ).val() ),
selected: $this.find( '.default' ).is( ':checked' ),
// Restore field to display original field choices.
if ( $field.hasClass( 'wpforms-field-select' ) ) {
const isModernSelect = app.dropdownField.helpers.isModernSelect( $primary );
// Remove previous items.
$primary.find( 'option' ).not( '.placeholder' ).remove();
// Update Modern Dropdown.
if ( isModernSelect && choices.length ) {
app.dropdownField.helpers.update( id, false );
// Update Classic select field.
selected = choices[ key ].selected;
optionHTML += selected ? ' selected>' : '>';
optionHTML += choices[ key ].label + '</option>';
$primary.append( optionHTML );
if ( $field.hasClass( 'wpforms-field-checkbox' ) ) {
// Remove previous items.
// Add new items to radio or checkbox field.
optionHTML = '<li><input type="' + type + '" disabled';
optionHTML += choices[ key ].selected ? ' selected>' : '>';
optionHTML += choices[ key ].label + '</li>';
$primary.append( optionHTML );
// Toggle elements and hide loading indicator.
$choices.find( 'ul' ).removeClass( 'wpforms-hidden' );
$choices.find( '.wpforms-alert' ).addClass( 'wpforms-hidden' );
$primary.removeClass( 'wpforms-hidden' );
wpf.fieldOptionLoading( $thisOption, true );
* Field Dynamic Choice Source toggle.
* @param {Element} el Element.
fieldDynamicChoiceSource( el ) { // eslint-disable-line max-lines-per-function
/* eslint-disable camelcase */
$thisOption = $this.parent(),
id = $thisOption.data( 'field-id' ),
form_id = $( '#wpforms-builder-form' ).data( 'id' ),
$choices = $( '#wpforms-field-option-row-' + id + '-choices' ),
$field = $( '#wpforms-field-' + id ),
type = $( '#wpforms-field-option-' + id + '-dynamic_choices option:selected' ).val();
wpf.fieldOptionLoading( $thisOption );
action: 'wpforms_builder_dynamic_source',
nonce: wpforms_builder.nonce,
$.post( wpforms_builder.ajax_url, data, function( res ) {
// eslint-disable-next-line no-console
// Toggle elements and hide loading indicator.
wpf.fieldOptionLoading( $thisOption, true );
// Update info box and remove old choices.
$choices.find( '.dynamic-name' ).text( res.data.source_name );
$choices.find( '.dynamic-type' ).text( res.data.type_name );
$choices.find( 'ul' ).addClass( 'wpforms-hidden' );
$choices.find( '.wpforms-alert' ).removeClass( 'wpforms-hidden' );
app.fieldDynamicChoiceSourceItems( $field, res.data.items );
if ( $field.hasClass( 'wpforms-field-select' ) ) {
// Remove any previous empty message.
$field.find( '.wpforms-notice-dynamic-empty' ).remove();
// If the source has more items than the field type can
// ideally handle alert the user.
if ( Number( res.data.total ) > limit ) {
let msg = wpforms_builder.dynamic_choices.limit_message;
msg = msg.replace( '{source}', res.data.source_name );
msg = msg.replace( '{type}', res.data.type_name );
msg = msg.replace( '{limit}', limit );
msg = msg.replace( '{total}', res.data.total );
title: wpforms_builder.heads_up,
icon: 'fa fa-info-circle',
text: wpforms_builder.ok,
// Toggle limit choices alert message.
app.firstNChoicesAlert( id, res.data.total );
// Toggle empty choices notice message.
if ( Number( res.data.total ) === 0 ) {
app.emptyChoicesNotice( id, res.data.source_name, res.data.type );
// Toggle elements and hide loading indicator.
wpf.fieldOptionLoading( $thisOption, true );
} ).fail( function( xhr, textStatus, e ) { // eslint-disable-line no-unused-vars
// eslint-disable-next-line no-console
console.log( xhr.responseText );
* Update a Field Items when `Dynamic Choice` Source is toggled.
* @param {Object} $field jQuery selector for current field.
* @param {Object} items Items collection.
fieldDynamicChoiceSourceItems( $field, items ) {
const $primary = $field.find( '.primary-input' );
if ( $field.hasClass( 'wpforms-field-select' ) ) {
const isModernSelect = app.dropdownField.helpers.isModernSelect( $primary );
app.fieldDynamicChoiceSourceForModernSelect( $primary, items );
app.fieldDynamicChoiceSourceForClassicSelect( $primary, items );
if ( $field.hasClass( 'wpforms-field-checkbox' ) ) {
// Remove previous items.
// Add new items to radio or checkbox field.
$primary.append( '<li><input type="' + type + '" disabled> ' + wpf.sanitizeHTML( items[ key ] ) + '</li>' );
* Update options for Modern style select when `Dynamic Choice` Source is toggled.
* @param {Object} $jquerySelector jQuery selector for primary input.
* @param {Object} items Items collection.
fieldDynamicChoiceSourceForModernSelect( $jquerySelector, items ) {
const instance = app.dropdownField.helpers.getInstance( $jquerySelector ),
fieldId = $jquerySelector.closest( '.wpforms-field' ).data().fieldId;
// Destroy the instance of Choices.js.
app.dropdownField.helpers.updatePlaceholderChoice( instance, fieldId );
app.fieldDynamicChoiceSourceForClassicSelect( $jquerySelector, items );
app.dropdownField.events.choicesInit( $jquerySelector );
* Update options for Classic style select when `Dynamic Choice` Source is toggled.
* @param {Object} $jquerySelector jQuery selector for primary input.
* @param {Object} items Items collection.
fieldDynamicChoiceSourceForClassicSelect( $jquerySelector, items ) {
const itemsSize = items.length;
$jquerySelector.find( 'option' ).not( '.placeholder' ).remove();
// Add options (items) to a single <select> field.
for ( ; index < itemsSize; index++ ) {
const item = wpf.sanitizeHTML( items[ index ] );
$jquerySelector.append( '<option value="' + item + '">' + item + '</option>' );
$jquerySelector.toggleClass( 'wpforms-hidden', ! itemsSize );
* Image choice toggle, hide image choices, image choices style, choices if Dynamic choices is not OFF.
fieldDynamicChoiceToggleImageChoices() {
$( '#wpforms-builder .wpforms-field-options .wpforms-field-option' ).each( function( key, value ) {
const $option = $( value ),
dynamicChoices = $option.find( '.wpforms-field-option-row-dynamic_choices select' ).val(),
isDynamicChoices = typeof dynamicChoices !== 'undefined' && '' !== dynamicChoices,
isImageChoices = $option.find( '.wpforms-field-option-row-choices_images input' ).is( ':checked' );
.find( '.wpforms-field-option-row-choices_images' )
.toggleClass( 'wpforms-hidden', isDynamicChoices );
if ( ! isImageChoices || isDynamicChoices ) {
.find( '.wpforms-field-option-row-choices_images_style' )
.addClass( 'wpforms-hidden' );
* Hide icon choice toggle, icon choices, color, size and style options if Dynamic choices is not OFF.
fieldDynamicChoiceToggleIconChoices() {
$( '#wpforms-builder .wpforms-field-options .wpforms-field-option' ).each( function( key, value ) {
const $option = $( value ),
dynamicChoices = $option.find( '.wpforms-field-option-row-dynamic_choices select' ).val(),
isDynamicChoices = typeof dynamicChoices !== 'undefined' && '' !== dynamicChoices,
isIconChoices = $option.find( '.wpforms-field-option-row-choices_icons input' ).is( ':checked' );
.find( '.wpforms-field-option-row-choices_icons' )
.toggleClass( 'wpforms-hidden', isDynamicChoices );
if ( ! isIconChoices || isDynamicChoices ) {
.find( '.wpforms-field-option-row-choices_icons_color' )
.addClass( 'wpforms-hidden' );
.find( '.wpforms-field-option-row-choices_icons_size' )
.addClass( 'wpforms-hidden' );
.find( '.wpforms-field-option-row-choices_icons_style' )
.addClass( 'wpforms-hidden' );
* Show choices limit alert message.
* @param {number} fieldId Field ID.
* @param {number} total Total number of choices.
firstNChoicesAlert: ( fieldId, total ) => {
const $field = $( '#wpforms-field-' + fieldId );
// Don't show a message for select fields.
if ( $field.hasClass( 'wpforms-field-select' ) ) {
const tmpl = wp.template( 'wpforms-choices-limit-message' ),
limit = app.settings.choicesLimit;
$field.find( '.wpforms-alert-dynamic' ).remove();
$field.find( '.primary-input' ).after( tmpl( data ) );
* Show an empty choice notice message.
* @param {number} fieldId Field ID.
* @param {string} source Source name.
* @param {string} type Source type.
emptyChoicesNotice( fieldId, source, type ) {
const field = $( '#wpforms-field-' + fieldId );
const emptyDynamicChoicesMessage = wpforms_builder.dynamic_choices.empty_message
.replace( '{source}', source )
.replace( '{type}', wpforms_builder.dynamic_choices.entities[ type ] );
const template = wp.template( 'wpforms-empty-choice-message' ),
message: emptyDynamicChoicesMessage,
field.find( '.label-title' ).after( template( data ) );
* Field layout selector toggling.
* @param {Element} el Layout selector toggle link element.
fieldLayoutSelectorToggle( el ) {
$layoutSelectorDisplay = $this.closest( 'label' ).next( '.layout-selector-display' );