: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
options = $.extend( {}, defaults, options );
action: 'wpforms_new_field_' + type,
defaults: options.defaults,
nonce: wpforms_builder.nonce,
return $.post( wpforms_builder.ajax_url, data, function( res ) { // eslint-disable-line complexity
wpf.debug( 'Add field AJAX call is unsuccessful:', res );
const $baseFieldsContainer = elements.$sortableFieldsWrap,
$newField = $( res.data.preview ),
$newOptions = $( res.data.options );
let $fieldContainer = options.$sortable;
$newField.css( 'display', 'none' );
if ( options.placeholder ) {
options.placeholder.remove();
if ( options.$sortable === 'default' || ! options.$sortable.length ) {
$fieldContainer = $baseFieldsContainer.find( '.wpforms-fields-sortable-default' );
if ( options.$sortable === 'base' || ! $fieldContainer.length ) {
$fieldContainer = $baseFieldsContainer;
const event = WPFormsUtils.triggerEvent(
'wpformsBeforeFieldAddToDOM',
[ options, $newField, $newOptions, $fieldContainer ]
// Allow callbacks on `wpformsBeforeFieldAddToDOM` to cancel adding field
// by triggering `event.preventDefault()`.
if ( event.isDefaultPrevented() ) {
// Add field to the base level of fields.
// Allow callbacks on `wpformsBeforeFieldAddToDOM` to skip adding field to the base level
// by setting `event.skipAddFieldToBaseLevel = true`.
if ( ! event.skipAddFieldToBaseLevel ) {
app.fieldAddToBaseLevel( options, $newField, $newOptions );
$builder.find( '.no-fields, .no-fields-preview' ).remove();
if ( $( '.wpforms-field-option:not(.wpforms-field-option-layout)' ).length ) {
$builder.find( '.wpforms-field-submit' ).show();
// Scroll to the added field.
if ( options.scroll && options.position.length ) {
app.scrollPreviewToField( res.data.field.id );
// Update next field id hidden input value.
elements.$nextFieldId.val( res.data.field.id + 1 );
app.toggleAllOptionGroups();
$builder.trigger( 'wpformsFieldAdd', [ res.data.field.id, type ] );
} ).fail( function( xhr, textStatus, e ) { // eslint-disable-line no-unused-vars
wpf.debug( 'Add field AJAX call failed:', xhr.responseText );
WPForms.Admin.Builder.DragFields.enableDragAndDrop();
* Add new field to the base level of fields.
* @param {Object} options Field add additional options.
* @param {jQuery} $newField New field preview object.
* @param {jQuery} $newOptions New field options object.
fieldAddToBaseLevel( options, $newField, $newOptions ) { // eslint-disable-line complexity
const $baseFieldsContainer = elements.$sortableFieldsWrap,
$baseFields = $baseFieldsContainer.find( '> :not(.wpforms-field-drag-pending)' ),
totalBaseFields = $baseFields.length;
const $fieldOptions = elements.$fieldOptions;
if ( options.position === 'top' ) {
// Add field to the top of base level fields.
$baseFieldsContainer.prepend( $newField );
$fieldOptions.prepend( $newOptions );
const $lastBaseField = $baseFields.last();
options.position === 'bottom' && (
! $lastBaseField.length ||
! $lastBaseField.hasClass( 'wpforms-field-stick' )
// Add field to the bottom of base level fields.
$baseFieldsContainer.append( $newField );
$fieldOptions.append( $newOptions );
if ( options.position === 'bottom' ) {
options.position = totalBaseFields;
options.position === totalBaseFields &&
$lastBaseField.length && $lastBaseField.hasClass( 'wpforms-field-stick' )
const lastBaseFieldId = $lastBaseField.data( 'field-id' );
// Check to see if the last field we have is configured to
// be stuck to the bottom, if so add the field above it.
$lastBaseField.before( $newField );
$fieldOptions.find( `#wpforms-field-option-${ lastBaseFieldId }` ).before( $newOptions );
const $fieldInPosition = $baseFieldsContainer.children( ':not(.wpforms-field-drag-pending)' ).eq( options.position );
if ( $fieldInPosition.length ) {
const fieldInPositionId = $fieldInPosition.data( 'field-id' );
// Add field to a specific location.
$fieldInPosition.before( $newField );
$fieldOptions.find( `#wpforms-field-option-${ fieldInPositionId }` ).before( $newOptions );
// Something is wrong. Add the field. This should never occur.
$baseFieldsContainer.append( $newField );
$fieldOptions.append( $newOptions );
* Scroll the preview panel to the desired field.
* @param {number} fieldId Field ID.
scrollPreviewToField( fieldId ) {
const $field = $( `#wpforms-field-${ fieldId }` ),
scrollTop = elements.$fieldsPreviewWrap.scrollTop(),
$layoutField = $field.closest( '.wpforms-field-layout' );
let fieldPosition = $field.position().top;
if ( $layoutField.length ) {
fieldPosition = $layoutField.position().top + fieldPosition + 20;
const scrollAmount = fieldPosition > scrollTop ? fieldPosition - scrollTop : fieldPosition + scrollTop;
elements.$fieldsPreviewWrap.scrollTop( scrollAmount );
* Update CAPTCHA form setting.
* @return {Object} jqXHR.
action: 'wpforms_update_field_captcha',
nonce: wpforms_builder.nonce,
return $.post( wpforms_builder.ajax_url, data, function( res ) {
icon: 'fa fa-exclamation-circle',
text: wpforms_builder.ok,
$enableCheckbox = $( '#wpforms-panel-field-settings-recaptcha' );
let caseName = res.data.current;
$enableCheckbox.data( 'provider', res.data.provider );
// not_configured - IF CAPTCHA is not configured in the WPForms plugin settings
// configured_not_enabled - IF CAPTCHA is configured in WPForms plugin settings, but wasn't set in form settings
// configured_enabled - IF CAPTCHA is configured in WPForms plugin and form settings
if ( 'configured_not_enabled' === caseName || 'configured_enabled' === caseName ) {
// Get a correct case name.
caseName = $enableCheckbox.prop( 'checked' ) ? 'configured_enabled' : 'configured_not_enabled';
// Check/uncheck a `CAPTCHA` checkbox in form setting.
args.buttons.confirm.action = function() {
$enableCheckbox.prop( 'checked', ( 'configured_not_enabled' === caseName ) ).trigger( 'change' );
args.title = res.data.cases[ caseName ].title;
args.content = res.data.cases[ caseName ].content;
// Do you need a Cancel button?
if ( res.data.cases[ caseName ].cancel ) {
text: wpforms_builder.cancel,
// eslint-disable-next-line no-console
} ).fail( function( xhr, textStatus, e ) { // eslint-disable-line no-unused-vars
// eslint-disable-next-line no-console
console.log( xhr.responseText );
* @since 1.7.7 Deprecated.
* @deprecated Use `WPForms.Admin.Builder.DragFields.disableDragAndDrop()` instead.
// eslint-disable-next-line no-console
console.warn( 'WARNING! Function "WPFormsBuilder.disableDragAndDrop()" has been deprecated, please use the new "WPForms.Admin.Builder.DragFields.disableDragAndDrop()" function instead!' );
WPForms.Admin.Builder.DragFields.disableDragAndDrop();
* @since 1.7.7 Deprecated.
* @deprecated Use `WPForms.Admin.Builder.DragFields.enableDragAndDrop()` instead.
// eslint-disable-next-line no-console
console.warn( 'WARNING! Function "WPFormsBuilder.enableDragAndDrop()" has been deprecated, please use the new "WPForms.Admin.Builder.DragFields.enableDragAndDrop()" function instead!' );
WPForms.Admin.Builder.DragFields.enableDragAndDrop();
* Disable Preview, Embed, Save form actions and Form Builder exit button.
function( _index, button ) {
button.prop( 'disabled', true ).addClass( 'wpforms-disabled' );
* Enable Preview, Embed, Save form actions and Form Builder exit button.
function( _index, button ) {
button.prop( 'disabled', false ).removeClass( 'wpforms-disabled' );
* Sortable fields in the builder form preview area.
* @since 1.7.7 Deprecated.
* @deprecated Use `WPForms.Admin.Builder.DragFields.initSortableFields()` instead.
// eslint-disable-next-line no-console
console.warn( 'WARNING! Function "WPFormsBuilder.fieldSortable()" has been deprecated, please use the new "WPForms.Admin.Builder.DragFields.initSortableFields()" function instead!' );
WPForms.Admin.Builder.DragFields.initSortableFields();
* Show popup in case if field is not draggable, and cancel moving.
* @since 1.7.6 The showPopUp parameter added.
* @since 1.7.7 Deprecated.
* @deprecated Use `WPForms.Admin.Builder.DragFields.fieldDragDisable()` instead.
* @param {jQuery} $field A field or list of fields.
* @param {boolean} showPopUp Whether the pop-up should be displayed on dragging attempt.
fieldDragDisable( $field, showPopUp = true ) {
// eslint-disable-next-line no-console
console.warn( 'WARNING! Function "WPFormsBuilder.fieldDragDisable()" has been deprecated, please use the new "WPForms.Admin.Builder.DragFields.fieldDragDisable()" function instead!' );
WPForms.Admin.Builder.DragFields.fieldDragDisable( $field, showPopUp );
* @since 1.7.7 Deprecated.
* @deprecated Use `WPForms.Admin.Builder.DragFields.fieldDragEnable()` instead.
* @param {jQuery} $field A field or list of fields.
fieldDragEnable( $field ) {
// eslint-disable-next-line no-console
console.warn( 'WARNING! Function "WPFormsBuilder.fieldDragEnable()" has been deprecated, please use the new "WPForms.Admin.Builder.DragFields.fieldDragEnable()" function instead!' );
WPForms.Admin.Builder.DragFields.fieldDragEnable( $field );
* @param {Event} event Event.
* @param {Element} el Element.
fieldChoiceAdd( event, el ) {
$parent = $this.parent(),
checked = $parent.find( 'input.default' ).is( ':checked' ),
fieldID = $this.closest( '.wpforms-field-option-row-choices' ).data( 'field-id' );
let id = $parent.parent().attr( 'data-next-id' );
const type = $parent.parent().data( 'field-type' ),
$choice = $parent.clone().insertAfter( $parent );
$choice.attr( 'data-key', id );
$choice.find( 'input.label' ).val( '' ).attr( 'name', 'fields[' + fieldID + '][choices][' + id + '][label]' );
$choice.find( 'input.value' ).val( '' ).attr( 'name', 'fields[' + fieldID + '][choices][' + id + '][value]' );
$choice.find( '.wpforms-image-upload input.source' ).val( '' ).attr( 'name', 'fields[' + fieldID + '][choices][' + id + '][image]' );
$choice.find( '.wpforms-icon-select input.source-icon' ).val( wpforms_builder.icon_choices.default_icon ).attr( 'name', 'fields[' + fieldID + '][choices][' + id + '][icon]' );
$choice.find( '.wpforms-icon-select input.source-icon-style' ).val( wpforms_builder.icon_choices.default_icon_style ).attr( 'name', 'fields[' + fieldID + '][choices][' + id + '][icon_style]' );
$choice.find( '.wpforms-icon-select .ic-fa-preview' ).removeClass().addClass( 'ic-fa-preview ic-fa-' + wpforms_builder.icon_choices.default_icon_style + ' ic-fa-' + wpforms_builder.icon_choices.default_icon );
$choice.find( '.wpforms-icon-select .ic-fa-preview + span' ).text( wpforms_builder.icon_choices.default_icon );
$choice.find( 'input.default' ).attr( 'name', 'fields[' + fieldID + '][choices][' + id + '][default]' ).prop( 'checked', false );
$choice.find( '.preview' ).empty();
$choice.find( '.wpforms-image-upload-add' ).show();
$choice.find( '.wpforms-money-input' ).trigger( 'focusout' );
if ( checked === true ) {
$parent.find( 'input.default' ).prop( 'checked', true );
$parent.parent().attr( 'data-next-id', id );
$builder.trigger( 'wpformsFieldChoiceAdd', [ fieldID ] );
app.fieldChoiceUpdate( type, fieldID );
* @param {Event} e Event.
* @param {Element} el Element.
fieldChoiceDelete( e, el ) {
$list = $this.parent().parent(),
total = $list.find( 'li' ).length,
id: $list.data( 'field-id' ),
choiceId: $this.closest( 'li' ).data( 'key' ),
message: '<strong>' + wpforms_builder.delete_choice_confirm + '</strong>',
$builder.trigger( 'wpformsBeforeFieldDeleteAlert', [ fieldData ] );
app.fieldChoiceDeleteAlert();
const deleteChoice = function() {
app.fieldChoiceUpdate( $list.data( 'field-type' ), $list.data( 'field-id' ) );
$builder.trigger( 'wpformsFieldChoiceDelete', [ $list.data( 'field-id' ) ] );
if ( ! fieldData.trigger ) {
content: fieldData.message,
icon: 'fa fa-exclamation-circle',
text: wpforms_builder.ok,
text: wpforms_builder.cancel,
* Field choice delete error alert.
fieldChoiceDeleteAlert() {
content: wpforms_builder.error_choice,
icon: 'fa fa-info-circle',
text: wpforms_builder.ok,