: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Update selects for mapping if any form fields was added, deleted or changed.
* @param {object} $connections jQuery selector for active connections.
updateMapSelects: function( $connections ) {
var fields = $.extend( {}, wpf.getFields() ),
// We should to detect changes for labels only.
currentSaveFields = _.mapObject( fields, function( field, key ) {
prevSaveFields = _.mapObject( __private.fields, function( field, key ) {
// Check if form has any fields and if they have changed labels after previous saving process.
( _.isEmpty( currentSaveFields ) && _.isEmpty( prevSaveFields ) ) ||
( JSON.stringify( currentSaveFields ) === JSON.stringify( prevSaveFields ) )
// Prepare a current form field IDs.
var fieldIds = Object.keys( currentSaveFields )
return parseInt( id, 10 );
// Determine deleted field IDs - it's a diff between previous and current form state.
var deleted = Object.keys( prevSaveFields )
return parseInt( id, 10 );
.filter( function( id ) {
return ! fieldIds.includes( id );
// Remove from mapping selects "deleted" fields.
for ( var index = 0; index < deleted.length; index++ ) {
$( '.wpforms-builder-provider-connection-fields-table .wpforms-builder-provider-connection-field-value option[value="' + deleted[ index ] + '"]', $connections ).remove();
for ( var id in fields ) {
if ( typeof fields[ id ].label !== 'undefined' && fields[ id ].label.toString().trim() !== '' ) {
label = wpf.sanitizeHTML( fields[ id ].label.toString().trim() );
label = wpforms_builder.field + ' #' + id;
// Try to find all select options by value.
$exists = $( '.wpforms-builder-provider-connection-fields-table .wpforms-builder-provider-connection-field-value option[value="' + id + '"]', $connections );
// If no option was found - add a new one for all selects.
if ( ! $exists.length ) {
$( '.wpforms-builder-provider-connection-fields-table .wpforms-builder-provider-connection-field-value', $connections ).append( $( '<option>', { value: id, text: label } ) );
// Update a field label if a previous and current labels not equal.
if ( wpf.sanitizeHTML( fields[ id ].label ) !== wpf.sanitizeHTML( prevSaveFields[ id ] ) ) {
// If selects for mapping was changed, that whole form state was changed as well.
// That's why we need to re-save it.
if ( wpf.savedState !== wpf.getFormState( '#wpforms-builder-form' ) ) {
wpf.savedState = wpf.getFormState( '#wpforms-builder-form' );
// Save form fields state for next saving process.
__private.fields = fields;
app.panelHolder.trigger( 'WPForms.Admin.Builder.Providers.updatedMapSelects', [ $connections, fields ] );
* All methods that modify UI of a page.
* Process UI related actions/events: click, change etc. - that are triggered from UI.
bindActions: function() {
// CONNECTION: ADD/DELETE.
.on( 'click', '.js-wpforms-builder-provider-account-add', function( e ) {
app.ui.account.setProvider( $( this ).data( 'provider' ) );
.on( 'click', '.js-wpforms-builder-provider-connection-add', function( e ) {
app.ui.connectionAdd( $( this ).data( 'provider' ) );
.on( 'click', '.js-wpforms-builder-provider-connection-delete', function( e ) {
$btn.closest( '.wpforms-builder-provider' ).data( 'provider' ),
$btn.closest( '.wpforms-builder-provider-connection' )
// CONNECTION: FIELDS - ADD/DELETE.
.on( 'click', '.js-wpforms-builder-provider-connection-fields-add', function( e ) {
var $table = $( this ).parents( '.wpforms-builder-provider-connection-fields-table' ),
$clone = $table.find( 'tr' ).last().clone( true ),
nextID = parseInt( /\[.+]\[.+]\[.+]\[(\d+)]/.exec( $clone.find( '.wpforms-builder-provider-connection-field-name' ).attr( 'name' ) )[ 1 ], 10 ) + 1;
// Clear the row and increment the counter.
$clone.find( '.wpforms-builder-provider-connection-field-name' )
.attr( 'name', $clone.find( '.wpforms-builder-provider-connection-field-name' ).attr( 'name' ).replace( /\[fields_meta\]\[(\d+)\]/g, '[fields_meta][' + nextID + ']' ) )
$clone.find( '.wpforms-builder-provider-connection-field-value' )
.attr( 'name', $clone.find( '.wpforms-builder-provider-connection-field-value' ).attr( 'name' ).replace( /\[fields_meta\]\[(\d+)\]/g, '[fields_meta][' + nextID + ']' ) )
// Re-enable "delete" button.
$clone.find( '.js-wpforms-builder-provider-connection-fields-delete' ).removeClass( 'hidden' );
// Put it back to the table.
$table.find( 'tbody' ).append( $clone.get( 0 ) );
.on( 'click', '.js-wpforms-builder-provider-connection-fields-delete', function( e ) {
var $row = $( this ).parents( '.wpforms-builder-provider-connection-fields-table tr' );
// CONNECTION: Generated.
app.panelHolder.on( 'connectionGenerated', function( e, data ) {
// Hide provider default settings screen.
.find( '.wpforms-builder-provider-connection[data-connection_id="' + data.connection.id + '"]' )
.closest( '.wpforms-panel-content-section' )
.find( '.wpforms-builder-provider-connections-default' )
.addClass( 'wpforms-hidden' );
app.panelHolder.on( 'connectionRendered', function( e, provider, connectionId ) {
// Some our addons have another arguments for this trigger.
if ( typeof connectionId === 'undefined' ) {
if ( ! _.isObject( provider ) || ! _.has( provider, 'connection_id' ) ) {
connectionId = provider.connection_id;
// If connection has mapped select fields - call `wpformsFieldUpdate` trigger.
if ( $( this ).find( '.wpforms-builder-provider-connection[data-connection_id="' + connectionId + '"] .wpforms-field-map-select' ).length ) {
// Remove error class in required fields if a value is supplied.
app.panelHolder.on( 'change', '.wpforms-builder-provider select.wpforms-required', function() {
if ( ! $this.hasClass( 'wpforms-error' ) || $this.val().length === 0 ) {
$this.removeClass( 'wpforms-error' );
* Add a connection to a page.
* This is a multistep process, where the 1st step is always the same for all providers.
* @since 1.5.9 Added a new parameter - provider.
* @param {string} provider Current provider slug.
connectionAdd: function( provider ) {
content: wpforms_builder_providers.prompt_connection.replace( /%type%/g, 'connection' ) +
'<input autofocus="" type="text" id="wpforms-builder-provider-connection-name" placeholder="' + wpforms_builder_providers.prompt_placeholder + '">' +
'<p class="error">' + wpforms_builder_providers.error_name + '</p>',
icon: 'fa fa-info-circle',
text: wpforms_builder.ok,
var name = this.$content.find( '#wpforms-builder-provider-connection-name' ).val().trim(),
error = this.$content.find( '.error' );
app.getProviderHolder( provider ).trigger( 'connectionCreate', [ name ] );
text: wpforms_builder.cancel,
* What to do with UI when connection is deleted.
* @since 1.5.9 Added a new parameter - provider.
* @param {string} provider Current provider slug.
* @param {object} $connection jQuery DOM element for a connection.
connectionDelete: function( provider, $connection ) {
content: wpforms_builder_providers.confirm_connection,
icon: 'fa fa-exclamation-circle',
text: wpforms_builder.ok,
// We need this BEFORE removing, as some handlers might need DOM element.
app.getProviderHolder( provider ).trigger( 'connectionDelete', [ $connection ] );
var $section = $connection.closest( '.wpforms-panel-content-section' );
$connection.fadeOut( 'fast', function() {
app.getProviderHolder( provider ).trigger( 'connectionDeleted', [ $connection ] );
if ( ! $section.find( '.wpforms-builder-provider-connection' ).length ) {
$section.find( '.wpforms-builder-provider-connections-default' ).removeClass( 'wpforms-hidden' );
text: wpforms_builder.cancel,
* Account specific methods.
* @since 1.5.8 Added binding `onClose` event.
* Current provider in the context of account creation.
* Preserve a list of action to perform when new account creation form is submitted.
* @param {Array<string, callable>}
* Set the account specific provider.
* @param {string} provider Provider slug.
setProvider: function( provider ) {
this.provider = provider;
* Add an account for provider.
.request( account.provider, {
task: 'account_template_get',
.done( function( response ) {
if ( ! response.success ) {
if ( response.data.title.length ) {
modal.setTitle( response.data.title );
if ( response.data.content.length ) {
modal.setContent( response.data.content );
if ( response.data.type.length ) {
modal.setType( response.data.type );
app.getProviderHolder( account.provider ).trigger( 'accountAddModal.content.done', [ modal, account.provider, response ] );
app.getProviderHolder( account.provider ).trigger( 'accountAddModal.content.fail', [ modal, account.provider ] );
app.getProviderHolder( account.provider ).trigger( 'accountAddModal.content.always', [ modal, account.provider ] );
contentLoaded: function( data, status, xhr ) {
// Data is already set in content.
this.buttons.add.enable();
this.buttons.cancel.enable();
app.getProviderHolder( account.provider ).trigger( 'accountAddModal.contentLoaded', [ modal ] );
onOpenBefore: function() { // Before the modal is displayed.
modal.buttons.add.disable();
modal.buttons.cancel.disable();
modal.$body.addClass( 'wpforms-providers-account-add-modal' );
app.getProviderHolder( account.provider ).trigger( 'accountAddModal.onOpenBefore', [ modal ] );
onClose: function() { // Before the modal is hidden.
// If an account was configured successfully - show a modal with adding a new connection.
if ( true === app.ui.account.isConfigured( account.provider ) ) {
app.ui.connectionAdd( account.provider );
icon: 'fa fa-info-circle',
text: wpforms_builder.provider_add_new_acc_btn,
app.getProviderHolder( account.provider ).trigger( 'accountAddModal.buttons.add.action.before', [ modal ] );
! _.isEmpty( account.provider ) &&
typeof account.submitHandlers[ account.provider ] !== 'undefined'
return account.submitHandlers[ account.provider ]( modal );
text: wpforms_builder.cancel,
* Register a template for Add New Account modal window.
registerAddHandler: function( provider, handler ) {
if ( typeof provider === 'string' && typeof handler === 'function' ) {
this.submitHandlers[ provider ] = handler;
* Check whether the defined provider is configured or not.
* @since 1.5.9 Added a new parameter - provider.
* @param {string} provider Current provider slug.
* @returns {boolean} Account status.
isConfigured: function( provider ) {
// Check if `Add New Account` button is hidden.
return app.getProviderHolder( provider ).find( '.js-wpforms-builder-provider-account-add' ).hasClass( 'hidden' );
* Get a jQuery DOM object, that has all the provider-related DOM inside.
* @returns {object} jQuery DOM element.
getProviderHolder: function( provider ) {
return $( '#' + provider + '-provider' );
// Provide access to public functions/properties.
}( document, window, jQuery ) );
WPForms.Admin.Builder.Providers.init();